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: 174438 $")
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,"%i",&ret) != 1) return -1;
02105 return ret;
02106 }
02107
02108 static int mycompar(const void *a, const void *b)
02109 {
02110 char **x = (char **) a;
02111 char **y = (char **) b;
02112 int xoff,yoff;
02113
02114 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02115 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02116 return(strcmp((*x) + xoff,(*y) + yoff));
02117 }
02118
02119 static int topcompar(const void *a, const void *b)
02120 {
02121 struct rpt_topkey *x = (struct rpt_topkey *) a;
02122 struct rpt_topkey *y = (struct rpt_topkey *) b;
02123
02124 return(x->timesince - y->timesince);
02125 }
02126
02127 #ifdef __RPT_NOTCH
02128
02129
02130 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02131 {
02132 int i,j;
02133 struct rptfilter *f;
02134
02135 for(i = 0; i < len; i++)
02136 {
02137 for(j = 0; j < MAXFILTERS; j++)
02138 {
02139 f = &myrpt->filters[j];
02140 if (!*f->desc) continue;
02141 f->x0 = f->x1; f->x1 = f->x2;
02142 f->x2 = ((float)buf[i]) / f->gain;
02143 f->y0 = f->y1; f->y1 = f->y2;
02144 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02145 + (f->const1 * f->y0) + (f->const2 * f->y1);
02146 buf[i] = (short)f->y2;
02147 }
02148 }
02149 }
02150
02151 #endif
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170 #ifdef NEW_ASTERISK
02171 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02172 {
02173 struct timeval when;
02174
02175 when.tv_sec = *t;
02176 when.tv_usec = 0;
02177 ast_localtime(&when, lt, NULL);
02178 }
02179
02180 #else
02181 static void rpt_localtime( time_t * t, struct tm *lt)
02182 {
02183 #ifdef OLD_ASTERISK
02184 localtime_r(t, lt);
02185 #else
02186 ast_localtime(t, lt, NULL);
02187 #endif
02188 }
02189 #endif
02190
02191
02192
02193
02194 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02195 {
02196 char *var;
02197 int ret;
02198 char include_zero = 0;
02199
02200 if(min < 0){
02201 min = -min;
02202 include_zero = 1;
02203 }
02204
02205 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02206 if(var){
02207 ret = myatoi(var);
02208 if(include_zero && !ret)
02209 return 0;
02210 if(ret < min)
02211 ret = min;
02212 if(ret > max)
02213 ret = max;
02214 }
02215 else
02216 ret = defl;
02217 return ret;
02218 }
02219
02220
02221 static void load_rpt_vars(int n,int init)
02222 {
02223 char *this,*val;
02224 int i,j,longestnode;
02225 struct ast_variable *vp;
02226 struct ast_config *cfg;
02227 char *strs[100];
02228 char s1[256];
02229 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02230 "ufena","ufdis","atena","atdis",NULL};
02231
02232 if (option_verbose > 2)
02233 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02234 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02235 ast_mutex_lock(&rpt_vars[n].lock);
02236 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02237 #ifdef NEW_ASTERISK
02238 cfg = ast_config_load("rpt.conf",config_flags);
02239 #else
02240 cfg = ast_config_load("rpt.conf");
02241 #endif
02242 if (!cfg) {
02243 ast_mutex_unlock(&rpt_vars[n].lock);
02244 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02245 pthread_exit(NULL);
02246 }
02247 rpt_vars[n].cfg = cfg;
02248 this = rpt_vars[n].name;
02249 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02250 if (init)
02251 {
02252 char *cp;
02253 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02254
02255 cp = (char *) &rpt_vars[n].p;
02256 memset(cp + sizeof(rpt_vars[n].p),0,
02257 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02258 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02259 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02260 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02261 rpt_vars[n].tailmessagen = 0;
02262 }
02263 #ifdef __RPT_NOTCH
02264
02265 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02266 #endif
02267 val = (char *) ast_variable_retrieve(cfg,this,"context");
02268 if (val) rpt_vars[n].p.ourcontext = val;
02269 else rpt_vars[n].p.ourcontext = this;
02270 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02271 if (val) rpt_vars[n].p.ourcallerid = val;
02272 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02273 if (val) rpt_vars[n].p.acctcode = val;
02274 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02275 if (val) rpt_vars[n].p.ident = val;
02276 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02277 if (val) rpt_vars[n].p.hangtime = atoi(val);
02278 else rpt_vars[n].p.hangtime = HANGTIME;
02279 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02280 if (val) rpt_vars[n].p.althangtime = atoi(val);
02281 else rpt_vars[n].p.althangtime = HANGTIME;
02282 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02283 if (val) rpt_vars[n].p.totime = atoi(val);
02284 else rpt_vars[n].p.totime = TOTIME;
02285 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02286 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02287 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02288 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02289 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02290 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02291 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02292 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02293 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02294 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02295 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02296 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02297 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02298 if (val) rpt_vars[n].p.statpost_program = val;
02299 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02300 rpt_vars[n].p.statpost_url =
02301 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02302 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02303 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02304 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02305 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02306 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02307 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02308 if (val) rpt_vars[n].p.tonezone = val;
02309 rpt_vars[n].p.tailmessages[0] = 0;
02310 rpt_vars[n].p.tailmessagemax = 0;
02311 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02312 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02313 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02314 if (!val) val = MEMORY;
02315 rpt_vars[n].p.memory = val;
02316 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02317 if (!val) val = MACRO;
02318 rpt_vars[n].p.macro = val;
02319 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02320 if (!val) val = TONEMACRO;
02321 rpt_vars[n].p.tonemacro = val;
02322 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02323 if (val) rpt_vars[n].p.startupmacro = val;
02324 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02325
02326
02327
02328 if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
02329 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02330 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02331 rpt_vars[n].p.ioport = val;
02332 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02333 if (!val)
02334 {
02335 val = FUNCTIONS;
02336 rpt_vars[n].p.simple = 1;
02337 }
02338 rpt_vars[n].p.functions = val;
02339 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02340 if (val) rpt_vars[n].p.link_functions = val;
02341 else
02342 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02343 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02344 if (val) rpt_vars[n].p.phone_functions = val;
02345 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02346 if (val) rpt_vars[n].p.dphone_functions = val;
02347 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02348 if (val) rpt_vars[n].p.alt_functions = val;
02349 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02350 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02351 rpt_vars[n].p.funcchar = *val;
02352 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02353 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02354 rpt_vars[n].p.endchar = *val;
02355 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02356 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02357 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02358 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02359 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02360 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02361 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02362 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02363 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02364 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02365 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02366 if (!val) val = NODES;
02367 rpt_vars[n].p.nodes = val;
02368 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02369 if (!val) val = EXTNODES;
02370 rpt_vars[n].p.extnodes = val;
02371 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02372 if (!val) val = EXTNODEFILE;
02373 rpt_vars[n].p.extnodefile = val;
02374 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02375 if (val) rpt_vars[n].p.archivedir = val;
02376 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02377 if (val) rpt_vars[n].p.authlevel = atoi(val);
02378 else rpt_vars[n].p.authlevel = 0;
02379 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02380 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02381 else rpt_vars[n].p.parrotmode = 0;
02382 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02383 if (val) rpt_vars[n].p.parrottime = atoi(val);
02384 else rpt_vars[n].p.parrottime = PARROTTIME;
02385 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02386 rpt_vars[n].p.rptnode = val;
02387 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02388 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02389 else rpt_vars[n].p.remote_mars = 0;
02390 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02391 if (val) rpt_vars[n].p.monminblocks = atol(val);
02392 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02393 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02394 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02395 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02396 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02397 if (val) rpt_vars[n].p.civaddr = atoi(val);
02398 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02399 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02400 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02401 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02402 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02403 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02404 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02405 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02406 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02407 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02408 #ifdef __RPT_NOTCH
02409 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02410 if (val) {
02411 i = finddelim(val,strs,MAXFILTERS * 2);
02412 i &= ~1;
02413 if (i >= 2) for(j = 0; j < i; j += 2)
02414 {
02415 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02416 &rpt_vars[n].filters[j >> 1].gain,
02417 &rpt_vars[n].filters[j >> 1].const0,
02418 &rpt_vars[n].filters[j >> 1].const1,
02419 &rpt_vars[n].filters[j >> 1].const2);
02420 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02421 strs[j],strs[j + 1]);
02422 }
02423
02424 }
02425 #endif
02426 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02427 if (val) {
02428 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02429 i = finddelim(val,strs,3);
02430 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02431 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02432 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02433 }
02434 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02435 if (val) {
02436 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02437 i = finddelim(val,strs,3);
02438 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02439 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02440 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02441 }
02442
02443 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02444 rpt_vars[n].p.csstanzaname = val;
02445
02446
02447 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02448 rpt_vars[n].p.skedstanzaname = val;
02449
02450
02451 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02452 rpt_vars[n].p.txlimitsstanzaname = val;
02453
02454 longestnode = 0;
02455
02456 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02457
02458 while(vp){
02459 j = strlen(vp->name);
02460 if (j > longestnode)
02461 longestnode = j;
02462 vp = vp->next;
02463 }
02464
02465 rpt_vars[n].longestnode = longestnode;
02466
02467
02468
02469
02470 rpt_vars[n].longestfunc = 0;
02471 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02472 while(vp){
02473 j = strlen(vp->name);
02474 if (j > rpt_vars[n].longestfunc)
02475 rpt_vars[n].longestfunc = j;
02476 vp = vp->next;
02477 }
02478
02479
02480
02481 rpt_vars[n].link_longestfunc = 0;
02482 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02483 while(vp){
02484 j = strlen(vp->name);
02485 if (j > rpt_vars[n].link_longestfunc)
02486 rpt_vars[n].link_longestfunc = j;
02487 vp = vp->next;
02488 }
02489 rpt_vars[n].phone_longestfunc = 0;
02490 if (rpt_vars[n].p.phone_functions)
02491 {
02492 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02493 while(vp){
02494 j = strlen(vp->name);
02495 if (j > rpt_vars[n].phone_longestfunc)
02496 rpt_vars[n].phone_longestfunc = j;
02497 vp = vp->next;
02498 }
02499 }
02500 rpt_vars[n].dphone_longestfunc = 0;
02501 if (rpt_vars[n].p.dphone_functions)
02502 {
02503 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02504 while(vp){
02505 j = strlen(vp->name);
02506 if (j > rpt_vars[n].dphone_longestfunc)
02507 rpt_vars[n].dphone_longestfunc = j;
02508 vp = vp->next;
02509 }
02510 }
02511 rpt_vars[n].alt_longestfunc = 0;
02512 if (rpt_vars[n].p.alt_functions)
02513 {
02514 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02515 while(vp){
02516 j = strlen(vp->name);
02517 if (j > rpt_vars[n].alt_longestfunc)
02518 rpt_vars[n].alt_longestfunc = j;
02519 vp = vp->next;
02520 }
02521 }
02522 rpt_vars[n].macro_longest = 1;
02523 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02524 while(vp){
02525 j = strlen(vp->name);
02526 if (j > rpt_vars[n].macro_longest)
02527 rpt_vars[n].macro_longest = j;
02528 vp = vp->next;
02529 }
02530
02531
02532 if(rpt_vars[n].p.csstanzaname)
02533 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02534 else
02535 vp = NULL;
02536 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02537 int k,nukw,statenum;
02538 statenum=atoi(vp->name);
02539 strncpy(s1, vp->value, 255);
02540 s1[255] = 0;
02541 nukw = finddelim(s1,strs,32);
02542
02543 for (k = 0 ; k < nukw ; k++){
02544 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02545 if(!strcmp(strs[k],cs_keywords[j])){
02546 switch(j){
02547 case 0:
02548 rpt_vars[n].p.s[statenum].txdisable = 0;
02549 break;
02550 case 1:
02551 rpt_vars[n].p.s[statenum].txdisable = 1;
02552 break;
02553
02554 case 2:
02555 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02556 break;
02557
02558 case 3:
02559 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02560 break;
02561
02562 case 4:
02563 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02564 break;
02565
02566 case 5:
02567 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02568 break;
02569
02570 case 6:
02571 rpt_vars[n].p.s[statenum].totdisable = 0;
02572 break;
02573
02574 case 7:
02575 rpt_vars[n].p.s[statenum].totdisable = 1;
02576 break;
02577
02578 case 8:
02579 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02580 break;
02581
02582 case 9:
02583 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02584 break;
02585
02586 case 10:
02587 rpt_vars[n].p.s[statenum].userfundisable = 0;
02588 break;
02589
02590 case 11:
02591 rpt_vars[n].p.s[statenum].userfundisable = 1;
02592 break;
02593
02594 case 12:
02595 rpt_vars[n].p.s[statenum].alternatetail = 1;
02596 break;
02597
02598 case 13:
02599 rpt_vars[n].p.s[statenum].alternatetail = 0;
02600 break;
02601
02602 default:
02603 ast_log(LOG_WARNING,
02604 "Unhandled control state keyword %s", cs_keywords[i]);
02605 break;
02606 }
02607 }
02608 }
02609 }
02610 vp = vp->next;
02611 }
02612 ast_mutex_unlock(&rpt_vars[n].lock);
02613 }
02614
02615
02616
02617
02618
02619 static int rpt_do_debug(int fd, int argc, char *argv[])
02620 {
02621 int newlevel;
02622
02623 if (argc != 4)
02624 return RESULT_SHOWUSAGE;
02625 newlevel = myatoi(argv[3]);
02626 if((newlevel < 0) || (newlevel > 7))
02627 return RESULT_SHOWUSAGE;
02628 if(newlevel)
02629 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02630 else
02631 ast_cli(fd, "app_rpt Debugging disabled\n");
02632
02633 debug = newlevel;
02634 return RESULT_SUCCESS;
02635 }
02636
02637
02638
02639
02640
02641 static int rpt_do_dump(int fd, int argc, char *argv[])
02642 {
02643 int i;
02644
02645 if (argc != 3)
02646 return RESULT_SHOWUSAGE;
02647
02648 for(i = 0; i < nrpts; i++)
02649 {
02650 if (!strcmp(argv[2],rpt_vars[i].name))
02651 {
02652 rpt_vars[i].disgorgetime = time(NULL) + 10;
02653 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02654 return RESULT_SUCCESS;
02655 }
02656 }
02657 return RESULT_FAILURE;
02658 }
02659
02660
02661
02662
02663
02664 static int rpt_do_stats(int fd, int argc, char *argv[])
02665 {
02666 int i,j,numoflinks;
02667 int dailytxtime, dailykerchunks;
02668 time_t now;
02669 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02670 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02671 int uptime;
02672 long long totaltxtime;
02673 struct rpt_link *l;
02674 char *listoflinks[MAX_STAT_LINKS];
02675 char *lastdtmfcommand,*parrot_ena;
02676 char *tot_state, *ider_state, *patch_state;
02677 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02678 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02679 struct rpt *myrpt;
02680
02681 static char *not_applicable = "N/A";
02682
02683 if(argc != 3)
02684 return RESULT_SHOWUSAGE;
02685
02686 tot_state = ider_state =
02687 patch_state = reverse_patch_state =
02688 input_signal = not_applicable;
02689 called_number = lastdtmfcommand = NULL;
02690
02691 time(&now);
02692 for(i = 0; i < nrpts; i++)
02693 {
02694 if (!strcmp(argv[2],rpt_vars[i].name)){
02695
02696 myrpt = &rpt_vars[i];
02697 rpt_mutex_lock(&myrpt->lock);
02698 uptime = (int)(now - starttime);
02699 dailytxtime = myrpt->dailytxtime;
02700 totaltxtime = myrpt->totaltxtime;
02701 dailykeyups = myrpt->dailykeyups;
02702 totalkeyups = myrpt->totalkeyups;
02703 dailykerchunks = myrpt->dailykerchunks;
02704 totalkerchunks = myrpt->totalkerchunks;
02705 dailyexecdcommands = myrpt->dailyexecdcommands;
02706 totalexecdcommands = myrpt->totalexecdcommands;
02707 timeouts = myrpt->timeouts;
02708
02709
02710 reverse_patch_state = "DOWN";
02711 numoflinks = 0;
02712 l = myrpt->links.next;
02713 while(l && (l != &myrpt->links)){
02714 if(numoflinks >= MAX_STAT_LINKS){
02715 ast_log(LOG_NOTICE,
02716 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02717 break;
02718 }
02719 if (l->name[0] == '0'){
02720 reverse_patch_state = "UP";
02721 l = l->next;
02722 continue;
02723 }
02724 listoflinks[numoflinks] = ast_strdup(l->name);
02725 if(listoflinks[numoflinks] == NULL){
02726 break;
02727 }
02728 else{
02729 numoflinks++;
02730 }
02731 l = l->next;
02732 }
02733
02734 if(myrpt->keyed)
02735 input_signal = "YES";
02736 else
02737 input_signal = "NO";
02738
02739 if(myrpt->p.parrotmode)
02740 parrot_ena = "ENABLED";
02741 else
02742 parrot_ena = "DISABLED";
02743
02744 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02745 sys_ena = "DISABLED";
02746 else
02747 sys_ena = "ENABLED";
02748
02749 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02750 tot_ena = "DISABLED";
02751 else
02752 tot_ena = "ENABLED";
02753
02754 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02755 link_ena = "DISABLED";
02756 else
02757 link_ena = "ENABLED";
02758
02759 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02760 patch_ena = "DISABLED";
02761 else
02762 patch_ena = "ENABLED";
02763
02764 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02765 sch_ena = "DISABLED";
02766 else
02767 sch_ena = "ENABLED";
02768
02769 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02770 user_funs = "DISABLED";
02771 else
02772 user_funs = "ENABLED";
02773
02774 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02775 tail_type = "ALTERNATE";
02776 else
02777 tail_type = "STANDARD";
02778
02779 if(!myrpt->totimer)
02780 tot_state = "TIMED OUT!";
02781 else if(myrpt->totimer != myrpt->p.totime)
02782 tot_state = "ARMED";
02783 else
02784 tot_state = "RESET";
02785
02786 if(myrpt->tailid)
02787 ider_state = "QUEUED IN TAIL";
02788 else if(myrpt->mustid)
02789 ider_state = "QUEUED FOR CLEANUP";
02790 else
02791 ider_state = "CLEAN";
02792
02793 switch(myrpt->callmode){
02794 case 1:
02795 patch_state = "DIALING";
02796 break;
02797 case 2:
02798 patch_state = "CONNECTING";
02799 break;
02800 case 3:
02801 patch_state = "UP";
02802 break;
02803
02804 case 4:
02805 patch_state = "CALL FAILED";
02806 break;
02807
02808 default:
02809 patch_state = "DOWN";
02810 }
02811
02812 if(strlen(myrpt->exten)){
02813 called_number = ast_strdup(myrpt->exten);
02814 }
02815
02816 if(strlen(myrpt->lastdtmfcommand)){
02817 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02818 }
02819 rpt_mutex_unlock(&myrpt->lock);
02820
02821 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02822 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02823 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02824 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02825 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02826 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02827 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02828 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02829 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02830 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02831 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02832 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02833 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02834 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02835 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02836 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02837 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02838 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02839 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02840 hours = dailytxtime/3600000;
02841 dailytxtime %= 3600000;
02842 minutes = dailytxtime/60000;
02843 dailytxtime %= 60000;
02844 seconds = dailytxtime/1000;
02845 dailytxtime %= 1000;
02846
02847 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02848 hours, minutes, seconds, dailytxtime);
02849
02850 hours = (int) totaltxtime/3600000;
02851 totaltxtime %= 3600000;
02852 minutes = (int) totaltxtime/60000;
02853 totaltxtime %= 60000;
02854 seconds = (int) totaltxtime/1000;
02855 totaltxtime %= 1000;
02856
02857 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02858 hours, minutes, seconds, (int) totaltxtime);
02859
02860 hours = uptime/3600;
02861 uptime %= 3600;
02862 minutes = uptime/60;
02863 uptime %= 60;
02864
02865 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02866 hours, minutes, uptime);
02867
02868 ast_cli(fd, "Nodes currently connected to us..................: ");
02869 if(!numoflinks){
02870 ast_cli(fd,"<NONE>");
02871 }
02872 else{
02873 for(j = 0 ;j < numoflinks; j++){
02874 ast_cli(fd, "%s", listoflinks[j]);
02875 if(j % 4 == 3){
02876 ast_cli(fd, "\n");
02877 ast_cli(fd, " : ");
02878 }
02879 else{
02880 if((numoflinks - 1) - j > 0)
02881 ast_cli(fd, ", ");
02882 }
02883 }
02884 }
02885 ast_cli(fd,"\n");
02886
02887 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02888 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02889 ast_cli(fd, "Autopatch called number..........................: %s\n",
02890 (called_number && strlen(called_number)) ? called_number : not_applicable);
02891 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02892 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02893 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02894
02895 for(j = 0; j < numoflinks; j++){
02896 ast_free(listoflinks[j]);
02897 }
02898 if(called_number){
02899 ast_free(called_number);
02900 }
02901 if(lastdtmfcommand){
02902 ast_free(lastdtmfcommand);
02903 }
02904 return RESULT_SUCCESS;
02905 }
02906 }
02907 return RESULT_FAILURE;
02908 }
02909
02910
02911
02912
02913
02914 static int rpt_do_lstats(int fd, int argc, char *argv[])
02915 {
02916 int i,j;
02917 char *connstate;
02918 struct rpt *myrpt;
02919 struct rpt_link *l;
02920 struct rpt_lstat *s,*t;
02921 struct rpt_lstat s_head;
02922 if(argc != 3)
02923 return RESULT_SHOWUSAGE;
02924
02925 s = NULL;
02926 s_head.next = &s_head;
02927 s_head.prev = &s_head;
02928
02929 for(i = 0; i < nrpts; i++)
02930 {
02931 if (!strcmp(argv[2],rpt_vars[i].name)){
02932
02933 myrpt = &rpt_vars[i];
02934 rpt_mutex_lock(&myrpt->lock);
02935
02936 j = 0;
02937 l = myrpt->links.next;
02938 while(l && (l != &myrpt->links)){
02939 if (l->name[0] == '0'){
02940 l = l->next;
02941 continue;
02942 }
02943 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02944 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02945 rpt_mutex_unlock(&myrpt->lock);
02946 return RESULT_FAILURE;
02947 }
02948 memset(s, 0, sizeof(struct rpt_lstat));
02949 strncpy(s->name, l->name, MAXREMSTR - 1);
02950 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02951 else strcpy(s->peer,"(none)");
02952 s->mode = l->mode;
02953 s->outbound = l->outbound;
02954 s->reconnects = l->reconnects;
02955 s->connecttime = l->connecttime;
02956 s->thisconnected = l->thisconnected;
02957 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02958 insque((struct qelem *) s, (struct qelem *) s_head.next);
02959 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02960 l = l->next;
02961 }
02962 rpt_mutex_unlock(&myrpt->lock);
02963 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02964 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02965
02966 for(s = s_head.next; s != &s_head; s = s->next){
02967 int hours, minutes, seconds;
02968 long long connecttime = s->connecttime;
02969 char conntime[21];
02970 hours = (int) connecttime/3600000;
02971 connecttime %= 3600000;
02972 minutes = (int) connecttime/60000;
02973 connecttime %= 60000;
02974 seconds = (int) connecttime/1000;
02975 connecttime %= 1000;
02976 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02977 hours, minutes, seconds, (int) connecttime);
02978 conntime[20] = 0;
02979 if(s->thisconnected)
02980 connstate = "ESTABLISHED";
02981 else
02982 connstate = "CONNECTING";
02983 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02984 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02985 }
02986
02987 s = s_head.next;
02988 while(s != &s_head){
02989 t = s;
02990 s = s->next;
02991 remque((struct qelem *)t);
02992 ast_free(t);
02993 }
02994 return RESULT_SUCCESS;
02995 }
02996 }
02997 return RESULT_FAILURE;
02998 }
02999
03000
03001
03002
03003
03004 static int rpt_do_nodes(int fd, int argc, char *argv[])
03005 {
03006 int i,j;
03007 char ns;
03008 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03009 struct rpt *myrpt;
03010 if(argc != 3)
03011 return RESULT_SHOWUSAGE;
03012
03013 for(i = 0; i < nrpts; i++)
03014 {
03015 if (!strcmp(argv[2],rpt_vars[i].name)){
03016
03017 myrpt = &rpt_vars[i];
03018 rpt_mutex_lock(&myrpt->lock);
03019 __mklinklist(myrpt,NULL,lbuf);
03020 rpt_mutex_unlock(&myrpt->lock);
03021
03022 ns = finddelim(lbuf,strs,MAXLINKLIST);
03023
03024 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03025 ast_cli(fd,"\n");
03026 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03027 for(j = 0 ;; j++){
03028 if(!strs[j]){
03029 if(!j){
03030 ast_cli(fd,"<NONE>");
03031 }
03032 break;
03033 }
03034 ast_cli(fd, "%s", strs[j]);
03035 if(j % 8 == 7){
03036 ast_cli(fd, "\n");
03037 }
03038 else{
03039 if(strs[j + 1])
03040 ast_cli(fd, ", ");
03041 }
03042 }
03043 ast_cli(fd,"\n\n");
03044 return RESULT_SUCCESS;
03045 }
03046 }
03047 return RESULT_FAILURE;
03048 }
03049
03050
03051
03052
03053
03054 static int rpt_do_local_nodes(int fd, int argc, char *argv[])
03055 {
03056
03057 int i;
03058 ast_cli(fd, "\nNode\n----\n");
03059 for (i=0; i< nrpts; i++)
03060 {
03061 ast_cli(fd, "%s\n", rpt_vars[i].name);
03062 }
03063 ast_cli(fd,"\n");
03064 return RESULT_SUCCESS;
03065 }
03066
03067
03068
03069
03070
03071
03072 static int rpt_do_reload(int fd, int argc, char *argv[])
03073 {
03074 int n;
03075
03076 if (argc > 2) return RESULT_SHOWUSAGE;
03077
03078 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03079
03080 return RESULT_FAILURE;
03081 }
03082
03083
03084
03085
03086
03087 static int rpt_do_restart(int fd, int argc, char *argv[])
03088 {
03089 int i;
03090
03091 if (argc > 2) return RESULT_SHOWUSAGE;
03092 for(i = 0; i < nrpts; i++)
03093 {
03094 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03095 }
03096 return RESULT_FAILURE;
03097 }
03098
03099
03100
03101
03102
03103
03104 static int rpt_do_fun(int fd, int argc, char *argv[])
03105 {
03106 int i,busy=0;
03107
03108 if (argc != 4) return RESULT_SHOWUSAGE;
03109
03110 for(i = 0; i < nrpts; i++){
03111 if(!strcmp(argv[2], rpt_vars[i].name)){
03112 struct rpt *myrpt = &rpt_vars[i];
03113 rpt_mutex_lock(&myrpt->lock);
03114 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03115 rpt_mutex_unlock(&myrpt->lock);
03116 busy=1;
03117 }
03118 if(!busy){
03119 myrpt->macrotimer = MACROTIME;
03120 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03121 }
03122 rpt_mutex_unlock(&myrpt->lock);
03123 }
03124 }
03125 if(busy){
03126 ast_cli(fd, "Function decoder busy");
03127 }
03128 return RESULT_FAILURE;
03129 }
03130
03131
03132
03133
03134
03135
03136
03137
03138 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03139 {
03140 int busy=0;
03141
03142 rpt_mutex_lock(&myrpt->lock);
03143 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03144 rpt_mutex_unlock(&myrpt->lock);
03145 busy=1;
03146 }
03147 if(!busy){
03148 int x;
03149 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03150 myrpt->macrotimer = MACROTIME;
03151 for(x = 0; *(sptr + x); x++)
03152 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03153 *(sptr + x) = 0;
03154 }
03155 rpt_mutex_unlock(&myrpt->lock);
03156
03157 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03158
03159 return busy;
03160 }
03161
03162
03163
03164 static int rpt_do_fun1(int fd, int argc, char *argv[])
03165 {
03166 int i;
03167
03168 if (argc != 4) return RESULT_SHOWUSAGE;
03169
03170 for(i = 0; i < nrpts; i++){
03171 if(!strcmp(argv[2], rpt_vars[i].name)){
03172 struct rpt *myrpt = &rpt_vars[i];
03173 rpt_push_alt_macro(myrpt,argv[3]);
03174 }
03175 }
03176 return RESULT_FAILURE;
03177 }
03178
03179
03180
03181
03182 static int rpt_do_cmd(int fd, int argc, char *argv[])
03183 {
03184 int i, l;
03185 int busy=0;
03186 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03187
03188 int thisRpt = -1;
03189 int thisAction = -1;
03190 struct rpt *myrpt = NULL;
03191 if (argc != 6) return RESULT_SHOWUSAGE;
03192
03193 for(i = 0; i < nrpts; i++)
03194 {
03195 if(!strcmp(argv[2], rpt_vars[i].name))
03196 {
03197 thisRpt = i;
03198 myrpt = &rpt_vars[i];
03199 break;
03200 }
03201 }
03202
03203 if (thisRpt < 0)
03204 {
03205 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03206 return RESULT_FAILURE;
03207 }
03208
03209
03210 l = strlen(argv[3]);
03211 for(i = 0 ; i < maxActions; i++)
03212 {
03213 if(!strncasecmp(argv[3], function_table[i].action, l))
03214 {
03215 thisAction = i;
03216 break;
03217 }
03218 }
03219
03220 if (thisAction < 0)
03221 {
03222 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03223 return RESULT_FAILURE;
03224 }
03225
03226
03227
03228 rpt_mutex_lock(&myrpt->lock);
03229
03230 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03231 {
03232 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03233 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03234 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03235 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03236 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03237 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03238 }
03239 else
03240 {
03241 busy = 1;
03242 }
03243 rpt_mutex_unlock(&myrpt->lock);
03244
03245 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03246 }
03247
03248 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03249 {
03250 int res;
03251
03252 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03253 return res;
03254
03255 while(chan->generatordata) {
03256 if (ast_safe_sleep(chan,1)) return -1;
03257 }
03258
03259 return 0;
03260 }
03261
03262 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03263 {
03264 return play_tone_pair(chan, freq, 0, duration, amplitude);
03265 }
03266
03267 static int play_silence(struct ast_channel *chan, int duration)
03268 {
03269 return play_tone_pair(chan, 0, 0, duration, 0);
03270 }
03271
03272 #ifdef NEW_ASTERISK
03273
03274 static char *res2cli(int r)
03275
03276 {
03277 switch (r)
03278 {
03279 case RESULT_SUCCESS:
03280 return(CLI_SUCCESS);
03281 case RESULT_SHOWUSAGE:
03282 return(CLI_SHOWUSAGE);
03283 default:
03284 return(CLI_FAILURE);
03285 }
03286 }
03287
03288 static char *handle_cli_debug(struct ast_cli_entry *e,
03289 int cmd, struct ast_cli_args *a)
03290 {
03291 switch (cmd) {
03292 case CLI_INIT:
03293 e->command = "rpt debug level";
03294 e->usage = debug_usage;
03295 return NULL;
03296 case CLI_GENERATE:
03297 return NULL;
03298 }
03299 return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
03300 }
03301
03302 static char *handle_cli_dump(struct ast_cli_entry *e,
03303 int cmd, struct ast_cli_args *a)
03304 {
03305 switch (cmd) {
03306 case CLI_INIT:
03307 e->command = "rpt dump level";
03308 e->usage = dump_usage;
03309 return NULL;
03310 case CLI_GENERATE:
03311 return NULL;
03312 }
03313 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03314 }
03315
03316
03317 static char *handle_cli_stats(struct ast_cli_entry *e,
03318 int cmd, struct ast_cli_args *a)
03319 {
03320 switch (cmd) {
03321 case CLI_INIT:
03322 e->command = "rpt stats";
03323 e->usage = dump_stats;
03324 return NULL;
03325 case CLI_GENERATE:
03326 return NULL;
03327 }
03328 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03329 }
03330
03331 static char *handle_cli_nodes(struct ast_cli_entry *e,
03332 int cmd, struct ast_cli_args *a)
03333 {
03334 switch (cmd) {
03335 case CLI_INIT:
03336 e->command = "rpt nodes";
03337 e->usage = dump_nodes;
03338 return NULL;
03339 case CLI_GENERATE:
03340 return NULL;
03341 }
03342 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03343 }
03344
03345 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03346 int cmd, struct ast_cli_args *a)
03347 {
03348 switch (cmd) {
03349 case CLI_INIT:
03350 e->command = "rpt localnodes";
03351 e->usage = usage_local_nodes;
03352 return NULL;
03353 case CLI_GENERATE:
03354 return NULL;
03355 }
03356 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03357 }
03358
03359 static char *handle_cli_lstats(struct ast_cli_entry *e,
03360 int cmd, struct ast_cli_args *a)
03361 {
03362 switch (cmd) {
03363 case CLI_INIT:
03364 e->command = "rpt lstats";
03365 e->usage = dump_lstats;
03366 return NULL;
03367 case CLI_GENERATE:
03368 return NULL;
03369 }
03370 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03371 }
03372
03373 static char *handle_cli_reload(struct ast_cli_entry *e,
03374 int cmd, struct ast_cli_args *a)
03375 {
03376 switch (cmd) {
03377 case CLI_INIT:
03378 e->command = "rpt reload";
03379 e->usage = reload_usage;
03380 return NULL;
03381 case CLI_GENERATE:
03382 return NULL;
03383 }
03384 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03385 }
03386
03387 static char *handle_cli_restart(struct ast_cli_entry *e,
03388 int cmd, struct ast_cli_args *a)
03389 {
03390 switch (cmd) {
03391 case CLI_INIT:
03392 e->command = "rpt restart";
03393 e->usage = restart_usage;
03394 return NULL;
03395 case CLI_GENERATE:
03396 return NULL;
03397 }
03398 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03399 }
03400
03401 static char *handle_cli_fun(struct ast_cli_entry *e,
03402 int cmd, struct ast_cli_args *a)
03403 {
03404 switch (cmd) {
03405 case CLI_INIT:
03406 e->command = "rpt fun";
03407 e->usage = fun_usage;
03408 return NULL;
03409 case CLI_GENERATE:
03410 return NULL;
03411 }
03412 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03413 }
03414
03415 static char *handle_cli_fun1(struct ast_cli_entry *e,
03416 int cmd, struct ast_cli_args *a)
03417 {
03418 switch (cmd) {
03419 case CLI_INIT:
03420 e->command = "rpt fun1";
03421 e->usage = fun_usage;
03422 return NULL;
03423 case CLI_GENERATE:
03424 return NULL;
03425 }
03426 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03427 }
03428
03429 static char *handle_cli_cmd(struct ast_cli_entry *e,
03430 int cmd, struct ast_cli_args *a)
03431 {
03432 switch (cmd) {
03433 case CLI_INIT:
03434 e->command = "rpt cmd";
03435 e->usage = cmd_usage;
03436 return NULL;
03437 case CLI_GENERATE:
03438 return NULL;
03439 }
03440 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03441 }
03442
03443 static struct ast_cli_entry rpt_cli[] = {
03444 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03445 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03446 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03447 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03448 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03449 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03450 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03451 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03452 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03453 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03454 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03455 };
03456
03457 #endif
03458
03459 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03460 {
03461
03462 static struct morse_bits mbits[] = {
03463 {0, 0},
03464 {0, 0},
03465 {6, 18},
03466 {0, 0},
03467 {7, 72},
03468 {0, 0},
03469 {0, 0},
03470 {6, 30},
03471 {5, 13},
03472 {6, 29},
03473 {0, 0},
03474 {5, 10},
03475 {6, 51},
03476 {6, 33},
03477 {6, 42},
03478 {5, 9},
03479 {5, 31},
03480 {5, 30},
03481 {5, 28},
03482 {5, 24},
03483 {5, 16},
03484 {5, 0},
03485 {5, 1},
03486 {5, 3},
03487 {5, 7},
03488 {5, 15},
03489 {6, 7},
03490 {6, 21},
03491 {0, 0},
03492 {5, 33},
03493 {0, 0},
03494 {6, 12},
03495 {0, 0},
03496 {2, 2},
03497 {4, 1},
03498 {4, 5},
03499 {3, 1},
03500 {1, 0},
03501 {4, 4},
03502 {3, 3},
03503 {4, 0},
03504 {2, 0},
03505 {4, 14},
03506 {3, 5},
03507 {4, 2},
03508 {2, 3},
03509 {2, 1},
03510 {3, 7},
03511 {4, 6},
03512 {4, 11},
03513 {3, 2},
03514 {3, 0},
03515 {1, 1},
03516 {3, 4},
03517 {4, 8},
03518 {3, 6},
03519 {4, 9},
03520 {4, 13},
03521 {4, 3}
03522 };
03523
03524
03525 int dottime;
03526 int dashtime;
03527 int intralettertime;
03528 int interlettertime;
03529 int interwordtime;
03530 int len, ddcomb;
03531 int res;
03532 int c;
03533 int i;
03534 int flags;
03535
03536 res = 0;
03537
03538
03539
03540 dottime = 900/speed;
03541
03542
03543
03544 dashtime = 3 * dottime;
03545 intralettertime = dottime;
03546 interlettertime = dottime * 4 ;
03547 interwordtime = dottime * 7;
03548
03549 for(;(*string) && (!res); string++){
03550
03551 c = *string;
03552
03553
03554
03555 if((c >= 'a') && (c <= 'z'))
03556 c -= 0x20;
03557
03558
03559
03560 if(c > 'Z')
03561 continue;
03562
03563
03564
03565 if(c == ' '){
03566 if(!res)
03567 res = play_silence(chan, interwordtime);
03568 continue;
03569 }
03570
03571
03572
03573 c -= 0x20;
03574
03575
03576
03577 len = mbits[c].len;
03578 ddcomb = mbits[c].ddcomb;
03579
03580
03581
03582 for(; len ; len--){
03583 if(!res)
03584 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03585 if(!res)
03586 res = play_silence(chan, intralettertime);
03587 ddcomb >>= 1;
03588 }
03589
03590
03591
03592 if(!res)
03593 res = play_silence(chan, interlettertime - intralettertime);
03594 }
03595
03596
03597
03598 if (!res)
03599 res = ast_waitstream(chan, "");
03600 ast_stopstream(chan);
03601
03602
03603
03604
03605
03606 for(i = 0; i < 20 ; i++){
03607 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03608 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03609 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03610 break;
03611 if( ast_safe_sleep(chan, 50)){
03612 res = -1;
03613 break;
03614 }
03615 }
03616
03617
03618 return res;
03619 }
03620
03621 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03622 {
03623 char *p,*stringp;
03624 char *tonesubset;
03625 int f1,f2;
03626 int duration;
03627 int amplitude;
03628 int res;
03629 int i;
03630 int flags;
03631
03632 res = 0;
03633
03634 if(!tonestring)
03635 return res;
03636
03637 p = stringp = ast_strdup(tonestring);
03638
03639 for(;tonestring;){
03640 tonesubset = strsep(&stringp,")");
03641 if(!tonesubset)
03642 break;
03643 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4)
03644 break;
03645 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03646 if(res)
03647 break;
03648 }
03649 if(p)
03650 ast_free(p);
03651 if(!res)
03652 res = play_tone_pair(chan, 0, 0, 100, 0);
03653
03654 if (!res)
03655 res = ast_waitstream(chan, "");
03656
03657 ast_stopstream(chan);
03658
03659
03660
03661
03662
03663 for(i = 0; i < 20 ; i++){
03664 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03665 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03666 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03667 break;
03668 if( ast_safe_sleep(chan, 50)){
03669 res = -1;
03670 break;
03671 }
03672 }
03673
03674 return res;
03675
03676 }
03677
03678 static int sayfile(struct ast_channel *mychannel,char *fname)
03679 {
03680 int res;
03681
03682 res = ast_streamfile(mychannel, fname, mychannel->language);
03683 if (!res)
03684 res = ast_waitstream(mychannel, "");
03685 else
03686 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03687 ast_stopstream(mychannel);
03688 return res;
03689 }
03690
03691 static int saycharstr(struct ast_channel *mychannel,char *str)
03692 {
03693 int res;
03694
03695 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03696 if (!res)
03697 res = ast_waitstream(mychannel, "");
03698 else
03699 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03700 ast_stopstream(mychannel);
03701 return res;
03702 }
03703
03704 static int saynum(struct ast_channel *mychannel, int num)
03705 {
03706 int res;
03707 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03708 if(!res)
03709 res = ast_waitstream(mychannel, "");
03710 else
03711 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03712 ast_stopstream(mychannel);
03713 return res;
03714 }
03715
03716
03717
03718
03719 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03720 {
03721 int res;
03722 char *val,fname[300];
03723
03724 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03725 if (!val) val = NODENAMES;
03726 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03727 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03728 return(sayfile(mychannel,fname));
03729 res = sayfile(mychannel,"rpt/node");
03730 if (!res)
03731 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03732 return res;
03733 }
03734
03735 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03736 {
03737 int res;
03738 char c;
03739
03740 static int morsespeed;
03741 static int morsefreq;
03742 static int morseampl;
03743 static int morseidfreq = 0;
03744 static int morseidampl;
03745 static char mcat[] = MORSE;
03746
03747 res = 0;
03748
03749 if(!morseidfreq){
03750 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03751 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03752 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03753 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03754 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03755 }
03756
03757
03758
03759 if(entry[0] == '|'){
03760 c = entry[1];
03761 if((c >= 'a')&&(c <= 'z'))
03762 c -= 0x20;
03763
03764 switch(c){
03765 case 'I':
03766 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03767 break;
03768
03769 case 'M':
03770 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03771 break;
03772
03773 case 'T':
03774 res = send_tone_telemetry(chan, entry + 2);
03775 break;
03776 default:
03777 res = -1;
03778 }
03779 }
03780 else
03781 res = sayfile(chan, entry);
03782 return res;
03783 }
03784
03785
03786
03787
03788
03789
03790
03791 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03792 {
03793
03794 int res;
03795 int i;
03796 char *entry;
03797 char *telemetry;
03798 char *telemetry_save;
03799
03800 res = 0;
03801 telemetry_save = NULL;
03802 entry = NULL;
03803
03804
03805 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03806 if(telemetry ){
03807 telemetry_save = ast_strdup(telemetry);
03808 if(!telemetry_save){
03809 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03810 return res;
03811 }
03812 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03813 }
03814
03815
03816
03817 if(!entry){
03818
03819 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03820 if(!strcasecmp(tele_defs[i].name, name))
03821 entry = tele_defs[i].value;
03822 }
03823 }
03824 if(entry){
03825 if(strlen(entry))
03826 if (chan) telem_any(myrpt,chan, entry);
03827 }
03828 else{
03829 res = -1;
03830 }
03831 if(telemetry_save)
03832 ast_free(telemetry_save);
03833 return res;
03834 }
03835
03836
03837
03838
03839
03840 static int get_wait_interval(struct rpt *myrpt, int type)
03841 {
03842 int interval;
03843 char *wait_times;
03844 char *wait_times_save;
03845
03846 wait_times_save = NULL;
03847 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03848
03849 if(wait_times){
03850 wait_times_save = ast_strdup(wait_times);
03851 if(!wait_times_save)
03852 return 0;
03853
03854 }
03855
03856 switch(type){
03857 case DLY_TELEM:
03858 if(wait_times)
03859 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03860 else
03861 interval = 1000;
03862 break;
03863
03864 case DLY_ID:
03865 if(wait_times)
03866 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03867 else
03868 interval = 500;
03869 break;
03870
03871 case DLY_UNKEY:
03872 if(wait_times)
03873 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03874 else
03875 interval = 1000;
03876 break;
03877
03878 case DLY_LINKUNKEY:
03879 if(wait_times)
03880 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03881 else
03882 interval = 1000;
03883 break;
03884
03885 case DLY_CALLTERM:
03886 if(wait_times)
03887 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03888 else
03889 interval = 1500;
03890 break;
03891
03892 case DLY_COMP:
03893 if(wait_times)
03894 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03895 else
03896 interval = 200;
03897 break;
03898
03899 case DLY_PARROT:
03900 if(wait_times)
03901 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03902 else
03903 interval = 200;
03904 break;
03905
03906 default:
03907 interval = 0;
03908 break;
03909 }
03910 if(wait_times_save)
03911 ast_free(wait_times_save);
03912 return interval;
03913 }
03914
03915
03916
03917
03918
03919 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03920 {
03921 int interval;
03922 interval = get_wait_interval(myrpt, type);
03923 if(debug)
03924 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03925 if(interval)
03926 ast_safe_sleep(chan,interval);
03927 if(debug)
03928 ast_log(LOG_NOTICE,"Delay complete\n");
03929 return;
03930 }
03931
03932 static int split_freq(char *mhz, char *decimals, char *freq);
03933
03934 static void *rpt_tele_thread(void *this)
03935 {
03936 struct dahdi_confinfo ci;
03937 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03938 struct rpt_tele *mytele = (struct rpt_tele *)this;
03939 struct rpt_tele *tlist;
03940 struct rpt *myrpt;
03941 struct rpt_link *l,*l1,linkbase;
03942 struct ast_channel *mychannel;
03943 int id_malloc, vmajor, vminor, m;
03944 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03945 time_t t;
03946 #ifdef NEW_ASTERISK
03947 struct ast_tm localtm;
03948 #else
03949 struct tm localtm;
03950 #endif
03951 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03952 int i,ns,rbimode;
03953 char mhz[MAXREMSTR];
03954 char decimals[MAXREMSTR];
03955 char mystr[200];
03956 struct dahdi_params par;
03957
03958
03959
03960 myrpt = mytele->rpt;
03961
03962
03963 rpt_mutex_lock(&myrpt->lock);
03964 nodename = ast_strdup(myrpt->name);
03965 if(!nodename)
03966 {
03967 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03968 rpt_mutex_lock(&myrpt->lock);
03969 remque((struct qelem *)mytele);
03970 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03971 rpt_mutex_unlock(&myrpt->lock);
03972 ast_free(mytele);
03973 pthread_exit(NULL);
03974 }
03975
03976 if (myrpt->p.ident){
03977 ident = ast_strdup(myrpt->p.ident);
03978 if(!ident)
03979 {
03980 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03981 rpt_mutex_lock(&myrpt->lock);
03982 remque((struct qelem *)mytele);
03983 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03984 __LINE__, mytele->mode);
03985 rpt_mutex_unlock(&myrpt->lock);
03986 ast_free(nodename);
03987 ast_free(mytele);
03988 pthread_exit(NULL);
03989 }
03990 else{
03991 id_malloc = 1;
03992 }
03993 }
03994 else
03995 {
03996 ident = "";
03997 id_malloc = 0;
03998 }
03999 rpt_mutex_unlock(&myrpt->lock);
04000
04001
04002
04003
04004 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
04005 if (!mychannel)
04006 {
04007 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04008 rpt_mutex_lock(&myrpt->lock);
04009 remque((struct qelem *)mytele);
04010 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04011 rpt_mutex_unlock(&myrpt->lock);
04012 ast_free(nodename);
04013 if(id_malloc)
04014 ast_free(ident);
04015 ast_free(mytele);
04016 pthread_exit(NULL);
04017 }
04018 #ifdef AST_CDR_FLAG_POST_DISABLED
04019 if (mychannel->cdr)
04020 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04021 #endif
04022 rpt_mutex_lock(&myrpt->lock);
04023 mytele->chan = mychannel;
04024 rpt_mutex_unlock(&myrpt->lock);
04025
04026 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04027 (mytele->mode != LINKUNKEY))
04028 {
04029 rpt_mutex_lock(&myrpt->lock);
04030 if (!myrpt->active_telem)
04031 {
04032 myrpt->active_telem = mytele;
04033 rpt_mutex_unlock(&myrpt->lock);
04034 break;
04035 }
04036 rpt_mutex_unlock(&myrpt->lock);
04037 usleep(100000);
04038 }
04039
04040
04041 ci.chan = 0;
04042
04043
04044
04045 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04046 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04047 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04048 myrpt->txconf : myrpt->conf);
04049 ci.confmode = DAHDI_CONF_CONFANN;
04050
04051 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04052 {
04053 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04054 rpt_mutex_lock(&myrpt->lock);
04055 myrpt->active_telem = NULL;
04056 remque((struct qelem *)mytele);
04057 rpt_mutex_unlock(&myrpt->lock);
04058 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04059 ast_free(nodename);
04060 if(id_malloc)
04061 ast_free(ident);
04062 ast_free(mytele);
04063 ast_hangup(mychannel);
04064 pthread_exit(NULL);
04065 }
04066 ast_stopstream(mychannel);
04067 switch(mytele->mode)
04068 {
04069 case ID:
04070 case ID1:
04071
04072 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04073 res = telem_any(myrpt,mychannel, ident);
04074 imdone=1;
04075 break;
04076
04077 case TAILMSG:
04078 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04079 break;
04080
04081 case IDTALKOVER:
04082 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04083 if(p)
04084 res = telem_any(myrpt,mychannel, p);
04085 imdone=1;
04086 break;
04087
04088 case PROC:
04089
04090 wait_interval(myrpt, DLY_TELEM, mychannel);
04091 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04092 if(res < 0){
04093 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04094 }
04095 break;
04096 case TERM:
04097
04098 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04099 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04100 if(res < 0){
04101 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04102 }
04103 break;
04104 case COMPLETE:
04105
04106 wait_interval(myrpt, DLY_TELEM, mychannel);
04107 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04108 break;
04109 case MACRO_NOTFOUND:
04110
04111 wait_interval(myrpt, DLY_TELEM, mychannel);
04112 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04113 break;
04114 case MACRO_BUSY:
04115
04116 wait_interval(myrpt, DLY_TELEM, mychannel);
04117 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04118 break;
04119 case UNKEY:
04120 if(myrpt->patchnoct && myrpt->callmode){
04121 imdone = 1;
04122 break;
04123 }
04124
04125
04126
04127
04128
04129 x = get_wait_interval(myrpt, DLY_UNKEY);
04130 rpt_mutex_lock(&myrpt->lock);
04131 myrpt->unkeytocttimer = x;
04132 rpt_mutex_unlock(&myrpt->lock);
04133
04134
04135
04136
04137
04138 tlist = myrpt->tele.next;
04139 unkeys_queued = 0;
04140 if (tlist != &myrpt->tele)
04141 {
04142 rpt_mutex_lock(&myrpt->lock);
04143 while(tlist != &myrpt->tele){
04144 if (tlist->mode == UNKEY) unkeys_queued++;
04145 tlist = tlist->next;
04146 }
04147 rpt_mutex_unlock(&myrpt->lock);
04148 }
04149 if( unkeys_queued > 1){
04150 imdone = 1;
04151 break;
04152 }
04153
04154
04155
04156 while(myrpt->unkeytocttimer)
04157 {
04158 int ctint;
04159 if(myrpt->unkeytocttimer > 100)
04160 ctint = 100;
04161 else
04162 ctint = myrpt->unkeytocttimer;
04163 ast_safe_sleep(mychannel, ctint);
04164 rpt_mutex_lock(&myrpt->lock);
04165 if(myrpt->unkeytocttimer < ctint)
04166 myrpt->unkeytocttimer = 0;
04167 else
04168 myrpt->unkeytocttimer -= ctint;
04169 rpt_mutex_unlock(&myrpt->lock);
04170 }
04171
04172
04173
04174
04175
04176 if(myrpt->keyed){
04177 imdone = 1;
04178 break;
04179 }
04180
04181 rpt_mutex_lock(&myrpt->lock);
04182 myrpt->dailykerchunks++;
04183 myrpt->totalkerchunks++;
04184 rpt_mutex_unlock(&myrpt->lock);
04185
04186 haslink = 0;
04187 hastx = 0;
04188 hasremote = 0;
04189 l = myrpt->links.next;
04190 if (l != &myrpt->links)
04191 {
04192 rpt_mutex_lock(&myrpt->lock);
04193 while(l != &myrpt->links)
04194 {
04195 if (l->name[0] == '0')
04196 {
04197 l = l->next;
04198 continue;
04199 }
04200 haslink = 1;
04201 if (l->mode) {
04202 hastx++;
04203 if (l->isremote) hasremote++;
04204 }
04205 l = l->next;
04206 }
04207 rpt_mutex_unlock(&myrpt->lock);
04208 }
04209 if (haslink)
04210 {
04211
04212 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04213 if(res)
04214 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04215
04216
04217
04218 if (myrpt->cmdnode[0])
04219 {
04220 ast_safe_sleep(mychannel,200);
04221 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04222 if(res)
04223 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04224 ast_stopstream(mychannel);
04225 }
04226 }
04227 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04228 ct_copy = ast_strdup(ct);
04229 if(ct_copy)
04230 {
04231 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04232 ast_free(ct_copy);
04233 }
04234 else
04235 res = -1;
04236 if(res)
04237 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04238 }
04239 if (hasremote && (!myrpt->cmdnode[0]))
04240 {
04241
04242 ci.chan = 0;
04243 ci.confno = myrpt->conf;
04244 ci.confmode = DAHDI_CONF_CONFANN;
04245
04246 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04247 {
04248 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04249 rpt_mutex_lock(&myrpt->lock);
04250 myrpt->active_telem = NULL;
04251 remque((struct qelem *)mytele);
04252 rpt_mutex_unlock(&myrpt->lock);
04253 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04254 ast_free(nodename);
04255 if(id_malloc)
04256 ast_free(ident);
04257 ast_free(mytele);
04258 ast_hangup(mychannel);
04259 pthread_exit(NULL);
04260 }
04261 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04262 ast_safe_sleep(mychannel,200);
04263 ct_copy = ast_strdup(ct);
04264 if(ct_copy)
04265 {
04266 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04267 ast_free(ct_copy);
04268 }
04269 else
04270 res = -1;
04271
04272 if(res)
04273 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04274 }
04275 }
04276 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04277 if (myrpt->lastunit)
04278 {
04279 char mystr[10];
04280
04281 ast_safe_sleep(mychannel,200);
04282
04283 ci.chan = 0;
04284 ci.confno = myrpt->txconf;
04285 ci.confmode = DAHDI_CONF_CONFANN;
04286
04287 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04288 {
04289 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04290 rpt_mutex_lock(&myrpt->lock);
04291 myrpt->active_telem = NULL;
04292 remque((struct qelem *)mytele);
04293 rpt_mutex_unlock(&myrpt->lock);
04294 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04295 ast_free(nodename);
04296 if(id_malloc)
04297 ast_free(ident);
04298 ast_free(mytele);
04299 ast_hangup(mychannel);
04300 pthread_exit(NULL);
04301 }
04302 sprintf(mystr,"%04x",myrpt->lastunit);
04303 myrpt->lastunit = 0;
04304 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04305 break;
04306 }
04307 #endif
04308 imdone = 1;
04309 break;
04310 case LINKUNKEY:
04311 if(myrpt->patchnoct && myrpt->callmode){
04312 imdone = 1;
04313 break;
04314 }
04315
04316
04317
04318
04319
04320 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04321 mytele->mylink.linkunkeytocttimer = x;
04322
04323
04324
04325
04326
04327 tlist = myrpt->tele.next;
04328 unkeys_queued = 0;
04329 if (tlist != &myrpt->tele)
04330 {
04331 rpt_mutex_lock(&myrpt->lock);
04332 while(tlist != &myrpt->tele){
04333 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04334 tlist = tlist->next;
04335 }
04336 rpt_mutex_unlock(&myrpt->lock);
04337 }
04338 if( unkeys_queued > 1){
04339 imdone = 1;
04340 break;
04341 }
04342
04343
04344
04345 while(mytele->mylink.linkunkeytocttimer)
04346 {
04347 int ctint;
04348 if(mytele->mylink.linkunkeytocttimer > 100)
04349 ctint = 100;
04350 else
04351 ctint = mytele->mylink.linkunkeytocttimer;
04352 ast_safe_sleep(mychannel, ctint);
04353 rpt_mutex_lock(&myrpt->lock);
04354 if(mytele->mylink.linkunkeytocttimer < ctint)
04355 mytele->mylink.linkunkeytocttimer = 0;
04356 else
04357 mytele->mylink.linkunkeytocttimer -= ctint;
04358 rpt_mutex_unlock(&myrpt->lock);
04359 }
04360
04361 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04362 ct_copy = ast_strdup(ct);
04363 if(ct_copy){
04364 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04365 ast_free(ct_copy);
04366 }
04367 else
04368 res = -1;
04369 if(res)
04370 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04371 }
04372 imdone = 1;
04373 break;
04374 case REMDISC:
04375
04376 wait_interval(myrpt, DLY_TELEM, mychannel);
04377 l = myrpt->links.next;
04378 haslink = 0;
04379
04380 if (l != &myrpt->links)
04381 {
04382 rpt_mutex_lock(&myrpt->lock);
04383 while(l != &myrpt->links)
04384 {
04385 if (l->name[0] == '0')
04386 {
04387 l = l->next;
04388 continue;
04389 }
04390 if (!strcmp(l->name,mytele->mylink.name))
04391 {
04392 haslink = 1;
04393 break;
04394 }
04395 l = l->next;
04396 }
04397 rpt_mutex_unlock(&myrpt->lock);
04398 }
04399 if (haslink)
04400 {
04401 imdone = 1;
04402 break;
04403 }
04404 res = saynode(myrpt,mychannel,mytele->mylink.name);
04405 if (!res)
04406 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04407 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04408 break;
04409 case REMALREADY:
04410
04411 wait_interval(myrpt, DLY_TELEM, mychannel);
04412 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04413 break;
04414 case REMNOTFOUND:
04415
04416 wait_interval(myrpt, DLY_TELEM, mychannel);
04417 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04418 break;
04419 case REMGO:
04420
04421 wait_interval(myrpt, DLY_TELEM, mychannel);
04422 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04423 break;
04424 case CONNECTED:
04425
04426 wait_interval(myrpt, DLY_TELEM, mychannel);
04427 res = saynode(myrpt,mychannel,mytele->mylink.name);
04428 if (!res)
04429 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04430 if (!res)
04431 res = ast_waitstream(mychannel, "");
04432 else
04433 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04434 ast_stopstream(mychannel);
04435 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04436 if (!res)
04437 res = ast_waitstream(mychannel, "");
04438 else
04439 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04440 ast_stopstream(mychannel);
04441 res = saynode(myrpt,mychannel,myrpt->name);
04442 imdone = 1;
04443 break;
04444 case CONNFAIL:
04445 res = saynode(myrpt,mychannel,mytele->mylink.name);
04446 if (!res)
04447 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04448 break;
04449 case MEMNOTFOUND:
04450
04451 wait_interval(myrpt, DLY_TELEM, mychannel);
04452 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04453 break;
04454 case PLAYBACK:
04455
04456 wait_interval(myrpt, DLY_TELEM, mychannel);
04457 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04458 break;
04459 case TOPKEY:
04460
04461 wait_interval(myrpt, DLY_TELEM, mychannel);
04462 for(i = 0; i < TOPKEYN; i++)
04463 {
04464 if (!myrpt->topkey[i].node[0]) continue;
04465 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04466 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04467 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04468 "rpt/keyedfor" : "rpt/unkeyedfor");
04469 if (!res) res = saynum(mychannel,
04470 myrpt->topkey[i].timesince);
04471 if (!res) res = sayfile(mychannel,"rpt/seconds");
04472 if (!myrpt->topkeylong) break;
04473 }
04474 imdone = 1;
04475 break;
04476 case SETREMOTE:
04477 ast_mutex_lock(&myrpt->remlock);
04478 res = 0;
04479 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04480 {
04481 res = set_ft897(myrpt);
04482 }
04483 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04484 {
04485 res = set_tm271(myrpt);
04486 }
04487 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04488 {
04489 res = set_ic706(myrpt);
04490 }
04491 #ifdef HAVE_IOPERM
04492 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04493 {
04494 if (ioperm(myrpt->p.iobase,1,1) == -1)
04495 {
04496 rpt_mutex_unlock(&myrpt->lock);
04497 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04498 res = -1;
04499 }
04500 else res = setrbi(myrpt);
04501 }
04502 #endif
04503 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04504 {
04505 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04506 res = setkenwood(myrpt);
04507 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04508 if (ast_safe_sleep(mychannel,200) == -1)
04509 {
04510 ast_mutex_unlock(&myrpt->remlock);
04511 res = -1;
04512 break;
04513 }
04514 if (myrpt->iofd < 0)
04515 {
04516 i = DAHDI_FLUSH_EVENT;
04517 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04518 {
04519 ast_mutex_unlock(&myrpt->remlock);
04520 ast_log(LOG_ERROR,"Cant flush events");
04521 res = -1;
04522 break;
04523 }
04524 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04525 {
04526 ast_mutex_unlock(&myrpt->remlock);
04527 ast_log(LOG_ERROR,"Cant get params");
04528 res = -1;
04529 break;
04530 }
04531 myrpt->remoterx =
04532 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04533 }
04534 }
04535
04536 ast_mutex_unlock(&myrpt->remlock);
04537 if (!res)
04538 {
04539 imdone = 1;
04540 break;
04541 }
04542
04543 case INVFREQ:
04544
04545 wait_interval(myrpt, DLY_TELEM, mychannel);
04546 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04547 break;
04548 case REMMODE:
04549 cp = 0;
04550 wait_interval(myrpt, DLY_TELEM, mychannel);
04551 switch(myrpt->remmode)
04552 {
04553 case REM_MODE_FM:
04554 saycharstr(mychannel,"FM");
04555 break;
04556 case REM_MODE_USB:
04557 saycharstr(mychannel,"USB");
04558 break;
04559 case REM_MODE_LSB:
04560 saycharstr(mychannel,"LSB");
04561 break;
04562 case REM_MODE_AM:
04563 saycharstr(mychannel,"AM");
04564 break;
04565 }
04566 wait_interval(myrpt, DLY_COMP, mychannel);
04567 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04568 break;
04569 case LOGINREQ:
04570 wait_interval(myrpt, DLY_TELEM, mychannel);
04571 sayfile(mychannel,"rpt/login");
04572 saycharstr(mychannel,myrpt->name);
04573 break;
04574 case REMLOGIN:
04575 wait_interval(myrpt, DLY_TELEM, mychannel);
04576 saycharstr(mychannel,myrpt->loginuser);
04577 saynode(myrpt,mychannel,myrpt->name);
04578 wait_interval(myrpt, DLY_COMP, mychannel);
04579 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04580 break;
04581 case REMXXX:
04582 wait_interval(myrpt, DLY_TELEM, mychannel);
04583 res = 0;
04584 switch(mytele->submode)
04585 {
04586 case 100:
04587 sayfile(mychannel, "rpt/rxpl");
04588 sayfile(mychannel, "rpt/off");
04589 break;
04590 case 101:
04591 sayfile(mychannel, "rpt/rxpl");
04592 sayfile(mychannel, "rpt/on");
04593 break;
04594 case 102:
04595 sayfile(mychannel, "rpt/txpl");
04596 sayfile(mychannel, "rpt/off");
04597 break;
04598 case 103:
04599 sayfile(mychannel, "rpt/txpl");
04600 sayfile(mychannel, "rpt/on");
04601 break;
04602 case 104:
04603 sayfile(mychannel, "rpt/lopwr");
04604 break;
04605 case 105:
04606 sayfile(mychannel, "rpt/medpwr");
04607 break;
04608 case 106:
04609 sayfile(mychannel, "rpt/hipwr");
04610 break;
04611 case 113:
04612 sayfile(mychannel,"rpt/down");
04613 sayfile(mychannel, "rpt/slow");
04614 break;
04615 case 114:
04616 sayfile(mychannel,"rpt/down");
04617 sayfile(mychannel, "rpt/quick");
04618 break;
04619 case 115:
04620 sayfile(mychannel,"rpt/down");
04621 sayfile(mychannel, "rpt/fast");
04622 break;
04623 case 116:
04624 sayfile(mychannel,"rpt/up");
04625 sayfile(mychannel, "rpt/slow");
04626 break;
04627 case 117:
04628 sayfile(mychannel,"rpt/up");
04629 sayfile(mychannel, "rpt/quick");
04630 break;
04631 case 118:
04632 sayfile(mychannel,"rpt/up");
04633 sayfile(mychannel, "rpt/fast");
04634 break;
04635 default:
04636 res = -1;
04637 }
04638 wait_interval(myrpt, DLY_COMP, mychannel);
04639 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04640 break;
04641 case SCAN:
04642 ast_mutex_lock(&myrpt->remlock);
04643 if (myrpt->hfscanstop)
04644 {
04645 myrpt->hfscanstatus = 0;
04646 myrpt->hfscanmode = 0;
04647 myrpt->hfscanstop = 0;
04648 mytele->mode = SCANSTAT;
04649 ast_mutex_unlock(&myrpt->remlock);
04650 if (ast_safe_sleep(mychannel,1000) == -1) break;
04651 sayfile(mychannel, "rpt/stop");
04652 imdone = 1;
04653 break;
04654 }
04655 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04656 i = myrpt->hfscanstatus;
04657 myrpt->hfscanstatus = 0;
04658 if (i) mytele->mode = SCANSTAT;
04659 ast_mutex_unlock(&myrpt->remlock);
04660 if (i < 0) sayfile(mychannel, "rpt/stop");
04661 else if (i > 0) saynum(mychannel,i);
04662 imdone = 1;
04663 break;
04664 case TUNE:
04665 ast_mutex_lock(&myrpt->remlock);
04666 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04667 {
04668 set_mode_ic706(myrpt, REM_MODE_AM);
04669 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04670 ast_safe_sleep(mychannel,500);
04671 set_mode_ic706(myrpt, myrpt->remmode);
04672 myrpt->tunerequest = 0;
04673 ast_mutex_unlock(&myrpt->remlock);
04674 imdone = 1;
04675 break;
04676 }
04677 set_mode_ft897(myrpt, REM_MODE_AM);
04678 simple_command_ft897(myrpt, 8);
04679 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04680 simple_command_ft897(myrpt, 0x88);
04681 ast_safe_sleep(mychannel,500);
04682 set_mode_ft897(myrpt, myrpt->remmode);
04683 myrpt->tunerequest = 0;
04684 ast_mutex_unlock(&myrpt->remlock);
04685 imdone = 1;
04686 break;
04687 case REMSHORTSTATUS:
04688 case REMLONGSTATUS:
04689 wait_interval(myrpt, DLY_TELEM, mychannel);
04690 res = saynode(myrpt,mychannel,myrpt->name);
04691 if(!res)
04692 res = sayfile(mychannel,"rpt/frequency");
04693 if(!res)
04694 res = split_freq(mhz, decimals, myrpt->freq);
04695 if (!multimode_capable(myrpt)) decimals[3] = 0;
04696 if(!res){
04697 m = atoi(mhz);
04698 if(m < 100)
04699 res = saynum(mychannel, m);
04700 else
04701 res = saycharstr(mychannel, mhz);
04702 }
04703 if(!res)
04704 res = sayfile(mychannel, "letters/dot");
04705 if(!res)
04706 res = saycharstr(mychannel, decimals);
04707
04708 if(res) break;
04709 if(myrpt->remmode == REM_MODE_FM){
04710 switch(myrpt->offset){
04711
04712 case REM_MINUS:
04713 res = sayfile(mychannel,"rpt/minus");
04714 break;
04715
04716 case REM_SIMPLEX:
04717 res = sayfile(mychannel,"rpt/simplex");
04718 break;
04719
04720 case REM_PLUS:
04721 res = sayfile(mychannel,"rpt/plus");
04722 break;
04723
04724 default:
04725 break;
04726 }
04727 }
04728 else{
04729 switch(myrpt->remmode){
04730
04731 case REM_MODE_USB:
04732 res = saycharstr(mychannel, "USB");
04733 break;
04734
04735 case REM_MODE_LSB:
04736 res = saycharstr(mychannel, "LSB");
04737 break;
04738
04739 case REM_MODE_AM:
04740 res = saycharstr(mychannel, "AM");
04741 break;
04742
04743
04744 default:
04745 break;
04746 }
04747 }
04748
04749 if (res == -1) break;
04750
04751 if(mytele->mode == REMSHORTSTATUS){
04752 wait_interval(myrpt, DLY_COMP, mychannel);
04753 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04754 break;
04755 }
04756
04757 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04758 {
04759 switch(myrpt->powerlevel){
04760
04761 case REM_LOWPWR:
04762 res = sayfile(mychannel,"rpt/lopwr") ;
04763 break;
04764 case REM_MEDPWR:
04765 res = sayfile(mychannel,"rpt/medpwr");
04766 break;
04767 case REM_HIPWR:
04768 res = sayfile(mychannel,"rpt/hipwr");
04769 break;
04770 }
04771 }
04772
04773 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04774 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04775 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04776 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04777 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04778 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04779 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04780 (sayfile(mychannel,"rpt/frequency") == -1) ||
04781 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04782 if(myrpt->remmode == REM_MODE_FM){
04783 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04784 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04785 (sayfile(mychannel,"rpt/txpl") == -1) ||
04786 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04787 {
04788 break;
04789 }
04790 }
04791 wait_interval(myrpt, DLY_COMP, mychannel);
04792 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04793 break;
04794 case STATUS:
04795
04796 wait_interval(myrpt, DLY_TELEM, mychannel);
04797 hastx = 0;
04798 linkbase.next = &linkbase;
04799 linkbase.prev = &linkbase;
04800 rpt_mutex_lock(&myrpt->lock);
04801
04802 l = myrpt->links.next;
04803 while(l != &myrpt->links)
04804 {
04805 if (l->name[0] == '0')
04806 {
04807 l = l->next;
04808 continue;
04809 }
04810 l1 = ast_malloc(sizeof(struct rpt_link));
04811 if (!l1)
04812 {
04813 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04814 remque((struct qelem *)mytele);
04815 myrpt->active_telem = NULL;
04816 rpt_mutex_unlock(&myrpt->lock);
04817 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04818 ast_free(nodename);
04819 if(id_malloc)
04820 ast_free(ident);
04821 ast_free(mytele);
04822 ast_hangup(mychannel);
04823 pthread_exit(NULL);
04824 }
04825 memcpy(l1,l,sizeof(struct rpt_link));
04826 l1->next = l1->prev = NULL;
04827 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04828 l = l->next;
04829 }
04830 rpt_mutex_unlock(&myrpt->lock);
04831 res = saynode(myrpt,mychannel,myrpt->name);
04832 if (myrpt->callmode)
04833 {
04834 hastx = 1;
04835 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04836 if (!res)
04837 res = ast_waitstream(mychannel, "");
04838 else
04839 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04840 ast_stopstream(mychannel);
04841 }
04842 l = linkbase.next;
04843 while(l != &linkbase)
04844 {
04845 char *s;
04846
04847 hastx = 1;
04848 res = saynode(myrpt,mychannel,l->name);
04849 s = "rpt/tranceive";
04850 if (!l->mode) s = "rpt/monitor";
04851 if (!l->thisconnected) s = "rpt/connecting";
04852 res = ast_streamfile(mychannel, s, mychannel->language);
04853 if (!res)
04854 res = ast_waitstream(mychannel, "");
04855 else
04856 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04857 ast_stopstream(mychannel);
04858 l = l->next;
04859 }
04860 if (!hastx)
04861 {
04862 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04863 if (!res)
04864 res = ast_waitstream(mychannel, "");
04865 else
04866 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04867 ast_stopstream(mychannel);
04868 }
04869
04870 l = linkbase.next;
04871 while(l != &linkbase)
04872 {
04873 l1 = l;
04874 l = l->next;
04875 remque((struct qelem *)l1);
04876 ast_free(l1);
04877 }
04878 imdone = 1;
04879 break;
04880 case FULLSTATUS:
04881 rpt_mutex_lock(&myrpt->lock);
04882
04883 __mklinklist(myrpt,NULL,lbuf);
04884 rpt_mutex_unlock(&myrpt->lock);
04885
04886 ns = finddelim(lbuf,strs,MAXLINKLIST);
04887
04888 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04889
04890 wait_interval(myrpt, DLY_TELEM, mychannel);
04891 hastx = 0;
04892 res = saynode(myrpt,mychannel,myrpt->name);
04893 if (myrpt->callmode)
04894 {
04895 hastx = 1;
04896 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04897 if (!res)
04898 res = ast_waitstream(mychannel, "");
04899 else
04900 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04901 ast_stopstream(mychannel);
04902 }
04903
04904 for(i = 0; i < ns; i++)
04905 {
04906 char *s,mode = 'T';
04907
04908
04909 if ((*strs[i] < '0') || (*strs[i] > '9'))
04910 {
04911 mode = *strs[i];
04912 strs[i]++;
04913 }
04914
04915 hastx = 1;
04916 res = saynode(myrpt,mychannel,strs[i]);
04917 s = "rpt/tranceive";
04918 if (mode == 'R') s = "rpt/monitor";
04919 if (mode == 'C') s = "rpt/connecting";
04920 res = ast_streamfile(mychannel, s, mychannel->language);
04921 if (!res)
04922 res = ast_waitstream(mychannel, "");
04923 else
04924 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04925 ast_stopstream(mychannel);
04926 }
04927 if (!hastx)
04928 {
04929 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04930 if (!res)
04931 res = ast_waitstream(mychannel, "");
04932 else
04933 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04934 ast_stopstream(mychannel);
04935 }
04936 imdone = 1;
04937 break;
04938
04939 case LASTNODEKEY:
04940 rpt_mutex_lock(&myrpt->lock);
04941 if(myrpt->lastnodewhichkeyedusup){
04942 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04943 if(!p){
04944 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04945 imdone = 1;
04946 break;
04947 }
04948 }
04949 else
04950 p = NULL;
04951 rpt_mutex_unlock(&myrpt->lock);
04952 if(!p){
04953 imdone = 1;
04954 break;
04955 }
04956 wait_interval(myrpt, DLY_TELEM, mychannel);
04957 res = saynode(myrpt,mychannel,p);
04958 ast_free(p);
04959 imdone = 1;
04960 break;
04961
04962 case UNAUTHTX:
04963 wait_interval(myrpt, DLY_TELEM, mychannel);
04964 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04965 if (!res)
04966 res = ast_waitstream(mychannel, "");
04967 else
04968 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04969 ast_stopstream(mychannel);
04970 imdone = 1;
04971 break;
04972
04973 case PARROT:
04974
04975 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04976 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04977 {
04978 imdone = 1;
04979 myrpt->parrotstate = 0;
04980 break;
04981 }
04982 wait_interval(myrpt, DLY_PARROT, mychannel);
04983 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04984 res = ast_streamfile(mychannel, mystr, mychannel->language);
04985 if (!res)
04986 res = ast_waitstream(mychannel, "");
04987 else
04988 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04989 ast_stopstream(mychannel);
04990 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04991 strcat(mystr,".wav");
04992 unlink(mystr);
04993 imdone = 1;
04994 myrpt->parrotstate = 0;
04995 break;
04996
04997 case TIMEOUT:
04998 res = saynode(myrpt,mychannel,myrpt->name);
04999 if (!res)
05000 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
05001 break;
05002
05003 case TIMEOUT_WARNING:
05004 time(&t);
05005 res = saynode(myrpt,mychannel,myrpt->name);
05006 if (!res)
05007 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05008 if (!res)
05009 res = ast_waitstream(mychannel, "");
05010 else
05011 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05012 ast_stopstream(mychannel);
05013 if(!res)
05014 ast_say_number(mychannel, myrpt->p.remotetimeout -
05015 (t - myrpt->last_activity_time),
05016 "", mychannel->language, (char *) NULL);
05017 if (!res)
05018 res = ast_waitstream(mychannel, "");
05019 ast_stopstream(mychannel);
05020 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05021 break;
05022
05023 case ACT_TIMEOUT_WARNING:
05024 time(&t);
05025 res = saynode(myrpt,mychannel,myrpt->name);
05026 if (!res)
05027 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05028 if (!res)
05029 res = ast_waitstream(mychannel, "");
05030 else
05031 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05032 ast_stopstream(mychannel);
05033 if(!res)
05034 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05035 (t - myrpt->last_activity_time),
05036 "", mychannel->language, (char *) NULL);
05037 if (!res)
05038 res = ast_waitstream(mychannel, "");
05039 ast_stopstream(mychannel);
05040 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05041 break;
05042
05043 case STATS_TIME:
05044 case STATS_TIME_LOCAL:
05045 wait_interval(myrpt, DLY_TELEM, mychannel);
05046 t = time(NULL);
05047 rpt_localtime(&t, &localtm);
05048
05049 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05050 p = "rpt/goodmorning";
05051 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05052 p = "rpt/goodafternoon";
05053 else
05054 p = "rpt/goodevening";
05055 if (sayfile(mychannel,p) == -1)
05056 {
05057 imdone = 1;
05058 break;
05059 }
05060
05061 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05062 {
05063 imdone = 1;
05064 break;
05065 }
05066
05067 res = ast_say_time(mychannel, t, "", mychannel->language);
05068 if (!res)
05069 res = ast_waitstream(mychannel, "");
05070 ast_stopstream(mychannel);
05071 imdone = 1;
05072 break;
05073 case STATS_VERSION:
05074 p = strstr(tdesc, "version");
05075 if(!p)
05076 break;
05077 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
05078 break;
05079 wait_interval(myrpt, DLY_TELEM, mychannel);
05080
05081 if (sayfile(mychannel,"rpt/version") == -1)
05082 {
05083 imdone = 1;
05084 break;
05085 }
05086 if(!res)
05087 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05088 if (!res)
05089 res = ast_waitstream(mychannel, "");
05090 ast_stopstream(mychannel);
05091 if (saycharstr(mychannel,".") == -1)
05092 {
05093 imdone = 1;
05094 break;
05095 }
05096 if(!res)
05097 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05098 if (!res){
05099 res = ast_waitstream(mychannel, "");
05100 ast_stopstream(mychannel);
05101 }
05102 else
05103 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05104 imdone = 1;
05105 break;
05106 case ARB_ALPHA:
05107 wait_interval(myrpt, DLY_TELEM, mychannel);
05108 if(mytele->param)
05109 saycharstr(mychannel, mytele->param);
05110 imdone = 1;
05111 break;
05112 case REV_PATCH:
05113 wait_interval(myrpt, DLY_TELEM, mychannel);
05114 if(mytele->param) {
05115
05116
05117 char *tpl_working, *tpl_current;
05118 char *tmp[100], *myparm;
05119 int looptemp=0,idx=0, dres = 0;
05120
05121
05122 tpl_working = ast_strdup(mytele->param);
05123 myparm = strsep(&tpl_working,",");
05124 tpl_current=strsep(&tpl_working, ":");
05125
05126 while(tpl_current && looptemp < sizeof(tmp)) {
05127 tmp[looptemp]=tpl_current;
05128 looptemp++;
05129 tpl_current=strsep(&tpl_working,":");
05130 }
05131
05132 for(idx=0; idx<looptemp; idx++) {
05133 if(!strcmp(tmp[idx], "PARKED")) {
05134 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05135 } else if(!strcmp(tmp[idx], "NODE")) {
05136 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05137 } else {
05138 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05139 if(!dres) {
05140 dres = ast_waitstream(mychannel, "");
05141 } else {
05142 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05143 dres = 0;
05144 }
05145 }
05146 }
05147 ast_free(tpl_working);
05148 }
05149 imdone = 1;
05150 break;
05151 case TEST_TONE:
05152 imdone = 1;
05153 if (myrpt->stopgen) break;
05154 myrpt->stopgen = -1;
05155 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05156 {
05157 myrpt->stopgen = 0;
05158 break;
05159 }
05160 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05161 if (ast_safe_sleep(mychannel,1)) break;
05162 imdone = 1;
05163 }
05164 myrpt->stopgen = 0;
05165 break;
05166 default:
05167 break;
05168 }
05169 if (!imdone)
05170 {
05171 if (!res)
05172 res = ast_waitstream(mychannel, "");
05173 else {
05174 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05175 res = 0;
05176 }
05177 }
05178 ast_stopstream(mychannel);
05179 rpt_mutex_lock(&myrpt->lock);
05180 if (mytele->mode == TAILMSG)
05181 {
05182 if (!res)
05183 {
05184 myrpt->tailmessagen++;
05185 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05186 }
05187 else
05188 {
05189 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05190 }
05191 }
05192 remque((struct qelem *)mytele);
05193 myrpt->active_telem = NULL;
05194 rpt_mutex_unlock(&myrpt->lock);
05195 ast_free(nodename);
05196 if(id_malloc)
05197 ast_free(ident);
05198 ast_free(mytele);
05199 ast_hangup(mychannel);
05200 #ifdef APP_RPT_LOCK_DEBUG
05201 {
05202 struct lockthread *t;
05203
05204 sleep(5);
05205 ast_mutex_lock(&locklock);
05206 t = get_lockthread(pthread_self());
05207 if (t) memset(t,0,sizeof(struct lockthread));
05208 ast_mutex_unlock(&locklock);
05209 }
05210 #endif
05211 pthread_exit(NULL);
05212 }
05213
05214 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05215 {
05216 struct rpt_tele *tele;
05217 struct rpt_link *mylink = NULL;
05218 int res;
05219 pthread_attr_t attr;
05220 char *v1, *v2;
05221
05222 if(debug > 6)
05223 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05224
05225 switch(mode)
05226 {
05227 case UNKEY:
05228
05229
05230 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05231 "unlinkedct");
05232 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05233 "remotect");
05234 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05235 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05236 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05237 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05238 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05239 break;
05240 case LINKUNKEY:
05241 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05242 return;
05243 break;
05244 default:
05245 break;
05246 }
05247 tele = ast_malloc(sizeof(struct rpt_tele));
05248 if (!tele)
05249 {
05250 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05251 pthread_exit(NULL);
05252 return;
05253 }
05254
05255 memset((char *)tele,0,sizeof(struct rpt_tele));
05256 tele->rpt = myrpt;
05257 tele->mode = mode;
05258 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05259 else mylink = (struct rpt_link *) data;
05260 rpt_mutex_lock(&myrpt->lock);
05261 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05262 (mode == LINKUNKEY)){
05263 memset(&tele->mylink,0,sizeof(struct rpt_link));
05264 if (mylink){
05265 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05266 }
05267 }
05268 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05269 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05270 tele->param[TELEPARAMSIZE - 1] = 0;
05271 }
05272 if (mode == REMXXX) tele->submode = (intptr_t) data;
05273 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05274 rpt_mutex_unlock(&myrpt->lock);
05275 pthread_attr_init(&attr);
05276 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05277 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05278 if(res < 0){
05279 rpt_mutex_lock(&myrpt->lock);
05280 remque((struct qlem *) tele);
05281 rpt_mutex_unlock(&myrpt->lock);
05282 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05283 }
05284 return;
05285 }
05286
05287 static void *rpt_call(void *this)
05288 {
05289 struct dahdi_confinfo ci;
05290 struct rpt *myrpt = (struct rpt *)this;
05291 int res;
05292 int stopped,congstarted,dialtimer,lastcidx,aborted;
05293 struct ast_channel *mychannel,*genchannel;
05294
05295 myrpt->mydtmf = 0;
05296
05297 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05298 if (!mychannel)
05299 {
05300 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05301 pthread_exit(NULL);
05302 }
05303 #ifdef AST_CDR_FLAG_POST_DISABLED
05304 if (mychannel->cdr)
05305 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05306 #endif
05307 ci.chan = 0;
05308 ci.confno = myrpt->conf;
05309 #if 0
05310 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05311 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05312 #endif
05313 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05314
05315 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05316 {
05317 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05318 ast_hangup(mychannel);
05319 myrpt->callmode = 0;
05320 pthread_exit(NULL);
05321 }
05322
05323 genchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05324 if (!genchannel)
05325 {
05326 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05327 ast_hangup(mychannel);
05328 pthread_exit(NULL);
05329 }
05330 #ifdef AST_CDR_FLAG_POST_DISABLED
05331 if (genchannel->cdr)
05332 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05333 #endif
05334 ci.chan = 0;
05335 ci.confno = myrpt->conf;
05336 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05337 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05338
05339 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05340 {
05341 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05342 ast_hangup(mychannel);
05343 ast_hangup(genchannel);
05344 myrpt->callmode = 0;
05345 pthread_exit(NULL);
05346 }
05347 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05348 {
05349 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05350 ast_hangup(mychannel);
05351 ast_hangup(genchannel);
05352 myrpt->callmode = 0;
05353 pthread_exit(NULL);
05354 }
05355 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05356 {
05357 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05358 ast_hangup(mychannel);
05359 ast_hangup(genchannel);
05360 myrpt->callmode = 0;
05361 pthread_exit(NULL);
05362 }
05363
05364 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05365 {
05366 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05367 ast_hangup(mychannel);
05368 ast_hangup(genchannel);
05369 myrpt->callmode = 0;
05370 pthread_exit(NULL);
05371 }
05372 stopped = 0;
05373 congstarted = 0;
05374 dialtimer = 0;
05375 lastcidx = 0;
05376 myrpt->calldigittimer = 0;
05377 aborted = 0;
05378
05379 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05380 {
05381 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05382 dialtimer = 0;
05383 lastcidx = myrpt->cidx;
05384 }
05385
05386 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05387 if(debug)
05388 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05389 rpt_mutex_lock(&myrpt->lock);
05390 aborted = 1;
05391 myrpt->callmode = 0;
05392 rpt_mutex_unlock(&myrpt->lock);
05393 break;
05394 }
05395
05396 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05397 {
05398 stopped = 1;
05399
05400 tone_zone_play_tone(genchannel->fds[0],-1);
05401 }
05402 if (myrpt->callmode == 1)
05403 {
05404 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05405 {
05406 myrpt->callmode = 2;
05407 break;
05408 }
05409
05410 if (myrpt->calldigittimer)
05411 myrpt->calldigittimer += MSWAIT;
05412 }
05413 if (myrpt->callmode == 4)
05414 {
05415 if(!congstarted){
05416 congstarted = 1;
05417
05418 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05419 }
05420 }
05421 res = ast_safe_sleep(mychannel, MSWAIT);
05422 if (res < 0)
05423 {
05424 if(debug)
05425 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05426 ast_hangup(mychannel);
05427 ast_hangup(genchannel);
05428 rpt_mutex_lock(&myrpt->lock);
05429 myrpt->callmode = 0;
05430 rpt_mutex_unlock(&myrpt->lock);
05431 pthread_exit(NULL);
05432 }
05433 dialtimer += MSWAIT;
05434 }
05435
05436 tone_zone_play_tone(genchannel->fds[0],-1);
05437
05438 if (!myrpt->callmode)
05439 {
05440 if(debug)
05441 ast_log(LOG_NOTICE, "callmode==0\n");
05442 ast_hangup(mychannel);
05443 ast_hangup(genchannel);
05444 rpt_mutex_lock(&myrpt->lock);
05445 myrpt->callmode = 0;
05446 myrpt->macropatch=0;
05447 channel_revert(myrpt);
05448 rpt_mutex_unlock(&myrpt->lock);
05449 if((!myrpt->patchquiet) && aborted)
05450 rpt_telemetry(myrpt, TERM, NULL);
05451 pthread_exit(NULL);
05452 }
05453
05454 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05455 char *name, *loc, *instr;
05456 instr = ast_strdup(myrpt->p.ourcallerid);
05457 if(instr){
05458 ast_callerid_parse(instr, &name, &loc);
05459 if(loc){
05460 if(mychannel->cid.cid_num)
05461 ast_free(mychannel->cid.cid_num);
05462 mychannel->cid.cid_num = ast_strdup(loc);
05463 }
05464 if(name){
05465 if(mychannel->cid.cid_name)
05466 ast_free(mychannel->cid.cid_name);
05467 mychannel->cid.cid_name = ast_strdup(name);
05468 }
05469 ast_free(instr);
05470 }
05471 }
05472
05473 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05474 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05475
05476 if (myrpt->p.acctcode)
05477 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05478 mychannel->priority = 1;
05479 ast_channel_undefer_dtmf(mychannel);
05480 if (ast_pbx_start(mychannel) < 0)
05481 {
05482 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05483 ast_hangup(mychannel);
05484 ast_hangup(genchannel);
05485 rpt_mutex_lock(&myrpt->lock);
05486 myrpt->callmode = 0;
05487 rpt_mutex_unlock(&myrpt->lock);
05488 pthread_exit(NULL);
05489 }
05490 usleep(10000);
05491 rpt_mutex_lock(&myrpt->lock);
05492 myrpt->callmode = 3;
05493
05494 ci.chan = 0;
05495 ci.confno = myrpt->conf;
05496 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05497 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05498
05499 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05500 {
05501 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05502 ast_hangup(mychannel);
05503 ast_hangup(genchannel);
05504 myrpt->callmode = 0;
05505 pthread_exit(NULL);
05506 }
05507
05508 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05509 {
05510 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05511 ast_hangup(mychannel);
05512 myrpt->callmode = 0;
05513 pthread_exit(NULL);
05514 }
05515 ci.chan = 0;
05516 ci.confno = res;
05517 ci.confmode = DAHDI_CONF_MONITOR;
05518
05519 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05520 {
05521 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05522 ast_hangup(mychannel);
05523 myrpt->callmode = 0;
05524 pthread_exit(NULL);
05525 }
05526 while(myrpt->callmode)
05527 {
05528 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05529 {
05530
05531 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05532 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05533 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05534 myrpt->callmode = 0;
05535 myrpt->macropatch=0;
05536 if(!myrpt->patchquiet){
05537 rpt_mutex_unlock(&myrpt->lock);
05538 rpt_telemetry(myrpt, TERM, NULL);
05539 rpt_mutex_lock(&myrpt->lock);
05540 }
05541 }
05542 else{
05543 myrpt->callmode = 4;
05544 rpt_mutex_unlock(&myrpt->lock);
05545
05546 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05547 rpt_mutex_lock(&myrpt->lock);
05548 }
05549 }
05550 if (myrpt->mydtmf)
05551 {
05552 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05553 wf.subclass = myrpt->mydtmf;
05554 rpt_mutex_unlock(&myrpt->lock);
05555 ast_queue_frame(mychannel,&wf);
05556 #ifdef NEW_ASTERISK
05557 ast_senddigit(genchannel,myrpt->mydtmf,0);
05558 #else
05559 ast_senddigit(genchannel,myrpt->mydtmf);
05560 #endif
05561 rpt_mutex_lock(&myrpt->lock);
05562 myrpt->mydtmf = 0;
05563 }
05564 rpt_mutex_unlock(&myrpt->lock);
05565 usleep(MSWAIT * 1000);
05566 rpt_mutex_lock(&myrpt->lock);
05567 }
05568 if(debug)
05569 ast_log(LOG_NOTICE, "exit channel loop\n");
05570 rpt_mutex_unlock(&myrpt->lock);
05571 tone_zone_play_tone(genchannel->fds[0],-1);
05572 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05573 ast_hangup(genchannel);
05574 rpt_mutex_lock(&myrpt->lock);
05575 myrpt->callmode = 0;
05576 myrpt->macropatch=0;
05577 channel_revert(myrpt);
05578 rpt_mutex_unlock(&myrpt->lock);
05579
05580 ci.chan = 0;
05581 ci.confno = myrpt->conf;
05582 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05583 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05584
05585 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05586 {
05587 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05588 }
05589 pthread_exit(NULL);
05590 }
05591
05592 static void send_link_dtmf(struct rpt *myrpt,char c)
05593 {
05594 char str[300];
05595 struct ast_frame wf;
05596 struct rpt_link *l;
05597
05598 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05599 wf.frametype = AST_FRAME_TEXT;
05600 wf.subclass = 0;
05601 wf.offset = 0;
05602 wf.mallocd = 0;
05603 wf.datalen = strlen(str) + 1;
05604 wf.samples = 0;
05605 l = myrpt->links.next;
05606
05607 while(l != &myrpt->links)
05608 {
05609 if (l->name[0] == '0')
05610 {
05611 l = l->next;
05612 continue;
05613 }
05614
05615 if (!strcmp(l->name,myrpt->cmdnode))
05616 {
05617 wf.data.ptr = str;
05618 if (l->chan) ast_write(l->chan,&wf);
05619 return;
05620 }
05621 l = l->next;
05622 }
05623 l = myrpt->links.next;
05624
05625 while(l != &myrpt->links)
05626 {
05627 wf.data.ptr = str;
05628 if (l->chan) ast_write(l->chan,&wf);
05629 l = l->next;
05630 }
05631 return;
05632 }
05633
05634 static void send_link_keyquery(struct rpt *myrpt)
05635 {
05636 char str[300];
05637 struct ast_frame wf;
05638 struct rpt_link *l;
05639
05640 rpt_mutex_lock(&myrpt->lock);
05641 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05642 myrpt->topkeystate = 1;
05643 time(&myrpt->topkeytime);
05644 rpt_mutex_unlock(&myrpt->lock);
05645 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05646 wf.frametype = AST_FRAME_TEXT;
05647 wf.subclass = 0;
05648 wf.offset = 0;
05649 wf.mallocd = 0;
05650 wf.datalen = strlen(str) + 1;
05651 wf.samples = 0;
05652 l = myrpt->links.next;
05653
05654 while(l != &myrpt->links)
05655 {
05656 wf.data.ptr = str;
05657 if (l->chan) ast_write(l->chan,&wf);
05658 l = l->next;
05659 }
05660 return;
05661 }
05662
05663
05664
05665 static void send_newkey(struct ast_channel *chan)
05666 {
05667
05668
05669 ast_sendtext(chan,newkeystr);
05670 return;
05671 }
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05686 {
05687 char *val, *s, *s1, *s2, *tele;
05688 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05689 char tmp[300], deststr[300] = "",modechange = 0;
05690 char sx[320],*sy;
05691 struct rpt_link *l;
05692 int reconnects = 0;
05693 int i,n;
05694 struct dahdi_confinfo ci;
05695
05696 val = node_lookup(myrpt,node);
05697 if (!val){
05698 if(strlen(node) >= myrpt->longestnode)
05699 return -1;
05700 return 1;
05701 }
05702
05703 if(!strcmp(myrpt->name,node))
05704 return -2;
05705
05706 if(debug > 3){
05707 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05708 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05709 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05710 }
05711
05712 strncpy(tmp,val,sizeof(tmp) - 1);
05713 s = tmp;
05714 s1 = strsep(&s,",");
05715 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05716 {
05717 sy = strchr(s1,'/');
05718 *sy = 0;
05719 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05720 s1 = sx;
05721 }
05722 s2 = strsep(&s,",");
05723 rpt_mutex_lock(&myrpt->lock);
05724 l = myrpt->links.next;
05725
05726 while(l != &myrpt->links){
05727 if (l->name[0] == '0')
05728 {
05729 l = l->next;
05730 continue;
05731 }
05732
05733 if (!strcmp(l->name, node))
05734 break;
05735 l = l->next;
05736 }
05737
05738 if (l != &myrpt->links){
05739
05740 if ((l->mode) || (!l->chan)) {
05741 rpt_mutex_unlock(&myrpt->lock);
05742 return 2;
05743 }
05744 reconnects = l->reconnects;
05745 rpt_mutex_unlock(&myrpt->lock);
05746 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05747 l->retries = l->max_retries + 1;
05748 l->disced = 2;
05749 modechange = 1;
05750 } else
05751 {
05752 __mklinklist(myrpt,NULL,lstr);
05753 rpt_mutex_unlock(&myrpt->lock);
05754 n = finddelim(lstr,strs,MAXLINKLIST);
05755 for(i = 0; i < n; i++)
05756 {
05757 if ((*strs[i] < '0') ||
05758 (*strs[i] > '9')) strs[i]++;
05759 if (!strcmp(strs[i],node))
05760 {
05761 return 2;
05762 }
05763 }
05764 }
05765 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05766
05767 l = ast_malloc(sizeof(struct rpt_link));
05768 if (!l)
05769 {
05770 ast_log(LOG_WARNING, "Unable to malloc\n");
05771 return -1;
05772 }
05773
05774 memset((char *)l,0,sizeof(struct rpt_link));
05775 l->mode = mode;
05776 l->outbound = 1;
05777 l->thisconnected = 0;
05778 voxinit_link(l,1);
05779 strncpy(l->name, node, MAXNODESTR - 1);
05780 l->isremote = (s && ast_true(s));
05781 if (modechange) l->connected = 1;
05782 l->hasconnected = l->perma = perma;
05783 #ifdef ALLOW_LOCAL_CHANNELS
05784 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05785 strncpy(deststr, s1, sizeof(deststr));
05786 else
05787 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05788 #else
05789 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05790 #endif
05791 tele = strchr(deststr, '/');
05792 if (!tele){
05793 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05794 ast_free(l);
05795 return -1;
05796 }
05797 *tele++ = 0;
05798 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
05799 if (l->chan){
05800 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05801 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05802 #ifdef AST_CDR_FLAG_POST_DISABLED
05803 if (l->chan->cdr)
05804 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05805 #endif
05806 #ifndef NEW_ASTERISK
05807 l->chan->whentohangup = 0;
05808 #endif
05809 l->chan->appl = "Apprpt";
05810 l->chan->data = "(Remote Rx)";
05811 if (debug > 3)
05812 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05813 deststr, tele, l->chan->name);
05814 if(l->chan->cid.cid_num)
05815 ast_free(l->chan->cid.cid_num);
05816 l->chan->cid.cid_num = ast_strdup(myrpt->name);
05817 ast_call(l->chan,tele,999);
05818 }
05819 else {
05820 if(debug > 3)
05821 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05822 deststr,tele,l->chan->name);
05823 if (myrpt->p.archivedir)
05824 {
05825 char str[100];
05826 sprintf(str,"LINKFAIL,%s",l->name);
05827 donodelog(myrpt,str);
05828 }
05829 ast_free(l);
05830 return -1;
05831 }
05832
05833 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05834 if (!l->pchan){
05835 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05836 ast_hangup(l->chan);
05837 ast_free(l);
05838 return -1;
05839 }
05840 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05841 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05842 #ifdef AST_CDR_FLAG_POST_DISABLED
05843 if (l->pchan->cdr)
05844 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05845 #endif
05846
05847 ci.chan = 0;
05848 ci.confno = myrpt->conf;
05849 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05850
05851 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05852 {
05853 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05854 ast_hangup(l->chan);
05855 ast_hangup(l->pchan);
05856 ast_free(l);
05857 return -1;
05858 }
05859 rpt_mutex_lock(&myrpt->lock);
05860 l->reconnects = reconnects;
05861
05862 l->max_retries = MAX_RETRIES;
05863 if (perma)
05864 l->max_retries = MAX_RETRIES_PERM;
05865 if (l->isremote) l->retries = l->max_retries + 1;
05866 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05867 __kickshort(myrpt);
05868 rpt_mutex_unlock(&myrpt->lock);
05869 if (!l->phonemode) send_newkey(l->chan);
05870 return 0;
05871 }
05872
05873
05874
05875
05876
05877
05878
05879 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05880 {
05881
05882 char *val, *s, *s1, *s2;
05883 char tmp[300];
05884 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05885 char mode,perma;
05886 char sx[320],*sy;
05887 struct rpt_link *l;
05888 int i,r;
05889
05890 if(!param)
05891 return DC_ERROR;
05892
05893
05894 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05895 return DC_ERROR;
05896
05897 strncpy(digitbuf,digits,MAXNODESTR - 1);
05898
05899 if(debug > 6)
05900 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05901
05902 switch(myatoi(param)){
05903 case 11:
05904 case 1:
05905 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05906 strcpy(digitbuf,myrpt->lastlinknode);
05907 val = node_lookup(myrpt,digitbuf);
05908 if (!val){
05909 if(strlen(digitbuf) >= myrpt->longestnode)
05910 return DC_ERROR;
05911 break;
05912 }
05913 strncpy(tmp,val,sizeof(tmp) - 1);
05914 s = tmp;
05915 s1 = strsep(&s,",");
05916 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05917 {
05918 sy = strchr(s1,'/');
05919 *sy = 0;
05920 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05921 s1 = sx;
05922 }
05923 s2 = strsep(&s,",");
05924 rpt_mutex_lock(&myrpt->lock);
05925 l = myrpt->links.next;
05926
05927 while(l != &myrpt->links){
05928 if (l->name[0] == '0')
05929 {
05930 l = l->next;
05931 continue;
05932 }
05933
05934 if (!strcmp(l->name, digitbuf))
05935 break;
05936 l = l->next;
05937 }
05938 if (l != &myrpt->links){
05939 struct ast_frame wf;
05940
05941
05942 if ((myatoi(param) < 10) &&
05943 (l->max_retries > MAX_RETRIES))
05944 {
05945 rpt_mutex_unlock(&myrpt->lock);
05946 return DC_COMPLETE;
05947 }
05948 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05949 l->retries = l->max_retries + 1;
05950 l->disced = 1;
05951 rpt_mutex_unlock(&myrpt->lock);
05952 wf.frametype = AST_FRAME_TEXT;
05953 wf.subclass = 0;
05954 wf.offset = 0;
05955 wf.mallocd = 0;
05956 wf.datalen = strlen(discstr) + 1;
05957 wf.samples = 0;
05958 wf.data.ptr = discstr;
05959 if (l->chan)
05960 {
05961 ast_write(l->chan,&wf);
05962 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05963 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05964 }
05965 rpt_telemetry(myrpt, COMPLETE, NULL);
05966 return DC_COMPLETE;
05967 }
05968 rpt_mutex_unlock(&myrpt->lock);
05969 return DC_COMPLETE;
05970 case 2:
05971 case 3:
05972 case 12:
05973 case 13:
05974 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05975 strcpy(digitbuf,myrpt->lastlinknode);
05976
05977 perma = (atoi(param) > 10) ? 1 : 0;
05978 mode = (atoi(param) & 1) ? 1 : 0;
05979 r = connect_link(myrpt, digitbuf, mode, perma);
05980 switch(r){
05981 case -2:
05982 return DC_COMPLETE;
05983
05984 case 0:
05985 rpt_telemetry(myrpt, COMPLETE, NULL);
05986 return DC_COMPLETE;
05987
05988 case 1:
05989 break;
05990
05991 case 2:
05992 rpt_telemetry(myrpt, REMALREADY, NULL);
05993 return DC_COMPLETE;
05994
05995 default:
05996 rpt_telemetry(myrpt, CONNFAIL, NULL);
05997 return DC_COMPLETE;
05998 }
05999 break;
06000
06001 case 4:
06002
06003
06004 if (((command_source != SOURCE_RPT) &&
06005 (command_source != SOURCE_PHONE) &&
06006 (command_source != SOURCE_ALT) &&
06007 (command_source != SOURCE_DPHONE)) ||
06008 (myrpt->links.next == &myrpt->links))
06009 return DC_COMPLETE;
06010
06011
06012 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06013
06014 rpt_telemetry(myrpt, REMALREADY, NULL);
06015 return DC_COMPLETE;
06016 }
06017 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06018 strcpy(digitbuf,myrpt->lastlinknode);
06019
06020 val = node_lookup(myrpt,digitbuf);
06021 if (!val){
06022 if(strlen(digitbuf) >= myrpt->longestnode)
06023 return DC_ERROR;
06024 break;
06025
06026 }
06027 rpt_mutex_lock(&myrpt->lock);
06028 strcpy(myrpt->lastlinknode,digitbuf);
06029 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06030 rpt_mutex_unlock(&myrpt->lock);
06031 rpt_telemetry(myrpt, REMGO, NULL);
06032 return DC_COMPLETE;
06033
06034 case 5:
06035 rpt_telemetry(myrpt, STATUS, NULL);
06036 return DC_COMPLETE;
06037
06038 case 15:
06039 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06040 return DC_COMPLETE;
06041
06042
06043 case 6:
06044 rpt_mutex_lock(&myrpt->lock);
06045 myrpt->savednodes[0] = 0;
06046 l = myrpt->links.next;
06047
06048 while(l != &myrpt->links){
06049 struct ast_frame wf;
06050 if (l->name[0] == '0')
06051 {
06052 l = l->next;
06053 continue;
06054 }
06055
06056 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06057 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06058 if(myrpt->savednodes[0])
06059 strcat(myrpt->savednodes, ",");
06060 strcat(myrpt->savednodes, tmp);
06061 }
06062 l->retries = l->max_retries + 1;
06063 l->disced = 2;
06064 rpt_mutex_unlock(&myrpt->lock);
06065
06066
06067 wf.frametype = AST_FRAME_TEXT;
06068 wf.subclass = 0;
06069 wf.offset = 0;
06070 wf.mallocd = 0;
06071 wf.datalen = strlen(discstr) + 1;
06072 wf.samples = 0;
06073 wf.data.ptr = discstr;
06074 if (l->chan)
06075 {
06076 ast_write(l->chan,&wf);
06077 ast_safe_sleep(l->chan,250);
06078 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06079 }
06080 rpt_mutex_lock(&myrpt->lock);
06081 l = l->next;
06082 }
06083 rpt_mutex_unlock(&myrpt->lock);
06084 if(debug > 3)
06085 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06086 rpt_telemetry(myrpt, COMPLETE, NULL);
06087 return DC_COMPLETE;
06088
06089 case 7:
06090 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06091 break;
06092
06093
06094 #ifdef _MDC_DECODE_H_
06095 case 8:
06096 myrpt->lastunit = 0xd00d;
06097 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06098 mdc1200_send(myrpt,myrpt->lastunit);
06099 break;
06100 #endif
06101
06102 case 16:
06103 strcpy(tmp, myrpt->savednodes);
06104 finddelim(tmp, strs, MAXLINKLIST);
06105 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06106 s1 = strs[i];
06107 mode = (s1[0] == 'X') ? 1 : 0;
06108 perma = (s1[1] == 'P') ? 1 : 0;
06109 connect_link(myrpt, s1 + 2, mode, perma);
06110 }
06111 rpt_telemetry(myrpt, COMPLETE, NULL);
06112 break;
06113
06114 case 200:
06115 case 201:
06116 case 202:
06117 case 203:
06118 case 204:
06119 case 205:
06120 case 206:
06121 case 207:
06122 case 208:
06123 case 209:
06124 case 210:
06125 case 211:
06126 case 212:
06127 case 213:
06128 case 214:
06129 case 215:
06130 if (((myrpt->p.propagate_dtmf) &&
06131 (command_source == SOURCE_LNK)) ||
06132 ((myrpt->p.propagate_phonedtmf) &&
06133 ((command_source == SOURCE_PHONE) ||
06134 (command_source == SOURCE_ALT) ||
06135 (command_source == SOURCE_DPHONE))))
06136 do_dtmf_local(myrpt,
06137 remdtmfstr[myatoi(param) - 200]);
06138 default:
06139 return DC_ERROR;
06140
06141 }
06142
06143 return DC_INDETERMINATE;
06144 }
06145
06146
06147
06148
06149
06150 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06151 {
06152 pthread_attr_t attr;
06153 int i, idx, paramlength;
06154 char *lparam;
06155 char *value = NULL;
06156 char *paramlist[20];
06157
06158 static char *keywords[] = {
06159 "context",
06160 "dialtime",
06161 "farenddisconnect",
06162 "noct",
06163 "quiet",
06164 NULL
06165 };
06166
06167 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06168 return DC_ERROR;
06169
06170 if(debug)
06171 printf("@@@@ Autopatch up\n");
06172
06173 if(!myrpt->callmode){
06174
06175 myrpt->patchnoct = 0;
06176 myrpt->patchdialtime = 0;
06177 myrpt->patchfarenddisconnect = 0;
06178 myrpt->patchquiet = 0;
06179 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06180
06181 if(param){
06182
06183 lparam = ast_strdup(param);
06184 if(!lparam){
06185 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06186 return DC_ERROR;
06187 }
06188 paramlength = finddelim(lparam, paramlist, 20);
06189 for(i = 0; i < paramlength; i++){
06190 idx = matchkeyword(paramlist[i], &value, keywords);
06191 if(value)
06192 value = skipchars(value, "= ");
06193 switch(idx){
06194
06195 case 1:
06196 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06197 break;
06198
06199 case 2:
06200 myrpt->patchdialtime = atoi(value);
06201 break;
06202
06203 case 3:
06204 myrpt->patchfarenddisconnect = atoi(value);
06205 break;
06206
06207 case 4:
06208 myrpt->patchnoct = atoi(value);
06209 break;
06210
06211 case 5:
06212 myrpt->patchquiet = atoi(value);
06213 break;
06214
06215 default:
06216 break;
06217 }
06218 }
06219 ast_free(lparam);
06220 }
06221 }
06222
06223 rpt_mutex_lock(&myrpt->lock);
06224
06225
06226
06227 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06228 myrpt->mydtmf = myrpt->p.endchar;
06229 }
06230 if (myrpt->callmode){
06231 rpt_mutex_unlock(&myrpt->lock);
06232 return DC_COMPLETE;
06233 }
06234 myrpt->callmode = 1;
06235 myrpt->cidx = 0;
06236 myrpt->exten[myrpt->cidx] = 0;
06237 rpt_mutex_unlock(&myrpt->lock);
06238 pthread_attr_init(&attr);
06239 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06240 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06241 return DC_COMPLETE;
06242 }
06243
06244
06245
06246
06247
06248 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06249 {
06250 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06251 return DC_ERROR;
06252
06253 if(debug)
06254 printf("@@@@ Autopatch down\n");
06255
06256 rpt_mutex_lock(&myrpt->lock);
06257
06258 myrpt->macropatch=0;
06259
06260 if (!myrpt->callmode){
06261 rpt_mutex_unlock(&myrpt->lock);
06262 return DC_COMPLETE;
06263 }
06264
06265 myrpt->callmode = 0;
06266 channel_revert(myrpt);
06267 rpt_mutex_unlock(&myrpt->lock);
06268 rpt_telemetry(myrpt, TERM, NULL);
06269 return DC_COMPLETE;
06270 }
06271
06272
06273
06274
06275
06276 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06277 {
06278
06279 if (!param)
06280 return DC_ERROR;
06281
06282 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06283 return DC_ERROR;
06284
06285 if(debug)
06286 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06287
06288 switch(myatoi(param)){
06289 case 1:
06290 rpt_telemetry(myrpt, ID1, NULL);
06291 return DC_COMPLETE;
06292 case 2:
06293 rpt_telemetry(myrpt, STATS_TIME, NULL);
06294 return DC_COMPLETE;
06295 case 3:
06296 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06297 return DC_COMPLETE;
06298 case 11:
06299 rpt_telemetry(myrpt, ID , NULL);
06300 return DC_COMPLETE;
06301 case 12:
06302 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06303 return DC_COMPLETE;
06304 default:
06305 return DC_ERROR;
06306 }
06307 return DC_INDETERMINATE;
06308 }
06309
06310
06311
06312 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06313 {
06314 char *val;
06315 int i;
06316 if (myrpt->remote)
06317 return DC_ERROR;
06318
06319 if(debug)
06320 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06321
06322 if(strlen(digitbuf) < 1)
06323 return DC_INDETERMINATE;
06324
06325 for(i = 0 ; i < digitbuf[i] ; i++) {
06326 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06327 return DC_ERROR;
06328 }
06329
06330 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06331 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06332
06333 if (!val){
06334 if (strlen(digitbuf) < myrpt->macro_longest)
06335 return DC_INDETERMINATE;
06336 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06337 return DC_COMPLETE;
06338 }
06339 rpt_mutex_lock(&myrpt->lock);
06340 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06341 {
06342 rpt_mutex_unlock(&myrpt->lock);
06343 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06344 return DC_ERROR;
06345 }
06346 myrpt->macrotimer = MACROTIME;
06347 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06348 rpt_mutex_unlock(&myrpt->lock);
06349 return DC_COMPLETE;
06350 }
06351
06352
06353
06354
06355
06356 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06357 {
06358
06359 if (myrpt->remote)
06360 return DC_ERROR;
06361
06362 if(debug)
06363 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06364
06365 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06366 return DC_ERROR;
06367
06368 rpt_telemetry(myrpt,PLAYBACK,param);
06369 return DC_COMPLETE;
06370 }
06371
06372
06373
06374
06375
06376 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06377 {
06378 char string[16];
06379 int res;
06380
06381 int i, r;
06382
06383 if(!param)
06384 return DC_ERROR;
06385
06386 switch(myatoi(param)){
06387 case 1:
06388 res = system("killall -9 asterisk");
06389 return DC_COMPLETE;
06390
06391 case 2:
06392 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06393 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06394 return DC_COMPLETE;
06395
06396 case 3:
06397 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06398 return DC_COMPLETE;
06399
06400 case 4:
06401 if (myrpt->stopgen < 0)
06402 {
06403 myrpt->stopgen = 1;
06404 }
06405 else
06406 {
06407 myrpt->stopgen = 0;
06408 rpt_telemetry(myrpt, TEST_TONE, NULL);
06409 }
06410 return DC_COMPLETE;
06411
06412 case 5:
06413 myrpt->disgorgetime = time(NULL) + 10;
06414 return DC_COMPLETE;
06415
06416 case 6:
06417 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06418 return DC_DOKEY;
06419
06420
06421 case 7:
06422 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06423 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06424 return DC_COMPLETE;
06425
06426 case 8:
06427 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06428 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06429 return DC_COMPLETE;
06430
06431 case 9:
06432 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06433 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06434 return DC_COMPLETE;
06435
06436 case 10:
06437 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06438 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06439 return DC_COMPLETE;
06440
06441 case 11:
06442 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06443 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06444 return DC_COMPLETE;
06445
06446 case 12:
06447 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06448 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06449 return DC_COMPLETE;
06450
06451 case 13:
06452 string[0] = string[1] = 'S';
06453 string[2] = myrpt->p.sysstate_cur + '0';
06454 string[3] = '\0';
06455 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06456 return DC_COMPLETE;
06457
06458 case 14:
06459 if(strlen(digitbuf) == 0)
06460 break;
06461 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06462 return DC_ERROR;
06463 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06464 string[0] = string[1] = 'S';
06465 string[2] = myrpt->p.sysstate_cur + '0';
06466 string[3] = '\0';
06467 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06468 return DC_COMPLETE;
06469
06470 case 15:
06471 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06472 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06473 return DC_COMPLETE;
06474
06475 case 16:
06476 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06477 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06478 return DC_COMPLETE;
06479
06480 case 17:
06481 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06482 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06483 return DC_COMPLETE;
06484
06485 case 18:
06486 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06487 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06488 return DC_COMPLETE;
06489
06490 case 19:
06491 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06492 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06493 return DC_COMPLETE;
06494
06495 case 20:
06496 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06497 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06498 return DC_COMPLETE;
06499
06500 case 21:
06501 birdbath(myrpt);
06502 if (myrpt->p.parrotmode < 2)
06503 {
06504 myrpt->p.parrotmode = 0;
06505 rpt_telemetry(myrpt,COMPLETE,NULL);
06506 return DC_COMPLETE;
06507 }
06508 break;
06509
06510 case 22:
06511 birdbath(myrpt);
06512 if (myrpt->p.parrotmode < 2)
06513 {
06514 myrpt->p.parrotmode = 1;
06515 rpt_telemetry(myrpt,COMPLETE,NULL);
06516 return DC_COMPLETE;
06517 }
06518 break;
06519 case 23:
06520 birdbath(myrpt);
06521 rpt_telemetry(myrpt,COMPLETE,NULL);
06522 return DC_COMPLETE;
06523 case 24:
06524 flush_telem(myrpt);
06525 rpt_telemetry(myrpt,COMPLETE,NULL);
06526 return DC_COMPLETE;
06527 case 25:
06528 send_link_keyquery(myrpt);
06529 myrpt->topkeylong = 0;
06530 rpt_telemetry(myrpt,COMPLETE,NULL);
06531 return DC_COMPLETE;
06532 case 26:
06533 send_link_keyquery(myrpt);
06534 myrpt->topkeylong = 1;
06535 rpt_telemetry(myrpt,COMPLETE,NULL);
06536 return DC_COMPLETE;
06537
06538 case 30:
06539
06540 if(strlen(digitbuf) < 2)
06541 break;
06542
06543 for(i = 0 ; i < 2 ; i++){
06544 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06545 return DC_ERROR;
06546 }
06547
06548 r = retreive_memory(myrpt, digitbuf);
06549 if (r < 0){
06550 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06551 return DC_COMPLETE;
06552 }
06553 if (r > 0){
06554 return DC_ERROR;
06555 }
06556 if (setrem(myrpt) == -1) return DC_ERROR;
06557 return DC_COMPLETE;
06558
06559 case 31:
06560
06561
06562 if(strlen(digitbuf) < 2)
06563 break;
06564
06565 for(i = 0 ; i < 2 ; i++){
06566 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06567 return DC_ERROR;
06568 }
06569 channel_steer(myrpt,digitbuf);
06570 return DC_COMPLETE;
06571
06572 case 32:
06573 i = strlen(digitbuf);
06574 if(!i){
06575 if(debug > 3)
06576 ast_log(LOG_NOTICE,"Padtest entered");
06577 myrpt->inpadtest = 1;
06578 }
06579 else{
06580 if(debug > 3)
06581 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06582 if(digitbuf[i-1] != myrpt->p.endchar)
06583 break;
06584 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06585 myrpt->inpadtest = 0;
06586 if(debug > 3)
06587 ast_log(LOG_NOTICE,"Padtest exited");
06588 return DC_COMPLETE;
06589 }
06590 }
06591 return DC_INDETERMINATE;
06592 }
06593
06594
06595
06596 static int collect_function_digits(struct rpt *myrpt, char *digits,
06597 int command_source, struct rpt_link *mylink)
06598 {
06599 int i,rv;
06600 char *stringp,*action,*param,*functiondigits;
06601 char function_table_name[30] = "";
06602 char workstring[200];
06603
06604 struct ast_variable *vp;
06605
06606 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06607
06608
06609
06610
06611 if (command_source == SOURCE_DPHONE) {
06612 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06613 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06614 }
06615 else if (command_source == SOURCE_ALT) {
06616 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06617 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06618 }
06619 else if (command_source == SOURCE_PHONE) {
06620 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06621 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06622 }
06623 else if (command_source == SOURCE_LNK)
06624 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06625 else
06626 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06627
06628 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06629 while(vp) {
06630 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06631 break;
06632 vp = vp->next;
06633 }
06634
06635 if(!vp) {
06636 int n;
06637
06638 n = myrpt->longestfunc;
06639 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06640 else
06641 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06642 else
06643 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06644 else
06645 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06646
06647 if(strlen(digits) >= n)
06648 return DC_ERROR;
06649 else
06650 return DC_INDETERMINATE;
06651 }
06652
06653 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06654 stringp = workstring;
06655 action = strsep(&stringp, ",");
06656 param = stringp;
06657 if(debug)
06658 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06659
06660 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06661 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06662 break;
06663 }
06664 if(debug)
06665 printf("@@@@ table index i = %d\n",i);
06666 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06667
06668 return DC_ERROR;
06669 }
06670 if(function_table[i].function == NULL){
06671
06672 if(debug)
06673 printf("@@@@ NULL for action: %s\n",action);
06674 return DC_ERROR;
06675 }
06676 functiondigits = digits + strlen(vp->name);
06677 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06678 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06679 return(rv);
06680 }
06681
06682
06683 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06684 char *str)
06685 {
06686 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06687 int i,seq, res, ts;
06688 struct rpt_link *l;
06689 struct ast_frame wf;
06690
06691 wf.frametype = AST_FRAME_TEXT;
06692 wf.subclass = 0;
06693 wf.offset = 0;
06694 wf.mallocd = 0;
06695 wf.datalen = strlen(str) + 1;
06696 wf.samples = 0;
06697
06698 strncpy(tmp,str,sizeof(tmp) - 1);
06699
06700 if (!strcmp(tmp,discstr))
06701 {
06702 mylink->disced = 1;
06703 mylink->retries = mylink->max_retries + 1;
06704 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06705 return;
06706 }
06707 if (!strcmp(tmp,newkeystr))
06708 {
06709 mylink->newkey = 1;
06710 return;
06711 }
06712 if (tmp[0] == 'L')
06713 {
06714 rpt_mutex_lock(&myrpt->lock);
06715 strcpy(mylink->linklist,tmp + 2);
06716 time(&mylink->linklistreceived);
06717 rpt_mutex_unlock(&myrpt->lock);
06718 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s recieved node list %s from node %s\n",
06719 myrpt->name,tmp,mylink->name);
06720 return;
06721 }
06722 if (tmp[0] == 'K')
06723 {
06724 if (sscanf(tmp,"%s %s %s %d %d",cmd,dest,src,&seq,&ts) != 5)
06725 {
06726 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06727 return;
06728 }
06729 if (dest[0] == '0')
06730 {
06731 strcpy(dest,myrpt->name);
06732 }
06733
06734 if (strcmp(dest,myrpt->name))
06735 {
06736 l = myrpt->links.next;
06737
06738 while(l != &myrpt->links)
06739 {
06740 if (l->name[0] == '0')
06741 {
06742 l = l->next;
06743 continue;
06744 }
06745
06746 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06747 {
06748 l = l->next;
06749 continue;
06750 }
06751
06752 if (!strcmp(l->name,dest))
06753 {
06754
06755 if (strcmp(l->name,src)) {
06756 wf.data.ptr = str;
06757 if (l->chan) ast_write(l->chan,&wf);
06758 }
06759 return;
06760 }
06761 l = l->next;
06762 }
06763 }
06764
06765 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06766 {
06767 l = myrpt->links.next;
06768
06769 while(l != &myrpt->links)
06770 {
06771 if (l->name[0] == '0')
06772 {
06773 l = l->next;
06774 continue;
06775 }
06776
06777 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06778 {
06779 l = l->next;
06780 continue;
06781 }
06782
06783 if (strcmp(l->name,src)) {
06784 wf.data.ptr = str;
06785 if (l->chan) ast_write(l->chan,&wf);
06786 }
06787 l = l->next;
06788 }
06789 }
06790
06791 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06792 if (cmd[1] == '?')
06793 {
06794 time_t now;
06795 int n = 0;
06796
06797 time(&now);
06798 if (myrpt->lastkeyedtime)
06799 {
06800 n = (int)(now - myrpt->lastkeyedtime);
06801 }
06802 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06803 wf.data.ptr = tmp1;
06804 wf.datalen = strlen(tmp1) + 1;
06805 if (mylink->chan) ast_write(mylink->chan,&wf);
06806 return;
06807 }
06808 if (myrpt->topkeystate != 1) return;
06809 rpt_mutex_lock(&myrpt->lock);
06810 for(i = 0; i < TOPKEYN; i++)
06811 {
06812 if (!strcmp(myrpt->topkey[i].node,src)) break;
06813 }
06814 if (i >= TOPKEYN)
06815 {
06816 for(i = 0; i < TOPKEYN; i++)
06817 {
06818 if (!myrpt->topkey[i].node[0]) break;
06819 }
06820 }
06821 if (i < TOPKEYN)
06822 {
06823 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06824 myrpt->topkey[i].timesince = ts;
06825 myrpt->topkey[i].keyed = seq;
06826 }
06827 rpt_mutex_unlock(&myrpt->lock);
06828 return;
06829 }
06830 if (tmp[0] == 'I')
06831 {
06832 if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
06833 {
06834 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06835 return;
06836 }
06837 mdc1200_notify(myrpt,src,seq);
06838 strcpy(dest,"*");
06839 }
06840 else
06841 {
06842 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
06843 {
06844 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06845 return;
06846 }
06847 if (strcmp(cmd,"D"))
06848 {
06849 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06850 return;
06851 }
06852 }
06853 if (dest[0] == '0')
06854 {
06855 strcpy(dest,myrpt->name);
06856 }
06857
06858
06859 if (strcmp(dest,myrpt->name))
06860 {
06861 l = myrpt->links.next;
06862
06863 while(l != &myrpt->links)
06864 {
06865 if (l->name[0] == '0')
06866 {
06867 l = l->next;
06868 continue;
06869 }
06870
06871 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06872 {
06873 l = l->next;
06874 continue;
06875 }
06876
06877 if (!strcmp(l->name,dest))
06878 {
06879
06880 if (strcmp(l->name,src)) {
06881 wf.data.ptr = str;
06882 if (l->chan) ast_write(l->chan,&wf);
06883 }
06884 return;
06885 }
06886 l = l->next;
06887 }
06888 l = myrpt->links.next;
06889
06890 while(l != &myrpt->links)
06891 {
06892 if (l->name[0] == '0')
06893 {
06894 l = l->next;
06895 continue;
06896 }
06897
06898 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06899 {
06900 l = l->next;
06901 continue;
06902 }
06903
06904 if (strcmp(l->name,src)) {
06905 wf.data.ptr = str;
06906 if (l->chan) ast_write(l->chan,&wf);
06907 }
06908 l = l->next;
06909 }
06910 return;
06911 }
06912 if (myrpt->p.archivedir)
06913 {
06914 char dtmfstr[100];
06915
06916 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06917 donodelog(myrpt,dtmfstr);
06918 }
06919 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06920 if (!c) return;
06921 rpt_mutex_lock(&myrpt->lock);
06922 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06923 if (myrpt->callmode == 1)
06924 {
06925 myrpt->exten[myrpt->cidx++] = c;
06926 myrpt->exten[myrpt->cidx] = 0;
06927
06928 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06929 {
06930
06931 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06932 myrpt->exten,1,NULL))
06933 {
06934 myrpt->callmode = 2;
06935 if(!myrpt->patchquiet)
06936 {
06937 rpt_mutex_unlock(&myrpt->lock);
06938 rpt_telemetry(myrpt,PROC,NULL);
06939 rpt_mutex_lock(&myrpt->lock);
06940 }
06941 }
06942 else
06943 {
06944 myrpt->calldigittimer = 1;
06945 }
06946 }
06947
06948 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06949 {
06950
06951 myrpt->callmode = 4;
06952 }
06953 }
06954 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06955 {
06956 myrpt->rem_dtmfidx = 0;
06957 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06958 time(&myrpt->rem_dtmf_time);
06959 rpt_mutex_unlock(&myrpt->lock);
06960 return;
06961 }
06962 else if (myrpt->rem_dtmfidx < 0)
06963 {
06964 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06965 {
06966 myrpt->mydtmf = c;
06967 }
06968 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06969 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06970 rpt_mutex_unlock(&myrpt->lock);
06971 return;
06972 }
06973 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06974 {
06975 time(&myrpt->rem_dtmf_time);
06976 if (myrpt->rem_dtmfidx < MAXDTMF)
06977 {
06978 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06979 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06980
06981 rpt_mutex_unlock(&myrpt->lock);
06982 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06983 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06984 rpt_mutex_lock(&myrpt->lock);
06985
06986 switch(res){
06987
06988 case DC_INDETERMINATE:
06989 break;
06990
06991 case DC_REQ_FLUSH:
06992 myrpt->rem_dtmfidx = 0;
06993 myrpt->rem_dtmfbuf[0] = 0;
06994 break;
06995
06996
06997 case DC_COMPLETE:
06998 case DC_COMPLETEQUIET:
06999 myrpt->totalexecdcommands++;
07000 myrpt->dailyexecdcommands++;
07001 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07002 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07003 myrpt->rem_dtmfbuf[0] = 0;
07004 myrpt->rem_dtmfidx = -1;
07005 myrpt->rem_dtmf_time = 0;
07006 break;
07007
07008 case DC_ERROR:
07009 default:
07010 myrpt->rem_dtmfbuf[0] = 0;
07011 myrpt->rem_dtmfidx = -1;
07012 myrpt->rem_dtmf_time = 0;
07013 break;
07014 }
07015 }
07016
07017 }
07018 rpt_mutex_unlock(&myrpt->lock);
07019 return;
07020 }
07021
07022 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07023 char c)
07024 {
07025
07026 char cmd[300];
07027 int res;
07028
07029 if (myrpt->p.archivedir)
07030 {
07031 char str[100];
07032
07033 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07034 donodelog(myrpt,str);
07035 }
07036 rpt_mutex_lock(&myrpt->lock);
07037
07038 if (mylink->phonemode == 3)
07039 {
07040 if(c == myrpt->p.endchar)
07041 {
07042 mylink->lastrealrx = 0;
07043 rpt_mutex_unlock(&myrpt->lock);
07044 return;
07045 }
07046
07047 if(c == myrpt->p.funcchar)
07048 {
07049 mylink->lastrealrx = !mylink->lastrealrx;
07050 rpt_mutex_unlock(&myrpt->lock);
07051 return;
07052 }
07053 }
07054 else
07055 {
07056 if (c == myrpt->p.endchar)
07057 {
07058 if (mylink->lastrx)
07059 {
07060 mylink->lastrealrx = 0;
07061 rpt_mutex_unlock(&myrpt->lock);
07062 return;
07063 }
07064 myrpt->stopgen = 1;
07065 if (myrpt->cmdnode[0])
07066 {
07067 myrpt->cmdnode[0] = 0;
07068 myrpt->dtmfidx = -1;
07069 myrpt->dtmfbuf[0] = 0;
07070 rpt_mutex_unlock(&myrpt->lock);
07071 rpt_telemetry(myrpt,COMPLETE,NULL);
07072 return;
07073 }
07074 }
07075 }
07076 if (myrpt->cmdnode[0])
07077 {
07078 rpt_mutex_unlock(&myrpt->lock);
07079 send_link_dtmf(myrpt,c);
07080 return;
07081 }
07082 if (myrpt->callmode == 1)
07083 {
07084 myrpt->exten[myrpt->cidx++] = c;
07085 myrpt->exten[myrpt->cidx] = 0;
07086
07087 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07088 {
07089
07090 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07091 myrpt->exten,1,NULL))
07092 {
07093 myrpt->callmode = 2;
07094 if(!myrpt->patchquiet)
07095 {
07096 rpt_mutex_unlock(&myrpt->lock);
07097 rpt_telemetry(myrpt,PROC,NULL);
07098 rpt_mutex_lock(&myrpt->lock);
07099 }
07100 }
07101 else
07102 {
07103 myrpt->calldigittimer = 1;
07104 }
07105 }
07106
07107 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07108 {
07109
07110 myrpt->callmode = 4;
07111 }
07112 }
07113 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07114 {
07115 myrpt->mydtmf = c;
07116 }
07117 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07118 {
07119 myrpt->rem_dtmfidx = 0;
07120 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07121 time(&myrpt->rem_dtmf_time);
07122 rpt_mutex_unlock(&myrpt->lock);
07123 return;
07124 }
07125 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07126 {
07127 time(&myrpt->rem_dtmf_time);
07128 if (myrpt->rem_dtmfidx < MAXDTMF)
07129 {
07130 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07131 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07132
07133 rpt_mutex_unlock(&myrpt->lock);
07134 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07135 switch(mylink->phonemode)
07136 {
07137 case 1:
07138 res = collect_function_digits(myrpt, cmd,
07139 SOURCE_PHONE, mylink);
07140 break;
07141 case 2:
07142 res = collect_function_digits(myrpt, cmd,
07143 SOURCE_DPHONE,mylink);
07144 break;
07145 case 4:
07146 res = collect_function_digits(myrpt, cmd,
07147 SOURCE_ALT,mylink);
07148 break;
07149 default:
07150 res = collect_function_digits(myrpt, cmd,
07151 SOURCE_LNK, mylink);
07152 break;
07153 }
07154
07155 rpt_mutex_lock(&myrpt->lock);
07156
07157 switch(res){
07158
07159 case DC_INDETERMINATE:
07160 break;
07161
07162 case DC_DOKEY:
07163 mylink->lastrealrx = 1;
07164 break;
07165
07166 case DC_REQ_FLUSH:
07167 myrpt->rem_dtmfidx = 0;
07168 myrpt->rem_dtmfbuf[0] = 0;
07169 break;
07170
07171
07172 case DC_COMPLETE:
07173 case DC_COMPLETEQUIET:
07174 myrpt->totalexecdcommands++;
07175 myrpt->dailyexecdcommands++;
07176 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07177 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07178 myrpt->rem_dtmfbuf[0] = 0;
07179 myrpt->rem_dtmfidx = -1;
07180 myrpt->rem_dtmf_time = 0;
07181 break;
07182
07183 case DC_ERROR:
07184 default:
07185 myrpt->rem_dtmfbuf[0] = 0;
07186 myrpt->rem_dtmfidx = -1;
07187 myrpt->rem_dtmf_time = 0;
07188 break;
07189 }
07190 }
07191
07192 }
07193 rpt_mutex_unlock(&myrpt->lock);
07194 return;
07195 }
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226
07227
07228 static int rbi_mhztoband(char *str)
07229 {
07230 int i;
07231
07232 i = atoi(str) / 10;
07233 switch(i)
07234 {
07235 case 2:
07236 return 10;
07237 case 5:
07238 return 11;
07239 case 14:
07240 return 2;
07241 case 22:
07242 return 3;
07243 case 44:
07244 return 4;
07245 case 124:
07246 return 0;
07247 case 125:
07248 return 1;
07249 case 126:
07250 return 8;
07251 case 127:
07252 return 5;
07253 case 128:
07254 return 6;
07255 case 129:
07256 return 7;
07257 default:
07258 break;
07259 }
07260 return -1;
07261 }
07262
07263
07264 static int rbi_pltocode(char *str)
07265 {
07266 int i;
07267 char *s;
07268
07269 s = strchr(str,'.');
07270 i = 0;
07271 if (s) i = atoi(s + 1);
07272 i += atoi(str) * 10;
07273 switch(i)
07274 {
07275 case 670:
07276 return 0;
07277 case 719:
07278 return 1;
07279 case 744:
07280 return 2;
07281 case 770:
07282 return 3;
07283 case 797:
07284 return 4;
07285 case 825:
07286 return 5;
07287 case 854:
07288 return 6;
07289 case 885:
07290 return 7;
07291 case 915:
07292 return 8;
07293 case 948:
07294 return 9;
07295 case 974:
07296 return 10;
07297 case 1000:
07298 return 11;
07299 case 1035:
07300 return 12;
07301 case 1072:
07302 return 13;
07303 case 1109:
07304 return 14;
07305 case 1148:
07306 return 15;
07307 case 1188:
07308 return 16;
07309 case 1230:
07310 return 17;
07311 case 1273:
07312 return 18;
07313 case 1318:
07314 return 19;
07315 case 1365:
07316 return 20;
07317 case 1413:
07318 return 21;
07319 case 1462:
07320 return 22;
07321 case 1514:
07322 return 23;
07323 case 1567:
07324 return 24;
07325 case 1622:
07326 return 25;
07327 case 1679:
07328 return 26;
07329 case 1738:
07330 return 27;
07331 case 1799:
07332 return 28;
07333 case 1862:
07334 return 29;
07335 case 1928:
07336 return 30;
07337 case 2035:
07338 return 31;
07339 case 2107:
07340 return 32;
07341 case 2181:
07342 return 33;
07343 case 2257:
07344 return 34;
07345 case 2336:
07346 return 35;
07347 case 2418:
07348 return 36;
07349 case 2503:
07350 return 37;
07351 }
07352 return -1;
07353 }
07354
07355
07356
07357
07358
07359 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07360 {
07361 #ifdef __i386__
07362 int i,j;
07363 unsigned char od,d;
07364 static volatile long long delayvar;
07365
07366 for(i = 0 ; i < 5 ; i++){
07367 od = *data++;
07368 for(j = 0 ; j < 8 ; j++){
07369 d = od & 1;
07370 outb(d,myrpt->p.iobase);
07371
07372 for(delayvar = 1; delayvar < 15000; delayvar++);
07373 od >>= 1;
07374 outb(d | 2,myrpt->p.iobase);
07375
07376 for(delayvar = 1; delayvar < 30000; delayvar++);
07377 outb(d,myrpt->p.iobase);
07378
07379 for(delayvar = 1; delayvar < 10000; delayvar++);
07380 }
07381 }
07382
07383 for(delayvar = 1; delayvar < 50000; delayvar++);
07384 #endif
07385 }
07386
07387 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07388 {
07389 struct dahdi_radio_param r;
07390
07391 memset(&r,0,sizeof(struct dahdi_radio_param));
07392 r.radpar = DAHDI_RADPAR_REMMODE;
07393 r.data = DAHDI_RADPAR_REM_RBI1;
07394
07395 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07396 {
07397 rbi_out_parallel(myrpt,data);
07398 return;
07399 }
07400 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07401 memcpy(&r.data,data,5);
07402 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07403 {
07404 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07405 return;
07406 }
07407 }
07408
07409 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07410 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07411 {
07412 int i,j,idx,oldmode,olddata;
07413 struct dahdi_radio_param prm;
07414 char c;
07415
07416 if(debug) {
07417 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07418 printf("String output was:\n");
07419 for(i = 0; i < txbytes; i++)
07420 printf("%02X ", (unsigned char ) txbuf[i]);
07421 printf("\n");
07422 }
07423
07424 if (myrpt->iofd >= 0)
07425 {
07426 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07427 {
07428 return -1;
07429 }
07430 if ((!rxmaxbytes) || (rxbuf == NULL))
07431 {
07432 return(0);
07433 }
07434 memset(rxbuf,0,rxmaxbytes);
07435 for(i = 0; i < rxmaxbytes; i++)
07436 {
07437 j = read(myrpt->iofd,&c,1);
07438 if (j < 1)
07439 {
07440 return(i);
07441 }
07442 rxbuf[i] = c;
07443 if (asciiflag & 1)
07444 {
07445 rxbuf[i + 1] = 0;
07446 if (c == '\r') break;
07447 }
07448 }
07449 if(debug) {
07450 printf("String returned was:\n");
07451 for(j = 0; j < i; j++)
07452 printf("%02X ", (unsigned char ) rxbuf[j]);
07453 printf("\n");
07454 }
07455 return(i);
07456 }
07457
07458
07459 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07460
07461 prm.radpar = DAHDI_RADPAR_UIOMODE;
07462 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07463 oldmode = prm.data;
07464 prm.radpar = DAHDI_RADPAR_UIODATA;
07465 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07466 olddata = prm.data;
07467 prm.radpar = DAHDI_RADPAR_REMMODE;
07468 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07469 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07470 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07471 if (asciiflag & 2)
07472 {
07473 i = DAHDI_ONHOOK;
07474 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07475 usleep(100000);
07476 }
07477 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07478 prm.data = rxmaxbytes;
07479 memcpy(prm.buf,txbuf,txbytes);
07480 prm.index = txbytes;
07481 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07482 if (rxbuf)
07483 {
07484 *rxbuf = 0;
07485 memcpy(rxbuf,prm.buf,prm.index);
07486 }
07487 idx = prm.index;
07488 prm.radpar = DAHDI_RADPAR_REMMODE;
07489 prm.data = DAHDI_RADPAR_REM_NONE;
07490 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07491 if (asciiflag & 2)
07492 {
07493 i = DAHDI_OFFHOOK;
07494 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07495 }
07496 prm.radpar = DAHDI_RADPAR_UIOMODE;
07497 prm.data = oldmode;
07498 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07499 prm.radpar = DAHDI_RADPAR_UIODATA;
07500 prm.data = olddata;
07501 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07502 return(idx);
07503 }
07504
07505 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07506 {
07507 unsigned char rxbuf[100];
07508 int i,rv ;
07509
07510 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07511 if (rv == -1) return(-1);
07512 if (rv != (cmdlen + 6)) return(1);
07513 for(i = 0; i < 6; i++)
07514 if (rxbuf[i] != cmd[i]) return(1);
07515 if (rxbuf[cmdlen] != 0xfe) return(1);
07516 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07517 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07518 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07519 return(0);
07520 }
07521
07522 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07523 {
07524 int i;
07525
07526 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07527 if (debug) printf("Send to kenwood: %s\n",txstr);
07528 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07529 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07530 if (i < 0) return -1;
07531 if ((i > 0) && (rxstr[i - 1] == '\r'))
07532 rxstr[i-- - 1] = 0;
07533 if (debug) printf("Got from kenwood: %s\n",rxstr);
07534 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07535 return(i);
07536 }
07537
07538
07539 static int kenwood_pltocode(char *str)
07540 {
07541 int i;
07542 char *s;
07543
07544 s = strchr(str,'.');
07545 i = 0;
07546 if (s) i = atoi(s + 1);
07547 i += atoi(str) * 10;
07548 switch(i)
07549 {
07550 case 670:
07551 return 1;
07552 case 719:
07553 return 3;
07554 case 744:
07555 return 4;
07556 case 770:
07557 return 5;
07558 case 797:
07559 return 6;
07560 case 825:
07561 return 7;
07562 case 854:
07563 return 8;
07564 case 885:
07565 return 9;
07566 case 915:
07567 return 10;
07568 case 948:
07569 return 11;
07570 case 974:
07571 return 12;
07572 case 1000:
07573 return 13;
07574 case 1035:
07575 return 14;
07576 case 1072:
07577 return 15;
07578 case 1109:
07579 return 16;
07580 case 1148:
07581 return 17;
07582 case 1188:
07583 return 18;
07584 case 1230:
07585 return 19;
07586 case 1273:
07587 return 20;
07588 case 1318:
07589 return 21;
07590 case 1365:
07591 return 22;
07592 case 1413:
07593 return 23;
07594 case 1462:
07595 return 24;
07596 case 1514:
07597 return 25;
07598 case 1567:
07599 return 26;
07600 case 1622:
07601 return 27;
07602 case 1679:
07603 return 28;
07604 case 1738:
07605 return 29;
07606 case 1799:
07607 return 30;
07608 case 1862:
07609 return 31;
07610 case 1928:
07611 return 32;
07612 case 2035:
07613 return 33;
07614 case 2107:
07615 return 34;
07616 case 2181:
07617 return 35;
07618 case 2257:
07619 return 36;
07620 case 2336:
07621 return 37;
07622 case 2418:
07623 return 38;
07624 case 2503:
07625 return 39;
07626 }
07627 return -1;
07628 }
07629
07630 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07631 char *cmpstr)
07632 {
07633 int i,j;
07634
07635 for(i = 0;i < KENWOOD_RETRIES;i++)
07636 {
07637 j = sendkenwood(myrpt,txstr,rxstr);
07638 if (j < 0) return(j);
07639 if (j == 0) continue;
07640 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07641 }
07642 return(-1);
07643 }
07644
07645 static int setkenwood(struct rpt *myrpt)
07646 {
07647 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07648 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07649 int myrxpl;
07650
07651 int offsets[] = {0,2,1};
07652 int powers[] = {2,1,0};
07653
07654 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07655 split_freq(mhz, decimals, myrpt->freq);
07656 if (atoi(mhz) > 400)
07657 {
07658 band = '6';
07659 band1 = '1';
07660 band2 = '5';
07661 strcpy(offset,"005000000");
07662 }
07663 else
07664 {
07665 band = '2';
07666 band1 = '0';
07667 band2 = '2';
07668 strcpy(offset,"000600000");
07669 }
07670 strcpy(freq,"000000");
07671 strncpy(freq,decimals,strlen(decimals));
07672 myrxpl = myrpt->rxplon;
07673 if (IS_XPMR(myrpt)) myrxpl = 0;
07674 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07675 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07676 (myrpt->txplon != 0),myrxpl,
07677 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07678 offset);
07679 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07680 sprintf(txstr,"RBN %c\r",band2);
07681 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07682 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07683 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07684 return 0;
07685 }
07686
07687 static int set_tm271(struct rpt *myrpt)
07688 {
07689 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07690 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07691
07692 int offsets[] = {0,2,1};
07693 int powers[] = {2,1,0};
07694
07695 split_freq(mhz, decimals, myrpt->freq);
07696 strcpy(freq,"000000");
07697 strncpy(freq,decimals,strlen(decimals));
07698
07699 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07700 atoi(mhz),freq,offsets[(int)myrpt->offset],
07701 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07702 kenwood_pltocode(myrpt->rxpl));
07703
07704 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07705 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07706 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07707 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07708 return 0;
07709 }
07710
07711 static int setrbi(struct rpt *myrpt)
07712 {
07713 char tmp[MAXREMSTR] = "",*s;
07714 unsigned char rbicmd[5];
07715 int band,txoffset = 0,txpower = 0,rxpl;
07716
07717
07718 if (!myrpt->remoterig) return(0);
07719 if (!myrpt->remoterig[0]) return(0);
07720
07721 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07722 if (setrbi_check(myrpt) == -1) return(-1);
07723 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07724 s = strchr(tmp,'.');
07725
07726
07727 if (s == NULL){
07728 if(debug)
07729 printf("@@@@ Frequency needs a decimal\n");
07730 return -1;
07731 }
07732
07733 *s++ = 0;
07734 if (strlen(tmp) < 2){
07735 if(debug)
07736 printf("@@@@ Bad MHz digits: %s\n", tmp);
07737 return -1;
07738 }
07739
07740 if (strlen(s) < 3){
07741 if(debug)
07742 printf("@@@@ Bad KHz digits: %s\n", s);
07743 return -1;
07744 }
07745
07746 if ((s[2] != '0') && (s[2] != '5')){
07747 if(debug)
07748 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07749 return -1;
07750 }
07751
07752 band = rbi_mhztoband(tmp);
07753 if (band == -1){
07754 if(debug)
07755 printf("@@@@ Bad Band: %s\n", tmp);
07756 return -1;
07757 }
07758
07759 rxpl = rbi_pltocode(myrpt->rxpl);
07760
07761 if (rxpl == -1){
07762 if(debug)
07763 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07764 return -1;
07765 }
07766
07767
07768 switch(myrpt->offset)
07769 {
07770 case REM_MINUS:
07771 txoffset = 0;
07772 break;
07773 case REM_PLUS:
07774 txoffset = 0x10;
07775 break;
07776 case REM_SIMPLEX:
07777 txoffset = 0x20;
07778 break;
07779 }
07780 switch(myrpt->powerlevel)
07781 {
07782 case REM_LOWPWR:
07783 txpower = 0;
07784 break;
07785 case REM_MEDPWR:
07786 txpower = 0x20;
07787 break;
07788 case REM_HIPWR:
07789 txpower = 0x10;
07790 break;
07791 }
07792 rbicmd[0] = 0;
07793 rbicmd[1] = band | txpower | 0xc0;
07794 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07795 if (s[2] == '5') rbicmd[2] |= 0x40;
07796 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07797 rbicmd[4] = rxpl;
07798 if (myrpt->txplon) rbicmd[4] |= 0x40;
07799 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07800 rbi_out(myrpt,rbicmd);
07801 return 0;
07802 }
07803
07804 static int setrtx(struct rpt *myrpt)
07805 {
07806 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07807 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07808 float ofac;
07809 double txfreq;
07810
07811
07812 if (!myrpt->remoterig) return(0);
07813 if (!myrpt->remoterig[0]) return(0);
07814
07815 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07816
07817 if (!IS_XPMR(myrpt)) return(0);
07818 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07819 s = strchr(tmp,'.');
07820
07821
07822 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07823
07824 if (s == NULL){
07825 if(debug)
07826 printf("@@@@ Frequency needs a decimal\n");
07827 return -1;
07828 }
07829 *s++ = 0;
07830 if (strlen(tmp) < 2){
07831 if(debug)
07832 printf("@@@@ Bad MHz digits: %s\n", tmp);
07833 return -1;
07834 }
07835
07836 if (strlen(s) < 3){
07837 if(debug)
07838 printf("@@@@ Bad KHz digits: %s\n", s);
07839 return -1;
07840 }
07841
07842 if ((s[2] != '0') && (s[2] != '5')){
07843 if(debug)
07844 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07845 return -1;
07846 }
07847
07848 band = rbi_mhztoband(tmp);
07849 if (band == -1){
07850 if(debug)
07851 printf("@@@@ Bad Band: %s\n", tmp);
07852 return -1;
07853 }
07854
07855 rxpl = rbi_pltocode(myrpt->rxpl);
07856
07857 if (rxpl == -1){
07858 if(debug)
07859 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07860 return -1;
07861 }
07862
07863 txpl = rbi_pltocode(myrpt->txpl);
07864
07865 if (txpl == -1){
07866 if(debug)
07867 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07868 return -1;
07869 }
07870
07871 switch(myrpt->offset)
07872 {
07873 case REM_MINUS:
07874 txoffset = 0;
07875 break;
07876 case REM_PLUS:
07877 txoffset = 0x10;
07878 break;
07879 case REM_SIMPLEX:
07880 txoffset = 0x20;
07881 break;
07882 }
07883 switch(myrpt->powerlevel)
07884 {
07885 case REM_LOWPWR:
07886 txpower = 0;
07887 break;
07888 case REM_MEDPWR:
07889 txpower = 0x20;
07890 break;
07891 case REM_HIPWR:
07892 txpower = 0x10;
07893 break;
07894 }
07895
07896 res = setrtx_check(myrpt);
07897 if (res < 0) return res;
07898 ofac = 0.0;
07899 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07900 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07901
07902 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07903 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07904 else
07905 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07906
07907 pwr = 'L';
07908 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07909 if (!res)
07910 {
07911 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07912 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07913 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07914 send_usb_txt(myrpt,rigstr);
07915 rpt_telemetry(myrpt,COMPLETE,NULL);
07916 res = 0;
07917 }
07918 return 0;
07919 }
07920 #if 0
07921
07922
07923
07924
07925 static int setxpmr(struct rpt *myrpt)
07926 {
07927 char rigstr[200];
07928 int rxpl,txpl;
07929
07930
07931 if (!myrpt->remoterig) return(0);
07932 if (!myrpt->remoterig[0]) return(0);
07933
07934 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07935
07936 if (!IS_XPMR(myrpt)) return(0);
07937
07938 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07939
07940 rxpl = rbi_pltocode(myrpt->rxpl);
07941
07942 if (rxpl == -1){
07943 if(debug)
07944 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07945 return -1;
07946 }
07947
07948 txpl = rbi_pltocode(myrpt->txpl);
07949 if (txpl == -1){
07950 if(debug)
07951 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07952 return -1;
07953 }
07954 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07955 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07956 (myrpt->txplon) ? myrpt->txpl : "0.0");
07957 send_usb_txt(myrpt,rigstr);
07958 return 0;
07959 }
07960 #endif
07961
07962 static int setrbi_check(struct rpt *myrpt)
07963 {
07964 char tmp[MAXREMSTR] = "",*s;
07965 int band,txpl;
07966
07967
07968 if (!myrpt->remote) return(0);
07969
07970 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07971 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07972 s = strchr(tmp,'.');
07973
07974
07975 if (s == NULL){
07976 if(debug)
07977 printf("@@@@ Frequency needs a decimal\n");
07978 return -1;
07979 }
07980
07981 *s++ = 0;
07982 if (strlen(tmp) < 2){
07983 if(debug)
07984 printf("@@@@ Bad MHz digits: %s\n", tmp);
07985 return -1;
07986 }
07987
07988 if (strlen(s) < 3){
07989 if(debug)
07990 printf("@@@@ Bad KHz digits: %s\n", s);
07991 return -1;
07992 }
07993
07994 if ((s[2] != '0') && (s[2] != '5')){
07995 if(debug)
07996 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07997 return -1;
07998 }
07999
08000 band = rbi_mhztoband(tmp);
08001 if (band == -1){
08002 if(debug)
08003 printf("@@@@ Bad Band: %s\n", tmp);
08004 return -1;
08005 }
08006
08007 txpl = rbi_pltocode(myrpt->txpl);
08008
08009 if (txpl == -1){
08010 if(debug)
08011 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08012 return -1;
08013 }
08014 return 0;
08015 }
08016
08017 static int setrtx_check(struct rpt *myrpt)
08018 {
08019 char tmp[MAXREMSTR] = "",*s;
08020 int band,txpl,rxpl;
08021
08022
08023 if (!myrpt->remote) return(0);
08024
08025 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08026 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08027 s = strchr(tmp,'.');
08028
08029
08030 if (s == NULL){
08031 if(debug)
08032 printf("@@@@ Frequency needs a decimal\n");
08033 return -1;
08034 }
08035
08036 *s++ = 0;
08037 if (strlen(tmp) < 2){
08038 if(debug)
08039 printf("@@@@ Bad MHz digits: %s\n", tmp);
08040 return -1;
08041 }
08042
08043 if (strlen(s) < 3){
08044 if(debug)
08045 printf("@@@@ Bad KHz digits: %s\n", s);
08046 return -1;
08047 }
08048
08049 if ((s[2] != '0') && (s[2] != '5')){
08050 if(debug)
08051 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08052 return -1;
08053 }
08054
08055 band = rbi_mhztoband(tmp);
08056 if (band == -1){
08057 if(debug)
08058 printf("@@@@ Bad Band: %s\n", tmp);
08059 return -1;
08060 }
08061
08062 txpl = rbi_pltocode(myrpt->txpl);
08063
08064 if (txpl == -1){
08065 if(debug)
08066 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08067 return -1;
08068 }
08069
08070 rxpl = rbi_pltocode(myrpt->rxpl);
08071
08072 if (rxpl == -1){
08073 if(debug)
08074 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08075 return -1;
08076 }
08077 return 0;
08078 }
08079
08080 static int check_freq_kenwood(int m, int d, int *defmode)
08081 {
08082 int dflmd = REM_MODE_FM;
08083
08084 if (m == 144){
08085 if(d < 10100)
08086 return -1;
08087 }
08088 else if((m >= 145) && (m < 148)){
08089 ;
08090 }
08091 else if((m >= 430) && (m < 450)){
08092 ;
08093 }
08094 else
08095 return -1;
08096
08097 if(defmode)
08098 *defmode = dflmd;
08099
08100
08101 return 0;
08102 }
08103
08104
08105 static int check_freq_tm271(int m, int d, int *defmode)
08106 {
08107 int dflmd = REM_MODE_FM;
08108
08109 if (m == 144){
08110 if(d < 10100)
08111 return -1;
08112 }
08113 else if((m >= 145) && (m < 148)){
08114 ;
08115 }
08116 return -1;
08117
08118 if(defmode)
08119 *defmode = dflmd;
08120
08121
08122 return 0;
08123 }
08124
08125
08126
08127
08128
08129 static int check_freq_rbi(int m, int d, int *defmode)
08130 {
08131 int dflmd = REM_MODE_FM;
08132
08133 if(m == 50){
08134 if(d < 10100)
08135 return -1;
08136 }
08137 else if((m >= 51) && ( m < 54)){
08138 ;
08139 }
08140 else if(m == 144){
08141 if(d < 10100)
08142 return -1;
08143 }
08144 else if((m >= 145) && (m < 148)){
08145 ;
08146 }
08147 else if((m >= 222) && (m < 225)){
08148 ;
08149 }
08150 else if((m >= 430) && (m < 450)){
08151 ;
08152 }
08153 else if((m >= 1240) && (m < 1300)){
08154 ;
08155 }
08156 else
08157 return -1;
08158
08159 if(defmode)
08160 *defmode = dflmd;
08161
08162
08163 return 0;
08164 }
08165
08166
08167
08168
08169 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08170 {
08171 int dflmd = REM_MODE_FM;
08172
08173 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08174 {
08175
08176 if(m == 144){
08177 if(d < 10100)
08178 return -1;
08179 }
08180 else if((m >= 145) && (m < 148)){
08181 ;
08182 }
08183 else
08184 return -1;
08185 }
08186 else
08187 {
08188 if((m >= 430) && (m < 450)){
08189 ;
08190 }
08191 else
08192 return -1;
08193 }
08194 if(defmode)
08195 *defmode = dflmd;
08196
08197
08198 return 0;
08199 }
08200
08201
08202
08203
08204
08205 static int decimals2int(char *fraction)
08206 {
08207 int i;
08208 char len = strlen(fraction);
08209 int multiplier = 100000;
08210 int res = 0;
08211
08212 if(!len)
08213 return 0;
08214 for( i = 0 ; i < len ; i++, multiplier /= 10)
08215 res += (fraction[i] - '0') * multiplier;
08216 return res;
08217 }
08218
08219
08220
08221
08222
08223
08224 static int split_freq(char *mhz, char *decimals, char *freq)
08225 {
08226 char freq_copy[MAXREMSTR];
08227 char *decp;
08228
08229 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08230 if(decp){
08231 *decp++ = 0;
08232 strncpy(mhz, freq_copy, MAXREMSTR);
08233 strcpy(decimals, "00000");
08234 strncpy(decimals, decp, strlen(decp));
08235 decimals[5] = 0;
08236 return 0;
08237 }
08238 else
08239 return -1;
08240
08241 }
08242
08243
08244
08245
08246
08247 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08248 {
08249 char freq_copy[MAXREMSTR];
08250 char *decp;
08251
08252 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08253 if(decp){
08254 *decp++ = 0;
08255 strncpy(hertz, freq_copy, MAXREMSTR);
08256 strncpy(decimal, decp, strlen(decp));
08257 decimal[strlen(decp)] = '\0';
08258 return 0;
08259 }
08260 else
08261 return -1;
08262 }
08263
08264
08265
08266
08267
08268
08269
08270
08271
08272
08273
08274 static int check_freq_ft897(int m, int d, int *defmode)
08275 {
08276 int dflmd = REM_MODE_FM;
08277
08278 if(m == 1){
08279 dflmd = REM_MODE_LSB;
08280 if(d < 80000)
08281 return -1;
08282 }
08283 else if(m == 3){
08284 dflmd = REM_MODE_LSB;
08285 if(d < 50000)
08286 return -1;
08287 }
08288 else if(m == 7){
08289 dflmd = REM_MODE_LSB;
08290 if(d > 30000)
08291 return -1;
08292 }
08293 else if(m == 14){
08294 dflmd = REM_MODE_USB;
08295 if(d > 35000)
08296 return -1;
08297 }
08298 else if(m == 18){
08299 dflmd = REM_MODE_USB;
08300 if((d < 6800) || (d > 16800))
08301 return -1;
08302 }
08303 else if(m == 21){
08304 dflmd = REM_MODE_USB;
08305 if((d < 20000) || (d > 45000))
08306 return -1;
08307 }
08308 else if(m == 24){
08309 dflmd = REM_MODE_USB;
08310 if((d < 89000) || (d > 99000))
08311 return -1;
08312 }
08313 else if(m == 28){
08314 dflmd = REM_MODE_USB;
08315 }
08316 else if(m == 29){
08317 if(d >= 51000)
08318 dflmd = REM_MODE_FM;
08319 else
08320 dflmd = REM_MODE_USB;
08321 if(d > 70000)
08322 return -1;
08323 }
08324 else if(m == 50){
08325 if(d >= 30000)
08326 dflmd = REM_MODE_FM;
08327 else
08328 dflmd = REM_MODE_USB;
08329
08330 }
08331 else if((m >= 51) && ( m < 54)){
08332 dflmd = REM_MODE_FM;
08333 }
08334 else if(m == 144){
08335 if(d >= 30000)
08336 dflmd = REM_MODE_FM;
08337 else
08338 dflmd = REM_MODE_USB;
08339 }
08340 else if((m >= 145) && (m < 148)){
08341 dflmd = REM_MODE_FM;
08342 }
08343 else if((m >= 430) && (m < 450)){
08344 if(m < 438)
08345 dflmd = REM_MODE_USB;
08346 else
08347 dflmd = REM_MODE_FM;
08348 ;
08349 }
08350 else
08351 return -1;
08352
08353 if(defmode)
08354 *defmode = dflmd;
08355
08356 return 0;
08357 }
08358
08359
08360
08361
08362
08363 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08364 {
08365 unsigned char cmdstr[5];
08366 int fd,m,d;
08367 char mhz[MAXREMSTR];
08368 char decimals[MAXREMSTR];
08369
08370 fd = 0;
08371 if(debug)
08372 printf("New frequency: %s\n",newfreq);
08373
08374 if(split_freq(mhz, decimals, newfreq))
08375 return -1;
08376
08377 m = atoi(mhz);
08378 d = atoi(decimals);
08379
08380
08381
08382 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08383 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08384 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08385 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08386 cmdstr[4] = 0x01;
08387
08388 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08389
08390 }
08391
08392
08393
08394 static int simple_command_ft897(struct rpt *myrpt, char command)
08395 {
08396 unsigned char cmdstr[5];
08397
08398 memset(cmdstr, 0, 5);
08399
08400 cmdstr[4] = command;
08401
08402 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08403
08404 }
08405
08406
08407
08408 static int set_offset_ft897(struct rpt *myrpt, char offset)
08409 {
08410 unsigned char cmdstr[5];
08411
08412 memset(cmdstr, 0, 5);
08413
08414 switch(offset){
08415 case REM_SIMPLEX:
08416 cmdstr[0] = 0x89;
08417 break;
08418
08419 case REM_MINUS:
08420 cmdstr[0] = 0x09;
08421 break;
08422
08423 case REM_PLUS:
08424 cmdstr[0] = 0x49;
08425 break;
08426
08427 default:
08428 return -1;
08429 }
08430
08431 cmdstr[4] = 0x09;
08432
08433 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08434 }
08435
08436
08437
08438 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08439 {
08440 unsigned char cmdstr[5];
08441
08442 memset(cmdstr, 0, 5);
08443
08444 switch(newmode){
08445 case REM_MODE_FM:
08446 cmdstr[0] = 0x08;
08447 break;
08448
08449 case REM_MODE_USB:
08450 cmdstr[0] = 0x01;
08451 break;
08452
08453 case REM_MODE_LSB:
08454 cmdstr[0] = 0x00;
08455 break;
08456
08457 case REM_MODE_AM:
08458 cmdstr[0] = 0x04;
08459 break;
08460
08461 default:
08462 return -1;
08463 }
08464 cmdstr[4] = 0x07;
08465
08466 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08467 }
08468
08469
08470
08471 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08472 {
08473 unsigned char cmdstr[5];
08474
08475 memset(cmdstr, 0, 5);
08476
08477 if(rxplon && txplon)
08478 cmdstr[0] = 0x2A;
08479 else if (!rxplon && txplon)
08480 cmdstr[0] = 0x4A;
08481 else if (rxplon && !txplon)
08482 cmdstr[0] = 0x3A;
08483 else
08484 cmdstr[0] = 0x8A;
08485
08486 cmdstr[4] = 0x0A;
08487
08488 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08489 }
08490
08491
08492
08493
08494 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08495 {
08496 unsigned char cmdstr[5];
08497 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08498 int h,d;
08499
08500 memset(cmdstr, 0, 5);
08501
08502 if(split_ctcss_freq(hertz, decimal, txtone))
08503 return -1;
08504
08505 h = atoi(hertz);
08506 d = atoi(decimal);
08507
08508 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08509 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08510
08511 if(rxtone){
08512
08513 if(split_ctcss_freq(hertz, decimal, rxtone))
08514 return -1;
08515
08516 h = atoi(hertz);
08517 d = atoi(decimal);
08518
08519 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08520 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08521 }
08522 cmdstr[4] = 0x0B;
08523
08524 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08525 }
08526
08527
08528
08529 static int set_ft897(struct rpt *myrpt)
08530 {
08531 int res;
08532
08533 if(debug)
08534 printf("@@@@ lock on\n");
08535
08536 res = simple_command_ft897(myrpt, 0x00);
08537
08538 if(debug)
08539 printf("@@@@ ptt off\n");
08540
08541 if(!res)
08542 res = simple_command_ft897(myrpt, 0x88);
08543
08544 if(debug)
08545 printf("Modulation mode\n");
08546
08547 if(!res)
08548 res = set_mode_ft897(myrpt, myrpt->remmode);
08549
08550 if(debug)
08551 printf("Split off\n");
08552
08553 if(!res)
08554 simple_command_ft897(myrpt, 0x82);
08555
08556 if(debug)
08557 printf("Frequency\n");
08558
08559 if(!res)
08560 res = set_freq_ft897(myrpt, myrpt->freq);
08561 if((myrpt->remmode == REM_MODE_FM)){
08562 if(debug)
08563 printf("Offset\n");
08564 if(!res)
08565 res = set_offset_ft897(myrpt, myrpt->offset);
08566 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08567 if(debug)
08568 printf("CTCSS tone freqs.\n");
08569 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08570 }
08571 if(!res){
08572 if(debug)
08573 printf("CTCSS mode\n");
08574 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08575 }
08576 }
08577 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08578 if(debug)
08579 printf("Clarifier off\n");
08580 simple_command_ft897(myrpt, 0x85);
08581 }
08582 return res;
08583 }
08584
08585 static int closerem_ft897(struct rpt *myrpt)
08586 {
08587 simple_command_ft897(myrpt, 0x88);
08588 return 0;
08589 }
08590
08591
08592
08593
08594
08595
08596
08597 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08598 {
08599 int m,d;
08600 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08601
08602 if(debug)
08603 printf("Before bump: %s\n", myrpt->freq);
08604
08605 if(split_freq(mhz, decimals, myrpt->freq))
08606 return -1;
08607
08608 m = atoi(mhz);
08609 d = atoi(decimals);
08610
08611 d += (interval / 10);
08612 if(d < 0){
08613 m--;
08614 d += 100000;
08615 }
08616 else if(d >= 100000){
08617 m++;
08618 d -= 100000;
08619 }
08620
08621 if(check_freq_ft897(m, d, NULL)){
08622 if(debug)
08623 printf("Bump freq invalid\n");
08624 return -1;
08625 }
08626
08627 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08628
08629 if(debug)
08630 printf("After bump: %s\n", myrpt->freq);
08631
08632 return set_freq_ft897(myrpt, myrpt->freq);
08633 }
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08645 {
08646 int dflmd = REM_MODE_FM;
08647 int rv=0;
08648
08649 if(debug > 6)
08650 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08651
08652
08653
08654 if(m == 1){
08655 dflmd = REM_MODE_LSB;
08656 if(d < 80000)rv=-1;
08657 }
08658 else if(m == 3){
08659 dflmd = REM_MODE_LSB;
08660 if(d < 50000)rv=-1;
08661 }
08662 else if(m == 7){
08663 dflmd = REM_MODE_LSB;
08664 if(d > 30000)rv=-1;
08665 }
08666 else if(m == 14){
08667 dflmd = REM_MODE_USB;
08668 if(d > 35000)rv=-1;
08669 }
08670 else if(m == 18){
08671 dflmd = REM_MODE_USB;
08672 if((d < 6800) || (d > 16800))rv=-1;
08673 }
08674 else if(m == 21){
08675 dflmd = REM_MODE_USB;
08676 if((d < 20000) || (d > 45000))rv=-1;
08677 }
08678 else if(m == 24){
08679 dflmd = REM_MODE_USB;
08680 if((d < 89000) || (d > 99000))rv=-1;
08681 }
08682 else if(m == 28){
08683 dflmd = REM_MODE_USB;
08684 }
08685 else if(m == 29){
08686 if(d >= 51000)
08687 dflmd = REM_MODE_FM;
08688 else
08689 dflmd = REM_MODE_USB;
08690 if(d > 70000)rv=-1;
08691 }
08692 else if(m == 50){
08693 if(d >= 30000)
08694 dflmd = REM_MODE_FM;
08695 else
08696 dflmd = REM_MODE_USB;
08697 }
08698 else if((m >= 51) && ( m < 54)){
08699 dflmd = REM_MODE_FM;
08700 }
08701 else if(m == 144){
08702 if(d >= 30000)
08703 dflmd = REM_MODE_FM;
08704 else
08705 dflmd = REM_MODE_USB;
08706 }
08707 else if((m >= 145) && (m < 148)){
08708 dflmd = REM_MODE_FM;
08709 }
08710 else if((m >= 430) && (m < 450)){
08711 if(m < 438)
08712 dflmd = REM_MODE_USB;
08713 else
08714 dflmd = REM_MODE_FM;
08715 }
08716
08717
08718 if(mars && rv<0){
08719 if((m >= 450) && (m < 470)){
08720 dflmd = REM_MODE_FM;
08721 rv=0;
08722 }
08723 else if((m >= 148) && (m < 174)){
08724 dflmd = REM_MODE_FM;
08725 rv=0;
08726 }
08727 else if((m >= 138) && (m < 144)){
08728 dflmd = REM_MODE_AM;
08729 rv=0;
08730 }
08731 else if((m >= 108) && (m < 138)){
08732 dflmd = REM_MODE_AM;
08733 rv=0;
08734 }
08735 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08736 dflmd = REM_MODE_AM;
08737 rv=0;
08738 }
08739 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08740 dflmd = REM_MODE_AM;
08741 rv=0;
08742 }
08743 }
08744
08745 if(defmode)
08746 *defmode = dflmd;
08747
08748 if(debug > 1)
08749 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08750
08751 return rv;
08752 }
08753
08754
08755 static int ic706_pltocode(char *str)
08756 {
08757 int i;
08758 char *s;
08759 int rv=-1;
08760
08761 s = strchr(str,'.');
08762 i = 0;
08763 if (s) i = atoi(s + 1);
08764 i += atoi(str) * 10;
08765 switch(i)
08766 {
08767 case 670:
08768 rv=0;
08769 case 693:
08770 rv=1;
08771 case 719:
08772 rv=2;
08773 case 744:
08774 rv=3;
08775 case 770:
08776 rv=4;
08777 case 797:
08778 rv=5;
08779 case 825:
08780 rv=6;
08781 case 854:
08782 rv=7;
08783 case 885:
08784 rv=8;
08785 case 915:
08786 rv=9;
08787 case 948:
08788 rv=10;
08789 case 974:
08790 rv=11;
08791 case 1000:
08792 rv=12;
08793 case 1035:
08794 rv=13;
08795 case 1072:
08796 rv=14;
08797 case 1109:
08798 rv=15;
08799 case 1148:
08800 rv=16;
08801 case 1188:
08802 rv=17;
08803 case 1230:
08804 rv=18;
08805 case 1273:
08806 rv=19;
08807 case 1318:
08808 rv=20;
08809 case 1365:
08810 rv=21;
08811 case 1413:
08812 rv=22;
08813 case 1462:
08814 rv=23;
08815 case 1514:
08816 rv=24;
08817 case 1567:
08818 rv=25;
08819 case 1598:
08820 rv=26;
08821 case 1622:
08822 rv=27;
08823 case 1655:
08824 rv=28;
08825 case 1679:
08826 rv=29;
08827 case 1713:
08828 rv=30;
08829 case 1738:
08830 rv=31;
08831 case 1773:
08832 rv=32;
08833 case 1799:
08834 rv=33;
08835 case 1835:
08836 rv=34;
08837 case 1862:
08838 rv=35;
08839 case 1899:
08840 rv=36;
08841 case 1928:
08842 rv=37;
08843 case 1966:
08844 rv=38;
08845 case 1995:
08846 rv=39;
08847 case 2035:
08848 rv=40;
08849 case 2065:
08850 rv=41;
08851 case 2107:
08852 rv=42;
08853 case 2181:
08854 rv=43;
08855 case 2257:
08856 rv=44;
08857 case 2291:
08858 rv=45;
08859 case 2336:
08860 rv=46;
08861 case 2418:
08862 rv=47;
08863 case 2503:
08864 rv=48;
08865 case 2541:
08866 rv=49;
08867 }
08868 if(debug > 1)
08869 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08870
08871 return rv;
08872 }
08873
08874
08875
08876 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08877 {
08878 unsigned char cmdstr[10];
08879
08880 cmdstr[0] = cmdstr[1] = 0xfe;
08881 cmdstr[2] = myrpt->p.civaddr;
08882 cmdstr[3] = 0xe0;
08883 cmdstr[4] = command;
08884 cmdstr[5] = subcommand;
08885 cmdstr[6] = 0xfd;
08886
08887 return(civ_cmd(myrpt,cmdstr,7));
08888 }
08889
08890
08891
08892
08893
08894 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08895 {
08896 unsigned char cmdstr[20];
08897 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08898 int fd,m,d;
08899
08900 fd = 0;
08901 if(debug)
08902 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08903
08904 if(split_freq(mhz, decimals, newfreq))
08905 return -1;
08906
08907 m = atoi(mhz);
08908 d = atoi(decimals);
08909
08910
08911
08912 cmdstr[0] = cmdstr[1] = 0xfe;
08913 cmdstr[2] = myrpt->p.civaddr;
08914 cmdstr[3] = 0xe0;
08915 cmdstr[4] = 5;
08916 cmdstr[5] = ((d % 10) << 4);
08917 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08918 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08919 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08920 cmdstr[9] = (m / 100);
08921 cmdstr[10] = 0xfd;
08922
08923 return(civ_cmd(myrpt,cmdstr,11));
08924 }
08925
08926
08927
08928 static int set_offset_ic706(struct rpt *myrpt, char offset)
08929 {
08930 unsigned char c;
08931
08932 if(debug > 6)
08933 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08934
08935 switch(offset){
08936 case REM_SIMPLEX:
08937 c = 0x10;
08938 break;
08939
08940 case REM_MINUS:
08941 c = 0x11;
08942 break;
08943
08944 case REM_PLUS:
08945 c = 0x12;
08946 break;
08947
08948 default:
08949 return -1;
08950 }
08951
08952 return simple_command_ic706(myrpt,0x0f,c);
08953
08954 }
08955
08956
08957
08958 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08959 {
08960 unsigned char c;
08961
08962 if(debug > 6)
08963 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08964
08965 switch(newmode){
08966 case REM_MODE_FM:
08967 c = 5;
08968 break;
08969
08970 case REM_MODE_USB:
08971 c = 1;
08972 break;
08973
08974 case REM_MODE_LSB:
08975 c = 0;
08976 break;
08977
08978 case REM_MODE_AM:
08979 c = 2;
08980 break;
08981
08982 default:
08983 return -1;
08984 }
08985 return simple_command_ic706(myrpt,6,c);
08986 }
08987
08988
08989
08990 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08991 {
08992 unsigned char cmdstr[10];
08993 int rv;
08994
08995 if(debug > 6)
08996 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
08997
08998 cmdstr[0] = cmdstr[1] = 0xfe;
08999 cmdstr[2] = myrpt->p.civaddr;
09000 cmdstr[3] = 0xe0;
09001 cmdstr[4] = 0x16;
09002 cmdstr[5] = 0x42;
09003 cmdstr[6] = (txplon != 0);
09004 cmdstr[7] = 0xfd;
09005
09006 rv = civ_cmd(myrpt,cmdstr,8);
09007 if (rv) return(-1);
09008
09009 cmdstr[0] = cmdstr[1] = 0xfe;
09010 cmdstr[2] = myrpt->p.civaddr;
09011 cmdstr[3] = 0xe0;
09012 cmdstr[4] = 0x16;
09013 cmdstr[5] = 0x43;
09014 cmdstr[6] = (rxplon != 0);
09015 cmdstr[7] = 0xfd;
09016
09017 return(civ_cmd(myrpt,cmdstr,8));
09018 }
09019
09020 #if 0
09021
09022
09023 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09024 {
09025 unsigned char cmdstr[10];
09026 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09027 int h,d,rv;
09028
09029 memset(cmdstr, 0, 5);
09030
09031 if(debug > 6)
09032 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09033
09034 if(split_ctcss_freq(hertz, decimal, txtone))
09035 return -1;
09036
09037 h = atoi(hertz);
09038 d = atoi(decimal);
09039
09040 cmdstr[0] = cmdstr[1] = 0xfe;
09041 cmdstr[2] = myrpt->p.civaddr;
09042 cmdstr[3] = 0xe0;
09043 cmdstr[4] = 0x1b;
09044 cmdstr[5] = 0;
09045 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09046 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09047 cmdstr[8] = 0xfd;
09048
09049 rv = civ_cmd(myrpt,cmdstr,9);
09050 if (rv) return(-1);
09051
09052 if (!rxtone) return(0);
09053
09054 if(split_ctcss_freq(hertz, decimal, rxtone))
09055 return -1;
09056
09057 h = atoi(hertz);
09058 d = atoi(decimal);
09059
09060 cmdstr[0] = cmdstr[1] = 0xfe;
09061 cmdstr[2] = myrpt->p.civaddr;
09062 cmdstr[3] = 0xe0;
09063 cmdstr[4] = 0x1b;
09064 cmdstr[5] = 1;
09065 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09066 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09067 cmdstr[8] = 0xfd;
09068 return(civ_cmd(myrpt,cmdstr,9));
09069 }
09070 #endif
09071
09072 static int vfo_ic706(struct rpt *myrpt)
09073 {
09074 unsigned char cmdstr[10];
09075
09076 cmdstr[0] = cmdstr[1] = 0xfe;
09077 cmdstr[2] = myrpt->p.civaddr;
09078 cmdstr[3] = 0xe0;
09079 cmdstr[4] = 7;
09080 cmdstr[5] = 0xfd;
09081
09082 return(civ_cmd(myrpt,cmdstr,6));
09083 }
09084
09085 static int mem2vfo_ic706(struct rpt *myrpt)
09086 {
09087 unsigned char cmdstr[10];
09088
09089 cmdstr[0] = cmdstr[1] = 0xfe;
09090 cmdstr[2] = myrpt->p.civaddr;
09091 cmdstr[3] = 0xe0;
09092 cmdstr[4] = 0x0a;
09093 cmdstr[5] = 0xfd;
09094
09095 return(civ_cmd(myrpt,cmdstr,6));
09096 }
09097
09098 static int select_mem_ic706(struct rpt *myrpt, int slot)
09099 {
09100 unsigned char cmdstr[10];
09101
09102 cmdstr[0] = cmdstr[1] = 0xfe;
09103 cmdstr[2] = myrpt->p.civaddr;
09104 cmdstr[3] = 0xe0;
09105 cmdstr[4] = 8;
09106 cmdstr[5] = 0;
09107 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09108 cmdstr[7] = 0xfd;
09109
09110 return(civ_cmd(myrpt,cmdstr,8));
09111 }
09112
09113 static int set_ic706(struct rpt *myrpt)
09114 {
09115 int res = 0,i;
09116
09117 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09118
09119 if (!res)
09120 res = simple_command_ic706(myrpt,7,0);
09121
09122 if((myrpt->remmode == REM_MODE_FM))
09123 {
09124 i = ic706_pltocode(myrpt->rxpl);
09125 if (i == -1) return -1;
09126 if(debug)
09127 printf("Select memory number\n");
09128 if (!res)
09129 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09130 if(debug)
09131 printf("Transfer memory to VFO\n");
09132 if (!res)
09133 res = mem2vfo_ic706(myrpt);
09134 }
09135
09136 if(debug)
09137 printf("Set to VFO\n");
09138
09139 if (!res)
09140 res = vfo_ic706(myrpt);
09141
09142 if(debug)
09143 printf("Modulation mode\n");
09144
09145 if (!res)
09146 res = set_mode_ic706(myrpt, myrpt->remmode);
09147
09148 if(debug)
09149 printf("Split off\n");
09150
09151 if(!res)
09152 simple_command_ic706(myrpt, 0x82,0);
09153
09154 if(debug)
09155 printf("Frequency\n");
09156
09157 if(!res)
09158 res = set_freq_ic706(myrpt, myrpt->freq);
09159 if((myrpt->remmode == REM_MODE_FM)){
09160 if(debug)
09161 printf("Offset\n");
09162 if(!res)
09163 res = set_offset_ic706(myrpt, myrpt->offset);
09164 if(!res){
09165 if(debug)
09166 printf("CTCSS mode\n");
09167 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09168 }
09169 }
09170 return res;
09171 }
09172
09173
09174
09175
09176
09177
09178
09179 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09180 {
09181 int m,d;
09182 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09183 unsigned char cmdstr[20];
09184
09185 if(debug)
09186 printf("Before bump: %s\n", myrpt->freq);
09187
09188 if(split_freq(mhz, decimals, myrpt->freq))
09189 return -1;
09190
09191 m = atoi(mhz);
09192 d = atoi(decimals);
09193
09194 d += (interval / 10);
09195 if(d < 0){
09196 m--;
09197 d += 100000;
09198 }
09199 else if(d >= 100000){
09200 m++;
09201 d -= 100000;
09202 }
09203
09204 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09205 if(debug)
09206 printf("Bump freq invalid\n");
09207 return -1;
09208 }
09209
09210 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09211
09212 if(debug)
09213 printf("After bump: %s\n", myrpt->freq);
09214
09215
09216
09217 cmdstr[0] = cmdstr[1] = 0xfe;
09218 cmdstr[2] = myrpt->p.civaddr;
09219 cmdstr[3] = 0xe0;
09220 cmdstr[4] = 0;
09221 cmdstr[5] = ((d % 10) << 4);
09222 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09223 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09224 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09225 cmdstr[9] = (m / 100);
09226 cmdstr[10] = 0xfd;
09227
09228 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09229 }
09230
09231
09232
09233
09234
09235
09236 static int setrem(struct rpt *myrpt)
09237 {
09238 char str[300];
09239 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09240 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09241 char *modes[] = {"FM","USB","LSB","AM"};
09242 int res = -1;
09243
09244 #if 0
09245 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09246 modes[(int)myrpt->remmode],
09247 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09248 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09249 myrpt->rxplon);
09250 #endif
09251 if (myrpt->p.archivedir)
09252 {
09253 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09254 modes[(int)myrpt->remmode],
09255 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09256 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09257 myrpt->rxplon);
09258 donodelog(myrpt,str);
09259 }
09260 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09261 {
09262 rpt_telemetry(myrpt,SETREMOTE,NULL);
09263 res = 0;
09264 }
09265 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09266 {
09267 rpt_telemetry(myrpt,SETREMOTE,NULL);
09268 res = 0;
09269 }
09270 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09271 {
09272 rpt_telemetry(myrpt,SETREMOTE,NULL);
09273 res = 0;
09274 }
09275 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09276 {
09277 res = setrbi_check(myrpt);
09278 if (!res)
09279 {
09280 rpt_telemetry(myrpt,SETREMOTE,NULL);
09281 res = 0;
09282 }
09283 }
09284 else if(ISRIG_RTX(myrpt->remoterig))
09285 {
09286 setrtx(myrpt);
09287 res = 0;
09288 }
09289 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09290 rpt_telemetry(myrpt,SETREMOTE,NULL);
09291 res = 0;
09292 }
09293 else
09294 res = 0;
09295
09296 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09297
09298 return res;
09299 }
09300
09301 static int closerem(struct rpt *myrpt)
09302 {
09303 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09304 return closerem_ft897(myrpt);
09305 else
09306 return 0;
09307 }
09308
09309
09310
09311
09312
09313 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09314 {
09315 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09316 return check_freq_ft897(m, d, defmode);
09317 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09318 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09319 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09320 return check_freq_rbi(m, d, defmode);
09321 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09322 return check_freq_kenwood(m, d, defmode);
09323 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09324 return check_freq_tm271(m, d, defmode);
09325 else if(ISRIG_RTX(myrpt->remoterig))
09326 return check_freq_rtx(m, d, defmode, myrpt);
09327 else
09328 return -1;
09329 }
09330
09331
09332
09333
09334
09335
09336 static char check_tx_freq(struct rpt *myrpt)
09337 {
09338 int i,rv=0;
09339 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09340 char radio_mhz_char[MAXREMSTR];
09341 char radio_decimals_char[MAXREMSTR];
09342 char limit_mhz_char[MAXREMSTR];
09343 char limit_decimals_char[MAXREMSTR];
09344 char limits[256];
09345 char *limit_ranges[40];
09346 struct ast_variable *limitlist;
09347
09348 if(debug > 3){
09349 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09350 }
09351
09352
09353
09354 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09355 if(debug > 3){
09356 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09357 }
09358 rv=1;
09359 return 1;
09360 }
09361
09362
09363 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09364
09365 if(!limitlist){
09366 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09367 rv=0;
09368 return 0;
09369 }
09370
09371 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09372 radio_mhz = atoi(radio_mhz_char);
09373 radio_decimals = decimals2int(radio_decimals_char);
09374
09375 if(debug > 3){
09376 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09377 }
09378
09379
09380
09381 for(;limitlist; limitlist=limitlist->next){
09382 if(!strcmp(limitlist->name, myrpt->loginlevel))
09383 break;
09384 }
09385
09386 if(!limitlist){
09387 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09388 rv=0;
09389 return 0;
09390 }
09391
09392 if(debug > 3){
09393 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09394 }
09395
09396
09397
09398 strncpy(limits, limitlist->value, 256);
09399 limits[255] = 0;
09400 finddelim(limits, limit_ranges, 40);
09401 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09402 char range[40];
09403 char *r,*s;
09404 strncpy(range, limit_ranges[i], 40);
09405 range[39] = 0;
09406 if(debug > 3)
09407 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09408
09409 r = strchr(range, '-');
09410 if(!r){
09411 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09412 rv=0;
09413 break;
09414 }
09415 *r++ = 0;
09416 s = eatwhite(range);
09417 r = eatwhite(r);
09418 split_freq(limit_mhz_char, limit_decimals_char, s);
09419 llimit_mhz = atoi(limit_mhz_char);
09420 llimit_decimals = decimals2int(limit_decimals_char);
09421 split_freq(limit_mhz_char, limit_decimals_char, r);
09422 ulimit_mhz = atoi(limit_mhz_char);
09423 ulimit_decimals = decimals2int(limit_decimals_char);
09424
09425 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09426 if(radio_mhz == llimit_mhz){
09427 if(radio_decimals >= llimit_decimals){
09428 if(llimit_mhz == ulimit_mhz){
09429 if(radio_decimals <= ulimit_decimals){
09430 rv=1;
09431 break;
09432 }
09433 else{
09434 if(debug > 3)
09435 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09436 rv=0;
09437 break;
09438 }
09439 }
09440 else{
09441 rv=1;
09442 break;
09443 }
09444 }
09445 else{
09446 if(debug > 3)
09447 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09448 rv=0;
09449 break;
09450 }
09451 }
09452 else if(radio_mhz == ulimit_mhz){
09453 if(radio_decimals <= ulimit_decimals){
09454 if(debug > 3)
09455 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09456 rv=1;
09457 break;
09458 }
09459 else{
09460 if(debug > 3)
09461 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09462 rv=0;
09463 break;
09464 }
09465 }
09466 else
09467 if(debug > 3)
09468 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09469 rv=1;
09470 break;
09471 }
09472 }
09473 if(debug > 3)
09474 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09475
09476 return rv;
09477 }
09478
09479
09480
09481
09482
09483
09484 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09485 {
09486 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09487 return multimode_bump_freq_ft897(myrpt, interval);
09488 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09489 return multimode_bump_freq_ic706(myrpt, interval);
09490 else
09491 return -1;
09492 }
09493
09494
09495
09496
09497
09498
09499 static void stop_scan(struct rpt *myrpt)
09500 {
09501 myrpt->hfscanstop = 1;
09502 rpt_telemetry(myrpt,SCAN,0);
09503 }
09504
09505
09506
09507
09508
09509
09510 static int service_scan(struct rpt *myrpt)
09511 {
09512 int res, interval;
09513 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09514
09515 switch(myrpt->hfscanmode){
09516
09517 case HF_SCAN_DOWN_SLOW:
09518 interval = -10;
09519 break;
09520
09521 case HF_SCAN_DOWN_QUICK:
09522 interval = -50;
09523 break;
09524
09525 case HF_SCAN_DOWN_FAST:
09526 interval = -200;
09527 break;
09528
09529 case HF_SCAN_UP_SLOW:
09530 interval = 10;
09531 break;
09532
09533 case HF_SCAN_UP_QUICK:
09534 interval = 50;
09535 break;
09536
09537 case HF_SCAN_UP_FAST:
09538 interval = 200;
09539 break;
09540
09541 default:
09542 myrpt->hfscanmode = 0;
09543 return -1;
09544 }
09545
09546 res = split_freq(mhz, decimals, myrpt->freq);
09547
09548 if(!res){
09549 k100 =decimals[0];
09550 k10 = decimals[1];
09551 res = multimode_bump_freq(myrpt, interval);
09552 }
09553
09554 if(!res)
09555 res = split_freq(mhz, decimals, myrpt->freq);
09556
09557
09558 if(res){
09559 myrpt->hfscanmode = 0;
09560 myrpt->hfscanstatus = -2;
09561 return -1;
09562 }
09563
09564
09565 if(k10 != decimals[1]){
09566 int myhund = (interval < 0) ? k100 : decimals[0];
09567 int myten = (interval < 0) ? k10 : decimals[1];
09568 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09569 } else myrpt->hfscanstatus = 0;
09570 return res;
09571
09572 }
09573
09574
09575
09576 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09577 {
09578 int res=0;
09579 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09580 res = retreive_memory(myrpt, digitbuf);
09581 if(!res)res=setrem(myrpt);
09582 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09583 return res;
09584 }
09585
09586
09587
09588
09589 static int channel_steer(struct rpt *myrpt, char *data)
09590 {
09591 int res=0;
09592
09593 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09594 if (!myrpt->remoterig) return(0);
09595 if(data<=0)
09596 {
09597 res=-1;
09598 }
09599 else
09600 {
09601 myrpt->nowchan=strtod(data,NULL);
09602 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09603 {
09604 char string[16];
09605 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09606 send_usb_txt(myrpt,string);
09607 }
09608 else
09609 {
09610 if(get_mem_set(myrpt, data))res=-1;
09611 }
09612 }
09613 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09614 return res;
09615 }
09616
09617
09618 static int channel_revert(struct rpt *myrpt)
09619 {
09620 int res=0;
09621 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09622 if (!myrpt->remoterig) return(0);
09623 if(myrpt->nowchan!=myrpt->waschan)
09624 {
09625 char data[8];
09626 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09627 sprintf(data,"%02d",myrpt->waschan);
09628 myrpt->nowchan=myrpt->waschan;
09629 channel_steer(myrpt,data);
09630 res=1;
09631 }
09632 return(res);
09633 }
09634
09635
09636
09637
09638 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09639 {
09640 char *s,*s1,*s2;
09641 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09642 intptr_t p;
09643 char multimode = 0;
09644 char oc,*cp,*cp1,*cp2;
09645 char tmp[20], freq[20] = "", savestr[20] = "";
09646 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09647
09648 if(debug > 6) {
09649 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09650 }
09651
09652 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09653 return DC_ERROR;
09654
09655 p = myatoi(param);
09656
09657 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09658 (!myrpt->loginlevel[0])) return DC_ERROR;
09659 multimode = multimode_capable(myrpt);
09660
09661 switch(p){
09662
09663 case 1:
09664 if(strlen(digitbuf) < 2)
09665 break;
09666
09667 for(i = 0 ; i < 2 ; i++){
09668 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09669 return DC_ERROR;
09670 }
09671 r=get_mem_set(myrpt, digitbuf);
09672 if (r < 0){
09673 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09674 return DC_COMPLETE;
09675 }
09676 else if (r > 0){
09677 return DC_ERROR;
09678 }
09679 return DC_COMPLETE;
09680
09681 case 2:
09682
09683
09684 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09685 if(digitbuf[i] == '*'){
09686 j++;
09687 continue;
09688 }
09689 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09690 goto invalid_freq;
09691 else{
09692 if(j == 0)
09693 l++;
09694 if(j == 1)
09695 k++;
09696 }
09697 }
09698
09699 i = strlen(digitbuf) - 1;
09700 if(multimode){
09701 if((j > 2) || (l > 3) || (k > 6))
09702 goto invalid_freq;
09703 }
09704 else{
09705 if((j > 2) || (l > 4) || (k > 3))
09706 goto invalid_freq;
09707 }
09708
09709
09710
09711 if(j < 2)
09712 break;
09713
09714
09715
09716 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09717
09718 s = tmp;
09719 s1 = strsep(&s, "*");
09720 s2 = strsep(&s,"*");
09721 ls2 = strlen(s2);
09722
09723 switch(ls2){
09724 case 1:
09725 ht = 0;
09726 k = 100 * atoi(s2);
09727 break;
09728
09729 case 2:
09730 ht = 0;
09731 k = 10 * atoi(s2);
09732 break;
09733
09734 case 3:
09735 if(!multimode){
09736 if((s2[2] != '0')&&(s2[2] != '5'))
09737 goto invalid_freq;
09738 }
09739 ht = 0;
09740 k = atoi(s2);
09741 break;
09742 case 4:
09743 k = atoi(s2)/10;
09744 ht = 10 * (atoi(s2+(ls2-1)));
09745 break;
09746
09747 case 5:
09748 k = atoi(s2)/100;
09749 ht = (atoi(s2+(ls2-2)));
09750 break;
09751
09752 default:
09753 goto invalid_freq;
09754 }
09755
09756
09757
09758 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09759
09760 if(debug)
09761 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09762
09763 split_freq(mhz, decimals, freq);
09764 m = atoi(mhz);
09765 d = atoi(decimals);
09766
09767 if(check_freq(myrpt, m, d, &defmode))
09768 goto invalid_freq;
09769
09770
09771 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09772 break;
09773
09774
09775 offset = REM_SIMPLEX;
09776
09777 if(defmode == REM_MODE_FM){
09778 oc = *s;
09779
09780 if (oc){
09781 switch(oc){
09782 case '1':
09783 offset = REM_MINUS;
09784 break;
09785
09786 case '2':
09787 offset = REM_SIMPLEX;
09788 break;
09789
09790 case '3':
09791 offset = REM_PLUS;
09792 break;
09793
09794 default:
09795 goto invalid_freq;
09796 }
09797 }
09798 }
09799 offsave = myrpt->offset;
09800 modesave = myrpt->remmode;
09801 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09802 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09803 myrpt->offset = offset;
09804 myrpt->remmode = defmode;
09805
09806 if (setrem(myrpt) == -1){
09807 myrpt->offset = offsave;
09808 myrpt->remmode = modesave;
09809 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09810 goto invalid_freq;
09811 }
09812
09813 return DC_COMPLETE;
09814
09815 invalid_freq:
09816 rpt_telemetry(myrpt,INVFREQ,NULL);
09817 return DC_ERROR;
09818
09819 case 3:
09820 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09821 if(digitbuf[i] == '*'){
09822 j++;
09823 continue;
09824 }
09825 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09826 return DC_ERROR;
09827 else{
09828 if(j)
09829 l++;
09830 else
09831 k++;
09832 }
09833 }
09834 if((j > 1) || (k > 3) || (l > 1))
09835 return DC_ERROR;
09836 i = strlen(digitbuf) - 1;
09837 if((j != 1) || (k < 2)|| (l != 1))
09838 break;
09839 if(debug)
09840 printf("PL digits entered %s\n", digitbuf);
09841
09842 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09843
09844 s = strchr(tmp,'*');
09845 if(s)
09846 *s = '.';
09847 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09848 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09849 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09850 {
09851 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09852 }
09853 if (setrem(myrpt) == -1){
09854 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09855 return DC_ERROR;
09856 }
09857 return DC_COMPLETE;
09858
09859 case 4:
09860
09861 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09862 return DC_ERROR;
09863
09864
09865
09866
09867
09868 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09869 {
09870 if(debug)
09871 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09872 return DC_ERROR;
09873 }
09874 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09875 if(digitbuf[i] == '*'){
09876 j++;
09877 continue;
09878 }
09879 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09880 return DC_ERROR;
09881 else{
09882 if(j)
09883 l++;
09884 else
09885 k++;
09886 }
09887 }
09888 if((j > 1) || (k > 3) || (l > 1))
09889 return DC_ERROR;
09890 i = strlen(digitbuf) - 1;
09891 if((j != 1) || (k < 2)|| (l != 1))
09892 break;
09893 if(debug)
09894 printf("PL digits entered %s\n", digitbuf);
09895
09896 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09897
09898 s = strchr(tmp,'*');
09899 if(s)
09900 *s = '.';
09901 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09902 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09903
09904 if (setrem(myrpt) == -1){
09905 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09906 return DC_ERROR;
09907 }
09908 return DC_COMPLETE;
09909
09910
09911 case 6:
09912 if(strlen(digitbuf) < 1)
09913 break;
09914
09915 if(!multimode)
09916 return DC_ERROR;
09917
09918 switch(*digitbuf){
09919 case '1':
09920 split_freq(mhz, decimals, myrpt->freq);
09921 m=atoi(mhz);
09922 if(m < 29)
09923 return DC_ERROR;
09924 myrpt->remmode = REM_MODE_FM;
09925
09926 rpt_telemetry(myrpt,REMMODE,NULL);
09927 break;
09928
09929 case '2':
09930 myrpt->remmode = REM_MODE_USB;
09931 rpt_telemetry(myrpt,REMMODE,NULL);
09932 break;
09933
09934 case '3':
09935 myrpt->remmode = REM_MODE_LSB;
09936 rpt_telemetry(myrpt,REMMODE,NULL);
09937 break;
09938
09939 case '4':
09940 myrpt->remmode = REM_MODE_AM;
09941 rpt_telemetry(myrpt,REMMODE,NULL);
09942 break;
09943
09944 default:
09945 return DC_ERROR;
09946 }
09947
09948 if(setrem(myrpt))
09949 return DC_ERROR;
09950 return DC_COMPLETEQUIET;
09951 case 99:
09952
09953 if (myrpt->loginlevel[0])
09954 return DC_ERROR;
09955 *myrpt->loginuser = 0;
09956 myrpt->loginlevel[0] = 0;
09957 cp = ast_strdup(param);
09958 cp1 = strchr(cp,',');
09959 ast_mutex_lock(&myrpt->lock);
09960 if (cp1)
09961 {
09962 *cp1 = 0;
09963 cp2 = strchr(cp1 + 1,',');
09964 if (cp2)
09965 {
09966 *cp2 = 0;
09967 strncpy(myrpt->loginlevel,cp2 + 1,
09968 sizeof(myrpt->loginlevel) - 1);
09969 }
09970 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09971 ast_mutex_unlock(&myrpt->lock);
09972 if (myrpt->p.archivedir)
09973 {
09974 char str[100];
09975
09976 sprintf(str,"LOGIN,%s,%s",
09977 myrpt->loginuser,myrpt->loginlevel);
09978 donodelog(myrpt,str);
09979 }
09980 if (debug)
09981 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09982 rpt_telemetry(myrpt,REMLOGIN,NULL);
09983 }
09984 ast_free(cp);
09985 return DC_COMPLETEQUIET;
09986 case 100:
09987 myrpt->rxplon = 0;
09988 setrem(myrpt);
09989 rpt_telemetry(myrpt,REMXXX,(void *)p);
09990 return DC_COMPLETEQUIET;
09991 case 101:
09992 myrpt->rxplon = 1;
09993 setrem(myrpt);
09994 rpt_telemetry(myrpt,REMXXX,(void *)p);
09995 return DC_COMPLETEQUIET;
09996 case 102:
09997 myrpt->txplon = 0;
09998 setrem(myrpt);
09999 rpt_telemetry(myrpt,REMXXX,(void *)p);
10000 return DC_COMPLETEQUIET;
10001 case 103:
10002 myrpt->txplon = 1;
10003 setrem(myrpt);
10004 rpt_telemetry(myrpt,REMXXX,(void *)p);
10005 return DC_COMPLETEQUIET;
10006 case 104:
10007 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10008 return DC_ERROR;
10009 myrpt->powerlevel = REM_LOWPWR;
10010 setrem(myrpt);
10011 rpt_telemetry(myrpt,REMXXX,(void *)p);
10012 return DC_COMPLETEQUIET;
10013 case 105:
10014 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10015 return DC_ERROR;
10016 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10017 myrpt->powerlevel = REM_MEDPWR;
10018 setrem(myrpt);
10019 rpt_telemetry(myrpt,REMXXX,(void *)p);
10020 return DC_COMPLETEQUIET;
10021 case 106:
10022 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10023 return DC_ERROR;
10024 myrpt->powerlevel = REM_HIPWR;
10025 setrem(myrpt);
10026 rpt_telemetry(myrpt,REMXXX,(void *)p);
10027 return DC_COMPLETEQUIET;
10028 case 107:
10029 multimode_bump_freq(myrpt, -20);
10030 return DC_COMPLETE;
10031 case 108:
10032 multimode_bump_freq(myrpt, -100);
10033 return DC_COMPLETE;
10034 case 109:
10035 multimode_bump_freq(myrpt, -500);
10036 return DC_COMPLETE;
10037 case 110:
10038 multimode_bump_freq(myrpt, 20);
10039 return DC_COMPLETE;
10040 case 111:
10041 multimode_bump_freq(myrpt, 100);
10042 return DC_COMPLETE;
10043 case 112:
10044 multimode_bump_freq(myrpt, 500);
10045 return DC_COMPLETE;
10046 case 113:
10047 myrpt->scantimer = REM_SCANTIME;
10048 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10049 rpt_telemetry(myrpt,REMXXX,(void *)p);
10050 return DC_COMPLETEQUIET;
10051 case 114:
10052 myrpt->scantimer = REM_SCANTIME;
10053 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10054 rpt_telemetry(myrpt,REMXXX,(void *)p);
10055 return DC_COMPLETEQUIET;
10056 case 115:
10057 myrpt->scantimer = REM_SCANTIME;
10058 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10059 rpt_telemetry(myrpt,REMXXX,(void *)p);
10060 return DC_COMPLETEQUIET;
10061 case 116:
10062 myrpt->scantimer = REM_SCANTIME;
10063 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10064 rpt_telemetry(myrpt,REMXXX,(void *)p);
10065 return DC_COMPLETEQUIET;
10066 case 117:
10067 myrpt->scantimer = REM_SCANTIME;
10068 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10069 rpt_telemetry(myrpt,REMXXX,(void *)p);
10070 return DC_COMPLETEQUIET;
10071 case 118:
10072 myrpt->scantimer = REM_SCANTIME;
10073 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10074 rpt_telemetry(myrpt,REMXXX,(void *)p);
10075 return DC_COMPLETEQUIET;
10076 case 119:
10077 if(debug > 3)
10078 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10079
10080 if((!myrpt->tunerequest) &&
10081 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10082 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10083 myrpt->remotetx = 0;
10084 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10085 myrpt->tunerequest = 1;
10086 rpt_telemetry(myrpt,TUNE,NULL);
10087 return DC_COMPLETEQUIET;
10088 }
10089 return DC_ERROR;
10090 case 5:
10091 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10092 return DC_COMPLETEQUIET;
10093 case 140:
10094 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10095 return DC_COMPLETEQUIET;
10096 case 200:
10097 case 201:
10098 case 202:
10099 case 203:
10100 case 204:
10101 case 205:
10102 case 206:
10103 case 207:
10104 case 208:
10105 case 209:
10106 case 210:
10107 case 211:
10108 case 212:
10109 case 213:
10110 case 214:
10111 case 215:
10112 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10113 return DC_COMPLETEQUIET;
10114 default:
10115 break;
10116 }
10117 return DC_INDETERMINATE;
10118 }
10119
10120
10121 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10122 {
10123 time_t now;
10124 int ret,res = 0,src;
10125
10126 if(debug > 6)
10127 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10128
10129 time(&myrpt->last_activity_time);
10130
10131 if(myrpt->hfscanmode){
10132 stop_scan(myrpt);
10133 return 0;
10134 }
10135
10136 time(&now);
10137
10138 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10139 {
10140 myrpt->dtmfidx = -1;
10141 myrpt->dtmfbuf[0] = 0;
10142 myrpt->dtmf_time_rem = 0;
10143 }
10144
10145 if (myrpt->dtmfidx == -1)
10146 {
10147
10148 if (c != myrpt->p.funcchar)
10149 {
10150 if (!myrpt->p.propagate_dtmf)
10151 {
10152 rpt_mutex_lock(&myrpt->lock);
10153 do_dtmf_local(myrpt,c);
10154 rpt_mutex_unlock(&myrpt->lock);
10155 }
10156 return 0;
10157 }
10158 myrpt->dtmfidx = 0;
10159 myrpt->dtmfbuf[0] = 0;
10160 myrpt->dtmf_time_rem = now;
10161 return 0;
10162 }
10163
10164 if (myrpt->dtmfidx >= MAXDTMF)
10165 {
10166 myrpt->dtmfidx = 0;
10167 myrpt->dtmfbuf[0] = 0;
10168 myrpt->dtmf_time_rem = now;
10169 }
10170 if (c == myrpt->p.funcchar)
10171 {
10172
10173 if ((myrpt->dtmfidx < 1) ||
10174 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10175 {
10176 myrpt->dtmfidx = 0;
10177 myrpt->dtmfbuf[0] = 0;
10178 myrpt->dtmf_time_rem = now;
10179 return 0;
10180 }
10181 }
10182 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10183 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10184 myrpt->dtmf_time_rem = now;
10185
10186
10187 src = SOURCE_RMT;
10188 if (phonemode == 2) src = SOURCE_DPHONE;
10189 else if (phonemode) src = SOURCE_PHONE;
10190 else if (phonemode == 4) src = SOURCE_ALT;
10191 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10192
10193 switch(ret){
10194
10195 case DC_INDETERMINATE:
10196 res = 0;
10197 break;
10198
10199 case DC_DOKEY:
10200 if (keyed) *keyed = 1;
10201 res = 0;
10202 break;
10203
10204 case DC_REQ_FLUSH:
10205 myrpt->dtmfidx = 0;
10206 myrpt->dtmfbuf[0] = 0;
10207 res = 0;
10208 break;
10209
10210
10211 case DC_COMPLETE:
10212 res = 1;
10213 case DC_COMPLETEQUIET:
10214 myrpt->totalexecdcommands++;
10215 myrpt->dailyexecdcommands++;
10216 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10217 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10218 myrpt->dtmfbuf[0] = 0;
10219 myrpt->dtmfidx = -1;
10220 myrpt->dtmf_time_rem = 0;
10221 break;
10222
10223 case DC_ERROR:
10224 default:
10225 myrpt->dtmfbuf[0] = 0;
10226 myrpt->dtmfidx = -1;
10227 myrpt->dtmf_time_rem = 0;
10228 res = 0;
10229 break;
10230 }
10231
10232 return res;
10233 }
10234
10235 static int handle_remote_data(struct rpt *myrpt, char *str)
10236 {
10237 char tmp[300],cmd[300],dest[300],src[300],c;
10238 int seq,res;
10239
10240
10241 strncpy(tmp,str,sizeof(tmp) - 1);
10242 if (!strcmp(tmp,discstr)) return 0;
10243 if (!strcmp(tmp,newkeystr))
10244 {
10245 myrpt->newkey = 1;
10246 return 0;
10247 }
10248
10249 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10250 if (tmp[0] == 'I')
10251 {
10252 if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
10253 {
10254 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10255 return 0;
10256 }
10257 mdc1200_notify(myrpt,src,seq);
10258 return 0;
10259 }
10260 #endif
10261 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
10262 {
10263 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10264 return 0;
10265 }
10266 if (strcmp(cmd,"D"))
10267 {
10268 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10269 return 0;
10270 }
10271
10272 if (strcmp(dest,myrpt->name)) return 0;
10273 if (myrpt->p.archivedir)
10274 {
10275 char dtmfstr[100];
10276
10277 sprintf(dtmfstr,"DTMF,%c",c);
10278 donodelog(myrpt,dtmfstr);
10279 }
10280 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10281 if (!c) return(0);
10282 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10283 if (res != 1)
10284 return res;
10285 rpt_telemetry(myrpt,COMPLETE,NULL);
10286 return 0;
10287 }
10288
10289 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10290 {
10291 int res;
10292
10293
10294 if(phonemode == 3)
10295 {
10296 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10297 {
10298 *keyed = 0;
10299 return 0;
10300 }
10301 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10302 {
10303 *keyed = 1;
10304 return 0;
10305 }
10306 }
10307 else
10308 {
10309
10310 if (keyed && *keyed && (c == myrpt->p.endchar))
10311 {
10312 *keyed = 0;
10313 return DC_INDETERMINATE;
10314 }
10315 }
10316 if (myrpt->p.archivedir)
10317 {
10318 char str[100];
10319
10320 sprintf(str,"DTMF(P),%c",c);
10321 donodelog(myrpt,str);
10322 }
10323 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10324 if (res != 1)
10325 return res;
10326 rpt_telemetry(myrpt,COMPLETE,NULL);
10327 return 0;
10328 }
10329
10330 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10331 {
10332 char *val, *s, *s1, *s2, *tele;
10333 char tmp[300], deststr[300] = "";
10334 char sx[320],*sy;
10335
10336
10337 val = node_lookup(myrpt,l->name);
10338 if (!val)
10339 {
10340 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10341 return -1;
10342 }
10343
10344 rpt_mutex_lock(&myrpt->lock);
10345
10346 remque((struct qelem *) l);
10347 rpt_mutex_unlock(&myrpt->lock);
10348 strncpy(tmp,val,sizeof(tmp) - 1);
10349 s = tmp;
10350 s1 = strsep(&s,",");
10351 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10352 {
10353 sy = strchr(s1,'/');
10354 *sy = 0;
10355 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10356 s1 = sx;
10357 }
10358 s2 = strsep(&s,",");
10359 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10360 tele = strchr(deststr, '/');
10361 if (!tele) {
10362 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10363 return -1;
10364 }
10365 *tele++ = 0;
10366 l->elaptime = 0;
10367 l->connecttime = 0;
10368 l->thisconnected = 0;
10369 l->newkey = 0;
10370 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
10371 if (l->chan){
10372 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10373 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10374 #ifndef NEW_ASTERISK
10375 l->chan->whentohangup = 0;
10376 #endif
10377 l->chan->appl = "Apprpt";
10378 l->chan->data = "(Remote Rx)";
10379 if (option_verbose > 2)
10380 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10381 deststr, tele, l->chan->name);
10382 if(l->chan->cid.cid_num)
10383 ast_free(l->chan->cid.cid_num);
10384 l->chan->cid.cid_num = ast_strdup(myrpt->name);
10385 ast_call(l->chan,tele,999);
10386
10387 }
10388 else
10389 {
10390 if (option_verbose > 2)
10391 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10392 deststr,tele,l->chan->name);
10393 return -1;
10394 }
10395 rpt_mutex_lock(&myrpt->lock);
10396
10397 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10398 rpt_mutex_unlock(&myrpt->lock);
10399 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10400 if (!l->phonemode) send_newkey(l->chan);
10401 return 0;
10402 }
10403
10404
10405 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10406 {
10407 int res;
10408 pthread_attr_t attr;
10409 char cmd[MAXDTMF+1] = "",c;
10410
10411
10412 c = c_in & 0x7f;
10413 if (myrpt->p.archivedir)
10414 {
10415 char str[100];
10416
10417 sprintf(str,"DTMF,MAIN,%c",c);
10418 donodelog(myrpt,str);
10419 }
10420 if (c == myrpt->p.endchar)
10421 {
10422
10423 if (myrpt->p.simple && myrpt->callmode)
10424 {
10425 if(debug)
10426 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10427 rpt_mutex_lock(&myrpt->lock);
10428 myrpt->callmode = 0;
10429 myrpt->macropatch=0;
10430 channel_revert(myrpt);
10431 rpt_mutex_unlock(&myrpt->lock);
10432 rpt_telemetry(myrpt,TERM,NULL);
10433 return;
10434 }
10435 rpt_mutex_lock(&myrpt->lock);
10436 myrpt->stopgen = 1;
10437 if (myrpt->cmdnode[0])
10438 {
10439 myrpt->cmdnode[0] = 0;
10440 myrpt->dtmfidx = -1;
10441 myrpt->dtmfbuf[0] = 0;
10442 rpt_mutex_unlock(&myrpt->lock);
10443 rpt_telemetry(myrpt,COMPLETE,NULL);
10444 return;
10445 }
10446 else if(!myrpt->inpadtest)
10447 {
10448 rpt_mutex_unlock(&myrpt->lock);
10449 if (myrpt->p.propagate_phonedtmf)
10450 do_dtmf_phone(myrpt,NULL,c);
10451 return;
10452 }
10453 else
10454 rpt_mutex_unlock(&myrpt->lock);
10455 }
10456 rpt_mutex_lock(&myrpt->lock);
10457 if (myrpt->cmdnode[0])
10458 {
10459 rpt_mutex_unlock(&myrpt->lock);
10460 send_link_dtmf(myrpt,c);
10461 return;
10462 }
10463 if (!myrpt->p.simple)
10464 {
10465 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10466 {
10467 myrpt->dtmfidx = 0;
10468 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10469 rpt_mutex_unlock(&myrpt->lock);
10470 time(&myrpt->dtmf_time);
10471 return;
10472 }
10473 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10474 {
10475 time(&myrpt->dtmf_time);
10476
10477 if (myrpt->dtmfidx < MAXDTMF)
10478 {
10479 int src;
10480
10481 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10482 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10483
10484 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10485
10486 rpt_mutex_unlock(&myrpt->lock);
10487 src = SOURCE_RPT;
10488 if (c_in & 0x80) src = SOURCE_ALT;
10489 res = collect_function_digits(myrpt, cmd, src, NULL);
10490 rpt_mutex_lock(&myrpt->lock);
10491 switch(res){
10492 case DC_INDETERMINATE:
10493 break;
10494 case DC_REQ_FLUSH:
10495 myrpt->dtmfidx = 0;
10496 myrpt->dtmfbuf[0] = 0;
10497 break;
10498 case DC_COMPLETE:
10499 case DC_COMPLETEQUIET:
10500 myrpt->totalexecdcommands++;
10501 myrpt->dailyexecdcommands++;
10502 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10503 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10504 myrpt->dtmfbuf[0] = 0;
10505 myrpt->dtmfidx = -1;
10506 myrpt->dtmf_time = 0;
10507 break;
10508
10509 case DC_ERROR:
10510 default:
10511 myrpt->dtmfbuf[0] = 0;
10512 myrpt->dtmfidx = -1;
10513 myrpt->dtmf_time = 0;
10514 break;
10515 }
10516 if(res != DC_INDETERMINATE) {
10517 rpt_mutex_unlock(&myrpt->lock);
10518 return;
10519 }
10520 }
10521 }
10522 }
10523 else
10524 {
10525 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10526 {
10527 myrpt->callmode = 1;
10528 myrpt->patchnoct = 0;
10529 myrpt->patchquiet = 0;
10530 myrpt->patchfarenddisconnect = 0;
10531 myrpt->patchdialtime = 0;
10532 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10533 myrpt->cidx = 0;
10534 myrpt->exten[myrpt->cidx] = 0;
10535 rpt_mutex_unlock(&myrpt->lock);
10536 pthread_attr_init(&attr);
10537 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10538 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10539 return;
10540 }
10541 }
10542 if (myrpt->callmode == 1)
10543 {
10544 myrpt->exten[myrpt->cidx++] = c;
10545 myrpt->exten[myrpt->cidx] = 0;
10546
10547 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10548 {
10549
10550 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10551 myrpt->exten,1,NULL))
10552 {
10553 myrpt->callmode = 2;
10554 rpt_mutex_unlock(&myrpt->lock);
10555 if(!myrpt->patchquiet)
10556 rpt_telemetry(myrpt,PROC,NULL);
10557 return;
10558 }
10559 else
10560 {
10561 myrpt->calldigittimer = 1;
10562 }
10563 }
10564
10565 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10566 {
10567
10568 myrpt->callmode = 4;
10569 }
10570 rpt_mutex_unlock(&myrpt->lock);
10571 return;
10572 }
10573 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10574 {
10575 myrpt->mydtmf = c;
10576 }
10577 rpt_mutex_unlock(&myrpt->lock);
10578 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10579 do_dtmf_phone(myrpt,NULL,c);
10580 return;
10581 }
10582
10583
10584
10585
10586 static void queue_id(struct rpt *myrpt)
10587 {
10588 if(myrpt->p.idtime){
10589 myrpt->mustid = myrpt->tailid = 0;
10590 myrpt->idtimer = myrpt->p.idtime;
10591 rpt_mutex_unlock(&myrpt->lock);
10592 rpt_telemetry(myrpt,ID,NULL);
10593 rpt_mutex_lock(&myrpt->lock);
10594 }
10595 }
10596
10597
10598
10599
10600 static void do_scheduler(struct rpt *myrpt)
10601 {
10602 int i,res;
10603
10604 #ifdef NEW_ASTERISK
10605 struct ast_tm tmnow;
10606 #else
10607 struct tm tmnow;
10608 #endif
10609 struct ast_variable *skedlist;
10610 char *strs[5],*vp,*val,value[100];
10611
10612 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10613
10614 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10615 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10616
10617
10618
10619 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10620 return;
10621
10622 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10623
10624
10625
10626 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10627 myrpt->dailykeyups = 0;
10628 myrpt->dailytxtime = 0;
10629 myrpt->dailykerchunks = 0;
10630 myrpt->dailyexecdcommands = 0;
10631 }
10632
10633 if(tmnow.tm_sec != 0)
10634 return;
10635
10636
10637
10638
10639
10640
10641 if (myrpt->remote)
10642 return;
10643
10644
10645
10646 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10647 if(debug > 6)
10648 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10649 return;
10650 }
10651
10652 if(!myrpt->p.skedstanzaname){
10653 if(debug > 6)
10654 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10655 return;
10656 }
10657
10658
10659 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10660
10661 if(debug > 6){
10662 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10663 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10664 }
10665
10666 for(; skedlist; skedlist = skedlist->next){
10667 if(debug > 6)
10668 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10669 strncpy(value,skedlist->value,99);
10670 value[99] = 0;
10671
10672 for( i = 0, vp = value ; i < 5; i++){
10673 if(!*vp)
10674 break;
10675 while((*vp == ' ') || (*vp == 0x09))
10676 vp++;
10677 strs[i] = vp;
10678 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10679 vp++;
10680 if(*vp)
10681 *vp++ = 0;
10682 }
10683 if(debug > 6)
10684 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10685 strs[0], strs[1], strs[2], strs[3], strs[4]);
10686 if(i == 5){
10687 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10688 continue;
10689 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10690 continue;
10691 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10692 continue;
10693 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10694 continue;
10695 if(atoi(strs[4]) == 7)
10696 strs[4] = "0";
10697 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10698 continue;
10699 if(debug)
10700 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10701 if(atoi(skedlist->name) == 0)
10702 return;
10703 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10704 if (!val){
10705 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10706 return;
10707 }
10708 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10709 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10710 skedlist->name);
10711 return;
10712 }
10713 myrpt->macrotimer = MACROTIME;
10714 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10715 }
10716 else{
10717 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10718 skedlist->name, skedlist->value);
10719 }
10720 }
10721
10722 }
10723
10724
10725 static void *rpt(void *this)
10726 {
10727 struct rpt *myrpt = (struct rpt *)this;
10728 char *tele,*idtalkover,c,myfirst,*p;
10729 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10730 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10731 struct ast_channel *who;
10732 struct dahdi_confinfo ci;
10733 time_t t;
10734 struct rpt_link *l,*m;
10735 struct rpt_tele *telem;
10736 char tmpstr[300],lstr[MAXLINKLIST];
10737
10738
10739 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10740 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10741 mkdir(tmpstr,0600);
10742 rpt_mutex_lock(&myrpt->lock);
10743
10744 telem = myrpt->tele.next;
10745 while(telem != &myrpt->tele)
10746 {
10747 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10748 telem = telem->next;
10749 }
10750 rpt_mutex_unlock(&myrpt->lock);
10751
10752 for(i = 0; i < nrpts; i++)
10753 {
10754 if (&rpt_vars[i] == myrpt)
10755 {
10756 load_rpt_vars(i,0);
10757 break;
10758 }
10759 }
10760
10761 rpt_mutex_lock(&myrpt->lock);
10762 while(myrpt->xlink)
10763 {
10764 myrpt->xlink = 3;
10765 rpt_mutex_unlock(&myrpt->lock);
10766 usleep(100000);
10767 rpt_mutex_lock(&myrpt->lock);
10768 }
10769 #ifdef HAVE_IOPERM
10770 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10771 (ioperm(myrpt->p.iobase,1,1) == -1))
10772 {
10773 rpt_mutex_unlock(&myrpt->lock);
10774 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10775 myrpt->rpt_thread = AST_PTHREADT_STOP;
10776 pthread_exit(NULL);
10777 }
10778 #endif
10779 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10780 tele = strchr(tmpstr,'/');
10781 if (!tele)
10782 {
10783 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10784 rpt_mutex_unlock(&myrpt->lock);
10785 myrpt->rpt_thread = AST_PTHREADT_STOP;
10786 pthread_exit(NULL);
10787 }
10788 *tele++ = 0;
10789 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10790 myrpt->dahdirxchannel = NULL;
10791 if (!strcasecmp(tmpstr,"DAHDI"))
10792 myrpt->dahdirxchannel = myrpt->rxchannel;
10793 if (myrpt->rxchannel)
10794 {
10795 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10796 {
10797 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10798 rpt_mutex_unlock(&myrpt->lock);
10799 ast_hangup(myrpt->rxchannel);
10800 myrpt->rpt_thread = AST_PTHREADT_STOP;
10801 pthread_exit(NULL);
10802 }
10803 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10804 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10805 #ifdef AST_CDR_FLAG_POST_DISABLED
10806 if (myrpt->rxchannel->cdr)
10807 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10808 #endif
10809 #ifndef NEW_ASTERISK
10810 myrpt->rxchannel->whentohangup = 0;
10811 #endif
10812 myrpt->rxchannel->appl = "Apprpt";
10813 myrpt->rxchannel->data = "(Repeater Rx)";
10814 if (option_verbose > 2)
10815 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10816 tmpstr,tele,myrpt->rxchannel->name);
10817 ast_call(myrpt->rxchannel,tele,999);
10818 if (myrpt->rxchannel->_state != AST_STATE_UP)
10819 {
10820 rpt_mutex_unlock(&myrpt->lock);
10821 ast_hangup(myrpt->rxchannel);
10822 myrpt->rpt_thread = AST_PTHREADT_STOP;
10823 pthread_exit(NULL);
10824 }
10825 }
10826 else
10827 {
10828 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10829 rpt_mutex_unlock(&myrpt->lock);
10830 myrpt->rpt_thread = AST_PTHREADT_STOP;
10831 pthread_exit(NULL);
10832 }
10833 myrpt->dahditxchannel = NULL;
10834 if (myrpt->txchanname)
10835 {
10836 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10837 tele = strchr(tmpstr,'/');
10838 if (!tele)
10839 {
10840 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10841 rpt_mutex_unlock(&myrpt->lock);
10842 ast_hangup(myrpt->rxchannel);
10843 myrpt->rpt_thread = AST_PTHREADT_STOP;
10844 pthread_exit(NULL);
10845 }
10846 *tele++ = 0;
10847 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10848 if (!strcasecmp(tmpstr,"DAHDI"))
10849 myrpt->dahditxchannel = myrpt->txchannel;
10850 if (myrpt->txchannel)
10851 {
10852 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10853 {
10854 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10855 rpt_mutex_unlock(&myrpt->lock);
10856 ast_hangup(myrpt->txchannel);
10857 ast_hangup(myrpt->rxchannel);
10858 myrpt->rpt_thread = AST_PTHREADT_STOP;
10859 pthread_exit(NULL);
10860 }
10861 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10862 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10863 #ifdef AST_CDR_FLAG_POST_DISABLED
10864 if (myrpt->txchannel->cdr)
10865 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10866 #endif
10867 #ifndef NEW_ASTERISK
10868 myrpt->txchannel->whentohangup = 0;
10869 #endif
10870 myrpt->txchannel->appl = "Apprpt";
10871 myrpt->txchannel->data = "(Repeater Tx)";
10872 if (option_verbose > 2)
10873 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10874 tmpstr,tele,myrpt->txchannel->name);
10875 ast_call(myrpt->txchannel,tele,999);
10876 if (myrpt->rxchannel->_state != AST_STATE_UP)
10877 {
10878 rpt_mutex_unlock(&myrpt->lock);
10879 ast_hangup(myrpt->rxchannel);
10880 ast_hangup(myrpt->txchannel);
10881 myrpt->rpt_thread = AST_PTHREADT_STOP;
10882 pthread_exit(NULL);
10883 }
10884 }
10885 else
10886 {
10887 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10888 rpt_mutex_unlock(&myrpt->lock);
10889 ast_hangup(myrpt->rxchannel);
10890 myrpt->rpt_thread = AST_PTHREADT_STOP;
10891 pthread_exit(NULL);
10892 }
10893 }
10894 else
10895 {
10896 myrpt->txchannel = myrpt->rxchannel;
10897 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10898 myrpt->dahditxchannel = myrpt->txchannel;
10899 }
10900 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10901 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10902
10903 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10904 if (!myrpt->pchannel)
10905 {
10906 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10907 rpt_mutex_unlock(&myrpt->lock);
10908 if (myrpt->txchannel != myrpt->rxchannel)
10909 ast_hangup(myrpt->txchannel);
10910 ast_hangup(myrpt->rxchannel);
10911 myrpt->rpt_thread = AST_PTHREADT_STOP;
10912 pthread_exit(NULL);
10913 }
10914 #ifdef AST_CDR_FLAG_POST_DISABLED
10915 if (myrpt->pchannel->cdr)
10916 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10917 #endif
10918 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10919 if (!myrpt->dahditxchannel)
10920 {
10921
10922 myrpt->dahditxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10923 if (!myrpt->dahditxchannel)
10924 {
10925 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10926 rpt_mutex_unlock(&myrpt->lock);
10927 if (myrpt->txchannel != myrpt->rxchannel)
10928 ast_hangup(myrpt->txchannel);
10929 ast_hangup(myrpt->rxchannel);
10930 myrpt->rpt_thread = AST_PTHREADT_STOP;
10931 pthread_exit(NULL);
10932 }
10933 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10934 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10935 #ifdef AST_CDR_FLAG_POST_DISABLED
10936 if (myrpt->dahditxchannel->cdr)
10937 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10938 #endif
10939 }
10940
10941 myrpt->monchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10942 if (!myrpt->monchannel)
10943 {
10944 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10945 rpt_mutex_unlock(&myrpt->lock);
10946 if (myrpt->txchannel != myrpt->rxchannel)
10947 ast_hangup(myrpt->txchannel);
10948 ast_hangup(myrpt->rxchannel);
10949 myrpt->rpt_thread = AST_PTHREADT_STOP;
10950 pthread_exit(NULL);
10951 }
10952 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10953 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10954 #ifdef AST_CDR_FLAG_POST_DISABLED
10955 if (myrpt->monchannel->cdr)
10956 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10957 #endif
10958
10959 ci.chan = 0;
10960 ci.confno = -1;
10961 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10962
10963 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10964 {
10965 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10966 rpt_mutex_unlock(&myrpt->lock);
10967 ast_hangup(myrpt->pchannel);
10968 ast_hangup(myrpt->monchannel);
10969 if (myrpt->txchannel != myrpt->rxchannel)
10970 ast_hangup(myrpt->txchannel);
10971 ast_hangup(myrpt->rxchannel);
10972 myrpt->rpt_thread = AST_PTHREADT_STOP;
10973 pthread_exit(NULL);
10974 }
10975
10976 myrpt->txconf = ci.confno;
10977
10978 ci.chan = 0;
10979 ci.confno = -1;
10980 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10981 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10982
10983 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10984 {
10985 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10986 rpt_mutex_unlock(&myrpt->lock);
10987 ast_hangup(myrpt->pchannel);
10988 ast_hangup(myrpt->monchannel);
10989 if (myrpt->txchannel != myrpt->rxchannel)
10990 ast_hangup(myrpt->txchannel);
10991 ast_hangup(myrpt->rxchannel);
10992 myrpt->rpt_thread = AST_PTHREADT_STOP;
10993 pthread_exit(NULL);
10994 }
10995
10996 myrpt->conf = ci.confno;
10997
10998 ci.chan = 0;
10999 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11000 (myrpt->dahditxchannel == myrpt->txchannel))
11001 {
11002
11003 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11004 {
11005 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11006 rpt_mutex_unlock(&myrpt->lock);
11007 ast_hangup(myrpt->pchannel);
11008 ast_hangup(myrpt->monchannel);
11009 if (myrpt->txchannel != myrpt->rxchannel)
11010 ast_hangup(myrpt->txchannel);
11011 ast_hangup(myrpt->rxchannel);
11012 myrpt->rpt_thread = AST_PTHREADT_STOP;
11013 pthread_exit(NULL);
11014 }
11015 ci.confmode = DAHDI_CONF_MONITORTX;
11016 }
11017 else
11018 {
11019 ci.confno = myrpt->txconf;
11020 ci.confmode = DAHDI_CONF_CONFANNMON;
11021 }
11022
11023 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11024 {
11025 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11026 rpt_mutex_unlock(&myrpt->lock);
11027 ast_hangup(myrpt->pchannel);
11028 ast_hangup(myrpt->monchannel);
11029 if (myrpt->txchannel != myrpt->rxchannel)
11030 ast_hangup(myrpt->txchannel);
11031 ast_hangup(myrpt->rxchannel);
11032 myrpt->rpt_thread = AST_PTHREADT_STOP;
11033 pthread_exit(NULL);
11034 }
11035
11036 myrpt->parrotchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11037 if (!myrpt->parrotchannel)
11038 {
11039 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11040 rpt_mutex_unlock(&myrpt->lock);
11041 if (myrpt->txchannel != myrpt->rxchannel)
11042 ast_hangup(myrpt->txchannel);
11043 ast_hangup(myrpt->rxchannel);
11044 myrpt->rpt_thread = AST_PTHREADT_STOP;
11045 pthread_exit(NULL);
11046 }
11047 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11048 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11049 #ifdef AST_CDR_FLAG_POST_DISABLED
11050 if (myrpt->parrotchannel->cdr)
11051 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11052 #endif
11053
11054 myrpt->voxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11055 if (!myrpt->voxchannel)
11056 {
11057 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11058 rpt_mutex_unlock(&myrpt->lock);
11059 if (myrpt->txchannel != myrpt->rxchannel)
11060 ast_hangup(myrpt->txchannel);
11061 ast_hangup(myrpt->rxchannel);
11062 myrpt->rpt_thread = AST_PTHREADT_STOP;
11063 pthread_exit(NULL);
11064 }
11065 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11066 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11067 #ifdef AST_CDR_FLAG_POST_DISABLED
11068 if (myrpt->voxchannel->cdr)
11069 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11070 #endif
11071
11072 myrpt->txpchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11073 if (!myrpt->txpchannel)
11074 {
11075 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11076 rpt_mutex_unlock(&myrpt->lock);
11077 ast_hangup(myrpt->pchannel);
11078 ast_hangup(myrpt->monchannel);
11079 if (myrpt->txchannel != myrpt->rxchannel)
11080 ast_hangup(myrpt->txchannel);
11081 ast_hangup(myrpt->rxchannel);
11082 myrpt->rpt_thread = AST_PTHREADT_STOP;
11083 pthread_exit(NULL);
11084 }
11085 #ifdef AST_CDR_FLAG_POST_DISABLED
11086 if (myrpt->txpchannel->cdr)
11087 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11088 #endif
11089
11090 ci.chan = 0;
11091 ci.confno = myrpt->txconf;
11092 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11093
11094 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11095 {
11096 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11097 rpt_mutex_unlock(&myrpt->lock);
11098 ast_hangup(myrpt->txpchannel);
11099 ast_hangup(myrpt->monchannel);
11100 if (myrpt->txchannel != myrpt->rxchannel)
11101 ast_hangup(myrpt->txchannel);
11102 ast_hangup(myrpt->rxchannel);
11103 myrpt->rpt_thread = AST_PTHREADT_STOP;
11104 pthread_exit(NULL);
11105 }
11106
11107 myrpt->iofd = -1;
11108 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11109 {
11110 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11111 rpt_mutex_unlock(&myrpt->lock);
11112 ast_hangup(myrpt->pchannel);
11113 if (myrpt->txchannel != myrpt->rxchannel)
11114 ast_hangup(myrpt->txchannel);
11115 ast_hangup(myrpt->rxchannel);
11116 pthread_exit(NULL);
11117 }
11118
11119
11120
11121 myrpt->links.next = &myrpt->links;
11122 myrpt->links.prev = &myrpt->links;
11123 myrpt->tailtimer = 0;
11124 myrpt->totimer = 0;
11125 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11126 myrpt->idtimer = myrpt->p.politeid;
11127 myrpt->mustid = myrpt->tailid = 0;
11128 myrpt->callmode = 0;
11129 myrpt->tounkeyed = 0;
11130 myrpt->tonotify = 0;
11131 myrpt->retxtimer = 0;
11132 myrpt->rerxtimer = 0;
11133 myrpt->skedtimer = 0;
11134 myrpt->tailevent = 0;
11135 lasttx = 0;
11136 myrpt->keyed = 0;
11137 myrpt->txkeyed = 0;
11138 time(&myrpt->lastkeyedtime);
11139 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11140 time(&myrpt->lasttxkeyedtime);
11141 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11142 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11143 myrpt->dtmfidx = -1;
11144 myrpt->dtmfbuf[0] = 0;
11145 myrpt->rem_dtmfidx = -1;
11146 myrpt->rem_dtmfbuf[0] = 0;
11147 myrpt->dtmf_time = 0;
11148 myrpt->rem_dtmf_time = 0;
11149 myrpt->inpadtest = 0;
11150 myrpt->disgorgetime = 0;
11151 myrpt->lastnodewhichkeyedusup[0] = '\0';
11152 myrpt->dailytxtime = 0;
11153 myrpt->totaltxtime = 0;
11154 myrpt->dailykeyups = 0;
11155 myrpt->totalkeyups = 0;
11156 myrpt->dailykerchunks = 0;
11157 myrpt->totalkerchunks = 0;
11158 myrpt->dailyexecdcommands = 0;
11159 myrpt->totalexecdcommands = 0;
11160 myrpt->timeouts = 0;
11161 myrpt->exten[0] = '\0';
11162 myrpt->lastdtmfcommand[0] = '\0';
11163 voxinit_rpt(myrpt,1);
11164 myrpt->wasvox = 0;
11165 if (myrpt->p.startupmacro)
11166 {
11167 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11168 }
11169 rpt_mutex_unlock(&myrpt->lock);
11170 val = 1;
11171 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11172 val = 1;
11173 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11174 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11175 dtmfed = 0;
11176 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11177 lastmyrx = 0;
11178 myfirst = 0;
11179 while (ms >= 0)
11180 {
11181 struct ast_frame *f,*f1,*f2;
11182 struct ast_channel *cs[300],*cs1[300];
11183 int totx=0,elap=0,n,x,toexit=0;
11184
11185
11186 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11187 struct rpt_link *dl;
11188 struct rpt_tele *dt;
11189
11190 myrpt->disgorgetime = 0;
11191 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11192 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11193 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11194 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11195 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11196 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11197
11198 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11199 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11200 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11201 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11202 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11203 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11204 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11205 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11206 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11207 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11208
11209 dl = myrpt->links.next;
11210 while(dl != &myrpt->links){
11211 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11212 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11213 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11214 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11215 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11216 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11217 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11218 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11219 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11220 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11221 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11222 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11223 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11224 dl = dl->next;
11225 }
11226
11227 dt = myrpt->tele.next;
11228 if(dt != &myrpt->tele)
11229 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11230 while(dt != &myrpt->tele){
11231 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11232 dt = dt->next;
11233 }
11234 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11235
11236 }
11237
11238
11239 if (myrpt->reload)
11240 {
11241 struct rpt_tele *inner_telem;
11242
11243 rpt_mutex_lock(&myrpt->lock);
11244 inner_telem = myrpt->tele.next;
11245 while(inner_telem != &myrpt->tele)
11246 {
11247 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11248 inner_telem = inner_telem->next;
11249 }
11250 myrpt->reload = 0;
11251 rpt_mutex_unlock(&myrpt->lock);
11252 usleep(10000);
11253
11254 for(i = 0; i < nrpts; i++)
11255 {
11256 if (&rpt_vars[i] == myrpt)
11257 {
11258 load_rpt_vars(i,0);
11259 break;
11260 }
11261 }
11262 }
11263
11264 rpt_mutex_lock(&myrpt->lock);
11265 if (ast_check_hangup(myrpt->rxchannel)) break;
11266 if (ast_check_hangup(myrpt->txchannel)) break;
11267 if (ast_check_hangup(myrpt->pchannel)) break;
11268 if (ast_check_hangup(myrpt->monchannel)) break;
11269 if (myrpt->parrotchannel &&
11270 ast_check_hangup(myrpt->parrotchannel)) break;
11271 if (myrpt->voxchannel &&
11272 ast_check_hangup(myrpt->voxchannel)) break;
11273 if (ast_check_hangup(myrpt->txpchannel)) break;
11274 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11275
11276
11277 myrpt->localtx = myrpt->keyed;
11278
11279 l = myrpt->links.next;
11280 remrx = 0;
11281 while(l != &myrpt->links)
11282 {
11283 if (l->lastrx){
11284 remrx = 1;
11285 if(l->name[0] != '0')
11286 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11287 }
11288 l = l->next;
11289 }
11290
11291 if(myrpt->p.idtime)
11292 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11293
11294
11295 if (myrpt->p.duplex > 1)
11296 {
11297 totx = myrpt->callmode;
11298 totx = totx || myrpt->localtx;
11299 }
11300 else
11301 {
11302 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11303
11304 if (lastmyrx != myrx)
11305 {
11306 voxinit_rpt(myrpt,!myrx);
11307 lastmyrx = myrx;
11308 }
11309 totx = 0;
11310 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11311 {
11312 if (myrpt->voxtostate)
11313 {
11314 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11315 myrpt->voxtostate = 0;
11316 }
11317 else
11318 {
11319 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11320 myrpt->voxtostate = 1;
11321 }
11322 }
11323 if (!myrpt->voxtostate)
11324 totx = myrpt->callmode && myrpt->wasvox;
11325 }
11326
11327 identqueued = 0;
11328 localmsgqueued = 0;
11329 othertelemqueued = 0;
11330 tailmessagequeued = 0;
11331 ctqueued = 0;
11332 telem = myrpt->tele.next;
11333 while(telem != &myrpt->tele)
11334 {
11335 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11336 identqueued = 1;
11337 }
11338 else if(telem->mode == TAILMSG)
11339 {
11340 tailmessagequeued = 1;
11341 }
11342 else if(telem->mode == STATS_TIME_LOCAL)
11343 {
11344 localmsgqueued = 1;
11345 }
11346 else
11347 {
11348 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11349 othertelemqueued = 1;
11350 else
11351 ctqueued = 1;
11352 }
11353 telem = telem->next;
11354 }
11355
11356
11357 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11358
11359
11360 myrpt->exttx = totx;
11361 totx = totx || myrpt->dtmf_local_timer;
11362
11363 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11364
11365 totx = totx || remrx;
11366
11367 if (myrpt->p.duplex > 0)
11368 totx = totx || identqueued || ctqueued || localmsgqueued;
11369
11370 if (myrpt->p.duplex > 1)
11371 {
11372 totx = totx || (myrpt->dtmfidx > -1) ||
11373 myrpt->cmdnode[0];
11374 }
11375
11376 totx = totx || (myrpt->parrotstate > 1);
11377
11378 if (!totx)
11379 {
11380 myrpt->totimer = myrpt->p.totime;
11381 myrpt->tounkeyed = 0;
11382 myrpt->tonotify = 0;
11383 }
11384 else{
11385 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11386 myrpt->p.althangtime :
11387 myrpt->p.hangtime;
11388 }
11389
11390 totx = totx && myrpt->totimer;
11391
11392 if ((!myrpt->totimer) && (!myrpt->tonotify))
11393 {
11394 myrpt->tonotify = 1;
11395 myrpt->timeouts++;
11396 rpt_mutex_unlock(&myrpt->lock);
11397 rpt_telemetry(myrpt,TIMEOUT,NULL);
11398 rpt_mutex_lock(&myrpt->lock);
11399 }
11400
11401
11402 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11403 {
11404 myrpt->tounkeyed = 1;
11405 }
11406 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11407 {
11408 myrpt->totimer = myrpt->p.totime;
11409 myrpt->tounkeyed = 0;
11410 myrpt->tonotify = 0;
11411 rpt_mutex_unlock(&myrpt->lock);
11412 continue;
11413 }
11414
11415 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11416 {
11417 if(debug)
11418 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11419 myrpt->callmode = 0;
11420 myrpt->macropatch=0;
11421 channel_revert(myrpt);
11422 }
11423
11424 if (!myrpt->totimer) myrpt->tailtimer = 0;
11425
11426 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11427
11428
11429 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11430 int hasid = 0,hastalkover = 0;
11431
11432 telem = myrpt->tele.next;
11433 while(telem != &myrpt->tele){
11434 if(telem->mode == ID){
11435 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11436 hasid = 1;
11437 }
11438 if(telem->mode == TAILMSG){
11439 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11440 }
11441 if (telem->mode == IDTALKOVER) hastalkover = 1;
11442 telem = telem->next;
11443 }
11444 rpt_mutex_unlock(&myrpt->lock);
11445 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11446 rpt_mutex_lock(&myrpt->lock);
11447 }
11448
11449
11450
11451
11452
11453 if(myrpt->mustid && (!myrpt->idtimer))
11454 queue_id(myrpt);
11455
11456 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11457 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11458 {
11459 myrpt->tailid = 1;
11460 }
11461
11462
11463
11464 if(myrpt->tailevent){
11465 myrpt->tailevent = 0;
11466 if(myrpt->tailid){
11467 totx = 1;
11468 queue_id(myrpt);
11469 }
11470 else if ((myrpt->p.tailmessages[0]) &&
11471 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11472 totx = 1;
11473 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11474 rpt_mutex_unlock(&myrpt->lock);
11475 rpt_telemetry(myrpt, TAILMSG, NULL);
11476 rpt_mutex_lock(&myrpt->lock);
11477 }
11478 }
11479
11480
11481
11482
11483 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11484 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11485 myrpt->txrealkeyed = totx;
11486 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11487 if (totx && (!lasttx))
11488 {
11489 char mydate[100],myfname[100];
11490 time_t myt;
11491
11492 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11493 if (myrpt->p.archivedir)
11494 {
11495 long blocksleft;
11496
11497 time(&myt);
11498 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11499 localtime(&myt));
11500 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11501 myrpt->name,mydate);
11502 myrpt->monstream = ast_writefile(myfname,"wav49",
11503 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11504 if (myrpt->p.monminblocks)
11505 {
11506 blocksleft = diskavail(myrpt);
11507 if (blocksleft >= myrpt->p.monminblocks)
11508 donodelog(myrpt,"TXKEY,MAIN");
11509 } else donodelog(myrpt,"TXKEY,MAIN");
11510 }
11511 lasttx = 1;
11512 myrpt->txkeyed = 1;
11513 time(&myrpt->lasttxkeyedtime);
11514 myrpt->dailykeyups++;
11515 myrpt->totalkeyups++;
11516 rpt_mutex_unlock(&myrpt->lock);
11517 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11518 rpt_mutex_lock(&myrpt->lock);
11519 }
11520 if ((!totx) && lasttx)
11521 {
11522 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11523 myrpt->monstream = NULL;
11524
11525 lasttx = 0;
11526 myrpt->txkeyed = 0;
11527 time(&myrpt->lasttxkeyedtime);
11528 rpt_mutex_unlock(&myrpt->lock);
11529 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11530 rpt_mutex_lock(&myrpt->lock);
11531 donodelog(myrpt,"TXUNKEY,MAIN");
11532 }
11533 time(&t);
11534
11535 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11536 {
11537 myrpt->inpadtest = 0;
11538 myrpt->dtmfidx = -1;
11539 myrpt->dtmfbuf[0] = 0;
11540 }
11541
11542 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11543 {
11544 myrpt->inpadtest = 0;
11545 myrpt->rem_dtmfidx = -1;
11546 myrpt->rem_dtmfbuf[0] = 0;
11547 }
11548
11549 if (myrpt->exttx && myrpt->parrotchannel &&
11550 myrpt->p.parrotmode && (!myrpt->parrotstate))
11551 {
11552 char myfname[300];
11553
11554 ci.confno = myrpt->conf;
11555 ci.confmode = DAHDI_CONF_CONFANNMON;
11556 ci.chan = 0;
11557
11558
11559 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11560 {
11561 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11562 break;
11563 }
11564
11565 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11566 strcat(myfname,".wav");
11567 unlink(myfname);
11568 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11569 myrpt->parrotstate = 1;
11570 myrpt->parrottimer = myrpt->p.parrottime;
11571 if (myrpt->parrotstream)
11572 ast_closestream(myrpt->parrotstream);
11573 myrpt->parrotstream = NULL;
11574 myrpt->parrotstream = ast_writefile(myfname,"wav",
11575 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11576 }
11577
11578
11579
11580 l = myrpt->links.next;
11581 while(l != &myrpt->links)
11582 {
11583 if (l->killme)
11584 {
11585
11586 remque((struct qelem *) l);
11587 if (!strcmp(myrpt->cmdnode,l->name))
11588 myrpt->cmdnode[0] = 0;
11589 rpt_mutex_unlock(&myrpt->lock);
11590
11591 if (l->chan) ast_hangup(l->chan);
11592 ast_hangup(l->pchan);
11593 ast_free(l);
11594 rpt_mutex_lock(&myrpt->lock);
11595
11596 l = myrpt->links.next;
11597 continue;
11598 }
11599 l = l->next;
11600 }
11601 n = 0;
11602 cs[n++] = myrpt->rxchannel;
11603 cs[n++] = myrpt->pchannel;
11604 cs[n++] = myrpt->monchannel;
11605 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11606 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11607 cs[n++] = myrpt->txpchannel;
11608 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11609 if (myrpt->dahditxchannel != myrpt->txchannel)
11610 cs[n++] = myrpt->dahditxchannel;
11611 l = myrpt->links.next;
11612 while(l != &myrpt->links)
11613 {
11614 if ((!l->killme) && (!l->disctime) && l->chan)
11615 {
11616 cs[n++] = l->chan;
11617 cs[n++] = l->pchan;
11618 }
11619 l = l->next;
11620 }
11621 if ((myrpt->topkeystate == 1) &&
11622 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11623 {
11624 myrpt->topkeystate = 2;
11625 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11626 topcompar);
11627 }
11628 rpt_mutex_unlock(&myrpt->lock);
11629
11630 if (myrpt->topkeystate == 2)
11631 {
11632 rpt_telemetry(myrpt,TOPKEY,NULL);
11633 myrpt->topkeystate = 3;
11634 }
11635 ms = MSWAIT;
11636 for(x = 0; x < n; x++)
11637 {
11638 int s = -(-x - myrpt->scram - 1) % n;
11639 cs1[x] = cs[s];
11640 }
11641 myrpt->scram++;
11642 who = ast_waitfor_n(cs1,n,&ms);
11643 if (who == NULL) ms = 0;
11644 elap = MSWAIT - ms;
11645 rpt_mutex_lock(&myrpt->lock);
11646 l = myrpt->links.next;
11647 while(l != &myrpt->links)
11648 {
11649 int myrx;
11650
11651 if (l->voxtotimer) l->voxtotimer -= elap;
11652 if (l->voxtotimer < 0) l->voxtotimer = 0;
11653
11654 if (l->lasttx != l->lasttx1)
11655 {
11656 voxinit_link(l,!l->lasttx);
11657 l->lasttx1 = l->lasttx;
11658 }
11659 myrx = l->lastrealrx;
11660 if ((l->phonemode) && (l->phonevox))
11661 {
11662 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11663 if (l->voxtotimer <= 0)
11664 {
11665 if (l->voxtostate)
11666 {
11667 l->voxtotimer = myrpt->p.voxtimeout_ms;
11668 l->voxtostate = 0;
11669 }
11670 else
11671 {
11672 l->voxtotimer = myrpt->p.voxrecover_ms;
11673 l->voxtostate = 1;
11674 }
11675 }
11676 if (!l->voxtostate)
11677 myrx = myrx || l->wasvox ;
11678 }
11679 l->lastrx = myrx;
11680 if (l->linklisttimer)
11681 {
11682 l->linklisttimer -= elap;
11683 if (l->linklisttimer < 0) l->linklisttimer = 0;
11684 }
11685 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11686 {
11687 struct ast_frame lf;
11688
11689 memset(&lf,0,sizeof(lf));
11690 lf.frametype = AST_FRAME_TEXT;
11691 lf.subclass = 0;
11692 lf.offset = 0;
11693 lf.mallocd = 0;
11694 lf.samples = 0;
11695 l->linklisttimer = LINKLISTTIME;
11696 strcpy(lstr,"L ");
11697 __mklinklist(myrpt,l,lstr + 2);
11698 if (l->chan)
11699 {
11700 lf.datalen = strlen(lstr) + 1;
11701 lf.data.ptr = lstr;
11702 ast_write(l->chan,&lf);
11703 if (debug > 6) ast_log(LOG_NOTICE,
11704 "@@@@ node %s sent node string %s to node %s\n",
11705 myrpt->name,lstr,l->name);
11706 }
11707 }
11708 if (l->newkey)
11709 {
11710 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11711 {
11712 l->retxtimer = 0;
11713 if (l->chan && l->phonemode == 0)
11714 {
11715 if (l->lasttx)
11716 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11717 else
11718 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11719 }
11720 }
11721 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11722 {
11723 if (debug == 7) printf("@@@@ rx un-key\n");
11724 l->lastrealrx = 0;
11725 l->rerxtimer = 0;
11726 if (l->lastrx1)
11727 {
11728 if (myrpt->p.archivedir)
11729 {
11730 char str[100];
11731
11732 sprintf(str,"RXUNKEY(T),%s",l->name);
11733 donodelog(myrpt,str);
11734 }
11735 if(myrpt->p.duplex)
11736 rpt_telemetry(myrpt,LINKUNKEY,l);
11737 l->lastrx1 = 0;
11738 }
11739 }
11740 }
11741 if (l->disctime)
11742 {
11743 l->disctime -= elap;
11744 if (l->disctime <= 0)
11745 l->disctime = 0;
11746 }
11747
11748 if (l->retrytimer)
11749 {
11750 l->retrytimer -= elap;
11751 if (l->retrytimer < 0) l->retrytimer = 0;
11752 }
11753
11754
11755 l->connecttime += elap;
11756
11757
11758 if (l->elaptime < 0)
11759 {
11760 l = l->next;
11761 continue;
11762 }
11763 l->elaptime += elap;
11764
11765 if ((l->elaptime > MAXCONNECTTIME) &&
11766 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11767 {
11768 l->elaptime = 0;
11769 rpt_mutex_unlock(&myrpt->lock);
11770 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11771 rpt_mutex_lock(&myrpt->lock);
11772 break;
11773 }
11774 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11775 (l->retries++ < l->max_retries) && (l->hasconnected))
11776 {
11777 if (l->chan) ast_hangup(l->chan);
11778 l->chan = 0;
11779 rpt_mutex_unlock(&myrpt->lock);
11780 if ((l->name[0] != '0') && (!l->isremote))
11781 {
11782 if (attempt_reconnect(myrpt,l) == -1)
11783 {
11784 l->retrytimer = RETRY_TIMER_MS;
11785 }
11786 }
11787 else
11788 {
11789 l->retrytimer = l->max_retries + 1;
11790 }
11791
11792 rpt_mutex_lock(&myrpt->lock);
11793 break;
11794 }
11795 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11796 (l->retries >= l->max_retries))
11797 {
11798
11799 remque((struct qelem *) l);
11800 if (!strcmp(myrpt->cmdnode,l->name))
11801 myrpt->cmdnode[0] = 0;
11802 rpt_mutex_unlock(&myrpt->lock);
11803 if (l->name[0] != '0')
11804 {
11805 if (!l->hasconnected)
11806 rpt_telemetry(myrpt,CONNFAIL,l);
11807 else rpt_telemetry(myrpt,REMDISC,l);
11808 }
11809 if (myrpt->p.archivedir)
11810 {
11811 char str[100];
11812
11813 if (!l->hasconnected)
11814 sprintf(str,"LINKFAIL,%s",l->name);
11815 else
11816 sprintf(str,"LINKDISC,%s",l->name);
11817 donodelog(myrpt,str);
11818 }
11819
11820 ast_hangup(l->pchan);
11821 ast_free(l);
11822 rpt_mutex_lock(&myrpt->lock);
11823 break;
11824 }
11825 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11826 {
11827 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11828
11829 remque((struct qelem *) l);
11830 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11831 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11832 rpt_mutex_unlock(&myrpt->lock);
11833 if (l->name[0] != '0')
11834 {
11835 rpt_telemetry(myrpt,REMDISC,l);
11836 }
11837 if (myrpt->p.archivedir)
11838 {
11839 char str[100];
11840 sprintf(str,"LINKDISC,%s",l->name);
11841 donodelog(myrpt,str);
11842 }
11843
11844 ast_hangup(l->pchan);
11845 ast_free(l);
11846 rpt_mutex_lock(&myrpt->lock);
11847 break;
11848 }
11849 l = l->next;
11850 }
11851 if (myrpt->linkposttimer)
11852 {
11853 myrpt->linkposttimer -= elap;
11854 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11855 }
11856 if (myrpt->linkposttimer <= 0)
11857 {
11858 int nstr;
11859 char lst,*str;
11860 time_t now;
11861
11862 myrpt->linkposttimer = LINKPOSTTIME;
11863 nstr = 0;
11864 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11865 {
11866
11867 if (l->name[0] == '0') continue;
11868 nstr += strlen(l->name) + 1;
11869 }
11870 str = ast_malloc(nstr + 256);
11871 if (!str)
11872 {
11873 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11874 break;
11875 }
11876 nstr = 0;
11877 strcpy(str,"nodes=");
11878 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11879 {
11880
11881 if (l->name[0] == '0') continue;
11882 lst = 'T';
11883 if (!l->mode) lst = 'R';
11884 if (!l->thisconnected) lst = 'C';
11885 if (nstr) strcat(str,",");
11886 sprintf(str + strlen(str),"%c%s",lst,l->name);
11887 nstr = 1;
11888 }
11889 p = strstr(tdesc, "version");
11890 if(p){
11891 int vmajor,vminor;
11892 if(sscanf(p, "version %d.%d", &vmajor, &vminor) == 2)
11893 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11894 }
11895 time(&now);
11896 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11897 sprintf(str + strlen(str),
11898 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11899 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11900 myrpt->timeouts,myrpt->totalexecdcommands);
11901 rpt_mutex_unlock(&myrpt->lock);
11902 statpost(myrpt,str);
11903 rpt_mutex_lock(&myrpt->lock);
11904 ast_free(str);
11905 }
11906 if (myrpt->keyposttimer)
11907 {
11908 myrpt->keyposttimer -= elap;
11909 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11910 }
11911 if (myrpt->keyposttimer <= 0)
11912 {
11913 char str[100];
11914 int diff = 0;
11915 time_t now;
11916
11917 myrpt->keyposttimer = KEYPOSTTIME;
11918 time(&now);
11919 if (myrpt->lastkeyedtime)
11920 {
11921 diff = (int)(now - myrpt->lastkeyedtime);
11922 }
11923 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11924 rpt_mutex_unlock(&myrpt->lock);
11925 statpost(myrpt,str);
11926 rpt_mutex_lock(&myrpt->lock);
11927 }
11928 if(totx){
11929 myrpt->dailytxtime += elap;
11930 myrpt->totaltxtime += elap;
11931 }
11932 i = myrpt->tailtimer;
11933 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11934 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11935 if((i) && (myrpt->tailtimer == 0))
11936 myrpt->tailevent = 1;
11937 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11938 if (myrpt->totimer < 0) myrpt->totimer = 0;
11939 if (myrpt->idtimer) myrpt->idtimer -= elap;
11940 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11941 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11942 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11943 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11944 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11945 if (myrpt->exttx)
11946 {
11947 myrpt->parrottimer = myrpt->p.parrottime;
11948 }
11949 else
11950 {
11951 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11952 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11953 }
11954
11955 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11956 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11957
11958 if (myrpt->dtmf_local_timer)
11959 {
11960 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11961 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11962 }
11963 do_dtmf_local(myrpt,0);
11964
11965 if (myrpt->skedtimer <= 0){
11966 myrpt->skedtimer = 200;
11967 do_scheduler(myrpt);
11968 }
11969 else
11970 myrpt->skedtimer -=elap;
11971 if (!ms)
11972 {
11973 rpt_mutex_unlock(&myrpt->lock);
11974 continue;
11975 }
11976 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11977 (myrpt->parrottimer <= 0))
11978 {
11979
11980 ci.confno = 0;
11981 ci.confmode = 0;
11982 ci.chan = 0;
11983
11984
11985 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11986 {
11987 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11988 break;
11989 }
11990 if (myrpt->parrotstream)
11991 ast_closestream(myrpt->parrotstream);
11992 myrpt->parrotstream = NULL;
11993 myrpt->parrotstate = 2;
11994 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
11995 }
11996 if (myrpt->cmdAction.state == CMD_STATE_READY)
11997 {
11998 int status;
11999 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12000
12001 rpt_mutex_unlock(&myrpt->lock);
12002
12003 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12004
12005 rpt_mutex_lock(&myrpt->lock);
12006 myrpt->cmdAction.state = CMD_STATE_IDLE;
12007 }
12008
12009 c = myrpt->macrobuf[0];
12010 time(&t);
12011 if (c && (!myrpt->macrotimer) &&
12012 starttime && (t > (starttime + START_DELAY)))
12013 {
12014 char cin = c & 0x7f;
12015 myrpt->macrotimer = MACROTIME;
12016 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12017 if ((cin == 'p') || (cin == 'P'))
12018 myrpt->macrotimer = MACROPTIME;
12019 rpt_mutex_unlock(&myrpt->lock);
12020 if (myrpt->p.archivedir)
12021 {
12022 char str[100];
12023
12024 sprintf(str,"DTMF(M),MAIN,%c",cin);
12025 donodelog(myrpt,str);
12026 }
12027 local_dtmf_helper(myrpt,c);
12028 } else rpt_mutex_unlock(&myrpt->lock);
12029 if (who == myrpt->rxchannel)
12030 {
12031 int ismuted;
12032
12033 f = ast_read(myrpt->rxchannel);
12034 if (!f)
12035 {
12036 if (debug) printf("@@@@ rpt:Hung Up\n");
12037 break;
12038 }
12039 if (f->frametype == AST_FRAME_VOICE)
12040 {
12041 #ifdef _MDC_DECODE_H_
12042 unsigned char ubuf[2560];
12043 short *sp;
12044 int n;
12045 #endif
12046
12047 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12048 memset(f->data.ptr,0,f->datalen);
12049 }
12050
12051 #ifdef _MDC_DECODE_H_
12052 sp = (short *) f->data;
12053
12054 for(n = 0; n < f->datalen / 2; n++)
12055 {
12056 ubuf[n] = (*sp++ >> 8) + 128;
12057 }
12058 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12059 if (n == 1)
12060 {
12061 unsigned char op,arg;
12062 unsigned short unitID;
12063
12064 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12065 if (debug > 2)
12066 {
12067 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12068 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12069 op & 255,arg & 255,unitID);
12070 }
12071 if ((op == 1) && (arg == 0))
12072 {
12073 myrpt->lastunit = unitID;
12074 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12075 mdc1200_send(myrpt,myrpt->lastunit);
12076 }
12077 }
12078 if ((debug > 2) && (i == 2))
12079 {
12080 unsigned char op,arg,ex1,ex2,ex3,ex4;
12081 unsigned short unitID;
12082
12083 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12084 &ex1,&ex2,&ex3,&ex4);
12085 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12086 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12087 op & 255,arg & 255,unitID);
12088 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12089 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12090 }
12091 #endif
12092 #ifdef __RPT_NOTCH
12093
12094 rpt_filter(myrpt,f->data,f->datalen / 2);
12095 #endif
12096 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12097 {
12098 ismuted = 0;
12099 }
12100 if (dtmfed) ismuted = 1;
12101 dtmfed = 0;
12102 if (ismuted)
12103 {
12104 memset(f->data.ptr,0,f->datalen);
12105 if (myrpt->lastf1)
12106 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12107 if (myrpt->lastf2)
12108 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12109 }
12110 if (f) f2 = ast_frdup(f);
12111 else f2 = NULL;
12112 f1 = myrpt->lastf2;
12113 myrpt->lastf2 = myrpt->lastf1;
12114 myrpt->lastf1 = f2;
12115 if (ismuted)
12116 {
12117 if (myrpt->lastf1)
12118 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12119 if (myrpt->lastf2)
12120 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12121 }
12122 if (f1)
12123 {
12124 ast_write(myrpt->pchannel,f1);
12125 ast_frfree(f1);
12126 }
12127 }
12128 #ifndef OLD_ASTERISK
12129 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12130 {
12131 if (myrpt->lastf1)
12132 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12133 if (myrpt->lastf2)
12134 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12135 dtmfed = 1;
12136 }
12137 #endif
12138 else if (f->frametype == AST_FRAME_DTMF)
12139 {
12140 c = (char) f->subclass;
12141 ast_frfree(f);
12142 if (myrpt->lastf1)
12143 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12144 if (myrpt->lastf2)
12145 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12146 dtmfed = 1;
12147 if (!myrpt->keyed) continue;
12148 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12149 if (c) local_dtmf_helper(myrpt,c);
12150 continue;
12151 }
12152 else if (f->frametype == AST_FRAME_CONTROL)
12153 {
12154 if (f->subclass == AST_CONTROL_HANGUP)
12155 {
12156 if (debug) printf("@@@@ rpt:Hung Up\n");
12157 ast_frfree(f);
12158 break;
12159 }
12160
12161 if (f->subclass == AST_CONTROL_RADIO_KEY)
12162 {
12163 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12164 {
12165 if (debug == 7) printf("@@@@ rx key\n");
12166 myrpt->keyed = 1;
12167 time(&myrpt->lastkeyedtime);
12168 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12169 }
12170 if (myrpt->p.archivedir)
12171 {
12172 donodelog(myrpt,"RXKEY,MAIN");
12173 }
12174 if (f->datalen && f->data.ptr)
12175 {
12176 char busy = 0;
12177
12178 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12179
12180 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12181 {
12182 char value[16];
12183 strcat(value,"*6");
12184 myrpt->macropatch=1;
12185 rpt_mutex_lock(&myrpt->lock);
12186 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12187 rpt_mutex_unlock(&myrpt->lock);
12188 busy=1;
12189 }
12190 if(!busy){
12191 myrpt->macrotimer = MACROTIME;
12192 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12193 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12194 }
12195 rpt_mutex_unlock(&myrpt->lock);
12196 }
12197 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12198 {
12199 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12200 if (value)
12201 {
12202 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12203 rpt_mutex_lock(&myrpt->lock);
12204 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12205 rpt_mutex_unlock(&myrpt->lock);
12206 busy=1;
12207 }
12208 if(!busy){
12209 myrpt->macrotimer = MACROTIME;
12210 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12211 }
12212 rpt_mutex_unlock(&myrpt->lock);
12213 }
12214 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12215 }
12216 } else myrpt->lasttone[0] = 0;
12217 }
12218
12219 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12220 {
12221 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12222 {
12223 if (debug == 7) printf("@@@@ rx un-key\n");
12224 if(myrpt->p.duplex && myrpt->keyed) {
12225 rpt_telemetry(myrpt,UNKEY,NULL);
12226 }
12227 }
12228 myrpt->keyed = 0;
12229 time(&myrpt->lastkeyedtime);
12230 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12231 if (myrpt->p.archivedir)
12232 {
12233 donodelog(myrpt,"RXUNKEY,MAIN");
12234 }
12235 }
12236 }
12237 ast_frfree(f);
12238 continue;
12239 }
12240 if (who == myrpt->pchannel)
12241 {
12242 f = ast_read(myrpt->pchannel);
12243 if (!f)
12244 {
12245 if (debug) printf("@@@@ rpt:Hung Up\n");
12246 break;
12247 }
12248 if (f->frametype == AST_FRAME_VOICE)
12249 {
12250 ast_write(myrpt->txpchannel,f);
12251 }
12252 if (f->frametype == AST_FRAME_CONTROL)
12253 {
12254 if (f->subclass == AST_CONTROL_HANGUP)
12255 {
12256 if (debug) printf("@@@@ rpt:Hung Up\n");
12257 ast_frfree(f);
12258 break;
12259 }
12260 }
12261 ast_frfree(f);
12262 continue;
12263 }
12264 if (who == myrpt->txchannel)
12265 {
12266 f = ast_read(myrpt->txchannel);
12267 if (!f)
12268 {
12269 if (debug) printf("@@@@ rpt:Hung Up\n");
12270 break;
12271 }
12272 if (f->frametype == AST_FRAME_CONTROL)
12273 {
12274 if (f->subclass == AST_CONTROL_HANGUP)
12275 {
12276 if (debug) printf("@@@@ rpt:Hung Up\n");
12277 ast_frfree(f);
12278 break;
12279 }
12280 }
12281 ast_frfree(f);
12282 continue;
12283 }
12284 if (who == myrpt->dahditxchannel)
12285 {
12286 f = ast_read(myrpt->dahditxchannel);
12287 if (!f)
12288 {
12289 if (debug) printf("@@@@ rpt:Hung Up\n");
12290 break;
12291 }
12292 if (f->frametype == AST_FRAME_VOICE)
12293 {
12294 struct ast_frame *vframe;
12295
12296 if (myrpt->p.duplex < 2)
12297 {
12298 if (myrpt->txrealkeyed)
12299 {
12300 if ((!myfirst) && myrpt->callmode)
12301 {
12302 x = 0;
12303 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12304 frame_list) x++;
12305 for(;x < myrpt->p.simplexpatchdelay; x++)
12306 {
12307 vframe = ast_frdup(f);
12308 memset(vframe->data.ptr,0,vframe->datalen);
12309 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12310 }
12311 myfirst = 1;
12312 }
12313 vframe = ast_frdup(f);
12314 AST_LIST_INSERT_TAIL(&myrpt->txq,
12315 vframe,frame_list);
12316 } else myfirst = 0;
12317 x = 0;
12318 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12319 frame_list) x++;
12320 if (!x)
12321 {
12322 memset(f->data.ptr,0,f->datalen);
12323 }
12324 else
12325 {
12326 ast_frfree(f);
12327 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12328 frame_list);
12329 }
12330 }
12331 else
12332 {
12333 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12334 frame_list))) ast_frfree(vframe);
12335 }
12336 ast_write(myrpt->txchannel,f);
12337 }
12338 if (f->frametype == AST_FRAME_CONTROL)
12339 {
12340 if (f->subclass == AST_CONTROL_HANGUP)
12341 {
12342 if (debug) printf("@@@@ rpt:Hung Up\n");
12343 ast_frfree(f);
12344 break;
12345 }
12346 }
12347 ast_frfree(f);
12348 continue;
12349 }
12350 toexit = 0;
12351 rpt_mutex_lock(&myrpt->lock);
12352 l = myrpt->links.next;
12353 while(l != &myrpt->links)
12354 {
12355 int remnomute;
12356 struct timeval now;
12357
12358 if (l->disctime)
12359 {
12360 l = l->next;
12361 continue;
12362 }
12363
12364 remrx = 0;
12365
12366 m = myrpt->links.next;
12367 while(m != &myrpt->links)
12368 {
12369
12370 if ((m != l) && (m->lastrx)) remrx = 1;
12371 m = m->next;
12372 }
12373 rpt_mutex_unlock(&myrpt->lock);
12374 now = ast_tvnow();
12375 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12376 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12377 {
12378 l->lastlinktv = now;
12379 remnomute = myrpt->localtx &&
12380 (!(myrpt->cmdnode[0] ||
12381 (myrpt->dtmfidx > -1)));
12382 totx = (((l->isremote) ? (remnomute) :
12383 myrpt->exttx) || remrx) && l->mode;
12384 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12385 {
12386 if (totx)
12387 {
12388 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12389 }
12390 else
12391 {
12392 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12393 }
12394 if (myrpt->p.archivedir)
12395 {
12396 char str[100];
12397
12398 if (totx)
12399 sprintf(str,"TXKEY,%s",l->name);
12400 else
12401 sprintf(str,"TXUNKEY,%s",l->name);
12402 donodelog(myrpt,str);
12403 }
12404 }
12405 l->lasttx = totx;
12406 }
12407 rpt_mutex_lock(&myrpt->lock);
12408 if (who == l->chan)
12409 {
12410 rpt_mutex_unlock(&myrpt->lock);
12411 f = ast_read(l->chan);
12412 if (!f)
12413 {
12414 rpt_mutex_lock(&myrpt->lock);
12415 __kickshort(myrpt);
12416 rpt_mutex_unlock(&myrpt->lock);
12417 if ((!l->disced) && (!l->outbound))
12418 {
12419 if ((l->name[0] == '0') || l->isremote)
12420 l->disctime = 1;
12421 else
12422 l->disctime = DISC_TIME;
12423 rpt_mutex_lock(&myrpt->lock);
12424 ast_hangup(l->chan);
12425 l->chan = 0;
12426 break;
12427 }
12428
12429 if (l->retrytimer)
12430 {
12431 ast_hangup(l->chan);
12432 l->chan = 0;
12433 rpt_mutex_lock(&myrpt->lock);
12434 break;
12435 }
12436 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12437 {
12438 rpt_mutex_lock(&myrpt->lock);
12439 if (l->chan) ast_hangup(l->chan);
12440 l->chan = 0;
12441 l->hasconnected = 1;
12442 l->retrytimer = RETRY_TIMER_MS;
12443 l->elaptime = 0;
12444 l->connecttime = 0;
12445 l->thisconnected = 0;
12446 break;
12447 }
12448 rpt_mutex_lock(&myrpt->lock);
12449
12450 remque((struct qelem *) l);
12451 if (!strcmp(myrpt->cmdnode,l->name))
12452 myrpt->cmdnode[0] = 0;
12453 __kickshort(myrpt);
12454 rpt_mutex_unlock(&myrpt->lock);
12455 if (!l->hasconnected)
12456 rpt_telemetry(myrpt,CONNFAIL,l);
12457 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12458 if (myrpt->p.archivedir)
12459 {
12460 char str[100];
12461
12462 if (!l->hasconnected)
12463 sprintf(str,"LINKFAIL,%s",l->name);
12464 else
12465 sprintf(str,"LINKDISC,%s",l->name);
12466 donodelog(myrpt,str);
12467 }
12468 if (l->lastf1) ast_frfree(l->lastf1);
12469 l->lastf1 = NULL;
12470 if (l->lastf2) ast_frfree(l->lastf2);
12471 l->lastf2 = NULL;
12472
12473 ast_hangup(l->chan);
12474 ast_hangup(l->pchan);
12475 ast_free(l);
12476 rpt_mutex_lock(&myrpt->lock);
12477 break;
12478 }
12479 if (f->frametype == AST_FRAME_VOICE)
12480 {
12481 int ismuted,n1;
12482
12483 if ((l->phonemode) && (l->phonevox))
12484 {
12485 n1 = dovox(&l->vox,
12486 f->data.ptr,f->datalen / 2);
12487 if (n1 != l->wasvox)
12488 {
12489 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12490 l->wasvox = n1;
12491 l->voxtostate = 0;
12492 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12493 else l->voxtotimer = 0;
12494 }
12495 if (l->lastrealrx || n1)
12496 {
12497 if (!myfirst)
12498 {
12499 x = 0;
12500 AST_LIST_TRAVERSE(&l->rxq, f1,
12501 frame_list) x++;
12502 for(;x < myrpt->p.simplexphonedelay; x++)
12503 {
12504 f1 = ast_frdup(f);
12505 memset(f1->data.ptr,0,f1->datalen);
12506 AST_LIST_INSERT_TAIL(&l->rxq,
12507 f1,frame_list);
12508 }
12509 myfirst = 1;
12510 }
12511 f1 = ast_frdup(f);
12512 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12513 } else myfirst = 0;
12514 x = 0;
12515 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12516 if (!x)
12517 {
12518 memset(f->data.ptr,0,f->datalen);
12519 }
12520 else
12521 {
12522 ast_frfree(f);
12523 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12524 }
12525 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12526 {
12527 ismuted = 0;
12528 }
12529
12530 ismuted |= (!l->lastrx);
12531 if (l->dtmfed && l->phonemode) ismuted = 1;
12532 l->dtmfed = 0;
12533 if (ismuted)
12534 {
12535 memset(f->data.ptr,0,f->datalen);
12536 if (l->lastf1)
12537 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12538 if (l->lastf2)
12539 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12540 }
12541 if (f) f2 = ast_frdup(f);
12542 else f2 = NULL;
12543 f1 = l->lastf2;
12544 l->lastf2 = l->lastf1;
12545 l->lastf1 = f2;
12546 if (ismuted)
12547 {
12548 if (l->lastf1)
12549 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12550 if (l->lastf2)
12551 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12552 }
12553 if (f1)
12554 {
12555 ast_write(l->pchan,f1);
12556 ast_frfree(f1);
12557 }
12558 }
12559 else
12560 {
12561 if (!l->lastrx)
12562 memset(f->data.ptr,0,f->datalen);
12563 ast_write(l->pchan,f);
12564 }
12565 }
12566 #ifndef OLD_ASTERISK
12567 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12568 {
12569 if (l->lastf1)
12570 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12571 if (l->lastf2)
12572 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12573 l->dtmfed = 1;
12574 }
12575 #endif
12576 if (f->frametype == AST_FRAME_TEXT)
12577 {
12578 handle_link_data(myrpt,l,f->data.ptr);
12579 }
12580 if (f->frametype == AST_FRAME_DTMF)
12581 {
12582 if (l->lastf1)
12583 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12584 if (l->lastf2)
12585 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12586 l->dtmfed = 1;
12587 handle_link_phone_dtmf(myrpt,l,f->subclass);
12588 }
12589 if (f->frametype == AST_FRAME_CONTROL)
12590 {
12591 if (f->subclass == AST_CONTROL_ANSWER)
12592 {
12593 char lconnected = l->connected;
12594
12595 __kickshort(myrpt);
12596 l->connected = 1;
12597 l->hasconnected = 1;
12598 l->thisconnected = 1;
12599 l->elaptime = -1;
12600 if (!l->phonemode) send_newkey(l->chan);
12601 if (!l->isremote) l->retries = 0;
12602 if (!lconnected)
12603 {
12604 rpt_telemetry(myrpt,CONNECTED,l);
12605 if (myrpt->p.archivedir)
12606 {
12607 char str[100];
12608
12609 if (l->mode)
12610 sprintf(str,"LINKTRX,%s",l->name);
12611 else
12612 sprintf(str,"LINKMONITOR,%s",l->name);
12613 donodelog(myrpt,str);
12614 }
12615 }
12616 else
12617 l->reconnects++;
12618 }
12619
12620 if (f->subclass == AST_CONTROL_RADIO_KEY)
12621 {
12622 if (debug == 7 ) printf("@@@@ rx key\n");
12623 l->lastrealrx = 1;
12624 l->rerxtimer = 0;
12625 if (!l->lastrx1)
12626 {
12627 if (myrpt->p.archivedir)
12628 {
12629 char str[100];
12630
12631 sprintf(str,"RXKEY,%s",l->name);
12632 donodelog(myrpt,str);
12633 }
12634 l->lastrx1 = 1;
12635 }
12636 }
12637
12638 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12639 {
12640 if (debug == 7) printf("@@@@ rx un-key\n");
12641 l->lastrealrx = 0;
12642 l->rerxtimer = 0;
12643 if (l->lastrx1)
12644 {
12645 if (myrpt->p.archivedir)
12646 {
12647 char str[100];
12648
12649 sprintf(str,"RXUNKEY,%s",l->name);
12650 donodelog(myrpt,str);
12651 }
12652 l->lastrx1 = 0;
12653 if(myrpt->p.duplex)
12654 rpt_telemetry(myrpt,LINKUNKEY,l);
12655 }
12656 }
12657 if (f->subclass == AST_CONTROL_HANGUP)
12658 {
12659 ast_frfree(f);
12660 rpt_mutex_lock(&myrpt->lock);
12661 __kickshort(myrpt);
12662 rpt_mutex_unlock(&myrpt->lock);
12663 if ((!l->outbound) && (!l->disced))
12664 {
12665 if ((l->name[0] == '0') || l->isremote)
12666 l->disctime = 1;
12667 else
12668 l->disctime = DISC_TIME;
12669 rpt_mutex_lock(&myrpt->lock);
12670 ast_hangup(l->chan);
12671 l->chan = 0;
12672 break;
12673 }
12674 if (l->retrytimer)
12675 {
12676 if (l->chan) ast_hangup(l->chan);
12677 l->chan = 0;
12678 rpt_mutex_lock(&myrpt->lock);
12679 break;
12680 }
12681 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12682 {
12683 rpt_mutex_lock(&myrpt->lock);
12684 if (l->chan) ast_hangup(l->chan);
12685 l->chan = 0;
12686 l->hasconnected = 1;
12687 l->elaptime = 0;
12688 l->retrytimer = RETRY_TIMER_MS;
12689 l->connecttime = 0;
12690 l->thisconnected = 0;
12691 break;
12692 }
12693 rpt_mutex_lock(&myrpt->lock);
12694
12695 remque((struct qelem *) l);
12696 if (!strcmp(myrpt->cmdnode,l->name))
12697 myrpt->cmdnode[0] = 0;
12698 __kickshort(myrpt);
12699 rpt_mutex_unlock(&myrpt->lock);
12700 if (!l->hasconnected)
12701 rpt_telemetry(myrpt,CONNFAIL,l);
12702 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12703 if (myrpt->p.archivedir)
12704 {
12705 char str[100];
12706
12707 if (!l->hasconnected)
12708 sprintf(str,"LINKFAIL,%s",l->name);
12709 else
12710 sprintf(str,"LINKDISC,%s",l->name);
12711 donodelog(myrpt,str);
12712 }
12713 if (l->lastf1) ast_frfree(l->lastf1);
12714 l->lastf1 = NULL;
12715 if (l->lastf2) ast_frfree(l->lastf2);
12716 l->lastf2 = NULL;
12717
12718 ast_hangup(l->chan);
12719 ast_hangup(l->pchan);
12720 ast_free(l);
12721 rpt_mutex_lock(&myrpt->lock);
12722 break;
12723 }
12724 }
12725 ast_frfree(f);
12726 rpt_mutex_lock(&myrpt->lock);
12727 break;
12728 }
12729 if (who == l->pchan)
12730 {
12731 rpt_mutex_unlock(&myrpt->lock);
12732 f = ast_read(l->pchan);
12733 if (!f)
12734 {
12735 if (debug) printf("@@@@ rpt:Hung Up\n");
12736 toexit = 1;
12737 rpt_mutex_lock(&myrpt->lock);
12738 break;
12739 }
12740 if (f->frametype == AST_FRAME_VOICE)
12741 {
12742 if (l->chan) ast_write(l->chan,f);
12743 }
12744 if (f->frametype == AST_FRAME_CONTROL)
12745 {
12746 if (f->subclass == AST_CONTROL_HANGUP)
12747 {
12748 if (debug) printf("@@@@ rpt:Hung Up\n");
12749 ast_frfree(f);
12750 toexit = 1;
12751 rpt_mutex_lock(&myrpt->lock);
12752 break;
12753 }
12754 }
12755 ast_frfree(f);
12756 rpt_mutex_lock(&myrpt->lock);
12757 break;
12758 }
12759 l = l->next;
12760 }
12761 rpt_mutex_unlock(&myrpt->lock);
12762 if (toexit) break;
12763 if (who == myrpt->monchannel)
12764 {
12765 f = ast_read(myrpt->monchannel);
12766 if (!f)
12767 {
12768 if (debug) printf("@@@@ rpt:Hung Up\n");
12769 break;
12770 }
12771 if (f->frametype == AST_FRAME_VOICE)
12772 {
12773 if (myrpt->monstream)
12774 ast_writestream(myrpt->monstream,f);
12775 }
12776 if (f->frametype == AST_FRAME_CONTROL)
12777 {
12778 if (f->subclass == AST_CONTROL_HANGUP)
12779 {
12780 if (debug) printf("@@@@ rpt:Hung Up\n");
12781 ast_frfree(f);
12782 break;
12783 }
12784 }
12785 ast_frfree(f);
12786 continue;
12787 }
12788 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12789 {
12790 f = ast_read(myrpt->parrotchannel);
12791 if (!f)
12792 {
12793 if (debug) printf("@@@@ rpt:Hung Up\n");
12794 break;
12795 }
12796 if (!myrpt->p.parrotmode)
12797 {
12798 char myfname[300];
12799
12800 if (myrpt->parrotstream)
12801 {
12802 ast_closestream(myrpt->parrotstream);
12803 myrpt->parrotstream = 0;
12804 }
12805 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12806 strcat(myfname,".wav");
12807 unlink(myfname);
12808 } else if (f->frametype == AST_FRAME_VOICE)
12809 {
12810 if (myrpt->parrotstream)
12811 ast_writestream(myrpt->parrotstream,f);
12812 }
12813 if (f->frametype == AST_FRAME_CONTROL)
12814 {
12815 if (f->subclass == AST_CONTROL_HANGUP)
12816 {
12817 if (debug) printf("@@@@ rpt:Hung Up\n");
12818 ast_frfree(f);
12819 break;
12820 }
12821 }
12822 ast_frfree(f);
12823 continue;
12824 }
12825 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12826 {
12827 f = ast_read(myrpt->voxchannel);
12828 if (!f)
12829 {
12830 if (debug) printf("@@@@ rpt:Hung Up\n");
12831 break;
12832 }
12833 if (f->frametype == AST_FRAME_VOICE)
12834 {
12835 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12836 if (n != myrpt->wasvox)
12837 {
12838 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12839 myrpt->wasvox = n;
12840 myrpt->voxtostate = 0;
12841 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12842 else myrpt->voxtotimer = 0;
12843 }
12844 }
12845 if (f->frametype == AST_FRAME_CONTROL)
12846 {
12847 if (f->subclass == AST_CONTROL_HANGUP)
12848 {
12849 if (debug) printf("@@@@ rpt:Hung Up\n");
12850 ast_frfree(f);
12851 break;
12852 }
12853 }
12854 ast_frfree(f);
12855 continue;
12856 }
12857 if (who == myrpt->txpchannel)
12858 {
12859 f = ast_read(myrpt->txpchannel);
12860 if (!f)
12861 {
12862 if (debug) printf("@@@@ rpt:Hung Up\n");
12863 break;
12864 }
12865 if (f->frametype == AST_FRAME_CONTROL)
12866 {
12867 if (f->subclass == AST_CONTROL_HANGUP)
12868 {
12869 if (debug) printf("@@@@ rpt:Hung Up\n");
12870 ast_frfree(f);
12871 break;
12872 }
12873 }
12874 ast_frfree(f);
12875 continue;
12876 }
12877 }
12878 usleep(100000);
12879 ast_hangup(myrpt->pchannel);
12880 ast_hangup(myrpt->monchannel);
12881 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12882 myrpt->parrotstate = 0;
12883 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12884 ast_hangup(myrpt->txpchannel);
12885 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12886 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12887 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12888 myrpt->lastf1 = NULL;
12889 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12890 myrpt->lastf2 = NULL;
12891 ast_hangup(myrpt->rxchannel);
12892 rpt_mutex_lock(&myrpt->lock);
12893 l = myrpt->links.next;
12894 while(l != &myrpt->links)
12895 {
12896 struct rpt_link *ll = l;
12897
12898 remque((struct qelem *) l);
12899
12900 if (l->chan) ast_hangup(l->chan);
12901 ast_hangup(l->pchan);
12902 l = l->next;
12903 ast_free(ll);
12904 }
12905 if (myrpt->xlink == 1) myrpt->xlink = 2;
12906 rpt_mutex_unlock(&myrpt->lock);
12907 if (debug) printf("@@@@ rpt:Hung up channel\n");
12908 myrpt->rpt_thread = AST_PTHREADT_STOP;
12909 pthread_exit(NULL);
12910 return NULL;
12911 }
12912
12913
12914 static void *rpt_master(void *ignore)
12915 {
12916 int i,n;
12917 pthread_attr_t attr;
12918 struct ast_config *cfg;
12919 char *this,*val;
12920
12921
12922 nodelog.next = nodelog.prev = &nodelog;
12923
12924 this = NULL;
12925 n = 0;
12926 #ifndef OLD_ASTERISK
12927
12928 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12929 usleep(250000);
12930 #endif
12931 #ifdef NEW_ASTERISK
12932 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12933 #else
12934 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12935 #endif
12936 cfg = rpt_vars[n].cfg;
12937 if (!cfg) {
12938 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12939 pthread_exit(NULL);
12940 }
12941 while((this = ast_category_browse(cfg,this)) != NULL)
12942 {
12943 for(i = 0 ; i < strlen(this) ; i++){
12944 if((this[i] < '0') || (this[i] > '9'))
12945 break;
12946 }
12947 if(i != strlen(this)) continue;
12948 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12949 rpt_vars[n].name = ast_strdup(this);
12950 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12951 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12952 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12953 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12954 rpt_vars[n].remote = 0;
12955 rpt_vars[n].remoterig = "";
12956 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12957 if (val)
12958 {
12959 rpt_vars[n].remoterig = ast_strdup(val);
12960 rpt_vars[n].remote = 1;
12961 }
12962 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12963 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12964 ast_mutex_init(&rpt_vars[n].lock);
12965 ast_mutex_init(&rpt_vars[n].remlock);
12966 ast_mutex_init(&rpt_vars[n].statpost_lock);
12967 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12968 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12969 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12970 rpt_vars[n].tailmessagen = 0;
12971 #ifdef _MDC_DECODE_H_
12972 rpt_vars[n].mdc = mdc_decoder_new(8000);
12973 #endif
12974 n++;
12975 }
12976 nrpts = n;
12977 ast_config_destroy(cfg);
12978
12979
12980 for(i = 0; i < n; i++)
12981 {
12982 load_rpt_vars(i,1);
12983
12984
12985 if (rpt_vars[i].remote)
12986 {
12987 if(retreive_memory(&rpt_vars[i],"init")){
12988 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
12989 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
12990 else
12991 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
12992 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
12993
12994 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
12995 rpt_vars[i].remmode = REM_MODE_FM;
12996 rpt_vars[i].offset = REM_SIMPLEX;
12997 rpt_vars[i].powerlevel = REM_LOWPWR;
12998 }
12999 continue;
13000 }
13001 else
13002 {
13003 rpt_vars[i].p.memory = rpt_vars[i].name;
13004 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13005 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13006 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13007 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13008 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13009 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13010
13011 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13012 rpt_vars[i].remmode = REM_MODE_FM;
13013 rpt_vars[i].offset = REM_SIMPLEX;
13014 rpt_vars[i].powerlevel = REM_LOWPWR;
13015 }
13016 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13017 }
13018 if (!rpt_vars[i].p.ident)
13019 {
13020 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13021 ast_config_destroy(cfg);
13022 pthread_exit(NULL);
13023 }
13024 pthread_attr_init(&attr);
13025 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13026 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13027 }
13028 usleep(500000);
13029 time(&starttime);
13030 for(;;)
13031 {
13032
13033 for(i = 0; i < n; i++)
13034 {
13035 int rv;
13036 if (rpt_vars[i].remote) continue;
13037 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13038 rv = -1;
13039 else
13040 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13041 if (rv)
13042 {
13043 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13044 {
13045 if(rpt_vars[i].threadrestarts >= 5)
13046 {
13047 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13048 exit(1);
13049 }
13050 else
13051 {
13052 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13053 rpt_vars[i].threadrestarts++;
13054 }
13055 }
13056 else
13057 rpt_vars[i].threadrestarts = 0;
13058
13059 rpt_vars[i].lastthreadrestarttime = time(NULL);
13060 pthread_attr_init(&attr);
13061 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13062 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13063
13064 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13065 }
13066
13067 }
13068 for(;;)
13069 {
13070 struct nodelog *nodep;
13071 char *space,datestr[100],fname[300];
13072 int fd;
13073
13074 ast_mutex_lock(&nodeloglock);
13075 nodep = nodelog.next;
13076 if(nodep == &nodelog)
13077 {
13078 ast_mutex_unlock(&nodeloglock);
13079 break;
13080 }
13081 remque((struct qelem *)nodep);
13082 ast_mutex_unlock(&nodeloglock);
13083 space = strchr(nodep->str,' ');
13084 if (!space)
13085 {
13086 ast_free(nodep);
13087 continue;
13088 }
13089 *space = 0;
13090 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13091 localtime(&nodep->timestamp));
13092 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13093 nodep->str,datestr);
13094 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13095 if (fd == -1)
13096 {
13097 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13098 ast_free(nodep);
13099 continue;
13100 }
13101 if (write(fd,space + 1,strlen(space + 1)) !=
13102 strlen(space + 1))
13103 {
13104 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13105 ast_free(nodep);
13106 continue;
13107 }
13108 close(fd);
13109 ast_free(nodep);
13110 }
13111 sleep(2);
13112 }
13113 ast_config_destroy(cfg);
13114 pthread_exit(NULL);
13115 }
13116
13117 static int rpt_exec(struct ast_channel *chan, void *data)
13118 {
13119 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13120 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13121 int ismuted,dtmfed,phone_vox = 0;
13122 #ifdef OLD_ASTERISK
13123 struct localuser *u;
13124 #endif
13125 char tmp[256], keyed = 0,keyed1 = 0;
13126 char *options,*stringp,*tele,c,*altp,*memp;
13127 char sx[320],*sy;
13128 struct rpt *myrpt;
13129 struct ast_frame *f,*f1,*f2;
13130 struct ast_channel *who;
13131 struct ast_channel *cs[20];
13132 struct rpt_link *l;
13133 struct dahdi_confinfo ci;
13134 struct dahdi_params par;
13135 int ms,elap,nullfd;
13136 time_t t,last_timeout_warning;
13137 struct dahdi_radio_param z;
13138 struct rpt_tele *telem;
13139 int numlinks;
13140
13141 nullfd = open("/dev/null",O_RDWR);
13142 if (ast_strlen_zero(data)) {
13143 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13144 return -1;
13145 }
13146
13147 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13148 time(&t);
13149
13150 if (t < starttime) t = starttime + START_DELAY;
13151 if ((!starttime) || (t < (starttime + START_DELAY)))
13152 {
13153 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13154 ast_safe_sleep(chan,3000);
13155 return -1;
13156 }
13157
13158 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13159
13160 altp=strstr(tmp, "|*");
13161 if(altp){
13162 altp[0]=0;
13163 altp++;
13164 }
13165
13166 memp=strstr(tmp, "|M");
13167 if(memp){
13168 memp[0]=0;
13169 memp+=2;
13170 }
13171
13172 stringp=tmp;
13173 strsep(&stringp, "|");
13174 options = stringp;
13175
13176 ast_log(LOG_NOTICE,"options=%s \n",options);
13177 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13178 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13179
13180 myrpt = NULL;
13181
13182 for(i = 0; i < nrpts; i++)
13183 {
13184
13185 if (!strcmp(tmp,rpt_vars[i].name))
13186 {
13187 myrpt = &rpt_vars[i];
13188 break;
13189 }
13190 }
13191
13192 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13193
13194 if (myrpt == NULL)
13195 {
13196 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13197 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13198 return (priority_jump(NULL,chan));
13199 }
13200
13201 numlinks=linkcount(myrpt);
13202
13203 if(options && *options == 'q')
13204 {
13205 char buf2[128];
13206
13207 if(myrpt->keyed)
13208 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13209 else
13210 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13211
13212 if(myrpt->txkeyed)
13213 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13214 else
13215 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13216
13217 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13218 pbx_builtin_setvar(chan, buf2);
13219 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13220 pbx_builtin_setvar(chan, buf2);
13221 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13222 pbx_builtin_setvar(chan, buf2);
13223 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13224 pbx_builtin_setvar(chan, buf2);
13225 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13226 pbx_builtin_setvar(chan, buf2);
13227 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13228 pbx_builtin_setvar(chan, buf2);
13229
13230
13231
13232
13233 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13234 pbx_builtin_setvar(chan, buf2);
13235 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13236 pbx_builtin_setvar(chan, buf2);
13237
13238 return priority_jump(myrpt,chan);
13239 }
13240
13241 if(options && *options == 'o')
13242 {
13243 return(channel_revert(myrpt));
13244 }
13245
13246 #if 0
13247 if((altp)&&(*options == 'Z'))
13248 {
13249 rpt_push_alt_macro(myrpt,altp);
13250 return 0;
13251 }
13252 #endif
13253
13254
13255
13256 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13257 {
13258 int val;
13259
13260 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13261
13262 myrpt->bargechan=0;
13263 if(options && strstr(options, "f")>0)
13264 {
13265 myrpt->bargechan=1;
13266 }
13267
13268 if(memp>0)
13269 {
13270 char radiochan;
13271 radiochan=strtod(data,NULL);
13272
13273
13274 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13275 {
13276 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13277 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13278 return (priority_jump(myrpt,chan));
13279 }
13280 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13281 {
13282 channel_steer(myrpt,memp);
13283 }
13284 }
13285 if(altp)rpt_push_alt_macro(myrpt,altp);
13286 phone_mode = 1;
13287 if (*options == 'D') phone_mode = 2;
13288 if (*options == 'S') phone_mode = 3;
13289 ast_set_callerid(chan,"0","app_rpt user","0");
13290 val = 1;
13291 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13292 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13293 }
13294 else
13295 {
13296 #ifdef ALLOW_LOCAL_CHANNELS
13297
13298 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13299 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13300 return -1;
13301 }
13302 #else
13303 if (strncmp(chan->name,"IAX2",4))
13304 {
13305 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13306 return -1;
13307 }
13308 #endif
13309 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13310 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13311 return -1;
13312 }
13313 }
13314 if (options && (*options == 'R'))
13315 {
13316
13317 char *return_context;
13318 int length, m, lot, timeout = 0;
13319 char buffer[256],*template;
13320 char *working, *context, *exten, *priority;
13321 char *s,*orig_s;
13322
13323 rpt_mutex_lock(&myrpt->lock);
13324 m = myrpt->callmode;
13325 rpt_mutex_unlock(&myrpt->lock);
13326
13327 if ((!myrpt->p.nobusyout) && m)
13328 {
13329 if (chan->_state != AST_STATE_UP)
13330 {
13331 ast_indicate(chan,AST_CONTROL_BUSY);
13332 }
13333 while(ast_safe_sleep(chan,10000) != -1);
13334 return -1;
13335 }
13336
13337 if (chan->_state != AST_STATE_UP)
13338 {
13339 ast_answer(chan);
13340 if (!phone_mode) send_newkey(chan);
13341 }
13342
13343 length=strlen(options)+2;
13344 orig_s=ast_malloc(length);
13345 if(!orig_s) {
13346 ast_log(LOG_WARNING, "Out of memory\n");
13347 return -1;
13348 }
13349 s=orig_s;
13350 strncpy(s,options,length);
13351
13352 template=strsep(&s,"|");
13353 if(!template) {
13354 ast_log(LOG_WARNING, "An announce template must be defined\n");
13355 ast_free(orig_s);
13356 return -1;
13357 }
13358
13359 if(s) {
13360 timeout = atoi(strsep(&s, "|"));
13361 timeout *= 1000;
13362 }
13363
13364 return_context = s;
13365
13366 if(return_context != NULL) {
13367
13368
13369 working = return_context;
13370 context = strsep(&working, "|");
13371 exten = strsep(&working, "|");
13372 if(!exten) {
13373
13374 priority = context;
13375 exten = NULL;
13376 context = NULL;
13377 } else {
13378 priority = strsep(&working, "|");
13379 if(!priority) {
13380
13381 priority = exten;
13382 exten = context;
13383 context = NULL;
13384 }
13385 }
13386 if(atoi(priority) < 0) {
13387 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13388 ast_free(orig_s);
13389 return -1;
13390 }
13391
13392 chan->priority = atoi(priority);
13393 #ifdef OLD_ASTERISK
13394 if(exten && strcasecmp(exten, "BYEXTENSION"))
13395 #else
13396 if(exten)
13397 #endif
13398 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13399 if(context)
13400 strncpy(chan->context, context, sizeof(chan->context)-1);
13401 } else {
13402 chan->priority++;
13403 }
13404
13405 if(option_verbose > 2) {
13406 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
13407 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
13408 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13409 }
13410 }
13411
13412
13413
13414
13415 ast_masq_park_call(chan, NULL, timeout, &lot);
13416
13417 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13418
13419 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13420
13421 rpt_telemetry(myrpt,REV_PATCH,buffer);
13422
13423 ast_free(orig_s);
13424
13425 return 0;
13426
13427 }
13428
13429 if (!options)
13430 {
13431 struct ast_hostent ahp;
13432 struct hostent *hp;
13433 struct in_addr ia;
13434 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13435
13436
13437 if (!chan->cid.cid_num)
13438 {
13439 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13440 return -1;
13441 }
13442
13443 memset(hisip,0,sizeof(hisip));
13444 #ifdef ALLOW_LOCAL_CHANNELS
13445
13446 if (strncmp(chan->name,"Local",5)==0) {
13447 strcpy(hisip,"127.0.0.1");
13448 } else {
13449 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13450 }
13451 #else
13452 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13453 #endif
13454
13455 if (!hisip[0])
13456 {
13457 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13458 return -1;
13459 }
13460
13461 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13462 ast_shrink_phone_number(b1);
13463 if (!strcmp(myrpt->name,b1))
13464 {
13465 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13466 return -1;
13467 }
13468
13469 if (*b1 < '1')
13470 {
13471 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13472 return -1;
13473 }
13474
13475
13476
13477 val = node_lookup(myrpt,b1);
13478 if (!val)
13479 {
13480 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13481 return -1;
13482 }
13483 strncpy(tmp,val,sizeof(tmp) - 1);
13484 s = tmp;
13485 s1 = strsep(&s,",");
13486 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13487 {
13488 sy = strchr(s1,'/');
13489 *sy = 0;
13490 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13491 s1 = sx;
13492 }
13493 s2 = strsep(&s,",");
13494 if (!s2)
13495 {
13496 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13497 return -1;
13498 }
13499 if (strcmp(s2,"NONE")) {
13500 hp = ast_gethostbyname(s2, &ahp);
13501 if (!hp)
13502 {
13503 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13504 return -1;
13505 }
13506 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13507 #ifdef OLD_ASTERISK
13508 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13509 #else
13510 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13511 #endif
13512 s3 = strchr(hisip,':');
13513 if (s3) *s3 = 0;
13514 if (strcmp(hisip,nodeip))
13515 {
13516 s3 = strchr(s1,'@');
13517 if (s3) s1 = s3 + 1;
13518 s3 = strchr(s1,'/');
13519 if (s3) *s3 = 0;
13520 s3 = strchr(s1,':');
13521 if (s3) *s3 = 0;
13522 hp = ast_gethostbyname(s1, &ahp);
13523 if (!hp)
13524 {
13525 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13526 return -1;
13527 }
13528 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13529 #ifdef OLD_ASTERISK
13530 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13531 #else
13532 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13533 #endif
13534 if (strcmp(hisip,nodeip))
13535 {
13536 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13537 return -1;
13538 }
13539 }
13540 }
13541 }
13542
13543
13544 if (!myrpt->remote)
13545 {
13546 char *b,*b1;
13547 int reconnects = 0;
13548
13549 rpt_mutex_lock(&myrpt->lock);
13550 i = myrpt->xlink;
13551 rpt_mutex_unlock(&myrpt->lock);
13552 if (i)
13553 {
13554 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13555 return -1;
13556 }
13557
13558 if (!chan->cid.cid_num)
13559 {
13560 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13561 return -1;
13562 }
13563
13564 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13565 ast_shrink_phone_number(b1);
13566 if (!strcmp(myrpt->name,b1))
13567 {
13568 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13569 return -1;
13570 }
13571 rpt_mutex_lock(&myrpt->lock);
13572 l = myrpt->links.next;
13573
13574 while(l != &myrpt->links)
13575 {
13576 if (l->name[0] == '0')
13577 {
13578 l = l->next;
13579 continue;
13580 }
13581
13582 if (!strcmp(l->name,b1)) break;
13583 l = l->next;
13584 }
13585
13586 if (l != &myrpt->links)
13587 {
13588 l->killme = 1;
13589 l->retries = l->max_retries + 1;
13590 l->disced = 2;
13591 reconnects = l->reconnects;
13592 reconnects++;
13593 rpt_mutex_unlock(&myrpt->lock);
13594 usleep(500000);
13595 } else
13596 rpt_mutex_unlock(&myrpt->lock);
13597
13598 l = ast_malloc(sizeof(struct rpt_link));
13599 if (!l)
13600 {
13601 ast_log(LOG_WARNING, "Unable to malloc\n");
13602 pthread_exit(NULL);
13603 }
13604
13605 memset((char *)l,0,sizeof(struct rpt_link));
13606 l->mode = 1;
13607 strncpy(l->name,b1,MAXNODESTR - 1);
13608 l->isremote = 0;
13609 l->chan = chan;
13610 l->connected = 1;
13611 l->thisconnected = 1;
13612 l->hasconnected = 1;
13613 l->reconnects = reconnects;
13614 l->phonemode = phone_mode;
13615 l->phonevox = phone_vox;
13616 l->lastf1 = NULL;
13617 l->lastf2 = NULL;
13618 l->dtmfed = 0;
13619 voxinit_link(l,1);
13620 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13621 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13622
13623 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13624 if (!l->pchan)
13625 {
13626 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13627 pthread_exit(NULL);
13628 }
13629 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13630 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13631 #ifdef AST_CDR_FLAG_POST_DISABLED
13632 if (l->pchan->cdr)
13633 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13634 #endif
13635
13636 ci.chan = 0;
13637 ci.confno = myrpt->conf;
13638 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13639
13640 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13641 {
13642 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13643 pthread_exit(NULL);
13644 }
13645 rpt_mutex_lock(&myrpt->lock);
13646 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13647 l->max_retries = MAX_RETRIES;
13648
13649 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13650 __kickshort(myrpt);
13651 rpt_mutex_unlock(&myrpt->lock);
13652 if (chan->_state != AST_STATE_UP) {
13653 ast_answer(chan);
13654 if (!phone_mode) send_newkey(chan);
13655 }
13656 if (myrpt->p.archivedir)
13657 {
13658 char str[100];
13659
13660 if (l->phonemode)
13661 sprintf(str,"LINK(P),%s",l->name);
13662 else
13663 sprintf(str,"LINK,%s",l->name);
13664 donodelog(myrpt,str);
13665 }
13666 if (!phone_mode) send_newkey(chan);
13667 return 0;
13668 }
13669
13670 rpt_mutex_lock(&myrpt->lock);
13671
13672 if (myrpt->remoteon)
13673 {
13674 rpt_mutex_unlock(&myrpt->lock);
13675 usleep(500000);
13676 if (myrpt->remoteon)
13677 {
13678 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13679 #ifdef AST_CDR_FLAG_POST_DISABLED
13680 if (chan->cdr)
13681 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13682 #endif
13683 return -1;
13684 }
13685 rpt_mutex_lock(&myrpt->lock);
13686 }
13687 if (myrpt->p.rptnode)
13688 {
13689 char killedit = 0;
13690 time_t now;
13691
13692 time(&now);
13693 for(i = 0; i < nrpts; i++)
13694 {
13695 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13696 {
13697 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13698 rpt_vars[i].keyed ||
13699 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13700 rpt_vars[i].txkeyed ||
13701 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13702 {
13703 rpt_mutex_unlock(&myrpt->lock);
13704 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13705 #ifdef AST_CDR_FLAG_POST_DISABLED
13706 if (chan->cdr)
13707 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13708 #endif
13709 return -1;
13710 }
13711 while(rpt_vars[i].xlink != 3)
13712 {
13713 if (!killedit)
13714 {
13715 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13716 rpt_vars[i].xlink = 1;
13717 killedit = 1;
13718 }
13719 rpt_mutex_unlock(&myrpt->lock);
13720 if (ast_safe_sleep(chan,500) == -1)
13721 {
13722 #ifdef AST_CDR_FLAG_POST_DISABLED
13723 if (chan->cdr)
13724 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13725 #endif
13726 return -1;
13727 }
13728 rpt_mutex_lock(&myrpt->lock);
13729 }
13730 break;
13731 }
13732 }
13733 }
13734
13735 #ifdef HAVE_IOPERM
13736 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13737 (ioperm(myrpt->p.iobase,1,1) == -1))
13738 {
13739 rpt_mutex_unlock(&myrpt->lock);
13740 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13741 return -1;
13742 }
13743 #endif
13744 myrpt->remoteon = 1;
13745 #ifdef OLD_ASTERISK
13746 LOCAL_USER_ADD(u);
13747 #endif
13748 rpt_mutex_unlock(&myrpt->lock);
13749
13750 for(i = 0; i < nrpts; i++)
13751 {
13752 if (&rpt_vars[i] == myrpt)
13753 {
13754 load_rpt_vars(i,0);
13755 break;
13756 }
13757 }
13758 rpt_mutex_lock(&myrpt->lock);
13759 tele = strchr(myrpt->rxchanname,'/');
13760 if (!tele)
13761 {
13762 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13763 rpt_mutex_unlock(&myrpt->lock);
13764 pthread_exit(NULL);
13765 }
13766 *tele++ = 0;
13767 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
13768 myrpt->dahdirxchannel = NULL;
13769 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13770 myrpt->dahdirxchannel = myrpt->rxchannel;
13771 if (myrpt->rxchannel)
13772 {
13773 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13774 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13775 #ifdef AST_CDR_FLAG_POST_DISABLED
13776 if (myrpt->rxchannel->cdr)
13777 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13778 #endif
13779 #ifndef NEW_ASTERISK
13780 myrpt->rxchannel->whentohangup = 0;
13781 #endif
13782 myrpt->rxchannel->appl = "Apprpt";
13783 myrpt->rxchannel->data = "(Link Rx)";
13784 if (option_verbose > 2)
13785 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13786 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13787 rpt_mutex_unlock(&myrpt->lock);
13788 ast_call(myrpt->rxchannel,tele,999);
13789 rpt_mutex_lock(&myrpt->lock);
13790 }
13791 else
13792 {
13793 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13794 rpt_mutex_unlock(&myrpt->lock);
13795 pthread_exit(NULL);
13796 }
13797 *--tele = '/';
13798 myrpt->dahditxchannel = NULL;
13799 if (myrpt->txchanname)
13800 {
13801 tele = strchr(myrpt->txchanname,'/');
13802 if (!tele)
13803 {
13804 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13805 rpt_mutex_unlock(&myrpt->lock);
13806 ast_hangup(myrpt->rxchannel);
13807 pthread_exit(NULL);
13808 }
13809 *tele++ = 0;
13810 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
13811 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13812 myrpt->dahditxchannel = myrpt->txchannel;
13813 if (myrpt->txchannel)
13814 {
13815 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13816 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13817 #ifdef AST_CDR_FLAG_POST_DISABLED
13818 if (myrpt->txchannel->cdr)
13819 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13820 #endif
13821 #ifndef NEW_ASTERISK
13822 myrpt->txchannel->whentohangup = 0;
13823 #endif
13824 myrpt->txchannel->appl = "Apprpt";
13825 myrpt->txchannel->data = "(Link Tx)";
13826 if (option_verbose > 2)
13827 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13828 myrpt->txchanname,tele,myrpt->txchannel->name);
13829 rpt_mutex_unlock(&myrpt->lock);
13830 ast_call(myrpt->txchannel,tele,999);
13831 rpt_mutex_lock(&myrpt->lock);
13832 }
13833 else
13834 {
13835 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13836 rpt_mutex_unlock(&myrpt->lock);
13837 ast_hangup(myrpt->rxchannel);
13838 pthread_exit(NULL);
13839 }
13840 *--tele = '/';
13841 }
13842 else
13843 {
13844 myrpt->txchannel = myrpt->rxchannel;
13845 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13846 myrpt->dahditxchannel = myrpt->rxchannel;
13847 }
13848
13849 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13850 if (!myrpt->pchannel)
13851 {
13852 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13853 rpt_mutex_unlock(&myrpt->lock);
13854 if (myrpt->txchannel != myrpt->rxchannel)
13855 ast_hangup(myrpt->txchannel);
13856 ast_hangup(myrpt->rxchannel);
13857 pthread_exit(NULL);
13858 }
13859 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13860 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13861 #ifdef AST_CDR_FLAG_POST_DISABLED
13862 if (myrpt->pchannel->cdr)
13863 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13864 #endif
13865 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13866 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13867
13868 ci.chan = 0;
13869 ci.confno = -1;
13870 ci.confmode = DAHDI_CONF_CONFANNMON ;
13871
13872 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13873 {
13874 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13875 rpt_mutex_unlock(&myrpt->lock);
13876 ast_hangup(myrpt->pchannel);
13877 if (myrpt->txchannel != myrpt->rxchannel)
13878 ast_hangup(myrpt->txchannel);
13879 ast_hangup(myrpt->rxchannel);
13880 pthread_exit(NULL);
13881 }
13882
13883 myrpt->conf = myrpt->txconf = ci.confno;
13884
13885 myrpt->iofd = -1;
13886 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13887 {
13888 rpt_mutex_unlock(&myrpt->lock);
13889 ast_hangup(myrpt->pchannel);
13890 if (myrpt->txchannel != myrpt->rxchannel)
13891 ast_hangup(myrpt->txchannel);
13892 ast_hangup(myrpt->rxchannel);
13893 pthread_exit(NULL);
13894 }
13895 iskenwood_pci4 = 0;
13896 memset(&z,0,sizeof(z));
13897 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13898 {
13899 z.radpar = DAHDI_RADPAR_REMMODE;
13900 z.data = DAHDI_RADPAR_REM_NONE;
13901 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13902
13903 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13904 {
13905 z.radpar = DAHDI_RADPAR_UIOMODE;
13906 z.data = 1;
13907 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13908 {
13909 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13910 return -1;
13911 }
13912 z.radpar = DAHDI_RADPAR_UIODATA;
13913 z.data = 3;
13914 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13915 {
13916 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13917 return -1;
13918 }
13919 i = DAHDI_OFFHOOK;
13920 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13921 {
13922 ast_log(LOG_ERROR,"Cannot set hook\n");
13923 return -1;
13924 }
13925 iskenwood_pci4 = 1;
13926 }
13927 }
13928 if (myrpt->txchannel == myrpt->dahditxchannel)
13929 {
13930 i = DAHDI_ONHOOK;
13931 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13932
13933 if ((myrpt->iofd < 1) && (!res) &&
13934 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13935 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13936 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13937 {
13938 z.radpar = DAHDI_RADPAR_UIOMODE;
13939 z.data = 1;
13940 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13941 {
13942 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13943 return -1;
13944 }
13945 z.radpar = DAHDI_RADPAR_UIODATA;
13946 z.data = 3;
13947 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13948 {
13949 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13950 return -1;
13951 }
13952 }
13953 }
13954 myrpt->remoterx = 0;
13955 myrpt->remotetx = 0;
13956 myrpt->retxtimer = 0;
13957 myrpt->rerxtimer = 0;
13958 myrpt->remoteon = 1;
13959 myrpt->dtmfidx = -1;
13960 myrpt->dtmfbuf[0] = 0;
13961 myrpt->dtmf_time_rem = 0;
13962 myrpt->hfscanmode = 0;
13963 myrpt->hfscanstatus = 0;
13964 if (myrpt->p.startupmacro)
13965 {
13966 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13967 }
13968 time(&myrpt->start_time);
13969 myrpt->last_activity_time = myrpt->start_time;
13970 last_timeout_warning = 0;
13971 myrpt->reload = 0;
13972 myrpt->tele.next = &myrpt->tele;
13973 myrpt->tele.prev = &myrpt->tele;
13974 myrpt->newkey = 0;
13975 rpt_mutex_unlock(&myrpt->lock);
13976 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13977 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13978 rem_rx = 0;
13979 remkeyed = 0;
13980
13981 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
13982 {
13983 i = 128;
13984 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
13985 }
13986 if (chan->_state != AST_STATE_UP) {
13987 ast_answer(chan);
13988 if (!phone_mode) send_newkey(chan);
13989 }
13990
13991 if (myrpt->rxchannel == myrpt->dahdirxchannel)
13992 {
13993 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
13994 {
13995 if (par.rxisoffhook)
13996 {
13997 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
13998 myrpt->remoterx = 1;
13999 remkeyed = 1;
14000 }
14001 }
14002 }
14003 if (myrpt->p.archivedir)
14004 {
14005 char mycmd[100],mydate[100],*b,*b1;
14006 time_t myt;
14007 long blocksleft;
14008
14009
14010 mkdir(myrpt->p.archivedir,0600);
14011 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14012 mkdir(mycmd,0600);
14013 time(&myt);
14014 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14015 localtime(&myt));
14016 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14017 myrpt->p.archivedir,myrpt->name,mydate);
14018 if (myrpt->p.monminblocks)
14019 {
14020 blocksleft = diskavail(myrpt);
14021 if (myrpt->p.remotetimeout)
14022 {
14023 blocksleft -= (myrpt->p.remotetimeout *
14024 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14025 }
14026 if (blocksleft >= myrpt->p.monminblocks)
14027 ast_cli_command(nullfd,mycmd);
14028 } else ast_cli_command(nullfd,mycmd);
14029
14030 if (!chan->cid.cid_num)
14031 {
14032 b1 = "0";
14033 } else {
14034 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14035 ast_shrink_phone_number(b1);
14036 }
14037 sprintf(mycmd,"CONNECT,%s",b1);
14038 donodelog(myrpt,mycmd);
14039 }
14040 myrpt->loginuser[0] = 0;
14041 myrpt->loginlevel[0] = 0;
14042 myrpt->authtelltimer = 0;
14043 myrpt->authtimer = 0;
14044 authtold = 0;
14045 authreq = 0;
14046 if (myrpt->p.authlevel > 1) authreq = 1;
14047 setrem(myrpt);
14048 n = 0;
14049 dtmfed = 0;
14050 cs[n++] = chan;
14051 cs[n++] = myrpt->rxchannel;
14052 cs[n++] = myrpt->pchannel;
14053 if (myrpt->rxchannel != myrpt->txchannel)
14054 cs[n++] = myrpt->txchannel;
14055 if (!phone_mode) send_newkey(chan);
14056
14057 for(;;)
14058 {
14059 if (ast_check_hangup(chan)) break;
14060 if (ast_check_hangup(myrpt->rxchannel)) break;
14061 notremming = 0;
14062 setting = 0;
14063 reming = 0;
14064 telem = myrpt->tele.next;
14065 while(telem != &myrpt->tele)
14066 {
14067 if (telem->mode == SETREMOTE) setting = 1;
14068 if ((telem->mode == SETREMOTE) ||
14069 (telem->mode == SCAN) ||
14070 (telem->mode == TUNE)) reming = 1;
14071 else notremming = 1;
14072 telem = telem->next;
14073 }
14074 if (myrpt->reload)
14075 {
14076 myrpt->reload = 0;
14077
14078 for(i = 0; i < nrpts; i++)
14079 {
14080 if (&rpt_vars[i] == myrpt)
14081 {
14082 load_rpt_vars(i,0);
14083 break;
14084 }
14085 }
14086 }
14087 time(&t);
14088 if (myrpt->p.remotetimeout)
14089 {
14090 time_t r;
14091
14092 r = (t - myrpt->start_time);
14093 if (r >= myrpt->p.remotetimeout)
14094 {
14095 saynode(myrpt,chan,myrpt->name);
14096 sayfile(chan,"rpt/timeout");
14097 ast_safe_sleep(chan,1000);
14098 break;
14099 }
14100 if ((myrpt->p.remotetimeoutwarning) &&
14101 (r >= (myrpt->p.remotetimeout -
14102 myrpt->p.remotetimeoutwarning)) &&
14103 (r <= (myrpt->p.remotetimeout -
14104 myrpt->p.remotetimeoutwarningfreq)))
14105 {
14106 if (myrpt->p.remotetimeoutwarningfreq)
14107 {
14108 if ((t - last_timeout_warning) >=
14109 myrpt->p.remotetimeoutwarningfreq)
14110 {
14111 time(&last_timeout_warning);
14112 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14113 }
14114 }
14115 else
14116 {
14117 if (!last_timeout_warning)
14118 {
14119 time(&last_timeout_warning);
14120 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14121 }
14122 }
14123 }
14124 }
14125 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14126 {
14127 time_t r;
14128
14129 r = (t - myrpt->last_activity_time);
14130 if (r >= myrpt->p.remoteinacttimeout)
14131 {
14132 saynode(myrpt,chan,myrpt->name);
14133 ast_safe_sleep(chan,1000);
14134 break;
14135 }
14136 if ((myrpt->p.remotetimeoutwarning) &&
14137 (r >= (myrpt->p.remoteinacttimeout -
14138 myrpt->p.remotetimeoutwarning)) &&
14139 (r <= (myrpt->p.remoteinacttimeout -
14140 myrpt->p.remotetimeoutwarningfreq)))
14141 {
14142 if (myrpt->p.remotetimeoutwarningfreq)
14143 {
14144 if ((t - last_timeout_warning) >=
14145 myrpt->p.remotetimeoutwarningfreq)
14146 {
14147 time(&last_timeout_warning);
14148 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14149 }
14150 }
14151 else
14152 {
14153 if (!last_timeout_warning)
14154 {
14155 time(&last_timeout_warning);
14156 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14157 }
14158 }
14159 }
14160 }
14161 ms = MSWAIT;
14162 who = ast_waitfor_n(cs,n,&ms);
14163 if (who == NULL) ms = 0;
14164 elap = MSWAIT - ms;
14165 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14166 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14167 if (!ms) continue;
14168
14169 if (myrpt->dtmf_local_timer)
14170 {
14171 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14172 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14173 }
14174 rpt_mutex_lock(&myrpt->lock);
14175 do_dtmf_local(myrpt,0);
14176 rpt_mutex_unlock(&myrpt->lock);
14177
14178 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14179 rem_totx |= keyed && (!myrpt->tunerequest);
14180 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14181 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14182 rem_totx |= myrpt->tunerequest;
14183
14184 if((debug > 6) && rem_totx) {
14185 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);
14186 }
14187 if (keyed && (!keyed1))
14188 {
14189 keyed1 = 1;
14190 }
14191
14192 if (!keyed && (keyed1))
14193 {
14194 time_t myt;
14195
14196 keyed1 = 0;
14197 time(&myt);
14198
14199 if ((myrpt->p.authlevel) &&
14200 (!myrpt->loginlevel[0]) &&
14201 (myt > (t + 3)))
14202 {
14203 authreq = 1;
14204 authtold = 0;
14205 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14206 }
14207 }
14208
14209 if (rem_rx && (!myrpt->remoterx))
14210 {
14211 myrpt->remoterx = 1;
14212 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14213 }
14214 if ((!rem_rx) && (myrpt->remoterx))
14215 {
14216 myrpt->remoterx = 0;
14217 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14218 }
14219
14220 if (authreq && (!myrpt->loginlevel[0]))
14221 {
14222 if ((!authtold) && ((myrpt->authtelltimer += elap)
14223 >= AUTHTELLTIME))
14224 {
14225 authtold = 1;
14226 rpt_telemetry(myrpt,LOGINREQ,NULL);
14227 }
14228 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14229 {
14230 break;
14231 }
14232 }
14233 if (myrpt->newkey)
14234 {
14235 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14236 {
14237 myrpt->retxtimer = 0;
14238 if ((myrpt->remoterx) && (!myrpt->remotetx))
14239 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14240 else
14241 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14242 }
14243
14244 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14245 {
14246 keyed = 0;
14247 myrpt->rerxtimer = 0;
14248 }
14249 }
14250 if (rem_totx && (!myrpt->remotetx))
14251 {
14252
14253 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14254 {
14255 if(debug > 6)
14256 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14257
14258 myrpt->remotetx = 1;
14259
14260 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14261 {
14262 time(&myrpt->last_activity_time);
14263 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14264 {
14265 z.radpar = DAHDI_RADPAR_UIODATA;
14266 z.data = 1;
14267 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14268 {
14269 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14270 return -1;
14271 }
14272 }
14273 else
14274 {
14275 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14276 }
14277 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14278 }
14279 }
14280 }
14281 if ((!rem_totx) && myrpt->remotetx)
14282 {
14283 myrpt->remotetx = 0;
14284 if(!myrpt->remtxfreqok){
14285 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14286 }
14287 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14288 {
14289 z.radpar = DAHDI_RADPAR_UIODATA;
14290 z.data = 3;
14291 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14292 {
14293 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14294 return -1;
14295 }
14296 }
14297 else
14298 {
14299 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14300 }
14301 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14302 }
14303 if (myrpt->hfscanmode){
14304 myrpt->scantimer -= elap;
14305 if(myrpt->scantimer <= 0){
14306 if (!reming)
14307 {
14308 myrpt->scantimer = REM_SCANTIME;
14309 rpt_telemetry(myrpt,SCAN,0);
14310 } else myrpt->scantimer = 1;
14311 }
14312 }
14313 rpt_mutex_lock(&myrpt->lock);
14314 c = myrpt->macrobuf[0];
14315 if (c && (!myrpt->macrotimer))
14316 {
14317 myrpt->macrotimer = MACROTIME;
14318 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14319 if ((c == 'p') || (c == 'P'))
14320 myrpt->macrotimer = MACROPTIME;
14321 rpt_mutex_unlock(&myrpt->lock);
14322 if (myrpt->p.archivedir)
14323 {
14324 char str[100];
14325 sprintf(str,"DTMF(M),%c",c);
14326 donodelog(myrpt,str);
14327 }
14328 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14329 continue;
14330 } else rpt_mutex_unlock(&myrpt->lock);
14331 if (who == chan)
14332 {
14333 f = ast_read(chan);
14334 if (!f)
14335 {
14336 if (debug) printf("@@@@ link:Hung Up\n");
14337 break;
14338 }
14339 if (f->frametype == AST_FRAME_VOICE)
14340 {
14341 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14342 {
14343 ismuted = 0;
14344 }
14345
14346 ismuted |= (!myrpt->remotetx);
14347 if (dtmfed && phone_mode) ismuted = 1;
14348 dtmfed = 0;
14349 if (ismuted)
14350 {
14351 memset(f->data.ptr,0,f->datalen);
14352 if (myrpt->lastf1)
14353 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14354 if (myrpt->lastf2)
14355 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14356 }
14357 if (f) f2 = ast_frdup(f);
14358 else f2 = NULL;
14359 f1 = myrpt->lastf2;
14360 myrpt->lastf2 = myrpt->lastf1;
14361 myrpt->lastf1 = f2;
14362 if (ismuted)
14363 {
14364 if (myrpt->lastf1)
14365 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14366 if (myrpt->lastf2)
14367 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14368 }
14369 if (f1)
14370 {
14371 if (phone_mode)
14372 ast_write(myrpt->txchannel,f1);
14373 else
14374 ast_write(myrpt->txchannel,f);
14375 ast_frfree(f1);
14376 }
14377 }
14378 #ifndef OLD_ASTERISK
14379 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14380 {
14381 if (myrpt->lastf1)
14382 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14383 if (myrpt->lastf2)
14384 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14385 dtmfed = 1;
14386 }
14387 #endif
14388 if (f->frametype == AST_FRAME_DTMF)
14389 {
14390 if (myrpt->lastf1)
14391 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14392 if (myrpt->lastf2)
14393 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14394 dtmfed = 1;
14395 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
14396 {
14397 if (debug) printf("@@@@ rpt:Hung Up\n");
14398 ast_frfree(f);
14399 break;
14400 }
14401 }
14402 if (f->frametype == AST_FRAME_TEXT)
14403 {
14404 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14405 {
14406 if (debug) printf("@@@@ rpt:Hung Up\n");
14407 ast_frfree(f);
14408 break;
14409 }
14410 }
14411 if (f->frametype == AST_FRAME_CONTROL)
14412 {
14413 if (f->subclass == AST_CONTROL_HANGUP)
14414 {
14415 if (debug) printf("@@@@ rpt:Hung Up\n");
14416 ast_frfree(f);
14417 break;
14418 }
14419
14420 if (f->subclass == AST_CONTROL_RADIO_KEY)
14421 {
14422 if (debug == 7) printf("@@@@ rx key\n");
14423 keyed = 1;
14424 myrpt->rerxtimer = 0;
14425 }
14426
14427 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14428 {
14429 myrpt->rerxtimer = 0;
14430 if (debug == 7) printf("@@@@ rx un-key\n");
14431 keyed = 0;
14432 }
14433 }
14434 ast_frfree(f);
14435 continue;
14436 }
14437 if (who == myrpt->rxchannel)
14438 {
14439 f = ast_read(myrpt->rxchannel);
14440 if (!f)
14441 {
14442 if (debug) printf("@@@@ link:Hung Up\n");
14443 break;
14444 }
14445 if (f->frametype == AST_FRAME_VOICE)
14446 {
14447 int myreming = 0;
14448
14449 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14450 myreming = reming;
14451
14452 if (myreming || (!remkeyed) ||
14453 ((myrpt->remote) && (myrpt->remotetx)) ||
14454 ((myrpt->remmode != REM_MODE_FM) &&
14455 notremming))
14456 memset(f->data.ptr,0,f->datalen);
14457 ast_write(myrpt->pchannel,f);
14458 }
14459 else if (f->frametype == AST_FRAME_CONTROL)
14460 {
14461 if (f->subclass == AST_CONTROL_HANGUP)
14462 {
14463 if (debug) printf("@@@@ rpt:Hung Up\n");
14464 ast_frfree(f);
14465 break;
14466 }
14467
14468 if (f->subclass == AST_CONTROL_RADIO_KEY)
14469 {
14470 if (debug == 7) printf("@@@@ remote rx key\n");
14471 if (!myrpt->remotetx)
14472 {
14473 remkeyed = 1;
14474 }
14475 }
14476
14477 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14478 {
14479 if (debug == 7) printf("@@@@ remote rx un-key\n");
14480 if (!myrpt->remotetx)
14481 {
14482 remkeyed = 0;
14483 }
14484 }
14485 }
14486 ast_frfree(f);
14487 continue;
14488 }
14489 if (who == myrpt->pchannel)
14490 {
14491 f = ast_read(myrpt->pchannel);
14492 if (!f)
14493 {
14494 if (debug) printf("@@@@ link:Hung Up\n");
14495 break;
14496 }
14497 if (f->frametype == AST_FRAME_VOICE)
14498 {
14499 ast_write(chan,f);
14500 }
14501 if (f->frametype == AST_FRAME_CONTROL)
14502 {
14503 if (f->subclass == AST_CONTROL_HANGUP)
14504 {
14505 if (debug) printf("@@@@ rpt:Hung Up\n");
14506 ast_frfree(f);
14507 break;
14508 }
14509 }
14510 ast_frfree(f);
14511 continue;
14512 }
14513 if ((myrpt->rxchannel != myrpt->txchannel) &&
14514 (who == myrpt->txchannel))
14515 {
14516 f = ast_read(myrpt->txchannel);
14517 if (!f)
14518 {
14519 if (debug) printf("@@@@ link:Hung Up\n");
14520 break;
14521 }
14522 if (f->frametype == AST_FRAME_CONTROL)
14523 {
14524 if (f->subclass == AST_CONTROL_HANGUP)
14525 {
14526 if (debug) printf("@@@@ rpt:Hung Up\n");
14527 ast_frfree(f);
14528 break;
14529 }
14530 }
14531 ast_frfree(f);
14532 continue;
14533 }
14534 }
14535 if (myrpt->p.archivedir)
14536 {
14537 char mycmd[100],*b,*b1;
14538
14539
14540 if (!chan->cid.cid_num)
14541 {
14542 b1 = "0";
14543 } else {
14544 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14545 ast_shrink_phone_number(b1);
14546 }
14547 sprintf(mycmd,"DISCONNECT,%s",b1);
14548 donodelog(myrpt,mycmd);
14549 }
14550
14551 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14552 sprintf(tmp,"mixmonitor stop %s",chan->name);
14553 ast_cli_command(nullfd,tmp);
14554 close(nullfd);
14555 rpt_mutex_lock(&myrpt->lock);
14556 myrpt->hfscanmode = 0;
14557 myrpt->hfscanstatus = 0;
14558 myrpt->remoteon = 0;
14559 rpt_mutex_unlock(&myrpt->lock);
14560 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14561 myrpt->lastf1 = NULL;
14562 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14563 myrpt->lastf2 = NULL;
14564 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14565 {
14566 z.radpar = DAHDI_RADPAR_UIOMODE;
14567 z.data = 3;
14568 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14569 {
14570 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14571 return -1;
14572 }
14573 z.radpar = DAHDI_RADPAR_UIODATA;
14574 z.data = 3;
14575 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14576 {
14577 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14578 return -1;
14579 }
14580 i = DAHDI_OFFHOOK;
14581 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14582 {
14583 ast_log(LOG_ERROR,"Cannot set hook\n");
14584 return -1;
14585 }
14586 }
14587 if (myrpt->iofd) close(myrpt->iofd);
14588 myrpt->iofd = -1;
14589 ast_hangup(myrpt->pchannel);
14590 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14591 ast_hangup(myrpt->rxchannel);
14592 closerem(myrpt);
14593 if (myrpt->p.rptnode)
14594 {
14595 rpt_mutex_lock(&myrpt->lock);
14596 for(i = 0; i < nrpts; i++)
14597 {
14598 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14599 {
14600 rpt_vars[i].xlink = 0;
14601 break;
14602 }
14603 }
14604 rpt_mutex_unlock(&myrpt->lock);
14605 }
14606 #ifdef OLD_ASTERISK
14607 LOCAL_USER_REMOVE(u);
14608 #endif
14609 return res;
14610 }
14611
14612 #ifndef OLD_ASTERISK
14613
14614
14615
14616 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14617 {
14618 int i;
14619 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14620 astman_append(s, "<nodes>\r\n");
14621 for (i=0; i< nrpts; i++)
14622 {
14623 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14624 }
14625 astman_append(s, "</nodes>\r\n");
14626 astman_append(s, "\r\n");
14627 return RESULT_SUCCESS;
14628 }
14629
14630
14631
14632
14633
14634
14635
14636 static void rpt_manager_success(struct mansession *s, const struct message *m)
14637 {
14638 const char *id = astman_get_header(m, "ActionID");
14639 if (!ast_strlen_zero(id))
14640 astman_append(s, "ActionID: %s\r\n", id);
14641 astman_append(s, "Response: Success\r\n");
14642 }
14643
14644
14645
14646
14647
14648 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14649 {
14650 int i,j,numoflinks;
14651 int dailytxtime, dailykerchunks;
14652 time_t now;
14653 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14654 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14655 long long totaltxtime;
14656 struct rpt_link *l;
14657 char *listoflinks[MAX_STAT_LINKS];
14658 char *lastdtmfcommand,*parrot_ena;
14659 char *tot_state, *ider_state, *patch_state;
14660 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14661 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14662 char *transmitterkeyed;
14663 const char *node = astman_get_header(m, "Node");
14664 struct rpt *myrpt;
14665
14666 static char *not_applicable = "N/A";
14667
14668 tot_state = ider_state =
14669 patch_state = reverse_patch_state =
14670 input_signal = not_applicable;
14671 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14672
14673 time(&now);
14674 for(i = 0; i < nrpts; i++)
14675 {
14676 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14677 rpt_manager_success(s,m);
14678
14679 myrpt = &rpt_vars[i];
14680
14681 if(myrpt->remote){
14682 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14683 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14684 char offsetc,powerlevelc;
14685
14686 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14687
14688 rpt_mutex_lock(&myrpt->lock);
14689 if((remoteon = myrpt->remoteon)){
14690 if(!ast_strlen_zero(myrpt->loginuser))
14691 loginuser = ast_strdup(myrpt->loginuser);
14692 if(!ast_strlen_zero(myrpt->loginlevel))
14693 loginlevel = ast_strdup(myrpt->loginlevel);
14694 if(!ast_strlen_zero(myrpt->freq))
14695 freq = ast_strdup(myrpt->freq);
14696 if(!ast_strlen_zero(myrpt->rxpl))
14697 rxpl = ast_strdup(myrpt->rxpl);
14698 if(!ast_strlen_zero(myrpt->txpl))
14699 txpl = ast_strdup(myrpt->txpl);
14700 remmode = myrpt->remmode;
14701 offset = myrpt->offset;
14702 powerlevel = myrpt->powerlevel;
14703 rxplon = myrpt->rxplon;
14704 txplon = myrpt->txplon;
14705 }
14706 rpt_mutex_unlock(&myrpt->lock);
14707 astman_append(s, "IsRemoteBase: YES\r\n");
14708 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14709 if(remoteon){
14710 if(loginuser){
14711 astman_append(s, "LogInUser: %s\r\n", loginuser);
14712 ast_free(loginuser);
14713 }
14714 if(loginlevel){
14715 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14716 ast_free(loginlevel);
14717 }
14718 if(freq){
14719 astman_append(s, "Freq: %s\r\n", freq);
14720 ast_free(freq);
14721 }
14722 reportfmstuff = 0;
14723 switch(remmode){
14724 case REM_MODE_FM:
14725 modestr = "FM";
14726 reportfmstuff = 1;
14727 break;
14728 case REM_MODE_AM:
14729 modestr = "AM";
14730 break;
14731 case REM_MODE_USB:
14732 modestr = "USB";
14733 break;
14734 default:
14735 modestr = "LSB";
14736 break;
14737 }
14738 astman_append(s, "RemMode: %s\r\n", modestr);
14739 if(reportfmstuff){
14740 switch(offset){
14741 case REM_SIMPLEX:
14742 offsetc = 'S';
14743 break;
14744 case REM_MINUS:
14745 offsetc = '-';
14746 break;
14747 default:
14748 offsetc = '+';
14749 break;
14750 }
14751 astman_append(s, "RemOffset: %c\r\n", offsetc);
14752 if(rxplon && rxpl){
14753 astman_append(s, "RxPl: %s\r\n",rxpl);
14754 ast_free(rxpl);
14755 }
14756 if(txplon && txpl){
14757 astman_append(s, "TxPl: %s\r\n",txpl);
14758 ast_free(txpl);
14759 }
14760 }
14761 switch(powerlevel){
14762 case REM_LOWPWR:
14763 powerlevelc = 'L';
14764 break;
14765 case REM_MEDPWR:
14766 powerlevelc = 'M';
14767 break;
14768 default:
14769 powerlevelc = 'H';
14770 break;
14771 }
14772 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14773 }
14774 astman_append(s, "\r\n");
14775 return 0;
14776 }
14777
14778
14779
14780 rpt_mutex_lock(&myrpt->lock);
14781 dailytxtime = myrpt->dailytxtime;
14782 totaltxtime = myrpt->totaltxtime;
14783 dailykeyups = myrpt->dailykeyups;
14784 totalkeyups = myrpt->totalkeyups;
14785 dailykerchunks = myrpt->dailykerchunks;
14786 totalkerchunks = myrpt->totalkerchunks;
14787 dailyexecdcommands = myrpt->dailyexecdcommands;
14788 totalexecdcommands = myrpt->totalexecdcommands;
14789 timeouts = myrpt->timeouts;
14790
14791
14792
14793 reverse_patch_state = "DOWN";
14794 numoflinks = 0;
14795 l = myrpt->links.next;
14796 while(l && (l != &myrpt->links)){
14797 if(numoflinks >= MAX_STAT_LINKS){
14798 ast_log(LOG_NOTICE,
14799 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14800 break;
14801 }
14802 if (l->name[0] == '0'){
14803 reverse_patch_state = "UP";
14804 l = l->next;
14805 continue;
14806 }
14807 listoflinks[numoflinks] = ast_strdup(l->name);
14808 if(listoflinks[numoflinks] == NULL){
14809 break;
14810 }
14811 else{
14812 numoflinks++;
14813 }
14814 l = l->next;
14815 }
14816
14817 if(myrpt->keyed)
14818 input_signal = "YES";
14819 else
14820 input_signal = "NO";
14821
14822 if(myrpt->txkeyed)
14823 transmitterkeyed = "YES";
14824 else
14825 transmitterkeyed = "NO";
14826
14827 if(myrpt->p.parrotmode)
14828 parrot_ena = "ENABLED";
14829 else
14830 parrot_ena = "DISABLED";
14831
14832 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14833 sys_ena = "DISABLED";
14834 else
14835 sys_ena = "ENABLED";
14836
14837 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14838 tot_ena = "DISABLED";
14839 else
14840 tot_ena = "ENABLED";
14841
14842 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14843 link_ena = "DISABLED";
14844 else
14845 link_ena = "ENABLED";
14846
14847 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14848 patch_ena = "DISABLED";
14849 else
14850 patch_ena = "ENABLED";
14851
14852 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14853 sch_ena = "DISABLED";
14854 else
14855 sch_ena = "ENABLED";
14856
14857 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14858 user_funs = "DISABLED";
14859 else
14860 user_funs = "ENABLED";
14861
14862 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14863 tail_type = "ALTERNATE";
14864 else
14865 tail_type = "STANDARD";
14866
14867 if(!myrpt->totimer)
14868 tot_state = "TIMED OUT!";
14869 else if(myrpt->totimer != myrpt->p.totime)
14870 tot_state = "ARMED";
14871 else
14872 tot_state = "RESET";
14873
14874 if(myrpt->tailid)
14875 ider_state = "QUEUED IN TAIL";
14876 else if(myrpt->mustid)
14877 ider_state = "QUEUED FOR CLEANUP";
14878 else
14879 ider_state = "CLEAN";
14880
14881 switch(myrpt->callmode){
14882 case 1:
14883 patch_state = "DIALING";
14884 break;
14885 case 2:
14886 patch_state = "CONNECTING";
14887 break;
14888 case 3:
14889 patch_state = "UP";
14890 break;
14891
14892 case 4:
14893 patch_state = "CALL FAILED";
14894 break;
14895
14896 default:
14897 patch_state = "DOWN";
14898 }
14899
14900 if(strlen(myrpt->exten)){
14901 called_number = ast_strdup(myrpt->exten);
14902 }
14903
14904 if(strlen(myrpt->lastdtmfcommand)){
14905 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14906 }
14907 rpt_mutex_unlock(&myrpt->lock);
14908
14909 astman_append(s, "IsRemoteBase: NO\r\n");
14910 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14911 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14912 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14913 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14914 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14915 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14916 astman_append(s, "TailLength: %s\r\n", tail_type);
14917 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14918 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14919 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14920 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14921 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14922 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14923 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14924 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14925 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14926 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14927 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14928 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14929 hours = dailytxtime/3600000;
14930 dailytxtime %= 3600000;
14931 minutes = dailytxtime/60000;
14932 dailytxtime %= 60000;
14933 seconds = dailytxtime/1000;
14934 dailytxtime %= 1000;
14935
14936 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14937 hours, minutes, seconds, dailytxtime);
14938
14939 hours = (int) totaltxtime/3600000;
14940 totaltxtime %= 3600000;
14941 minutes = (int) totaltxtime/60000;
14942 totaltxtime %= 60000;
14943 seconds = (int) totaltxtime/1000;
14944 totaltxtime %= 1000;
14945
14946 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14947 hours, minutes, seconds, (int) totaltxtime);
14948
14949 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14950 if(!numoflinks){
14951 strcat(str,"<NONE>");
14952 }
14953 else{
14954 for(j = 0 ;j < numoflinks; j++){
14955 sprintf(str+strlen(str), "%s", listoflinks[j]);
14956 if(j < numoflinks - 1)
14957 strcat(str,",");
14958 }
14959 }
14960 astman_append(s,"%s\r\n", str);
14961
14962 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14963 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14964 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14965 (called_number && strlen(called_number)) ? called_number : not_applicable);
14966 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14967 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14968 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14969
14970 for(j = 0; j < numoflinks; j++){
14971 ast_free(listoflinks[j]);
14972 }
14973 if(called_number){
14974 ast_free(called_number);
14975 }
14976 if(lastdtmfcommand){
14977 ast_free(lastdtmfcommand);
14978 }
14979 astman_append(s, "\r\n");
14980 return 0;
14981 }
14982 }
14983 astman_send_error(s, m, "RptStatus unknown or missing node");
14984 return -1;
14985 }
14986
14987
14988
14989
14990
14991
14992
14993 static int manager_rpt_status(struct mansession *s, const struct message *m)
14994 {
14995 int i,res,len,idx;
14996 int uptime,hours,minutes;
14997 time_t now;
14998 const char *cmd = astman_get_header(m, "Command");
14999 char *str;
15000 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15001 struct mgrcmdtbl{
15002 const char *cmd;
15003 int index;
15004 };
15005 static struct mgrcmdtbl mct[] = {
15006 {"RptStat",MGRCMD_RPTSTAT},
15007 {"NodeStat",MGRCMD_NODESTAT},
15008 {NULL,0}
15009 };
15010
15011 time(&now);
15012
15013 len = 1024;
15014 if(!(str = ast_malloc(len)))
15015 return -1;
15016
15017
15018 if(ast_strlen_zero(cmd)){
15019 astman_send_error(s, m, "RptStatus missing command");
15020 ast_free(str);
15021 return 0;
15022 }
15023
15024 for(i = 0 ; mct[i].cmd ; i++){
15025 if(!strcmp(mct[i].cmd, cmd))
15026 break;
15027 }
15028
15029 if(!mct[i].cmd){
15030 astman_send_error(s, m, "RptStatus unknown command");
15031 ast_free(str);
15032 return 0;
15033 }
15034 else
15035 idx = mct[i].index;
15036
15037 switch(idx){
15038
15039 case MGRCMD_RPTSTAT:
15040
15041 if((res = snprintf(str, len, "Nodes: ")) > -1)
15042 len -= res;
15043 else{
15044 ast_free(str);
15045 return 0;
15046 }
15047 for(i = 0; i < nrpts; i++){
15048 if(i < nrpts - 1){
15049 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15050 ast_free(str);
15051 return 0;
15052 }
15053 }
15054 else{
15055 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15056 ast_free(str);
15057 return 0;
15058 }
15059 }
15060 len -= res;
15061 }
15062
15063 rpt_manager_success(s,m);
15064
15065 if(!nrpts)
15066 astman_append(s, "<NONE>\r\n");
15067 else
15068 astman_append(s, "%s\r\n", str);
15069
15070 uptime = (int)(now - starttime);
15071 hours = uptime/3600;
15072 uptime %= 3600;
15073 minutes = uptime/60;
15074 uptime %= 60;
15075
15076 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15077 hours, minutes, uptime);
15078
15079 astman_append(s, "\r\n");
15080 break;
15081
15082 case MGRCMD_NODESTAT:
15083 res = rpt_manager_do_stats(s,m,str);
15084 ast_free(str);
15085 return res;
15086
15087 default:
15088 astman_send_error(s, m, "RptStatus invalid command");
15089 break;
15090 }
15091 ast_free(str);
15092 return 0;
15093 }
15094
15095 #endif
15096
15097 #ifdef OLD_ASTERISK
15098 int unload_module()
15099 #else
15100 static int unload_module(void)
15101 #endif
15102 {
15103 int i, res;
15104
15105 #ifdef OLD_ASTERISK
15106 STANDARD_HANGUP_LOCALUSERS;
15107 #endif
15108 for(i = 0; i < nrpts; i++) {
15109 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15110 ast_mutex_destroy(&rpt_vars[i].lock);
15111 ast_mutex_destroy(&rpt_vars[i].remlock);
15112 }
15113 res = ast_unregister_application(app);
15114
15115 #ifdef NEW_ASTERISK
15116 ast_cli_unregister_multiple(rpt_cli,sizeof(rpt_cli) /
15117 sizeof(struct ast_cli_entry));
15118 #else
15119
15120 ast_cli_unregister(&cli_debug);
15121 ast_cli_unregister(&cli_dump);
15122 ast_cli_unregister(&cli_stats);
15123 ast_cli_unregister(&cli_lstats);
15124 ast_cli_unregister(&cli_nodes);
15125 ast_cli_unregister(&cli_local_nodes);
15126 ast_cli_unregister(&cli_reload);
15127 ast_cli_unregister(&cli_restart);
15128 ast_cli_unregister(&cli_fun);
15129 ast_cli_unregister(&cli_fun1);
15130 res |= ast_cli_unregister(&cli_cmd);
15131 #endif
15132 #ifndef OLD_ASTERISK
15133 res |= ast_manager_unregister("RptLocalNodes");
15134 res |= ast_manager_unregister("RptStatus");
15135 #endif
15136 return res;
15137 }
15138
15139 #ifdef OLD_ASTERISK
15140 int load_module()
15141 #else
15142 static int load_module(void)
15143 #endif
15144 {
15145 int res;
15146 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15147
15148 #ifdef NEW_ASTERISK
15149 ast_cli_register_multiple(rpt_cli,sizeof(rpt_cli) /
15150 sizeof(struct ast_cli_entry));
15151 res = 0;
15152 #else
15153
15154 ast_cli_register(&cli_debug);
15155 ast_cli_register(&cli_dump);
15156 ast_cli_register(&cli_stats);
15157 ast_cli_register(&cli_lstats);
15158 ast_cli_register(&cli_nodes);
15159 ast_cli_register(&cli_local_nodes);
15160 ast_cli_register(&cli_reload);
15161 ast_cli_register(&cli_restart);
15162 ast_cli_register(&cli_fun);
15163 ast_cli_register(&cli_fun1);
15164 res = ast_cli_register(&cli_cmd);
15165 #endif
15166 #ifndef OLD_ASTERISK
15167 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15168 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15169
15170 #endif
15171 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15172 return res;
15173 }
15174
15175 #ifdef OLD_ASTERISK
15176 char *description()
15177 {
15178 return tdesc;
15179 }
15180 int usecount(void)
15181 {
15182 int res;
15183 STANDARD_USECOUNT(res);
15184 return res;
15185 }
15186
15187 char *key()
15188 {
15189 return ASTERISK_GPL_KEY;
15190 }
15191 #endif
15192
15193 #ifdef OLD_ASTERISK
15194 int reload()
15195 #else
15196 static int reload(void)
15197 #endif
15198 {
15199 int n;
15200
15201 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15202 return(0);
15203 }
15204
15205
15206 #ifndef OLD_ASTERISK
15207
15208 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15209 .load = load_module,
15210 .unload = unload_module,
15211 .reload = reload,
15212 );
15213 #endif
15214