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 #ifdef OLD_ASTERISK
00170 #define ast_free free
00171 #define ast_malloc malloc
00172 #define ast_strdup strdup
00173 #endif
00174
00175
00176 #define MAXDTMF 32
00177 #define MAXMACRO 2048
00178 #define MAXLINKLIST 512
00179 #define LINKLISTTIME 10000
00180 #define LINKLISTSHORTTIME 200
00181 #define LINKPOSTTIME 30000
00182 #define LINKPOSTSHORTTIME 200
00183 #define KEYPOSTTIME 30000
00184 #define KEYPOSTSHORTTIME 200
00185 #define MACROTIME 100
00186 #define MACROPTIME 500
00187 #define DTMF_TIMEOUT 3
00188 #define KENWOOD_RETRIES 5
00189 #define TOPKEYN 32
00190 #define TOPKEYWAIT 3
00191 #define TOPKEYMAXSTR 30
00192
00193 #define AUTHTELLTIME 7000
00194 #define AUTHTXTIME 1000
00195 #define AUTHLOGOUTTIME 25000
00196
00197 #ifdef __RPT_NOTCH
00198 #define MAXFILTERS 10
00199 #endif
00200
00201 #define DISC_TIME 10000
00202 #define MAX_RETRIES 5
00203 #define MAX_RETRIES_PERM 1000000000
00204
00205 #define REDUNDANT_TX_TIME 2000
00206
00207 #define RETRY_TIMER_MS 5000
00208
00209 #define PATCH_DIALPLAN_TIMEOUT 1500
00210
00211 #ifdef OLD_ASTERISK
00212 #define START_DELAY 10
00213 #else
00214 #define START_DELAY 2
00215 #endif
00216
00217 #define RPT_LOCKOUT_SECS 10
00218
00219 #define MAXPEERSTR 31
00220 #define MAXREMSTR 15
00221
00222 #define DELIMCHR ','
00223 #define QUOTECHR 34
00224
00225 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00226
00227 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00228 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00229 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00230 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00232
00233 #define NODES "nodes"
00234 #define EXTNODES "extnodes"
00235 #define MEMORY "memory"
00236 #define MACRO "macro"
00237 #define FUNCTIONS "functions"
00238 #define TELEMETRY "telemetry"
00239 #define MORSE "morse"
00240 #define TONEMACRO "tonemacro"
00241 #define FUNCCHAR '*'
00242 #define ENDCHAR '#'
00243 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00244 #define NODENAMES "rpt/nodenames"
00245 #define PARROTFILE "/tmp/parrot_%s_%u"
00246
00247 #define PARROTTIME 1000
00248
00249 #define DEFAULT_IOBASE 0x378
00250
00251 #define DEFAULT_CIV_ADDR 0x58
00252
00253 #define MAXCONNECTTIME 5000
00254
00255 #define MAXNODESTR 300
00256
00257 #define MAXNODELEN 16
00258
00259 #define MAXIDENTLEN 32
00260
00261 #define MAXPATCHCONTEXT 100
00262
00263 #define ACTIONSIZE 32
00264
00265 #define TELEPARAMSIZE 256
00266
00267 #define REM_SCANTIME 100
00268
00269 #define DTMF_LOCAL_TIME 250
00270 #define DTMF_LOCAL_STARTTIME 500
00271
00272 #define IC706_PL_MEMORY_OFFSET 50
00273
00274 #define VOX_ON_DEBOUNCE_COUNT 3
00275 #define VOX_OFF_DEBOUNCE_COUNT 20
00276 #define VOX_MAX_THRESHOLD 10000.0
00277 #define VOX_MIN_THRESHOLD 3000.0
00278 #define VOX_TIMEOUT_MS 5000
00279 #define VOX_RECOVER_MS 500
00280 #define SIMPLEX_PATCH_DELAY 25
00281 #define SIMPLEX_PHONE_DELAY 25
00282
00283 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00284
00285 #define ALLOW_LOCAL_CHANNELS
00286
00287 enum {REM_OFF,REM_MONITOR,REM_TX};
00288
00289 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00290 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00291 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00292 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00293 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00294 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00295 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00296 STATS_TIME_LOCAL};
00297
00298
00299 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00300
00301 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00302
00303 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00304
00305 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00306
00307 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00308
00309 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00310
00311 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00312 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00313
00314 #include "asterisk.h"
00315
00316 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211580 $")
00317
00318 #include <signal.h>
00319 #include <stdio.h>
00320 #include <stdint.h>
00321 #include <unistd.h>
00322 #include <string.h>
00323 #include <stdlib.h>
00324 #include <search.h>
00325 #include <sys/types.h>
00326 #include <sys/stat.h>
00327 #include <errno.h>
00328 #include <dirent.h>
00329 #include <ctype.h>
00330 #include <sys/stat.h>
00331 #include <sys/time.h>
00332 #include <sys/file.h>
00333 #include <sys/ioctl.h>
00334 #ifdef HAVE_SYS_IO_H
00335 #include <sys/io.h>
00336 #endif
00337 #include <sys/vfs.h>
00338 #include <math.h>
00339 #include <dahdi/user.h>
00340 #include <dahdi/tonezone.h>
00341 #include <netinet/in.h>
00342 #include <arpa/inet.h>
00343
00344 #include "asterisk/utils.h"
00345 #include "asterisk/lock.h"
00346 #include "asterisk/file.h"
00347 #include "asterisk/logger.h"
00348 #include "asterisk/channel.h"
00349 #include "asterisk/callerid.h"
00350 #include "asterisk/pbx.h"
00351 #include "asterisk/module.h"
00352 #include "asterisk/translate.h"
00353 #include "asterisk/features.h"
00354 #include "asterisk/options.h"
00355 #include "asterisk/cli.h"
00356 #include "asterisk/config.h"
00357 #include "asterisk/say.h"
00358 #include "asterisk/localtime.h"
00359 #include "asterisk/cdr.h"
00360 #include "asterisk/options.h"
00361 #include "asterisk/manager.h"
00362 #include "asterisk/app.h"
00363
00364 #include <termios.h>
00365
00366 #ifdef NEW_ASTERISK
00367 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00368 #endif
00369
00370
00371
00372 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00373
00374 void ast_playtones_stop(struct ast_channel *chan);
00375
00376 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00377
00378 static char *app = "Rpt";
00379
00380 static char *synopsis = "Radio Repeater/Remote Base Control System";
00381
00382 static char *descrip =
00383 " Rpt(nodename[|options][|M][|*]): \n"
00384 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00385 "\n"
00386 " Not specifying an option puts it in normal endpoint mode (where source\n"
00387 " IP and nodename are verified).\n"
00388 "\n"
00389 " Options are as follows:\n"
00390 "\n"
00391 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00392 " this if you have checked security already (like with an IAX2\n"
00393 " user/password or something).\n"
00394 "\n"
00395 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00396 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00397 " specified by the 'announce-string') is played on radio system.\n"
00398 " Users of radio system can access autopatch, dial specified\n"
00399 " code, and pick up call. Announce-string is list of names of\n"
00400 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00401 " or \"NODE\" to substitute node number.\n"
00402 "\n"
00403 " P - Phone Control mode. This allows a regular phone user to have\n"
00404 " full control and audio access to the radio system. For the\n"
00405 " user to have DTMF control, the 'phone_functions' parameter\n"
00406 " must be specified for the node in 'rpt.conf'. An additional\n"
00407 " function (cop,6) must be listed so that PTT control is available.\n"
00408 "\n"
00409 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00410 " have full control and audio access to the radio system. In this\n"
00411 " mode, the PTT is activated for the entire length of the call.\n"
00412 " For the user to have DTMF control (not generally recomended in\n"
00413 " this mode), the 'dphone_functions' parameter must be specified\n"
00414 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00415 " available to the phone user.\n"
00416 "\n"
00417 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00418 " audio-only access to the radio system. In this mode, the\n"
00419 " transmitter is toggled on and off when the phone user presses the\n"
00420 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00421 " will turn off if the endchar (#) key is pressed. When a user first\n"
00422 " calls in, the transmitter will be off, and the user can listen for\n"
00423 " radio traffic. When the user wants to transmit, they press the *\n"
00424 " key, start talking, then press the * key again or the # key to turn\n"
00425 " the transmitter off. No other functions can be executed by the\n"
00426 " user on the phone when this mode is selected. Note: If your\n"
00427 " radio system is full-duplex, we recommend using either P or D\n"
00428 " modes as they provide more flexibility.\n"
00429 "\n"
00430 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00431 "\n"
00432 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00433 "\n"
00434 " * - Alt Macro to execute (e.g. *7 for status)\n"
00435 "\n";
00436 ;
00437
00438 static int debug = 0;
00439 static int nrpts = 0;
00440
00441 static char remdtmfstr[] = "0123456789*#ABCD";
00442
00443 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00444
00445 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00446
00447 #define NRPTSTAT 7
00448
00449 struct rpt_chan_stat
00450 {
00451 struct timeval last;
00452 long long total;
00453 unsigned long count;
00454 unsigned long largest;
00455 struct timeval largest_time;
00456 };
00457
00458 char *discstr = "!!DISCONNECT!!";
00459 char *newkeystr = "!NEWKEY!";
00460 static char *remote_rig_ft897="ft897";
00461 static char *remote_rig_rbi="rbi";
00462 static char *remote_rig_kenwood="kenwood";
00463 static char *remote_rig_tm271="tm271";
00464 static char *remote_rig_ic706="ic706";
00465 static char *remote_rig_rtx150="rtx150";
00466 static char *remote_rig_rtx450="rtx450";
00467 static char *remote_rig_ppp16="ppp16";
00468
00469 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00470 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00471
00472 #ifdef OLD_ASTERISK
00473 STANDARD_LOCAL_USER;
00474 LOCAL_USER_DECL;
00475 #endif
00476
00477 #define MSWAIT 200
00478 #define HANGTIME 5000
00479 #define TOTIME 180000
00480 #define IDTIME 300000
00481 #define MAXRPTS 20
00482 #define MAX_STAT_LINKS 32
00483 #define POLITEID 30000
00484 #define FUNCTDELAY 1500
00485
00486 #define MAXXLAT 20
00487 #define MAXXLATTIME 3
00488
00489 #define MAX_SYSSTATES 10
00490
00491 struct vox {
00492 float speech_energy;
00493 float noise_energy;
00494 int enacount;
00495 char voxena;
00496 char lastvox;
00497 int offdebcnt;
00498 int ondebcnt;
00499 } ;
00500
00501 #define mymax(x,y) ((x > y) ? x : y)
00502 #define mymin(x,y) ((x < y) ? x : y)
00503
00504 struct rpt_topkey
00505 {
00506 char node[TOPKEYMAXSTR];
00507 int timesince;
00508 int keyed;
00509 } ;
00510
00511 struct rpt_xlat
00512 {
00513 char funccharseq[MAXXLAT];
00514 char endcharseq[MAXXLAT];
00515 char passchars[MAXXLAT];
00516 int funcindex;
00517 int endindex;
00518 time_t lastone;
00519 } ;
00520
00521 static time_t starttime = 0;
00522
00523 static pthread_t rpt_master_thread;
00524
00525 struct rpt;
00526
00527 struct rpt_link
00528 {
00529 struct rpt_link *next;
00530 struct rpt_link *prev;
00531 char mode;
00532 char isremote;
00533 char phonemode;
00534 char phonevox;
00535 char name[MAXNODESTR];
00536 char lasttx;
00537 char lasttx1;
00538 char lastrx;
00539 char lastrealrx;
00540 char lastrx1;
00541 char connected;
00542 char hasconnected;
00543 char perma;
00544 char thisconnected;
00545 char outbound;
00546 char disced;
00547 char killme;
00548 long elaptime;
00549 long disctime;
00550 long retrytimer;
00551 long retxtimer;
00552 long rerxtimer;
00553 int retries;
00554 int max_retries;
00555 int reconnects;
00556 long long connecttime;
00557 struct ast_channel *chan;
00558 struct ast_channel *pchan;
00559 char linklist[MAXLINKLIST];
00560 time_t linklistreceived;
00561 long linklisttimer;
00562 int dtmfed;
00563 int linkunkeytocttimer;
00564 struct timeval lastlinktv;
00565 struct ast_frame *lastf1,*lastf2;
00566 struct rpt_chan_stat chan_stat[NRPTSTAT];
00567 struct vox vox;
00568 char wasvox;
00569 int voxtotimer;
00570 char voxtostate;
00571 char newkey;
00572 #ifdef OLD_ASTERISK
00573 AST_LIST_HEAD(, ast_frame) rxq;
00574 #else
00575 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00576 #endif
00577 } ;
00578
00579 struct rpt_lstat
00580 {
00581 struct rpt_lstat *next;
00582 struct rpt_lstat *prev;
00583 char peer[MAXPEERSTR];
00584 char name[MAXNODESTR];
00585 char mode;
00586 char outbound;
00587 char reconnects;
00588 char thisconnected;
00589 long long connecttime;
00590 struct rpt_chan_stat chan_stat[NRPTSTAT];
00591 } ;
00592
00593 struct rpt_tele
00594 {
00595 struct rpt_tele *next;
00596 struct rpt_tele *prev;
00597 struct rpt *rpt;
00598 struct ast_channel *chan;
00599 int mode;
00600 struct rpt_link mylink;
00601 char param[TELEPARAMSIZE];
00602 intptr_t submode;
00603 uintptr_t parrot;
00604 pthread_t threadid;
00605 } ;
00606
00607 struct function_table_tag
00608 {
00609 char action[ACTIONSIZE];
00610 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00611 int command_source, struct rpt_link *mylink);
00612 } ;
00613
00614
00615
00616 struct morse_bits
00617 {
00618 int len;
00619 int ddcomb;
00620 } ;
00621
00622 struct telem_defaults
00623 {
00624 char name[20];
00625 char value[80];
00626 } ;
00627
00628
00629 struct sysstate
00630 {
00631 char txdisable;
00632 char totdisable;
00633 char linkfundisable;
00634 char autopatchdisable;
00635 char schedulerdisable;
00636 char userfundisable;
00637 char alternatetail;
00638 };
00639
00640
00641 #define CMD_DEPTH 1
00642 #define CMD_STATE_IDLE 0
00643 #define CMD_STATE_BUSY 1
00644 #define CMD_STATE_READY 2
00645 #define CMD_STATE_EXECUTING 3
00646
00647 struct rpt_cmd_struct
00648 {
00649 int state;
00650 int functionNumber;
00651 char param[MAXDTMF];
00652 char digits[MAXDTMF];
00653 int command_source;
00654 };
00655
00656 static struct rpt
00657 {
00658 ast_mutex_t lock;
00659 ast_mutex_t remlock;
00660 ast_mutex_t statpost_lock;
00661 struct ast_config *cfg;
00662 char reload;
00663 char xlink;
00664 unsigned int statpost_seqno;
00665
00666 char *name;
00667 char *rxchanname;
00668 char *txchanname;
00669 char remote;
00670 char *remoterig;
00671 struct rpt_chan_stat chan_stat[NRPTSTAT];
00672 unsigned int scram;
00673
00674 struct {
00675 char *ourcontext;
00676 char *ourcallerid;
00677 char *acctcode;
00678 char *ident;
00679 char *tonezone;
00680 char simple;
00681 char *functions;
00682 char *link_functions;
00683 char *phone_functions;
00684 char *dphone_functions;
00685 char *alt_functions;
00686 char *nodes;
00687 char *extnodes;
00688 char *extnodefile;
00689 int hangtime;
00690 int althangtime;
00691 int totime;
00692 int idtime;
00693 int tailmessagetime;
00694 int tailsquashedtime;
00695 int duplex;
00696 int politeid;
00697 char *tailmessages[500];
00698 int tailmessagemax;
00699 char *memory;
00700 char *macro;
00701 char *tonemacro;
00702 char *startupmacro;
00703 int iobase;
00704 char *ioport;
00705 char funcchar;
00706 char endchar;
00707 char nobusyout;
00708 char notelemtx;
00709 char propagate_dtmf;
00710 char propagate_phonedtmf;
00711 char linktolink;
00712 unsigned char civaddr;
00713 struct rpt_xlat inxlat;
00714 struct rpt_xlat outxlat;
00715 char *archivedir;
00716 int authlevel;
00717 char *csstanzaname;
00718 char *skedstanzaname;
00719 char *txlimitsstanzaname;
00720 long monminblocks;
00721 int remoteinacttimeout;
00722 int remotetimeout;
00723 int remotetimeoutwarning;
00724 int remotetimeoutwarningfreq;
00725 int sysstate_cur;
00726 struct sysstate s[MAX_SYSSTATES];
00727 char parrotmode;
00728 int parrottime;
00729 char *rptnode;
00730 char remote_mars;
00731 int voxtimeout_ms;
00732 int voxrecover_ms;
00733 int simplexpatchdelay;
00734 int simplexphonedelay;
00735 char *statpost_program;
00736 char *statpost_url;
00737 } p;
00738 struct rpt_link links;
00739 int unkeytocttimer;
00740 time_t lastkeyedtime;
00741 time_t lasttxkeyedtime;
00742 char keyed;
00743 char txkeyed;
00744 char exttx;
00745 char localtx;
00746 char remoterx;
00747 char remotetx;
00748 char remoteon;
00749 char remtxfreqok;
00750 char tounkeyed;
00751 char tonotify;
00752 char dtmfbuf[MAXDTMF];
00753 char macrobuf[MAXMACRO];
00754 char rem_dtmfbuf[MAXDTMF];
00755 char lastdtmfcommand[MAXDTMF];
00756 char cmdnode[50];
00757 char nowchan;
00758 char waschan;
00759 char bargechan;
00760 char macropatch;
00761 char parrotstate;
00762 int parrottimer;
00763 unsigned int parrotcnt;
00764 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00765 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00766 struct ast_channel *voxchannel;
00767 struct ast_frame *lastf1,*lastf2;
00768 struct rpt_tele tele;
00769 struct timeval lasttv,curtv;
00770 pthread_t rpt_call_thread,rpt_thread;
00771 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00772 int calldigittimer;
00773 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00774 int mustid,tailid;
00775 int tailevent;
00776 int telemrefcount;
00777 int dtmfidx,rem_dtmfidx;
00778 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00779 int totalexecdcommands, dailyexecdcommands;
00780 long retxtimer;
00781 long rerxtimer;
00782 long long totaltxtime;
00783 char mydtmf;
00784 char exten[AST_MAX_EXTENSION];
00785 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00786 char offset;
00787 char powerlevel;
00788 char txplon;
00789 char rxplon;
00790 char remmode;
00791 char tunerequest;
00792 char hfscanmode;
00793 int hfscanstatus;
00794 char hfscanstop;
00795 char lastlinknode[MAXNODESTR];
00796 char savednodes[MAXNODESTR];
00797 int stopgen;
00798 char patchfarenddisconnect;
00799 char patchnoct;
00800 char patchquiet;
00801 char patchcontext[MAXPATCHCONTEXT];
00802 int patchdialtime;
00803 int macro_longest;
00804 int phone_longestfunc;
00805 int alt_longestfunc;
00806 int dphone_longestfunc;
00807 int link_longestfunc;
00808 int longestfunc;
00809 int longestnode;
00810 int threadrestarts;
00811 int tailmessagen;
00812 time_t disgorgetime;
00813 time_t lastthreadrestarttime;
00814 long macrotimer;
00815 char lastnodewhichkeyedusup[MAXNODESTR];
00816 int dtmf_local_timer;
00817 char dtmf_local_str[100];
00818 struct ast_filestream *monstream,*parrotstream;
00819 char loginuser[50];
00820 char loginlevel[10];
00821 long authtelltimer;
00822 long authtimer;
00823 int iofd;
00824 time_t start_time,last_activity_time;
00825 char lasttone[32];
00826 struct rpt_tele *active_telem;
00827 struct rpt_topkey topkey[TOPKEYN];
00828 int topkeystate;
00829 time_t topkeytime;
00830 int topkeylong;
00831 struct vox vox;
00832 char wasvox;
00833 int voxtotimer;
00834 char voxtostate;
00835 int linkposttimer;
00836 int keyposttimer;
00837 char newkey;
00838 char inpadtest;
00839 #ifdef OLD_ASTERISK
00840 AST_LIST_HEAD(, ast_frame) txq;
00841 #else
00842 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00843 #endif
00844 char txrealkeyed;
00845 #ifdef __RPT_NOTCH
00846 struct rptfilter
00847 {
00848 char desc[100];
00849 float x0;
00850 float x1;
00851 float x2;
00852 float y0;
00853 float y1;
00854 float y2;
00855 float gain;
00856 float const0;
00857 float const1;
00858 float const2;
00859 } filters[MAXFILTERS];
00860 #endif
00861 #ifdef _MDC_DECODE_H_
00862 mdc_decoder_t *mdc;
00863 unsigned short lastunit;
00864 #endif
00865 struct rpt_cmd_struct cmdAction;
00866 } rpt_vars[MAXRPTS];
00867
00868 struct nodelog {
00869 struct nodelog *next;
00870 struct nodelog *prev;
00871 time_t timestamp;
00872 char archivedir[MAXNODESTR];
00873 char str[MAXNODESTR * 2];
00874 } nodelog;
00875
00876 static int service_scan(struct rpt *myrpt);
00877 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00878 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00879 static int simple_command_ft897(struct rpt *myrpt, char command);
00880 static int setrem(struct rpt *myrpt);
00881 static int setrtx_check(struct rpt *myrpt);
00882 static int channel_revert(struct rpt *myrpt);
00883 static int channel_steer(struct rpt *myrpt, char *data);
00884
00885 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00886
00887 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00888
00889 #ifdef APP_RPT_LOCK_DEBUG
00890
00891 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00892
00893 #define MAXLOCKTHREAD 100
00894
00895 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00896 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00897
00898 struct lockthread
00899 {
00900 pthread_t id;
00901 int lockcount;
00902 int lastlock;
00903 int lastunlock;
00904 } lockthreads[MAXLOCKTHREAD];
00905
00906
00907 struct by_lightning
00908 {
00909 int line;
00910 struct timeval tv;
00911 struct rpt *rpt;
00912 struct lockthread lockthread;
00913 } lock_ring[32];
00914
00915 int lock_ring_index = 0;
00916
00917 AST_MUTEX_DEFINE_STATIC(locklock);
00918
00919 static struct lockthread *get_lockthread(pthread_t id)
00920 {
00921 int i;
00922
00923 for(i = 0; i < MAXLOCKTHREAD; i++)
00924 {
00925 if (lockthreads[i].id == id) return(&lockthreads[i]);
00926 }
00927 return(NULL);
00928 }
00929
00930 static struct lockthread *put_lockthread(pthread_t id)
00931 {
00932 int i;
00933
00934 for(i = 0; i < MAXLOCKTHREAD; i++)
00935 {
00936 if (lockthreads[i].id == id)
00937 return(&lockthreads[i]);
00938 }
00939 for(i = 0; i < MAXLOCKTHREAD; i++)
00940 {
00941 if (!lockthreads[i].id)
00942 {
00943 lockthreads[i].lockcount = 0;
00944 lockthreads[i].lastlock = 0;
00945 lockthreads[i].lastunlock = 0;
00946 lockthreads[i].id = id;
00947 return(&lockthreads[i]);
00948 }
00949 }
00950 return(NULL);
00951 }
00952
00953
00954 static void rpt_mutex_spew(void)
00955 {
00956 struct by_lightning lock_ring_copy[32];
00957 int lock_ring_index_copy;
00958 int i,j;
00959 long long diff;
00960 char a[100];
00961 struct timeval lasttv;
00962
00963 ast_mutex_lock(&locklock);
00964 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00965 lock_ring_index_copy = lock_ring_index;
00966 ast_mutex_unlock(&locklock);
00967
00968 lasttv.tv_sec = lasttv.tv_usec = 0;
00969 for(i = 0 ; i < 32 ; i++)
00970 {
00971 j = (i + lock_ring_index_copy) % 32;
00972 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00973 localtime(&lock_ring_copy[j].tv.tv_sec));
00974 diff = 0;
00975 if(lasttv.tv_sec)
00976 {
00977 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00978 * 1000000;
00979 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00980 }
00981 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00982 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00983 if (!lock_ring_copy[j].tv.tv_sec) continue;
00984 if (lock_ring_copy[j].line < 0)
00985 {
00986 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00987 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);
00988 }
00989 else
00990 {
00991 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00992 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);
00993 }
00994 }
00995 }
00996
00997
00998 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
00999 {
01000 struct lockthread *t;
01001 pthread_t id;
01002
01003 id = pthread_self();
01004 ast_mutex_lock(&locklock);
01005 t = put_lockthread(id);
01006 if (!t)
01007 {
01008 ast_mutex_unlock(&locklock);
01009 return;
01010 }
01011 if (t->lockcount)
01012 {
01013 int lastline = t->lastlock;
01014 ast_mutex_unlock(&locklock);
01015 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);
01016 rpt_mutex_spew();
01017 return;
01018 }
01019 t->lastlock = line;
01020 t->lockcount = 1;
01021 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01022 lock_ring[lock_ring_index].rpt = myrpt;
01023 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01024 lock_ring[lock_ring_index++].line = line;
01025 if(lock_ring_index == 32)
01026 lock_ring_index = 0;
01027 ast_mutex_unlock(&locklock);
01028 ast_mutex_lock(lockp);
01029 }
01030
01031
01032 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01033 {
01034 struct lockthread *t;
01035 pthread_t id;
01036
01037 id = pthread_self();
01038 ast_mutex_lock(&locklock);
01039 t = put_lockthread(id);
01040 if (!t)
01041 {
01042 ast_mutex_unlock(&locklock);
01043 return;
01044 }
01045 if (!t->lockcount)
01046 {
01047 int lastline = t->lastunlock;
01048 ast_mutex_unlock(&locklock);
01049 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);
01050 rpt_mutex_spew();
01051 return;
01052 }
01053 t->lastunlock = line;
01054 t->lockcount = 0;
01055 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01056 lock_ring[lock_ring_index].rpt = myrpt;
01057 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01058 lock_ring[lock_ring_index++].line = -line;
01059 if(lock_ring_index == 32)
01060 lock_ring_index = 0;
01061 ast_mutex_unlock(&locklock);
01062 ast_mutex_unlock(lockp);
01063 }
01064
01065 #else
01066
01067 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01068 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01069
01070 #endif
01071
01072
01073
01074
01075
01076 static int multimode_capable(struct rpt *myrpt)
01077 {
01078 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01079 return 1;
01080 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01081 return 1;
01082 return 0;
01083 }
01084
01085 static void voxinit_rpt(struct rpt *myrpt,char enable)
01086 {
01087
01088 myrpt->vox.speech_energy = 0.0;
01089 myrpt->vox.noise_energy = 0.0;
01090 myrpt->vox.enacount = 0;
01091 myrpt->vox.voxena = 0;
01092 if (!enable) myrpt->vox.voxena = -1;
01093 myrpt->vox.lastvox = 0;
01094 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01095 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01096 myrpt->wasvox = 0;
01097 myrpt->voxtotimer = 0;
01098 myrpt->voxtostate = 0;
01099 }
01100
01101 static void voxinit_link(struct rpt_link *mylink,char enable)
01102 {
01103
01104 mylink->vox.speech_energy = 0.0;
01105 mylink->vox.noise_energy = 0.0;
01106 mylink->vox.enacount = 0;
01107 mylink->vox.voxena = 0;
01108 if (!enable) mylink->vox.voxena = -1;
01109 mylink->vox.lastvox = 0;
01110 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01111 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01112 mylink->wasvox = 0;
01113 mylink->voxtotimer = 0;
01114 mylink->voxtostate = 0;
01115 }
01116
01117 static int dovox(struct vox *v,short *buf,int bs)
01118 {
01119
01120 int i;
01121 float esquare = 0.0;
01122 float energy = 0.0;
01123 float threshold = 0.0;
01124
01125 if (v->voxena < 0) return(v->lastvox);
01126 for(i = 0; i < bs; i++)
01127 {
01128 esquare += (float) buf[i] * (float) buf[i];
01129 }
01130 energy = sqrt(esquare);
01131
01132 if (energy >= v->speech_energy)
01133 v->speech_energy += (energy - v->speech_energy) / 4;
01134 else
01135 v->speech_energy += (energy - v->speech_energy) / 64;
01136
01137 if (energy >= v->noise_energy)
01138 v->noise_energy += (energy - v->noise_energy) / 64;
01139 else
01140 v->noise_energy += (energy - v->noise_energy) / 4;
01141
01142 if (v->voxena) threshold = v->speech_energy / 8;
01143 else
01144 {
01145 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01146 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01147 }
01148 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01149 if (energy > threshold)
01150 {
01151 if (v->voxena) v->noise_energy *= 0.75;
01152 v->voxena = 1;
01153 } else v->voxena = 0;
01154 if (v->lastvox != v->voxena)
01155 {
01156 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01157 {
01158 v->lastvox = v->voxena;
01159 v->enacount = 0;
01160 }
01161 } else v->enacount = 0;
01162 return(v->lastvox);
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 static int rpt_do_debug(int fd, int argc, char *argv[]);
01174 static int rpt_do_dump(int fd, int argc, char *argv[]);
01175 static int rpt_do_stats(int fd, int argc, char *argv[]);
01176 static int rpt_do_lstats(int fd, int argc, char *argv[]);
01177 static int rpt_do_nodes(int fd, int argc, char *argv[]);
01178 static int rpt_do_local_nodes(int fd, int argc, char *argv[]);
01179 static int rpt_do_reload(int fd, int argc, char *argv[]);
01180 static int rpt_do_restart(int fd, int argc, char *argv[]);
01181 static int rpt_do_fun(int fd, int argc, char *argv[]);
01182 static int rpt_do_fun1(int fd, int argc, char *argv[]);
01183 static int rpt_do_cmd(int fd, int argc, char *argv[]);
01184
01185 static char debug_usage[] =
01186 "Usage: rpt debug level {0-7}\n"
01187 " Enables debug messages in app_rpt\n";
01188
01189 static char dump_usage[] =
01190 "Usage: rpt dump <nodename>\n"
01191 " Dumps struct debug info to log\n";
01192
01193 static char dump_stats[] =
01194 "Usage: rpt stats <nodename>\n"
01195 " Dumps node statistics to console\n";
01196
01197 static char dump_lstats[] =
01198 "Usage: rpt lstats <nodename>\n"
01199 " Dumps link statistics to console\n";
01200
01201 static char dump_nodes[] =
01202 "Usage: rpt nodes <nodename>\n"
01203 " Dumps a list of directly and indirectly connected nodes to the console\n";
01204
01205 static char usage_local_nodes[] =
01206 "Usage: rpt localnodes\n"
01207 " Dumps a list of the locally configured node numbers to the console.\n";
01208
01209 static char reload_usage[] =
01210 "Usage: rpt reload\n"
01211 " Reloads app_rpt running config parameters\n";
01212
01213 static char restart_usage[] =
01214 "Usage: rpt restart\n"
01215 " Restarts app_rpt\n";
01216
01217 static char fun_usage[] =
01218 "Usage: rpt fun <nodename> <command>\n"
01219 " Send a DTMF function to a node\n";
01220
01221 static char cmd_usage[] =
01222 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01223 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01224
01225 #ifndef NEW_ASTERISK
01226
01227 static struct ast_cli_entry cli_debug =
01228 { { "rpt", "debug", "level" }, rpt_do_debug,
01229 "Enable app_rpt debugging", debug_usage };
01230
01231 static struct ast_cli_entry cli_dump =
01232 { { "rpt", "dump" }, rpt_do_dump,
01233 "Dump app_rpt structs for debugging", dump_usage };
01234
01235 static struct ast_cli_entry cli_stats =
01236 { { "rpt", "stats" }, rpt_do_stats,
01237 "Dump node statistics", dump_stats };
01238
01239 static struct ast_cli_entry cli_nodes =
01240 { { "rpt", "nodes" }, rpt_do_nodes,
01241 "Dump node list", dump_nodes };
01242
01243 static struct ast_cli_entry cli_local_nodes =
01244 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01245 "Dump list of local node numbers", usage_local_nodes };
01246
01247 static struct ast_cli_entry cli_lstats =
01248 { { "rpt", "lstats" }, rpt_do_lstats,
01249 "Dump link statistics", dump_lstats };
01250
01251 static struct ast_cli_entry cli_reload =
01252 { { "rpt", "reload" }, rpt_do_reload,
01253 "Reload app_rpt config", reload_usage };
01254
01255 static struct ast_cli_entry cli_restart =
01256 { { "rpt", "restart" }, rpt_do_restart,
01257 "Restart app_rpt", restart_usage };
01258
01259 static struct ast_cli_entry cli_fun =
01260 { { "rpt", "fun" }, rpt_do_fun,
01261 "Execute a DTMF function", fun_usage };
01262
01263 static struct ast_cli_entry cli_fun1 =
01264 { { "rpt", "fun1" }, rpt_do_fun1,
01265 "Execute a DTMF function", fun_usage };
01266
01267 static struct ast_cli_entry cli_cmd =
01268 { { "rpt", "cmd" }, rpt_do_cmd,
01269 "Execute a DTMF function", cmd_usage };
01270
01271 #endif
01272
01273
01274
01275
01276
01277
01278 static struct telem_defaults tele_defs[] = {
01279 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01280 {"ct2","|t(660,880,150,3072)"},
01281 {"ct3","|t(440,0,150,3072)"},
01282 {"ct4","|t(550,0,150,3072)"},
01283 {"ct5","|t(660,0,150,3072)"},
01284 {"ct6","|t(880,0,150,3072)"},
01285 {"ct7","|t(660,440,150,3072)"},
01286 {"ct8","|t(700,1100,150,3072)"},
01287 {"remotemon","|t(1600,0,75,2048)"},
01288 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01289 {"cmdmode","|t(900,904,200,2048)"},
01290 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01291 } ;
01292
01293
01294
01295
01296
01297 static int setrbi(struct rpt *myrpt);
01298 static int set_ft897(struct rpt *myrpt);
01299 static int set_ic706(struct rpt *myrpt);
01300 static int setkenwood(struct rpt *myrpt);
01301 static int set_tm271(struct rpt *myrpt);
01302 static int setrbi_check(struct rpt *myrpt);
01303
01304
01305
01306
01307
01308
01309
01310 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01311 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01312 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318
01319
01320
01321
01322 static struct function_table_tag function_table[] = {
01323 {"cop", function_cop},
01324 {"autopatchup", function_autopatchup},
01325 {"autopatchdn", function_autopatchdn},
01326 {"ilink", function_ilink},
01327 {"status", function_status},
01328 {"remote", function_remote},
01329 {"macro", function_macro},
01330 {"playback", function_playback}
01331 } ;
01332
01333 static long diskavail(struct rpt *myrpt)
01334 {
01335 struct statfs statfsbuf;
01336
01337 if (!myrpt->p.archivedir) return(0);
01338 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01339 {
01340 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01341 myrpt->p.archivedir,myrpt->name);
01342 return(-1);
01343 }
01344 return(statfsbuf.f_bavail);
01345 }
01346
01347 static void flush_telem(struct rpt *myrpt)
01348 {
01349 struct rpt_tele *telem;
01350 if(debug > 2)
01351 ast_log(LOG_NOTICE, "flush_telem()!!");
01352 rpt_mutex_lock(&myrpt->lock);
01353 telem = myrpt->tele.next;
01354 while(telem != &myrpt->tele)
01355 {
01356 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01357 telem = telem->next;
01358 }
01359 rpt_mutex_unlock(&myrpt->lock);
01360 }
01361
01362
01363
01364 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01365 {
01366 int res=0;
01367
01368
01369 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01370 res = 0;
01371 } else {
01372 res = -1;
01373 }
01374 return res;
01375 }
01376
01377
01378 static int linkcount(struct rpt *myrpt)
01379 {
01380 struct rpt_link *l;
01381 char *reverse_patch_state;
01382 int numoflinks;
01383
01384 reverse_patch_state = "DOWN";
01385 numoflinks = 0;
01386 l = myrpt->links.next;
01387 while(l && (l != &myrpt->links)){
01388 if(numoflinks >= MAX_STAT_LINKS){
01389 ast_log(LOG_WARNING,
01390 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01391 break;
01392 }
01393
01394
01395
01396
01397
01398 numoflinks++;
01399
01400 l = l->next;
01401 }
01402 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01403 return numoflinks;
01404 }
01405
01406
01407
01408
01409
01410
01411 static int retreive_memory(struct rpt *myrpt, char *memory)
01412 {
01413 char tmp[30], *s, *s1, *val;
01414
01415 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01416
01417 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01418 if (!val){
01419 return -1;
01420 }
01421 strncpy(tmp,val,sizeof(tmp) - 1);
01422 tmp[sizeof(tmp)-1] = 0;
01423
01424 s = strchr(tmp,',');
01425 if (!s)
01426 return 1;
01427 *s++ = 0;
01428 s1 = strchr(s,',');
01429 if (!s1)
01430 return 1;
01431 *s1++ = 0;
01432 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01433 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01434 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01435 myrpt->remmode = REM_MODE_FM;
01436 myrpt->offset = REM_SIMPLEX;
01437 myrpt->powerlevel = REM_MEDPWR;
01438 myrpt->txplon = myrpt->rxplon = 0;
01439 while(*s1){
01440 switch(*s1++){
01441 case 'A':
01442 case 'a':
01443 strcpy(myrpt->rxpl, "100.0");
01444 strcpy(myrpt->txpl, "100.0");
01445 myrpt->remmode = REM_MODE_AM;
01446 break;
01447 case 'B':
01448 case 'b':
01449 strcpy(myrpt->rxpl, "100.0");
01450 strcpy(myrpt->txpl, "100.0");
01451 myrpt->remmode = REM_MODE_LSB;
01452 break;
01453 case 'F':
01454 myrpt->remmode = REM_MODE_FM;
01455 break;
01456 case 'L':
01457 case 'l':
01458 myrpt->powerlevel = REM_LOWPWR;
01459 break;
01460 case 'H':
01461 case 'h':
01462 myrpt->powerlevel = REM_HIPWR;
01463 break;
01464
01465 case 'M':
01466 case 'm':
01467 myrpt->powerlevel = REM_MEDPWR;
01468 break;
01469
01470 case '-':
01471 myrpt->offset = REM_MINUS;
01472 break;
01473
01474 case '+':
01475 myrpt->offset = REM_PLUS;
01476 break;
01477
01478 case 'S':
01479 case 's':
01480 myrpt->offset = REM_SIMPLEX;
01481 break;
01482
01483 case 'T':
01484 case 't':
01485 myrpt->txplon = 1;
01486 break;
01487
01488 case 'R':
01489 case 'r':
01490 myrpt->rxplon = 1;
01491 break;
01492
01493 case 'U':
01494 case 'u':
01495 strcpy(myrpt->rxpl, "100.0");
01496 strcpy(myrpt->txpl, "100.0");
01497 myrpt->remmode = REM_MODE_USB;
01498 break;
01499 default:
01500 return 1;
01501 }
01502 }
01503 return 0;
01504 }
01505
01506
01507
01508 static void birdbath(struct rpt *myrpt)
01509 {
01510 struct rpt_tele *telem;
01511 if(debug > 2)
01512 ast_log(LOG_NOTICE, "birdbath!!");
01513 rpt_mutex_lock(&myrpt->lock);
01514 telem = myrpt->tele.next;
01515 while(telem != &myrpt->tele)
01516 {
01517 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01518 telem = telem->next;
01519 }
01520 rpt_mutex_unlock(&myrpt->lock);
01521 }
01522
01523 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01524 {
01525 struct rpt_link *l;
01526
01527 l = myrpt->links.next;
01528
01529 while(l != &myrpt->links)
01530 {
01531 if (!l->phonemode)
01532 {
01533 l = l->next;
01534 continue;
01535 }
01536
01537 if (mylink && (l == mylink))
01538 {
01539 l = l->next;
01540 continue;
01541 }
01542 #ifdef NEW_ASTERISK
01543 if (l->chan) ast_senddigit(l->chan,c,0);
01544 #else
01545 if (l->chan) ast_senddigit(l->chan,c);
01546 #endif
01547 l = l->next;
01548 }
01549 return;
01550 }
01551
01552
01553 static void donodelog(struct rpt *myrpt,char *str)
01554 {
01555 struct nodelog *nodep;
01556 char datestr[100];
01557
01558 if (!myrpt->p.archivedir) return;
01559 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01560 if (nodep == NULL)
01561 {
01562 ast_log(LOG_ERROR,"Cannot get memory for node log");
01563 return;
01564 }
01565 time(&nodep->timestamp);
01566 strncpy(nodep->archivedir,myrpt->p.archivedir,
01567 sizeof(nodep->archivedir) - 1);
01568 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01569 localtime(&nodep->timestamp));
01570 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01571 myrpt->name,datestr,str);
01572 ast_mutex_lock(&nodeloglock);
01573 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01574 ast_mutex_unlock(&nodeloglock);
01575 }
01576
01577
01578 static void do_dtmf_local(struct rpt *myrpt, char c)
01579 {
01580 int i;
01581 char digit;
01582 static const char* dtmf_tones[] = {
01583 "!941+1336/200,!0/200",
01584 "!697+1209/200,!0/200",
01585 "!697+1336/200,!0/200",
01586 "!697+1477/200,!0/200",
01587 "!770+1209/200,!0/200",
01588 "!770+1336/200,!0/200",
01589 "!770+1477/200,!0/200",
01590 "!852+1209/200,!0/200",
01591 "!852+1336/200,!0/200",
01592 "!852+1477/200,!0/200",
01593 "!697+1633/200,!0/200",
01594 "!770+1633/200,!0/200",
01595 "!852+1633/200,!0/200",
01596 "!941+1633/200,!0/200",
01597 "!941+1209/200,!0/200",
01598 "!941+1477/200,!0/200" };
01599
01600
01601 if (c)
01602 {
01603 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01604 if (!myrpt->dtmf_local_timer)
01605 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01606 }
01607
01608 if (myrpt->dtmf_local_timer == 1)
01609 {
01610 if(debug > 6)
01611 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01612
01613
01614 if (myrpt->dtmf_local_str[0])
01615 {
01616 digit = myrpt->dtmf_local_str[0];
01617 myrpt->dtmf_local_str[0] = 0;
01618 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01619 {
01620 myrpt->dtmf_local_str[i - 1] =
01621 myrpt->dtmf_local_str[i];
01622 }
01623 myrpt->dtmf_local_str[i - 1] = 0;
01624 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01625 rpt_mutex_unlock(&myrpt->lock);
01626 if (digit >= '0' && digit <='9')
01627 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01628 else if (digit >= 'A' && digit <= 'D')
01629 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01630 else if (digit == '*')
01631 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01632 else if (digit == '#')
01633 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01634 else {
01635
01636 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01637 }
01638 rpt_mutex_lock(&myrpt->lock);
01639 }
01640 else
01641 {
01642 myrpt->dtmf_local_timer = 0;
01643 }
01644 }
01645 }
01646
01647 static int setdtr(int fd, int enable)
01648 {
01649 struct termios mode;
01650
01651 if (fd < 0) return -1;
01652 if (tcgetattr(fd, &mode)) {
01653 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01654 return -1;
01655 }
01656 if (enable)
01657 {
01658 cfsetspeed(&mode, B9600);
01659 }
01660 else
01661 {
01662 cfsetspeed(&mode, B0);
01663 usleep(100000);
01664 }
01665 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01666 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01667 return -1;
01668 }
01669 if (enable) usleep(100000);
01670 return 0;
01671 }
01672
01673 static int openserial(struct rpt *myrpt,char *fname)
01674 {
01675 struct termios mode;
01676 int fd;
01677
01678 fd = open(fname,O_RDWR);
01679 if (fd == -1)
01680 {
01681 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01682 return -1;
01683 }
01684 memset(&mode, 0, sizeof(mode));
01685 if (tcgetattr(fd, &mode)) {
01686 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01687 return -1;
01688 }
01689 #ifndef SOLARIS
01690 cfmakeraw(&mode);
01691 #else
01692 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01693 |INLCR|IGNCR|ICRNL|IXON);
01694 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01695 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01696 mode.c_cflag |= CS8;
01697 mode.c_cc[VTIME] = 3;
01698 mode.c_cc[VMIN] = 1;
01699 #endif
01700
01701 cfsetispeed(&mode, B9600);
01702 cfsetospeed(&mode, B9600);
01703 if (tcsetattr(fd, TCSANOW, &mode))
01704 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01705 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01706 usleep(100000);
01707 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01708 return(fd);
01709 }
01710
01711 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01712 {
01713 if (!fromnode)
01714 {
01715 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01716 unit,myrpt->name);
01717 }
01718 else
01719 {
01720 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01721 unit,fromnode,myrpt->name);
01722 }
01723 }
01724
01725 #ifdef _MDC_DECODE_H_
01726
01727 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01728 {
01729 struct rpt_link *l;
01730 struct ast_frame wf;
01731 char str[200];
01732
01733
01734 sprintf(str,"I %s %04X",myrpt->name,unit);
01735
01736 wf.frametype = AST_FRAME_TEXT;
01737 wf.subclass = 0;
01738 wf.offset = 0;
01739 wf.mallocd = 0;
01740 wf.datalen = strlen(str) + 1;
01741 wf.samples = 0;
01742
01743
01744 l = myrpt->links.next;
01745
01746 while(l != &myrpt->links)
01747 {
01748 if (l->name[0] == '0')
01749 {
01750 l = l->next;
01751 continue;
01752 }
01753 wf.data = str;
01754 if (l->chan) ast_write(l->chan,&wf);
01755 l = l->next;
01756 }
01757 return;
01758 }
01759
01760 #endif
01761
01762 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01763 {
01764 time_t now;
01765 int gotone;
01766
01767 time(&now);
01768 gotone = 0;
01769
01770 if ((now - xlat->lastone) > MAXXLATTIME)
01771 {
01772 xlat->funcindex = xlat->endindex = 0;
01773 }
01774 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01775 {
01776 time(&xlat->lastone);
01777 gotone = 1;
01778 if (!xlat->funccharseq[xlat->funcindex])
01779 {
01780 xlat->funcindex = xlat->endindex = 0;
01781 return(myrpt->p.funcchar);
01782 }
01783 } else xlat->funcindex = 0;
01784 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01785 {
01786 time(&xlat->lastone);
01787 gotone = 1;
01788 if (!xlat->endcharseq[xlat->endindex])
01789 {
01790 xlat->funcindex = xlat->endindex = 0;
01791 return(myrpt->p.endchar);
01792 }
01793 } else xlat->endindex = 0;
01794
01795 if (gotone) return(0);
01796
01797 if (!xlat->passchars[0]) return(c);
01798
01799 if (strchr(xlat->passchars,c)) return(c);
01800 return(0);
01801 }
01802
01803
01804
01805
01806
01807 static char *eatwhite(char *s)
01808 {
01809 while((*s == ' ') || (*s == 0x09)){
01810 if(!*s)
01811 break;
01812 s++;
01813 }
01814 return s;
01815 }
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827 static int finddelim(char *str, char *strp[], int limit)
01828 {
01829 int i,l,inquo;
01830
01831 inquo = 0;
01832 i = 0;
01833 strp[i++] = str;
01834 if (!*str)
01835 {
01836 strp[0] = 0;
01837 return(0);
01838 }
01839 for(l = 0; *str && (l < limit) ; str++)
01840 {
01841 if (*str == QUOTECHR)
01842 {
01843 if (inquo)
01844 {
01845 *str = 0;
01846 inquo = 0;
01847 }
01848 else
01849 {
01850 strp[i - 1] = str + 1;
01851 inquo = 1;
01852 }
01853 }
01854 if ((*str == DELIMCHR) && (!inquo))
01855 {
01856 *str = 0;
01857 l++;
01858 strp[i++] = str + 1;
01859 }
01860 }
01861 strp[i] = 0;
01862 return(i);
01863
01864 }
01865
01866
01867
01868 static int send_usb_txt(struct rpt *myrpt, char *txt)
01869 {
01870 struct ast_frame wf;
01871
01872 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01873 wf.frametype = AST_FRAME_TEXT;
01874 wf.subclass = 0;
01875 wf.offset = 0;
01876 wf.mallocd = 0;
01877 wf.datalen = strlen(txt) + 1;
01878 wf.data.ptr = txt;
01879 wf.samples = 0;
01880 ast_write(myrpt->txchannel,&wf);
01881 return 0;
01882 }
01883
01884 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01885 {
01886 struct rpt_link *l;
01887 char mode;
01888 int i,spos;
01889
01890 buf[0] = 0;
01891 if (myrpt->remote) return;
01892
01893 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01894 {
01895
01896 if (l->name[0] == '0') continue;
01897
01898 if (l == mylink) continue;
01899 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01900
01901 mode = 'T';
01902 if (!l->mode) mode = 'R';
01903 if (!l->thisconnected) mode = 'C';
01904 spos = strlen(buf);
01905 if (spos)
01906 {
01907 strcat(buf,",");
01908 spos++;
01909 }
01910
01911 if (l->linklist[0])
01912 {
01913 snprintf(buf + spos,MAXLINKLIST - spos,
01914 "%c%s,%s",mode,l->name,l->linklist);
01915 }
01916 else
01917 {
01918 snprintf(buf + spos,MAXLINKLIST - spos,
01919 "%c%s",mode,l->name);
01920 }
01921
01922 if (mode == 'T') continue;
01923
01924 for(i = spos; buf[i]; i++)
01925 {
01926 if (buf[i] == 'T') buf[i] = mode;
01927 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01928 }
01929 }
01930 return;
01931 }
01932
01933
01934 static void __kickshort(struct rpt *myrpt)
01935 {
01936 struct rpt_link *l;
01937
01938 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01939 {
01940
01941 if (l->name[0] == '0') continue;
01942 l->linklisttimer = LINKLISTSHORTTIME;
01943 }
01944 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01945 return;
01946 }
01947
01948 static void statpost(struct rpt *myrpt,char *pairs)
01949 {
01950 char *str,*astr;
01951 char *astrs[100];
01952 int n,pid;
01953 time_t now;
01954 unsigned int seq;
01955
01956 if (!myrpt->p.statpost_url) return;
01957 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01958 astr = ast_strdup(myrpt->p.statpost_program);
01959 if ((!str) || (!astr)) return;
01960 n = finddelim(astr,astrs,100);
01961 if (n < 1) return;
01962 ast_mutex_lock(&myrpt->statpost_lock);
01963 seq = ++myrpt->statpost_seqno;
01964 ast_mutex_unlock(&myrpt->statpost_lock);
01965 astrs[n++] = str;
01966 astrs[n] = NULL;
01967 time(&now);
01968 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01969 myrpt->name,(unsigned int) now,seq);
01970 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01971 if (!(pid = ast_safe_fork(0)))
01972 {
01973 execv(astrs[0],astrs);
01974 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01975 perror("asterisk");
01976 exit(0);
01977 }
01978 ast_free(astr);
01979 ast_free(str);
01980 return;
01981 }
01982
01983 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01984 {
01985
01986 char *val;
01987 int longestnode,j;
01988 struct stat mystat;
01989 static time_t last = 0;
01990 static struct ast_config *ourcfg = NULL;
01991 struct ast_variable *vp;
01992
01993
01994 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01995 if (val) return(val);
01996 ast_mutex_lock(&nodelookuplock);
01997
01998 if (stat(myrpt->p.extnodefile,&mystat) == -1)
01999 {
02000 if (ourcfg) ast_config_destroy(ourcfg);
02001 ourcfg = NULL;
02002 ast_mutex_unlock(&nodelookuplock);
02003 return(NULL);
02004 }
02005
02006 if (mystat.st_mtime > last)
02007 {
02008 if (ourcfg) ast_config_destroy(ourcfg);
02009 #ifdef NEW_ASTERISK
02010 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02011 #else
02012 ourcfg = ast_config_load(myrpt->p.extnodefile);
02013 #endif
02014
02015 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02016 {
02017 ast_mutex_unlock(&nodelookuplock);
02018 return(NULL);
02019 }
02020
02021 last = mystat.st_mtime;
02022
02023
02024 longestnode = 0;
02025 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02026 while(vp){
02027 j = strlen(vp->name);
02028 if (j > longestnode)
02029 longestnode = j;
02030 vp = vp->next;
02031 }
02032
02033 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02034 while(vp){
02035 j = strlen(vp->name);
02036 if (j > longestnode)
02037 longestnode = j;
02038 vp = vp->next;
02039 }
02040
02041 myrpt->longestnode = longestnode;
02042 }
02043 val = NULL;
02044 if (ourcfg)
02045 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02046 ast_mutex_unlock(&nodelookuplock);
02047 return(val);
02048 }
02049
02050
02051
02052
02053
02054
02055 static int matchkeyword(char *string, char **param, char *keywords[])
02056 {
02057 int i,ls;
02058 for( i = 0 ; keywords[i] ; i++){
02059 ls = strlen(keywords[i]);
02060 if(!ls){
02061 *param = NULL;
02062 return 0;
02063 }
02064 if(!strncmp(string, keywords[i], ls)){
02065 if(param)
02066 *param = string + ls;
02067 return i + 1;
02068 }
02069 }
02070 *param = NULL;
02071 return 0;
02072 }
02073
02074
02075
02076
02077
02078
02079 static char *skipchars(char *string, char *charlist)
02080 {
02081 int i;
02082 while(*string){
02083 for(i = 0; charlist[i] ; i++){
02084 if(*string == charlist[i]){
02085 string++;
02086 break;
02087 }
02088 }
02089 if(!charlist[i])
02090 return string;
02091 }
02092 return string;
02093 }
02094
02095
02096
02097 static int myatoi(char *str)
02098 {
02099 int ret;
02100
02101 if (str == NULL) return -1;
02102
02103 if (sscanf(str, "%30i", &ret) != 1) {
02104 return -1;
02105 }
02106
02107 return ret;
02108 }
02109
02110 static int mycompar(const void *a, const void *b)
02111 {
02112 char **x = (char **) a;
02113 char **y = (char **) b;
02114 int xoff,yoff;
02115
02116 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02117 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02118 return(strcmp((*x) + xoff,(*y) + yoff));
02119 }
02120
02121 static int topcompar(const void *a, const void *b)
02122 {
02123 struct rpt_topkey *x = (struct rpt_topkey *) a;
02124 struct rpt_topkey *y = (struct rpt_topkey *) b;
02125
02126 return(x->timesince - y->timesince);
02127 }
02128
02129 #ifdef __RPT_NOTCH
02130
02131
02132 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02133 {
02134 int i,j;
02135 struct rptfilter *f;
02136
02137 for(i = 0; i < len; i++)
02138 {
02139 for(j = 0; j < MAXFILTERS; j++)
02140 {
02141 f = &myrpt->filters[j];
02142 if (!*f->desc) continue;
02143 f->x0 = f->x1; f->x1 = f->x2;
02144 f->x2 = ((float)buf[i]) / f->gain;
02145 f->y0 = f->y1; f->y1 = f->y2;
02146 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02147 + (f->const1 * f->y0) + (f->const2 * f->y1);
02148 buf[i] = (short)f->y2;
02149 }
02150 }
02151 }
02152
02153 #endif
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172 #ifdef NEW_ASTERISK
02173 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02174 {
02175 struct timeval when;
02176
02177 when.tv_sec = *t;
02178 when.tv_usec = 0;
02179 ast_localtime(&when, lt, NULL);
02180 }
02181
02182 #else
02183 static void rpt_localtime( time_t * t, struct tm *lt)
02184 {
02185 #ifdef OLD_ASTERISK
02186 localtime_r(t, lt);
02187 #else
02188 ast_localtime(t, lt, NULL);
02189 #endif
02190 }
02191 #endif
02192
02193
02194
02195
02196 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02197 {
02198 char *var;
02199 int ret;
02200 char include_zero = 0;
02201
02202 if(min < 0){
02203 min = -min;
02204 include_zero = 1;
02205 }
02206
02207 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02208 if(var){
02209 ret = myatoi(var);
02210 if(include_zero && !ret)
02211 return 0;
02212 if(ret < min)
02213 ret = min;
02214 if(ret > max)
02215 ret = max;
02216 }
02217 else
02218 ret = defl;
02219 return ret;
02220 }
02221
02222
02223 static void load_rpt_vars(int n,int init)
02224 {
02225 char *this,*val;
02226 int i,j,longestnode;
02227 struct ast_variable *vp;
02228 struct ast_config *cfg;
02229 char *strs[100];
02230 char s1[256];
02231 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02232 "ufena","ufdis","atena","atdis",NULL};
02233
02234 if (option_verbose > 2)
02235 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02236 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02237 ast_mutex_lock(&rpt_vars[n].lock);
02238 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02239 #ifdef NEW_ASTERISK
02240 cfg = ast_config_load("rpt.conf",config_flags);
02241 #else
02242 cfg = ast_config_load("rpt.conf");
02243 #endif
02244 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02245 ast_mutex_unlock(&rpt_vars[n].lock);
02246 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02247 pthread_exit(NULL);
02248 }
02249 rpt_vars[n].cfg = cfg;
02250 this = rpt_vars[n].name;
02251 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02252 if (init)
02253 {
02254 char *cp;
02255 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02256
02257 cp = (char *) &rpt_vars[n].p;
02258 memset(cp + sizeof(rpt_vars[n].p),0,
02259 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02260 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02261 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02262 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02263 rpt_vars[n].tailmessagen = 0;
02264 }
02265 #ifdef __RPT_NOTCH
02266
02267 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02268 #endif
02269 val = (char *) ast_variable_retrieve(cfg,this,"context");
02270 if (val) rpt_vars[n].p.ourcontext = val;
02271 else rpt_vars[n].p.ourcontext = this;
02272 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02273 if (val) rpt_vars[n].p.ourcallerid = val;
02274 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02275 if (val) rpt_vars[n].p.acctcode = val;
02276 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02277 if (val) rpt_vars[n].p.ident = val;
02278 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02279 if (val) rpt_vars[n].p.hangtime = atoi(val);
02280 else rpt_vars[n].p.hangtime = HANGTIME;
02281 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02282 if (val) rpt_vars[n].p.althangtime = atoi(val);
02283 else rpt_vars[n].p.althangtime = HANGTIME;
02284 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02285 if (val) rpt_vars[n].p.totime = atoi(val);
02286 else rpt_vars[n].p.totime = TOTIME;
02287 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02288 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02289 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02290 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02291 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02292 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02293 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02294 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02295 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02296 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02297 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02298 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02299 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02300 if (val) rpt_vars[n].p.statpost_program = val;
02301 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02302 rpt_vars[n].p.statpost_url =
02303 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02304 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02305 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02306 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02307 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02308 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02309 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02310 if (val) rpt_vars[n].p.tonezone = val;
02311 rpt_vars[n].p.tailmessages[0] = 0;
02312 rpt_vars[n].p.tailmessagemax = 0;
02313 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02314 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02315 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02316 if (!val) val = MEMORY;
02317 rpt_vars[n].p.memory = val;
02318 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02319 if (!val) val = MACRO;
02320 rpt_vars[n].p.macro = val;
02321 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02322 if (!val) val = TONEMACRO;
02323 rpt_vars[n].p.tonemacro = val;
02324 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02325 if (val) rpt_vars[n].p.startupmacro = val;
02326 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02327
02328
02329
02330 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02331 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02332 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02333 rpt_vars[n].p.ioport = val;
02334 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02335 if (!val)
02336 {
02337 val = FUNCTIONS;
02338 rpt_vars[n].p.simple = 1;
02339 }
02340 rpt_vars[n].p.functions = val;
02341 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02342 if (val) rpt_vars[n].p.link_functions = val;
02343 else
02344 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02345 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02346 if (val) rpt_vars[n].p.phone_functions = val;
02347 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02348 if (val) rpt_vars[n].p.dphone_functions = val;
02349 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02350 if (val) rpt_vars[n].p.alt_functions = val;
02351 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02352 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02353 rpt_vars[n].p.funcchar = *val;
02354 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02355 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02356 rpt_vars[n].p.endchar = *val;
02357 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02358 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02359 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02360 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02361 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02362 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02363 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02364 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02365 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02366 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02367 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02368 if (!val) val = NODES;
02369 rpt_vars[n].p.nodes = val;
02370 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02371 if (!val) val = EXTNODES;
02372 rpt_vars[n].p.extnodes = val;
02373 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02374 if (!val) val = EXTNODEFILE;
02375 rpt_vars[n].p.extnodefile = val;
02376 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02377 if (val) rpt_vars[n].p.archivedir = val;
02378 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02379 if (val) rpt_vars[n].p.authlevel = atoi(val);
02380 else rpt_vars[n].p.authlevel = 0;
02381 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02382 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02383 else rpt_vars[n].p.parrotmode = 0;
02384 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02385 if (val) rpt_vars[n].p.parrottime = atoi(val);
02386 else rpt_vars[n].p.parrottime = PARROTTIME;
02387 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02388 rpt_vars[n].p.rptnode = val;
02389 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02390 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02391 else rpt_vars[n].p.remote_mars = 0;
02392 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02393 if (val) rpt_vars[n].p.monminblocks = atol(val);
02394 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02395 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02396 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02397 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02398 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02399 if (val) rpt_vars[n].p.civaddr = atoi(val);
02400 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02401 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02402 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02403 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02404 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02405 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02406 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02407 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02408 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02409 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02410 #ifdef __RPT_NOTCH
02411 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02412 if (val) {
02413 i = finddelim(val,strs,MAXFILTERS * 2);
02414 i &= ~1;
02415 if (i >= 2) for(j = 0; j < i; j += 2)
02416 {
02417 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02418 &rpt_vars[n].filters[j >> 1].gain,
02419 &rpt_vars[n].filters[j >> 1].const0,
02420 &rpt_vars[n].filters[j >> 1].const1,
02421 &rpt_vars[n].filters[j >> 1].const2);
02422 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02423 strs[j],strs[j + 1]);
02424 }
02425
02426 }
02427 #endif
02428 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02429 if (val) {
02430 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02431 i = finddelim(val,strs,3);
02432 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02433 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02434 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02435 }
02436 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02437 if (val) {
02438 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02439 i = finddelim(val,strs,3);
02440 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02441 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02442 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02443 }
02444
02445 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02446 rpt_vars[n].p.csstanzaname = val;
02447
02448
02449 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02450 rpt_vars[n].p.skedstanzaname = val;
02451
02452
02453 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02454 rpt_vars[n].p.txlimitsstanzaname = val;
02455
02456 longestnode = 0;
02457
02458 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02459
02460 while(vp){
02461 j = strlen(vp->name);
02462 if (j > longestnode)
02463 longestnode = j;
02464 vp = vp->next;
02465 }
02466
02467 rpt_vars[n].longestnode = longestnode;
02468
02469
02470
02471
02472 rpt_vars[n].longestfunc = 0;
02473 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02474 while(vp){
02475 j = strlen(vp->name);
02476 if (j > rpt_vars[n].longestfunc)
02477 rpt_vars[n].longestfunc = j;
02478 vp = vp->next;
02479 }
02480
02481
02482
02483 rpt_vars[n].link_longestfunc = 0;
02484 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02485 while(vp){
02486 j = strlen(vp->name);
02487 if (j > rpt_vars[n].link_longestfunc)
02488 rpt_vars[n].link_longestfunc = j;
02489 vp = vp->next;
02490 }
02491 rpt_vars[n].phone_longestfunc = 0;
02492 if (rpt_vars[n].p.phone_functions)
02493 {
02494 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02495 while(vp){
02496 j = strlen(vp->name);
02497 if (j > rpt_vars[n].phone_longestfunc)
02498 rpt_vars[n].phone_longestfunc = j;
02499 vp = vp->next;
02500 }
02501 }
02502 rpt_vars[n].dphone_longestfunc = 0;
02503 if (rpt_vars[n].p.dphone_functions)
02504 {
02505 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02506 while(vp){
02507 j = strlen(vp->name);
02508 if (j > rpt_vars[n].dphone_longestfunc)
02509 rpt_vars[n].dphone_longestfunc = j;
02510 vp = vp->next;
02511 }
02512 }
02513 rpt_vars[n].alt_longestfunc = 0;
02514 if (rpt_vars[n].p.alt_functions)
02515 {
02516 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02517 while(vp){
02518 j = strlen(vp->name);
02519 if (j > rpt_vars[n].alt_longestfunc)
02520 rpt_vars[n].alt_longestfunc = j;
02521 vp = vp->next;
02522 }
02523 }
02524 rpt_vars[n].macro_longest = 1;
02525 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02526 while(vp){
02527 j = strlen(vp->name);
02528 if (j > rpt_vars[n].macro_longest)
02529 rpt_vars[n].macro_longest = j;
02530 vp = vp->next;
02531 }
02532
02533
02534 if(rpt_vars[n].p.csstanzaname)
02535 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02536 else
02537 vp = NULL;
02538 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02539 int k,nukw,statenum;
02540 statenum=atoi(vp->name);
02541 strncpy(s1, vp->value, 255);
02542 s1[255] = 0;
02543 nukw = finddelim(s1,strs,32);
02544
02545 for (k = 0 ; k < nukw ; k++){
02546 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02547 if(!strcmp(strs[k],cs_keywords[j])){
02548 switch(j){
02549 case 0:
02550 rpt_vars[n].p.s[statenum].txdisable = 0;
02551 break;
02552 case 1:
02553 rpt_vars[n].p.s[statenum].txdisable = 1;
02554 break;
02555
02556 case 2:
02557 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02558 break;
02559
02560 case 3:
02561 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02562 break;
02563
02564 case 4:
02565 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02566 break;
02567
02568 case 5:
02569 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02570 break;
02571
02572 case 6:
02573 rpt_vars[n].p.s[statenum].totdisable = 0;
02574 break;
02575
02576 case 7:
02577 rpt_vars[n].p.s[statenum].totdisable = 1;
02578 break;
02579
02580 case 8:
02581 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02582 break;
02583
02584 case 9:
02585 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02586 break;
02587
02588 case 10:
02589 rpt_vars[n].p.s[statenum].userfundisable = 0;
02590 break;
02591
02592 case 11:
02593 rpt_vars[n].p.s[statenum].userfundisable = 1;
02594 break;
02595
02596 case 12:
02597 rpt_vars[n].p.s[statenum].alternatetail = 1;
02598 break;
02599
02600 case 13:
02601 rpt_vars[n].p.s[statenum].alternatetail = 0;
02602 break;
02603
02604 default:
02605 ast_log(LOG_WARNING,
02606 "Unhandled control state keyword %s", cs_keywords[i]);
02607 break;
02608 }
02609 }
02610 }
02611 }
02612 vp = vp->next;
02613 }
02614 ast_mutex_unlock(&rpt_vars[n].lock);
02615 }
02616
02617
02618
02619
02620
02621 static int rpt_do_debug(int fd, int argc, char *argv[])
02622 {
02623 int newlevel;
02624
02625 if (argc != 4)
02626 return RESULT_SHOWUSAGE;
02627 newlevel = myatoi(argv[3]);
02628 if((newlevel < 0) || (newlevel > 7))
02629 return RESULT_SHOWUSAGE;
02630 if(newlevel)
02631 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02632 else
02633 ast_cli(fd, "app_rpt Debugging disabled\n");
02634
02635 debug = newlevel;
02636 return RESULT_SUCCESS;
02637 }
02638
02639
02640
02641
02642
02643 static int rpt_do_dump(int fd, int argc, char *argv[])
02644 {
02645 int i;
02646
02647 if (argc != 3)
02648 return RESULT_SHOWUSAGE;
02649
02650 for(i = 0; i < nrpts; i++)
02651 {
02652 if (!strcmp(argv[2],rpt_vars[i].name))
02653 {
02654 rpt_vars[i].disgorgetime = time(NULL) + 10;
02655 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02656 return RESULT_SUCCESS;
02657 }
02658 }
02659 return RESULT_FAILURE;
02660 }
02661
02662
02663
02664
02665
02666 static int rpt_do_stats(int fd, int argc, char *argv[])
02667 {
02668 int i,j,numoflinks;
02669 int dailytxtime, dailykerchunks;
02670 time_t now;
02671 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02672 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02673 int uptime;
02674 long long totaltxtime;
02675 struct rpt_link *l;
02676 char *listoflinks[MAX_STAT_LINKS];
02677 char *lastdtmfcommand,*parrot_ena;
02678 char *tot_state, *ider_state, *patch_state;
02679 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02680 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02681 struct rpt *myrpt;
02682
02683 static char *not_applicable = "N/A";
02684
02685 if(argc != 3)
02686 return RESULT_SHOWUSAGE;
02687
02688 tot_state = ider_state =
02689 patch_state = reverse_patch_state =
02690 input_signal = not_applicable;
02691 called_number = lastdtmfcommand = NULL;
02692
02693 time(&now);
02694 for(i = 0; i < nrpts; i++)
02695 {
02696 if (!strcmp(argv[2],rpt_vars[i].name)){
02697
02698 myrpt = &rpt_vars[i];
02699 rpt_mutex_lock(&myrpt->lock);
02700 uptime = (int)(now - starttime);
02701 dailytxtime = myrpt->dailytxtime;
02702 totaltxtime = myrpt->totaltxtime;
02703 dailykeyups = myrpt->dailykeyups;
02704 totalkeyups = myrpt->totalkeyups;
02705 dailykerchunks = myrpt->dailykerchunks;
02706 totalkerchunks = myrpt->totalkerchunks;
02707 dailyexecdcommands = myrpt->dailyexecdcommands;
02708 totalexecdcommands = myrpt->totalexecdcommands;
02709 timeouts = myrpt->timeouts;
02710
02711
02712 reverse_patch_state = "DOWN";
02713 numoflinks = 0;
02714 l = myrpt->links.next;
02715 while(l && (l != &myrpt->links)){
02716 if(numoflinks >= MAX_STAT_LINKS){
02717 ast_log(LOG_NOTICE,
02718 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02719 break;
02720 }
02721 if (l->name[0] == '0'){
02722 reverse_patch_state = "UP";
02723 l = l->next;
02724 continue;
02725 }
02726 listoflinks[numoflinks] = ast_strdup(l->name);
02727 if(listoflinks[numoflinks] == NULL){
02728 break;
02729 }
02730 else{
02731 numoflinks++;
02732 }
02733 l = l->next;
02734 }
02735
02736 if(myrpt->keyed)
02737 input_signal = "YES";
02738 else
02739 input_signal = "NO";
02740
02741 if(myrpt->p.parrotmode)
02742 parrot_ena = "ENABLED";
02743 else
02744 parrot_ena = "DISABLED";
02745
02746 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02747 sys_ena = "DISABLED";
02748 else
02749 sys_ena = "ENABLED";
02750
02751 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02752 tot_ena = "DISABLED";
02753 else
02754 tot_ena = "ENABLED";
02755
02756 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02757 link_ena = "DISABLED";
02758 else
02759 link_ena = "ENABLED";
02760
02761 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02762 patch_ena = "DISABLED";
02763 else
02764 patch_ena = "ENABLED";
02765
02766 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02767 sch_ena = "DISABLED";
02768 else
02769 sch_ena = "ENABLED";
02770
02771 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02772 user_funs = "DISABLED";
02773 else
02774 user_funs = "ENABLED";
02775
02776 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02777 tail_type = "ALTERNATE";
02778 else
02779 tail_type = "STANDARD";
02780
02781 if(!myrpt->totimer)
02782 tot_state = "TIMED OUT!";
02783 else if(myrpt->totimer != myrpt->p.totime)
02784 tot_state = "ARMED";
02785 else
02786 tot_state = "RESET";
02787
02788 if(myrpt->tailid)
02789 ider_state = "QUEUED IN TAIL";
02790 else if(myrpt->mustid)
02791 ider_state = "QUEUED FOR CLEANUP";
02792 else
02793 ider_state = "CLEAN";
02794
02795 switch(myrpt->callmode){
02796 case 1:
02797 patch_state = "DIALING";
02798 break;
02799 case 2:
02800 patch_state = "CONNECTING";
02801 break;
02802 case 3:
02803 patch_state = "UP";
02804 break;
02805
02806 case 4:
02807 patch_state = "CALL FAILED";
02808 break;
02809
02810 default:
02811 patch_state = "DOWN";
02812 }
02813
02814 if(strlen(myrpt->exten)){
02815 called_number = ast_strdup(myrpt->exten);
02816 }
02817
02818 if(strlen(myrpt->lastdtmfcommand)){
02819 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02820 }
02821 rpt_mutex_unlock(&myrpt->lock);
02822
02823 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02824 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02825 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02826 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02827 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02828 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02829 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02830 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02831 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02832 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02833 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02834 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02835 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02836 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02837 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02838 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02839 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02840 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02841 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02842 hours = dailytxtime/3600000;
02843 dailytxtime %= 3600000;
02844 minutes = dailytxtime/60000;
02845 dailytxtime %= 60000;
02846 seconds = dailytxtime/1000;
02847 dailytxtime %= 1000;
02848
02849 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02850 hours, minutes, seconds, dailytxtime);
02851
02852 hours = (int) totaltxtime/3600000;
02853 totaltxtime %= 3600000;
02854 minutes = (int) totaltxtime/60000;
02855 totaltxtime %= 60000;
02856 seconds = (int) totaltxtime/1000;
02857 totaltxtime %= 1000;
02858
02859 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02860 hours, minutes, seconds, (int) totaltxtime);
02861
02862 hours = uptime/3600;
02863 uptime %= 3600;
02864 minutes = uptime/60;
02865 uptime %= 60;
02866
02867 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02868 hours, minutes, uptime);
02869
02870 ast_cli(fd, "Nodes currently connected to us..................: ");
02871 if(!numoflinks){
02872 ast_cli(fd,"<NONE>");
02873 }
02874 else{
02875 for(j = 0 ;j < numoflinks; j++){
02876 ast_cli(fd, "%s", listoflinks[j]);
02877 if(j % 4 == 3){
02878 ast_cli(fd, "\n");
02879 ast_cli(fd, " : ");
02880 }
02881 else{
02882 if((numoflinks - 1) - j > 0)
02883 ast_cli(fd, ", ");
02884 }
02885 }
02886 }
02887 ast_cli(fd,"\n");
02888
02889 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02890 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02891 ast_cli(fd, "Autopatch called number..........................: %s\n",
02892 (called_number && strlen(called_number)) ? called_number : not_applicable);
02893 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02894 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02895 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02896
02897 for(j = 0; j < numoflinks; j++){
02898 ast_free(listoflinks[j]);
02899 }
02900 if(called_number){
02901 ast_free(called_number);
02902 }
02903 if(lastdtmfcommand){
02904 ast_free(lastdtmfcommand);
02905 }
02906 return RESULT_SUCCESS;
02907 }
02908 }
02909 return RESULT_FAILURE;
02910 }
02911
02912
02913
02914
02915
02916 static int rpt_do_lstats(int fd, int argc, char *argv[])
02917 {
02918 int i,j;
02919 char *connstate;
02920 struct rpt *myrpt;
02921 struct rpt_link *l;
02922 struct rpt_lstat *s,*t;
02923 struct rpt_lstat s_head;
02924 if(argc != 3)
02925 return RESULT_SHOWUSAGE;
02926
02927 s = NULL;
02928 s_head.next = &s_head;
02929 s_head.prev = &s_head;
02930
02931 for(i = 0; i < nrpts; i++)
02932 {
02933 if (!strcmp(argv[2],rpt_vars[i].name)){
02934
02935 myrpt = &rpt_vars[i];
02936 rpt_mutex_lock(&myrpt->lock);
02937
02938 j = 0;
02939 l = myrpt->links.next;
02940 while(l && (l != &myrpt->links)){
02941 if (l->name[0] == '0'){
02942 l = l->next;
02943 continue;
02944 }
02945 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02946 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02947 rpt_mutex_unlock(&myrpt->lock);
02948 return RESULT_FAILURE;
02949 }
02950 memset(s, 0, sizeof(struct rpt_lstat));
02951 strncpy(s->name, l->name, MAXREMSTR - 1);
02952 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02953 else strcpy(s->peer,"(none)");
02954 s->mode = l->mode;
02955 s->outbound = l->outbound;
02956 s->reconnects = l->reconnects;
02957 s->connecttime = l->connecttime;
02958 s->thisconnected = l->thisconnected;
02959 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02960 insque((struct qelem *) s, (struct qelem *) s_head.next);
02961 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02962 l = l->next;
02963 }
02964 rpt_mutex_unlock(&myrpt->lock);
02965 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02966 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02967
02968 for(s = s_head.next; s != &s_head; s = s->next){
02969 int hours, minutes, seconds;
02970 long long connecttime = s->connecttime;
02971 char conntime[21];
02972 hours = (int) connecttime/3600000;
02973 connecttime %= 3600000;
02974 minutes = (int) connecttime/60000;
02975 connecttime %= 60000;
02976 seconds = (int) connecttime/1000;
02977 connecttime %= 1000;
02978 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02979 hours, minutes, seconds, (int) connecttime);
02980 conntime[20] = 0;
02981 if(s->thisconnected)
02982 connstate = "ESTABLISHED";
02983 else
02984 connstate = "CONNECTING";
02985 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02986 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02987 }
02988
02989 s = s_head.next;
02990 while(s != &s_head){
02991 t = s;
02992 s = s->next;
02993 remque((struct qelem *)t);
02994 ast_free(t);
02995 }
02996 return RESULT_SUCCESS;
02997 }
02998 }
02999 return RESULT_FAILURE;
03000 }
03001
03002
03003
03004
03005
03006 static int rpt_do_nodes(int fd, int argc, char *argv[])
03007 {
03008 int i,j;
03009 char ns;
03010 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03011 struct rpt *myrpt;
03012 if(argc != 3)
03013 return RESULT_SHOWUSAGE;
03014
03015 for(i = 0; i < nrpts; i++)
03016 {
03017 if (!strcmp(argv[2],rpt_vars[i].name)){
03018
03019 myrpt = &rpt_vars[i];
03020 rpt_mutex_lock(&myrpt->lock);
03021 __mklinklist(myrpt,NULL,lbuf);
03022 rpt_mutex_unlock(&myrpt->lock);
03023
03024 ns = finddelim(lbuf,strs,MAXLINKLIST);
03025
03026 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03027 ast_cli(fd,"\n");
03028 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03029 for(j = 0 ;; j++){
03030 if(!strs[j]){
03031 if(!j){
03032 ast_cli(fd,"<NONE>");
03033 }
03034 break;
03035 }
03036 ast_cli(fd, "%s", strs[j]);
03037 if(j % 8 == 7){
03038 ast_cli(fd, "\n");
03039 }
03040 else{
03041 if(strs[j + 1])
03042 ast_cli(fd, ", ");
03043 }
03044 }
03045 ast_cli(fd,"\n\n");
03046 return RESULT_SUCCESS;
03047 }
03048 }
03049 return RESULT_FAILURE;
03050 }
03051
03052
03053
03054
03055
03056 static int rpt_do_local_nodes(int fd, int argc, char *argv[])
03057 {
03058
03059 int i;
03060 ast_cli(fd, "\nNode\n----\n");
03061 for (i=0; i< nrpts; i++)
03062 {
03063 ast_cli(fd, "%s\n", rpt_vars[i].name);
03064 }
03065 ast_cli(fd,"\n");
03066 return RESULT_SUCCESS;
03067 }
03068
03069
03070
03071
03072
03073
03074 static int rpt_do_reload(int fd, int argc, char *argv[])
03075 {
03076 int n;
03077
03078 if (argc > 2) return RESULT_SHOWUSAGE;
03079
03080 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03081
03082 return RESULT_FAILURE;
03083 }
03084
03085
03086
03087
03088
03089 static int rpt_do_restart(int fd, int argc, char *argv[])
03090 {
03091 int i;
03092
03093 if (argc > 2) return RESULT_SHOWUSAGE;
03094 for(i = 0; i < nrpts; i++)
03095 {
03096 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03097 }
03098 return RESULT_FAILURE;
03099 }
03100
03101
03102
03103
03104
03105
03106 static int rpt_do_fun(int fd, int argc, char *argv[])
03107 {
03108 int i,busy=0;
03109
03110 if (argc != 4) return RESULT_SHOWUSAGE;
03111
03112 for(i = 0; i < nrpts; i++){
03113 if(!strcmp(argv[2], rpt_vars[i].name)){
03114 struct rpt *myrpt = &rpt_vars[i];
03115 rpt_mutex_lock(&myrpt->lock);
03116 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03117 rpt_mutex_unlock(&myrpt->lock);
03118 busy=1;
03119 }
03120 if(!busy){
03121 myrpt->macrotimer = MACROTIME;
03122 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03123 }
03124 rpt_mutex_unlock(&myrpt->lock);
03125 }
03126 }
03127 if(busy){
03128 ast_cli(fd, "Function decoder busy");
03129 }
03130 return RESULT_FAILURE;
03131 }
03132
03133
03134
03135
03136
03137
03138
03139
03140 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03141 {
03142 int busy=0;
03143
03144 rpt_mutex_lock(&myrpt->lock);
03145 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03146 rpt_mutex_unlock(&myrpt->lock);
03147 busy=1;
03148 }
03149 if(!busy){
03150 int x;
03151 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03152 myrpt->macrotimer = MACROTIME;
03153 for(x = 0; *(sptr + x); x++)
03154 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03155 *(sptr + x) = 0;
03156 }
03157 rpt_mutex_unlock(&myrpt->lock);
03158
03159 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03160
03161 return busy;
03162 }
03163
03164
03165
03166 static int rpt_do_fun1(int fd, int argc, char *argv[])
03167 {
03168 int i;
03169
03170 if (argc != 4) return RESULT_SHOWUSAGE;
03171
03172 for(i = 0; i < nrpts; i++){
03173 if(!strcmp(argv[2], rpt_vars[i].name)){
03174 struct rpt *myrpt = &rpt_vars[i];
03175 rpt_push_alt_macro(myrpt,argv[3]);
03176 }
03177 }
03178 return RESULT_FAILURE;
03179 }
03180
03181
03182
03183
03184 static int rpt_do_cmd(int fd, int argc, char *argv[])
03185 {
03186 int i, l;
03187 int busy=0;
03188 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03189
03190 int thisRpt = -1;
03191 int thisAction = -1;
03192 struct rpt *myrpt = NULL;
03193 if (argc != 6) return RESULT_SHOWUSAGE;
03194
03195 for(i = 0; i < nrpts; i++)
03196 {
03197 if(!strcmp(argv[2], rpt_vars[i].name))
03198 {
03199 thisRpt = i;
03200 myrpt = &rpt_vars[i];
03201 break;
03202 }
03203 }
03204
03205 if (thisRpt < 0)
03206 {
03207 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03208 return RESULT_FAILURE;
03209 }
03210
03211
03212 l = strlen(argv[3]);
03213 for(i = 0 ; i < maxActions; i++)
03214 {
03215 if(!strncasecmp(argv[3], function_table[i].action, l))
03216 {
03217 thisAction = i;
03218 break;
03219 }
03220 }
03221
03222 if (thisAction < 0)
03223 {
03224 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03225 return RESULT_FAILURE;
03226 }
03227
03228
03229
03230 rpt_mutex_lock(&myrpt->lock);
03231
03232 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03233 {
03234 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03235 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03236 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03237 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03238 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03239 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03240 }
03241 else
03242 {
03243 busy = 1;
03244 }
03245 rpt_mutex_unlock(&myrpt->lock);
03246
03247 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03248 }
03249
03250 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03251 {
03252 int res;
03253
03254 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03255 return res;
03256
03257 while(chan->generatordata) {
03258 if (ast_safe_sleep(chan,1)) return -1;
03259 }
03260
03261 return 0;
03262 }
03263
03264 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03265 {
03266 return play_tone_pair(chan, freq, 0, duration, amplitude);
03267 }
03268
03269 static int play_silence(struct ast_channel *chan, int duration)
03270 {
03271 return play_tone_pair(chan, 0, 0, duration, 0);
03272 }
03273
03274 #ifdef NEW_ASTERISK
03275
03276 static char *res2cli(int r)
03277
03278 {
03279 switch (r)
03280 {
03281 case RESULT_SUCCESS:
03282 return(CLI_SUCCESS);
03283 case RESULT_SHOWUSAGE:
03284 return(CLI_SHOWUSAGE);
03285 default:
03286 return(CLI_FAILURE);
03287 }
03288 }
03289
03290 static char *handle_cli_debug(struct ast_cli_entry *e,
03291 int cmd, struct ast_cli_args *a)
03292 {
03293 switch (cmd) {
03294 case CLI_INIT:
03295 e->command = "rpt debug level";
03296 e->usage = debug_usage;
03297 return NULL;
03298 case CLI_GENERATE:
03299 return NULL;
03300 }
03301 return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
03302 }
03303
03304 static char *handle_cli_dump(struct ast_cli_entry *e,
03305 int cmd, struct ast_cli_args *a)
03306 {
03307 switch (cmd) {
03308 case CLI_INIT:
03309 e->command = "rpt dump level";
03310 e->usage = dump_usage;
03311 return NULL;
03312 case CLI_GENERATE:
03313 return NULL;
03314 }
03315 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03316 }
03317
03318
03319 static char *handle_cli_stats(struct ast_cli_entry *e,
03320 int cmd, struct ast_cli_args *a)
03321 {
03322 switch (cmd) {
03323 case CLI_INIT:
03324 e->command = "rpt stats";
03325 e->usage = dump_stats;
03326 return NULL;
03327 case CLI_GENERATE:
03328 return NULL;
03329 }
03330 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03331 }
03332
03333 static char *handle_cli_nodes(struct ast_cli_entry *e,
03334 int cmd, struct ast_cli_args *a)
03335 {
03336 switch (cmd) {
03337 case CLI_INIT:
03338 e->command = "rpt nodes";
03339 e->usage = dump_nodes;
03340 return NULL;
03341 case CLI_GENERATE:
03342 return NULL;
03343 }
03344 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03345 }
03346
03347 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03348 int cmd, struct ast_cli_args *a)
03349 {
03350 switch (cmd) {
03351 case CLI_INIT:
03352 e->command = "rpt localnodes";
03353 e->usage = usage_local_nodes;
03354 return NULL;
03355 case CLI_GENERATE:
03356 return NULL;
03357 }
03358 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03359 }
03360
03361 static char *handle_cli_lstats(struct ast_cli_entry *e,
03362 int cmd, struct ast_cli_args *a)
03363 {
03364 switch (cmd) {
03365 case CLI_INIT:
03366 e->command = "rpt lstats";
03367 e->usage = dump_lstats;
03368 return NULL;
03369 case CLI_GENERATE:
03370 return NULL;
03371 }
03372 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03373 }
03374
03375 static char *handle_cli_reload(struct ast_cli_entry *e,
03376 int cmd, struct ast_cli_args *a)
03377 {
03378 switch (cmd) {
03379 case CLI_INIT:
03380 e->command = "rpt reload";
03381 e->usage = reload_usage;
03382 return NULL;
03383 case CLI_GENERATE:
03384 return NULL;
03385 }
03386 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03387 }
03388
03389 static char *handle_cli_restart(struct ast_cli_entry *e,
03390 int cmd, struct ast_cli_args *a)
03391 {
03392 switch (cmd) {
03393 case CLI_INIT:
03394 e->command = "rpt restart";
03395 e->usage = restart_usage;
03396 return NULL;
03397 case CLI_GENERATE:
03398 return NULL;
03399 }
03400 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03401 }
03402
03403 static char *handle_cli_fun(struct ast_cli_entry *e,
03404 int cmd, struct ast_cli_args *a)
03405 {
03406 switch (cmd) {
03407 case CLI_INIT:
03408 e->command = "rpt fun";
03409 e->usage = fun_usage;
03410 return NULL;
03411 case CLI_GENERATE:
03412 return NULL;
03413 }
03414 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03415 }
03416
03417 static char *handle_cli_fun1(struct ast_cli_entry *e,
03418 int cmd, struct ast_cli_args *a)
03419 {
03420 switch (cmd) {
03421 case CLI_INIT:
03422 e->command = "rpt fun1";
03423 e->usage = fun_usage;
03424 return NULL;
03425 case CLI_GENERATE:
03426 return NULL;
03427 }
03428 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03429 }
03430
03431 static char *handle_cli_cmd(struct ast_cli_entry *e,
03432 int cmd, struct ast_cli_args *a)
03433 {
03434 switch (cmd) {
03435 case CLI_INIT:
03436 e->command = "rpt cmd";
03437 e->usage = cmd_usage;
03438 return NULL;
03439 case CLI_GENERATE:
03440 return NULL;
03441 }
03442 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03443 }
03444
03445 static struct ast_cli_entry rpt_cli[] = {
03446 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03447 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03448 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03449 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03450 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03451 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03452 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03453 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03454 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03455 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03456 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03457 };
03458
03459 #endif
03460
03461 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03462 {
03463
03464 static struct morse_bits mbits[] = {
03465 {0, 0},
03466 {0, 0},
03467 {6, 18},
03468 {0, 0},
03469 {7, 72},
03470 {0, 0},
03471 {0, 0},
03472 {6, 30},
03473 {5, 13},
03474 {6, 29},
03475 {0, 0},
03476 {5, 10},
03477 {6, 51},
03478 {6, 33},
03479 {6, 42},
03480 {5, 9},
03481 {5, 31},
03482 {5, 30},
03483 {5, 28},
03484 {5, 24},
03485 {5, 16},
03486 {5, 0},
03487 {5, 1},
03488 {5, 3},
03489 {5, 7},
03490 {5, 15},
03491 {6, 7},
03492 {6, 21},
03493 {0, 0},
03494 {5, 33},
03495 {0, 0},
03496 {6, 12},
03497 {0, 0},
03498 {2, 2},
03499 {4, 1},
03500 {4, 5},
03501 {3, 1},
03502 {1, 0},
03503 {4, 4},
03504 {3, 3},
03505 {4, 0},
03506 {2, 0},
03507 {4, 14},
03508 {3, 5},
03509 {4, 2},
03510 {2, 3},
03511 {2, 1},
03512 {3, 7},
03513 {4, 6},
03514 {4, 11},
03515 {3, 2},
03516 {3, 0},
03517 {1, 1},
03518 {3, 4},
03519 {4, 8},
03520 {3, 6},
03521 {4, 9},
03522 {4, 13},
03523 {4, 3}
03524 };
03525
03526
03527 int dottime;
03528 int dashtime;
03529 int intralettertime;
03530 int interlettertime;
03531 int interwordtime;
03532 int len, ddcomb;
03533 int res;
03534 int c;
03535 int i;
03536 int flags;
03537
03538 res = 0;
03539
03540
03541
03542 dottime = 900/speed;
03543
03544
03545
03546 dashtime = 3 * dottime;
03547 intralettertime = dottime;
03548 interlettertime = dottime * 4 ;
03549 interwordtime = dottime * 7;
03550
03551 for(;(*string) && (!res); string++){
03552
03553 c = *string;
03554
03555
03556
03557 if((c >= 'a') && (c <= 'z'))
03558 c -= 0x20;
03559
03560
03561
03562 if(c > 'Z')
03563 continue;
03564
03565
03566
03567 if(c == ' '){
03568 if(!res)
03569 res = play_silence(chan, interwordtime);
03570 continue;
03571 }
03572
03573
03574
03575 c -= 0x20;
03576
03577
03578
03579 len = mbits[c].len;
03580 ddcomb = mbits[c].ddcomb;
03581
03582
03583
03584 for(; len ; len--){
03585 if(!res)
03586 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03587 if(!res)
03588 res = play_silence(chan, intralettertime);
03589 ddcomb >>= 1;
03590 }
03591
03592
03593
03594 if(!res)
03595 res = play_silence(chan, interlettertime - intralettertime);
03596 }
03597
03598
03599
03600 if (!res)
03601 res = ast_waitstream(chan, "");
03602 ast_stopstream(chan);
03603
03604
03605
03606
03607
03608 for(i = 0; i < 20 ; i++){
03609 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03610 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03611 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03612 break;
03613 if( ast_safe_sleep(chan, 50)){
03614 res = -1;
03615 break;
03616 }
03617 }
03618
03619
03620 return res;
03621 }
03622
03623 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03624 {
03625 char *p,*stringp;
03626 char *tonesubset;
03627 int f1,f2;
03628 int duration;
03629 int amplitude;
03630 int res;
03631 int i;
03632 int flags;
03633
03634 res = 0;
03635
03636 if(!tonestring)
03637 return res;
03638
03639 p = stringp = ast_strdup(tonestring);
03640
03641 for(;tonestring;){
03642 tonesubset = strsep(&stringp,")");
03643 if(!tonesubset)
03644 break;
03645 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03646 break;
03647 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03648 if(res)
03649 break;
03650 }
03651 if(p)
03652 ast_free(p);
03653 if(!res)
03654 res = play_tone_pair(chan, 0, 0, 100, 0);
03655
03656 if (!res)
03657 res = ast_waitstream(chan, "");
03658
03659 ast_stopstream(chan);
03660
03661
03662
03663
03664
03665 for(i = 0; i < 20 ; i++){
03666 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03667 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03668 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03669 break;
03670 if( ast_safe_sleep(chan, 50)){
03671 res = -1;
03672 break;
03673 }
03674 }
03675
03676 return res;
03677
03678 }
03679
03680 static int sayfile(struct ast_channel *mychannel,char *fname)
03681 {
03682 int res;
03683
03684 res = ast_streamfile(mychannel, fname, mychannel->language);
03685 if (!res)
03686 res = ast_waitstream(mychannel, "");
03687 else
03688 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03689 ast_stopstream(mychannel);
03690 return res;
03691 }
03692
03693 static int saycharstr(struct ast_channel *mychannel,char *str)
03694 {
03695 int res;
03696
03697 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03698 if (!res)
03699 res = ast_waitstream(mychannel, "");
03700 else
03701 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03702 ast_stopstream(mychannel);
03703 return res;
03704 }
03705
03706 static int saynum(struct ast_channel *mychannel, int num)
03707 {
03708 int res;
03709 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03710 if(!res)
03711 res = ast_waitstream(mychannel, "");
03712 else
03713 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03714 ast_stopstream(mychannel);
03715 return res;
03716 }
03717
03718
03719
03720
03721 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03722 {
03723 int res;
03724 char *val,fname[300];
03725
03726 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03727 if (!val) val = NODENAMES;
03728 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03729 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03730 return(sayfile(mychannel,fname));
03731 res = sayfile(mychannel,"rpt/node");
03732 if (!res)
03733 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03734 return res;
03735 }
03736
03737 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03738 {
03739 int res;
03740 char c;
03741
03742 static int morsespeed;
03743 static int morsefreq;
03744 static int morseampl;
03745 static int morseidfreq = 0;
03746 static int morseidampl;
03747 static char mcat[] = MORSE;
03748
03749 res = 0;
03750
03751 if(!morseidfreq){
03752 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03753 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03754 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03755 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03756 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03757 }
03758
03759
03760
03761 if(entry[0] == '|'){
03762 c = entry[1];
03763 if((c >= 'a')&&(c <= 'z'))
03764 c -= 0x20;
03765
03766 switch(c){
03767 case 'I':
03768 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03769 break;
03770
03771 case 'M':
03772 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03773 break;
03774
03775 case 'T':
03776 res = send_tone_telemetry(chan, entry + 2);
03777 break;
03778 default:
03779 res = -1;
03780 }
03781 }
03782 else
03783 res = sayfile(chan, entry);
03784 return res;
03785 }
03786
03787
03788
03789
03790
03791
03792
03793 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03794 {
03795
03796 int res;
03797 int i;
03798 char *entry;
03799 char *telemetry;
03800 char *telemetry_save;
03801
03802 res = 0;
03803 telemetry_save = NULL;
03804 entry = NULL;
03805
03806
03807 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03808 if(telemetry ){
03809 telemetry_save = ast_strdup(telemetry);
03810 if(!telemetry_save){
03811 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03812 return res;
03813 }
03814 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03815 }
03816
03817
03818
03819 if(!entry){
03820
03821 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03822 if(!strcasecmp(tele_defs[i].name, name))
03823 entry = tele_defs[i].value;
03824 }
03825 }
03826 if(entry){
03827 if(strlen(entry))
03828 if (chan) telem_any(myrpt,chan, entry);
03829 }
03830 else{
03831 res = -1;
03832 }
03833 if(telemetry_save)
03834 ast_free(telemetry_save);
03835 return res;
03836 }
03837
03838
03839
03840
03841
03842 static int get_wait_interval(struct rpt *myrpt, int type)
03843 {
03844 int interval;
03845 char *wait_times;
03846 char *wait_times_save;
03847
03848 wait_times_save = NULL;
03849 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03850
03851 if(wait_times){
03852 wait_times_save = ast_strdup(wait_times);
03853 if(!wait_times_save)
03854 return 0;
03855
03856 }
03857
03858 switch(type){
03859 case DLY_TELEM:
03860 if(wait_times)
03861 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03862 else
03863 interval = 1000;
03864 break;
03865
03866 case DLY_ID:
03867 if(wait_times)
03868 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03869 else
03870 interval = 500;
03871 break;
03872
03873 case DLY_UNKEY:
03874 if(wait_times)
03875 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03876 else
03877 interval = 1000;
03878 break;
03879
03880 case DLY_LINKUNKEY:
03881 if(wait_times)
03882 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03883 else
03884 interval = 1000;
03885 break;
03886
03887 case DLY_CALLTERM:
03888 if(wait_times)
03889 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03890 else
03891 interval = 1500;
03892 break;
03893
03894 case DLY_COMP:
03895 if(wait_times)
03896 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03897 else
03898 interval = 200;
03899 break;
03900
03901 case DLY_PARROT:
03902 if(wait_times)
03903 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03904 else
03905 interval = 200;
03906 break;
03907
03908 default:
03909 interval = 0;
03910 break;
03911 }
03912 if(wait_times_save)
03913 ast_free(wait_times_save);
03914 return interval;
03915 }
03916
03917
03918
03919
03920
03921 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03922 {
03923 int interval;
03924 interval = get_wait_interval(myrpt, type);
03925 if(debug)
03926 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03927 if(interval)
03928 ast_safe_sleep(chan,interval);
03929 if(debug)
03930 ast_log(LOG_NOTICE,"Delay complete\n");
03931 return;
03932 }
03933
03934 static int split_freq(char *mhz, char *decimals, char *freq);
03935
03936 static void *rpt_tele_thread(void *this)
03937 {
03938 struct dahdi_confinfo ci;
03939 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03940 struct rpt_tele *mytele = (struct rpt_tele *)this;
03941 struct rpt_tele *tlist;
03942 struct rpt *myrpt;
03943 struct rpt_link *l,*l1,linkbase;
03944 struct ast_channel *mychannel;
03945 int vmajor, vminor, m;
03946 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03947 time_t t;
03948 #ifdef NEW_ASTERISK
03949 struct ast_tm localtm;
03950 #else
03951 struct tm localtm;
03952 #endif
03953 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03954 int i,ns,rbimode;
03955 char mhz[MAXREMSTR];
03956 char decimals[MAXREMSTR];
03957 char mystr[200];
03958 struct dahdi_params par;
03959
03960
03961
03962 myrpt = mytele->rpt;
03963
03964
03965 rpt_mutex_lock(&myrpt->lock);
03966 nodename = ast_strdup(myrpt->name);
03967 if(!nodename)
03968 {
03969 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03970 rpt_mutex_lock(&myrpt->lock);
03971 remque((struct qelem *)mytele);
03972 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03973 rpt_mutex_unlock(&myrpt->lock);
03974 ast_free(mytele);
03975 pthread_exit(NULL);
03976 }
03977
03978 if (myrpt->p.ident){
03979 ident = ast_strdup(myrpt->p.ident);
03980 if(!ident)
03981 {
03982 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03983 rpt_mutex_lock(&myrpt->lock);
03984 remque((struct qelem *)mytele);
03985 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03986 __LINE__, mytele->mode);
03987 rpt_mutex_unlock(&myrpt->lock);
03988 ast_free(nodename);
03989 ast_free(mytele);
03990 pthread_exit(NULL);
03991 }
03992 }
03993 else
03994 {
03995 ident = "";
03996 }
03997 rpt_mutex_unlock(&myrpt->lock);
03998
03999
04000
04001
04002 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
04003 if (!mychannel)
04004 {
04005 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04006 rpt_mutex_lock(&myrpt->lock);
04007 remque((struct qelem *)mytele);
04008 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04009 rpt_mutex_unlock(&myrpt->lock);
04010 ast_free(nodename);
04011 ast_free(ident);
04012 ast_free(mytele);
04013 pthread_exit(NULL);
04014 }
04015 #ifdef AST_CDR_FLAG_POST_DISABLED
04016 if (mychannel->cdr)
04017 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04018 #endif
04019 rpt_mutex_lock(&myrpt->lock);
04020 mytele->chan = mychannel;
04021 rpt_mutex_unlock(&myrpt->lock);
04022
04023 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04024 (mytele->mode != LINKUNKEY))
04025 {
04026 rpt_mutex_lock(&myrpt->lock);
04027 if (!myrpt->active_telem)
04028 {
04029 myrpt->active_telem = mytele;
04030 rpt_mutex_unlock(&myrpt->lock);
04031 break;
04032 }
04033 rpt_mutex_unlock(&myrpt->lock);
04034 usleep(100000);
04035 }
04036
04037
04038 ci.chan = 0;
04039
04040
04041
04042 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04043 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04044 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04045 myrpt->txconf : myrpt->conf);
04046 ci.confmode = DAHDI_CONF_CONFANN;
04047
04048 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04049 {
04050 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04051 rpt_mutex_lock(&myrpt->lock);
04052 myrpt->active_telem = NULL;
04053 remque((struct qelem *)mytele);
04054 rpt_mutex_unlock(&myrpt->lock);
04055 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04056 ast_free(nodename);
04057 ast_free(ident);
04058 ast_free(mytele);
04059 ast_hangup(mychannel);
04060 pthread_exit(NULL);
04061 }
04062 ast_stopstream(mychannel);
04063 switch(mytele->mode)
04064 {
04065 case ID:
04066 case ID1:
04067
04068 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04069 res = telem_any(myrpt,mychannel, ident);
04070 imdone=1;
04071 break;
04072
04073 case TAILMSG:
04074 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04075 break;
04076
04077 case IDTALKOVER:
04078 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04079 if(p)
04080 res = telem_any(myrpt,mychannel, p);
04081 imdone=1;
04082 break;
04083
04084 case PROC:
04085
04086 wait_interval(myrpt, DLY_TELEM, mychannel);
04087 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04088 if(res < 0){
04089 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04090 }
04091 break;
04092 case TERM:
04093
04094 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04095 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04096 if(res < 0){
04097 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04098 }
04099 break;
04100 case COMPLETE:
04101
04102 wait_interval(myrpt, DLY_TELEM, mychannel);
04103 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04104 break;
04105 case MACRO_NOTFOUND:
04106
04107 wait_interval(myrpt, DLY_TELEM, mychannel);
04108 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04109 break;
04110 case MACRO_BUSY:
04111
04112 wait_interval(myrpt, DLY_TELEM, mychannel);
04113 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04114 break;
04115 case UNKEY:
04116 if(myrpt->patchnoct && myrpt->callmode){
04117 imdone = 1;
04118 break;
04119 }
04120
04121
04122
04123
04124
04125 x = get_wait_interval(myrpt, DLY_UNKEY);
04126 rpt_mutex_lock(&myrpt->lock);
04127 myrpt->unkeytocttimer = x;
04128 rpt_mutex_unlock(&myrpt->lock);
04129
04130
04131
04132
04133
04134 tlist = myrpt->tele.next;
04135 unkeys_queued = 0;
04136 if (tlist != &myrpt->tele)
04137 {
04138 rpt_mutex_lock(&myrpt->lock);
04139 while(tlist != &myrpt->tele){
04140 if (tlist->mode == UNKEY) unkeys_queued++;
04141 tlist = tlist->next;
04142 }
04143 rpt_mutex_unlock(&myrpt->lock);
04144 }
04145 if( unkeys_queued > 1){
04146 imdone = 1;
04147 break;
04148 }
04149
04150
04151
04152 while(myrpt->unkeytocttimer)
04153 {
04154 int ctint;
04155 if(myrpt->unkeytocttimer > 100)
04156 ctint = 100;
04157 else
04158 ctint = myrpt->unkeytocttimer;
04159 ast_safe_sleep(mychannel, ctint);
04160 rpt_mutex_lock(&myrpt->lock);
04161 if(myrpt->unkeytocttimer < ctint)
04162 myrpt->unkeytocttimer = 0;
04163 else
04164 myrpt->unkeytocttimer -= ctint;
04165 rpt_mutex_unlock(&myrpt->lock);
04166 }
04167
04168
04169
04170
04171
04172 if(myrpt->keyed){
04173 imdone = 1;
04174 break;
04175 }
04176
04177 rpt_mutex_lock(&myrpt->lock);
04178 myrpt->dailykerchunks++;
04179 myrpt->totalkerchunks++;
04180 rpt_mutex_unlock(&myrpt->lock);
04181
04182 haslink = 0;
04183 hastx = 0;
04184 hasremote = 0;
04185 l = myrpt->links.next;
04186 if (l != &myrpt->links)
04187 {
04188 rpt_mutex_lock(&myrpt->lock);
04189 while(l != &myrpt->links)
04190 {
04191 if (l->name[0] == '0')
04192 {
04193 l = l->next;
04194 continue;
04195 }
04196 haslink = 1;
04197 if (l->mode) {
04198 hastx++;
04199 if (l->isremote) hasremote++;
04200 }
04201 l = l->next;
04202 }
04203 rpt_mutex_unlock(&myrpt->lock);
04204 }
04205 if (haslink)
04206 {
04207
04208 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04209 if(res)
04210 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04211
04212
04213
04214 if (myrpt->cmdnode[0])
04215 {
04216 ast_safe_sleep(mychannel,200);
04217 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04218 if(res)
04219 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04220 ast_stopstream(mychannel);
04221 }
04222 }
04223 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04224 ct_copy = ast_strdup(ct);
04225 if(ct_copy)
04226 {
04227 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04228 ast_free(ct_copy);
04229 }
04230 else
04231 res = -1;
04232 if(res)
04233 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04234 }
04235 if (hasremote && (!myrpt->cmdnode[0]))
04236 {
04237
04238 ci.chan = 0;
04239 ci.confno = myrpt->conf;
04240 ci.confmode = DAHDI_CONF_CONFANN;
04241
04242 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04243 {
04244 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04245 rpt_mutex_lock(&myrpt->lock);
04246 myrpt->active_telem = NULL;
04247 remque((struct qelem *)mytele);
04248 rpt_mutex_unlock(&myrpt->lock);
04249 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04250 ast_free(nodename);
04251 ast_free(ident);
04252 ast_free(mytele);
04253 ast_hangup(mychannel);
04254 pthread_exit(NULL);
04255 }
04256 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04257 ast_safe_sleep(mychannel,200);
04258 ct_copy = ast_strdup(ct);
04259 if(ct_copy)
04260 {
04261 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04262 ast_free(ct_copy);
04263 }
04264 else
04265 res = -1;
04266
04267 if(res)
04268 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04269 }
04270 }
04271 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04272 if (myrpt->lastunit)
04273 {
04274 char mystr[10];
04275
04276 ast_safe_sleep(mychannel,200);
04277
04278 ci.chan = 0;
04279 ci.confno = myrpt->txconf;
04280 ci.confmode = DAHDI_CONF_CONFANN;
04281
04282 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04283 {
04284 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04285 rpt_mutex_lock(&myrpt->lock);
04286 myrpt->active_telem = NULL;
04287 remque((struct qelem *)mytele);
04288 rpt_mutex_unlock(&myrpt->lock);
04289 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04290 ast_free(nodename);
04291 ast_free(ident);
04292 ast_free(mytele);
04293 ast_hangup(mychannel);
04294 pthread_exit(NULL);
04295 }
04296 sprintf(mystr,"%04x",myrpt->lastunit);
04297 myrpt->lastunit = 0;
04298 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04299 break;
04300 }
04301 #endif
04302 imdone = 1;
04303 break;
04304 case LINKUNKEY:
04305 if(myrpt->patchnoct && myrpt->callmode){
04306 imdone = 1;
04307 break;
04308 }
04309
04310
04311
04312
04313
04314 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04315 mytele->mylink.linkunkeytocttimer = x;
04316
04317
04318
04319
04320
04321 tlist = myrpt->tele.next;
04322 unkeys_queued = 0;
04323 if (tlist != &myrpt->tele)
04324 {
04325 rpt_mutex_lock(&myrpt->lock);
04326 while(tlist != &myrpt->tele){
04327 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04328 tlist = tlist->next;
04329 }
04330 rpt_mutex_unlock(&myrpt->lock);
04331 }
04332 if( unkeys_queued > 1){
04333 imdone = 1;
04334 break;
04335 }
04336
04337
04338
04339 while(mytele->mylink.linkunkeytocttimer)
04340 {
04341 int ctint;
04342 if(mytele->mylink.linkunkeytocttimer > 100)
04343 ctint = 100;
04344 else
04345 ctint = mytele->mylink.linkunkeytocttimer;
04346 ast_safe_sleep(mychannel, ctint);
04347 rpt_mutex_lock(&myrpt->lock);
04348 if(mytele->mylink.linkunkeytocttimer < ctint)
04349 mytele->mylink.linkunkeytocttimer = 0;
04350 else
04351 mytele->mylink.linkunkeytocttimer -= ctint;
04352 rpt_mutex_unlock(&myrpt->lock);
04353 }
04354
04355 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04356 ct_copy = ast_strdup(ct);
04357 if(ct_copy){
04358 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04359 ast_free(ct_copy);
04360 }
04361 else
04362 res = -1;
04363 if(res)
04364 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04365 }
04366 imdone = 1;
04367 break;
04368 case REMDISC:
04369
04370 wait_interval(myrpt, DLY_TELEM, mychannel);
04371 l = myrpt->links.next;
04372 haslink = 0;
04373
04374 if (l != &myrpt->links)
04375 {
04376 rpt_mutex_lock(&myrpt->lock);
04377 while(l != &myrpt->links)
04378 {
04379 if (l->name[0] == '0')
04380 {
04381 l = l->next;
04382 continue;
04383 }
04384 if (!strcmp(l->name,mytele->mylink.name))
04385 {
04386 haslink = 1;
04387 break;
04388 }
04389 l = l->next;
04390 }
04391 rpt_mutex_unlock(&myrpt->lock);
04392 }
04393 if (haslink)
04394 {
04395 imdone = 1;
04396 break;
04397 }
04398 res = saynode(myrpt,mychannel,mytele->mylink.name);
04399 if (!res)
04400 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04401 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04402 break;
04403 case REMALREADY:
04404
04405 wait_interval(myrpt, DLY_TELEM, mychannel);
04406 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04407 break;
04408 case REMNOTFOUND:
04409
04410 wait_interval(myrpt, DLY_TELEM, mychannel);
04411 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04412 break;
04413 case REMGO:
04414
04415 wait_interval(myrpt, DLY_TELEM, mychannel);
04416 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04417 break;
04418 case CONNECTED:
04419
04420 wait_interval(myrpt, DLY_TELEM, mychannel);
04421 res = saynode(myrpt,mychannel,mytele->mylink.name);
04422 if (!res)
04423 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04424 if (!res)
04425 res = ast_waitstream(mychannel, "");
04426 else
04427 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04428 ast_stopstream(mychannel);
04429 res = ast_streamfile(mychannel, "digits/2", 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 = saynode(myrpt,mychannel,myrpt->name);
04436 imdone = 1;
04437 break;
04438 case CONNFAIL:
04439 res = saynode(myrpt,mychannel,mytele->mylink.name);
04440 if (!res)
04441 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04442 break;
04443 case MEMNOTFOUND:
04444
04445 wait_interval(myrpt, DLY_TELEM, mychannel);
04446 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04447 break;
04448 case PLAYBACK:
04449
04450 wait_interval(myrpt, DLY_TELEM, mychannel);
04451 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04452 break;
04453 case TOPKEY:
04454
04455 wait_interval(myrpt, DLY_TELEM, mychannel);
04456 for(i = 0; i < TOPKEYN; i++)
04457 {
04458 if (!myrpt->topkey[i].node[0]) continue;
04459 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04460 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04461 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04462 "rpt/keyedfor" : "rpt/unkeyedfor");
04463 if (!res) res = saynum(mychannel,
04464 myrpt->topkey[i].timesince);
04465 if (!res) res = sayfile(mychannel,"rpt/seconds");
04466 if (!myrpt->topkeylong) break;
04467 }
04468 imdone = 1;
04469 break;
04470 case SETREMOTE:
04471 ast_mutex_lock(&myrpt->remlock);
04472 res = 0;
04473 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04474 {
04475 res = set_ft897(myrpt);
04476 }
04477 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04478 {
04479 res = set_tm271(myrpt);
04480 }
04481 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04482 {
04483 res = set_ic706(myrpt);
04484 }
04485 #ifdef HAVE_IOPERM
04486 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04487 {
04488 if (ioperm(myrpt->p.iobase,1,1) == -1)
04489 {
04490 rpt_mutex_unlock(&myrpt->lock);
04491 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04492 res = -1;
04493 }
04494 else res = setrbi(myrpt);
04495 }
04496 #endif
04497 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04498 {
04499 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04500 res = setkenwood(myrpt);
04501 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04502 if (ast_safe_sleep(mychannel,200) == -1)
04503 {
04504 ast_mutex_unlock(&myrpt->remlock);
04505 res = -1;
04506 break;
04507 }
04508 if (myrpt->iofd < 0)
04509 {
04510 i = DAHDI_FLUSH_EVENT;
04511 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04512 {
04513 ast_mutex_unlock(&myrpt->remlock);
04514 ast_log(LOG_ERROR,"Cant flush events");
04515 res = -1;
04516 break;
04517 }
04518 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04519 {
04520 ast_mutex_unlock(&myrpt->remlock);
04521 ast_log(LOG_ERROR,"Cant get params");
04522 res = -1;
04523 break;
04524 }
04525 myrpt->remoterx =
04526 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04527 }
04528 }
04529
04530 ast_mutex_unlock(&myrpt->remlock);
04531 if (!res)
04532 {
04533 imdone = 1;
04534 break;
04535 }
04536
04537 case INVFREQ:
04538
04539 wait_interval(myrpt, DLY_TELEM, mychannel);
04540 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04541 break;
04542 case REMMODE:
04543 cp = 0;
04544 wait_interval(myrpt, DLY_TELEM, mychannel);
04545 switch(myrpt->remmode)
04546 {
04547 case REM_MODE_FM:
04548 saycharstr(mychannel,"FM");
04549 break;
04550 case REM_MODE_USB:
04551 saycharstr(mychannel,"USB");
04552 break;
04553 case REM_MODE_LSB:
04554 saycharstr(mychannel,"LSB");
04555 break;
04556 case REM_MODE_AM:
04557 saycharstr(mychannel,"AM");
04558 break;
04559 }
04560 wait_interval(myrpt, DLY_COMP, mychannel);
04561 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04562 break;
04563 case LOGINREQ:
04564 wait_interval(myrpt, DLY_TELEM, mychannel);
04565 sayfile(mychannel,"rpt/login");
04566 saycharstr(mychannel,myrpt->name);
04567 break;
04568 case REMLOGIN:
04569 wait_interval(myrpt, DLY_TELEM, mychannel);
04570 saycharstr(mychannel,myrpt->loginuser);
04571 saynode(myrpt,mychannel,myrpt->name);
04572 wait_interval(myrpt, DLY_COMP, mychannel);
04573 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04574 break;
04575 case REMXXX:
04576 wait_interval(myrpt, DLY_TELEM, mychannel);
04577 res = 0;
04578 switch(mytele->submode)
04579 {
04580 case 100:
04581 sayfile(mychannel, "rpt/rxpl");
04582 sayfile(mychannel, "rpt/off");
04583 break;
04584 case 101:
04585 sayfile(mychannel, "rpt/rxpl");
04586 sayfile(mychannel, "rpt/on");
04587 break;
04588 case 102:
04589 sayfile(mychannel, "rpt/txpl");
04590 sayfile(mychannel, "rpt/off");
04591 break;
04592 case 103:
04593 sayfile(mychannel, "rpt/txpl");
04594 sayfile(mychannel, "rpt/on");
04595 break;
04596 case 104:
04597 sayfile(mychannel, "rpt/lopwr");
04598 break;
04599 case 105:
04600 sayfile(mychannel, "rpt/medpwr");
04601 break;
04602 case 106:
04603 sayfile(mychannel, "rpt/hipwr");
04604 break;
04605 case 113:
04606 sayfile(mychannel,"rpt/down");
04607 sayfile(mychannel, "rpt/slow");
04608 break;
04609 case 114:
04610 sayfile(mychannel,"rpt/down");
04611 sayfile(mychannel, "rpt/quick");
04612 break;
04613 case 115:
04614 sayfile(mychannel,"rpt/down");
04615 sayfile(mychannel, "rpt/fast");
04616 break;
04617 case 116:
04618 sayfile(mychannel,"rpt/up");
04619 sayfile(mychannel, "rpt/slow");
04620 break;
04621 case 117:
04622 sayfile(mychannel,"rpt/up");
04623 sayfile(mychannel, "rpt/quick");
04624 break;
04625 case 118:
04626 sayfile(mychannel,"rpt/up");
04627 sayfile(mychannel, "rpt/fast");
04628 break;
04629 default:
04630 res = -1;
04631 }
04632 wait_interval(myrpt, DLY_COMP, mychannel);
04633 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04634 break;
04635 case SCAN:
04636 ast_mutex_lock(&myrpt->remlock);
04637 if (myrpt->hfscanstop)
04638 {
04639 myrpt->hfscanstatus = 0;
04640 myrpt->hfscanmode = 0;
04641 myrpt->hfscanstop = 0;
04642 mytele->mode = SCANSTAT;
04643 ast_mutex_unlock(&myrpt->remlock);
04644 if (ast_safe_sleep(mychannel,1000) == -1) break;
04645 sayfile(mychannel, "rpt/stop");
04646 imdone = 1;
04647 break;
04648 }
04649 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04650 i = myrpt->hfscanstatus;
04651 myrpt->hfscanstatus = 0;
04652 if (i) mytele->mode = SCANSTAT;
04653 ast_mutex_unlock(&myrpt->remlock);
04654 if (i < 0) sayfile(mychannel, "rpt/stop");
04655 else if (i > 0) saynum(mychannel,i);
04656 imdone = 1;
04657 break;
04658 case TUNE:
04659 ast_mutex_lock(&myrpt->remlock);
04660 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04661 {
04662 set_mode_ic706(myrpt, REM_MODE_AM);
04663 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04664 ast_safe_sleep(mychannel,500);
04665 set_mode_ic706(myrpt, myrpt->remmode);
04666 myrpt->tunerequest = 0;
04667 ast_mutex_unlock(&myrpt->remlock);
04668 imdone = 1;
04669 break;
04670 }
04671 set_mode_ft897(myrpt, REM_MODE_AM);
04672 simple_command_ft897(myrpt, 8);
04673 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04674 simple_command_ft897(myrpt, 0x88);
04675 ast_safe_sleep(mychannel,500);
04676 set_mode_ft897(myrpt, myrpt->remmode);
04677 myrpt->tunerequest = 0;
04678 ast_mutex_unlock(&myrpt->remlock);
04679 imdone = 1;
04680 break;
04681 case REMSHORTSTATUS:
04682 case REMLONGSTATUS:
04683 wait_interval(myrpt, DLY_TELEM, mychannel);
04684 res = saynode(myrpt,mychannel,myrpt->name);
04685 if(!res)
04686 res = sayfile(mychannel,"rpt/frequency");
04687 if(!res)
04688 res = split_freq(mhz, decimals, myrpt->freq);
04689 if (!multimode_capable(myrpt)) decimals[3] = 0;
04690 if(!res){
04691 m = atoi(mhz);
04692 if(m < 100)
04693 res = saynum(mychannel, m);
04694 else
04695 res = saycharstr(mychannel, mhz);
04696 }
04697 if(!res)
04698 res = sayfile(mychannel, "letters/dot");
04699 if(!res)
04700 res = saycharstr(mychannel, decimals);
04701
04702 if(res) break;
04703 if(myrpt->remmode == REM_MODE_FM){
04704 switch(myrpt->offset){
04705
04706 case REM_MINUS:
04707 res = sayfile(mychannel,"rpt/minus");
04708 break;
04709
04710 case REM_SIMPLEX:
04711 res = sayfile(mychannel,"rpt/simplex");
04712 break;
04713
04714 case REM_PLUS:
04715 res = sayfile(mychannel,"rpt/plus");
04716 break;
04717
04718 default:
04719 break;
04720 }
04721 }
04722 else{
04723 switch(myrpt->remmode){
04724
04725 case REM_MODE_USB:
04726 res = saycharstr(mychannel, "USB");
04727 break;
04728
04729 case REM_MODE_LSB:
04730 res = saycharstr(mychannel, "LSB");
04731 break;
04732
04733 case REM_MODE_AM:
04734 res = saycharstr(mychannel, "AM");
04735 break;
04736
04737
04738 default:
04739 break;
04740 }
04741 }
04742
04743 if (res == -1) break;
04744
04745 if(mytele->mode == REMSHORTSTATUS){
04746 wait_interval(myrpt, DLY_COMP, mychannel);
04747 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04748 break;
04749 }
04750
04751 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04752 {
04753 switch(myrpt->powerlevel){
04754
04755 case REM_LOWPWR:
04756 res = sayfile(mychannel,"rpt/lopwr") ;
04757 break;
04758 case REM_MEDPWR:
04759 res = sayfile(mychannel,"rpt/medpwr");
04760 break;
04761 case REM_HIPWR:
04762 res = sayfile(mychannel,"rpt/hipwr");
04763 break;
04764 }
04765 }
04766
04767 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04768 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04769 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04770 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04771 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04772 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04773 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04774 (sayfile(mychannel,"rpt/frequency") == -1) ||
04775 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04776 if(myrpt->remmode == REM_MODE_FM){
04777 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04778 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04779 (sayfile(mychannel,"rpt/txpl") == -1) ||
04780 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04781 {
04782 break;
04783 }
04784 }
04785 wait_interval(myrpt, DLY_COMP, mychannel);
04786 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04787 break;
04788 case STATUS:
04789
04790 wait_interval(myrpt, DLY_TELEM, mychannel);
04791 hastx = 0;
04792 linkbase.next = &linkbase;
04793 linkbase.prev = &linkbase;
04794 rpt_mutex_lock(&myrpt->lock);
04795
04796 l = myrpt->links.next;
04797 while(l != &myrpt->links)
04798 {
04799 if (l->name[0] == '0')
04800 {
04801 l = l->next;
04802 continue;
04803 }
04804 l1 = ast_malloc(sizeof(struct rpt_link));
04805 if (!l1)
04806 {
04807 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04808 remque((struct qelem *)mytele);
04809 myrpt->active_telem = NULL;
04810 rpt_mutex_unlock(&myrpt->lock);
04811 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04812 ast_free(nodename);
04813 ast_free(ident);
04814 ast_free(mytele);
04815 ast_hangup(mychannel);
04816 pthread_exit(NULL);
04817 }
04818 memcpy(l1,l,sizeof(struct rpt_link));
04819 l1->next = l1->prev = NULL;
04820 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04821 l = l->next;
04822 }
04823 rpt_mutex_unlock(&myrpt->lock);
04824 res = saynode(myrpt,mychannel,myrpt->name);
04825 if (myrpt->callmode)
04826 {
04827 hastx = 1;
04828 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04829 if (!res)
04830 res = ast_waitstream(mychannel, "");
04831 else
04832 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04833 ast_stopstream(mychannel);
04834 }
04835 l = linkbase.next;
04836 while(l != &linkbase)
04837 {
04838 char *s;
04839
04840 hastx = 1;
04841 res = saynode(myrpt,mychannel,l->name);
04842 s = "rpt/tranceive";
04843 if (!l->mode) s = "rpt/monitor";
04844 if (!l->thisconnected) s = "rpt/connecting";
04845 res = ast_streamfile(mychannel, s, mychannel->language);
04846 if (!res)
04847 res = ast_waitstream(mychannel, "");
04848 else
04849 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04850 ast_stopstream(mychannel);
04851 l = l->next;
04852 }
04853 if (!hastx)
04854 {
04855 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04856 if (!res)
04857 res = ast_waitstream(mychannel, "");
04858 else
04859 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04860 ast_stopstream(mychannel);
04861 }
04862
04863 l = linkbase.next;
04864 while(l != &linkbase)
04865 {
04866 l1 = l;
04867 l = l->next;
04868 remque((struct qelem *)l1);
04869 ast_free(l1);
04870 }
04871 imdone = 1;
04872 break;
04873 case FULLSTATUS:
04874 rpt_mutex_lock(&myrpt->lock);
04875
04876 __mklinklist(myrpt,NULL,lbuf);
04877 rpt_mutex_unlock(&myrpt->lock);
04878
04879 ns = finddelim(lbuf,strs,MAXLINKLIST);
04880
04881 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04882
04883 wait_interval(myrpt, DLY_TELEM, mychannel);
04884 hastx = 0;
04885 res = saynode(myrpt,mychannel,myrpt->name);
04886 if (myrpt->callmode)
04887 {
04888 hastx = 1;
04889 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04890 if (!res)
04891 res = ast_waitstream(mychannel, "");
04892 else
04893 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04894 ast_stopstream(mychannel);
04895 }
04896
04897 for(i = 0; i < ns; i++)
04898 {
04899 char *s,mode = 'T';
04900
04901
04902 if ((*strs[i] < '0') || (*strs[i] > '9'))
04903 {
04904 mode = *strs[i];
04905 strs[i]++;
04906 }
04907
04908 hastx = 1;
04909 res = saynode(myrpt,mychannel,strs[i]);
04910 s = "rpt/tranceive";
04911 if (mode == 'R') s = "rpt/monitor";
04912 if (mode == 'C') s = "rpt/connecting";
04913 res = ast_streamfile(mychannel, s, mychannel->language);
04914 if (!res)
04915 res = ast_waitstream(mychannel, "");
04916 else
04917 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04918 ast_stopstream(mychannel);
04919 }
04920 if (!hastx)
04921 {
04922 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04923 if (!res)
04924 res = ast_waitstream(mychannel, "");
04925 else
04926 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04927 ast_stopstream(mychannel);
04928 }
04929 imdone = 1;
04930 break;
04931
04932 case LASTNODEKEY:
04933 rpt_mutex_lock(&myrpt->lock);
04934 if(myrpt->lastnodewhichkeyedusup){
04935 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04936 if(!p){
04937 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04938 imdone = 1;
04939 break;
04940 }
04941 }
04942 else
04943 p = NULL;
04944 rpt_mutex_unlock(&myrpt->lock);
04945 if(!p){
04946 imdone = 1;
04947 break;
04948 }
04949 wait_interval(myrpt, DLY_TELEM, mychannel);
04950 res = saynode(myrpt,mychannel,p);
04951 ast_free(p);
04952 imdone = 1;
04953 break;
04954
04955 case UNAUTHTX:
04956 wait_interval(myrpt, DLY_TELEM, mychannel);
04957 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04958 if (!res)
04959 res = ast_waitstream(mychannel, "");
04960 else
04961 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04962 ast_stopstream(mychannel);
04963 imdone = 1;
04964 break;
04965
04966 case PARROT:
04967
04968 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04969 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04970 {
04971 imdone = 1;
04972 myrpt->parrotstate = 0;
04973 break;
04974 }
04975 wait_interval(myrpt, DLY_PARROT, mychannel);
04976 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04977 res = ast_streamfile(mychannel, mystr, mychannel->language);
04978 if (!res)
04979 res = ast_waitstream(mychannel, "");
04980 else
04981 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04982 ast_stopstream(mychannel);
04983 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04984 strcat(mystr,".wav");
04985 unlink(mystr);
04986 imdone = 1;
04987 myrpt->parrotstate = 0;
04988 break;
04989
04990 case TIMEOUT:
04991 res = saynode(myrpt,mychannel,myrpt->name);
04992 if (!res)
04993 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
04994 break;
04995
04996 case TIMEOUT_WARNING:
04997 time(&t);
04998 res = saynode(myrpt,mychannel,myrpt->name);
04999 if (!res)
05000 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05001 if (!res)
05002 res = ast_waitstream(mychannel, "");
05003 else
05004 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05005 ast_stopstream(mychannel);
05006 if(!res)
05007 ast_say_number(mychannel, myrpt->p.remotetimeout -
05008 (t - myrpt->last_activity_time),
05009 "", mychannel->language, (char *) NULL);
05010 if (!res)
05011 res = ast_waitstream(mychannel, "");
05012 ast_stopstream(mychannel);
05013 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05014 break;
05015
05016 case ACT_TIMEOUT_WARNING:
05017 time(&t);
05018 res = saynode(myrpt,mychannel,myrpt->name);
05019 if (!res)
05020 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05021 if (!res)
05022 res = ast_waitstream(mychannel, "");
05023 else
05024 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05025 ast_stopstream(mychannel);
05026 if(!res)
05027 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05028 (t - myrpt->last_activity_time),
05029 "", mychannel->language, (char *) NULL);
05030 if (!res)
05031 res = ast_waitstream(mychannel, "");
05032 ast_stopstream(mychannel);
05033 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05034 break;
05035
05036 case STATS_TIME:
05037 case STATS_TIME_LOCAL:
05038 wait_interval(myrpt, DLY_TELEM, mychannel);
05039 t = time(NULL);
05040 rpt_localtime(&t, &localtm);
05041
05042 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05043 p = "rpt/goodmorning";
05044 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05045 p = "rpt/goodafternoon";
05046 else
05047 p = "rpt/goodevening";
05048 if (sayfile(mychannel,p) == -1)
05049 {
05050 imdone = 1;
05051 break;
05052 }
05053
05054 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05055 {
05056 imdone = 1;
05057 break;
05058 }
05059
05060 res = ast_say_time(mychannel, t, "", mychannel->language);
05061 if (!res)
05062 res = ast_waitstream(mychannel, "");
05063 ast_stopstream(mychannel);
05064 imdone = 1;
05065 break;
05066 case STATS_VERSION:
05067 p = strstr(tdesc, "version");
05068 if(!p)
05069 break;
05070 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05071 break;
05072 wait_interval(myrpt, DLY_TELEM, mychannel);
05073
05074 if (sayfile(mychannel,"rpt/version") == -1)
05075 {
05076 imdone = 1;
05077 break;
05078 }
05079 if(!res)
05080 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05081 if (!res)
05082 res = ast_waitstream(mychannel, "");
05083 ast_stopstream(mychannel);
05084 if (saycharstr(mychannel,".") == -1)
05085 {
05086 imdone = 1;
05087 break;
05088 }
05089 if(!res)
05090 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05091 if (!res){
05092 res = ast_waitstream(mychannel, "");
05093 ast_stopstream(mychannel);
05094 }
05095 else
05096 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05097 imdone = 1;
05098 break;
05099 case ARB_ALPHA:
05100 wait_interval(myrpt, DLY_TELEM, mychannel);
05101 if(mytele->param)
05102 saycharstr(mychannel, mytele->param);
05103 imdone = 1;
05104 break;
05105 case REV_PATCH:
05106 wait_interval(myrpt, DLY_TELEM, mychannel);
05107 if(mytele->param) {
05108
05109
05110 char *tpl_working, *tpl_current;
05111 char *tmp[100], *myparm;
05112 int looptemp=0,idx=0, dres = 0;
05113
05114
05115 tpl_working = ast_strdup(mytele->param);
05116 myparm = strsep(&tpl_working,",");
05117 tpl_current=strsep(&tpl_working, ":");
05118
05119 while(tpl_current && looptemp < sizeof(tmp)) {
05120 tmp[looptemp]=tpl_current;
05121 looptemp++;
05122 tpl_current=strsep(&tpl_working,":");
05123 }
05124
05125 for(idx=0; idx<looptemp; idx++) {
05126 if(!strcmp(tmp[idx], "PARKED")) {
05127 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05128 } else if(!strcmp(tmp[idx], "NODE")) {
05129 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05130 } else {
05131 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05132 if(!dres) {
05133 dres = ast_waitstream(mychannel, "");
05134 } else {
05135 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05136 dres = 0;
05137 }
05138 }
05139 }
05140 ast_free(tpl_working);
05141 }
05142 imdone = 1;
05143 break;
05144 case TEST_TONE:
05145 imdone = 1;
05146 if (myrpt->stopgen) break;
05147 myrpt->stopgen = -1;
05148 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05149 {
05150 myrpt->stopgen = 0;
05151 break;
05152 }
05153 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05154 if (ast_safe_sleep(mychannel,1)) break;
05155 imdone = 1;
05156 }
05157 myrpt->stopgen = 0;
05158 break;
05159 default:
05160 break;
05161 }
05162 if (!imdone)
05163 {
05164 if (!res)
05165 res = ast_waitstream(mychannel, "");
05166 else {
05167 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05168 res = 0;
05169 }
05170 }
05171 ast_stopstream(mychannel);
05172 rpt_mutex_lock(&myrpt->lock);
05173 if (mytele->mode == TAILMSG)
05174 {
05175 if (!res)
05176 {
05177 myrpt->tailmessagen++;
05178 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05179 }
05180 else
05181 {
05182 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05183 }
05184 }
05185 remque((struct qelem *)mytele);
05186 myrpt->active_telem = NULL;
05187 rpt_mutex_unlock(&myrpt->lock);
05188 ast_free(nodename);
05189 ast_free(ident);
05190 ast_free(mytele);
05191 ast_hangup(mychannel);
05192 #ifdef APP_RPT_LOCK_DEBUG
05193 {
05194 struct lockthread *t;
05195
05196 sleep(5);
05197 ast_mutex_lock(&locklock);
05198 t = get_lockthread(pthread_self());
05199 if (t) memset(t,0,sizeof(struct lockthread));
05200 ast_mutex_unlock(&locklock);
05201 }
05202 #endif
05203 pthread_exit(NULL);
05204 }
05205
05206 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05207 {
05208 struct rpt_tele *tele;
05209 struct rpt_link *mylink = NULL;
05210 int res;
05211 pthread_attr_t attr;
05212 char *v1, *v2;
05213
05214 if(debug > 6)
05215 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05216
05217 switch(mode)
05218 {
05219 case UNKEY:
05220
05221
05222 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05223 "unlinkedct");
05224 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05225 "remotect");
05226 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05227 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05228 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05229 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05230 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05231 break;
05232 case LINKUNKEY:
05233 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05234 return;
05235 break;
05236 default:
05237 break;
05238 }
05239 tele = ast_malloc(sizeof(struct rpt_tele));
05240 if (!tele)
05241 {
05242 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05243 pthread_exit(NULL);
05244 return;
05245 }
05246
05247 memset((char *)tele,0,sizeof(struct rpt_tele));
05248 tele->rpt = myrpt;
05249 tele->mode = mode;
05250 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05251 else mylink = (struct rpt_link *) data;
05252 rpt_mutex_lock(&myrpt->lock);
05253 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05254 (mode == LINKUNKEY)){
05255 memset(&tele->mylink,0,sizeof(struct rpt_link));
05256 if (mylink){
05257 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05258 }
05259 }
05260 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05261 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05262 tele->param[TELEPARAMSIZE - 1] = 0;
05263 }
05264 if (mode == REMXXX) tele->submode = (intptr_t) data;
05265 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05266 rpt_mutex_unlock(&myrpt->lock);
05267 pthread_attr_init(&attr);
05268 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05269 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05270 if(res < 0){
05271 rpt_mutex_lock(&myrpt->lock);
05272 remque((struct qlem *) tele);
05273 rpt_mutex_unlock(&myrpt->lock);
05274 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05275 }
05276 return;
05277 }
05278
05279 static void *rpt_call(void *this)
05280 {
05281 struct dahdi_confinfo ci;
05282 struct rpt *myrpt = (struct rpt *)this;
05283 int res;
05284 int stopped,congstarted,dialtimer,lastcidx,aborted;
05285 struct ast_channel *mychannel,*genchannel;
05286
05287 myrpt->mydtmf = 0;
05288
05289 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05290 if (!mychannel)
05291 {
05292 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05293 pthread_exit(NULL);
05294 }
05295 #ifdef AST_CDR_FLAG_POST_DISABLED
05296 if (mychannel->cdr)
05297 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05298 #endif
05299 ci.chan = 0;
05300 ci.confno = myrpt->conf;
05301 #if 0
05302 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05303 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05304 #endif
05305 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05306
05307 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05308 {
05309 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05310 ast_hangup(mychannel);
05311 myrpt->callmode = 0;
05312 pthread_exit(NULL);
05313 }
05314
05315 genchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05316 if (!genchannel)
05317 {
05318 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05319 ast_hangup(mychannel);
05320 pthread_exit(NULL);
05321 }
05322 #ifdef AST_CDR_FLAG_POST_DISABLED
05323 if (genchannel->cdr)
05324 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05325 #endif
05326 ci.chan = 0;
05327 ci.confno = myrpt->conf;
05328 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05329 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05330
05331 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05332 {
05333 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05334 ast_hangup(mychannel);
05335 ast_hangup(genchannel);
05336 myrpt->callmode = 0;
05337 pthread_exit(NULL);
05338 }
05339 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05340 {
05341 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
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(genchannel->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
05356 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05357 {
05358 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05359 ast_hangup(mychannel);
05360 ast_hangup(genchannel);
05361 myrpt->callmode = 0;
05362 pthread_exit(NULL);
05363 }
05364 stopped = 0;
05365 congstarted = 0;
05366 dialtimer = 0;
05367 lastcidx = 0;
05368 myrpt->calldigittimer = 0;
05369 aborted = 0;
05370
05371 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05372 {
05373 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05374 dialtimer = 0;
05375 lastcidx = myrpt->cidx;
05376 }
05377
05378 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05379 if(debug)
05380 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05381 rpt_mutex_lock(&myrpt->lock);
05382 aborted = 1;
05383 myrpt->callmode = 0;
05384 rpt_mutex_unlock(&myrpt->lock);
05385 break;
05386 }
05387
05388 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05389 {
05390 stopped = 1;
05391
05392 tone_zone_play_tone(genchannel->fds[0],-1);
05393 }
05394 if (myrpt->callmode == 1)
05395 {
05396 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05397 {
05398 myrpt->callmode = 2;
05399 break;
05400 }
05401
05402 if (myrpt->calldigittimer)
05403 myrpt->calldigittimer += MSWAIT;
05404 }
05405 if (myrpt->callmode == 4)
05406 {
05407 if(!congstarted){
05408 congstarted = 1;
05409
05410 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05411 }
05412 }
05413 res = ast_safe_sleep(mychannel, MSWAIT);
05414 if (res < 0)
05415 {
05416 if(debug)
05417 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05418 ast_hangup(mychannel);
05419 ast_hangup(genchannel);
05420 rpt_mutex_lock(&myrpt->lock);
05421 myrpt->callmode = 0;
05422 rpt_mutex_unlock(&myrpt->lock);
05423 pthread_exit(NULL);
05424 }
05425 dialtimer += MSWAIT;
05426 }
05427
05428 tone_zone_play_tone(genchannel->fds[0],-1);
05429
05430 if (!myrpt->callmode)
05431 {
05432 if(debug)
05433 ast_log(LOG_NOTICE, "callmode==0\n");
05434 ast_hangup(mychannel);
05435 ast_hangup(genchannel);
05436 rpt_mutex_lock(&myrpt->lock);
05437 myrpt->callmode = 0;
05438 myrpt->macropatch=0;
05439 channel_revert(myrpt);
05440 rpt_mutex_unlock(&myrpt->lock);
05441 if((!myrpt->patchquiet) && aborted)
05442 rpt_telemetry(myrpt, TERM, NULL);
05443 pthread_exit(NULL);
05444 }
05445
05446 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05447 char *name, *loc, *instr;
05448 instr = ast_strdup(myrpt->p.ourcallerid);
05449 if(instr){
05450 ast_callerid_parse(instr, &name, &loc);
05451 if(loc){
05452 if(mychannel->cid.cid_num)
05453 ast_free(mychannel->cid.cid_num);
05454 mychannel->cid.cid_num = ast_strdup(loc);
05455 }
05456 if(name){
05457 if(mychannel->cid.cid_name)
05458 ast_free(mychannel->cid.cid_name);
05459 mychannel->cid.cid_name = ast_strdup(name);
05460 }
05461 ast_free(instr);
05462 }
05463 }
05464
05465 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05466 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05467
05468 if (myrpt->p.acctcode)
05469 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05470 mychannel->priority = 1;
05471 ast_channel_undefer_dtmf(mychannel);
05472 if (ast_pbx_start(mychannel) < 0)
05473 {
05474 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05475 ast_hangup(mychannel);
05476 ast_hangup(genchannel);
05477 rpt_mutex_lock(&myrpt->lock);
05478 myrpt->callmode = 0;
05479 rpt_mutex_unlock(&myrpt->lock);
05480 pthread_exit(NULL);
05481 }
05482 usleep(10000);
05483 rpt_mutex_lock(&myrpt->lock);
05484 myrpt->callmode = 3;
05485
05486 ci.chan = 0;
05487 ci.confno = myrpt->conf;
05488 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05489 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05490
05491 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05492 {
05493 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05494 ast_hangup(mychannel);
05495 ast_hangup(genchannel);
05496 myrpt->callmode = 0;
05497 pthread_exit(NULL);
05498 }
05499
05500 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05501 {
05502 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05503 ast_hangup(mychannel);
05504 myrpt->callmode = 0;
05505 pthread_exit(NULL);
05506 }
05507 ci.chan = 0;
05508 ci.confno = res;
05509 ci.confmode = DAHDI_CONF_MONITOR;
05510
05511 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05512 {
05513 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05514 ast_hangup(mychannel);
05515 myrpt->callmode = 0;
05516 pthread_exit(NULL);
05517 }
05518 while(myrpt->callmode)
05519 {
05520 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05521 {
05522
05523 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05524 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05525 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05526 myrpt->callmode = 0;
05527 myrpt->macropatch=0;
05528 if(!myrpt->patchquiet){
05529 rpt_mutex_unlock(&myrpt->lock);
05530 rpt_telemetry(myrpt, TERM, NULL);
05531 rpt_mutex_lock(&myrpt->lock);
05532 }
05533 }
05534 else{
05535 myrpt->callmode = 4;
05536 rpt_mutex_unlock(&myrpt->lock);
05537
05538 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05539 rpt_mutex_lock(&myrpt->lock);
05540 }
05541 }
05542 if (myrpt->mydtmf)
05543 {
05544 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05545 wf.subclass = myrpt->mydtmf;
05546 rpt_mutex_unlock(&myrpt->lock);
05547 ast_queue_frame(mychannel,&wf);
05548 #ifdef NEW_ASTERISK
05549 ast_senddigit(genchannel,myrpt->mydtmf,0);
05550 #else
05551 ast_senddigit(genchannel,myrpt->mydtmf);
05552 #endif
05553 rpt_mutex_lock(&myrpt->lock);
05554 myrpt->mydtmf = 0;
05555 }
05556 rpt_mutex_unlock(&myrpt->lock);
05557 usleep(MSWAIT * 1000);
05558 rpt_mutex_lock(&myrpt->lock);
05559 }
05560 if(debug)
05561 ast_log(LOG_NOTICE, "exit channel loop\n");
05562 rpt_mutex_unlock(&myrpt->lock);
05563 tone_zone_play_tone(genchannel->fds[0],-1);
05564 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05565 ast_hangup(genchannel);
05566 rpt_mutex_lock(&myrpt->lock);
05567 myrpt->callmode = 0;
05568 myrpt->macropatch=0;
05569 channel_revert(myrpt);
05570 rpt_mutex_unlock(&myrpt->lock);
05571
05572 ci.chan = 0;
05573 ci.confno = myrpt->conf;
05574 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05575 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05576
05577 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05578 {
05579 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05580 }
05581 pthread_exit(NULL);
05582 }
05583
05584 static void send_link_dtmf(struct rpt *myrpt,char c)
05585 {
05586 char str[300];
05587 struct ast_frame wf;
05588 struct rpt_link *l;
05589
05590 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05591 wf.frametype = AST_FRAME_TEXT;
05592 wf.subclass = 0;
05593 wf.offset = 0;
05594 wf.mallocd = 0;
05595 wf.datalen = strlen(str) + 1;
05596 wf.samples = 0;
05597 l = myrpt->links.next;
05598
05599 while(l != &myrpt->links)
05600 {
05601 if (l->name[0] == '0')
05602 {
05603 l = l->next;
05604 continue;
05605 }
05606
05607 if (!strcmp(l->name,myrpt->cmdnode))
05608 {
05609 wf.data.ptr = str;
05610 if (l->chan) ast_write(l->chan,&wf);
05611 return;
05612 }
05613 l = l->next;
05614 }
05615 l = myrpt->links.next;
05616
05617 while(l != &myrpt->links)
05618 {
05619 wf.data.ptr = str;
05620 if (l->chan) ast_write(l->chan,&wf);
05621 l = l->next;
05622 }
05623 return;
05624 }
05625
05626 static void send_link_keyquery(struct rpt *myrpt)
05627 {
05628 char str[300];
05629 struct ast_frame wf;
05630 struct rpt_link *l;
05631
05632 rpt_mutex_lock(&myrpt->lock);
05633 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05634 myrpt->topkeystate = 1;
05635 time(&myrpt->topkeytime);
05636 rpt_mutex_unlock(&myrpt->lock);
05637 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05638 wf.frametype = AST_FRAME_TEXT;
05639 wf.subclass = 0;
05640 wf.offset = 0;
05641 wf.mallocd = 0;
05642 wf.datalen = strlen(str) + 1;
05643 wf.samples = 0;
05644 l = myrpt->links.next;
05645
05646 while(l != &myrpt->links)
05647 {
05648 wf.data.ptr = str;
05649 if (l->chan) ast_write(l->chan,&wf);
05650 l = l->next;
05651 }
05652 return;
05653 }
05654
05655
05656
05657 static void send_newkey(struct ast_channel *chan)
05658 {
05659
05660
05661 ast_sendtext(chan,newkeystr);
05662 return;
05663 }
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05678 {
05679 char *val, *s, *s1, *s2, *tele;
05680 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05681 char tmp[300], deststr[300] = "",modechange = 0;
05682 char sx[320],*sy;
05683 struct rpt_link *l;
05684 int reconnects = 0;
05685 int i,n;
05686 struct dahdi_confinfo ci;
05687
05688 val = node_lookup(myrpt,node);
05689 if (!val){
05690 if(strlen(node) >= myrpt->longestnode)
05691 return -1;
05692 return 1;
05693 }
05694
05695 if(!strcmp(myrpt->name,node))
05696 return -2;
05697
05698 if(debug > 3){
05699 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05700 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05701 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05702 }
05703
05704 strncpy(tmp,val,sizeof(tmp) - 1);
05705 s = tmp;
05706 s1 = strsep(&s,",");
05707 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05708 {
05709 sy = strchr(s1,'/');
05710 *sy = 0;
05711 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05712 s1 = sx;
05713 }
05714 s2 = strsep(&s,",");
05715 rpt_mutex_lock(&myrpt->lock);
05716 l = myrpt->links.next;
05717
05718 while(l != &myrpt->links){
05719 if (l->name[0] == '0')
05720 {
05721 l = l->next;
05722 continue;
05723 }
05724
05725 if (!strcmp(l->name, node))
05726 break;
05727 l = l->next;
05728 }
05729
05730 if (l != &myrpt->links){
05731
05732 if ((l->mode) || (!l->chan)) {
05733 rpt_mutex_unlock(&myrpt->lock);
05734 return 2;
05735 }
05736 reconnects = l->reconnects;
05737 rpt_mutex_unlock(&myrpt->lock);
05738 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05739 l->retries = l->max_retries + 1;
05740 l->disced = 2;
05741 modechange = 1;
05742 } else
05743 {
05744 __mklinklist(myrpt,NULL,lstr);
05745 rpt_mutex_unlock(&myrpt->lock);
05746 n = finddelim(lstr,strs,MAXLINKLIST);
05747 for(i = 0; i < n; i++)
05748 {
05749 if ((*strs[i] < '0') ||
05750 (*strs[i] > '9')) strs[i]++;
05751 if (!strcmp(strs[i],node))
05752 {
05753 return 2;
05754 }
05755 }
05756 }
05757 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05758
05759 l = ast_malloc(sizeof(struct rpt_link));
05760 if (!l)
05761 {
05762 ast_log(LOG_WARNING, "Unable to malloc\n");
05763 return -1;
05764 }
05765
05766 memset((char *)l,0,sizeof(struct rpt_link));
05767 l->mode = mode;
05768 l->outbound = 1;
05769 l->thisconnected = 0;
05770 voxinit_link(l,1);
05771 strncpy(l->name, node, MAXNODESTR - 1);
05772 l->isremote = (s && ast_true(s));
05773 if (modechange) l->connected = 1;
05774 l->hasconnected = l->perma = perma;
05775 #ifdef ALLOW_LOCAL_CHANNELS
05776 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05777 strncpy(deststr, s1, sizeof(deststr));
05778 else
05779 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05780 #else
05781 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05782 #endif
05783 tele = strchr(deststr, '/');
05784 if (!tele){
05785 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05786 ast_free(l);
05787 return -1;
05788 }
05789 *tele++ = 0;
05790 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
05791 if (l->chan){
05792 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05793 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05794 #ifdef AST_CDR_FLAG_POST_DISABLED
05795 if (l->chan->cdr)
05796 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05797 #endif
05798 #ifndef NEW_ASTERISK
05799 l->chan->whentohangup = 0;
05800 #endif
05801 l->chan->appl = "Apprpt";
05802 l->chan->data = "(Remote Rx)";
05803 if (debug > 3)
05804 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05805 deststr, tele, l->chan->name);
05806 if(l->chan->cid.cid_num)
05807 ast_free(l->chan->cid.cid_num);
05808 l->chan->cid.cid_num = ast_strdup(myrpt->name);
05809 ast_call(l->chan,tele,999);
05810 }
05811 else {
05812 if(debug > 3)
05813 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05814 deststr,tele,l->chan->name);
05815 if (myrpt->p.archivedir)
05816 {
05817 char str[100];
05818 sprintf(str,"LINKFAIL,%s",l->name);
05819 donodelog(myrpt,str);
05820 }
05821 ast_free(l);
05822 return -1;
05823 }
05824
05825 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05826 if (!l->pchan){
05827 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05828 ast_hangup(l->chan);
05829 ast_free(l);
05830 return -1;
05831 }
05832 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05833 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05834 #ifdef AST_CDR_FLAG_POST_DISABLED
05835 if (l->pchan->cdr)
05836 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05837 #endif
05838
05839 ci.chan = 0;
05840 ci.confno = myrpt->conf;
05841 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05842
05843 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05844 {
05845 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05846 ast_hangup(l->chan);
05847 ast_hangup(l->pchan);
05848 ast_free(l);
05849 return -1;
05850 }
05851 rpt_mutex_lock(&myrpt->lock);
05852 l->reconnects = reconnects;
05853
05854 l->max_retries = MAX_RETRIES;
05855 if (perma)
05856 l->max_retries = MAX_RETRIES_PERM;
05857 if (l->isremote) l->retries = l->max_retries + 1;
05858 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05859 __kickshort(myrpt);
05860 rpt_mutex_unlock(&myrpt->lock);
05861 if (!l->phonemode) send_newkey(l->chan);
05862 return 0;
05863 }
05864
05865
05866
05867
05868
05869
05870
05871 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05872 {
05873
05874 char *val, *s, *s1, *s2;
05875 char tmp[300];
05876 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05877 char mode,perma;
05878 char sx[320],*sy;
05879 struct rpt_link *l;
05880 int i,r;
05881
05882 if(!param)
05883 return DC_ERROR;
05884
05885
05886 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05887 return DC_ERROR;
05888
05889 strncpy(digitbuf,digits,MAXNODESTR - 1);
05890
05891 if(debug > 6)
05892 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05893
05894 switch(myatoi(param)){
05895 case 11:
05896 case 1:
05897 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05898 strcpy(digitbuf,myrpt->lastlinknode);
05899 val = node_lookup(myrpt,digitbuf);
05900 if (!val){
05901 if(strlen(digitbuf) >= myrpt->longestnode)
05902 return DC_ERROR;
05903 break;
05904 }
05905 strncpy(tmp,val,sizeof(tmp) - 1);
05906 s = tmp;
05907 s1 = strsep(&s,",");
05908 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05909 {
05910 sy = strchr(s1,'/');
05911 *sy = 0;
05912 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05913 s1 = sx;
05914 }
05915 s2 = strsep(&s,",");
05916 rpt_mutex_lock(&myrpt->lock);
05917 l = myrpt->links.next;
05918
05919 while(l != &myrpt->links){
05920 if (l->name[0] == '0')
05921 {
05922 l = l->next;
05923 continue;
05924 }
05925
05926 if (!strcmp(l->name, digitbuf))
05927 break;
05928 l = l->next;
05929 }
05930 if (l != &myrpt->links){
05931 struct ast_frame wf;
05932
05933
05934 if ((myatoi(param) < 10) &&
05935 (l->max_retries > MAX_RETRIES))
05936 {
05937 rpt_mutex_unlock(&myrpt->lock);
05938 return DC_COMPLETE;
05939 }
05940 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05941 l->retries = l->max_retries + 1;
05942 l->disced = 1;
05943 rpt_mutex_unlock(&myrpt->lock);
05944 wf.frametype = AST_FRAME_TEXT;
05945 wf.subclass = 0;
05946 wf.offset = 0;
05947 wf.mallocd = 0;
05948 wf.datalen = strlen(discstr) + 1;
05949 wf.samples = 0;
05950 wf.data.ptr = discstr;
05951 if (l->chan)
05952 {
05953 ast_write(l->chan,&wf);
05954 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05955 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05956 }
05957 rpt_telemetry(myrpt, COMPLETE, NULL);
05958 return DC_COMPLETE;
05959 }
05960 rpt_mutex_unlock(&myrpt->lock);
05961 return DC_COMPLETE;
05962 case 2:
05963 case 3:
05964 case 12:
05965 case 13:
05966 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05967 strcpy(digitbuf,myrpt->lastlinknode);
05968
05969 perma = (atoi(param) > 10) ? 1 : 0;
05970 mode = (atoi(param) & 1) ? 1 : 0;
05971 r = connect_link(myrpt, digitbuf, mode, perma);
05972 switch(r){
05973 case -2:
05974 return DC_COMPLETE;
05975
05976 case 0:
05977 rpt_telemetry(myrpt, COMPLETE, NULL);
05978 return DC_COMPLETE;
05979
05980 case 1:
05981 break;
05982
05983 case 2:
05984 rpt_telemetry(myrpt, REMALREADY, NULL);
05985 return DC_COMPLETE;
05986
05987 default:
05988 rpt_telemetry(myrpt, CONNFAIL, NULL);
05989 return DC_COMPLETE;
05990 }
05991 break;
05992
05993 case 4:
05994
05995
05996 if (((command_source != SOURCE_RPT) &&
05997 (command_source != SOURCE_PHONE) &&
05998 (command_source != SOURCE_ALT) &&
05999 (command_source != SOURCE_DPHONE)) ||
06000 (myrpt->links.next == &myrpt->links))
06001 return DC_COMPLETE;
06002
06003
06004 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06005
06006 rpt_telemetry(myrpt, REMALREADY, NULL);
06007 return DC_COMPLETE;
06008 }
06009 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06010 strcpy(digitbuf,myrpt->lastlinknode);
06011
06012 val = node_lookup(myrpt,digitbuf);
06013 if (!val){
06014 if(strlen(digitbuf) >= myrpt->longestnode)
06015 return DC_ERROR;
06016 break;
06017
06018 }
06019 rpt_mutex_lock(&myrpt->lock);
06020 strcpy(myrpt->lastlinknode,digitbuf);
06021 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06022 rpt_mutex_unlock(&myrpt->lock);
06023 rpt_telemetry(myrpt, REMGO, NULL);
06024 return DC_COMPLETE;
06025
06026 case 5:
06027 rpt_telemetry(myrpt, STATUS, NULL);
06028 return DC_COMPLETE;
06029
06030 case 15:
06031 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06032 return DC_COMPLETE;
06033
06034
06035 case 6:
06036 rpt_mutex_lock(&myrpt->lock);
06037 myrpt->savednodes[0] = 0;
06038 l = myrpt->links.next;
06039
06040 while(l != &myrpt->links){
06041 struct ast_frame wf;
06042 if (l->name[0] == '0')
06043 {
06044 l = l->next;
06045 continue;
06046 }
06047
06048 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06049 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06050 if(myrpt->savednodes[0])
06051 strcat(myrpt->savednodes, ",");
06052 strcat(myrpt->savednodes, tmp);
06053 }
06054 l->retries = l->max_retries + 1;
06055 l->disced = 2;
06056 rpt_mutex_unlock(&myrpt->lock);
06057
06058
06059 wf.frametype = AST_FRAME_TEXT;
06060 wf.subclass = 0;
06061 wf.offset = 0;
06062 wf.mallocd = 0;
06063 wf.datalen = strlen(discstr) + 1;
06064 wf.samples = 0;
06065 wf.data.ptr = discstr;
06066 if (l->chan)
06067 {
06068 ast_write(l->chan,&wf);
06069 ast_safe_sleep(l->chan,250);
06070 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06071 }
06072 rpt_mutex_lock(&myrpt->lock);
06073 l = l->next;
06074 }
06075 rpt_mutex_unlock(&myrpt->lock);
06076 if(debug > 3)
06077 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06078 rpt_telemetry(myrpt, COMPLETE, NULL);
06079 return DC_COMPLETE;
06080
06081 case 7:
06082 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06083 break;
06084
06085
06086 #ifdef _MDC_DECODE_H_
06087 case 8:
06088 myrpt->lastunit = 0xd00d;
06089 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06090 mdc1200_send(myrpt,myrpt->lastunit);
06091 break;
06092 #endif
06093
06094 case 16:
06095 strcpy(tmp, myrpt->savednodes);
06096 finddelim(tmp, strs, MAXLINKLIST);
06097 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06098 s1 = strs[i];
06099 mode = (s1[0] == 'X') ? 1 : 0;
06100 perma = (s1[1] == 'P') ? 1 : 0;
06101 connect_link(myrpt, s1 + 2, mode, perma);
06102 }
06103 rpt_telemetry(myrpt, COMPLETE, NULL);
06104 break;
06105
06106 case 200:
06107 case 201:
06108 case 202:
06109 case 203:
06110 case 204:
06111 case 205:
06112 case 206:
06113 case 207:
06114 case 208:
06115 case 209:
06116 case 210:
06117 case 211:
06118 case 212:
06119 case 213:
06120 case 214:
06121 case 215:
06122 if (((myrpt->p.propagate_dtmf) &&
06123 (command_source == SOURCE_LNK)) ||
06124 ((myrpt->p.propagate_phonedtmf) &&
06125 ((command_source == SOURCE_PHONE) ||
06126 (command_source == SOURCE_ALT) ||
06127 (command_source == SOURCE_DPHONE))))
06128 do_dtmf_local(myrpt,
06129 remdtmfstr[myatoi(param) - 200]);
06130 default:
06131 return DC_ERROR;
06132
06133 }
06134
06135 return DC_INDETERMINATE;
06136 }
06137
06138
06139
06140
06141
06142 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06143 {
06144 pthread_attr_t attr;
06145 int i, idx, paramlength;
06146 char *lparam;
06147 char *value = NULL;
06148 char *paramlist[20];
06149
06150 static char *keywords[] = {
06151 "context",
06152 "dialtime",
06153 "farenddisconnect",
06154 "noct",
06155 "quiet",
06156 NULL
06157 };
06158
06159 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06160 return DC_ERROR;
06161
06162 if(debug)
06163 printf("@@@@ Autopatch up\n");
06164
06165 if(!myrpt->callmode){
06166
06167 myrpt->patchnoct = 0;
06168 myrpt->patchdialtime = 0;
06169 myrpt->patchfarenddisconnect = 0;
06170 myrpt->patchquiet = 0;
06171 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06172
06173 if(param){
06174
06175 lparam = ast_strdup(param);
06176 if(!lparam){
06177 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06178 return DC_ERROR;
06179 }
06180 paramlength = finddelim(lparam, paramlist, 20);
06181 for(i = 0; i < paramlength; i++){
06182 idx = matchkeyword(paramlist[i], &value, keywords);
06183 if(value)
06184 value = skipchars(value, "= ");
06185 switch(idx){
06186
06187 case 1:
06188 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06189 break;
06190
06191 case 2:
06192 myrpt->patchdialtime = atoi(value);
06193 break;
06194
06195 case 3:
06196 myrpt->patchfarenddisconnect = atoi(value);
06197 break;
06198
06199 case 4:
06200 myrpt->patchnoct = atoi(value);
06201 break;
06202
06203 case 5:
06204 myrpt->patchquiet = atoi(value);
06205 break;
06206
06207 default:
06208 break;
06209 }
06210 }
06211 ast_free(lparam);
06212 }
06213 }
06214
06215 rpt_mutex_lock(&myrpt->lock);
06216
06217
06218
06219 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06220 myrpt->mydtmf = myrpt->p.endchar;
06221 }
06222 if (myrpt->callmode){
06223 rpt_mutex_unlock(&myrpt->lock);
06224 return DC_COMPLETE;
06225 }
06226 myrpt->callmode = 1;
06227 myrpt->cidx = 0;
06228 myrpt->exten[myrpt->cidx] = 0;
06229 rpt_mutex_unlock(&myrpt->lock);
06230 pthread_attr_init(&attr);
06231 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06232 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06233 return DC_COMPLETE;
06234 }
06235
06236
06237
06238
06239
06240 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06241 {
06242 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06243 return DC_ERROR;
06244
06245 if(debug)
06246 printf("@@@@ Autopatch down\n");
06247
06248 rpt_mutex_lock(&myrpt->lock);
06249
06250 myrpt->macropatch=0;
06251
06252 if (!myrpt->callmode){
06253 rpt_mutex_unlock(&myrpt->lock);
06254 return DC_COMPLETE;
06255 }
06256
06257 myrpt->callmode = 0;
06258 channel_revert(myrpt);
06259 rpt_mutex_unlock(&myrpt->lock);
06260 rpt_telemetry(myrpt, TERM, NULL);
06261 return DC_COMPLETE;
06262 }
06263
06264
06265
06266
06267
06268 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06269 {
06270
06271 if (!param)
06272 return DC_ERROR;
06273
06274 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06275 return DC_ERROR;
06276
06277 if(debug)
06278 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06279
06280 switch(myatoi(param)){
06281 case 1:
06282 rpt_telemetry(myrpt, ID1, NULL);
06283 return DC_COMPLETE;
06284 case 2:
06285 rpt_telemetry(myrpt, STATS_TIME, NULL);
06286 return DC_COMPLETE;
06287 case 3:
06288 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06289 return DC_COMPLETE;
06290 case 11:
06291 rpt_telemetry(myrpt, ID , NULL);
06292 return DC_COMPLETE;
06293 case 12:
06294 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06295 return DC_COMPLETE;
06296 default:
06297 return DC_ERROR;
06298 }
06299 return DC_INDETERMINATE;
06300 }
06301
06302
06303
06304 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06305 {
06306 char *val;
06307 int i;
06308 if (myrpt->remote)
06309 return DC_ERROR;
06310
06311 if(debug)
06312 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06313
06314 if(strlen(digitbuf) < 1)
06315 return DC_INDETERMINATE;
06316
06317 for(i = 0 ; i < digitbuf[i] ; i++) {
06318 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06319 return DC_ERROR;
06320 }
06321
06322 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06323 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06324
06325 if (!val){
06326 if (strlen(digitbuf) < myrpt->macro_longest)
06327 return DC_INDETERMINATE;
06328 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06329 return DC_COMPLETE;
06330 }
06331 rpt_mutex_lock(&myrpt->lock);
06332 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06333 {
06334 rpt_mutex_unlock(&myrpt->lock);
06335 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06336 return DC_ERROR;
06337 }
06338 myrpt->macrotimer = MACROTIME;
06339 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06340 rpt_mutex_unlock(&myrpt->lock);
06341 return DC_COMPLETE;
06342 }
06343
06344
06345
06346
06347
06348 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06349 {
06350
06351 if (myrpt->remote)
06352 return DC_ERROR;
06353
06354 if(debug)
06355 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06356
06357 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06358 return DC_ERROR;
06359
06360 rpt_telemetry(myrpt,PLAYBACK,param);
06361 return DC_COMPLETE;
06362 }
06363
06364
06365
06366
06367
06368 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06369 {
06370 char string[16];
06371 int res;
06372
06373 int i, r;
06374
06375 if(!param)
06376 return DC_ERROR;
06377
06378 switch(myatoi(param)){
06379 case 1:
06380 res = system("killall -9 asterisk");
06381 return DC_COMPLETE;
06382
06383 case 2:
06384 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06385 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06386 return DC_COMPLETE;
06387
06388 case 3:
06389 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06390 return DC_COMPLETE;
06391
06392 case 4:
06393 if (myrpt->stopgen < 0)
06394 {
06395 myrpt->stopgen = 1;
06396 }
06397 else
06398 {
06399 myrpt->stopgen = 0;
06400 rpt_telemetry(myrpt, TEST_TONE, NULL);
06401 }
06402 return DC_COMPLETE;
06403
06404 case 5:
06405 myrpt->disgorgetime = time(NULL) + 10;
06406 return DC_COMPLETE;
06407
06408 case 6:
06409 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06410 return DC_DOKEY;
06411
06412
06413 case 7:
06414 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06415 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06416 return DC_COMPLETE;
06417
06418 case 8:
06419 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06420 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06421 return DC_COMPLETE;
06422
06423 case 9:
06424 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06425 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06426 return DC_COMPLETE;
06427
06428 case 10:
06429 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06430 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06431 return DC_COMPLETE;
06432
06433 case 11:
06434 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06435 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06436 return DC_COMPLETE;
06437
06438 case 12:
06439 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06440 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06441 return DC_COMPLETE;
06442
06443 case 13:
06444 string[0] = string[1] = 'S';
06445 string[2] = myrpt->p.sysstate_cur + '0';
06446 string[3] = '\0';
06447 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06448 return DC_COMPLETE;
06449
06450 case 14:
06451 if(strlen(digitbuf) == 0)
06452 break;
06453 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06454 return DC_ERROR;
06455 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06456 string[0] = string[1] = 'S';
06457 string[2] = myrpt->p.sysstate_cur + '0';
06458 string[3] = '\0';
06459 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06460 return DC_COMPLETE;
06461
06462 case 15:
06463 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06464 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06465 return DC_COMPLETE;
06466
06467 case 16:
06468 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06469 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06470 return DC_COMPLETE;
06471
06472 case 17:
06473 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06474 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06475 return DC_COMPLETE;
06476
06477 case 18:
06478 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06479 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06480 return DC_COMPLETE;
06481
06482 case 19:
06483 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06484 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06485 return DC_COMPLETE;
06486
06487 case 20:
06488 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06489 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06490 return DC_COMPLETE;
06491
06492 case 21:
06493 birdbath(myrpt);
06494 if (myrpt->p.parrotmode < 2)
06495 {
06496 myrpt->p.parrotmode = 0;
06497 rpt_telemetry(myrpt,COMPLETE,NULL);
06498 return DC_COMPLETE;
06499 }
06500 break;
06501
06502 case 22:
06503 birdbath(myrpt);
06504 if (myrpt->p.parrotmode < 2)
06505 {
06506 myrpt->p.parrotmode = 1;
06507 rpt_telemetry(myrpt,COMPLETE,NULL);
06508 return DC_COMPLETE;
06509 }
06510 break;
06511 case 23:
06512 birdbath(myrpt);
06513 rpt_telemetry(myrpt,COMPLETE,NULL);
06514 return DC_COMPLETE;
06515 case 24:
06516 flush_telem(myrpt);
06517 rpt_telemetry(myrpt,COMPLETE,NULL);
06518 return DC_COMPLETE;
06519 case 25:
06520 send_link_keyquery(myrpt);
06521 myrpt->topkeylong = 0;
06522 rpt_telemetry(myrpt,COMPLETE,NULL);
06523 return DC_COMPLETE;
06524 case 26:
06525 send_link_keyquery(myrpt);
06526 myrpt->topkeylong = 1;
06527 rpt_telemetry(myrpt,COMPLETE,NULL);
06528 return DC_COMPLETE;
06529
06530 case 30:
06531
06532 if(strlen(digitbuf) < 2)
06533 break;
06534
06535 for(i = 0 ; i < 2 ; i++){
06536 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06537 return DC_ERROR;
06538 }
06539
06540 r = retreive_memory(myrpt, digitbuf);
06541 if (r < 0){
06542 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06543 return DC_COMPLETE;
06544 }
06545 if (r > 0){
06546 return DC_ERROR;
06547 }
06548 if (setrem(myrpt) == -1) return DC_ERROR;
06549 return DC_COMPLETE;
06550
06551 case 31:
06552
06553
06554 if(strlen(digitbuf) < 2)
06555 break;
06556
06557 for(i = 0 ; i < 2 ; i++){
06558 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06559 return DC_ERROR;
06560 }
06561 channel_steer(myrpt,digitbuf);
06562 return DC_COMPLETE;
06563
06564 case 32:
06565 i = strlen(digitbuf);
06566 if(!i){
06567 if(debug > 3)
06568 ast_log(LOG_NOTICE,"Padtest entered");
06569 myrpt->inpadtest = 1;
06570 }
06571 else{
06572 if(debug > 3)
06573 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06574 if(digitbuf[i-1] != myrpt->p.endchar)
06575 break;
06576 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06577 myrpt->inpadtest = 0;
06578 if(debug > 3)
06579 ast_log(LOG_NOTICE,"Padtest exited");
06580 return DC_COMPLETE;
06581 }
06582 }
06583 return DC_INDETERMINATE;
06584 }
06585
06586
06587
06588 static int collect_function_digits(struct rpt *myrpt, char *digits,
06589 int command_source, struct rpt_link *mylink)
06590 {
06591 int i,rv;
06592 char *stringp,*action,*param,*functiondigits;
06593 char function_table_name[30] = "";
06594 char workstring[200];
06595
06596 struct ast_variable *vp;
06597
06598 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06599
06600
06601
06602
06603 if (command_source == SOURCE_DPHONE) {
06604 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06605 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06606 }
06607 else if (command_source == SOURCE_ALT) {
06608 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06609 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06610 }
06611 else if (command_source == SOURCE_PHONE) {
06612 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06613 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06614 }
06615 else if (command_source == SOURCE_LNK)
06616 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06617 else
06618 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06619
06620 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06621 while(vp) {
06622 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06623 break;
06624 vp = vp->next;
06625 }
06626
06627 if(!vp) {
06628 int n;
06629
06630 n = myrpt->longestfunc;
06631 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06632 else
06633 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06634 else
06635 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06636 else
06637 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06638
06639 if(strlen(digits) >= n)
06640 return DC_ERROR;
06641 else
06642 return DC_INDETERMINATE;
06643 }
06644
06645 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06646 stringp = workstring;
06647 action = strsep(&stringp, ",");
06648 param = stringp;
06649 if(debug)
06650 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06651
06652 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06653 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06654 break;
06655 }
06656 if(debug)
06657 printf("@@@@ table index i = %d\n",i);
06658 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06659
06660 return DC_ERROR;
06661 }
06662 if(function_table[i].function == NULL){
06663
06664 if(debug)
06665 printf("@@@@ NULL for action: %s\n",action);
06666 return DC_ERROR;
06667 }
06668 functiondigits = digits + strlen(vp->name);
06669 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06670 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06671 return(rv);
06672 }
06673
06674
06675 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06676 char *str)
06677 {
06678
06679
06680 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06681 int i,seq, res, ts;
06682 struct rpt_link *l;
06683 struct ast_frame wf;
06684
06685 wf.frametype = AST_FRAME_TEXT;
06686 wf.subclass = 0;
06687 wf.offset = 0;
06688 wf.mallocd = 0;
06689 wf.datalen = strlen(str) + 1;
06690 wf.samples = 0;
06691
06692 strncpy(tmp,str,sizeof(tmp) - 1);
06693
06694 if (!strcmp(tmp,discstr))
06695 {
06696 mylink->disced = 1;
06697 mylink->retries = mylink->max_retries + 1;
06698 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06699 return;
06700 }
06701 if (!strcmp(tmp,newkeystr))
06702 {
06703 mylink->newkey = 1;
06704 return;
06705 }
06706 if (tmp[0] == 'L')
06707 {
06708 rpt_mutex_lock(&myrpt->lock);
06709 strcpy(mylink->linklist,tmp + 2);
06710 time(&mylink->linklistreceived);
06711 rpt_mutex_unlock(&myrpt->lock);
06712 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06713 myrpt->name,tmp,mylink->name);
06714 return;
06715 }
06716 if (tmp[0] == 'K')
06717 {
06718 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06719 {
06720 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06721 return;
06722 }
06723 if (dest[0] == '0')
06724 {
06725 strcpy(dest,myrpt->name);
06726 }
06727
06728 if (strcmp(dest,myrpt->name))
06729 {
06730 l = myrpt->links.next;
06731
06732 while(l != &myrpt->links)
06733 {
06734 if (l->name[0] == '0')
06735 {
06736 l = l->next;
06737 continue;
06738 }
06739
06740 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06741 {
06742 l = l->next;
06743 continue;
06744 }
06745
06746 if (!strcmp(l->name,dest))
06747 {
06748
06749 if (strcmp(l->name,src)) {
06750 wf.data.ptr = str;
06751 if (l->chan) ast_write(l->chan,&wf);
06752 }
06753 return;
06754 }
06755 l = l->next;
06756 }
06757 }
06758
06759 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06760 {
06761 l = myrpt->links.next;
06762
06763 while(l != &myrpt->links)
06764 {
06765 if (l->name[0] == '0')
06766 {
06767 l = l->next;
06768 continue;
06769 }
06770
06771 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06772 {
06773 l = l->next;
06774 continue;
06775 }
06776
06777 if (strcmp(l->name,src)) {
06778 wf.data.ptr = str;
06779 if (l->chan) ast_write(l->chan,&wf);
06780 }
06781 l = l->next;
06782 }
06783 }
06784
06785 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06786 if (cmd[1] == '?')
06787 {
06788 time_t now;
06789 int n = 0;
06790
06791 time(&now);
06792 if (myrpt->lastkeyedtime)
06793 {
06794 n = (int)(now - myrpt->lastkeyedtime);
06795 }
06796 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06797 wf.data.ptr = tmp1;
06798 wf.datalen = strlen(tmp1) + 1;
06799 if (mylink->chan) ast_write(mylink->chan,&wf);
06800 return;
06801 }
06802 if (myrpt->topkeystate != 1) return;
06803 rpt_mutex_lock(&myrpt->lock);
06804 for(i = 0; i < TOPKEYN; i++)
06805 {
06806 if (!strcmp(myrpt->topkey[i].node,src)) break;
06807 }
06808 if (i >= TOPKEYN)
06809 {
06810 for(i = 0; i < TOPKEYN; i++)
06811 {
06812 if (!myrpt->topkey[i].node[0]) break;
06813 }
06814 }
06815 if (i < TOPKEYN)
06816 {
06817 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06818 myrpt->topkey[i].timesince = ts;
06819 myrpt->topkey[i].keyed = seq;
06820 }
06821 rpt_mutex_unlock(&myrpt->lock);
06822 return;
06823 }
06824 if (tmp[0] == 'I')
06825 {
06826
06827
06828 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06829 {
06830 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06831 return;
06832 }
06833 mdc1200_notify(myrpt,src,seq);
06834 strcpy(dest,"*");
06835 }
06836 else
06837 {
06838
06839
06840 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06841 {
06842 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06843 return;
06844 }
06845 if (strcmp(cmd,"D"))
06846 {
06847 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06848 return;
06849 }
06850 }
06851 if (dest[0] == '0')
06852 {
06853 strcpy(dest,myrpt->name);
06854 }
06855
06856
06857 if (strcmp(dest,myrpt->name))
06858 {
06859 l = myrpt->links.next;
06860
06861 while(l != &myrpt->links)
06862 {
06863 if (l->name[0] == '0')
06864 {
06865 l = l->next;
06866 continue;
06867 }
06868
06869 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06870 {
06871 l = l->next;
06872 continue;
06873 }
06874
06875 if (!strcmp(l->name,dest))
06876 {
06877
06878 if (strcmp(l->name,src)) {
06879 wf.data.ptr = str;
06880 if (l->chan) ast_write(l->chan,&wf);
06881 }
06882 return;
06883 }
06884 l = l->next;
06885 }
06886 l = myrpt->links.next;
06887
06888 while(l != &myrpt->links)
06889 {
06890 if (l->name[0] == '0')
06891 {
06892 l = l->next;
06893 continue;
06894 }
06895
06896 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06897 {
06898 l = l->next;
06899 continue;
06900 }
06901
06902 if (strcmp(l->name,src)) {
06903 wf.data.ptr = str;
06904 if (l->chan) ast_write(l->chan,&wf);
06905 }
06906 l = l->next;
06907 }
06908 return;
06909 }
06910 if (myrpt->p.archivedir)
06911 {
06912 char dtmfstr[100];
06913
06914 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06915 donodelog(myrpt,dtmfstr);
06916 }
06917 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06918 if (!c) return;
06919 rpt_mutex_lock(&myrpt->lock);
06920 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06921 if (myrpt->callmode == 1)
06922 {
06923 myrpt->exten[myrpt->cidx++] = c;
06924 myrpt->exten[myrpt->cidx] = 0;
06925
06926 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06927 {
06928
06929 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06930 myrpt->exten,1,NULL))
06931 {
06932 myrpt->callmode = 2;
06933 if(!myrpt->patchquiet)
06934 {
06935 rpt_mutex_unlock(&myrpt->lock);
06936 rpt_telemetry(myrpt,PROC,NULL);
06937 rpt_mutex_lock(&myrpt->lock);
06938 }
06939 }
06940 else
06941 {
06942 myrpt->calldigittimer = 1;
06943 }
06944 }
06945
06946 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06947 {
06948
06949 myrpt->callmode = 4;
06950 }
06951 }
06952 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06953 {
06954 myrpt->rem_dtmfidx = 0;
06955 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06956 time(&myrpt->rem_dtmf_time);
06957 rpt_mutex_unlock(&myrpt->lock);
06958 return;
06959 }
06960 else if (myrpt->rem_dtmfidx < 0)
06961 {
06962 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06963 {
06964 myrpt->mydtmf = c;
06965 }
06966 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06967 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06968 rpt_mutex_unlock(&myrpt->lock);
06969 return;
06970 }
06971 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06972 {
06973 time(&myrpt->rem_dtmf_time);
06974 if (myrpt->rem_dtmfidx < MAXDTMF)
06975 {
06976 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06977 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06978
06979 rpt_mutex_unlock(&myrpt->lock);
06980 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06981 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06982 rpt_mutex_lock(&myrpt->lock);
06983
06984 switch(res){
06985
06986 case DC_INDETERMINATE:
06987 break;
06988
06989 case DC_REQ_FLUSH:
06990 myrpt->rem_dtmfidx = 0;
06991 myrpt->rem_dtmfbuf[0] = 0;
06992 break;
06993
06994
06995 case DC_COMPLETE:
06996 case DC_COMPLETEQUIET:
06997 myrpt->totalexecdcommands++;
06998 myrpt->dailyexecdcommands++;
06999 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07000 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07001 myrpt->rem_dtmfbuf[0] = 0;
07002 myrpt->rem_dtmfidx = -1;
07003 myrpt->rem_dtmf_time = 0;
07004 break;
07005
07006 case DC_ERROR:
07007 default:
07008 myrpt->rem_dtmfbuf[0] = 0;
07009 myrpt->rem_dtmfidx = -1;
07010 myrpt->rem_dtmf_time = 0;
07011 break;
07012 }
07013 }
07014
07015 }
07016 rpt_mutex_unlock(&myrpt->lock);
07017 return;
07018 }
07019
07020 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07021 char c)
07022 {
07023
07024 char cmd[300];
07025 int res;
07026
07027 if (myrpt->p.archivedir)
07028 {
07029 char str[100];
07030
07031 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07032 donodelog(myrpt,str);
07033 }
07034 rpt_mutex_lock(&myrpt->lock);
07035
07036 if (mylink->phonemode == 3)
07037 {
07038 if(c == myrpt->p.endchar)
07039 {
07040 mylink->lastrealrx = 0;
07041 rpt_mutex_unlock(&myrpt->lock);
07042 return;
07043 }
07044
07045 if(c == myrpt->p.funcchar)
07046 {
07047 mylink->lastrealrx = !mylink->lastrealrx;
07048 rpt_mutex_unlock(&myrpt->lock);
07049 return;
07050 }
07051 }
07052 else
07053 {
07054 if (c == myrpt->p.endchar)
07055 {
07056 if (mylink->lastrx)
07057 {
07058 mylink->lastrealrx = 0;
07059 rpt_mutex_unlock(&myrpt->lock);
07060 return;
07061 }
07062 myrpt->stopgen = 1;
07063 if (myrpt->cmdnode[0])
07064 {
07065 myrpt->cmdnode[0] = 0;
07066 myrpt->dtmfidx = -1;
07067 myrpt->dtmfbuf[0] = 0;
07068 rpt_mutex_unlock(&myrpt->lock);
07069 rpt_telemetry(myrpt,COMPLETE,NULL);
07070 return;
07071 }
07072 }
07073 }
07074 if (myrpt->cmdnode[0])
07075 {
07076 rpt_mutex_unlock(&myrpt->lock);
07077 send_link_dtmf(myrpt,c);
07078 return;
07079 }
07080 if (myrpt->callmode == 1)
07081 {
07082 myrpt->exten[myrpt->cidx++] = c;
07083 myrpt->exten[myrpt->cidx] = 0;
07084
07085 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07086 {
07087
07088 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07089 myrpt->exten,1,NULL))
07090 {
07091 myrpt->callmode = 2;
07092 if(!myrpt->patchquiet)
07093 {
07094 rpt_mutex_unlock(&myrpt->lock);
07095 rpt_telemetry(myrpt,PROC,NULL);
07096 rpt_mutex_lock(&myrpt->lock);
07097 }
07098 }
07099 else
07100 {
07101 myrpt->calldigittimer = 1;
07102 }
07103 }
07104
07105 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07106 {
07107
07108 myrpt->callmode = 4;
07109 }
07110 }
07111 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07112 {
07113 myrpt->mydtmf = c;
07114 }
07115 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07116 {
07117 myrpt->rem_dtmfidx = 0;
07118 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07119 time(&myrpt->rem_dtmf_time);
07120 rpt_mutex_unlock(&myrpt->lock);
07121 return;
07122 }
07123 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07124 {
07125 time(&myrpt->rem_dtmf_time);
07126 if (myrpt->rem_dtmfidx < MAXDTMF)
07127 {
07128 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07129 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07130
07131 rpt_mutex_unlock(&myrpt->lock);
07132 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07133 switch(mylink->phonemode)
07134 {
07135 case 1:
07136 res = collect_function_digits(myrpt, cmd,
07137 SOURCE_PHONE, mylink);
07138 break;
07139 case 2:
07140 res = collect_function_digits(myrpt, cmd,
07141 SOURCE_DPHONE,mylink);
07142 break;
07143 case 4:
07144 res = collect_function_digits(myrpt, cmd,
07145 SOURCE_ALT,mylink);
07146 break;
07147 default:
07148 res = collect_function_digits(myrpt, cmd,
07149 SOURCE_LNK, mylink);
07150 break;
07151 }
07152
07153 rpt_mutex_lock(&myrpt->lock);
07154
07155 switch(res){
07156
07157 case DC_INDETERMINATE:
07158 break;
07159
07160 case DC_DOKEY:
07161 mylink->lastrealrx = 1;
07162 break;
07163
07164 case DC_REQ_FLUSH:
07165 myrpt->rem_dtmfidx = 0;
07166 myrpt->rem_dtmfbuf[0] = 0;
07167 break;
07168
07169
07170 case DC_COMPLETE:
07171 case DC_COMPLETEQUIET:
07172 myrpt->totalexecdcommands++;
07173 myrpt->dailyexecdcommands++;
07174 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07175 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07176 myrpt->rem_dtmfbuf[0] = 0;
07177 myrpt->rem_dtmfidx = -1;
07178 myrpt->rem_dtmf_time = 0;
07179 break;
07180
07181 case DC_ERROR:
07182 default:
07183 myrpt->rem_dtmfbuf[0] = 0;
07184 myrpt->rem_dtmfidx = -1;
07185 myrpt->rem_dtmf_time = 0;
07186 break;
07187 }
07188 }
07189
07190 }
07191 rpt_mutex_unlock(&myrpt->lock);
07192 return;
07193 }
07194
07195
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226 static int rbi_mhztoband(char *str)
07227 {
07228 int i;
07229
07230 i = atoi(str) / 10;
07231 switch(i)
07232 {
07233 case 2:
07234 return 10;
07235 case 5:
07236 return 11;
07237 case 14:
07238 return 2;
07239 case 22:
07240 return 3;
07241 case 44:
07242 return 4;
07243 case 124:
07244 return 0;
07245 case 125:
07246 return 1;
07247 case 126:
07248 return 8;
07249 case 127:
07250 return 5;
07251 case 128:
07252 return 6;
07253 case 129:
07254 return 7;
07255 default:
07256 break;
07257 }
07258 return -1;
07259 }
07260
07261
07262 static int rbi_pltocode(char *str)
07263 {
07264 int i;
07265 char *s;
07266
07267 s = strchr(str,'.');
07268 i = 0;
07269 if (s) i = atoi(s + 1);
07270 i += atoi(str) * 10;
07271 switch(i)
07272 {
07273 case 670:
07274 return 0;
07275 case 719:
07276 return 1;
07277 case 744:
07278 return 2;
07279 case 770:
07280 return 3;
07281 case 797:
07282 return 4;
07283 case 825:
07284 return 5;
07285 case 854:
07286 return 6;
07287 case 885:
07288 return 7;
07289 case 915:
07290 return 8;
07291 case 948:
07292 return 9;
07293 case 974:
07294 return 10;
07295 case 1000:
07296 return 11;
07297 case 1035:
07298 return 12;
07299 case 1072:
07300 return 13;
07301 case 1109:
07302 return 14;
07303 case 1148:
07304 return 15;
07305 case 1188:
07306 return 16;
07307 case 1230:
07308 return 17;
07309 case 1273:
07310 return 18;
07311 case 1318:
07312 return 19;
07313 case 1365:
07314 return 20;
07315 case 1413:
07316 return 21;
07317 case 1462:
07318 return 22;
07319 case 1514:
07320 return 23;
07321 case 1567:
07322 return 24;
07323 case 1622:
07324 return 25;
07325 case 1679:
07326 return 26;
07327 case 1738:
07328 return 27;
07329 case 1799:
07330 return 28;
07331 case 1862:
07332 return 29;
07333 case 1928:
07334 return 30;
07335 case 2035:
07336 return 31;
07337 case 2107:
07338 return 32;
07339 case 2181:
07340 return 33;
07341 case 2257:
07342 return 34;
07343 case 2336:
07344 return 35;
07345 case 2418:
07346 return 36;
07347 case 2503:
07348 return 37;
07349 }
07350 return -1;
07351 }
07352
07353
07354
07355
07356
07357 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07358 {
07359 #ifdef __i386__
07360 int i,j;
07361 unsigned char od,d;
07362 static volatile long long delayvar;
07363
07364 for(i = 0 ; i < 5 ; i++){
07365 od = *data++;
07366 for(j = 0 ; j < 8 ; j++){
07367 d = od & 1;
07368 outb(d,myrpt->p.iobase);
07369
07370 for(delayvar = 1; delayvar < 15000; delayvar++);
07371 od >>= 1;
07372 outb(d | 2,myrpt->p.iobase);
07373
07374 for(delayvar = 1; delayvar < 30000; delayvar++);
07375 outb(d,myrpt->p.iobase);
07376
07377 for(delayvar = 1; delayvar < 10000; delayvar++);
07378 }
07379 }
07380
07381 for(delayvar = 1; delayvar < 50000; delayvar++);
07382 #endif
07383 }
07384
07385 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07386 {
07387 struct dahdi_radio_param r;
07388
07389 memset(&r,0,sizeof(struct dahdi_radio_param));
07390 r.radpar = DAHDI_RADPAR_REMMODE;
07391 r.data = DAHDI_RADPAR_REM_RBI1;
07392
07393 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07394 {
07395 rbi_out_parallel(myrpt,data);
07396 return;
07397 }
07398 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07399 memcpy(&r.data,data,5);
07400 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07401 {
07402 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07403 return;
07404 }
07405 }
07406
07407 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07408 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07409 {
07410 int i,j,idx,oldmode,olddata;
07411 struct dahdi_radio_param prm;
07412 char c;
07413
07414 if(debug) {
07415 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07416 printf("String output was:\n");
07417 for(i = 0; i < txbytes; i++)
07418 printf("%02X ", (unsigned char ) txbuf[i]);
07419 printf("\n");
07420 }
07421
07422 if (myrpt->iofd >= 0)
07423 {
07424 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07425 {
07426 return -1;
07427 }
07428 if ((!rxmaxbytes) || (rxbuf == NULL))
07429 {
07430 return(0);
07431 }
07432 memset(rxbuf,0,rxmaxbytes);
07433 for(i = 0; i < rxmaxbytes; i++)
07434 {
07435 j = read(myrpt->iofd,&c,1);
07436 if (j < 1)
07437 {
07438 return(i);
07439 }
07440 rxbuf[i] = c;
07441 if (asciiflag & 1)
07442 {
07443 rxbuf[i + 1] = 0;
07444 if (c == '\r') break;
07445 }
07446 }
07447 if(debug) {
07448 printf("String returned was:\n");
07449 for(j = 0; j < i; j++)
07450 printf("%02X ", (unsigned char ) rxbuf[j]);
07451 printf("\n");
07452 }
07453 return(i);
07454 }
07455
07456
07457 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07458
07459 prm.radpar = DAHDI_RADPAR_UIOMODE;
07460 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07461 oldmode = prm.data;
07462 prm.radpar = DAHDI_RADPAR_UIODATA;
07463 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07464 olddata = prm.data;
07465 prm.radpar = DAHDI_RADPAR_REMMODE;
07466 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07467 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07468 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07469 if (asciiflag & 2)
07470 {
07471 i = DAHDI_ONHOOK;
07472 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07473 usleep(100000);
07474 }
07475 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07476 prm.data = rxmaxbytes;
07477 memcpy(prm.buf,txbuf,txbytes);
07478 prm.index = txbytes;
07479 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07480 if (rxbuf)
07481 {
07482 *rxbuf = 0;
07483 memcpy(rxbuf,prm.buf,prm.index);
07484 }
07485 idx = prm.index;
07486 prm.radpar = DAHDI_RADPAR_REMMODE;
07487 prm.data = DAHDI_RADPAR_REM_NONE;
07488 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07489 if (asciiflag & 2)
07490 {
07491 i = DAHDI_OFFHOOK;
07492 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07493 }
07494 prm.radpar = DAHDI_RADPAR_UIOMODE;
07495 prm.data = oldmode;
07496 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07497 prm.radpar = DAHDI_RADPAR_UIODATA;
07498 prm.data = olddata;
07499 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07500 return(idx);
07501 }
07502
07503 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07504 {
07505 unsigned char rxbuf[100];
07506 int i,rv ;
07507
07508 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07509 if (rv == -1) return(-1);
07510 if (rv != (cmdlen + 6)) return(1);
07511 for(i = 0; i < 6; i++)
07512 if (rxbuf[i] != cmd[i]) return(1);
07513 if (rxbuf[cmdlen] != 0xfe) return(1);
07514 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07515 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07516 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07517 return(0);
07518 }
07519
07520 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07521 {
07522 int i;
07523
07524 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07525 if (debug) printf("Send to kenwood: %s\n",txstr);
07526 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07527 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07528 if (i < 0) return -1;
07529 if ((i > 0) && (rxstr[i - 1] == '\r'))
07530 rxstr[i-- - 1] = 0;
07531 if (debug) printf("Got from kenwood: %s\n",rxstr);
07532 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07533 return(i);
07534 }
07535
07536
07537 static int kenwood_pltocode(char *str)
07538 {
07539 int i;
07540 char *s;
07541
07542 s = strchr(str,'.');
07543 i = 0;
07544 if (s) i = atoi(s + 1);
07545 i += atoi(str) * 10;
07546 switch(i)
07547 {
07548 case 670:
07549 return 1;
07550 case 719:
07551 return 3;
07552 case 744:
07553 return 4;
07554 case 770:
07555 return 5;
07556 case 797:
07557 return 6;
07558 case 825:
07559 return 7;
07560 case 854:
07561 return 8;
07562 case 885:
07563 return 9;
07564 case 915:
07565 return 10;
07566 case 948:
07567 return 11;
07568 case 974:
07569 return 12;
07570 case 1000:
07571 return 13;
07572 case 1035:
07573 return 14;
07574 case 1072:
07575 return 15;
07576 case 1109:
07577 return 16;
07578 case 1148:
07579 return 17;
07580 case 1188:
07581 return 18;
07582 case 1230:
07583 return 19;
07584 case 1273:
07585 return 20;
07586 case 1318:
07587 return 21;
07588 case 1365:
07589 return 22;
07590 case 1413:
07591 return 23;
07592 case 1462:
07593 return 24;
07594 case 1514:
07595 return 25;
07596 case 1567:
07597 return 26;
07598 case 1622:
07599 return 27;
07600 case 1679:
07601 return 28;
07602 case 1738:
07603 return 29;
07604 case 1799:
07605 return 30;
07606 case 1862:
07607 return 31;
07608 case 1928:
07609 return 32;
07610 case 2035:
07611 return 33;
07612 case 2107:
07613 return 34;
07614 case 2181:
07615 return 35;
07616 case 2257:
07617 return 36;
07618 case 2336:
07619 return 37;
07620 case 2418:
07621 return 38;
07622 case 2503:
07623 return 39;
07624 }
07625 return -1;
07626 }
07627
07628 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07629 char *cmpstr)
07630 {
07631 int i,j;
07632
07633 for(i = 0;i < KENWOOD_RETRIES;i++)
07634 {
07635 j = sendkenwood(myrpt,txstr,rxstr);
07636 if (j < 0) return(j);
07637 if (j == 0) continue;
07638 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07639 }
07640 return(-1);
07641 }
07642
07643 static int setkenwood(struct rpt *myrpt)
07644 {
07645 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07646 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07647 int myrxpl;
07648
07649 int offsets[] = {0,2,1};
07650 int powers[] = {2,1,0};
07651
07652 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07653 split_freq(mhz, decimals, myrpt->freq);
07654 if (atoi(mhz) > 400)
07655 {
07656 band = '6';
07657 band1 = '1';
07658 band2 = '5';
07659 strcpy(offset,"005000000");
07660 }
07661 else
07662 {
07663 band = '2';
07664 band1 = '0';
07665 band2 = '2';
07666 strcpy(offset,"000600000");
07667 }
07668 strcpy(freq,"000000");
07669 strncpy(freq,decimals,strlen(decimals));
07670 myrxpl = myrpt->rxplon;
07671 if (IS_XPMR(myrpt)) myrxpl = 0;
07672 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07673 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07674 (myrpt->txplon != 0),myrxpl,
07675 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07676 offset);
07677 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07678 sprintf(txstr,"RBN %c\r",band2);
07679 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07680 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07681 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07682 return 0;
07683 }
07684
07685 static int set_tm271(struct rpt *myrpt)
07686 {
07687 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07688 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07689
07690 int offsets[] = {0,2,1};
07691 int powers[] = {2,1,0};
07692
07693 split_freq(mhz, decimals, myrpt->freq);
07694 strcpy(freq,"000000");
07695 strncpy(freq,decimals,strlen(decimals));
07696
07697 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07698 atoi(mhz),freq,offsets[(int)myrpt->offset],
07699 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07700 kenwood_pltocode(myrpt->rxpl));
07701
07702 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07703 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07704 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07705 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07706 return 0;
07707 }
07708
07709 static int setrbi(struct rpt *myrpt)
07710 {
07711 char tmp[MAXREMSTR] = "",*s;
07712 unsigned char rbicmd[5];
07713 int band,txoffset = 0,txpower = 0,rxpl;
07714
07715
07716 if (!myrpt->remoterig) return(0);
07717 if (!myrpt->remoterig[0]) return(0);
07718
07719 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07720 if (setrbi_check(myrpt) == -1) return(-1);
07721 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07722 s = strchr(tmp,'.');
07723
07724
07725 if (s == NULL){
07726 if(debug)
07727 printf("@@@@ Frequency needs a decimal\n");
07728 return -1;
07729 }
07730
07731 *s++ = 0;
07732 if (strlen(tmp) < 2){
07733 if(debug)
07734 printf("@@@@ Bad MHz digits: %s\n", tmp);
07735 return -1;
07736 }
07737
07738 if (strlen(s) < 3){
07739 if(debug)
07740 printf("@@@@ Bad KHz digits: %s\n", s);
07741 return -1;
07742 }
07743
07744 if ((s[2] != '0') && (s[2] != '5')){
07745 if(debug)
07746 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07747 return -1;
07748 }
07749
07750 band = rbi_mhztoband(tmp);
07751 if (band == -1){
07752 if(debug)
07753 printf("@@@@ Bad Band: %s\n", tmp);
07754 return -1;
07755 }
07756
07757 rxpl = rbi_pltocode(myrpt->rxpl);
07758
07759 if (rxpl == -1){
07760 if(debug)
07761 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07762 return -1;
07763 }
07764
07765
07766 switch(myrpt->offset)
07767 {
07768 case REM_MINUS:
07769 txoffset = 0;
07770 break;
07771 case REM_PLUS:
07772 txoffset = 0x10;
07773 break;
07774 case REM_SIMPLEX:
07775 txoffset = 0x20;
07776 break;
07777 }
07778 switch(myrpt->powerlevel)
07779 {
07780 case REM_LOWPWR:
07781 txpower = 0;
07782 break;
07783 case REM_MEDPWR:
07784 txpower = 0x20;
07785 break;
07786 case REM_HIPWR:
07787 txpower = 0x10;
07788 break;
07789 }
07790 rbicmd[0] = 0;
07791 rbicmd[1] = band | txpower | 0xc0;
07792 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07793 if (s[2] == '5') rbicmd[2] |= 0x40;
07794 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07795 rbicmd[4] = rxpl;
07796 if (myrpt->txplon) rbicmd[4] |= 0x40;
07797 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07798 rbi_out(myrpt,rbicmd);
07799 return 0;
07800 }
07801
07802 static int setrtx(struct rpt *myrpt)
07803 {
07804 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07805 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07806 float ofac;
07807 double txfreq;
07808
07809
07810 if (!myrpt->remoterig) return(0);
07811 if (!myrpt->remoterig[0]) return(0);
07812
07813 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07814
07815 if (!IS_XPMR(myrpt)) return(0);
07816 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07817 s = strchr(tmp,'.');
07818
07819
07820 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07821
07822 if (s == NULL){
07823 if(debug)
07824 printf("@@@@ Frequency needs a decimal\n");
07825 return -1;
07826 }
07827 *s++ = 0;
07828 if (strlen(tmp) < 2){
07829 if(debug)
07830 printf("@@@@ Bad MHz digits: %s\n", tmp);
07831 return -1;
07832 }
07833
07834 if (strlen(s) < 3){
07835 if(debug)
07836 printf("@@@@ Bad KHz digits: %s\n", s);
07837 return -1;
07838 }
07839
07840 if ((s[2] != '0') && (s[2] != '5')){
07841 if(debug)
07842 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07843 return -1;
07844 }
07845
07846 band = rbi_mhztoband(tmp);
07847 if (band == -1){
07848 if(debug)
07849 printf("@@@@ Bad Band: %s\n", tmp);
07850 return -1;
07851 }
07852
07853 rxpl = rbi_pltocode(myrpt->rxpl);
07854
07855 if (rxpl == -1){
07856 if(debug)
07857 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07858 return -1;
07859 }
07860
07861 txpl = rbi_pltocode(myrpt->txpl);
07862
07863 if (txpl == -1){
07864 if(debug)
07865 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07866 return -1;
07867 }
07868
07869 switch(myrpt->offset)
07870 {
07871 case REM_MINUS:
07872 txoffset = 0;
07873 break;
07874 case REM_PLUS:
07875 txoffset = 0x10;
07876 break;
07877 case REM_SIMPLEX:
07878 txoffset = 0x20;
07879 break;
07880 }
07881 switch(myrpt->powerlevel)
07882 {
07883 case REM_LOWPWR:
07884 txpower = 0;
07885 break;
07886 case REM_MEDPWR:
07887 txpower = 0x20;
07888 break;
07889 case REM_HIPWR:
07890 txpower = 0x10;
07891 break;
07892 }
07893
07894 res = setrtx_check(myrpt);
07895 if (res < 0) return res;
07896 ofac = 0.0;
07897 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07898 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07899
07900 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07901 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07902 else
07903 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07904
07905 pwr = 'L';
07906 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07907 if (!res)
07908 {
07909 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07910 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07911 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07912 send_usb_txt(myrpt,rigstr);
07913 rpt_telemetry(myrpt,COMPLETE,NULL);
07914 res = 0;
07915 }
07916 return 0;
07917 }
07918 #if 0
07919
07920
07921
07922
07923 static int setxpmr(struct rpt *myrpt)
07924 {
07925 char rigstr[200];
07926 int rxpl,txpl;
07927
07928
07929 if (!myrpt->remoterig) return(0);
07930 if (!myrpt->remoterig[0]) return(0);
07931
07932 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07933
07934 if (!IS_XPMR(myrpt)) return(0);
07935
07936 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07937
07938 rxpl = rbi_pltocode(myrpt->rxpl);
07939
07940 if (rxpl == -1){
07941 if(debug)
07942 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07943 return -1;
07944 }
07945
07946 txpl = rbi_pltocode(myrpt->txpl);
07947 if (txpl == -1){
07948 if(debug)
07949 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07950 return -1;
07951 }
07952 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07953 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07954 (myrpt->txplon) ? myrpt->txpl : "0.0");
07955 send_usb_txt(myrpt,rigstr);
07956 return 0;
07957 }
07958 #endif
07959
07960 static int setrbi_check(struct rpt *myrpt)
07961 {
07962 char tmp[MAXREMSTR] = "",*s;
07963 int band,txpl;
07964
07965
07966 if (!myrpt->remote) return(0);
07967
07968 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07969 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07970 s = strchr(tmp,'.');
07971
07972
07973 if (s == NULL){
07974 if(debug)
07975 printf("@@@@ Frequency needs a decimal\n");
07976 return -1;
07977 }
07978
07979 *s++ = 0;
07980 if (strlen(tmp) < 2){
07981 if(debug)
07982 printf("@@@@ Bad MHz digits: %s\n", tmp);
07983 return -1;
07984 }
07985
07986 if (strlen(s) < 3){
07987 if(debug)
07988 printf("@@@@ Bad KHz digits: %s\n", s);
07989 return -1;
07990 }
07991
07992 if ((s[2] != '0') && (s[2] != '5')){
07993 if(debug)
07994 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07995 return -1;
07996 }
07997
07998 band = rbi_mhztoband(tmp);
07999 if (band == -1){
08000 if(debug)
08001 printf("@@@@ Bad Band: %s\n", tmp);
08002 return -1;
08003 }
08004
08005 txpl = rbi_pltocode(myrpt->txpl);
08006
08007 if (txpl == -1){
08008 if(debug)
08009 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08010 return -1;
08011 }
08012 return 0;
08013 }
08014
08015 static int setrtx_check(struct rpt *myrpt)
08016 {
08017 char tmp[MAXREMSTR] = "",*s;
08018 int band,txpl,rxpl;
08019
08020
08021 if (!myrpt->remote) return(0);
08022
08023 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08024 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08025 s = strchr(tmp,'.');
08026
08027
08028 if (s == NULL){
08029 if(debug)
08030 printf("@@@@ Frequency needs a decimal\n");
08031 return -1;
08032 }
08033
08034 *s++ = 0;
08035 if (strlen(tmp) < 2){
08036 if(debug)
08037 printf("@@@@ Bad MHz digits: %s\n", tmp);
08038 return -1;
08039 }
08040
08041 if (strlen(s) < 3){
08042 if(debug)
08043 printf("@@@@ Bad KHz digits: %s\n", s);
08044 return -1;
08045 }
08046
08047 if ((s[2] != '0') && (s[2] != '5')){
08048 if(debug)
08049 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08050 return -1;
08051 }
08052
08053 band = rbi_mhztoband(tmp);
08054 if (band == -1){
08055 if(debug)
08056 printf("@@@@ Bad Band: %s\n", tmp);
08057 return -1;
08058 }
08059
08060 txpl = rbi_pltocode(myrpt->txpl);
08061
08062 if (txpl == -1){
08063 if(debug)
08064 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08065 return -1;
08066 }
08067
08068 rxpl = rbi_pltocode(myrpt->rxpl);
08069
08070 if (rxpl == -1){
08071 if(debug)
08072 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08073 return -1;
08074 }
08075 return 0;
08076 }
08077
08078 static int check_freq_kenwood(int m, int d, int *defmode)
08079 {
08080 int dflmd = REM_MODE_FM;
08081
08082 if (m == 144){
08083 if(d < 10100)
08084 return -1;
08085 }
08086 else if((m >= 145) && (m < 148)){
08087 ;
08088 }
08089 else if((m >= 430) && (m < 450)){
08090 ;
08091 }
08092 else
08093 return -1;
08094
08095 if(defmode)
08096 *defmode = dflmd;
08097
08098
08099 return 0;
08100 }
08101
08102
08103 static int check_freq_tm271(int m, int d, int *defmode)
08104 {
08105 int dflmd = REM_MODE_FM;
08106
08107 if (m == 144){
08108 if(d < 10100)
08109 return -1;
08110 }
08111 else if((m >= 145) && (m < 148)){
08112 ;
08113 }
08114 return -1;
08115
08116 if(defmode)
08117 *defmode = dflmd;
08118
08119
08120 return 0;
08121 }
08122
08123
08124
08125
08126
08127 static int check_freq_rbi(int m, int d, int *defmode)
08128 {
08129 int dflmd = REM_MODE_FM;
08130
08131 if(m == 50){
08132 if(d < 10100)
08133 return -1;
08134 }
08135 else if((m >= 51) && ( m < 54)){
08136 ;
08137 }
08138 else if(m == 144){
08139 if(d < 10100)
08140 return -1;
08141 }
08142 else if((m >= 145) && (m < 148)){
08143 ;
08144 }
08145 else if((m >= 222) && (m < 225)){
08146 ;
08147 }
08148 else if((m >= 430) && (m < 450)){
08149 ;
08150 }
08151 else if((m >= 1240) && (m < 1300)){
08152 ;
08153 }
08154 else
08155 return -1;
08156
08157 if(defmode)
08158 *defmode = dflmd;
08159
08160
08161 return 0;
08162 }
08163
08164
08165
08166
08167 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08168 {
08169 int dflmd = REM_MODE_FM;
08170
08171 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08172 {
08173
08174 if(m == 144){
08175 if(d < 10100)
08176 return -1;
08177 }
08178 else if((m >= 145) && (m < 148)){
08179 ;
08180 }
08181 else
08182 return -1;
08183 }
08184 else
08185 {
08186 if((m >= 430) && (m < 450)){
08187 ;
08188 }
08189 else
08190 return -1;
08191 }
08192 if(defmode)
08193 *defmode = dflmd;
08194
08195
08196 return 0;
08197 }
08198
08199
08200
08201
08202
08203 static int decimals2int(char *fraction)
08204 {
08205 int i;
08206 char len = strlen(fraction);
08207 int multiplier = 100000;
08208 int res = 0;
08209
08210 if(!len)
08211 return 0;
08212 for( i = 0 ; i < len ; i++, multiplier /= 10)
08213 res += (fraction[i] - '0') * multiplier;
08214 return res;
08215 }
08216
08217
08218
08219
08220
08221
08222 static int split_freq(char *mhz, char *decimals, char *freq)
08223 {
08224 char freq_copy[MAXREMSTR];
08225 char *decp;
08226
08227 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08228 if(decp){
08229 *decp++ = 0;
08230 strncpy(mhz, freq_copy, MAXREMSTR);
08231 strcpy(decimals, "00000");
08232 strncpy(decimals, decp, strlen(decp));
08233 decimals[5] = 0;
08234 return 0;
08235 }
08236 else
08237 return -1;
08238
08239 }
08240
08241
08242
08243
08244
08245 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08246 {
08247 char freq_copy[MAXREMSTR];
08248 char *decp;
08249
08250 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08251 if(decp){
08252 *decp++ = 0;
08253 strncpy(hertz, freq_copy, MAXREMSTR);
08254 strncpy(decimal, decp, strlen(decp));
08255 decimal[strlen(decp)] = '\0';
08256 return 0;
08257 }
08258 else
08259 return -1;
08260 }
08261
08262
08263
08264
08265
08266
08267
08268
08269
08270
08271
08272 static int check_freq_ft897(int m, int d, int *defmode)
08273 {
08274 int dflmd = REM_MODE_FM;
08275
08276 if(m == 1){
08277 dflmd = REM_MODE_LSB;
08278 if(d < 80000)
08279 return -1;
08280 }
08281 else if(m == 3){
08282 dflmd = REM_MODE_LSB;
08283 if(d < 50000)
08284 return -1;
08285 }
08286 else if(m == 7){
08287 dflmd = REM_MODE_LSB;
08288 if(d > 30000)
08289 return -1;
08290 }
08291 else if(m == 14){
08292 dflmd = REM_MODE_USB;
08293 if(d > 35000)
08294 return -1;
08295 }
08296 else if(m == 18){
08297 dflmd = REM_MODE_USB;
08298 if((d < 6800) || (d > 16800))
08299 return -1;
08300 }
08301 else if(m == 21){
08302 dflmd = REM_MODE_USB;
08303 if((d < 20000) || (d > 45000))
08304 return -1;
08305 }
08306 else if(m == 24){
08307 dflmd = REM_MODE_USB;
08308 if((d < 89000) || (d > 99000))
08309 return -1;
08310 }
08311 else if(m == 28){
08312 dflmd = REM_MODE_USB;
08313 }
08314 else if(m == 29){
08315 if(d >= 51000)
08316 dflmd = REM_MODE_FM;
08317 else
08318 dflmd = REM_MODE_USB;
08319 if(d > 70000)
08320 return -1;
08321 }
08322 else if(m == 50){
08323 if(d >= 30000)
08324 dflmd = REM_MODE_FM;
08325 else
08326 dflmd = REM_MODE_USB;
08327
08328 }
08329 else if((m >= 51) && ( m < 54)){
08330 dflmd = REM_MODE_FM;
08331 }
08332 else if(m == 144){
08333 if(d >= 30000)
08334 dflmd = REM_MODE_FM;
08335 else
08336 dflmd = REM_MODE_USB;
08337 }
08338 else if((m >= 145) && (m < 148)){
08339 dflmd = REM_MODE_FM;
08340 }
08341 else if((m >= 430) && (m < 450)){
08342 if(m < 438)
08343 dflmd = REM_MODE_USB;
08344 else
08345 dflmd = REM_MODE_FM;
08346 ;
08347 }
08348 else
08349 return -1;
08350
08351 if(defmode)
08352 *defmode = dflmd;
08353
08354 return 0;
08355 }
08356
08357
08358
08359
08360
08361 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08362 {
08363 unsigned char cmdstr[5];
08364 int fd,m,d;
08365 char mhz[MAXREMSTR];
08366 char decimals[MAXREMSTR];
08367
08368 fd = 0;
08369 if(debug)
08370 printf("New frequency: %s\n",newfreq);
08371
08372 if(split_freq(mhz, decimals, newfreq))
08373 return -1;
08374
08375 m = atoi(mhz);
08376 d = atoi(decimals);
08377
08378
08379
08380 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08381 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08382 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08383 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08384 cmdstr[4] = 0x01;
08385
08386 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08387
08388 }
08389
08390
08391
08392 static int simple_command_ft897(struct rpt *myrpt, char command)
08393 {
08394 unsigned char cmdstr[5];
08395
08396 memset(cmdstr, 0, 5);
08397
08398 cmdstr[4] = command;
08399
08400 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08401
08402 }
08403
08404
08405
08406 static int set_offset_ft897(struct rpt *myrpt, char offset)
08407 {
08408 unsigned char cmdstr[5];
08409
08410 memset(cmdstr, 0, 5);
08411
08412 switch(offset){
08413 case REM_SIMPLEX:
08414 cmdstr[0] = 0x89;
08415 break;
08416
08417 case REM_MINUS:
08418 cmdstr[0] = 0x09;
08419 break;
08420
08421 case REM_PLUS:
08422 cmdstr[0] = 0x49;
08423 break;
08424
08425 default:
08426 return -1;
08427 }
08428
08429 cmdstr[4] = 0x09;
08430
08431 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08432 }
08433
08434
08435
08436 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08437 {
08438 unsigned char cmdstr[5];
08439
08440 memset(cmdstr, 0, 5);
08441
08442 switch(newmode){
08443 case REM_MODE_FM:
08444 cmdstr[0] = 0x08;
08445 break;
08446
08447 case REM_MODE_USB:
08448 cmdstr[0] = 0x01;
08449 break;
08450
08451 case REM_MODE_LSB:
08452 cmdstr[0] = 0x00;
08453 break;
08454
08455 case REM_MODE_AM:
08456 cmdstr[0] = 0x04;
08457 break;
08458
08459 default:
08460 return -1;
08461 }
08462 cmdstr[4] = 0x07;
08463
08464 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08465 }
08466
08467
08468
08469 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08470 {
08471 unsigned char cmdstr[5];
08472
08473 memset(cmdstr, 0, 5);
08474
08475 if(rxplon && txplon)
08476 cmdstr[0] = 0x2A;
08477 else if (!rxplon && txplon)
08478 cmdstr[0] = 0x4A;
08479 else if (rxplon && !txplon)
08480 cmdstr[0] = 0x3A;
08481 else
08482 cmdstr[0] = 0x8A;
08483
08484 cmdstr[4] = 0x0A;
08485
08486 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08487 }
08488
08489
08490
08491
08492 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08493 {
08494 unsigned char cmdstr[5];
08495 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08496 int h,d;
08497
08498 memset(cmdstr, 0, 5);
08499
08500 if(split_ctcss_freq(hertz, decimal, txtone))
08501 return -1;
08502
08503 h = atoi(hertz);
08504 d = atoi(decimal);
08505
08506 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08507 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08508
08509 if(rxtone){
08510
08511 if(split_ctcss_freq(hertz, decimal, rxtone))
08512 return -1;
08513
08514 h = atoi(hertz);
08515 d = atoi(decimal);
08516
08517 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08518 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08519 }
08520 cmdstr[4] = 0x0B;
08521
08522 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08523 }
08524
08525
08526
08527 static int set_ft897(struct rpt *myrpt)
08528 {
08529 int res;
08530
08531 if(debug)
08532 printf("@@@@ lock on\n");
08533
08534 res = simple_command_ft897(myrpt, 0x00);
08535
08536 if(debug)
08537 printf("@@@@ ptt off\n");
08538
08539 if(!res)
08540 res = simple_command_ft897(myrpt, 0x88);
08541
08542 if(debug)
08543 printf("Modulation mode\n");
08544
08545 if(!res)
08546 res = set_mode_ft897(myrpt, myrpt->remmode);
08547
08548 if(debug)
08549 printf("Split off\n");
08550
08551 if(!res)
08552 simple_command_ft897(myrpt, 0x82);
08553
08554 if(debug)
08555 printf("Frequency\n");
08556
08557 if(!res)
08558 res = set_freq_ft897(myrpt, myrpt->freq);
08559 if((myrpt->remmode == REM_MODE_FM)){
08560 if(debug)
08561 printf("Offset\n");
08562 if(!res)
08563 res = set_offset_ft897(myrpt, myrpt->offset);
08564 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08565 if(debug)
08566 printf("CTCSS tone freqs.\n");
08567 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08568 }
08569 if(!res){
08570 if(debug)
08571 printf("CTCSS mode\n");
08572 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08573 }
08574 }
08575 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08576 if(debug)
08577 printf("Clarifier off\n");
08578 simple_command_ft897(myrpt, 0x85);
08579 }
08580 return res;
08581 }
08582
08583 static int closerem_ft897(struct rpt *myrpt)
08584 {
08585 simple_command_ft897(myrpt, 0x88);
08586 return 0;
08587 }
08588
08589
08590
08591
08592
08593
08594
08595 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08596 {
08597 int m,d;
08598 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08599
08600 if(debug)
08601 printf("Before bump: %s\n", myrpt->freq);
08602
08603 if(split_freq(mhz, decimals, myrpt->freq))
08604 return -1;
08605
08606 m = atoi(mhz);
08607 d = atoi(decimals);
08608
08609 d += (interval / 10);
08610 if(d < 0){
08611 m--;
08612 d += 100000;
08613 }
08614 else if(d >= 100000){
08615 m++;
08616 d -= 100000;
08617 }
08618
08619 if(check_freq_ft897(m, d, NULL)){
08620 if(debug)
08621 printf("Bump freq invalid\n");
08622 return -1;
08623 }
08624
08625 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08626
08627 if(debug)
08628 printf("After bump: %s\n", myrpt->freq);
08629
08630 return set_freq_ft897(myrpt, myrpt->freq);
08631 }
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08643 {
08644 int dflmd = REM_MODE_FM;
08645 int rv=0;
08646
08647 if(debug > 6)
08648 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08649
08650
08651
08652 if(m == 1){
08653 dflmd = REM_MODE_LSB;
08654 if(d < 80000)rv=-1;
08655 }
08656 else if(m == 3){
08657 dflmd = REM_MODE_LSB;
08658 if(d < 50000)rv=-1;
08659 }
08660 else if(m == 7){
08661 dflmd = REM_MODE_LSB;
08662 if(d > 30000)rv=-1;
08663 }
08664 else if(m == 14){
08665 dflmd = REM_MODE_USB;
08666 if(d > 35000)rv=-1;
08667 }
08668 else if(m == 18){
08669 dflmd = REM_MODE_USB;
08670 if((d < 6800) || (d > 16800))rv=-1;
08671 }
08672 else if(m == 21){
08673 dflmd = REM_MODE_USB;
08674 if((d < 20000) || (d > 45000))rv=-1;
08675 }
08676 else if(m == 24){
08677 dflmd = REM_MODE_USB;
08678 if((d < 89000) || (d > 99000))rv=-1;
08679 }
08680 else if(m == 28){
08681 dflmd = REM_MODE_USB;
08682 }
08683 else if(m == 29){
08684 if(d >= 51000)
08685 dflmd = REM_MODE_FM;
08686 else
08687 dflmd = REM_MODE_USB;
08688 if(d > 70000)rv=-1;
08689 }
08690 else if(m == 50){
08691 if(d >= 30000)
08692 dflmd = REM_MODE_FM;
08693 else
08694 dflmd = REM_MODE_USB;
08695 }
08696 else if((m >= 51) && ( m < 54)){
08697 dflmd = REM_MODE_FM;
08698 }
08699 else if(m == 144){
08700 if(d >= 30000)
08701 dflmd = REM_MODE_FM;
08702 else
08703 dflmd = REM_MODE_USB;
08704 }
08705 else if((m >= 145) && (m < 148)){
08706 dflmd = REM_MODE_FM;
08707 }
08708 else if((m >= 430) && (m < 450)){
08709 if(m < 438)
08710 dflmd = REM_MODE_USB;
08711 else
08712 dflmd = REM_MODE_FM;
08713 }
08714
08715
08716 if(mars && rv<0){
08717 if((m >= 450) && (m < 470)){
08718 dflmd = REM_MODE_FM;
08719 rv=0;
08720 }
08721 else if((m >= 148) && (m < 174)){
08722 dflmd = REM_MODE_FM;
08723 rv=0;
08724 }
08725 else if((m >= 138) && (m < 144)){
08726 dflmd = REM_MODE_AM;
08727 rv=0;
08728 }
08729 else if((m >= 108) && (m < 138)){
08730 dflmd = REM_MODE_AM;
08731 rv=0;
08732 }
08733 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08734 dflmd = REM_MODE_AM;
08735 rv=0;
08736 }
08737 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08738 dflmd = REM_MODE_AM;
08739 rv=0;
08740 }
08741 }
08742
08743 if(defmode)
08744 *defmode = dflmd;
08745
08746 if(debug > 1)
08747 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08748
08749 return rv;
08750 }
08751
08752
08753 static int ic706_pltocode(char *str)
08754 {
08755 int i;
08756 char *s;
08757 int rv=-1;
08758
08759 s = strchr(str,'.');
08760 i = 0;
08761 if (s) i = atoi(s + 1);
08762 i += atoi(str) * 10;
08763 switch(i)
08764 {
08765 case 670:
08766 rv=0;
08767 case 693:
08768 rv=1;
08769 case 719:
08770 rv=2;
08771 case 744:
08772 rv=3;
08773 case 770:
08774 rv=4;
08775 case 797:
08776 rv=5;
08777 case 825:
08778 rv=6;
08779 case 854:
08780 rv=7;
08781 case 885:
08782 rv=8;
08783 case 915:
08784 rv=9;
08785 case 948:
08786 rv=10;
08787 case 974:
08788 rv=11;
08789 case 1000:
08790 rv=12;
08791 case 1035:
08792 rv=13;
08793 case 1072:
08794 rv=14;
08795 case 1109:
08796 rv=15;
08797 case 1148:
08798 rv=16;
08799 case 1188:
08800 rv=17;
08801 case 1230:
08802 rv=18;
08803 case 1273:
08804 rv=19;
08805 case 1318:
08806 rv=20;
08807 case 1365:
08808 rv=21;
08809 case 1413:
08810 rv=22;
08811 case 1462:
08812 rv=23;
08813 case 1514:
08814 rv=24;
08815 case 1567:
08816 rv=25;
08817 case 1598:
08818 rv=26;
08819 case 1622:
08820 rv=27;
08821 case 1655:
08822 rv=28;
08823 case 1679:
08824 rv=29;
08825 case 1713:
08826 rv=30;
08827 case 1738:
08828 rv=31;
08829 case 1773:
08830 rv=32;
08831 case 1799:
08832 rv=33;
08833 case 1835:
08834 rv=34;
08835 case 1862:
08836 rv=35;
08837 case 1899:
08838 rv=36;
08839 case 1928:
08840 rv=37;
08841 case 1966:
08842 rv=38;
08843 case 1995:
08844 rv=39;
08845 case 2035:
08846 rv=40;
08847 case 2065:
08848 rv=41;
08849 case 2107:
08850 rv=42;
08851 case 2181:
08852 rv=43;
08853 case 2257:
08854 rv=44;
08855 case 2291:
08856 rv=45;
08857 case 2336:
08858 rv=46;
08859 case 2418:
08860 rv=47;
08861 case 2503:
08862 rv=48;
08863 case 2541:
08864 rv=49;
08865 }
08866 if(debug > 1)
08867 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08868
08869 return rv;
08870 }
08871
08872
08873
08874 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08875 {
08876 unsigned char cmdstr[10];
08877
08878 cmdstr[0] = cmdstr[1] = 0xfe;
08879 cmdstr[2] = myrpt->p.civaddr;
08880 cmdstr[3] = 0xe0;
08881 cmdstr[4] = command;
08882 cmdstr[5] = subcommand;
08883 cmdstr[6] = 0xfd;
08884
08885 return(civ_cmd(myrpt,cmdstr,7));
08886 }
08887
08888
08889
08890
08891
08892 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08893 {
08894 unsigned char cmdstr[20];
08895 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08896 int fd,m,d;
08897
08898 fd = 0;
08899 if(debug)
08900 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08901
08902 if(split_freq(mhz, decimals, newfreq))
08903 return -1;
08904
08905 m = atoi(mhz);
08906 d = atoi(decimals);
08907
08908
08909
08910 cmdstr[0] = cmdstr[1] = 0xfe;
08911 cmdstr[2] = myrpt->p.civaddr;
08912 cmdstr[3] = 0xe0;
08913 cmdstr[4] = 5;
08914 cmdstr[5] = ((d % 10) << 4);
08915 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08916 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08917 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08918 cmdstr[9] = (m / 100);
08919 cmdstr[10] = 0xfd;
08920
08921 return(civ_cmd(myrpt,cmdstr,11));
08922 }
08923
08924
08925
08926 static int set_offset_ic706(struct rpt *myrpt, char offset)
08927 {
08928 unsigned char c;
08929
08930 if(debug > 6)
08931 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08932
08933 switch(offset){
08934 case REM_SIMPLEX:
08935 c = 0x10;
08936 break;
08937
08938 case REM_MINUS:
08939 c = 0x11;
08940 break;
08941
08942 case REM_PLUS:
08943 c = 0x12;
08944 break;
08945
08946 default:
08947 return -1;
08948 }
08949
08950 return simple_command_ic706(myrpt,0x0f,c);
08951
08952 }
08953
08954
08955
08956 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08957 {
08958 unsigned char c;
08959
08960 if(debug > 6)
08961 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08962
08963 switch(newmode){
08964 case REM_MODE_FM:
08965 c = 5;
08966 break;
08967
08968 case REM_MODE_USB:
08969 c = 1;
08970 break;
08971
08972 case REM_MODE_LSB:
08973 c = 0;
08974 break;
08975
08976 case REM_MODE_AM:
08977 c = 2;
08978 break;
08979
08980 default:
08981 return -1;
08982 }
08983 return simple_command_ic706(myrpt,6,c);
08984 }
08985
08986
08987
08988 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08989 {
08990 unsigned char cmdstr[10];
08991 int rv;
08992
08993 if(debug > 6)
08994 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
08995
08996 cmdstr[0] = cmdstr[1] = 0xfe;
08997 cmdstr[2] = myrpt->p.civaddr;
08998 cmdstr[3] = 0xe0;
08999 cmdstr[4] = 0x16;
09000 cmdstr[5] = 0x42;
09001 cmdstr[6] = (txplon != 0);
09002 cmdstr[7] = 0xfd;
09003
09004 rv = civ_cmd(myrpt,cmdstr,8);
09005 if (rv) return(-1);
09006
09007 cmdstr[0] = cmdstr[1] = 0xfe;
09008 cmdstr[2] = myrpt->p.civaddr;
09009 cmdstr[3] = 0xe0;
09010 cmdstr[4] = 0x16;
09011 cmdstr[5] = 0x43;
09012 cmdstr[6] = (rxplon != 0);
09013 cmdstr[7] = 0xfd;
09014
09015 return(civ_cmd(myrpt,cmdstr,8));
09016 }
09017
09018 #if 0
09019
09020
09021 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09022 {
09023 unsigned char cmdstr[10];
09024 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09025 int h,d,rv;
09026
09027 memset(cmdstr, 0, 5);
09028
09029 if(debug > 6)
09030 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09031
09032 if(split_ctcss_freq(hertz, decimal, txtone))
09033 return -1;
09034
09035 h = atoi(hertz);
09036 d = atoi(decimal);
09037
09038 cmdstr[0] = cmdstr[1] = 0xfe;
09039 cmdstr[2] = myrpt->p.civaddr;
09040 cmdstr[3] = 0xe0;
09041 cmdstr[4] = 0x1b;
09042 cmdstr[5] = 0;
09043 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09044 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09045 cmdstr[8] = 0xfd;
09046
09047 rv = civ_cmd(myrpt,cmdstr,9);
09048 if (rv) return(-1);
09049
09050 if (!rxtone) return(0);
09051
09052 if(split_ctcss_freq(hertz, decimal, rxtone))
09053 return -1;
09054
09055 h = atoi(hertz);
09056 d = atoi(decimal);
09057
09058 cmdstr[0] = cmdstr[1] = 0xfe;
09059 cmdstr[2] = myrpt->p.civaddr;
09060 cmdstr[3] = 0xe0;
09061 cmdstr[4] = 0x1b;
09062 cmdstr[5] = 1;
09063 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09064 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09065 cmdstr[8] = 0xfd;
09066 return(civ_cmd(myrpt,cmdstr,9));
09067 }
09068 #endif
09069
09070 static int vfo_ic706(struct rpt *myrpt)
09071 {
09072 unsigned char cmdstr[10];
09073
09074 cmdstr[0] = cmdstr[1] = 0xfe;
09075 cmdstr[2] = myrpt->p.civaddr;
09076 cmdstr[3] = 0xe0;
09077 cmdstr[4] = 7;
09078 cmdstr[5] = 0xfd;
09079
09080 return(civ_cmd(myrpt,cmdstr,6));
09081 }
09082
09083 static int mem2vfo_ic706(struct rpt *myrpt)
09084 {
09085 unsigned char cmdstr[10];
09086
09087 cmdstr[0] = cmdstr[1] = 0xfe;
09088 cmdstr[2] = myrpt->p.civaddr;
09089 cmdstr[3] = 0xe0;
09090 cmdstr[4] = 0x0a;
09091 cmdstr[5] = 0xfd;
09092
09093 return(civ_cmd(myrpt,cmdstr,6));
09094 }
09095
09096 static int select_mem_ic706(struct rpt *myrpt, int slot)
09097 {
09098 unsigned char cmdstr[10];
09099
09100 cmdstr[0] = cmdstr[1] = 0xfe;
09101 cmdstr[2] = myrpt->p.civaddr;
09102 cmdstr[3] = 0xe0;
09103 cmdstr[4] = 8;
09104 cmdstr[5] = 0;
09105 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09106 cmdstr[7] = 0xfd;
09107
09108 return(civ_cmd(myrpt,cmdstr,8));
09109 }
09110
09111 static int set_ic706(struct rpt *myrpt)
09112 {
09113 int res = 0,i;
09114
09115 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09116
09117 if (!res)
09118 res = simple_command_ic706(myrpt,7,0);
09119
09120 if((myrpt->remmode == REM_MODE_FM))
09121 {
09122 i = ic706_pltocode(myrpt->rxpl);
09123 if (i == -1) return -1;
09124 if(debug)
09125 printf("Select memory number\n");
09126 if (!res)
09127 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09128 if(debug)
09129 printf("Transfer memory to VFO\n");
09130 if (!res)
09131 res = mem2vfo_ic706(myrpt);
09132 }
09133
09134 if(debug)
09135 printf("Set to VFO\n");
09136
09137 if (!res)
09138 res = vfo_ic706(myrpt);
09139
09140 if(debug)
09141 printf("Modulation mode\n");
09142
09143 if (!res)
09144 res = set_mode_ic706(myrpt, myrpt->remmode);
09145
09146 if(debug)
09147 printf("Split off\n");
09148
09149 if(!res)
09150 simple_command_ic706(myrpt, 0x82,0);
09151
09152 if(debug)
09153 printf("Frequency\n");
09154
09155 if(!res)
09156 res = set_freq_ic706(myrpt, myrpt->freq);
09157 if((myrpt->remmode == REM_MODE_FM)){
09158 if(debug)
09159 printf("Offset\n");
09160 if(!res)
09161 res = set_offset_ic706(myrpt, myrpt->offset);
09162 if(!res){
09163 if(debug)
09164 printf("CTCSS mode\n");
09165 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09166 }
09167 }
09168 return res;
09169 }
09170
09171
09172
09173
09174
09175
09176
09177 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09178 {
09179 int m,d;
09180 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09181 unsigned char cmdstr[20];
09182
09183 if(debug)
09184 printf("Before bump: %s\n", myrpt->freq);
09185
09186 if(split_freq(mhz, decimals, myrpt->freq))
09187 return -1;
09188
09189 m = atoi(mhz);
09190 d = atoi(decimals);
09191
09192 d += (interval / 10);
09193 if(d < 0){
09194 m--;
09195 d += 100000;
09196 }
09197 else if(d >= 100000){
09198 m++;
09199 d -= 100000;
09200 }
09201
09202 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09203 if(debug)
09204 printf("Bump freq invalid\n");
09205 return -1;
09206 }
09207
09208 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09209
09210 if(debug)
09211 printf("After bump: %s\n", myrpt->freq);
09212
09213
09214
09215 cmdstr[0] = cmdstr[1] = 0xfe;
09216 cmdstr[2] = myrpt->p.civaddr;
09217 cmdstr[3] = 0xe0;
09218 cmdstr[4] = 0;
09219 cmdstr[5] = ((d % 10) << 4);
09220 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09221 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09222 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09223 cmdstr[9] = (m / 100);
09224 cmdstr[10] = 0xfd;
09225
09226 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09227 }
09228
09229
09230
09231
09232
09233
09234 static int setrem(struct rpt *myrpt)
09235 {
09236 char str[300];
09237 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09238 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09239 char *modes[] = {"FM","USB","LSB","AM"};
09240 int res = -1;
09241
09242 #if 0
09243 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09244 modes[(int)myrpt->remmode],
09245 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09246 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09247 myrpt->rxplon);
09248 #endif
09249 if (myrpt->p.archivedir)
09250 {
09251 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09252 modes[(int)myrpt->remmode],
09253 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09254 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09255 myrpt->rxplon);
09256 donodelog(myrpt,str);
09257 }
09258 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09259 {
09260 rpt_telemetry(myrpt,SETREMOTE,NULL);
09261 res = 0;
09262 }
09263 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09264 {
09265 rpt_telemetry(myrpt,SETREMOTE,NULL);
09266 res = 0;
09267 }
09268 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09269 {
09270 rpt_telemetry(myrpt,SETREMOTE,NULL);
09271 res = 0;
09272 }
09273 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09274 {
09275 res = setrbi_check(myrpt);
09276 if (!res)
09277 {
09278 rpt_telemetry(myrpt,SETREMOTE,NULL);
09279 res = 0;
09280 }
09281 }
09282 else if(ISRIG_RTX(myrpt->remoterig))
09283 {
09284 setrtx(myrpt);
09285 res = 0;
09286 }
09287 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09288 rpt_telemetry(myrpt,SETREMOTE,NULL);
09289 res = 0;
09290 }
09291 else
09292 res = 0;
09293
09294 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09295
09296 return res;
09297 }
09298
09299 static int closerem(struct rpt *myrpt)
09300 {
09301 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09302 return closerem_ft897(myrpt);
09303 else
09304 return 0;
09305 }
09306
09307
09308
09309
09310
09311 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09312 {
09313 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09314 return check_freq_ft897(m, d, defmode);
09315 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09316 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09317 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09318 return check_freq_rbi(m, d, defmode);
09319 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09320 return check_freq_kenwood(m, d, defmode);
09321 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09322 return check_freq_tm271(m, d, defmode);
09323 else if(ISRIG_RTX(myrpt->remoterig))
09324 return check_freq_rtx(m, d, defmode, myrpt);
09325 else
09326 return -1;
09327 }
09328
09329
09330
09331
09332
09333
09334 static char check_tx_freq(struct rpt *myrpt)
09335 {
09336 int i,rv=0;
09337 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09338 char radio_mhz_char[MAXREMSTR];
09339 char radio_decimals_char[MAXREMSTR];
09340 char limit_mhz_char[MAXREMSTR];
09341 char limit_decimals_char[MAXREMSTR];
09342 char limits[256];
09343 char *limit_ranges[40];
09344 struct ast_variable *limitlist;
09345
09346 if(debug > 3){
09347 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09348 }
09349
09350
09351
09352 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09353 if(debug > 3){
09354 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09355 }
09356 rv=1;
09357 return 1;
09358 }
09359
09360
09361 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09362
09363 if(!limitlist){
09364 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09365 rv=0;
09366 return 0;
09367 }
09368
09369 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09370 radio_mhz = atoi(radio_mhz_char);
09371 radio_decimals = decimals2int(radio_decimals_char);
09372
09373 if(debug > 3){
09374 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09375 }
09376
09377
09378
09379 for(;limitlist; limitlist=limitlist->next){
09380 if(!strcmp(limitlist->name, myrpt->loginlevel))
09381 break;
09382 }
09383
09384 if(!limitlist){
09385 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09386 rv=0;
09387 return 0;
09388 }
09389
09390 if(debug > 3){
09391 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09392 }
09393
09394
09395
09396 strncpy(limits, limitlist->value, 256);
09397 limits[255] = 0;
09398 finddelim(limits, limit_ranges, 40);
09399 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09400 char range[40];
09401 char *r,*s;
09402 strncpy(range, limit_ranges[i], 40);
09403 range[39] = 0;
09404 if(debug > 3)
09405 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09406
09407 r = strchr(range, '-');
09408 if(!r){
09409 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09410 rv=0;
09411 break;
09412 }
09413 *r++ = 0;
09414 s = eatwhite(range);
09415 r = eatwhite(r);
09416 split_freq(limit_mhz_char, limit_decimals_char, s);
09417 llimit_mhz = atoi(limit_mhz_char);
09418 llimit_decimals = decimals2int(limit_decimals_char);
09419 split_freq(limit_mhz_char, limit_decimals_char, r);
09420 ulimit_mhz = atoi(limit_mhz_char);
09421 ulimit_decimals = decimals2int(limit_decimals_char);
09422
09423 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09424 if(radio_mhz == llimit_mhz){
09425 if(radio_decimals >= llimit_decimals){
09426 if(llimit_mhz == ulimit_mhz){
09427 if(radio_decimals <= ulimit_decimals){
09428 rv=1;
09429 break;
09430 }
09431 else{
09432 if(debug > 3)
09433 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09434 rv=0;
09435 break;
09436 }
09437 }
09438 else{
09439 rv=1;
09440 break;
09441 }
09442 }
09443 else{
09444 if(debug > 3)
09445 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09446 rv=0;
09447 break;
09448 }
09449 }
09450 else if(radio_mhz == ulimit_mhz){
09451 if(radio_decimals <= ulimit_decimals){
09452 if(debug > 3)
09453 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09454 rv=1;
09455 break;
09456 }
09457 else{
09458 if(debug > 3)
09459 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09460 rv=0;
09461 break;
09462 }
09463 }
09464 else
09465 if(debug > 3)
09466 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09467 rv=1;
09468 break;
09469 }
09470 }
09471 if(debug > 3)
09472 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09473
09474 return rv;
09475 }
09476
09477
09478
09479
09480
09481
09482 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09483 {
09484 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09485 return multimode_bump_freq_ft897(myrpt, interval);
09486 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09487 return multimode_bump_freq_ic706(myrpt, interval);
09488 else
09489 return -1;
09490 }
09491
09492
09493
09494
09495
09496
09497 static void stop_scan(struct rpt *myrpt)
09498 {
09499 myrpt->hfscanstop = 1;
09500 rpt_telemetry(myrpt,SCAN,0);
09501 }
09502
09503
09504
09505
09506
09507
09508 static int service_scan(struct rpt *myrpt)
09509 {
09510 int res, interval;
09511 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09512
09513 switch(myrpt->hfscanmode){
09514
09515 case HF_SCAN_DOWN_SLOW:
09516 interval = -10;
09517 break;
09518
09519 case HF_SCAN_DOWN_QUICK:
09520 interval = -50;
09521 break;
09522
09523 case HF_SCAN_DOWN_FAST:
09524 interval = -200;
09525 break;
09526
09527 case HF_SCAN_UP_SLOW:
09528 interval = 10;
09529 break;
09530
09531 case HF_SCAN_UP_QUICK:
09532 interval = 50;
09533 break;
09534
09535 case HF_SCAN_UP_FAST:
09536 interval = 200;
09537 break;
09538
09539 default:
09540 myrpt->hfscanmode = 0;
09541 return -1;
09542 }
09543
09544 res = split_freq(mhz, decimals, myrpt->freq);
09545
09546 if(!res){
09547 k100 =decimals[0];
09548 k10 = decimals[1];
09549 res = multimode_bump_freq(myrpt, interval);
09550 }
09551
09552 if(!res)
09553 res = split_freq(mhz, decimals, myrpt->freq);
09554
09555
09556 if(res){
09557 myrpt->hfscanmode = 0;
09558 myrpt->hfscanstatus = -2;
09559 return -1;
09560 }
09561
09562
09563 if(k10 != decimals[1]){
09564 int myhund = (interval < 0) ? k100 : decimals[0];
09565 int myten = (interval < 0) ? k10 : decimals[1];
09566 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09567 } else myrpt->hfscanstatus = 0;
09568 return res;
09569
09570 }
09571
09572
09573
09574 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09575 {
09576 int res=0;
09577 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09578 res = retreive_memory(myrpt, digitbuf);
09579 if(!res)res=setrem(myrpt);
09580 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09581 return res;
09582 }
09583
09584
09585
09586
09587 static int channel_steer(struct rpt *myrpt, char *data)
09588 {
09589 int res=0;
09590
09591 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09592 if (!myrpt->remoterig) return(0);
09593 if(data<=0)
09594 {
09595 res=-1;
09596 }
09597 else
09598 {
09599 myrpt->nowchan=strtod(data,NULL);
09600 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09601 {
09602 char string[16];
09603 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09604 send_usb_txt(myrpt,string);
09605 }
09606 else
09607 {
09608 if(get_mem_set(myrpt, data))res=-1;
09609 }
09610 }
09611 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09612 return res;
09613 }
09614
09615
09616 static int channel_revert(struct rpt *myrpt)
09617 {
09618 int res=0;
09619 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09620 if (!myrpt->remoterig) return(0);
09621 if(myrpt->nowchan!=myrpt->waschan)
09622 {
09623 char data[8];
09624 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09625 sprintf(data,"%02d",myrpt->waschan);
09626 myrpt->nowchan=myrpt->waschan;
09627 channel_steer(myrpt,data);
09628 res=1;
09629 }
09630 return(res);
09631 }
09632
09633
09634
09635
09636 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09637 {
09638 char *s,*s1,*s2;
09639 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09640 intptr_t p;
09641 char multimode = 0;
09642 char oc,*cp,*cp1,*cp2;
09643 char tmp[20], freq[20] = "", savestr[20] = "";
09644 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09645
09646 if(debug > 6) {
09647 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09648 }
09649
09650 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09651 return DC_ERROR;
09652
09653 p = myatoi(param);
09654
09655 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09656 (!myrpt->loginlevel[0])) return DC_ERROR;
09657 multimode = multimode_capable(myrpt);
09658
09659 switch(p){
09660
09661 case 1:
09662 if(strlen(digitbuf) < 2)
09663 break;
09664
09665 for(i = 0 ; i < 2 ; i++){
09666 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09667 return DC_ERROR;
09668 }
09669 r=get_mem_set(myrpt, digitbuf);
09670 if (r < 0){
09671 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09672 return DC_COMPLETE;
09673 }
09674 else if (r > 0){
09675 return DC_ERROR;
09676 }
09677 return DC_COMPLETE;
09678
09679 case 2:
09680
09681
09682 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09683 if(digitbuf[i] == '*'){
09684 j++;
09685 continue;
09686 }
09687 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09688 goto invalid_freq;
09689 else{
09690 if(j == 0)
09691 l++;
09692 if(j == 1)
09693 k++;
09694 }
09695 }
09696
09697 i = strlen(digitbuf) - 1;
09698 if(multimode){
09699 if((j > 2) || (l > 3) || (k > 6))
09700 goto invalid_freq;
09701 }
09702 else{
09703 if((j > 2) || (l > 4) || (k > 3))
09704 goto invalid_freq;
09705 }
09706
09707
09708
09709 if(j < 2)
09710 break;
09711
09712
09713
09714 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09715
09716 s = tmp;
09717 s1 = strsep(&s, "*");
09718 s2 = strsep(&s,"*");
09719 ls2 = strlen(s2);
09720
09721 switch(ls2){
09722 case 1:
09723 ht = 0;
09724 k = 100 * atoi(s2);
09725 break;
09726
09727 case 2:
09728 ht = 0;
09729 k = 10 * atoi(s2);
09730 break;
09731
09732 case 3:
09733 if(!multimode){
09734 if((s2[2] != '0')&&(s2[2] != '5'))
09735 goto invalid_freq;
09736 }
09737 ht = 0;
09738 k = atoi(s2);
09739 break;
09740 case 4:
09741 k = atoi(s2)/10;
09742 ht = 10 * (atoi(s2+(ls2-1)));
09743 break;
09744
09745 case 5:
09746 k = atoi(s2)/100;
09747 ht = (atoi(s2+(ls2-2)));
09748 break;
09749
09750 default:
09751 goto invalid_freq;
09752 }
09753
09754
09755
09756 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09757
09758 if(debug)
09759 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09760
09761 split_freq(mhz, decimals, freq);
09762 m = atoi(mhz);
09763 d = atoi(decimals);
09764
09765 if(check_freq(myrpt, m, d, &defmode))
09766 goto invalid_freq;
09767
09768
09769 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09770 break;
09771
09772
09773 offset = REM_SIMPLEX;
09774
09775 if(defmode == REM_MODE_FM){
09776 oc = *s;
09777
09778 if (oc){
09779 switch(oc){
09780 case '1':
09781 offset = REM_MINUS;
09782 break;
09783
09784 case '2':
09785 offset = REM_SIMPLEX;
09786 break;
09787
09788 case '3':
09789 offset = REM_PLUS;
09790 break;
09791
09792 default:
09793 goto invalid_freq;
09794 }
09795 }
09796 }
09797 offsave = myrpt->offset;
09798 modesave = myrpt->remmode;
09799 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09800 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09801 myrpt->offset = offset;
09802 myrpt->remmode = defmode;
09803
09804 if (setrem(myrpt) == -1){
09805 myrpt->offset = offsave;
09806 myrpt->remmode = modesave;
09807 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09808 goto invalid_freq;
09809 }
09810
09811 return DC_COMPLETE;
09812
09813 invalid_freq:
09814 rpt_telemetry(myrpt,INVFREQ,NULL);
09815 return DC_ERROR;
09816
09817 case 3:
09818 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09819 if(digitbuf[i] == '*'){
09820 j++;
09821 continue;
09822 }
09823 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09824 return DC_ERROR;
09825 else{
09826 if(j)
09827 l++;
09828 else
09829 k++;
09830 }
09831 }
09832 if((j > 1) || (k > 3) || (l > 1))
09833 return DC_ERROR;
09834 i = strlen(digitbuf) - 1;
09835 if((j != 1) || (k < 2)|| (l != 1))
09836 break;
09837 if(debug)
09838 printf("PL digits entered %s\n", digitbuf);
09839
09840 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09841
09842 s = strchr(tmp,'*');
09843 if(s)
09844 *s = '.';
09845 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09846 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09847 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09848 {
09849 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09850 }
09851 if (setrem(myrpt) == -1){
09852 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09853 return DC_ERROR;
09854 }
09855 return DC_COMPLETE;
09856
09857 case 4:
09858
09859 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09860 return DC_ERROR;
09861
09862
09863
09864
09865
09866 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09867 {
09868 if(debug)
09869 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09870 return DC_ERROR;
09871 }
09872 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09873 if(digitbuf[i] == '*'){
09874 j++;
09875 continue;
09876 }
09877 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09878 return DC_ERROR;
09879 else{
09880 if(j)
09881 l++;
09882 else
09883 k++;
09884 }
09885 }
09886 if((j > 1) || (k > 3) || (l > 1))
09887 return DC_ERROR;
09888 i = strlen(digitbuf) - 1;
09889 if((j != 1) || (k < 2)|| (l != 1))
09890 break;
09891 if(debug)
09892 printf("PL digits entered %s\n", digitbuf);
09893
09894 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09895
09896 s = strchr(tmp,'*');
09897 if(s)
09898 *s = '.';
09899 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09900 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09901
09902 if (setrem(myrpt) == -1){
09903 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09904 return DC_ERROR;
09905 }
09906 return DC_COMPLETE;
09907
09908
09909 case 6:
09910 if(strlen(digitbuf) < 1)
09911 break;
09912
09913 if(!multimode)
09914 return DC_ERROR;
09915
09916 switch(*digitbuf){
09917 case '1':
09918 split_freq(mhz, decimals, myrpt->freq);
09919 m=atoi(mhz);
09920 if(m < 29)
09921 return DC_ERROR;
09922 myrpt->remmode = REM_MODE_FM;
09923
09924 rpt_telemetry(myrpt,REMMODE,NULL);
09925 break;
09926
09927 case '2':
09928 myrpt->remmode = REM_MODE_USB;
09929 rpt_telemetry(myrpt,REMMODE,NULL);
09930 break;
09931
09932 case '3':
09933 myrpt->remmode = REM_MODE_LSB;
09934 rpt_telemetry(myrpt,REMMODE,NULL);
09935 break;
09936
09937 case '4':
09938 myrpt->remmode = REM_MODE_AM;
09939 rpt_telemetry(myrpt,REMMODE,NULL);
09940 break;
09941
09942 default:
09943 return DC_ERROR;
09944 }
09945
09946 if(setrem(myrpt))
09947 return DC_ERROR;
09948 return DC_COMPLETEQUIET;
09949 case 99:
09950
09951 if (myrpt->loginlevel[0])
09952 return DC_ERROR;
09953 *myrpt->loginuser = 0;
09954 myrpt->loginlevel[0] = 0;
09955 cp = ast_strdup(param);
09956 cp1 = strchr(cp,',');
09957 ast_mutex_lock(&myrpt->lock);
09958 if (cp1)
09959 {
09960 *cp1 = 0;
09961 cp2 = strchr(cp1 + 1,',');
09962 if (cp2)
09963 {
09964 *cp2 = 0;
09965 strncpy(myrpt->loginlevel,cp2 + 1,
09966 sizeof(myrpt->loginlevel) - 1);
09967 }
09968 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09969 ast_mutex_unlock(&myrpt->lock);
09970 if (myrpt->p.archivedir)
09971 {
09972 char str[100];
09973
09974 sprintf(str,"LOGIN,%s,%s",
09975 myrpt->loginuser,myrpt->loginlevel);
09976 donodelog(myrpt,str);
09977 }
09978 if (debug)
09979 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09980 rpt_telemetry(myrpt,REMLOGIN,NULL);
09981 }
09982 ast_free(cp);
09983 return DC_COMPLETEQUIET;
09984 case 100:
09985 myrpt->rxplon = 0;
09986 setrem(myrpt);
09987 rpt_telemetry(myrpt,REMXXX,(void *)p);
09988 return DC_COMPLETEQUIET;
09989 case 101:
09990 myrpt->rxplon = 1;
09991 setrem(myrpt);
09992 rpt_telemetry(myrpt,REMXXX,(void *)p);
09993 return DC_COMPLETEQUIET;
09994 case 102:
09995 myrpt->txplon = 0;
09996 setrem(myrpt);
09997 rpt_telemetry(myrpt,REMXXX,(void *)p);
09998 return DC_COMPLETEQUIET;
09999 case 103:
10000 myrpt->txplon = 1;
10001 setrem(myrpt);
10002 rpt_telemetry(myrpt,REMXXX,(void *)p);
10003 return DC_COMPLETEQUIET;
10004 case 104:
10005 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10006 return DC_ERROR;
10007 myrpt->powerlevel = REM_LOWPWR;
10008 setrem(myrpt);
10009 rpt_telemetry(myrpt,REMXXX,(void *)p);
10010 return DC_COMPLETEQUIET;
10011 case 105:
10012 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10013 return DC_ERROR;
10014 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10015 myrpt->powerlevel = REM_MEDPWR;
10016 setrem(myrpt);
10017 rpt_telemetry(myrpt,REMXXX,(void *)p);
10018 return DC_COMPLETEQUIET;
10019 case 106:
10020 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10021 return DC_ERROR;
10022 myrpt->powerlevel = REM_HIPWR;
10023 setrem(myrpt);
10024 rpt_telemetry(myrpt,REMXXX,(void *)p);
10025 return DC_COMPLETEQUIET;
10026 case 107:
10027 multimode_bump_freq(myrpt, -20);
10028 return DC_COMPLETE;
10029 case 108:
10030 multimode_bump_freq(myrpt, -100);
10031 return DC_COMPLETE;
10032 case 109:
10033 multimode_bump_freq(myrpt, -500);
10034 return DC_COMPLETE;
10035 case 110:
10036 multimode_bump_freq(myrpt, 20);
10037 return DC_COMPLETE;
10038 case 111:
10039 multimode_bump_freq(myrpt, 100);
10040 return DC_COMPLETE;
10041 case 112:
10042 multimode_bump_freq(myrpt, 500);
10043 return DC_COMPLETE;
10044 case 113:
10045 myrpt->scantimer = REM_SCANTIME;
10046 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10047 rpt_telemetry(myrpt,REMXXX,(void *)p);
10048 return DC_COMPLETEQUIET;
10049 case 114:
10050 myrpt->scantimer = REM_SCANTIME;
10051 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10052 rpt_telemetry(myrpt,REMXXX,(void *)p);
10053 return DC_COMPLETEQUIET;
10054 case 115:
10055 myrpt->scantimer = REM_SCANTIME;
10056 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10057 rpt_telemetry(myrpt,REMXXX,(void *)p);
10058 return DC_COMPLETEQUIET;
10059 case 116:
10060 myrpt->scantimer = REM_SCANTIME;
10061 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10062 rpt_telemetry(myrpt,REMXXX,(void *)p);
10063 return DC_COMPLETEQUIET;
10064 case 117:
10065 myrpt->scantimer = REM_SCANTIME;
10066 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10067 rpt_telemetry(myrpt,REMXXX,(void *)p);
10068 return DC_COMPLETEQUIET;
10069 case 118:
10070 myrpt->scantimer = REM_SCANTIME;
10071 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10072 rpt_telemetry(myrpt,REMXXX,(void *)p);
10073 return DC_COMPLETEQUIET;
10074 case 119:
10075 if(debug > 3)
10076 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10077
10078 if((!myrpt->tunerequest) &&
10079 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10080 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10081 myrpt->remotetx = 0;
10082 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10083 myrpt->tunerequest = 1;
10084 rpt_telemetry(myrpt,TUNE,NULL);
10085 return DC_COMPLETEQUIET;
10086 }
10087 return DC_ERROR;
10088 case 5:
10089 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10090 return DC_COMPLETEQUIET;
10091 case 140:
10092 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10093 return DC_COMPLETEQUIET;
10094 case 200:
10095 case 201:
10096 case 202:
10097 case 203:
10098 case 204:
10099 case 205:
10100 case 206:
10101 case 207:
10102 case 208:
10103 case 209:
10104 case 210:
10105 case 211:
10106 case 212:
10107 case 213:
10108 case 214:
10109 case 215:
10110 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10111 return DC_COMPLETEQUIET;
10112 default:
10113 break;
10114 }
10115 return DC_INDETERMINATE;
10116 }
10117
10118
10119 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10120 {
10121 time_t now;
10122 int ret,res = 0,src;
10123
10124 if(debug > 6)
10125 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10126
10127 time(&myrpt->last_activity_time);
10128
10129 if(myrpt->hfscanmode){
10130 stop_scan(myrpt);
10131 return 0;
10132 }
10133
10134 time(&now);
10135
10136 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10137 {
10138 myrpt->dtmfidx = -1;
10139 myrpt->dtmfbuf[0] = 0;
10140 myrpt->dtmf_time_rem = 0;
10141 }
10142
10143 if (myrpt->dtmfidx == -1)
10144 {
10145
10146 if (c != myrpt->p.funcchar)
10147 {
10148 if (!myrpt->p.propagate_dtmf)
10149 {
10150 rpt_mutex_lock(&myrpt->lock);
10151 do_dtmf_local(myrpt,c);
10152 rpt_mutex_unlock(&myrpt->lock);
10153 }
10154 return 0;
10155 }
10156 myrpt->dtmfidx = 0;
10157 myrpt->dtmfbuf[0] = 0;
10158 myrpt->dtmf_time_rem = now;
10159 return 0;
10160 }
10161
10162 if (myrpt->dtmfidx >= MAXDTMF)
10163 {
10164 myrpt->dtmfidx = 0;
10165 myrpt->dtmfbuf[0] = 0;
10166 myrpt->dtmf_time_rem = now;
10167 }
10168 if (c == myrpt->p.funcchar)
10169 {
10170
10171 if ((myrpt->dtmfidx < 1) ||
10172 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10173 {
10174 myrpt->dtmfidx = 0;
10175 myrpt->dtmfbuf[0] = 0;
10176 myrpt->dtmf_time_rem = now;
10177 return 0;
10178 }
10179 }
10180 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10181 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10182 myrpt->dtmf_time_rem = now;
10183
10184
10185 src = SOURCE_RMT;
10186 if (phonemode == 2) src = SOURCE_DPHONE;
10187 else if (phonemode) src = SOURCE_PHONE;
10188 else if (phonemode == 4) src = SOURCE_ALT;
10189 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10190
10191 switch(ret){
10192
10193 case DC_INDETERMINATE:
10194 res = 0;
10195 break;
10196
10197 case DC_DOKEY:
10198 if (keyed) *keyed = 1;
10199 res = 0;
10200 break;
10201
10202 case DC_REQ_FLUSH:
10203 myrpt->dtmfidx = 0;
10204 myrpt->dtmfbuf[0] = 0;
10205 res = 0;
10206 break;
10207
10208
10209 case DC_COMPLETE:
10210 res = 1;
10211 case DC_COMPLETEQUIET:
10212 myrpt->totalexecdcommands++;
10213 myrpt->dailyexecdcommands++;
10214 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10215 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10216 myrpt->dtmfbuf[0] = 0;
10217 myrpt->dtmfidx = -1;
10218 myrpt->dtmf_time_rem = 0;
10219 break;
10220
10221 case DC_ERROR:
10222 default:
10223 myrpt->dtmfbuf[0] = 0;
10224 myrpt->dtmfidx = -1;
10225 myrpt->dtmf_time_rem = 0;
10226 res = 0;
10227 break;
10228 }
10229
10230 return res;
10231 }
10232
10233 static int handle_remote_data(struct rpt *myrpt, char *str)
10234 {
10235
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
10253
10254 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10255 {
10256 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10257 return 0;
10258 }
10259 mdc1200_notify(myrpt,src,seq);
10260 return 0;
10261 }
10262 #endif
10263
10264
10265 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10266 {
10267 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10268 return 0;
10269 }
10270 if (strcmp(cmd,"D"))
10271 {
10272 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10273 return 0;
10274 }
10275
10276 if (strcmp(dest,myrpt->name)) return 0;
10277 if (myrpt->p.archivedir)
10278 {
10279 char dtmfstr[100];
10280
10281 sprintf(dtmfstr,"DTMF,%c",c);
10282 donodelog(myrpt,dtmfstr);
10283 }
10284 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10285 if (!c) return(0);
10286 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10287 if (res != 1)
10288 return res;
10289 rpt_telemetry(myrpt,COMPLETE,NULL);
10290 return 0;
10291 }
10292
10293 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10294 {
10295 int res;
10296
10297
10298 if(phonemode == 3)
10299 {
10300 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10301 {
10302 *keyed = 0;
10303 return 0;
10304 }
10305 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10306 {
10307 *keyed = 1;
10308 return 0;
10309 }
10310 }
10311 else
10312 {
10313
10314 if (keyed && *keyed && (c == myrpt->p.endchar))
10315 {
10316 *keyed = 0;
10317 return DC_INDETERMINATE;
10318 }
10319 }
10320 if (myrpt->p.archivedir)
10321 {
10322 char str[100];
10323
10324 sprintf(str,"DTMF(P),%c",c);
10325 donodelog(myrpt,str);
10326 }
10327 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10328 if (res != 1)
10329 return res;
10330 rpt_telemetry(myrpt,COMPLETE,NULL);
10331 return 0;
10332 }
10333
10334 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10335 {
10336 char *val, *s, *s1, *s2, *tele;
10337 char tmp[300], deststr[300] = "";
10338 char sx[320],*sy;
10339
10340
10341 val = node_lookup(myrpt,l->name);
10342 if (!val)
10343 {
10344 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10345 return -1;
10346 }
10347
10348 rpt_mutex_lock(&myrpt->lock);
10349
10350 remque((struct qelem *) l);
10351 rpt_mutex_unlock(&myrpt->lock);
10352 strncpy(tmp,val,sizeof(tmp) - 1);
10353 s = tmp;
10354 s1 = strsep(&s,",");
10355 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10356 {
10357 sy = strchr(s1,'/');
10358 *sy = 0;
10359 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10360 s1 = sx;
10361 }
10362 s2 = strsep(&s,",");
10363 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10364 tele = strchr(deststr, '/');
10365 if (!tele) {
10366 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10367 return -1;
10368 }
10369 *tele++ = 0;
10370 l->elaptime = 0;
10371 l->connecttime = 0;
10372 l->thisconnected = 0;
10373 l->newkey = 0;
10374 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
10375 if (l->chan){
10376 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10377 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10378 #ifndef NEW_ASTERISK
10379 l->chan->whentohangup = 0;
10380 #endif
10381 l->chan->appl = "Apprpt";
10382 l->chan->data = "(Remote Rx)";
10383 if (option_verbose > 2)
10384 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10385 deststr, tele, l->chan->name);
10386 if(l->chan->cid.cid_num)
10387 ast_free(l->chan->cid.cid_num);
10388 l->chan->cid.cid_num = ast_strdup(myrpt->name);
10389 ast_call(l->chan,tele,999);
10390
10391 }
10392 else
10393 {
10394 if (option_verbose > 2)
10395 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10396 deststr,tele,l->chan->name);
10397 return -1;
10398 }
10399 rpt_mutex_lock(&myrpt->lock);
10400
10401 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10402 rpt_mutex_unlock(&myrpt->lock);
10403 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10404 if (!l->phonemode) send_newkey(l->chan);
10405 return 0;
10406 }
10407
10408
10409 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10410 {
10411 int res;
10412 pthread_attr_t attr;
10413 char cmd[MAXDTMF+1] = "",c;
10414
10415
10416 c = c_in & 0x7f;
10417 if (myrpt->p.archivedir)
10418 {
10419 char str[100];
10420
10421 sprintf(str,"DTMF,MAIN,%c",c);
10422 donodelog(myrpt,str);
10423 }
10424 if (c == myrpt->p.endchar)
10425 {
10426
10427 if (myrpt->p.simple && myrpt->callmode)
10428 {
10429 if(debug)
10430 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10431 rpt_mutex_lock(&myrpt->lock);
10432 myrpt->callmode = 0;
10433 myrpt->macropatch=0;
10434 channel_revert(myrpt);
10435 rpt_mutex_unlock(&myrpt->lock);
10436 rpt_telemetry(myrpt,TERM,NULL);
10437 return;
10438 }
10439 rpt_mutex_lock(&myrpt->lock);
10440 myrpt->stopgen = 1;
10441 if (myrpt->cmdnode[0])
10442 {
10443 myrpt->cmdnode[0] = 0;
10444 myrpt->dtmfidx = -1;
10445 myrpt->dtmfbuf[0] = 0;
10446 rpt_mutex_unlock(&myrpt->lock);
10447 rpt_telemetry(myrpt,COMPLETE,NULL);
10448 return;
10449 }
10450 else if(!myrpt->inpadtest)
10451 {
10452 rpt_mutex_unlock(&myrpt->lock);
10453 if (myrpt->p.propagate_phonedtmf)
10454 do_dtmf_phone(myrpt,NULL,c);
10455 return;
10456 }
10457 else
10458 rpt_mutex_unlock(&myrpt->lock);
10459 }
10460 rpt_mutex_lock(&myrpt->lock);
10461 if (myrpt->cmdnode[0])
10462 {
10463 rpt_mutex_unlock(&myrpt->lock);
10464 send_link_dtmf(myrpt,c);
10465 return;
10466 }
10467 if (!myrpt->p.simple)
10468 {
10469 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10470 {
10471 myrpt->dtmfidx = 0;
10472 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10473 rpt_mutex_unlock(&myrpt->lock);
10474 time(&myrpt->dtmf_time);
10475 return;
10476 }
10477 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10478 {
10479 time(&myrpt->dtmf_time);
10480
10481 if (myrpt->dtmfidx < MAXDTMF)
10482 {
10483 int src;
10484
10485 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10486 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10487
10488 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10489
10490 rpt_mutex_unlock(&myrpt->lock);
10491 src = SOURCE_RPT;
10492 if (c_in & 0x80) src = SOURCE_ALT;
10493 res = collect_function_digits(myrpt, cmd, src, NULL);
10494 rpt_mutex_lock(&myrpt->lock);
10495 switch(res){
10496 case DC_INDETERMINATE:
10497 break;
10498 case DC_REQ_FLUSH:
10499 myrpt->dtmfidx = 0;
10500 myrpt->dtmfbuf[0] = 0;
10501 break;
10502 case DC_COMPLETE:
10503 case DC_COMPLETEQUIET:
10504 myrpt->totalexecdcommands++;
10505 myrpt->dailyexecdcommands++;
10506 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10507 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10508 myrpt->dtmfbuf[0] = 0;
10509 myrpt->dtmfidx = -1;
10510 myrpt->dtmf_time = 0;
10511 break;
10512
10513 case DC_ERROR:
10514 default:
10515 myrpt->dtmfbuf[0] = 0;
10516 myrpt->dtmfidx = -1;
10517 myrpt->dtmf_time = 0;
10518 break;
10519 }
10520 if(res != DC_INDETERMINATE) {
10521 rpt_mutex_unlock(&myrpt->lock);
10522 return;
10523 }
10524 }
10525 }
10526 }
10527 else
10528 {
10529 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10530 {
10531 myrpt->callmode = 1;
10532 myrpt->patchnoct = 0;
10533 myrpt->patchquiet = 0;
10534 myrpt->patchfarenddisconnect = 0;
10535 myrpt->patchdialtime = 0;
10536 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10537 myrpt->cidx = 0;
10538 myrpt->exten[myrpt->cidx] = 0;
10539 rpt_mutex_unlock(&myrpt->lock);
10540 pthread_attr_init(&attr);
10541 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10542 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10543 return;
10544 }
10545 }
10546 if (myrpt->callmode == 1)
10547 {
10548 myrpt->exten[myrpt->cidx++] = c;
10549 myrpt->exten[myrpt->cidx] = 0;
10550
10551 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10552 {
10553
10554 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10555 myrpt->exten,1,NULL))
10556 {
10557 myrpt->callmode = 2;
10558 rpt_mutex_unlock(&myrpt->lock);
10559 if(!myrpt->patchquiet)
10560 rpt_telemetry(myrpt,PROC,NULL);
10561 return;
10562 }
10563 else
10564 {
10565 myrpt->calldigittimer = 1;
10566 }
10567 }
10568
10569 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10570 {
10571
10572 myrpt->callmode = 4;
10573 }
10574 rpt_mutex_unlock(&myrpt->lock);
10575 return;
10576 }
10577 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10578 {
10579 myrpt->mydtmf = c;
10580 }
10581 rpt_mutex_unlock(&myrpt->lock);
10582 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10583 do_dtmf_phone(myrpt,NULL,c);
10584 return;
10585 }
10586
10587
10588
10589
10590 static void queue_id(struct rpt *myrpt)
10591 {
10592 if(myrpt->p.idtime){
10593 myrpt->mustid = myrpt->tailid = 0;
10594 myrpt->idtimer = myrpt->p.idtime;
10595 rpt_mutex_unlock(&myrpt->lock);
10596 rpt_telemetry(myrpt,ID,NULL);
10597 rpt_mutex_lock(&myrpt->lock);
10598 }
10599 }
10600
10601
10602
10603
10604 static void do_scheduler(struct rpt *myrpt)
10605 {
10606 int i,res;
10607
10608 #ifdef NEW_ASTERISK
10609 struct ast_tm tmnow;
10610 #else
10611 struct tm tmnow;
10612 #endif
10613 struct ast_variable *skedlist;
10614 char *strs[5],*vp,*val,value[100];
10615
10616 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10617
10618 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10619 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10620
10621
10622
10623 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10624 return;
10625
10626 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10627
10628
10629
10630 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10631 myrpt->dailykeyups = 0;
10632 myrpt->dailytxtime = 0;
10633 myrpt->dailykerchunks = 0;
10634 myrpt->dailyexecdcommands = 0;
10635 }
10636
10637 if(tmnow.tm_sec != 0)
10638 return;
10639
10640
10641
10642
10643
10644
10645 if (myrpt->remote)
10646 return;
10647
10648
10649
10650 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10651 if(debug > 6)
10652 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10653 return;
10654 }
10655
10656 if(!myrpt->p.skedstanzaname){
10657 if(debug > 6)
10658 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10659 return;
10660 }
10661
10662
10663 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10664
10665 if(debug > 6){
10666 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10667 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10668 }
10669
10670 for(; skedlist; skedlist = skedlist->next){
10671 if(debug > 6)
10672 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10673 strncpy(value,skedlist->value,99);
10674 value[99] = 0;
10675
10676 for( i = 0, vp = value ; i < 5; i++){
10677 if(!*vp)
10678 break;
10679 while((*vp == ' ') || (*vp == 0x09))
10680 vp++;
10681 strs[i] = vp;
10682 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10683 vp++;
10684 if(*vp)
10685 *vp++ = 0;
10686 }
10687 if(debug > 6)
10688 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10689 strs[0], strs[1], strs[2], strs[3], strs[4]);
10690 if(i == 5){
10691 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10692 continue;
10693 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10694 continue;
10695 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10696 continue;
10697 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10698 continue;
10699 if(atoi(strs[4]) == 7)
10700 strs[4] = "0";
10701 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10702 continue;
10703 if(debug)
10704 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10705 if(atoi(skedlist->name) == 0)
10706 return;
10707 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10708 if (!val){
10709 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10710 return;
10711 }
10712 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10713 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10714 skedlist->name);
10715 return;
10716 }
10717 myrpt->macrotimer = MACROTIME;
10718 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10719 }
10720 else{
10721 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10722 skedlist->name, skedlist->value);
10723 }
10724 }
10725
10726 }
10727
10728
10729 static void *rpt(void *this)
10730 {
10731 struct rpt *myrpt = (struct rpt *)this;
10732 char *tele,*idtalkover,c,myfirst,*p;
10733 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10734 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10735 struct ast_channel *who;
10736 struct dahdi_confinfo ci;
10737 time_t t;
10738 struct rpt_link *l,*m;
10739 struct rpt_tele *telem;
10740 char tmpstr[300],lstr[MAXLINKLIST];
10741
10742
10743 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10744 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10745 mkdir(tmpstr,0600);
10746 rpt_mutex_lock(&myrpt->lock);
10747
10748 telem = myrpt->tele.next;
10749 while(telem != &myrpt->tele)
10750 {
10751 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10752 telem = telem->next;
10753 }
10754 rpt_mutex_unlock(&myrpt->lock);
10755
10756 for(i = 0; i < nrpts; i++)
10757 {
10758 if (&rpt_vars[i] == myrpt)
10759 {
10760 load_rpt_vars(i,0);
10761 break;
10762 }
10763 }
10764
10765 rpt_mutex_lock(&myrpt->lock);
10766 while(myrpt->xlink)
10767 {
10768 myrpt->xlink = 3;
10769 rpt_mutex_unlock(&myrpt->lock);
10770 usleep(100000);
10771 rpt_mutex_lock(&myrpt->lock);
10772 }
10773 #ifdef HAVE_IOPERM
10774 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10775 (ioperm(myrpt->p.iobase,1,1) == -1))
10776 {
10777 rpt_mutex_unlock(&myrpt->lock);
10778 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10779 myrpt->rpt_thread = AST_PTHREADT_STOP;
10780 pthread_exit(NULL);
10781 }
10782 #endif
10783 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10784 tele = strchr(tmpstr,'/');
10785 if (!tele)
10786 {
10787 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10788 rpt_mutex_unlock(&myrpt->lock);
10789 myrpt->rpt_thread = AST_PTHREADT_STOP;
10790 pthread_exit(NULL);
10791 }
10792 *tele++ = 0;
10793 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10794 myrpt->dahdirxchannel = NULL;
10795 if (!strcasecmp(tmpstr,"DAHDI"))
10796 myrpt->dahdirxchannel = myrpt->rxchannel;
10797 if (myrpt->rxchannel)
10798 {
10799 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10800 {
10801 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10802 rpt_mutex_unlock(&myrpt->lock);
10803 ast_hangup(myrpt->rxchannel);
10804 myrpt->rpt_thread = AST_PTHREADT_STOP;
10805 pthread_exit(NULL);
10806 }
10807 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10808 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10809 #ifdef AST_CDR_FLAG_POST_DISABLED
10810 if (myrpt->rxchannel->cdr)
10811 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10812 #endif
10813 #ifndef NEW_ASTERISK
10814 myrpt->rxchannel->whentohangup = 0;
10815 #endif
10816 myrpt->rxchannel->appl = "Apprpt";
10817 myrpt->rxchannel->data = "(Repeater Rx)";
10818 if (option_verbose > 2)
10819 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10820 tmpstr,tele,myrpt->rxchannel->name);
10821 ast_call(myrpt->rxchannel,tele,999);
10822 if (myrpt->rxchannel->_state != AST_STATE_UP)
10823 {
10824 rpt_mutex_unlock(&myrpt->lock);
10825 ast_hangup(myrpt->rxchannel);
10826 myrpt->rpt_thread = AST_PTHREADT_STOP;
10827 pthread_exit(NULL);
10828 }
10829 }
10830 else
10831 {
10832 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10833 rpt_mutex_unlock(&myrpt->lock);
10834 myrpt->rpt_thread = AST_PTHREADT_STOP;
10835 pthread_exit(NULL);
10836 }
10837 myrpt->dahditxchannel = NULL;
10838 if (myrpt->txchanname)
10839 {
10840 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10841 tele = strchr(tmpstr,'/');
10842 if (!tele)
10843 {
10844 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10845 rpt_mutex_unlock(&myrpt->lock);
10846 ast_hangup(myrpt->rxchannel);
10847 myrpt->rpt_thread = AST_PTHREADT_STOP;
10848 pthread_exit(NULL);
10849 }
10850 *tele++ = 0;
10851 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10852 if (!strcasecmp(tmpstr,"DAHDI"))
10853 myrpt->dahditxchannel = myrpt->txchannel;
10854 if (myrpt->txchannel)
10855 {
10856 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10857 {
10858 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10859 rpt_mutex_unlock(&myrpt->lock);
10860 ast_hangup(myrpt->txchannel);
10861 ast_hangup(myrpt->rxchannel);
10862 myrpt->rpt_thread = AST_PTHREADT_STOP;
10863 pthread_exit(NULL);
10864 }
10865 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10866 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10867 #ifdef AST_CDR_FLAG_POST_DISABLED
10868 if (myrpt->txchannel->cdr)
10869 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10870 #endif
10871 #ifndef NEW_ASTERISK
10872 myrpt->txchannel->whentohangup = 0;
10873 #endif
10874 myrpt->txchannel->appl = "Apprpt";
10875 myrpt->txchannel->data = "(Repeater Tx)";
10876 if (option_verbose > 2)
10877 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10878 tmpstr,tele,myrpt->txchannel->name);
10879 ast_call(myrpt->txchannel,tele,999);
10880 if (myrpt->rxchannel->_state != AST_STATE_UP)
10881 {
10882 rpt_mutex_unlock(&myrpt->lock);
10883 ast_hangup(myrpt->rxchannel);
10884 ast_hangup(myrpt->txchannel);
10885 myrpt->rpt_thread = AST_PTHREADT_STOP;
10886 pthread_exit(NULL);
10887 }
10888 }
10889 else
10890 {
10891 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10892 rpt_mutex_unlock(&myrpt->lock);
10893 ast_hangup(myrpt->rxchannel);
10894 myrpt->rpt_thread = AST_PTHREADT_STOP;
10895 pthread_exit(NULL);
10896 }
10897 }
10898 else
10899 {
10900 myrpt->txchannel = myrpt->rxchannel;
10901 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10902 myrpt->dahditxchannel = myrpt->txchannel;
10903 }
10904 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10905 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10906
10907 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10908 if (!myrpt->pchannel)
10909 {
10910 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10911 rpt_mutex_unlock(&myrpt->lock);
10912 if (myrpt->txchannel != myrpt->rxchannel)
10913 ast_hangup(myrpt->txchannel);
10914 ast_hangup(myrpt->rxchannel);
10915 myrpt->rpt_thread = AST_PTHREADT_STOP;
10916 pthread_exit(NULL);
10917 }
10918 #ifdef AST_CDR_FLAG_POST_DISABLED
10919 if (myrpt->pchannel->cdr)
10920 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10921 #endif
10922 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10923 if (!myrpt->dahditxchannel)
10924 {
10925
10926 myrpt->dahditxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10927 if (!myrpt->dahditxchannel)
10928 {
10929 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10930 rpt_mutex_unlock(&myrpt->lock);
10931 if (myrpt->txchannel != myrpt->rxchannel)
10932 ast_hangup(myrpt->txchannel);
10933 ast_hangup(myrpt->rxchannel);
10934 myrpt->rpt_thread = AST_PTHREADT_STOP;
10935 pthread_exit(NULL);
10936 }
10937 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10938 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10939 #ifdef AST_CDR_FLAG_POST_DISABLED
10940 if (myrpt->dahditxchannel->cdr)
10941 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10942 #endif
10943 }
10944
10945 myrpt->monchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10946 if (!myrpt->monchannel)
10947 {
10948 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10949 rpt_mutex_unlock(&myrpt->lock);
10950 if (myrpt->txchannel != myrpt->rxchannel)
10951 ast_hangup(myrpt->txchannel);
10952 ast_hangup(myrpt->rxchannel);
10953 myrpt->rpt_thread = AST_PTHREADT_STOP;
10954 pthread_exit(NULL);
10955 }
10956 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10957 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10958 #ifdef AST_CDR_FLAG_POST_DISABLED
10959 if (myrpt->monchannel->cdr)
10960 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10961 #endif
10962
10963 ci.chan = 0;
10964 ci.confno = -1;
10965 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10966
10967 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10968 {
10969 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10970 rpt_mutex_unlock(&myrpt->lock);
10971 ast_hangup(myrpt->pchannel);
10972 ast_hangup(myrpt->monchannel);
10973 if (myrpt->txchannel != myrpt->rxchannel)
10974 ast_hangup(myrpt->txchannel);
10975 ast_hangup(myrpt->rxchannel);
10976 myrpt->rpt_thread = AST_PTHREADT_STOP;
10977 pthread_exit(NULL);
10978 }
10979
10980 myrpt->txconf = ci.confno;
10981
10982 ci.chan = 0;
10983 ci.confno = -1;
10984 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10985 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10986
10987 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10988 {
10989 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10990 rpt_mutex_unlock(&myrpt->lock);
10991 ast_hangup(myrpt->pchannel);
10992 ast_hangup(myrpt->monchannel);
10993 if (myrpt->txchannel != myrpt->rxchannel)
10994 ast_hangup(myrpt->txchannel);
10995 ast_hangup(myrpt->rxchannel);
10996 myrpt->rpt_thread = AST_PTHREADT_STOP;
10997 pthread_exit(NULL);
10998 }
10999
11000 myrpt->conf = ci.confno;
11001
11002 ci.chan = 0;
11003 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11004 (myrpt->dahditxchannel == myrpt->txchannel))
11005 {
11006
11007 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11008 {
11009 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11010 rpt_mutex_unlock(&myrpt->lock);
11011 ast_hangup(myrpt->pchannel);
11012 ast_hangup(myrpt->monchannel);
11013 if (myrpt->txchannel != myrpt->rxchannel)
11014 ast_hangup(myrpt->txchannel);
11015 ast_hangup(myrpt->rxchannel);
11016 myrpt->rpt_thread = AST_PTHREADT_STOP;
11017 pthread_exit(NULL);
11018 }
11019 ci.confmode = DAHDI_CONF_MONITORTX;
11020 }
11021 else
11022 {
11023 ci.confno = myrpt->txconf;
11024 ci.confmode = DAHDI_CONF_CONFANNMON;
11025 }
11026
11027 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11028 {
11029 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11030 rpt_mutex_unlock(&myrpt->lock);
11031 ast_hangup(myrpt->pchannel);
11032 ast_hangup(myrpt->monchannel);
11033 if (myrpt->txchannel != myrpt->rxchannel)
11034 ast_hangup(myrpt->txchannel);
11035 ast_hangup(myrpt->rxchannel);
11036 myrpt->rpt_thread = AST_PTHREADT_STOP;
11037 pthread_exit(NULL);
11038 }
11039
11040 myrpt->parrotchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11041 if (!myrpt->parrotchannel)
11042 {
11043 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11044 rpt_mutex_unlock(&myrpt->lock);
11045 if (myrpt->txchannel != myrpt->rxchannel)
11046 ast_hangup(myrpt->txchannel);
11047 ast_hangup(myrpt->rxchannel);
11048 myrpt->rpt_thread = AST_PTHREADT_STOP;
11049 pthread_exit(NULL);
11050 }
11051 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11052 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11053 #ifdef AST_CDR_FLAG_POST_DISABLED
11054 if (myrpt->parrotchannel->cdr)
11055 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11056 #endif
11057
11058 myrpt->voxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11059 if (!myrpt->voxchannel)
11060 {
11061 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11062 rpt_mutex_unlock(&myrpt->lock);
11063 if (myrpt->txchannel != myrpt->rxchannel)
11064 ast_hangup(myrpt->txchannel);
11065 ast_hangup(myrpt->rxchannel);
11066 myrpt->rpt_thread = AST_PTHREADT_STOP;
11067 pthread_exit(NULL);
11068 }
11069 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11070 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11071 #ifdef AST_CDR_FLAG_POST_DISABLED
11072 if (myrpt->voxchannel->cdr)
11073 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11074 #endif
11075
11076 myrpt->txpchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11077 if (!myrpt->txpchannel)
11078 {
11079 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11080 rpt_mutex_unlock(&myrpt->lock);
11081 ast_hangup(myrpt->pchannel);
11082 ast_hangup(myrpt->monchannel);
11083 if (myrpt->txchannel != myrpt->rxchannel)
11084 ast_hangup(myrpt->txchannel);
11085 ast_hangup(myrpt->rxchannel);
11086 myrpt->rpt_thread = AST_PTHREADT_STOP;
11087 pthread_exit(NULL);
11088 }
11089 #ifdef AST_CDR_FLAG_POST_DISABLED
11090 if (myrpt->txpchannel->cdr)
11091 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11092 #endif
11093
11094 ci.chan = 0;
11095 ci.confno = myrpt->txconf;
11096 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11097
11098 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11099 {
11100 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11101 rpt_mutex_unlock(&myrpt->lock);
11102 ast_hangup(myrpt->txpchannel);
11103 ast_hangup(myrpt->monchannel);
11104 if (myrpt->txchannel != myrpt->rxchannel)
11105 ast_hangup(myrpt->txchannel);
11106 ast_hangup(myrpt->rxchannel);
11107 myrpt->rpt_thread = AST_PTHREADT_STOP;
11108 pthread_exit(NULL);
11109 }
11110
11111 myrpt->iofd = -1;
11112 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11113 {
11114 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11115 rpt_mutex_unlock(&myrpt->lock);
11116 ast_hangup(myrpt->pchannel);
11117 if (myrpt->txchannel != myrpt->rxchannel)
11118 ast_hangup(myrpt->txchannel);
11119 ast_hangup(myrpt->rxchannel);
11120 pthread_exit(NULL);
11121 }
11122
11123
11124
11125 myrpt->links.next = &myrpt->links;
11126 myrpt->links.prev = &myrpt->links;
11127 myrpt->tailtimer = 0;
11128 myrpt->totimer = 0;
11129 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11130 myrpt->idtimer = myrpt->p.politeid;
11131 myrpt->mustid = myrpt->tailid = 0;
11132 myrpt->callmode = 0;
11133 myrpt->tounkeyed = 0;
11134 myrpt->tonotify = 0;
11135 myrpt->retxtimer = 0;
11136 myrpt->rerxtimer = 0;
11137 myrpt->skedtimer = 0;
11138 myrpt->tailevent = 0;
11139 lasttx = 0;
11140 myrpt->keyed = 0;
11141 myrpt->txkeyed = 0;
11142 time(&myrpt->lastkeyedtime);
11143 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11144 time(&myrpt->lasttxkeyedtime);
11145 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11146 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11147 myrpt->dtmfidx = -1;
11148 myrpt->dtmfbuf[0] = 0;
11149 myrpt->rem_dtmfidx = -1;
11150 myrpt->rem_dtmfbuf[0] = 0;
11151 myrpt->dtmf_time = 0;
11152 myrpt->rem_dtmf_time = 0;
11153 myrpt->inpadtest = 0;
11154 myrpt->disgorgetime = 0;
11155 myrpt->lastnodewhichkeyedusup[0] = '\0';
11156 myrpt->dailytxtime = 0;
11157 myrpt->totaltxtime = 0;
11158 myrpt->dailykeyups = 0;
11159 myrpt->totalkeyups = 0;
11160 myrpt->dailykerchunks = 0;
11161 myrpt->totalkerchunks = 0;
11162 myrpt->dailyexecdcommands = 0;
11163 myrpt->totalexecdcommands = 0;
11164 myrpt->timeouts = 0;
11165 myrpt->exten[0] = '\0';
11166 myrpt->lastdtmfcommand[0] = '\0';
11167 voxinit_rpt(myrpt,1);
11168 myrpt->wasvox = 0;
11169 if (myrpt->p.startupmacro)
11170 {
11171 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11172 }
11173 rpt_mutex_unlock(&myrpt->lock);
11174 val = 1;
11175 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11176 val = 1;
11177 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11178 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11179 dtmfed = 0;
11180 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11181 lastmyrx = 0;
11182 myfirst = 0;
11183 while (ms >= 0)
11184 {
11185 struct ast_frame *f,*f1,*f2;
11186 struct ast_channel *cs[300],*cs1[300];
11187 int totx=0,elap=0,n,x,toexit=0;
11188
11189
11190 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11191 struct rpt_link *dl;
11192 struct rpt_tele *dt;
11193
11194 myrpt->disgorgetime = 0;
11195 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11196 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11197 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11198 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11199 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11200 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11201
11202 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11203 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11204 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11205 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11206 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11207 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11208 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11209 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11210 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11211 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11212
11213 dl = myrpt->links.next;
11214 while(dl != &myrpt->links){
11215 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11216 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11217 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11218 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11219 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11220 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11221 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11222 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11223 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11224 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11225 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11226 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11227 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11228 dl = dl->next;
11229 }
11230
11231 dt = myrpt->tele.next;
11232 if(dt != &myrpt->tele)
11233 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11234 while(dt != &myrpt->tele){
11235 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11236 dt = dt->next;
11237 }
11238 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11239
11240 }
11241
11242
11243 if (myrpt->reload)
11244 {
11245 struct rpt_tele *inner_telem;
11246
11247 rpt_mutex_lock(&myrpt->lock);
11248 inner_telem = myrpt->tele.next;
11249 while(inner_telem != &myrpt->tele)
11250 {
11251 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11252 inner_telem = inner_telem->next;
11253 }
11254 myrpt->reload = 0;
11255 rpt_mutex_unlock(&myrpt->lock);
11256 usleep(10000);
11257
11258 for(i = 0; i < nrpts; i++)
11259 {
11260 if (&rpt_vars[i] == myrpt)
11261 {
11262 load_rpt_vars(i,0);
11263 break;
11264 }
11265 }
11266 }
11267
11268 rpt_mutex_lock(&myrpt->lock);
11269 if (ast_check_hangup(myrpt->rxchannel)) break;
11270 if (ast_check_hangup(myrpt->txchannel)) break;
11271 if (ast_check_hangup(myrpt->pchannel)) break;
11272 if (ast_check_hangup(myrpt->monchannel)) break;
11273 if (myrpt->parrotchannel &&
11274 ast_check_hangup(myrpt->parrotchannel)) break;
11275 if (myrpt->voxchannel &&
11276 ast_check_hangup(myrpt->voxchannel)) break;
11277 if (ast_check_hangup(myrpt->txpchannel)) break;
11278 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11279
11280
11281 myrpt->localtx = myrpt->keyed;
11282
11283 l = myrpt->links.next;
11284 remrx = 0;
11285 while(l != &myrpt->links)
11286 {
11287 if (l->lastrx){
11288 remrx = 1;
11289 if(l->name[0] != '0')
11290 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11291 }
11292 l = l->next;
11293 }
11294
11295 if(myrpt->p.idtime)
11296 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11297
11298
11299 if (myrpt->p.duplex > 1)
11300 {
11301 totx = myrpt->callmode;
11302 totx = totx || myrpt->localtx;
11303 }
11304 else
11305 {
11306 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11307
11308 if (lastmyrx != myrx)
11309 {
11310 voxinit_rpt(myrpt,!myrx);
11311 lastmyrx = myrx;
11312 }
11313 totx = 0;
11314 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11315 {
11316 if (myrpt->voxtostate)
11317 {
11318 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11319 myrpt->voxtostate = 0;
11320 }
11321 else
11322 {
11323 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11324 myrpt->voxtostate = 1;
11325 }
11326 }
11327 if (!myrpt->voxtostate)
11328 totx = myrpt->callmode && myrpt->wasvox;
11329 }
11330
11331 identqueued = 0;
11332 localmsgqueued = 0;
11333 othertelemqueued = 0;
11334 tailmessagequeued = 0;
11335 ctqueued = 0;
11336 telem = myrpt->tele.next;
11337 while(telem != &myrpt->tele)
11338 {
11339 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11340 identqueued = 1;
11341 }
11342 else if(telem->mode == TAILMSG)
11343 {
11344 tailmessagequeued = 1;
11345 }
11346 else if(telem->mode == STATS_TIME_LOCAL)
11347 {
11348 localmsgqueued = 1;
11349 }
11350 else
11351 {
11352 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11353 othertelemqueued = 1;
11354 else
11355 ctqueued = 1;
11356 }
11357 telem = telem->next;
11358 }
11359
11360
11361 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11362
11363
11364 myrpt->exttx = totx;
11365 totx = totx || myrpt->dtmf_local_timer;
11366
11367 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11368
11369 totx = totx || remrx;
11370
11371 if (myrpt->p.duplex > 0)
11372 totx = totx || identqueued || ctqueued || localmsgqueued;
11373
11374 if (myrpt->p.duplex > 1)
11375 {
11376 totx = totx || (myrpt->dtmfidx > -1) ||
11377 myrpt->cmdnode[0];
11378 }
11379
11380 totx = totx || (myrpt->parrotstate > 1);
11381
11382 if (!totx)
11383 {
11384 myrpt->totimer = myrpt->p.totime;
11385 myrpt->tounkeyed = 0;
11386 myrpt->tonotify = 0;
11387 }
11388 else{
11389 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11390 myrpt->p.althangtime :
11391 myrpt->p.hangtime;
11392 }
11393
11394 totx = totx && myrpt->totimer;
11395
11396 if ((!myrpt->totimer) && (!myrpt->tonotify))
11397 {
11398 myrpt->tonotify = 1;
11399 myrpt->timeouts++;
11400 rpt_mutex_unlock(&myrpt->lock);
11401 rpt_telemetry(myrpt,TIMEOUT,NULL);
11402 rpt_mutex_lock(&myrpt->lock);
11403 }
11404
11405
11406 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11407 {
11408 myrpt->tounkeyed = 1;
11409 }
11410 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11411 {
11412 myrpt->totimer = myrpt->p.totime;
11413 myrpt->tounkeyed = 0;
11414 myrpt->tonotify = 0;
11415 rpt_mutex_unlock(&myrpt->lock);
11416 continue;
11417 }
11418
11419 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11420 {
11421 if(debug)
11422 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11423 myrpt->callmode = 0;
11424 myrpt->macropatch=0;
11425 channel_revert(myrpt);
11426 }
11427
11428 if (!myrpt->totimer) myrpt->tailtimer = 0;
11429
11430 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11431
11432
11433 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11434 int hasid = 0,hastalkover = 0;
11435
11436 telem = myrpt->tele.next;
11437 while(telem != &myrpt->tele){
11438 if(telem->mode == ID){
11439 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11440 hasid = 1;
11441 }
11442 if(telem->mode == TAILMSG){
11443 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11444 }
11445 if (telem->mode == IDTALKOVER) hastalkover = 1;
11446 telem = telem->next;
11447 }
11448 rpt_mutex_unlock(&myrpt->lock);
11449 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11450 rpt_mutex_lock(&myrpt->lock);
11451 }
11452
11453
11454
11455
11456
11457 if(myrpt->mustid && (!myrpt->idtimer))
11458 queue_id(myrpt);
11459
11460 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11461 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11462 {
11463 myrpt->tailid = 1;
11464 }
11465
11466
11467
11468 if(myrpt->tailevent){
11469 myrpt->tailevent = 0;
11470 if(myrpt->tailid){
11471 totx = 1;
11472 queue_id(myrpt);
11473 }
11474 else if ((myrpt->p.tailmessages[0]) &&
11475 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11476 totx = 1;
11477 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11478 rpt_mutex_unlock(&myrpt->lock);
11479 rpt_telemetry(myrpt, TAILMSG, NULL);
11480 rpt_mutex_lock(&myrpt->lock);
11481 }
11482 }
11483
11484
11485
11486
11487 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11488 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11489 myrpt->txrealkeyed = totx;
11490 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11491 if (totx && (!lasttx))
11492 {
11493 char mydate[100],myfname[100];
11494 time_t myt;
11495
11496 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11497 if (myrpt->p.archivedir)
11498 {
11499 long blocksleft;
11500
11501 time(&myt);
11502 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11503 localtime(&myt));
11504 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11505 myrpt->name,mydate);
11506 myrpt->monstream = ast_writefile(myfname,"wav49",
11507 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11508 if (myrpt->p.monminblocks)
11509 {
11510 blocksleft = diskavail(myrpt);
11511 if (blocksleft >= myrpt->p.monminblocks)
11512 donodelog(myrpt,"TXKEY,MAIN");
11513 } else donodelog(myrpt,"TXKEY,MAIN");
11514 }
11515 lasttx = 1;
11516 myrpt->txkeyed = 1;
11517 time(&myrpt->lasttxkeyedtime);
11518 myrpt->dailykeyups++;
11519 myrpt->totalkeyups++;
11520 rpt_mutex_unlock(&myrpt->lock);
11521 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11522 rpt_mutex_lock(&myrpt->lock);
11523 }
11524 if ((!totx) && lasttx)
11525 {
11526 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11527 myrpt->monstream = NULL;
11528
11529 lasttx = 0;
11530 myrpt->txkeyed = 0;
11531 time(&myrpt->lasttxkeyedtime);
11532 rpt_mutex_unlock(&myrpt->lock);
11533 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11534 rpt_mutex_lock(&myrpt->lock);
11535 donodelog(myrpt,"TXUNKEY,MAIN");
11536 }
11537 time(&t);
11538
11539 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11540 {
11541 myrpt->inpadtest = 0;
11542 myrpt->dtmfidx = -1;
11543 myrpt->dtmfbuf[0] = 0;
11544 }
11545
11546 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11547 {
11548 myrpt->inpadtest = 0;
11549 myrpt->rem_dtmfidx = -1;
11550 myrpt->rem_dtmfbuf[0] = 0;
11551 }
11552
11553 if (myrpt->exttx && myrpt->parrotchannel &&
11554 myrpt->p.parrotmode && (!myrpt->parrotstate))
11555 {
11556 char myfname[300];
11557
11558 ci.confno = myrpt->conf;
11559 ci.confmode = DAHDI_CONF_CONFANNMON;
11560 ci.chan = 0;
11561
11562
11563 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11564 {
11565 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11566 break;
11567 }
11568
11569 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11570 strcat(myfname,".wav");
11571 unlink(myfname);
11572 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11573 myrpt->parrotstate = 1;
11574 myrpt->parrottimer = myrpt->p.parrottime;
11575 if (myrpt->parrotstream)
11576 ast_closestream(myrpt->parrotstream);
11577 myrpt->parrotstream = NULL;
11578 myrpt->parrotstream = ast_writefile(myfname,"wav",
11579 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11580 }
11581
11582
11583
11584 l = myrpt->links.next;
11585 while(l != &myrpt->links)
11586 {
11587 if (l->killme)
11588 {
11589
11590 remque((struct qelem *) l);
11591 if (!strcmp(myrpt->cmdnode,l->name))
11592 myrpt->cmdnode[0] = 0;
11593 rpt_mutex_unlock(&myrpt->lock);
11594
11595 if (l->chan) ast_hangup(l->chan);
11596 ast_hangup(l->pchan);
11597 ast_free(l);
11598 rpt_mutex_lock(&myrpt->lock);
11599
11600 l = myrpt->links.next;
11601 continue;
11602 }
11603 l = l->next;
11604 }
11605 n = 0;
11606 cs[n++] = myrpt->rxchannel;
11607 cs[n++] = myrpt->pchannel;
11608 cs[n++] = myrpt->monchannel;
11609 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11610 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11611 cs[n++] = myrpt->txpchannel;
11612 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11613 if (myrpt->dahditxchannel != myrpt->txchannel)
11614 cs[n++] = myrpt->dahditxchannel;
11615 l = myrpt->links.next;
11616 while(l != &myrpt->links)
11617 {
11618 if ((!l->killme) && (!l->disctime) && l->chan)
11619 {
11620 cs[n++] = l->chan;
11621 cs[n++] = l->pchan;
11622 }
11623 l = l->next;
11624 }
11625 if ((myrpt->topkeystate == 1) &&
11626 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11627 {
11628 myrpt->topkeystate = 2;
11629 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11630 topcompar);
11631 }
11632 rpt_mutex_unlock(&myrpt->lock);
11633
11634 if (myrpt->topkeystate == 2)
11635 {
11636 rpt_telemetry(myrpt,TOPKEY,NULL);
11637 myrpt->topkeystate = 3;
11638 }
11639 ms = MSWAIT;
11640 for(x = 0; x < n; x++)
11641 {
11642 int s = -(-x - myrpt->scram - 1) % n;
11643 cs1[x] = cs[s];
11644 }
11645 myrpt->scram++;
11646 who = ast_waitfor_n(cs1,n,&ms);
11647 if (who == NULL) ms = 0;
11648 elap = MSWAIT - ms;
11649 rpt_mutex_lock(&myrpt->lock);
11650 l = myrpt->links.next;
11651 while(l != &myrpt->links)
11652 {
11653 int myrx;
11654
11655 if (l->voxtotimer) l->voxtotimer -= elap;
11656 if (l->voxtotimer < 0) l->voxtotimer = 0;
11657
11658 if (l->lasttx != l->lasttx1)
11659 {
11660 voxinit_link(l,!l->lasttx);
11661 l->lasttx1 = l->lasttx;
11662 }
11663 myrx = l->lastrealrx;
11664 if ((l->phonemode) && (l->phonevox))
11665 {
11666 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11667 if (l->voxtotimer <= 0)
11668 {
11669 if (l->voxtostate)
11670 {
11671 l->voxtotimer = myrpt->p.voxtimeout_ms;
11672 l->voxtostate = 0;
11673 }
11674 else
11675 {
11676 l->voxtotimer = myrpt->p.voxrecover_ms;
11677 l->voxtostate = 1;
11678 }
11679 }
11680 if (!l->voxtostate)
11681 myrx = myrx || l->wasvox ;
11682 }
11683 l->lastrx = myrx;
11684 if (l->linklisttimer)
11685 {
11686 l->linklisttimer -= elap;
11687 if (l->linklisttimer < 0) l->linklisttimer = 0;
11688 }
11689 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11690 {
11691 struct ast_frame lf;
11692
11693 memset(&lf,0,sizeof(lf));
11694 lf.frametype = AST_FRAME_TEXT;
11695 lf.subclass = 0;
11696 lf.offset = 0;
11697 lf.mallocd = 0;
11698 lf.samples = 0;
11699 l->linklisttimer = LINKLISTTIME;
11700 strcpy(lstr,"L ");
11701 __mklinklist(myrpt,l,lstr + 2);
11702 if (l->chan)
11703 {
11704 lf.datalen = strlen(lstr) + 1;
11705 lf.data.ptr = lstr;
11706 ast_write(l->chan,&lf);
11707 if (debug > 6) ast_log(LOG_NOTICE,
11708 "@@@@ node %s sent node string %s to node %s\n",
11709 myrpt->name,lstr,l->name);
11710 }
11711 }
11712 if (l->newkey)
11713 {
11714 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11715 {
11716 l->retxtimer = 0;
11717 if (l->chan && l->phonemode == 0)
11718 {
11719 if (l->lasttx)
11720 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11721 else
11722 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11723 }
11724 }
11725 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11726 {
11727 if (debug == 7) printf("@@@@ rx un-key\n");
11728 l->lastrealrx = 0;
11729 l->rerxtimer = 0;
11730 if (l->lastrx1)
11731 {
11732 if (myrpt->p.archivedir)
11733 {
11734 char str[100];
11735
11736 sprintf(str,"RXUNKEY(T),%s",l->name);
11737 donodelog(myrpt,str);
11738 }
11739 if(myrpt->p.duplex)
11740 rpt_telemetry(myrpt,LINKUNKEY,l);
11741 l->lastrx1 = 0;
11742 }
11743 }
11744 }
11745 if (l->disctime)
11746 {
11747 l->disctime -= elap;
11748 if (l->disctime <= 0)
11749 l->disctime = 0;
11750 }
11751
11752 if (l->retrytimer)
11753 {
11754 l->retrytimer -= elap;
11755 if (l->retrytimer < 0) l->retrytimer = 0;
11756 }
11757
11758
11759 l->connecttime += elap;
11760
11761
11762 if (l->elaptime < 0)
11763 {
11764 l = l->next;
11765 continue;
11766 }
11767 l->elaptime += elap;
11768
11769 if ((l->elaptime > MAXCONNECTTIME) &&
11770 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11771 {
11772 l->elaptime = 0;
11773 rpt_mutex_unlock(&myrpt->lock);
11774 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11775 rpt_mutex_lock(&myrpt->lock);
11776 break;
11777 }
11778 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11779 (l->retries++ < l->max_retries) && (l->hasconnected))
11780 {
11781 if (l->chan) ast_hangup(l->chan);
11782 l->chan = 0;
11783 rpt_mutex_unlock(&myrpt->lock);
11784 if ((l->name[0] != '0') && (!l->isremote))
11785 {
11786 if (attempt_reconnect(myrpt,l) == -1)
11787 {
11788 l->retrytimer = RETRY_TIMER_MS;
11789 }
11790 }
11791 else
11792 {
11793 l->retrytimer = l->max_retries + 1;
11794 }
11795
11796 rpt_mutex_lock(&myrpt->lock);
11797 break;
11798 }
11799 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11800 (l->retries >= l->max_retries))
11801 {
11802
11803 remque((struct qelem *) l);
11804 if (!strcmp(myrpt->cmdnode,l->name))
11805 myrpt->cmdnode[0] = 0;
11806 rpt_mutex_unlock(&myrpt->lock);
11807 if (l->name[0] != '0')
11808 {
11809 if (!l->hasconnected)
11810 rpt_telemetry(myrpt,CONNFAIL,l);
11811 else rpt_telemetry(myrpt,REMDISC,l);
11812 }
11813 if (myrpt->p.archivedir)
11814 {
11815 char str[100];
11816
11817 if (!l->hasconnected)
11818 sprintf(str,"LINKFAIL,%s",l->name);
11819 else
11820 sprintf(str,"LINKDISC,%s",l->name);
11821 donodelog(myrpt,str);
11822 }
11823
11824 ast_hangup(l->pchan);
11825 ast_free(l);
11826 rpt_mutex_lock(&myrpt->lock);
11827 break;
11828 }
11829 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11830 {
11831 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11832
11833 remque((struct qelem *) l);
11834 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11835 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11836 rpt_mutex_unlock(&myrpt->lock);
11837 if (l->name[0] != '0')
11838 {
11839 rpt_telemetry(myrpt,REMDISC,l);
11840 }
11841 if (myrpt->p.archivedir)
11842 {
11843 char str[100];
11844 sprintf(str,"LINKDISC,%s",l->name);
11845 donodelog(myrpt,str);
11846 }
11847
11848 ast_hangup(l->pchan);
11849 ast_free(l);
11850 rpt_mutex_lock(&myrpt->lock);
11851 break;
11852 }
11853 l = l->next;
11854 }
11855 if (myrpt->linkposttimer)
11856 {
11857 myrpt->linkposttimer -= elap;
11858 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11859 }
11860 if (myrpt->linkposttimer <= 0)
11861 {
11862 int nstr;
11863 char lst,*str;
11864 time_t now;
11865
11866 myrpt->linkposttimer = LINKPOSTTIME;
11867 nstr = 0;
11868 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11869 {
11870
11871 if (l->name[0] == '0') continue;
11872 nstr += strlen(l->name) + 1;
11873 }
11874 str = ast_malloc(nstr + 256);
11875 if (!str)
11876 {
11877 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11878 break;
11879 }
11880 nstr = 0;
11881 strcpy(str,"nodes=");
11882 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11883 {
11884
11885 if (l->name[0] == '0') continue;
11886 lst = 'T';
11887 if (!l->mode) lst = 'R';
11888 if (!l->thisconnected) lst = 'C';
11889 if (nstr) strcat(str,",");
11890 sprintf(str + strlen(str),"%c%s",lst,l->name);
11891 nstr = 1;
11892 }
11893 p = strstr(tdesc, "version");
11894 if(p){
11895 int vmajor,vminor;
11896 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11897 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11898 }
11899 time(&now);
11900 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11901 sprintf(str + strlen(str),
11902 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11903 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11904 myrpt->timeouts,myrpt->totalexecdcommands);
11905 rpt_mutex_unlock(&myrpt->lock);
11906 statpost(myrpt,str);
11907 rpt_mutex_lock(&myrpt->lock);
11908 ast_free(str);
11909 }
11910 if (myrpt->keyposttimer)
11911 {
11912 myrpt->keyposttimer -= elap;
11913 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11914 }
11915 if (myrpt->keyposttimer <= 0)
11916 {
11917 char str[100];
11918 int diff = 0;
11919 time_t now;
11920
11921 myrpt->keyposttimer = KEYPOSTTIME;
11922 time(&now);
11923 if (myrpt->lastkeyedtime)
11924 {
11925 diff = (int)(now - myrpt->lastkeyedtime);
11926 }
11927 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11928 rpt_mutex_unlock(&myrpt->lock);
11929 statpost(myrpt,str);
11930 rpt_mutex_lock(&myrpt->lock);
11931 }
11932 if(totx){
11933 myrpt->dailytxtime += elap;
11934 myrpt->totaltxtime += elap;
11935 }
11936 i = myrpt->tailtimer;
11937 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11938 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11939 if((i) && (myrpt->tailtimer == 0))
11940 myrpt->tailevent = 1;
11941 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11942 if (myrpt->totimer < 0) myrpt->totimer = 0;
11943 if (myrpt->idtimer) myrpt->idtimer -= elap;
11944 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11945 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11946 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11947 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11948 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11949 if (myrpt->exttx)
11950 {
11951 myrpt->parrottimer = myrpt->p.parrottime;
11952 }
11953 else
11954 {
11955 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11956 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11957 }
11958
11959 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11960 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11961
11962 if (myrpt->dtmf_local_timer)
11963 {
11964 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11965 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11966 }
11967 do_dtmf_local(myrpt,0);
11968
11969 if (myrpt->skedtimer <= 0){
11970 myrpt->skedtimer = 200;
11971 do_scheduler(myrpt);
11972 }
11973 else
11974 myrpt->skedtimer -=elap;
11975 if (!ms)
11976 {
11977 rpt_mutex_unlock(&myrpt->lock);
11978 continue;
11979 }
11980 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11981 (myrpt->parrottimer <= 0))
11982 {
11983
11984 ci.confno = 0;
11985 ci.confmode = 0;
11986 ci.chan = 0;
11987
11988
11989 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11990 {
11991 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11992 break;
11993 }
11994 if (myrpt->parrotstream)
11995 ast_closestream(myrpt->parrotstream);
11996 myrpt->parrotstream = NULL;
11997 myrpt->parrotstate = 2;
11998 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
11999 }
12000 if (myrpt->cmdAction.state == CMD_STATE_READY)
12001 {
12002 int status;
12003 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12004
12005 rpt_mutex_unlock(&myrpt->lock);
12006
12007 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12008
12009 rpt_mutex_lock(&myrpt->lock);
12010 myrpt->cmdAction.state = CMD_STATE_IDLE;
12011 }
12012
12013 c = myrpt->macrobuf[0];
12014 time(&t);
12015 if (c && (!myrpt->macrotimer) &&
12016 starttime && (t > (starttime + START_DELAY)))
12017 {
12018 char cin = c & 0x7f;
12019 myrpt->macrotimer = MACROTIME;
12020 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12021 if ((cin == 'p') || (cin == 'P'))
12022 myrpt->macrotimer = MACROPTIME;
12023 rpt_mutex_unlock(&myrpt->lock);
12024 if (myrpt->p.archivedir)
12025 {
12026 char str[100];
12027
12028 sprintf(str,"DTMF(M),MAIN,%c",cin);
12029 donodelog(myrpt,str);
12030 }
12031 local_dtmf_helper(myrpt,c);
12032 } else rpt_mutex_unlock(&myrpt->lock);
12033 if (who == myrpt->rxchannel)
12034 {
12035 int ismuted;
12036
12037 f = ast_read(myrpt->rxchannel);
12038 if (!f)
12039 {
12040 if (debug) printf("@@@@ rpt:Hung Up\n");
12041 break;
12042 }
12043 if (f->frametype == AST_FRAME_VOICE)
12044 {
12045 #ifdef _MDC_DECODE_H_
12046 unsigned char ubuf[2560];
12047 short *sp;
12048 int n;
12049 #endif
12050
12051 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12052 memset(f->data.ptr,0,f->datalen);
12053 }
12054
12055 #ifdef _MDC_DECODE_H_
12056 sp = (short *) f->data;
12057
12058 for(n = 0; n < f->datalen / 2; n++)
12059 {
12060 ubuf[n] = (*sp++ >> 8) + 128;
12061 }
12062 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12063 if (n == 1)
12064 {
12065 unsigned char op,arg;
12066 unsigned short unitID;
12067
12068 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12069 if (debug > 2)
12070 {
12071 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12072 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12073 op & 255,arg & 255,unitID);
12074 }
12075 if ((op == 1) && (arg == 0))
12076 {
12077 myrpt->lastunit = unitID;
12078 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12079 mdc1200_send(myrpt,myrpt->lastunit);
12080 }
12081 }
12082 if ((debug > 2) && (i == 2))
12083 {
12084 unsigned char op,arg,ex1,ex2,ex3,ex4;
12085 unsigned short unitID;
12086
12087 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12088 &ex1,&ex2,&ex3,&ex4);
12089 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12090 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12091 op & 255,arg & 255,unitID);
12092 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12093 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12094 }
12095 #endif
12096 #ifdef __RPT_NOTCH
12097
12098 rpt_filter(myrpt,f->data,f->datalen / 2);
12099 #endif
12100 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12101 {
12102 ismuted = 0;
12103 }
12104 if (dtmfed) ismuted = 1;
12105 dtmfed = 0;
12106 if (ismuted)
12107 {
12108 memset(f->data.ptr,0,f->datalen);
12109 if (myrpt->lastf1)
12110 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12111 if (myrpt->lastf2)
12112 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12113 }
12114 if (f) f2 = ast_frdup(f);
12115 else f2 = NULL;
12116 f1 = myrpt->lastf2;
12117 myrpt->lastf2 = myrpt->lastf1;
12118 myrpt->lastf1 = f2;
12119 if (ismuted)
12120 {
12121 if (myrpt->lastf1)
12122 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12123 if (myrpt->lastf2)
12124 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12125 }
12126 if (f1)
12127 {
12128 ast_write(myrpt->pchannel,f1);
12129 ast_frfree(f1);
12130 }
12131 }
12132 #ifndef OLD_ASTERISK
12133 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12134 {
12135 if (myrpt->lastf1)
12136 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12137 if (myrpt->lastf2)
12138 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12139 dtmfed = 1;
12140 }
12141 #endif
12142 else if (f->frametype == AST_FRAME_DTMF)
12143 {
12144 c = (char) f->subclass;
12145 ast_frfree(f);
12146 if (myrpt->lastf1)
12147 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12148 if (myrpt->lastf2)
12149 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12150 dtmfed = 1;
12151 if (!myrpt->keyed) continue;
12152 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12153 if (c) local_dtmf_helper(myrpt,c);
12154 continue;
12155 }
12156 else if (f->frametype == AST_FRAME_CONTROL)
12157 {
12158 if (f->subclass == AST_CONTROL_HANGUP)
12159 {
12160 if (debug) printf("@@@@ rpt:Hung Up\n");
12161 ast_frfree(f);
12162 break;
12163 }
12164
12165 if (f->subclass == AST_CONTROL_RADIO_KEY)
12166 {
12167 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12168 {
12169 if (debug == 7) printf("@@@@ rx key\n");
12170 myrpt->keyed = 1;
12171 time(&myrpt->lastkeyedtime);
12172 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12173 }
12174 if (myrpt->p.archivedir)
12175 {
12176 donodelog(myrpt,"RXKEY,MAIN");
12177 }
12178 if (f->datalen && f->data.ptr)
12179 {
12180 char busy = 0;
12181
12182 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12183
12184 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12185 {
12186 char value[16];
12187 strcat(value,"*6");
12188 myrpt->macropatch=1;
12189 rpt_mutex_lock(&myrpt->lock);
12190 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12191 rpt_mutex_unlock(&myrpt->lock);
12192 busy=1;
12193 }
12194 if(!busy){
12195 myrpt->macrotimer = MACROTIME;
12196 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12197 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12198 }
12199 rpt_mutex_unlock(&myrpt->lock);
12200 }
12201 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12202 {
12203 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12204 if (value)
12205 {
12206 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12207 rpt_mutex_lock(&myrpt->lock);
12208 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12209 rpt_mutex_unlock(&myrpt->lock);
12210 busy=1;
12211 }
12212 if(!busy){
12213 myrpt->macrotimer = MACROTIME;
12214 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12215 }
12216 rpt_mutex_unlock(&myrpt->lock);
12217 }
12218 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12219 }
12220 } else myrpt->lasttone[0] = 0;
12221 }
12222
12223 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12224 {
12225 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12226 {
12227 if (debug == 7) printf("@@@@ rx un-key\n");
12228 if(myrpt->p.duplex && myrpt->keyed) {
12229 rpt_telemetry(myrpt,UNKEY,NULL);
12230 }
12231 }
12232 myrpt->keyed = 0;
12233 time(&myrpt->lastkeyedtime);
12234 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12235 if (myrpt->p.archivedir)
12236 {
12237 donodelog(myrpt,"RXUNKEY,MAIN");
12238 }
12239 }
12240 }
12241 ast_frfree(f);
12242 continue;
12243 }
12244 if (who == myrpt->pchannel)
12245 {
12246 f = ast_read(myrpt->pchannel);
12247 if (!f)
12248 {
12249 if (debug) printf("@@@@ rpt:Hung Up\n");
12250 break;
12251 }
12252 if (f->frametype == AST_FRAME_VOICE)
12253 {
12254 ast_write(myrpt->txpchannel,f);
12255 }
12256 if (f->frametype == AST_FRAME_CONTROL)
12257 {
12258 if (f->subclass == AST_CONTROL_HANGUP)
12259 {
12260 if (debug) printf("@@@@ rpt:Hung Up\n");
12261 ast_frfree(f);
12262 break;
12263 }
12264 }
12265 ast_frfree(f);
12266 continue;
12267 }
12268 if (who == myrpt->txchannel)
12269 {
12270 f = ast_read(myrpt->txchannel);
12271 if (!f)
12272 {
12273 if (debug) printf("@@@@ rpt:Hung Up\n");
12274 break;
12275 }
12276 if (f->frametype == AST_FRAME_CONTROL)
12277 {
12278 if (f->subclass == AST_CONTROL_HANGUP)
12279 {
12280 if (debug) printf("@@@@ rpt:Hung Up\n");
12281 ast_frfree(f);
12282 break;
12283 }
12284 }
12285 ast_frfree(f);
12286 continue;
12287 }
12288 if (who == myrpt->dahditxchannel)
12289 {
12290 f = ast_read(myrpt->dahditxchannel);
12291 if (!f)
12292 {
12293 if (debug) printf("@@@@ rpt:Hung Up\n");
12294 break;
12295 }
12296 if (f->frametype == AST_FRAME_VOICE)
12297 {
12298 struct ast_frame *vframe;
12299
12300 if (myrpt->p.duplex < 2)
12301 {
12302 if (myrpt->txrealkeyed)
12303 {
12304 if ((!myfirst) && myrpt->callmode)
12305 {
12306 x = 0;
12307 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12308 frame_list) x++;
12309 for(;x < myrpt->p.simplexpatchdelay; x++)
12310 {
12311 vframe = ast_frdup(f);
12312 memset(vframe->data.ptr,0,vframe->datalen);
12313 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12314 }
12315 myfirst = 1;
12316 }
12317 vframe = ast_frdup(f);
12318 AST_LIST_INSERT_TAIL(&myrpt->txq,
12319 vframe,frame_list);
12320 } else myfirst = 0;
12321 x = 0;
12322 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12323 frame_list) x++;
12324 if (!x)
12325 {
12326 memset(f->data.ptr,0,f->datalen);
12327 }
12328 else
12329 {
12330 ast_frfree(f);
12331 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12332 frame_list);
12333 }
12334 }
12335 else
12336 {
12337 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12338 frame_list))) ast_frfree(vframe);
12339 }
12340 ast_write(myrpt->txchannel,f);
12341 }
12342 if (f->frametype == AST_FRAME_CONTROL)
12343 {
12344 if (f->subclass == AST_CONTROL_HANGUP)
12345 {
12346 if (debug) printf("@@@@ rpt:Hung Up\n");
12347 ast_frfree(f);
12348 break;
12349 }
12350 }
12351 ast_frfree(f);
12352 continue;
12353 }
12354 toexit = 0;
12355 rpt_mutex_lock(&myrpt->lock);
12356 l = myrpt->links.next;
12357 while(l != &myrpt->links)
12358 {
12359 int remnomute;
12360 struct timeval now;
12361
12362 if (l->disctime)
12363 {
12364 l = l->next;
12365 continue;
12366 }
12367
12368 remrx = 0;
12369
12370 m = myrpt->links.next;
12371 while(m != &myrpt->links)
12372 {
12373
12374 if ((m != l) && (m->lastrx)) remrx = 1;
12375 m = m->next;
12376 }
12377 rpt_mutex_unlock(&myrpt->lock);
12378 now = ast_tvnow();
12379 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12380 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12381 {
12382 l->lastlinktv = now;
12383 remnomute = myrpt->localtx &&
12384 (!(myrpt->cmdnode[0] ||
12385 (myrpt->dtmfidx > -1)));
12386 totx = (((l->isremote) ? (remnomute) :
12387 myrpt->exttx) || remrx) && l->mode;
12388 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12389 {
12390 if (totx)
12391 {
12392 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12393 }
12394 else
12395 {
12396 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12397 }
12398 if (myrpt->p.archivedir)
12399 {
12400 char str[100];
12401
12402 if (totx)
12403 sprintf(str,"TXKEY,%s",l->name);
12404 else
12405 sprintf(str,"TXUNKEY,%s",l->name);
12406 donodelog(myrpt,str);
12407 }
12408 }
12409 l->lasttx = totx;
12410 }
12411 rpt_mutex_lock(&myrpt->lock);
12412 if (who == l->chan)
12413 {
12414 rpt_mutex_unlock(&myrpt->lock);
12415 f = ast_read(l->chan);
12416 if (!f)
12417 {
12418 rpt_mutex_lock(&myrpt->lock);
12419 __kickshort(myrpt);
12420 rpt_mutex_unlock(&myrpt->lock);
12421 if ((!l->disced) && (!l->outbound))
12422 {
12423 if ((l->name[0] == '0') || l->isremote)
12424 l->disctime = 1;
12425 else
12426 l->disctime = DISC_TIME;
12427 rpt_mutex_lock(&myrpt->lock);
12428 ast_hangup(l->chan);
12429 l->chan = 0;
12430 break;
12431 }
12432
12433 if (l->retrytimer)
12434 {
12435 ast_hangup(l->chan);
12436 l->chan = 0;
12437 rpt_mutex_lock(&myrpt->lock);
12438 break;
12439 }
12440 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12441 {
12442 rpt_mutex_lock(&myrpt->lock);
12443 if (l->chan) ast_hangup(l->chan);
12444 l->chan = 0;
12445 l->hasconnected = 1;
12446 l->retrytimer = RETRY_TIMER_MS;
12447 l->elaptime = 0;
12448 l->connecttime = 0;
12449 l->thisconnected = 0;
12450 break;
12451 }
12452 rpt_mutex_lock(&myrpt->lock);
12453
12454 remque((struct qelem *) l);
12455 if (!strcmp(myrpt->cmdnode,l->name))
12456 myrpt->cmdnode[0] = 0;
12457 __kickshort(myrpt);
12458 rpt_mutex_unlock(&myrpt->lock);
12459 if (!l->hasconnected)
12460 rpt_telemetry(myrpt,CONNFAIL,l);
12461 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12462 if (myrpt->p.archivedir)
12463 {
12464 char str[100];
12465
12466 if (!l->hasconnected)
12467 sprintf(str,"LINKFAIL,%s",l->name);
12468 else
12469 sprintf(str,"LINKDISC,%s",l->name);
12470 donodelog(myrpt,str);
12471 }
12472 if (l->lastf1) ast_frfree(l->lastf1);
12473 l->lastf1 = NULL;
12474 if (l->lastf2) ast_frfree(l->lastf2);
12475 l->lastf2 = NULL;
12476
12477 ast_hangup(l->chan);
12478 ast_hangup(l->pchan);
12479 ast_free(l);
12480 rpt_mutex_lock(&myrpt->lock);
12481 break;
12482 }
12483 if (f->frametype == AST_FRAME_VOICE)
12484 {
12485 int ismuted,n1;
12486
12487 if ((l->phonemode) && (l->phonevox))
12488 {
12489 n1 = dovox(&l->vox,
12490 f->data.ptr,f->datalen / 2);
12491 if (n1 != l->wasvox)
12492 {
12493 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12494 l->wasvox = n1;
12495 l->voxtostate = 0;
12496 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12497 else l->voxtotimer = 0;
12498 }
12499 if (l->lastrealrx || n1)
12500 {
12501 if (!myfirst)
12502 {
12503 x = 0;
12504 AST_LIST_TRAVERSE(&l->rxq, f1,
12505 frame_list) x++;
12506 for(;x < myrpt->p.simplexphonedelay; x++)
12507 {
12508 f1 = ast_frdup(f);
12509 memset(f1->data.ptr,0,f1->datalen);
12510 AST_LIST_INSERT_TAIL(&l->rxq,
12511 f1,frame_list);
12512 }
12513 myfirst = 1;
12514 }
12515 f1 = ast_frdup(f);
12516 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12517 } else myfirst = 0;
12518 x = 0;
12519 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12520 if (!x)
12521 {
12522 memset(f->data.ptr,0,f->datalen);
12523 }
12524 else
12525 {
12526 ast_frfree(f);
12527 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12528 }
12529 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12530 {
12531 ismuted = 0;
12532 }
12533
12534 ismuted |= (!l->lastrx);
12535 if (l->dtmfed && l->phonemode) ismuted = 1;
12536 l->dtmfed = 0;
12537 if (ismuted)
12538 {
12539 memset(f->data.ptr,0,f->datalen);
12540 if (l->lastf1)
12541 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12542 if (l->lastf2)
12543 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12544 }
12545 if (f) f2 = ast_frdup(f);
12546 else f2 = NULL;
12547 f1 = l->lastf2;
12548 l->lastf2 = l->lastf1;
12549 l->lastf1 = f2;
12550 if (ismuted)
12551 {
12552 if (l->lastf1)
12553 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12554 if (l->lastf2)
12555 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12556 }
12557 if (f1)
12558 {
12559 ast_write(l->pchan,f1);
12560 ast_frfree(f1);
12561 }
12562 }
12563 else
12564 {
12565 if (!l->lastrx)
12566 memset(f->data.ptr,0,f->datalen);
12567 ast_write(l->pchan,f);
12568 }
12569 }
12570 #ifndef OLD_ASTERISK
12571 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12572 {
12573 if (l->lastf1)
12574 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12575 if (l->lastf2)
12576 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12577 l->dtmfed = 1;
12578 }
12579 #endif
12580 if (f->frametype == AST_FRAME_TEXT)
12581 {
12582 handle_link_data(myrpt,l,f->data.ptr);
12583 }
12584 if (f->frametype == AST_FRAME_DTMF)
12585 {
12586 if (l->lastf1)
12587 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12588 if (l->lastf2)
12589 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12590 l->dtmfed = 1;
12591 handle_link_phone_dtmf(myrpt,l,f->subclass);
12592 }
12593 if (f->frametype == AST_FRAME_CONTROL)
12594 {
12595 if (f->subclass == AST_CONTROL_ANSWER)
12596 {
12597 char lconnected = l->connected;
12598
12599 __kickshort(myrpt);
12600 l->connected = 1;
12601 l->hasconnected = 1;
12602 l->thisconnected = 1;
12603 l->elaptime = -1;
12604 if (!l->phonemode) send_newkey(l->chan);
12605 if (!l->isremote) l->retries = 0;
12606 if (!lconnected)
12607 {
12608 rpt_telemetry(myrpt,CONNECTED,l);
12609 if (myrpt->p.archivedir)
12610 {
12611 char str[100];
12612
12613 if (l->mode)
12614 sprintf(str,"LINKTRX,%s",l->name);
12615 else
12616 sprintf(str,"LINKMONITOR,%s",l->name);
12617 donodelog(myrpt,str);
12618 }
12619 }
12620 else
12621 l->reconnects++;
12622 }
12623
12624 if (f->subclass == AST_CONTROL_RADIO_KEY)
12625 {
12626 if (debug == 7 ) printf("@@@@ rx key\n");
12627 l->lastrealrx = 1;
12628 l->rerxtimer = 0;
12629 if (!l->lastrx1)
12630 {
12631 if (myrpt->p.archivedir)
12632 {
12633 char str[100];
12634
12635 sprintf(str,"RXKEY,%s",l->name);
12636 donodelog(myrpt,str);
12637 }
12638 l->lastrx1 = 1;
12639 }
12640 }
12641
12642 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12643 {
12644 if (debug == 7) printf("@@@@ rx un-key\n");
12645 l->lastrealrx = 0;
12646 l->rerxtimer = 0;
12647 if (l->lastrx1)
12648 {
12649 if (myrpt->p.archivedir)
12650 {
12651 char str[100];
12652
12653 sprintf(str,"RXUNKEY,%s",l->name);
12654 donodelog(myrpt,str);
12655 }
12656 l->lastrx1 = 0;
12657 if(myrpt->p.duplex)
12658 rpt_telemetry(myrpt,LINKUNKEY,l);
12659 }
12660 }
12661 if (f->subclass == AST_CONTROL_HANGUP)
12662 {
12663 ast_frfree(f);
12664 rpt_mutex_lock(&myrpt->lock);
12665 __kickshort(myrpt);
12666 rpt_mutex_unlock(&myrpt->lock);
12667 if ((!l->outbound) && (!l->disced))
12668 {
12669 if ((l->name[0] == '0') || l->isremote)
12670 l->disctime = 1;
12671 else
12672 l->disctime = DISC_TIME;
12673 rpt_mutex_lock(&myrpt->lock);
12674 ast_hangup(l->chan);
12675 l->chan = 0;
12676 break;
12677 }
12678 if (l->retrytimer)
12679 {
12680 if (l->chan) ast_hangup(l->chan);
12681 l->chan = 0;
12682 rpt_mutex_lock(&myrpt->lock);
12683 break;
12684 }
12685 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12686 {
12687 rpt_mutex_lock(&myrpt->lock);
12688 if (l->chan) ast_hangup(l->chan);
12689 l->chan = 0;
12690 l->hasconnected = 1;
12691 l->elaptime = 0;
12692 l->retrytimer = RETRY_TIMER_MS;
12693 l->connecttime = 0;
12694 l->thisconnected = 0;
12695 break;
12696 }
12697 rpt_mutex_lock(&myrpt->lock);
12698
12699 remque((struct qelem *) l);
12700 if (!strcmp(myrpt->cmdnode,l->name))
12701 myrpt->cmdnode[0] = 0;
12702 __kickshort(myrpt);
12703 rpt_mutex_unlock(&myrpt->lock);
12704 if (!l->hasconnected)
12705 rpt_telemetry(myrpt,CONNFAIL,l);
12706 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12707 if (myrpt->p.archivedir)
12708 {
12709 char str[100];
12710
12711 if (!l->hasconnected)
12712 sprintf(str,"LINKFAIL,%s",l->name);
12713 else
12714 sprintf(str,"LINKDISC,%s",l->name);
12715 donodelog(myrpt,str);
12716 }
12717 if (l->lastf1) ast_frfree(l->lastf1);
12718 l->lastf1 = NULL;
12719 if (l->lastf2) ast_frfree(l->lastf2);
12720 l->lastf2 = NULL;
12721
12722 ast_hangup(l->chan);
12723 ast_hangup(l->pchan);
12724 ast_free(l);
12725 rpt_mutex_lock(&myrpt->lock);
12726 break;
12727 }
12728 }
12729 ast_frfree(f);
12730 rpt_mutex_lock(&myrpt->lock);
12731 break;
12732 }
12733 if (who == l->pchan)
12734 {
12735 rpt_mutex_unlock(&myrpt->lock);
12736 f = ast_read(l->pchan);
12737 if (!f)
12738 {
12739 if (debug) printf("@@@@ rpt:Hung Up\n");
12740 toexit = 1;
12741 rpt_mutex_lock(&myrpt->lock);
12742 break;
12743 }
12744 if (f->frametype == AST_FRAME_VOICE)
12745 {
12746 if (l->chan) ast_write(l->chan,f);
12747 }
12748 if (f->frametype == AST_FRAME_CONTROL)
12749 {
12750 if (f->subclass == AST_CONTROL_HANGUP)
12751 {
12752 if (debug) printf("@@@@ rpt:Hung Up\n");
12753 ast_frfree(f);
12754 toexit = 1;
12755 rpt_mutex_lock(&myrpt->lock);
12756 break;
12757 }
12758 }
12759 ast_frfree(f);
12760 rpt_mutex_lock(&myrpt->lock);
12761 break;
12762 }
12763 l = l->next;
12764 }
12765 rpt_mutex_unlock(&myrpt->lock);
12766 if (toexit) break;
12767 if (who == myrpt->monchannel)
12768 {
12769 f = ast_read(myrpt->monchannel);
12770 if (!f)
12771 {
12772 if (debug) printf("@@@@ rpt:Hung Up\n");
12773 break;
12774 }
12775 if (f->frametype == AST_FRAME_VOICE)
12776 {
12777 if (myrpt->monstream)
12778 ast_writestream(myrpt->monstream,f);
12779 }
12780 if (f->frametype == AST_FRAME_CONTROL)
12781 {
12782 if (f->subclass == AST_CONTROL_HANGUP)
12783 {
12784 if (debug) printf("@@@@ rpt:Hung Up\n");
12785 ast_frfree(f);
12786 break;
12787 }
12788 }
12789 ast_frfree(f);
12790 continue;
12791 }
12792 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12793 {
12794 f = ast_read(myrpt->parrotchannel);
12795 if (!f)
12796 {
12797 if (debug) printf("@@@@ rpt:Hung Up\n");
12798 break;
12799 }
12800 if (!myrpt->p.parrotmode)
12801 {
12802 char myfname[300];
12803
12804 if (myrpt->parrotstream)
12805 {
12806 ast_closestream(myrpt->parrotstream);
12807 myrpt->parrotstream = 0;
12808 }
12809 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12810 strcat(myfname,".wav");
12811 unlink(myfname);
12812 } else if (f->frametype == AST_FRAME_VOICE)
12813 {
12814 if (myrpt->parrotstream)
12815 ast_writestream(myrpt->parrotstream,f);
12816 }
12817 if (f->frametype == AST_FRAME_CONTROL)
12818 {
12819 if (f->subclass == AST_CONTROL_HANGUP)
12820 {
12821 if (debug) printf("@@@@ rpt:Hung Up\n");
12822 ast_frfree(f);
12823 break;
12824 }
12825 }
12826 ast_frfree(f);
12827 continue;
12828 }
12829 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12830 {
12831 f = ast_read(myrpt->voxchannel);
12832 if (!f)
12833 {
12834 if (debug) printf("@@@@ rpt:Hung Up\n");
12835 break;
12836 }
12837 if (f->frametype == AST_FRAME_VOICE)
12838 {
12839 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12840 if (n != myrpt->wasvox)
12841 {
12842 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12843 myrpt->wasvox = n;
12844 myrpt->voxtostate = 0;
12845 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12846 else myrpt->voxtotimer = 0;
12847 }
12848 }
12849 if (f->frametype == AST_FRAME_CONTROL)
12850 {
12851 if (f->subclass == AST_CONTROL_HANGUP)
12852 {
12853 if (debug) printf("@@@@ rpt:Hung Up\n");
12854 ast_frfree(f);
12855 break;
12856 }
12857 }
12858 ast_frfree(f);
12859 continue;
12860 }
12861 if (who == myrpt->txpchannel)
12862 {
12863 f = ast_read(myrpt->txpchannel);
12864 if (!f)
12865 {
12866 if (debug) printf("@@@@ rpt:Hung Up\n");
12867 break;
12868 }
12869 if (f->frametype == AST_FRAME_CONTROL)
12870 {
12871 if (f->subclass == AST_CONTROL_HANGUP)
12872 {
12873 if (debug) printf("@@@@ rpt:Hung Up\n");
12874 ast_frfree(f);
12875 break;
12876 }
12877 }
12878 ast_frfree(f);
12879 continue;
12880 }
12881 }
12882 usleep(100000);
12883 ast_hangup(myrpt->pchannel);
12884 ast_hangup(myrpt->monchannel);
12885 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12886 myrpt->parrotstate = 0;
12887 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12888 ast_hangup(myrpt->txpchannel);
12889 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12890 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12891 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12892 myrpt->lastf1 = NULL;
12893 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12894 myrpt->lastf2 = NULL;
12895 ast_hangup(myrpt->rxchannel);
12896 rpt_mutex_lock(&myrpt->lock);
12897 l = myrpt->links.next;
12898 while(l != &myrpt->links)
12899 {
12900 struct rpt_link *ll = l;
12901
12902 remque((struct qelem *) l);
12903
12904 if (l->chan) ast_hangup(l->chan);
12905 ast_hangup(l->pchan);
12906 l = l->next;
12907 ast_free(ll);
12908 }
12909 if (myrpt->xlink == 1) myrpt->xlink = 2;
12910 rpt_mutex_unlock(&myrpt->lock);
12911 if (debug) printf("@@@@ rpt:Hung up channel\n");
12912 myrpt->rpt_thread = AST_PTHREADT_STOP;
12913 pthread_exit(NULL);
12914 return NULL;
12915 }
12916
12917
12918 static void *rpt_master(void *ignore)
12919 {
12920 int i,n;
12921 pthread_attr_t attr;
12922 struct ast_config *cfg;
12923 char *this,*val;
12924
12925
12926 nodelog.next = nodelog.prev = &nodelog;
12927
12928 this = NULL;
12929 n = 0;
12930 #ifndef OLD_ASTERISK
12931
12932 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12933 usleep(250000);
12934 #endif
12935 #ifdef NEW_ASTERISK
12936 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12937 #else
12938 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12939 #endif
12940 cfg = rpt_vars[n].cfg;
12941 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12942 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12943 pthread_exit(NULL);
12944 }
12945 while((this = ast_category_browse(cfg,this)) != NULL)
12946 {
12947 for(i = 0 ; i < strlen(this) ; i++){
12948 if((this[i] < '0') || (this[i] > '9'))
12949 break;
12950 }
12951 if(i != strlen(this)) continue;
12952 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12953 rpt_vars[n].name = ast_strdup(this);
12954 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12955 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12956 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12957 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12958 rpt_vars[n].remote = 0;
12959 rpt_vars[n].remoterig = "";
12960 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12961 if (val)
12962 {
12963 rpt_vars[n].remoterig = ast_strdup(val);
12964 rpt_vars[n].remote = 1;
12965 }
12966 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12967 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12968 ast_mutex_init(&rpt_vars[n].lock);
12969 ast_mutex_init(&rpt_vars[n].remlock);
12970 ast_mutex_init(&rpt_vars[n].statpost_lock);
12971 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12972 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12973 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12974 rpt_vars[n].tailmessagen = 0;
12975 #ifdef _MDC_DECODE_H_
12976 rpt_vars[n].mdc = mdc_decoder_new(8000);
12977 #endif
12978 n++;
12979 }
12980 nrpts = n;
12981 ast_config_destroy(cfg);
12982
12983
12984 for(i = 0; i < n; i++)
12985 {
12986 load_rpt_vars(i,1);
12987
12988
12989 if (rpt_vars[i].remote)
12990 {
12991 if(retreive_memory(&rpt_vars[i],"init")){
12992 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
12993 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
12994 else
12995 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
12996 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
12997
12998 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
12999 rpt_vars[i].remmode = REM_MODE_FM;
13000 rpt_vars[i].offset = REM_SIMPLEX;
13001 rpt_vars[i].powerlevel = REM_LOWPWR;
13002 }
13003 continue;
13004 }
13005 else
13006 {
13007 rpt_vars[i].p.memory = rpt_vars[i].name;
13008 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13009 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13010 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13011 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13012 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13013 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13014
13015 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13016 rpt_vars[i].remmode = REM_MODE_FM;
13017 rpt_vars[i].offset = REM_SIMPLEX;
13018 rpt_vars[i].powerlevel = REM_LOWPWR;
13019 }
13020 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13021 }
13022 if (!rpt_vars[i].p.ident)
13023 {
13024 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13025 ast_config_destroy(cfg);
13026 pthread_exit(NULL);
13027 }
13028 pthread_attr_init(&attr);
13029 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13030 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13031 }
13032 usleep(500000);
13033 time(&starttime);
13034 for(;;)
13035 {
13036
13037 for(i = 0; i < n; i++)
13038 {
13039 int rv;
13040 if (rpt_vars[i].remote) continue;
13041 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13042 rv = -1;
13043 else
13044 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13045 if (rv)
13046 {
13047 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13048 {
13049 if(rpt_vars[i].threadrestarts >= 5)
13050 {
13051 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13052 exit(1);
13053 }
13054 else
13055 {
13056 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13057 rpt_vars[i].threadrestarts++;
13058 }
13059 }
13060 else
13061 rpt_vars[i].threadrestarts = 0;
13062
13063 rpt_vars[i].lastthreadrestarttime = time(NULL);
13064 pthread_attr_init(&attr);
13065 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13066 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13067
13068 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13069 }
13070
13071 }
13072 for(;;)
13073 {
13074 struct nodelog *nodep;
13075 char *space,datestr[100],fname[300];
13076 int fd;
13077
13078 ast_mutex_lock(&nodeloglock);
13079 nodep = nodelog.next;
13080 if(nodep == &nodelog)
13081 {
13082 ast_mutex_unlock(&nodeloglock);
13083 break;
13084 }
13085 remque((struct qelem *)nodep);
13086 ast_mutex_unlock(&nodeloglock);
13087 space = strchr(nodep->str,' ');
13088 if (!space)
13089 {
13090 ast_free(nodep);
13091 continue;
13092 }
13093 *space = 0;
13094 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13095 localtime(&nodep->timestamp));
13096 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13097 nodep->str,datestr);
13098 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13099 if (fd == -1)
13100 {
13101 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13102 ast_free(nodep);
13103 continue;
13104 }
13105 if (write(fd,space + 1,strlen(space + 1)) !=
13106 strlen(space + 1))
13107 {
13108 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13109 ast_free(nodep);
13110 continue;
13111 }
13112 close(fd);
13113 ast_free(nodep);
13114 }
13115 sleep(2);
13116 }
13117 ast_config_destroy(cfg);
13118 pthread_exit(NULL);
13119 }
13120
13121 static int rpt_exec(struct ast_channel *chan, void *data)
13122 {
13123 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13124 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13125 int ismuted,dtmfed,phone_vox = 0;
13126 #ifdef OLD_ASTERISK
13127 struct localuser *u;
13128 #endif
13129 char tmp[256], keyed = 0,keyed1 = 0;
13130 char *options,*stringp,*tele,c,*altp,*memp;
13131 char sx[320],*sy;
13132 struct rpt *myrpt;
13133 struct ast_frame *f,*f1,*f2;
13134 struct ast_channel *who;
13135 struct ast_channel *cs[20];
13136 struct rpt_link *l;
13137 struct dahdi_confinfo ci;
13138 struct dahdi_params par;
13139 int ms,elap,nullfd;
13140 time_t t,last_timeout_warning;
13141 struct dahdi_radio_param z;
13142 struct rpt_tele *telem;
13143 int numlinks;
13144
13145 nullfd = open("/dev/null",O_RDWR);
13146 if (ast_strlen_zero(data)) {
13147 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13148 return -1;
13149 }
13150
13151 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13152 time(&t);
13153
13154 if (t < starttime) t = starttime + START_DELAY;
13155 if ((!starttime) || (t < (starttime + START_DELAY)))
13156 {
13157 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13158 ast_safe_sleep(chan,3000);
13159 return -1;
13160 }
13161
13162 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13163
13164 altp=strstr(tmp, "|*");
13165 if(altp){
13166 altp[0]=0;
13167 altp++;
13168 }
13169
13170 memp=strstr(tmp, "|M");
13171 if(memp){
13172 memp[0]=0;
13173 memp+=2;
13174 }
13175
13176 stringp=tmp;
13177 strsep(&stringp, "|");
13178 options = stringp;
13179
13180 ast_log(LOG_NOTICE,"options=%s \n",options);
13181 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13182 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13183
13184 myrpt = NULL;
13185
13186 for(i = 0; i < nrpts; i++)
13187 {
13188
13189 if (!strcmp(tmp,rpt_vars[i].name))
13190 {
13191 myrpt = &rpt_vars[i];
13192 break;
13193 }
13194 }
13195
13196 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13197
13198 if (myrpt == NULL)
13199 {
13200 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13201 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13202 return (priority_jump(NULL,chan));
13203 }
13204
13205 numlinks=linkcount(myrpt);
13206
13207 if(options && *options == 'q')
13208 {
13209 char buf2[128];
13210
13211 if(myrpt->keyed)
13212 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13213 else
13214 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13215
13216 if(myrpt->txkeyed)
13217 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13218 else
13219 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13220
13221 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13222 pbx_builtin_setvar(chan, buf2);
13223 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13224 pbx_builtin_setvar(chan, buf2);
13225 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13226 pbx_builtin_setvar(chan, buf2);
13227 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13228 pbx_builtin_setvar(chan, buf2);
13229 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13230 pbx_builtin_setvar(chan, buf2);
13231 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13232 pbx_builtin_setvar(chan, buf2);
13233
13234
13235
13236
13237 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13238 pbx_builtin_setvar(chan, buf2);
13239 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13240 pbx_builtin_setvar(chan, buf2);
13241
13242 return priority_jump(myrpt,chan);
13243 }
13244
13245 if(options && *options == 'o')
13246 {
13247 return(channel_revert(myrpt));
13248 }
13249
13250 #if 0
13251 if((altp)&&(*options == 'Z'))
13252 {
13253 rpt_push_alt_macro(myrpt,altp);
13254 return 0;
13255 }
13256 #endif
13257
13258
13259
13260 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13261 {
13262 int val;
13263
13264 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13265
13266 myrpt->bargechan=0;
13267 if(options && strstr(options, "f")>0)
13268 {
13269 myrpt->bargechan=1;
13270 }
13271
13272 if(memp>0)
13273 {
13274 char radiochan;
13275 radiochan=strtod(data,NULL);
13276
13277
13278 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13279 {
13280 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13281 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13282 return (priority_jump(myrpt,chan));
13283 }
13284 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13285 {
13286 channel_steer(myrpt,memp);
13287 }
13288 }
13289 if(altp)rpt_push_alt_macro(myrpt,altp);
13290 phone_mode = 1;
13291 if (*options == 'D') phone_mode = 2;
13292 if (*options == 'S') phone_mode = 3;
13293 ast_set_callerid(chan,"0","app_rpt user","0");
13294 val = 1;
13295 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13296 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13297 }
13298 else
13299 {
13300 #ifdef ALLOW_LOCAL_CHANNELS
13301
13302 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13303 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13304 return -1;
13305 }
13306 #else
13307 if (strncmp(chan->name,"IAX2",4))
13308 {
13309 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13310 return -1;
13311 }
13312 #endif
13313 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13314 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13315 return -1;
13316 }
13317 }
13318 if (options && (*options == 'R'))
13319 {
13320
13321 char *return_context;
13322 int length, m, lot, timeout = 0;
13323 char buffer[256],*template;
13324 char *working, *context, *exten, *priority;
13325 char *s,*orig_s;
13326
13327 rpt_mutex_lock(&myrpt->lock);
13328 m = myrpt->callmode;
13329 rpt_mutex_unlock(&myrpt->lock);
13330
13331 if ((!myrpt->p.nobusyout) && m)
13332 {
13333 if (chan->_state != AST_STATE_UP)
13334 {
13335 ast_indicate(chan,AST_CONTROL_BUSY);
13336 }
13337 while(ast_safe_sleep(chan,10000) != -1);
13338 return -1;
13339 }
13340
13341 if (chan->_state != AST_STATE_UP)
13342 {
13343 ast_answer(chan);
13344 if (!phone_mode) send_newkey(chan);
13345 }
13346
13347 length=strlen(options)+2;
13348 orig_s=ast_malloc(length);
13349 if(!orig_s) {
13350 ast_log(LOG_WARNING, "Out of memory\n");
13351 return -1;
13352 }
13353 s=orig_s;
13354 strncpy(s,options,length);
13355
13356 template=strsep(&s,"|");
13357 if(!template) {
13358 ast_log(LOG_WARNING, "An announce template must be defined\n");
13359 ast_free(orig_s);
13360 return -1;
13361 }
13362
13363 if(s) {
13364 timeout = atoi(strsep(&s, "|"));
13365 timeout *= 1000;
13366 }
13367
13368 return_context = s;
13369
13370 if(return_context != NULL) {
13371
13372
13373 working = return_context;
13374 context = strsep(&working, "|");
13375 exten = strsep(&working, "|");
13376 if(!exten) {
13377
13378 priority = context;
13379 exten = NULL;
13380 context = NULL;
13381 } else {
13382 priority = strsep(&working, "|");
13383 if(!priority) {
13384
13385 priority = exten;
13386 exten = context;
13387 context = NULL;
13388 }
13389 }
13390 if(atoi(priority) < 0) {
13391 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13392 ast_free(orig_s);
13393 return -1;
13394 }
13395
13396 chan->priority = atoi(priority);
13397 #ifdef OLD_ASTERISK
13398 if(exten && strcasecmp(exten, "BYEXTENSION"))
13399 #else
13400 if(exten)
13401 #endif
13402 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13403 if(context)
13404 strncpy(chan->context, context, sizeof(chan->context)-1);
13405 } else {
13406 chan->priority++;
13407 }
13408
13409 if(option_verbose > 2) {
13410 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
13411 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
13412 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13413 }
13414 }
13415
13416
13417
13418
13419 ast_masq_park_call(chan, NULL, timeout, &lot);
13420
13421 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13422
13423 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13424
13425 rpt_telemetry(myrpt,REV_PATCH,buffer);
13426
13427 ast_free(orig_s);
13428
13429 return 0;
13430
13431 }
13432
13433 if (!options)
13434 {
13435 struct ast_hostent ahp;
13436 struct hostent *hp;
13437 struct in_addr ia;
13438 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13439
13440
13441 if (!chan->cid.cid_num)
13442 {
13443 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13444 return -1;
13445 }
13446
13447 memset(hisip,0,sizeof(hisip));
13448 #ifdef ALLOW_LOCAL_CHANNELS
13449
13450 if (strncmp(chan->name,"Local",5)==0) {
13451 strcpy(hisip,"127.0.0.1");
13452 } else {
13453 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13454 }
13455 #else
13456 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13457 #endif
13458
13459 if (!hisip[0])
13460 {
13461 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13462 return -1;
13463 }
13464
13465 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13466 ast_shrink_phone_number(b1);
13467 if (!strcmp(myrpt->name,b1))
13468 {
13469 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13470 return -1;
13471 }
13472
13473 if (*b1 < '1')
13474 {
13475 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13476 return -1;
13477 }
13478
13479
13480
13481 val = node_lookup(myrpt,b1);
13482 if (!val)
13483 {
13484 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13485 return -1;
13486 }
13487 strncpy(tmp,val,sizeof(tmp) - 1);
13488 s = tmp;
13489 s1 = strsep(&s,",");
13490 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13491 {
13492 sy = strchr(s1,'/');
13493 *sy = 0;
13494 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13495 s1 = sx;
13496 }
13497 s2 = strsep(&s,",");
13498 if (!s2)
13499 {
13500 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13501 return -1;
13502 }
13503 if (strcmp(s2,"NONE")) {
13504 hp = ast_gethostbyname(s2, &ahp);
13505 if (!hp)
13506 {
13507 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13508 return -1;
13509 }
13510 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13511 #ifdef OLD_ASTERISK
13512 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13513 #else
13514 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13515 #endif
13516 s3 = strchr(hisip,':');
13517 if (s3) *s3 = 0;
13518 if (strcmp(hisip,nodeip))
13519 {
13520 s3 = strchr(s1,'@');
13521 if (s3) s1 = s3 + 1;
13522 s3 = strchr(s1,'/');
13523 if (s3) *s3 = 0;
13524 s3 = strchr(s1,':');
13525 if (s3) *s3 = 0;
13526 hp = ast_gethostbyname(s1, &ahp);
13527 if (!hp)
13528 {
13529 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13530 return -1;
13531 }
13532 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13533 #ifdef OLD_ASTERISK
13534 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13535 #else
13536 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13537 #endif
13538 if (strcmp(hisip,nodeip))
13539 {
13540 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13541 return -1;
13542 }
13543 }
13544 }
13545 }
13546
13547
13548 if (!myrpt->remote)
13549 {
13550 char *b,*b1;
13551 int reconnects = 0;
13552
13553 rpt_mutex_lock(&myrpt->lock);
13554 i = myrpt->xlink;
13555 rpt_mutex_unlock(&myrpt->lock);
13556 if (i)
13557 {
13558 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13559 return -1;
13560 }
13561
13562 if (!chan->cid.cid_num)
13563 {
13564 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13565 return -1;
13566 }
13567
13568 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13569 ast_shrink_phone_number(b1);
13570 if (!strcmp(myrpt->name,b1))
13571 {
13572 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13573 return -1;
13574 }
13575 rpt_mutex_lock(&myrpt->lock);
13576 l = myrpt->links.next;
13577
13578 while(l != &myrpt->links)
13579 {
13580 if (l->name[0] == '0')
13581 {
13582 l = l->next;
13583 continue;
13584 }
13585
13586 if (!strcmp(l->name,b1)) break;
13587 l = l->next;
13588 }
13589
13590 if (l != &myrpt->links)
13591 {
13592 l->killme = 1;
13593 l->retries = l->max_retries + 1;
13594 l->disced = 2;
13595 reconnects = l->reconnects;
13596 reconnects++;
13597 rpt_mutex_unlock(&myrpt->lock);
13598 usleep(500000);
13599 } else
13600 rpt_mutex_unlock(&myrpt->lock);
13601
13602 l = ast_malloc(sizeof(struct rpt_link));
13603 if (!l)
13604 {
13605 ast_log(LOG_WARNING, "Unable to malloc\n");
13606 pthread_exit(NULL);
13607 }
13608
13609 memset((char *)l,0,sizeof(struct rpt_link));
13610 l->mode = 1;
13611 strncpy(l->name,b1,MAXNODESTR - 1);
13612 l->isremote = 0;
13613 l->chan = chan;
13614 l->connected = 1;
13615 l->thisconnected = 1;
13616 l->hasconnected = 1;
13617 l->reconnects = reconnects;
13618 l->phonemode = phone_mode;
13619 l->phonevox = phone_vox;
13620 l->lastf1 = NULL;
13621 l->lastf2 = NULL;
13622 l->dtmfed = 0;
13623 voxinit_link(l,1);
13624 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13625 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13626
13627 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13628 if (!l->pchan)
13629 {
13630 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13631 pthread_exit(NULL);
13632 }
13633 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13634 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13635 #ifdef AST_CDR_FLAG_POST_DISABLED
13636 if (l->pchan->cdr)
13637 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13638 #endif
13639
13640 ci.chan = 0;
13641 ci.confno = myrpt->conf;
13642 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13643
13644 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13645 {
13646 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13647 pthread_exit(NULL);
13648 }
13649 rpt_mutex_lock(&myrpt->lock);
13650 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13651 l->max_retries = MAX_RETRIES;
13652
13653 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13654 __kickshort(myrpt);
13655 rpt_mutex_unlock(&myrpt->lock);
13656 if (chan->_state != AST_STATE_UP) {
13657 ast_answer(chan);
13658 if (!phone_mode) send_newkey(chan);
13659 }
13660 if (myrpt->p.archivedir)
13661 {
13662 char str[100];
13663
13664 if (l->phonemode)
13665 sprintf(str,"LINK(P),%s",l->name);
13666 else
13667 sprintf(str,"LINK,%s",l->name);
13668 donodelog(myrpt,str);
13669 }
13670 if (!phone_mode) send_newkey(chan);
13671 return 0;
13672 }
13673
13674 rpt_mutex_lock(&myrpt->lock);
13675
13676 if (myrpt->remoteon)
13677 {
13678 rpt_mutex_unlock(&myrpt->lock);
13679 usleep(500000);
13680 if (myrpt->remoteon)
13681 {
13682 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13683 #ifdef AST_CDR_FLAG_POST_DISABLED
13684 if (chan->cdr)
13685 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13686 #endif
13687 return -1;
13688 }
13689 rpt_mutex_lock(&myrpt->lock);
13690 }
13691 if (myrpt->p.rptnode)
13692 {
13693 char killedit = 0;
13694 time_t now;
13695
13696 time(&now);
13697 for(i = 0; i < nrpts; i++)
13698 {
13699 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13700 {
13701 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13702 rpt_vars[i].keyed ||
13703 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13704 rpt_vars[i].txkeyed ||
13705 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13706 {
13707 rpt_mutex_unlock(&myrpt->lock);
13708 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13709 #ifdef AST_CDR_FLAG_POST_DISABLED
13710 if (chan->cdr)
13711 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13712 #endif
13713 return -1;
13714 }
13715 while(rpt_vars[i].xlink != 3)
13716 {
13717 if (!killedit)
13718 {
13719 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13720 rpt_vars[i].xlink = 1;
13721 killedit = 1;
13722 }
13723 rpt_mutex_unlock(&myrpt->lock);
13724 if (ast_safe_sleep(chan,500) == -1)
13725 {
13726 #ifdef AST_CDR_FLAG_POST_DISABLED
13727 if (chan->cdr)
13728 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13729 #endif
13730 return -1;
13731 }
13732 rpt_mutex_lock(&myrpt->lock);
13733 }
13734 break;
13735 }
13736 }
13737 }
13738
13739 #ifdef HAVE_IOPERM
13740 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13741 (ioperm(myrpt->p.iobase,1,1) == -1))
13742 {
13743 rpt_mutex_unlock(&myrpt->lock);
13744 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13745 return -1;
13746 }
13747 #endif
13748 myrpt->remoteon = 1;
13749 #ifdef OLD_ASTERISK
13750 LOCAL_USER_ADD(u);
13751 #endif
13752 rpt_mutex_unlock(&myrpt->lock);
13753
13754 for(i = 0; i < nrpts; i++)
13755 {
13756 if (&rpt_vars[i] == myrpt)
13757 {
13758 load_rpt_vars(i,0);
13759 break;
13760 }
13761 }
13762 rpt_mutex_lock(&myrpt->lock);
13763 tele = strchr(myrpt->rxchanname,'/');
13764 if (!tele)
13765 {
13766 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13767 rpt_mutex_unlock(&myrpt->lock);
13768 pthread_exit(NULL);
13769 }
13770 *tele++ = 0;
13771 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
13772 myrpt->dahdirxchannel = NULL;
13773 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13774 myrpt->dahdirxchannel = myrpt->rxchannel;
13775 if (myrpt->rxchannel)
13776 {
13777 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13778 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13779 #ifdef AST_CDR_FLAG_POST_DISABLED
13780 if (myrpt->rxchannel->cdr)
13781 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13782 #endif
13783 #ifndef NEW_ASTERISK
13784 myrpt->rxchannel->whentohangup = 0;
13785 #endif
13786 myrpt->rxchannel->appl = "Apprpt";
13787 myrpt->rxchannel->data = "(Link Rx)";
13788 if (option_verbose > 2)
13789 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13790 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13791 rpt_mutex_unlock(&myrpt->lock);
13792 ast_call(myrpt->rxchannel,tele,999);
13793 rpt_mutex_lock(&myrpt->lock);
13794 }
13795 else
13796 {
13797 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13798 rpt_mutex_unlock(&myrpt->lock);
13799 pthread_exit(NULL);
13800 }
13801 *--tele = '/';
13802 myrpt->dahditxchannel = NULL;
13803 if (myrpt->txchanname)
13804 {
13805 tele = strchr(myrpt->txchanname,'/');
13806 if (!tele)
13807 {
13808 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13809 rpt_mutex_unlock(&myrpt->lock);
13810 ast_hangup(myrpt->rxchannel);
13811 pthread_exit(NULL);
13812 }
13813 *tele++ = 0;
13814 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
13815 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13816 myrpt->dahditxchannel = myrpt->txchannel;
13817 if (myrpt->txchannel)
13818 {
13819 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13820 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13821 #ifdef AST_CDR_FLAG_POST_DISABLED
13822 if (myrpt->txchannel->cdr)
13823 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13824 #endif
13825 #ifndef NEW_ASTERISK
13826 myrpt->txchannel->whentohangup = 0;
13827 #endif
13828 myrpt->txchannel->appl = "Apprpt";
13829 myrpt->txchannel->data = "(Link Tx)";
13830 if (option_verbose > 2)
13831 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13832 myrpt->txchanname,tele,myrpt->txchannel->name);
13833 rpt_mutex_unlock(&myrpt->lock);
13834 ast_call(myrpt->txchannel,tele,999);
13835 rpt_mutex_lock(&myrpt->lock);
13836 }
13837 else
13838 {
13839 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13840 rpt_mutex_unlock(&myrpt->lock);
13841 ast_hangup(myrpt->rxchannel);
13842 pthread_exit(NULL);
13843 }
13844 *--tele = '/';
13845 }
13846 else
13847 {
13848 myrpt->txchannel = myrpt->rxchannel;
13849 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13850 myrpt->dahditxchannel = myrpt->rxchannel;
13851 }
13852
13853 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13854 if (!myrpt->pchannel)
13855 {
13856 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13857 rpt_mutex_unlock(&myrpt->lock);
13858 if (myrpt->txchannel != myrpt->rxchannel)
13859 ast_hangup(myrpt->txchannel);
13860 ast_hangup(myrpt->rxchannel);
13861 pthread_exit(NULL);
13862 }
13863 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13864 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13865 #ifdef AST_CDR_FLAG_POST_DISABLED
13866 if (myrpt->pchannel->cdr)
13867 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13868 #endif
13869 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13870 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13871
13872 ci.chan = 0;
13873 ci.confno = -1;
13874 ci.confmode = DAHDI_CONF_CONFANNMON ;
13875
13876 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13877 {
13878 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13879 rpt_mutex_unlock(&myrpt->lock);
13880 ast_hangup(myrpt->pchannel);
13881 if (myrpt->txchannel != myrpt->rxchannel)
13882 ast_hangup(myrpt->txchannel);
13883 ast_hangup(myrpt->rxchannel);
13884 pthread_exit(NULL);
13885 }
13886
13887 myrpt->conf = myrpt->txconf = ci.confno;
13888
13889 myrpt->iofd = -1;
13890 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13891 {
13892 rpt_mutex_unlock(&myrpt->lock);
13893 ast_hangup(myrpt->pchannel);
13894 if (myrpt->txchannel != myrpt->rxchannel)
13895 ast_hangup(myrpt->txchannel);
13896 ast_hangup(myrpt->rxchannel);
13897 pthread_exit(NULL);
13898 }
13899 iskenwood_pci4 = 0;
13900 memset(&z,0,sizeof(z));
13901 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13902 {
13903 z.radpar = DAHDI_RADPAR_REMMODE;
13904 z.data = DAHDI_RADPAR_REM_NONE;
13905 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13906
13907 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13908 {
13909 z.radpar = DAHDI_RADPAR_UIOMODE;
13910 z.data = 1;
13911 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13912 {
13913 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13914 return -1;
13915 }
13916 z.radpar = DAHDI_RADPAR_UIODATA;
13917 z.data = 3;
13918 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13919 {
13920 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13921 return -1;
13922 }
13923 i = DAHDI_OFFHOOK;
13924 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13925 {
13926 ast_log(LOG_ERROR,"Cannot set hook\n");
13927 return -1;
13928 }
13929 iskenwood_pci4 = 1;
13930 }
13931 }
13932 if (myrpt->txchannel == myrpt->dahditxchannel)
13933 {
13934 i = DAHDI_ONHOOK;
13935 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13936
13937 if ((myrpt->iofd < 1) && (!res) &&
13938 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13939 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13940 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13941 {
13942 z.radpar = DAHDI_RADPAR_UIOMODE;
13943 z.data = 1;
13944 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13945 {
13946 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13947 return -1;
13948 }
13949 z.radpar = DAHDI_RADPAR_UIODATA;
13950 z.data = 3;
13951 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13952 {
13953 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13954 return -1;
13955 }
13956 }
13957 }
13958 myrpt->remoterx = 0;
13959 myrpt->remotetx = 0;
13960 myrpt->retxtimer = 0;
13961 myrpt->rerxtimer = 0;
13962 myrpt->remoteon = 1;
13963 myrpt->dtmfidx = -1;
13964 myrpt->dtmfbuf[0] = 0;
13965 myrpt->dtmf_time_rem = 0;
13966 myrpt->hfscanmode = 0;
13967 myrpt->hfscanstatus = 0;
13968 if (myrpt->p.startupmacro)
13969 {
13970 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13971 }
13972 time(&myrpt->start_time);
13973 myrpt->last_activity_time = myrpt->start_time;
13974 last_timeout_warning = 0;
13975 myrpt->reload = 0;
13976 myrpt->tele.next = &myrpt->tele;
13977 myrpt->tele.prev = &myrpt->tele;
13978 myrpt->newkey = 0;
13979 rpt_mutex_unlock(&myrpt->lock);
13980 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13981 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13982 rem_rx = 0;
13983 remkeyed = 0;
13984
13985 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
13986 {
13987 i = 128;
13988 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
13989 }
13990 if (chan->_state != AST_STATE_UP) {
13991 ast_answer(chan);
13992 if (!phone_mode) send_newkey(chan);
13993 }
13994
13995 if (myrpt->rxchannel == myrpt->dahdirxchannel)
13996 {
13997 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
13998 {
13999 if (par.rxisoffhook)
14000 {
14001 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14002 myrpt->remoterx = 1;
14003 remkeyed = 1;
14004 }
14005 }
14006 }
14007 if (myrpt->p.archivedir)
14008 {
14009 char mycmd[100],mydate[100],*b,*b1;
14010 time_t myt;
14011 long blocksleft;
14012
14013
14014 mkdir(myrpt->p.archivedir,0600);
14015 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14016 mkdir(mycmd,0600);
14017 time(&myt);
14018 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14019 localtime(&myt));
14020 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14021 myrpt->p.archivedir,myrpt->name,mydate);
14022 if (myrpt->p.monminblocks)
14023 {
14024 blocksleft = diskavail(myrpt);
14025 if (myrpt->p.remotetimeout)
14026 {
14027 blocksleft -= (myrpt->p.remotetimeout *
14028 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14029 }
14030 if (blocksleft >= myrpt->p.monminblocks)
14031 ast_cli_command(nullfd,mycmd);
14032 } else ast_cli_command(nullfd,mycmd);
14033
14034 if (!chan->cid.cid_num)
14035 {
14036 b1 = "0";
14037 } else {
14038 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14039 ast_shrink_phone_number(b1);
14040 }
14041 sprintf(mycmd,"CONNECT,%s",b1);
14042 donodelog(myrpt,mycmd);
14043 }
14044 myrpt->loginuser[0] = 0;
14045 myrpt->loginlevel[0] = 0;
14046 myrpt->authtelltimer = 0;
14047 myrpt->authtimer = 0;
14048 authtold = 0;
14049 authreq = 0;
14050 if (myrpt->p.authlevel > 1) authreq = 1;
14051 setrem(myrpt);
14052 n = 0;
14053 dtmfed = 0;
14054 cs[n++] = chan;
14055 cs[n++] = myrpt->rxchannel;
14056 cs[n++] = myrpt->pchannel;
14057 if (myrpt->rxchannel != myrpt->txchannel)
14058 cs[n++] = myrpt->txchannel;
14059 if (!phone_mode) send_newkey(chan);
14060
14061 for(;;)
14062 {
14063 if (ast_check_hangup(chan)) break;
14064 if (ast_check_hangup(myrpt->rxchannel)) break;
14065 notremming = 0;
14066 setting = 0;
14067 reming = 0;
14068 telem = myrpt->tele.next;
14069 while(telem != &myrpt->tele)
14070 {
14071 if (telem->mode == SETREMOTE) setting = 1;
14072 if ((telem->mode == SETREMOTE) ||
14073 (telem->mode == SCAN) ||
14074 (telem->mode == TUNE)) reming = 1;
14075 else notremming = 1;
14076 telem = telem->next;
14077 }
14078 if (myrpt->reload)
14079 {
14080 myrpt->reload = 0;
14081
14082 for(i = 0; i < nrpts; i++)
14083 {
14084 if (&rpt_vars[i] == myrpt)
14085 {
14086 load_rpt_vars(i,0);
14087 break;
14088 }
14089 }
14090 }
14091 time(&t);
14092 if (myrpt->p.remotetimeout)
14093 {
14094 time_t r;
14095
14096 r = (t - myrpt->start_time);
14097 if (r >= myrpt->p.remotetimeout)
14098 {
14099 saynode(myrpt,chan,myrpt->name);
14100 sayfile(chan,"rpt/timeout");
14101 ast_safe_sleep(chan,1000);
14102 break;
14103 }
14104 if ((myrpt->p.remotetimeoutwarning) &&
14105 (r >= (myrpt->p.remotetimeout -
14106 myrpt->p.remotetimeoutwarning)) &&
14107 (r <= (myrpt->p.remotetimeout -
14108 myrpt->p.remotetimeoutwarningfreq)))
14109 {
14110 if (myrpt->p.remotetimeoutwarningfreq)
14111 {
14112 if ((t - last_timeout_warning) >=
14113 myrpt->p.remotetimeoutwarningfreq)
14114 {
14115 time(&last_timeout_warning);
14116 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14117 }
14118 }
14119 else
14120 {
14121 if (!last_timeout_warning)
14122 {
14123 time(&last_timeout_warning);
14124 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14125 }
14126 }
14127 }
14128 }
14129 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14130 {
14131 time_t r;
14132
14133 r = (t - myrpt->last_activity_time);
14134 if (r >= myrpt->p.remoteinacttimeout)
14135 {
14136 saynode(myrpt,chan,myrpt->name);
14137 ast_safe_sleep(chan,1000);
14138 break;
14139 }
14140 if ((myrpt->p.remotetimeoutwarning) &&
14141 (r >= (myrpt->p.remoteinacttimeout -
14142 myrpt->p.remotetimeoutwarning)) &&
14143 (r <= (myrpt->p.remoteinacttimeout -
14144 myrpt->p.remotetimeoutwarningfreq)))
14145 {
14146 if (myrpt->p.remotetimeoutwarningfreq)
14147 {
14148 if ((t - last_timeout_warning) >=
14149 myrpt->p.remotetimeoutwarningfreq)
14150 {
14151 time(&last_timeout_warning);
14152 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14153 }
14154 }
14155 else
14156 {
14157 if (!last_timeout_warning)
14158 {
14159 time(&last_timeout_warning);
14160 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14161 }
14162 }
14163 }
14164 }
14165 ms = MSWAIT;
14166 who = ast_waitfor_n(cs,n,&ms);
14167 if (who == NULL) ms = 0;
14168 elap = MSWAIT - ms;
14169 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14170 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14171 if (!ms) continue;
14172
14173 if (myrpt->dtmf_local_timer)
14174 {
14175 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14176 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14177 }
14178 rpt_mutex_lock(&myrpt->lock);
14179 do_dtmf_local(myrpt,0);
14180 rpt_mutex_unlock(&myrpt->lock);
14181
14182 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14183 rem_totx |= keyed && (!myrpt->tunerequest);
14184 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14185 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14186 rem_totx |= myrpt->tunerequest;
14187
14188 if((debug > 6) && rem_totx) {
14189 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);
14190 }
14191 if (keyed && (!keyed1))
14192 {
14193 keyed1 = 1;
14194 }
14195
14196 if (!keyed && (keyed1))
14197 {
14198 time_t myt;
14199
14200 keyed1 = 0;
14201 time(&myt);
14202
14203 if ((myrpt->p.authlevel) &&
14204 (!myrpt->loginlevel[0]) &&
14205 (myt > (t + 3)))
14206 {
14207 authreq = 1;
14208 authtold = 0;
14209 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14210 }
14211 }
14212
14213 if (rem_rx && (!myrpt->remoterx))
14214 {
14215 myrpt->remoterx = 1;
14216 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14217 }
14218 if ((!rem_rx) && (myrpt->remoterx))
14219 {
14220 myrpt->remoterx = 0;
14221 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14222 }
14223
14224 if (authreq && (!myrpt->loginlevel[0]))
14225 {
14226 if ((!authtold) && ((myrpt->authtelltimer += elap)
14227 >= AUTHTELLTIME))
14228 {
14229 authtold = 1;
14230 rpt_telemetry(myrpt,LOGINREQ,NULL);
14231 }
14232 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14233 {
14234 break;
14235 }
14236 }
14237 if (myrpt->newkey)
14238 {
14239 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14240 {
14241 myrpt->retxtimer = 0;
14242 if ((myrpt->remoterx) && (!myrpt->remotetx))
14243 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14244 else
14245 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14246 }
14247
14248 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14249 {
14250 keyed = 0;
14251 myrpt->rerxtimer = 0;
14252 }
14253 }
14254 if (rem_totx && (!myrpt->remotetx))
14255 {
14256
14257 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14258 {
14259 if(debug > 6)
14260 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14261
14262 myrpt->remotetx = 1;
14263
14264 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14265 {
14266 time(&myrpt->last_activity_time);
14267 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14268 {
14269 z.radpar = DAHDI_RADPAR_UIODATA;
14270 z.data = 1;
14271 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14272 {
14273 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14274 return -1;
14275 }
14276 }
14277 else
14278 {
14279 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14280 }
14281 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14282 }
14283 }
14284 }
14285 if ((!rem_totx) && myrpt->remotetx)
14286 {
14287 myrpt->remotetx = 0;
14288 if(!myrpt->remtxfreqok){
14289 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14290 }
14291 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14292 {
14293 z.radpar = DAHDI_RADPAR_UIODATA;
14294 z.data = 3;
14295 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14296 {
14297 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14298 return -1;
14299 }
14300 }
14301 else
14302 {
14303 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14304 }
14305 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14306 }
14307 if (myrpt->hfscanmode){
14308 myrpt->scantimer -= elap;
14309 if(myrpt->scantimer <= 0){
14310 if (!reming)
14311 {
14312 myrpt->scantimer = REM_SCANTIME;
14313 rpt_telemetry(myrpt,SCAN,0);
14314 } else myrpt->scantimer = 1;
14315 }
14316 }
14317 rpt_mutex_lock(&myrpt->lock);
14318 c = myrpt->macrobuf[0];
14319 if (c && (!myrpt->macrotimer))
14320 {
14321 myrpt->macrotimer = MACROTIME;
14322 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14323 if ((c == 'p') || (c == 'P'))
14324 myrpt->macrotimer = MACROPTIME;
14325 rpt_mutex_unlock(&myrpt->lock);
14326 if (myrpt->p.archivedir)
14327 {
14328 char str[100];
14329 sprintf(str,"DTMF(M),%c",c);
14330 donodelog(myrpt,str);
14331 }
14332 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14333 continue;
14334 } else rpt_mutex_unlock(&myrpt->lock);
14335 if (who == chan)
14336 {
14337 f = ast_read(chan);
14338 if (!f)
14339 {
14340 if (debug) printf("@@@@ link:Hung Up\n");
14341 break;
14342 }
14343 if (f->frametype == AST_FRAME_VOICE)
14344 {
14345 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14346 {
14347 ismuted = 0;
14348 }
14349
14350 ismuted |= (!myrpt->remotetx);
14351 if (dtmfed && phone_mode) ismuted = 1;
14352 dtmfed = 0;
14353 if (ismuted)
14354 {
14355 memset(f->data.ptr,0,f->datalen);
14356 if (myrpt->lastf1)
14357 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14358 if (myrpt->lastf2)
14359 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14360 }
14361 if (f) f2 = ast_frdup(f);
14362 else f2 = NULL;
14363 f1 = myrpt->lastf2;
14364 myrpt->lastf2 = myrpt->lastf1;
14365 myrpt->lastf1 = f2;
14366 if (ismuted)
14367 {
14368 if (myrpt->lastf1)
14369 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14370 if (myrpt->lastf2)
14371 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14372 }
14373 if (f1)
14374 {
14375 if (phone_mode)
14376 ast_write(myrpt->txchannel,f1);
14377 else
14378 ast_write(myrpt->txchannel,f);
14379 ast_frfree(f1);
14380 }
14381 }
14382 #ifndef OLD_ASTERISK
14383 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14384 {
14385 if (myrpt->lastf1)
14386 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14387 if (myrpt->lastf2)
14388 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14389 dtmfed = 1;
14390 }
14391 #endif
14392 if (f->frametype == AST_FRAME_DTMF)
14393 {
14394 if (myrpt->lastf1)
14395 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14396 if (myrpt->lastf2)
14397 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14398 dtmfed = 1;
14399 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
14400 {
14401 if (debug) printf("@@@@ rpt:Hung Up\n");
14402 ast_frfree(f);
14403 break;
14404 }
14405 }
14406 if (f->frametype == AST_FRAME_TEXT)
14407 {
14408 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14409 {
14410 if (debug) printf("@@@@ rpt:Hung Up\n");
14411 ast_frfree(f);
14412 break;
14413 }
14414 }
14415 if (f->frametype == AST_FRAME_CONTROL)
14416 {
14417 if (f->subclass == AST_CONTROL_HANGUP)
14418 {
14419 if (debug) printf("@@@@ rpt:Hung Up\n");
14420 ast_frfree(f);
14421 break;
14422 }
14423
14424 if (f->subclass == AST_CONTROL_RADIO_KEY)
14425 {
14426 if (debug == 7) printf("@@@@ rx key\n");
14427 keyed = 1;
14428 myrpt->rerxtimer = 0;
14429 }
14430
14431 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14432 {
14433 myrpt->rerxtimer = 0;
14434 if (debug == 7) printf("@@@@ rx un-key\n");
14435 keyed = 0;
14436 }
14437 }
14438 ast_frfree(f);
14439 continue;
14440 }
14441 if (who == myrpt->rxchannel)
14442 {
14443 f = ast_read(myrpt->rxchannel);
14444 if (!f)
14445 {
14446 if (debug) printf("@@@@ link:Hung Up\n");
14447 break;
14448 }
14449 if (f->frametype == AST_FRAME_VOICE)
14450 {
14451 int myreming = 0;
14452
14453 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14454 myreming = reming;
14455
14456 if (myreming || (!remkeyed) ||
14457 ((myrpt->remote) && (myrpt->remotetx)) ||
14458 ((myrpt->remmode != REM_MODE_FM) &&
14459 notremming))
14460 memset(f->data.ptr,0,f->datalen);
14461 ast_write(myrpt->pchannel,f);
14462 }
14463 else if (f->frametype == AST_FRAME_CONTROL)
14464 {
14465 if (f->subclass == AST_CONTROL_HANGUP)
14466 {
14467 if (debug) printf("@@@@ rpt:Hung Up\n");
14468 ast_frfree(f);
14469 break;
14470 }
14471
14472 if (f->subclass == AST_CONTROL_RADIO_KEY)
14473 {
14474 if (debug == 7) printf("@@@@ remote rx key\n");
14475 if (!myrpt->remotetx)
14476 {
14477 remkeyed = 1;
14478 }
14479 }
14480
14481 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14482 {
14483 if (debug == 7) printf("@@@@ remote rx un-key\n");
14484 if (!myrpt->remotetx)
14485 {
14486 remkeyed = 0;
14487 }
14488 }
14489 }
14490 ast_frfree(f);
14491 continue;
14492 }
14493 if (who == myrpt->pchannel)
14494 {
14495 f = ast_read(myrpt->pchannel);
14496 if (!f)
14497 {
14498 if (debug) printf("@@@@ link:Hung Up\n");
14499 break;
14500 }
14501 if (f->frametype == AST_FRAME_VOICE)
14502 {
14503 ast_write(chan,f);
14504 }
14505 if (f->frametype == AST_FRAME_CONTROL)
14506 {
14507 if (f->subclass == AST_CONTROL_HANGUP)
14508 {
14509 if (debug) printf("@@@@ rpt:Hung Up\n");
14510 ast_frfree(f);
14511 break;
14512 }
14513 }
14514 ast_frfree(f);
14515 continue;
14516 }
14517 if ((myrpt->rxchannel != myrpt->txchannel) &&
14518 (who == myrpt->txchannel))
14519 {
14520 f = ast_read(myrpt->txchannel);
14521 if (!f)
14522 {
14523 if (debug) printf("@@@@ link:Hung Up\n");
14524 break;
14525 }
14526 if (f->frametype == AST_FRAME_CONTROL)
14527 {
14528 if (f->subclass == AST_CONTROL_HANGUP)
14529 {
14530 if (debug) printf("@@@@ rpt:Hung Up\n");
14531 ast_frfree(f);
14532 break;
14533 }
14534 }
14535 ast_frfree(f);
14536 continue;
14537 }
14538 }
14539 if (myrpt->p.archivedir)
14540 {
14541 char mycmd[100],*b,*b1;
14542
14543
14544 if (!chan->cid.cid_num)
14545 {
14546 b1 = "0";
14547 } else {
14548 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14549 ast_shrink_phone_number(b1);
14550 }
14551 sprintf(mycmd,"DISCONNECT,%s",b1);
14552 donodelog(myrpt,mycmd);
14553 }
14554
14555 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14556 sprintf(tmp,"mixmonitor stop %s",chan->name);
14557 ast_cli_command(nullfd,tmp);
14558 close(nullfd);
14559 rpt_mutex_lock(&myrpt->lock);
14560 myrpt->hfscanmode = 0;
14561 myrpt->hfscanstatus = 0;
14562 myrpt->remoteon = 0;
14563 rpt_mutex_unlock(&myrpt->lock);
14564 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14565 myrpt->lastf1 = NULL;
14566 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14567 myrpt->lastf2 = NULL;
14568 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14569 {
14570 z.radpar = DAHDI_RADPAR_UIOMODE;
14571 z.data = 3;
14572 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14573 {
14574 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14575 return -1;
14576 }
14577 z.radpar = DAHDI_RADPAR_UIODATA;
14578 z.data = 3;
14579 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14580 {
14581 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14582 return -1;
14583 }
14584 i = DAHDI_OFFHOOK;
14585 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14586 {
14587 ast_log(LOG_ERROR,"Cannot set hook\n");
14588 return -1;
14589 }
14590 }
14591 if (myrpt->iofd) close(myrpt->iofd);
14592 myrpt->iofd = -1;
14593 ast_hangup(myrpt->pchannel);
14594 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14595 ast_hangup(myrpt->rxchannel);
14596 closerem(myrpt);
14597 if (myrpt->p.rptnode)
14598 {
14599 rpt_mutex_lock(&myrpt->lock);
14600 for(i = 0; i < nrpts; i++)
14601 {
14602 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14603 {
14604 rpt_vars[i].xlink = 0;
14605 break;
14606 }
14607 }
14608 rpt_mutex_unlock(&myrpt->lock);
14609 }
14610 #ifdef OLD_ASTERISK
14611 LOCAL_USER_REMOVE(u);
14612 #endif
14613 return res;
14614 }
14615
14616 #ifndef OLD_ASTERISK
14617
14618
14619
14620 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14621 {
14622 int i;
14623 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14624 astman_append(s, "<nodes>\r\n");
14625 for (i=0; i< nrpts; i++)
14626 {
14627 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14628 }
14629 astman_append(s, "</nodes>\r\n");
14630 astman_append(s, "\r\n");
14631 return RESULT_SUCCESS;
14632 }
14633
14634
14635
14636
14637
14638
14639
14640 static void rpt_manager_success(struct mansession *s, const struct message *m)
14641 {
14642 const char *id = astman_get_header(m, "ActionID");
14643 if (!ast_strlen_zero(id))
14644 astman_append(s, "ActionID: %s\r\n", id);
14645 astman_append(s, "Response: Success\r\n");
14646 }
14647
14648
14649
14650
14651
14652 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14653 {
14654 int i,j,numoflinks;
14655 int dailytxtime, dailykerchunks;
14656 time_t now;
14657 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14658 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14659 long long totaltxtime;
14660 struct rpt_link *l;
14661 char *listoflinks[MAX_STAT_LINKS];
14662 char *lastdtmfcommand,*parrot_ena;
14663 char *tot_state, *ider_state, *patch_state;
14664 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14665 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14666 char *transmitterkeyed;
14667 const char *node = astman_get_header(m, "Node");
14668 struct rpt *myrpt;
14669
14670 static char *not_applicable = "N/A";
14671
14672 tot_state = ider_state =
14673 patch_state = reverse_patch_state =
14674 input_signal = not_applicable;
14675 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14676
14677 time(&now);
14678 for(i = 0; i < nrpts; i++)
14679 {
14680 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14681 rpt_manager_success(s,m);
14682
14683 myrpt = &rpt_vars[i];
14684
14685 if(myrpt->remote){
14686 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14687 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14688 char offsetc,powerlevelc;
14689
14690 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14691
14692 rpt_mutex_lock(&myrpt->lock);
14693 if((remoteon = myrpt->remoteon)){
14694 if(!ast_strlen_zero(myrpt->loginuser))
14695 loginuser = ast_strdup(myrpt->loginuser);
14696 if(!ast_strlen_zero(myrpt->loginlevel))
14697 loginlevel = ast_strdup(myrpt->loginlevel);
14698 if(!ast_strlen_zero(myrpt->freq))
14699 freq = ast_strdup(myrpt->freq);
14700 if(!ast_strlen_zero(myrpt->rxpl))
14701 rxpl = ast_strdup(myrpt->rxpl);
14702 if(!ast_strlen_zero(myrpt->txpl))
14703 txpl = ast_strdup(myrpt->txpl);
14704 remmode = myrpt->remmode;
14705 offset = myrpt->offset;
14706 powerlevel = myrpt->powerlevel;
14707 rxplon = myrpt->rxplon;
14708 txplon = myrpt->txplon;
14709 }
14710 rpt_mutex_unlock(&myrpt->lock);
14711 astman_append(s, "IsRemoteBase: YES\r\n");
14712 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14713 if(remoteon){
14714 if(loginuser){
14715 astman_append(s, "LogInUser: %s\r\n", loginuser);
14716 ast_free(loginuser);
14717 }
14718 if(loginlevel){
14719 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14720 ast_free(loginlevel);
14721 }
14722 if(freq){
14723 astman_append(s, "Freq: %s\r\n", freq);
14724 ast_free(freq);
14725 }
14726 reportfmstuff = 0;
14727 switch(remmode){
14728 case REM_MODE_FM:
14729 modestr = "FM";
14730 reportfmstuff = 1;
14731 break;
14732 case REM_MODE_AM:
14733 modestr = "AM";
14734 break;
14735 case REM_MODE_USB:
14736 modestr = "USB";
14737 break;
14738 default:
14739 modestr = "LSB";
14740 break;
14741 }
14742 astman_append(s, "RemMode: %s\r\n", modestr);
14743 if(reportfmstuff){
14744 switch(offset){
14745 case REM_SIMPLEX:
14746 offsetc = 'S';
14747 break;
14748 case REM_MINUS:
14749 offsetc = '-';
14750 break;
14751 default:
14752 offsetc = '+';
14753 break;
14754 }
14755 astman_append(s, "RemOffset: %c\r\n", offsetc);
14756 if(rxplon && rxpl){
14757 astman_append(s, "RxPl: %s\r\n",rxpl);
14758 ast_free(rxpl);
14759 }
14760 if(txplon && txpl){
14761 astman_append(s, "TxPl: %s\r\n",txpl);
14762 ast_free(txpl);
14763 }
14764 }
14765 switch(powerlevel){
14766 case REM_LOWPWR:
14767 powerlevelc = 'L';
14768 break;
14769 case REM_MEDPWR:
14770 powerlevelc = 'M';
14771 break;
14772 default:
14773 powerlevelc = 'H';
14774 break;
14775 }
14776 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14777 }
14778 astman_append(s, "\r\n");
14779 return 0;
14780 }
14781
14782
14783
14784 rpt_mutex_lock(&myrpt->lock);
14785 dailytxtime = myrpt->dailytxtime;
14786 totaltxtime = myrpt->totaltxtime;
14787 dailykeyups = myrpt->dailykeyups;
14788 totalkeyups = myrpt->totalkeyups;
14789 dailykerchunks = myrpt->dailykerchunks;
14790 totalkerchunks = myrpt->totalkerchunks;
14791 dailyexecdcommands = myrpt->dailyexecdcommands;
14792 totalexecdcommands = myrpt->totalexecdcommands;
14793 timeouts = myrpt->timeouts;
14794
14795
14796
14797 reverse_patch_state = "DOWN";
14798 numoflinks = 0;
14799 l = myrpt->links.next;
14800 while(l && (l != &myrpt->links)){
14801 if(numoflinks >= MAX_STAT_LINKS){
14802 ast_log(LOG_NOTICE,
14803 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14804 break;
14805 }
14806 if (l->name[0] == '0'){
14807 reverse_patch_state = "UP";
14808 l = l->next;
14809 continue;
14810 }
14811 listoflinks[numoflinks] = ast_strdup(l->name);
14812 if(listoflinks[numoflinks] == NULL){
14813 break;
14814 }
14815 else{
14816 numoflinks++;
14817 }
14818 l = l->next;
14819 }
14820
14821 if(myrpt->keyed)
14822 input_signal = "YES";
14823 else
14824 input_signal = "NO";
14825
14826 if(myrpt->txkeyed)
14827 transmitterkeyed = "YES";
14828 else
14829 transmitterkeyed = "NO";
14830
14831 if(myrpt->p.parrotmode)
14832 parrot_ena = "ENABLED";
14833 else
14834 parrot_ena = "DISABLED";
14835
14836 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14837 sys_ena = "DISABLED";
14838 else
14839 sys_ena = "ENABLED";
14840
14841 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14842 tot_ena = "DISABLED";
14843 else
14844 tot_ena = "ENABLED";
14845
14846 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14847 link_ena = "DISABLED";
14848 else
14849 link_ena = "ENABLED";
14850
14851 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14852 patch_ena = "DISABLED";
14853 else
14854 patch_ena = "ENABLED";
14855
14856 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14857 sch_ena = "DISABLED";
14858 else
14859 sch_ena = "ENABLED";
14860
14861 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14862 user_funs = "DISABLED";
14863 else
14864 user_funs = "ENABLED";
14865
14866 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14867 tail_type = "ALTERNATE";
14868 else
14869 tail_type = "STANDARD";
14870
14871 if(!myrpt->totimer)
14872 tot_state = "TIMED OUT!";
14873 else if(myrpt->totimer != myrpt->p.totime)
14874 tot_state = "ARMED";
14875 else
14876 tot_state = "RESET";
14877
14878 if(myrpt->tailid)
14879 ider_state = "QUEUED IN TAIL";
14880 else if(myrpt->mustid)
14881 ider_state = "QUEUED FOR CLEANUP";
14882 else
14883 ider_state = "CLEAN";
14884
14885 switch(myrpt->callmode){
14886 case 1:
14887 patch_state = "DIALING";
14888 break;
14889 case 2:
14890 patch_state = "CONNECTING";
14891 break;
14892 case 3:
14893 patch_state = "UP";
14894 break;
14895
14896 case 4:
14897 patch_state = "CALL FAILED";
14898 break;
14899
14900 default:
14901 patch_state = "DOWN";
14902 }
14903
14904 if(strlen(myrpt->exten)){
14905 called_number = ast_strdup(myrpt->exten);
14906 }
14907
14908 if(strlen(myrpt->lastdtmfcommand)){
14909 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14910 }
14911 rpt_mutex_unlock(&myrpt->lock);
14912
14913 astman_append(s, "IsRemoteBase: NO\r\n");
14914 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14915 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14916 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14917 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14918 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14919 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14920 astman_append(s, "TailLength: %s\r\n", tail_type);
14921 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14922 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14923 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14924 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14925 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14926 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14927 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14928 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14929 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14930 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14931 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14932 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14933 hours = dailytxtime/3600000;
14934 dailytxtime %= 3600000;
14935 minutes = dailytxtime/60000;
14936 dailytxtime %= 60000;
14937 seconds = dailytxtime/1000;
14938 dailytxtime %= 1000;
14939
14940 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14941 hours, minutes, seconds, dailytxtime);
14942
14943 hours = (int) totaltxtime/3600000;
14944 totaltxtime %= 3600000;
14945 minutes = (int) totaltxtime/60000;
14946 totaltxtime %= 60000;
14947 seconds = (int) totaltxtime/1000;
14948 totaltxtime %= 1000;
14949
14950 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14951 hours, minutes, seconds, (int) totaltxtime);
14952
14953 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14954 if(!numoflinks){
14955 strcat(str,"<NONE>");
14956 }
14957 else{
14958 for(j = 0 ;j < numoflinks; j++){
14959 sprintf(str+strlen(str), "%s", listoflinks[j]);
14960 if(j < numoflinks - 1)
14961 strcat(str,",");
14962 }
14963 }
14964 astman_append(s,"%s\r\n", str);
14965
14966 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14967 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14968 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14969 (called_number && strlen(called_number)) ? called_number : not_applicable);
14970 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14971 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14972 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14973
14974 for(j = 0; j < numoflinks; j++){
14975 ast_free(listoflinks[j]);
14976 }
14977 if(called_number){
14978 ast_free(called_number);
14979 }
14980 if(lastdtmfcommand){
14981 ast_free(lastdtmfcommand);
14982 }
14983 astman_append(s, "\r\n");
14984 return 0;
14985 }
14986 }
14987 astman_send_error(s, m, "RptStatus unknown or missing node");
14988 return -1;
14989 }
14990
14991
14992
14993
14994
14995
14996
14997 static int manager_rpt_status(struct mansession *s, const struct message *m)
14998 {
14999 int i,res,len,idx;
15000 int uptime,hours,minutes;
15001 time_t now;
15002 const char *cmd = astman_get_header(m, "Command");
15003 char *str;
15004 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15005 struct mgrcmdtbl{
15006 const char *cmd;
15007 int index;
15008 };
15009 static struct mgrcmdtbl mct[] = {
15010 {"RptStat",MGRCMD_RPTSTAT},
15011 {"NodeStat",MGRCMD_NODESTAT},
15012 {NULL,0}
15013 };
15014
15015 time(&now);
15016
15017 len = 1024;
15018 if(!(str = ast_malloc(len)))
15019 return -1;
15020
15021
15022 if(ast_strlen_zero(cmd)){
15023 astman_send_error(s, m, "RptStatus missing command");
15024 ast_free(str);
15025 return 0;
15026 }
15027
15028 for(i = 0 ; mct[i].cmd ; i++){
15029 if(!strcmp(mct[i].cmd, cmd))
15030 break;
15031 }
15032
15033 if(!mct[i].cmd){
15034 astman_send_error(s, m, "RptStatus unknown command");
15035 ast_free(str);
15036 return 0;
15037 }
15038 else
15039 idx = mct[i].index;
15040
15041 switch(idx){
15042
15043 case MGRCMD_RPTSTAT:
15044
15045 if((res = snprintf(str, len, "Nodes: ")) > -1)
15046 len -= res;
15047 else{
15048 ast_free(str);
15049 return 0;
15050 }
15051 for(i = 0; i < nrpts; i++){
15052 if(i < nrpts - 1){
15053 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15054 ast_free(str);
15055 return 0;
15056 }
15057 }
15058 else{
15059 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15060 ast_free(str);
15061 return 0;
15062 }
15063 }
15064 len -= res;
15065 }
15066
15067 rpt_manager_success(s,m);
15068
15069 if(!nrpts)
15070 astman_append(s, "<NONE>\r\n");
15071 else
15072 astman_append(s, "%s\r\n", str);
15073
15074 uptime = (int)(now - starttime);
15075 hours = uptime/3600;
15076 uptime %= 3600;
15077 minutes = uptime/60;
15078 uptime %= 60;
15079
15080 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15081 hours, minutes, uptime);
15082
15083 astman_append(s, "\r\n");
15084 break;
15085
15086 case MGRCMD_NODESTAT:
15087 res = rpt_manager_do_stats(s,m,str);
15088 ast_free(str);
15089 return res;
15090
15091 default:
15092 astman_send_error(s, m, "RptStatus invalid command");
15093 break;
15094 }
15095 ast_free(str);
15096 return 0;
15097 }
15098
15099 #endif
15100
15101 #ifdef OLD_ASTERISK
15102 int unload_module()
15103 #else
15104 static int unload_module(void)
15105 #endif
15106 {
15107 int i, res;
15108
15109 #ifdef OLD_ASTERISK
15110 STANDARD_HANGUP_LOCALUSERS;
15111 #endif
15112 for(i = 0; i < nrpts; i++) {
15113 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15114 ast_mutex_destroy(&rpt_vars[i].lock);
15115 ast_mutex_destroy(&rpt_vars[i].remlock);
15116 }
15117 res = ast_unregister_application(app);
15118
15119 #ifdef NEW_ASTERISK
15120 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15121 #else
15122
15123 ast_cli_unregister(&cli_debug);
15124 ast_cli_unregister(&cli_dump);
15125 ast_cli_unregister(&cli_stats);
15126 ast_cli_unregister(&cli_lstats);
15127 ast_cli_unregister(&cli_nodes);
15128 ast_cli_unregister(&cli_local_nodes);
15129 ast_cli_unregister(&cli_reload);
15130 ast_cli_unregister(&cli_restart);
15131 ast_cli_unregister(&cli_fun);
15132 ast_cli_unregister(&cli_fun1);
15133 res |= ast_cli_unregister(&cli_cmd);
15134 #endif
15135 #ifndef OLD_ASTERISK
15136 res |= ast_manager_unregister("RptLocalNodes");
15137 res |= ast_manager_unregister("RptStatus");
15138 #endif
15139 return res;
15140 }
15141
15142 #ifdef OLD_ASTERISK
15143 int load_module()
15144 #else
15145 static int load_module(void)
15146 #endif
15147 {
15148 int res;
15149 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15150
15151 #ifdef NEW_ASTERISK
15152 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15153 res = 0;
15154 #else
15155
15156 ast_cli_register(&cli_debug);
15157 ast_cli_register(&cli_dump);
15158 ast_cli_register(&cli_stats);
15159 ast_cli_register(&cli_lstats);
15160 ast_cli_register(&cli_nodes);
15161 ast_cli_register(&cli_local_nodes);
15162 ast_cli_register(&cli_reload);
15163 ast_cli_register(&cli_restart);
15164 ast_cli_register(&cli_fun);
15165 ast_cli_register(&cli_fun1);
15166 res = ast_cli_register(&cli_cmd);
15167 #endif
15168 #ifndef OLD_ASTERISK
15169 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15170 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15171
15172 #endif
15173 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15174 return res;
15175 }
15176
15177 #ifdef OLD_ASTERISK
15178 char *description()
15179 {
15180 return tdesc;
15181 }
15182 int usecount(void)
15183 {
15184 int res;
15185 STANDARD_USECOUNT(res);
15186 return res;
15187 }
15188
15189 char *key()
15190 {
15191 return ASTERISK_GPL_KEY;
15192 }
15193 #endif
15194
15195 #ifdef OLD_ASTERISK
15196 int reload()
15197 #else
15198 static int reload(void)
15199 #endif
15200 {
15201 int n;
15202
15203 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15204 return(0);
15205 }
15206
15207
15208 #ifndef OLD_ASTERISK
15209
15210 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15211 .load = load_module,
15212 .unload = unload_module,
15213 .reload = reload,
15214 );
15215 #endif
15216