00001 #define NEW_ASTERISK
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 #ifdef OLD_ASTERISK
00171 #define ast_free free
00172 #define ast_malloc malloc
00173 #define ast_strdup strdup
00174 #endif
00175
00176
00177 #define MAXDTMF 32
00178 #define MAXMACRO 2048
00179 #define MAXLINKLIST 512
00180 #define LINKLISTTIME 10000
00181 #define LINKLISTSHORTTIME 200
00182 #define LINKPOSTTIME 30000
00183 #define LINKPOSTSHORTTIME 200
00184 #define KEYPOSTTIME 30000
00185 #define KEYPOSTSHORTTIME 200
00186 #define MACROTIME 100
00187 #define MACROPTIME 500
00188 #define DTMF_TIMEOUT 3
00189 #define KENWOOD_RETRIES 5
00190 #define TOPKEYN 32
00191 #define TOPKEYWAIT 3
00192 #define TOPKEYMAXSTR 30
00193
00194 #define AUTHTELLTIME 7000
00195 #define AUTHTXTIME 1000
00196 #define AUTHLOGOUTTIME 25000
00197
00198 #ifdef __RPT_NOTCH
00199 #define MAXFILTERS 10
00200 #endif
00201
00202 #define DISC_TIME 10000
00203 #define MAX_RETRIES 5
00204 #define MAX_RETRIES_PERM 1000000000
00205
00206 #define REDUNDANT_TX_TIME 2000
00207
00208 #define RETRY_TIMER_MS 5000
00209
00210 #define PATCH_DIALPLAN_TIMEOUT 1500
00211
00212 #ifdef OLD_ASTERISK
00213 #define START_DELAY 10
00214 #else
00215 #define START_DELAY 2
00216 #endif
00217
00218 #define RPT_LOCKOUT_SECS 10
00219
00220 #define MAXPEERSTR 31
00221 #define MAXREMSTR 15
00222
00223 #define DELIMCHR ','
00224 #define QUOTECHR 34
00225
00226 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00227
00228 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00229 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00230 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00232 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00233
00234 #define NODES "nodes"
00235 #define EXTNODES "extnodes"
00236 #define MEMORY "memory"
00237 #define MACRO "macro"
00238 #define FUNCTIONS "functions"
00239 #define TELEMETRY "telemetry"
00240 #define MORSE "morse"
00241 #define TONEMACRO "tonemacro"
00242 #define FUNCCHAR '*'
00243 #define ENDCHAR '#'
00244 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00245 #define NODENAMES "rpt/nodenames"
00246 #define PARROTFILE "/tmp/parrot_%s_%u"
00247
00248 #define PARROTTIME 1000
00249
00250 #define DEFAULT_IOBASE 0x378
00251
00252 #define DEFAULT_CIV_ADDR 0x58
00253
00254 #define MAXCONNECTTIME 5000
00255
00256 #define MAXNODESTR 300
00257
00258 #define MAXNODELEN 16
00259
00260 #define MAXIDENTLEN 32
00261
00262 #define MAXPATCHCONTEXT 100
00263
00264 #define ACTIONSIZE 32
00265
00266 #define TELEPARAMSIZE 256
00267
00268 #define REM_SCANTIME 100
00269
00270 #define DTMF_LOCAL_TIME 250
00271 #define DTMF_LOCAL_STARTTIME 500
00272
00273 #define IC706_PL_MEMORY_OFFSET 50
00274
00275 #define VOX_ON_DEBOUNCE_COUNT 3
00276 #define VOX_OFF_DEBOUNCE_COUNT 20
00277 #define VOX_MAX_THRESHOLD 10000.0
00278 #define VOX_MIN_THRESHOLD 3000.0
00279 #define VOX_TIMEOUT_MS 5000
00280 #define VOX_RECOVER_MS 500
00281 #define SIMPLEX_PATCH_DELAY 25
00282 #define SIMPLEX_PHONE_DELAY 25
00283
00284 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00285
00286 #define ALLOW_LOCAL_CHANNELS
00287
00288 enum {REM_OFF,REM_MONITOR,REM_TX};
00289
00290 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00291 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00292 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00293 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00294 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00295 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00296 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00297 STATS_TIME_LOCAL};
00298
00299
00300 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00301
00302 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00303
00304 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00305
00306 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00307
00308 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00309
00310 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00311
00312 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00313 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00314
00315 #include "asterisk.h"
00316
00317 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00318
00319 #include <signal.h>
00320 #include <stdio.h>
00321 #include <stdint.h>
00322 #include <unistd.h>
00323 #include <string.h>
00324 #include <stdlib.h>
00325 #include <search.h>
00326 #include <sys/types.h>
00327 #include <sys/stat.h>
00328 #include <errno.h>
00329 #include <dirent.h>
00330 #include <ctype.h>
00331 #include <sys/stat.h>
00332 #include <sys/time.h>
00333 #include <sys/file.h>
00334 #include <sys/ioctl.h>
00335 #ifdef HAVE_SYS_IO_H
00336 #include <sys/io.h>
00337 #endif
00338 #include <sys/vfs.h>
00339 #include <math.h>
00340 #include <dahdi/user.h>
00341 #include <dahdi/tonezone.h>
00342 #include <netinet/in.h>
00343 #include <arpa/inet.h>
00344
00345 #include "asterisk/utils.h"
00346 #include "asterisk/lock.h"
00347 #include "asterisk/file.h"
00348 #include "asterisk/logger.h"
00349 #include "asterisk/channel.h"
00350 #include "asterisk/callerid.h"
00351 #include "asterisk/pbx.h"
00352 #include "asterisk/module.h"
00353 #include "asterisk/translate.h"
00354 #include "asterisk/features.h"
00355 #include "asterisk/options.h"
00356 #include "asterisk/cli.h"
00357 #include "asterisk/config.h"
00358 #include "asterisk/say.h"
00359 #include "asterisk/localtime.h"
00360 #include "asterisk/cdr.h"
00361 #include "asterisk/options.h"
00362 #include "asterisk/manager.h"
00363 #include "asterisk/app.h"
00364
00365 #include <termios.h>
00366
00367 #ifdef NEW_ASTERISK
00368 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00369 #endif
00370
00371
00372
00373 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00374
00375 void ast_playtones_stop(struct ast_channel *chan);
00376
00377 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00378
00379 static char *app = "Rpt";
00380
00381 static char *synopsis = "Radio Repeater/Remote Base Control System";
00382
00383 static char *descrip =
00384 " Rpt(nodename[|options][|M][|*]): \n"
00385 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00386 "\n"
00387 " Not specifying an option puts it in normal endpoint mode (where source\n"
00388 " IP and nodename are verified).\n"
00389 "\n"
00390 " Options are as follows:\n"
00391 "\n"
00392 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00393 " this if you have checked security already (like with an IAX2\n"
00394 " user/password or something).\n"
00395 "\n"
00396 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00397 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00398 " specified by the 'announce-string') is played on radio system.\n"
00399 " Users of radio system can access autopatch, dial specified\n"
00400 " code, and pick up call. Announce-string is list of names of\n"
00401 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00402 " or \"NODE\" to substitute node number.\n"
00403 "\n"
00404 " P - Phone Control mode. This allows a regular phone user to have\n"
00405 " full control and audio access to the radio system. For the\n"
00406 " user to have DTMF control, the 'phone_functions' parameter\n"
00407 " must be specified for the node in 'rpt.conf'. An additional\n"
00408 " function (cop,6) must be listed so that PTT control is available.\n"
00409 "\n"
00410 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00411 " have full control and audio access to the radio system. In this\n"
00412 " mode, the PTT is activated for the entire length of the call.\n"
00413 " For the user to have DTMF control (not generally recomended in\n"
00414 " this mode), the 'dphone_functions' parameter must be specified\n"
00415 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00416 " available to the phone user.\n"
00417 "\n"
00418 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00419 " audio-only access to the radio system. In this mode, the\n"
00420 " transmitter is toggled on and off when the phone user presses the\n"
00421 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00422 " will turn off if the endchar (#) key is pressed. When a user first\n"
00423 " calls in, the transmitter will be off, and the user can listen for\n"
00424 " radio traffic. When the user wants to transmit, they press the *\n"
00425 " key, start talking, then press the * key again or the # key to turn\n"
00426 " the transmitter off. No other functions can be executed by the\n"
00427 " user on the phone when this mode is selected. Note: If your\n"
00428 " radio system is full-duplex, we recommend using either P or D\n"
00429 " modes as they provide more flexibility.\n"
00430 "\n"
00431 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00432 "\n"
00433 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00434 "\n"
00435 " * - Alt Macro to execute (e.g. *7 for status)\n"
00436 "\n";
00437 ;
00438
00439 static int debug = 0;
00440 static int nrpts = 0;
00441
00442 static const char remdtmfstr[] = "0123456789*#ABCD";
00443
00444 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00445
00446 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00447
00448 #define NRPTSTAT 7
00449
00450 struct rpt_chan_stat
00451 {
00452 struct timeval last;
00453 long long total;
00454 unsigned long count;
00455 unsigned long largest;
00456 struct timeval largest_time;
00457 };
00458
00459 char *discstr = "!!DISCONNECT!!";
00460 char *newkeystr = "!NEWKEY!";
00461 static char *remote_rig_ft897="ft897";
00462 static char *remote_rig_rbi="rbi";
00463 static char *remote_rig_kenwood="kenwood";
00464 static char *remote_rig_tm271="tm271";
00465 static char *remote_rig_ic706="ic706";
00466 static char *remote_rig_rtx150="rtx150";
00467 static char *remote_rig_rtx450="rtx450";
00468 static char *remote_rig_ppp16="ppp16";
00469
00470 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00471 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00472
00473 #ifdef OLD_ASTERISK
00474 STANDARD_LOCAL_USER;
00475 LOCAL_USER_DECL;
00476 #endif
00477
00478 #define MSWAIT 200
00479 #define HANGTIME 5000
00480 #define TOTIME 180000
00481 #define IDTIME 300000
00482 #define MAXRPTS 20
00483 #define MAX_STAT_LINKS 32
00484 #define POLITEID 30000
00485 #define FUNCTDELAY 1500
00486
00487 #define MAXXLAT 20
00488 #define MAXXLATTIME 3
00489
00490 #define MAX_SYSSTATES 10
00491
00492 struct vox {
00493 float speech_energy;
00494 float noise_energy;
00495 int enacount;
00496 char voxena;
00497 char lastvox;
00498 int offdebcnt;
00499 int ondebcnt;
00500 } ;
00501
00502 #define mymax(x,y) ((x > y) ? x : y)
00503 #define mymin(x,y) ((x < y) ? x : y)
00504
00505 struct rpt_topkey
00506 {
00507 char node[TOPKEYMAXSTR];
00508 int timesince;
00509 int keyed;
00510 } ;
00511
00512 struct rpt_xlat
00513 {
00514 char funccharseq[MAXXLAT];
00515 char endcharseq[MAXXLAT];
00516 char passchars[MAXXLAT];
00517 int funcindex;
00518 int endindex;
00519 time_t lastone;
00520 } ;
00521
00522 static time_t starttime = 0;
00523
00524 static pthread_t rpt_master_thread;
00525
00526 struct rpt;
00527
00528 struct rpt_link
00529 {
00530 struct rpt_link *next;
00531 struct rpt_link *prev;
00532 char mode;
00533 char isremote;
00534 char phonemode;
00535 char phonevox;
00536 char name[MAXNODESTR];
00537 char lasttx;
00538 char lasttx1;
00539 char lastrx;
00540 char lastrealrx;
00541 char lastrx1;
00542 char connected;
00543 char hasconnected;
00544 char perma;
00545 char thisconnected;
00546 char outbound;
00547 char disced;
00548 char killme;
00549 long elaptime;
00550 long disctime;
00551 long retrytimer;
00552 long retxtimer;
00553 long rerxtimer;
00554 int retries;
00555 int max_retries;
00556 int reconnects;
00557 long long connecttime;
00558 struct ast_channel *chan;
00559 struct ast_channel *pchan;
00560 char linklist[MAXLINKLIST];
00561 time_t linklistreceived;
00562 long linklisttimer;
00563 int dtmfed;
00564 int linkunkeytocttimer;
00565 struct timeval lastlinktv;
00566 struct ast_frame *lastf1,*lastf2;
00567 struct rpt_chan_stat chan_stat[NRPTSTAT];
00568 struct vox vox;
00569 char wasvox;
00570 int voxtotimer;
00571 char voxtostate;
00572 char newkey;
00573 #ifdef OLD_ASTERISK
00574 AST_LIST_HEAD(, ast_frame) rxq;
00575 #else
00576 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00577 #endif
00578 } ;
00579
00580 struct rpt_lstat
00581 {
00582 struct rpt_lstat *next;
00583 struct rpt_lstat *prev;
00584 char peer[MAXPEERSTR];
00585 char name[MAXNODESTR];
00586 char mode;
00587 char outbound;
00588 char reconnects;
00589 char thisconnected;
00590 long long connecttime;
00591 struct rpt_chan_stat chan_stat[NRPTSTAT];
00592 } ;
00593
00594 struct rpt_tele
00595 {
00596 struct rpt_tele *next;
00597 struct rpt_tele *prev;
00598 struct rpt *rpt;
00599 struct ast_channel *chan;
00600 int mode;
00601 struct rpt_link mylink;
00602 char param[TELEPARAMSIZE];
00603 intptr_t submode;
00604 uintptr_t parrot;
00605 pthread_t threadid;
00606 } ;
00607
00608 struct function_table_tag
00609 {
00610 char action[ACTIONSIZE];
00611 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00612 int command_source, struct rpt_link *mylink);
00613 } ;
00614
00615
00616
00617 struct morse_bits
00618 {
00619 int len;
00620 int ddcomb;
00621 } ;
00622
00623 struct telem_defaults
00624 {
00625 char name[20];
00626 char value[80];
00627 } ;
00628
00629
00630 struct sysstate
00631 {
00632 char txdisable;
00633 char totdisable;
00634 char linkfundisable;
00635 char autopatchdisable;
00636 char schedulerdisable;
00637 char userfundisable;
00638 char alternatetail;
00639 };
00640
00641
00642 #define CMD_DEPTH 1
00643 #define CMD_STATE_IDLE 0
00644 #define CMD_STATE_BUSY 1
00645 #define CMD_STATE_READY 2
00646 #define CMD_STATE_EXECUTING 3
00647
00648 struct rpt_cmd_struct
00649 {
00650 int state;
00651 int functionNumber;
00652 char param[MAXDTMF];
00653 char digits[MAXDTMF];
00654 int command_source;
00655 };
00656
00657 static struct rpt
00658 {
00659 ast_mutex_t lock;
00660 ast_mutex_t remlock;
00661 ast_mutex_t statpost_lock;
00662 struct ast_config *cfg;
00663 char reload;
00664 char xlink;
00665 unsigned int statpost_seqno;
00666
00667 char *name;
00668 char *rxchanname;
00669 char *txchanname;
00670 char remote;
00671 char *remoterig;
00672 struct rpt_chan_stat chan_stat[NRPTSTAT];
00673 unsigned int scram;
00674
00675 struct {
00676 char *ourcontext;
00677 char *ourcallerid;
00678 char *acctcode;
00679 char *ident;
00680 char *tonezone;
00681 char simple;
00682 char *functions;
00683 char *link_functions;
00684 char *phone_functions;
00685 char *dphone_functions;
00686 char *alt_functions;
00687 char *nodes;
00688 char *extnodes;
00689 char *extnodefile;
00690 int hangtime;
00691 int althangtime;
00692 int totime;
00693 int idtime;
00694 int tailmessagetime;
00695 int tailsquashedtime;
00696 int duplex;
00697 int politeid;
00698 char *tailmessages[500];
00699 int tailmessagemax;
00700 char *memory;
00701 char *macro;
00702 char *tonemacro;
00703 char *startupmacro;
00704 int iobase;
00705 char *ioport;
00706 char funcchar;
00707 char endchar;
00708 char nobusyout;
00709 char notelemtx;
00710 char propagate_dtmf;
00711 char propagate_phonedtmf;
00712 char linktolink;
00713 unsigned char civaddr;
00714 struct rpt_xlat inxlat;
00715 struct rpt_xlat outxlat;
00716 char *archivedir;
00717 int authlevel;
00718 char *csstanzaname;
00719 char *skedstanzaname;
00720 char *txlimitsstanzaname;
00721 long monminblocks;
00722 int remoteinacttimeout;
00723 int remotetimeout;
00724 int remotetimeoutwarning;
00725 int remotetimeoutwarningfreq;
00726 int sysstate_cur;
00727 struct sysstate s[MAX_SYSSTATES];
00728 char parrotmode;
00729 int parrottime;
00730 char *rptnode;
00731 char remote_mars;
00732 int voxtimeout_ms;
00733 int voxrecover_ms;
00734 int simplexpatchdelay;
00735 int simplexphonedelay;
00736 char *statpost_program;
00737 char *statpost_url;
00738 } p;
00739 struct rpt_link links;
00740 int unkeytocttimer;
00741 time_t lastkeyedtime;
00742 time_t lasttxkeyedtime;
00743 char keyed;
00744 char txkeyed;
00745 char exttx;
00746 char localtx;
00747 char remoterx;
00748 char remotetx;
00749 char remoteon;
00750 char remtxfreqok;
00751 char tounkeyed;
00752 char tonotify;
00753 char dtmfbuf[MAXDTMF];
00754 char macrobuf[MAXMACRO];
00755 char rem_dtmfbuf[MAXDTMF];
00756 char lastdtmfcommand[MAXDTMF];
00757 char cmdnode[50];
00758 char nowchan;
00759 char waschan;
00760 char bargechan;
00761 char macropatch;
00762 char parrotstate;
00763 int parrottimer;
00764 unsigned int parrotcnt;
00765 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00766 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00767 struct ast_channel *voxchannel;
00768 struct ast_frame *lastf1,*lastf2;
00769 struct rpt_tele tele;
00770 struct timeval lasttv,curtv;
00771 pthread_t rpt_call_thread,rpt_thread;
00772 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00773 int calldigittimer;
00774 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00775 int mustid,tailid;
00776 int tailevent;
00777 int telemrefcount;
00778 int dtmfidx,rem_dtmfidx;
00779 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00780 int totalexecdcommands, dailyexecdcommands;
00781 long retxtimer;
00782 long rerxtimer;
00783 long long totaltxtime;
00784 char mydtmf;
00785 char exten[AST_MAX_EXTENSION];
00786 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00787 char offset;
00788 char powerlevel;
00789 char txplon;
00790 char rxplon;
00791 char remmode;
00792 char tunerequest;
00793 char hfscanmode;
00794 int hfscanstatus;
00795 char hfscanstop;
00796 char lastlinknode[MAXNODESTR];
00797 char savednodes[MAXNODESTR];
00798 int stopgen;
00799 char patchfarenddisconnect;
00800 char patchnoct;
00801 char patchquiet;
00802 char patchcontext[MAXPATCHCONTEXT];
00803 int patchdialtime;
00804 int macro_longest;
00805 int phone_longestfunc;
00806 int alt_longestfunc;
00807 int dphone_longestfunc;
00808 int link_longestfunc;
00809 int longestfunc;
00810 int longestnode;
00811 int threadrestarts;
00812 int tailmessagen;
00813 time_t disgorgetime;
00814 time_t lastthreadrestarttime;
00815 long macrotimer;
00816 char lastnodewhichkeyedusup[MAXNODESTR];
00817 int dtmf_local_timer;
00818 char dtmf_local_str[100];
00819 struct ast_filestream *monstream,*parrotstream;
00820 char loginuser[50];
00821 char loginlevel[10];
00822 long authtelltimer;
00823 long authtimer;
00824 int iofd;
00825 time_t start_time,last_activity_time;
00826 char lasttone[32];
00827 struct rpt_tele *active_telem;
00828 struct rpt_topkey topkey[TOPKEYN];
00829 int topkeystate;
00830 time_t topkeytime;
00831 int topkeylong;
00832 struct vox vox;
00833 char wasvox;
00834 int voxtotimer;
00835 char voxtostate;
00836 int linkposttimer;
00837 int keyposttimer;
00838 char newkey;
00839 char inpadtest;
00840 #ifdef OLD_ASTERISK
00841 AST_LIST_HEAD(, ast_frame) txq;
00842 #else
00843 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00844 #endif
00845 char txrealkeyed;
00846 #ifdef __RPT_NOTCH
00847 struct rptfilter
00848 {
00849 char desc[100];
00850 float x0;
00851 float x1;
00852 float x2;
00853 float y0;
00854 float y1;
00855 float y2;
00856 float gain;
00857 float const0;
00858 float const1;
00859 float const2;
00860 } filters[MAXFILTERS];
00861 #endif
00862 #ifdef _MDC_DECODE_H_
00863 mdc_decoder_t *mdc;
00864 unsigned short lastunit;
00865 #endif
00866 struct rpt_cmd_struct cmdAction;
00867 } rpt_vars[MAXRPTS];
00868
00869 struct nodelog {
00870 struct nodelog *next;
00871 struct nodelog *prev;
00872 time_t timestamp;
00873 char archivedir[MAXNODESTR];
00874 char str[MAXNODESTR * 2];
00875 } nodelog;
00876
00877 static int service_scan(struct rpt *myrpt);
00878 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00879 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00880 static int simple_command_ft897(struct rpt *myrpt, char command);
00881 static int setrem(struct rpt *myrpt);
00882 static int setrtx_check(struct rpt *myrpt);
00883 static int channel_revert(struct rpt *myrpt);
00884 static int channel_steer(struct rpt *myrpt, char *data);
00885
00886 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00887
00888 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00889
00890 #ifdef APP_RPT_LOCK_DEBUG
00891
00892 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00893
00894 #define MAXLOCKTHREAD 100
00895
00896 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00897 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00898
00899 struct lockthread
00900 {
00901 pthread_t id;
00902 int lockcount;
00903 int lastlock;
00904 int lastunlock;
00905 } lockthreads[MAXLOCKTHREAD];
00906
00907
00908 struct by_lightning
00909 {
00910 int line;
00911 struct timeval tv;
00912 struct rpt *rpt;
00913 struct lockthread lockthread;
00914 } lock_ring[32];
00915
00916 int lock_ring_index = 0;
00917
00918 AST_MUTEX_DEFINE_STATIC(locklock);
00919
00920 static struct lockthread *get_lockthread(pthread_t id)
00921 {
00922 int i;
00923
00924 for(i = 0; i < MAXLOCKTHREAD; i++)
00925 {
00926 if (lockthreads[i].id == id) return(&lockthreads[i]);
00927 }
00928 return(NULL);
00929 }
00930
00931 static struct lockthread *put_lockthread(pthread_t id)
00932 {
00933 int i;
00934
00935 for(i = 0; i < MAXLOCKTHREAD; i++)
00936 {
00937 if (lockthreads[i].id == id)
00938 return(&lockthreads[i]);
00939 }
00940 for(i = 0; i < MAXLOCKTHREAD; i++)
00941 {
00942 if (!lockthreads[i].id)
00943 {
00944 lockthreads[i].lockcount = 0;
00945 lockthreads[i].lastlock = 0;
00946 lockthreads[i].lastunlock = 0;
00947 lockthreads[i].id = id;
00948 return(&lockthreads[i]);
00949 }
00950 }
00951 return(NULL);
00952 }
00953
00954
00955 static void rpt_mutex_spew(void)
00956 {
00957 struct by_lightning lock_ring_copy[32];
00958 int lock_ring_index_copy;
00959 int i,j;
00960 long long diff;
00961 char a[100];
00962 struct timeval lasttv;
00963
00964 ast_mutex_lock(&locklock);
00965 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00966 lock_ring_index_copy = lock_ring_index;
00967 ast_mutex_unlock(&locklock);
00968
00969 lasttv.tv_sec = lasttv.tv_usec = 0;
00970 for(i = 0 ; i < 32 ; i++)
00971 {
00972 j = (i + lock_ring_index_copy) % 32;
00973 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00974 localtime(&lock_ring_copy[j].tv.tv_sec));
00975 diff = 0;
00976 if(lasttv.tv_sec)
00977 {
00978 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00979 * 1000000;
00980 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00981 }
00982 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00983 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00984 if (!lock_ring_copy[j].tv.tv_sec) continue;
00985 if (lock_ring_copy[j].line < 0)
00986 {
00987 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00988 i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00989 }
00990 else
00991 {
00992 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00993 i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00994 }
00995 }
00996 }
00997
00998
00999 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01000 {
01001 struct lockthread *t;
01002 pthread_t id;
01003
01004 id = pthread_self();
01005 ast_mutex_lock(&locklock);
01006 t = put_lockthread(id);
01007 if (!t)
01008 {
01009 ast_mutex_unlock(&locklock);
01010 return;
01011 }
01012 if (t->lockcount)
01013 {
01014 int lastline = t->lastlock;
01015 ast_mutex_unlock(&locklock);
01016 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01017 rpt_mutex_spew();
01018 return;
01019 }
01020 t->lastlock = line;
01021 t->lockcount = 1;
01022 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01023 lock_ring[lock_ring_index].rpt = myrpt;
01024 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01025 lock_ring[lock_ring_index++].line = line;
01026 if(lock_ring_index == 32)
01027 lock_ring_index = 0;
01028 ast_mutex_unlock(&locklock);
01029 ast_mutex_lock(lockp);
01030 }
01031
01032
01033 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01034 {
01035 struct lockthread *t;
01036 pthread_t id;
01037
01038 id = pthread_self();
01039 ast_mutex_lock(&locklock);
01040 t = put_lockthread(id);
01041 if (!t)
01042 {
01043 ast_mutex_unlock(&locklock);
01044 return;
01045 }
01046 if (!t->lockcount)
01047 {
01048 int lastline = t->lastunlock;
01049 ast_mutex_unlock(&locklock);
01050 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01051 rpt_mutex_spew();
01052 return;
01053 }
01054 t->lastunlock = line;
01055 t->lockcount = 0;
01056 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01057 lock_ring[lock_ring_index].rpt = myrpt;
01058 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01059 lock_ring[lock_ring_index++].line = -line;
01060 if(lock_ring_index == 32)
01061 lock_ring_index = 0;
01062 ast_mutex_unlock(&locklock);
01063 ast_mutex_unlock(lockp);
01064 }
01065
01066 #else
01067
01068 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01069 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01070
01071 #endif
01072
01073
01074
01075
01076
01077 static int multimode_capable(struct rpt *myrpt)
01078 {
01079 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01080 return 1;
01081 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01082 return 1;
01083 return 0;
01084 }
01085
01086 static void voxinit_rpt(struct rpt *myrpt,char enable)
01087 {
01088
01089 myrpt->vox.speech_energy = 0.0;
01090 myrpt->vox.noise_energy = 0.0;
01091 myrpt->vox.enacount = 0;
01092 myrpt->vox.voxena = 0;
01093 if (!enable) myrpt->vox.voxena = -1;
01094 myrpt->vox.lastvox = 0;
01095 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01096 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01097 myrpt->wasvox = 0;
01098 myrpt->voxtotimer = 0;
01099 myrpt->voxtostate = 0;
01100 }
01101
01102 static void voxinit_link(struct rpt_link *mylink,char enable)
01103 {
01104
01105 mylink->vox.speech_energy = 0.0;
01106 mylink->vox.noise_energy = 0.0;
01107 mylink->vox.enacount = 0;
01108 mylink->vox.voxena = 0;
01109 if (!enable) mylink->vox.voxena = -1;
01110 mylink->vox.lastvox = 0;
01111 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01112 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01113 mylink->wasvox = 0;
01114 mylink->voxtotimer = 0;
01115 mylink->voxtostate = 0;
01116 }
01117
01118 static int dovox(struct vox *v,short *buf,int bs)
01119 {
01120
01121 int i;
01122 float esquare = 0.0;
01123 float energy = 0.0;
01124 float threshold = 0.0;
01125
01126 if (v->voxena < 0) return(v->lastvox);
01127 for(i = 0; i < bs; i++)
01128 {
01129 esquare += (float) buf[i] * (float) buf[i];
01130 }
01131 energy = sqrt(esquare);
01132
01133 if (energy >= v->speech_energy)
01134 v->speech_energy += (energy - v->speech_energy) / 4;
01135 else
01136 v->speech_energy += (energy - v->speech_energy) / 64;
01137
01138 if (energy >= v->noise_energy)
01139 v->noise_energy += (energy - v->noise_energy) / 64;
01140 else
01141 v->noise_energy += (energy - v->noise_energy) / 4;
01142
01143 if (v->voxena) threshold = v->speech_energy / 8;
01144 else
01145 {
01146 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01147 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01148 }
01149 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01150 if (energy > threshold)
01151 {
01152 if (v->voxena) v->noise_energy *= 0.75;
01153 v->voxena = 1;
01154 } else v->voxena = 0;
01155 if (v->lastvox != v->voxena)
01156 {
01157 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01158 {
01159 v->lastvox = v->voxena;
01160 v->enacount = 0;
01161 }
01162 } else v->enacount = 0;
01163 return(v->lastvox);
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static int rpt_do_debug(int fd, int argc, const char * const *argv);
01175 static int rpt_do_dump(int fd, int argc, const char * const *argv);
01176 static int rpt_do_stats(int fd, int argc, const char * const *argv);
01177 static int rpt_do_lstats(int fd, int argc, const char * const *argv);
01178 static int rpt_do_nodes(int fd, int argc, const char * const *argv);
01179 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv);
01180 static int rpt_do_reload(int fd, int argc, const char * const *argv);
01181 static int rpt_do_restart(int fd, int argc, const char * const *argv);
01182 static int rpt_do_fun(int fd, int argc, const char * const *argv);
01183 static int rpt_do_fun1(int fd, int argc, const char * const *argv);
01184 static int rpt_do_cmd(int fd, int argc, const char * const *argv);
01185
01186 static char debug_usage[] =
01187 "Usage: rpt debug level {0-7}\n"
01188 " Enables debug messages in app_rpt\n";
01189
01190 static char dump_usage[] =
01191 "Usage: rpt dump <nodename>\n"
01192 " Dumps struct debug info to log\n";
01193
01194 static char dump_stats[] =
01195 "Usage: rpt stats <nodename>\n"
01196 " Dumps node statistics to console\n";
01197
01198 static char dump_lstats[] =
01199 "Usage: rpt lstats <nodename>\n"
01200 " Dumps link statistics to console\n";
01201
01202 static char dump_nodes[] =
01203 "Usage: rpt nodes <nodename>\n"
01204 " Dumps a list of directly and indirectly connected nodes to the console\n";
01205
01206 static char usage_local_nodes[] =
01207 "Usage: rpt localnodes\n"
01208 " Dumps a list of the locally configured node numbers to the console.\n";
01209
01210 static char reload_usage[] =
01211 "Usage: rpt reload\n"
01212 " Reloads app_rpt running config parameters\n";
01213
01214 static char restart_usage[] =
01215 "Usage: rpt restart\n"
01216 " Restarts app_rpt\n";
01217
01218 static char fun_usage[] =
01219 "Usage: rpt fun <nodename> <command>\n"
01220 " Send a DTMF function to a node\n";
01221
01222 static char cmd_usage[] =
01223 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01224 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01225
01226 #ifndef NEW_ASTERISK
01227
01228 static struct ast_cli_entry cli_debug =
01229 { { "rpt", "debug", "level" }, rpt_do_debug,
01230 "Enable app_rpt debugging", debug_usage };
01231
01232 static struct ast_cli_entry cli_dump =
01233 { { "rpt", "dump" }, rpt_do_dump,
01234 "Dump app_rpt structs for debugging", dump_usage };
01235
01236 static struct ast_cli_entry cli_stats =
01237 { { "rpt", "stats" }, rpt_do_stats,
01238 "Dump node statistics", dump_stats };
01239
01240 static struct ast_cli_entry cli_nodes =
01241 { { "rpt", "nodes" }, rpt_do_nodes,
01242 "Dump node list", dump_nodes };
01243
01244 static struct ast_cli_entry cli_local_nodes =
01245 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01246 "Dump list of local node numbers", usage_local_nodes };
01247
01248 static struct ast_cli_entry cli_lstats =
01249 { { "rpt", "lstats" }, rpt_do_lstats,
01250 "Dump link statistics", dump_lstats };
01251
01252 static struct ast_cli_entry cli_reload =
01253 { { "rpt", "reload" }, rpt_do_reload,
01254 "Reload app_rpt config", reload_usage };
01255
01256 static struct ast_cli_entry cli_restart =
01257 { { "rpt", "restart" }, rpt_do_restart,
01258 "Restart app_rpt", restart_usage };
01259
01260 static struct ast_cli_entry cli_fun =
01261 { { "rpt", "fun" }, rpt_do_fun,
01262 "Execute a DTMF function", fun_usage };
01263
01264 static struct ast_cli_entry cli_fun1 =
01265 { { "rpt", "fun1" }, rpt_do_fun1,
01266 "Execute a DTMF function", fun_usage };
01267
01268 static struct ast_cli_entry cli_cmd =
01269 { { "rpt", "cmd" }, rpt_do_cmd,
01270 "Execute a DTMF function", cmd_usage };
01271
01272 #endif
01273
01274
01275
01276
01277
01278
01279 static struct telem_defaults tele_defs[] = {
01280 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01281 {"ct2","|t(660,880,150,3072)"},
01282 {"ct3","|t(440,0,150,3072)"},
01283 {"ct4","|t(550,0,150,3072)"},
01284 {"ct5","|t(660,0,150,3072)"},
01285 {"ct6","|t(880,0,150,3072)"},
01286 {"ct7","|t(660,440,150,3072)"},
01287 {"ct8","|t(700,1100,150,3072)"},
01288 {"remotemon","|t(1600,0,75,2048)"},
01289 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01290 {"cmdmode","|t(900,904,200,2048)"},
01291 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01292 } ;
01293
01294
01295
01296
01297
01298 static int setrbi(struct rpt *myrpt);
01299 static int set_ft897(struct rpt *myrpt);
01300 static int set_ic706(struct rpt *myrpt);
01301 static int setkenwood(struct rpt *myrpt);
01302 static int set_tm271(struct rpt *myrpt);
01303 static int setrbi_check(struct rpt *myrpt);
01304
01305
01306
01307
01308
01309
01310
01311 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01312 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01319
01320
01321
01322
01323 static struct function_table_tag function_table[] = {
01324 {"cop", function_cop},
01325 {"autopatchup", function_autopatchup},
01326 {"autopatchdn", function_autopatchdn},
01327 {"ilink", function_ilink},
01328 {"status", function_status},
01329 {"remote", function_remote},
01330 {"macro", function_macro},
01331 {"playback", function_playback}
01332 } ;
01333
01334 static long diskavail(struct rpt *myrpt)
01335 {
01336 struct statfs statfsbuf;
01337
01338 if (!myrpt->p.archivedir) return(0);
01339 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01340 {
01341 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01342 myrpt->p.archivedir,myrpt->name);
01343 return(-1);
01344 }
01345 return(statfsbuf.f_bavail);
01346 }
01347
01348 static void flush_telem(struct rpt *myrpt)
01349 {
01350 struct rpt_tele *telem;
01351 if(debug > 2)
01352 ast_log(LOG_NOTICE, "flush_telem()!!");
01353 rpt_mutex_lock(&myrpt->lock);
01354 telem = myrpt->tele.next;
01355 while(telem != &myrpt->tele)
01356 {
01357 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01358 telem = telem->next;
01359 }
01360 rpt_mutex_unlock(&myrpt->lock);
01361 }
01362
01363
01364
01365 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01366 {
01367 int res=0;
01368
01369
01370 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01371 res = 0;
01372 } else {
01373 res = -1;
01374 }
01375 return res;
01376 }
01377
01378
01379 static int linkcount(struct rpt *myrpt)
01380 {
01381 struct rpt_link *l;
01382 char *reverse_patch_state;
01383 int numoflinks;
01384
01385 reverse_patch_state = "DOWN";
01386 numoflinks = 0;
01387 l = myrpt->links.next;
01388 while(l && (l != &myrpt->links)){
01389 if(numoflinks >= MAX_STAT_LINKS){
01390 ast_log(LOG_WARNING,
01391 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01392 break;
01393 }
01394
01395
01396
01397
01398
01399 numoflinks++;
01400
01401 l = l->next;
01402 }
01403 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01404 return numoflinks;
01405 }
01406
01407
01408
01409
01410
01411
01412 static int retreive_memory(struct rpt *myrpt, char *memory)
01413 {
01414 char tmp[30], *s, *s1, *val;
01415
01416 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01417
01418 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01419 if (!val){
01420 return -1;
01421 }
01422 strncpy(tmp,val,sizeof(tmp) - 1);
01423 tmp[sizeof(tmp)-1] = 0;
01424
01425 s = strchr(tmp,',');
01426 if (!s)
01427 return 1;
01428 *s++ = 0;
01429 s1 = strchr(s,',');
01430 if (!s1)
01431 return 1;
01432 *s1++ = 0;
01433 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01434 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01435 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01436 myrpt->remmode = REM_MODE_FM;
01437 myrpt->offset = REM_SIMPLEX;
01438 myrpt->powerlevel = REM_MEDPWR;
01439 myrpt->txplon = myrpt->rxplon = 0;
01440 while(*s1){
01441 switch(*s1++){
01442 case 'A':
01443 case 'a':
01444 strcpy(myrpt->rxpl, "100.0");
01445 strcpy(myrpt->txpl, "100.0");
01446 myrpt->remmode = REM_MODE_AM;
01447 break;
01448 case 'B':
01449 case 'b':
01450 strcpy(myrpt->rxpl, "100.0");
01451 strcpy(myrpt->txpl, "100.0");
01452 myrpt->remmode = REM_MODE_LSB;
01453 break;
01454 case 'F':
01455 myrpt->remmode = REM_MODE_FM;
01456 break;
01457 case 'L':
01458 case 'l':
01459 myrpt->powerlevel = REM_LOWPWR;
01460 break;
01461 case 'H':
01462 case 'h':
01463 myrpt->powerlevel = REM_HIPWR;
01464 break;
01465
01466 case 'M':
01467 case 'm':
01468 myrpt->powerlevel = REM_MEDPWR;
01469 break;
01470
01471 case '-':
01472 myrpt->offset = REM_MINUS;
01473 break;
01474
01475 case '+':
01476 myrpt->offset = REM_PLUS;
01477 break;
01478
01479 case 'S':
01480 case 's':
01481 myrpt->offset = REM_SIMPLEX;
01482 break;
01483
01484 case 'T':
01485 case 't':
01486 myrpt->txplon = 1;
01487 break;
01488
01489 case 'R':
01490 case 'r':
01491 myrpt->rxplon = 1;
01492 break;
01493
01494 case 'U':
01495 case 'u':
01496 strcpy(myrpt->rxpl, "100.0");
01497 strcpy(myrpt->txpl, "100.0");
01498 myrpt->remmode = REM_MODE_USB;
01499 break;
01500 default:
01501 return 1;
01502 }
01503 }
01504 return 0;
01505 }
01506
01507
01508
01509 static void birdbath(struct rpt *myrpt)
01510 {
01511 struct rpt_tele *telem;
01512 if(debug > 2)
01513 ast_log(LOG_NOTICE, "birdbath!!");
01514 rpt_mutex_lock(&myrpt->lock);
01515 telem = myrpt->tele.next;
01516 while(telem != &myrpt->tele)
01517 {
01518 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01519 telem = telem->next;
01520 }
01521 rpt_mutex_unlock(&myrpt->lock);
01522 }
01523
01524 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01525 {
01526 struct rpt_link *l;
01527
01528 l = myrpt->links.next;
01529
01530 while(l != &myrpt->links)
01531 {
01532 if (!l->phonemode)
01533 {
01534 l = l->next;
01535 continue;
01536 }
01537
01538 if (mylink && (l == mylink))
01539 {
01540 l = l->next;
01541 continue;
01542 }
01543 #ifdef NEW_ASTERISK
01544 if (l->chan) ast_senddigit(l->chan,c,0);
01545 #else
01546 if (l->chan) ast_senddigit(l->chan,c);
01547 #endif
01548 l = l->next;
01549 }
01550 return;
01551 }
01552
01553
01554 static void donodelog(struct rpt *myrpt,char *str)
01555 {
01556 struct nodelog *nodep;
01557 char datestr[100];
01558
01559 if (!myrpt->p.archivedir) return;
01560 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01561 if (nodep == NULL)
01562 {
01563 ast_log(LOG_ERROR,"Cannot get memory for node log");
01564 return;
01565 }
01566 time(&nodep->timestamp);
01567 strncpy(nodep->archivedir,myrpt->p.archivedir,
01568 sizeof(nodep->archivedir) - 1);
01569 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01570 localtime(&nodep->timestamp));
01571 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01572 myrpt->name,datestr,str);
01573 ast_mutex_lock(&nodeloglock);
01574 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01575 ast_mutex_unlock(&nodeloglock);
01576 }
01577
01578
01579 static void do_dtmf_local(struct rpt *myrpt, char c)
01580 {
01581 int i;
01582 char digit;
01583 static const char* dtmf_tones[] = {
01584 "!941+1336/200,!0/200",
01585 "!697+1209/200,!0/200",
01586 "!697+1336/200,!0/200",
01587 "!697+1477/200,!0/200",
01588 "!770+1209/200,!0/200",
01589 "!770+1336/200,!0/200",
01590 "!770+1477/200,!0/200",
01591 "!852+1209/200,!0/200",
01592 "!852+1336/200,!0/200",
01593 "!852+1477/200,!0/200",
01594 "!697+1633/200,!0/200",
01595 "!770+1633/200,!0/200",
01596 "!852+1633/200,!0/200",
01597 "!941+1633/200,!0/200",
01598 "!941+1209/200,!0/200",
01599 "!941+1477/200,!0/200" };
01600
01601
01602 if (c)
01603 {
01604 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01605 if (!myrpt->dtmf_local_timer)
01606 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01607 }
01608
01609 if (myrpt->dtmf_local_timer == 1)
01610 {
01611 if(debug > 6)
01612 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01613
01614
01615 if (myrpt->dtmf_local_str[0])
01616 {
01617 digit = myrpt->dtmf_local_str[0];
01618 myrpt->dtmf_local_str[0] = 0;
01619 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01620 {
01621 myrpt->dtmf_local_str[i - 1] =
01622 myrpt->dtmf_local_str[i];
01623 }
01624 myrpt->dtmf_local_str[i - 1] = 0;
01625 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01626 rpt_mutex_unlock(&myrpt->lock);
01627 if (digit >= '0' && digit <='9')
01628 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01629 else if (digit >= 'A' && digit <= 'D')
01630 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01631 else if (digit == '*')
01632 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01633 else if (digit == '#')
01634 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01635 else {
01636
01637 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01638 }
01639 rpt_mutex_lock(&myrpt->lock);
01640 }
01641 else
01642 {
01643 myrpt->dtmf_local_timer = 0;
01644 }
01645 }
01646 }
01647
01648 static int setdtr(int fd, int enable)
01649 {
01650 struct termios mode;
01651
01652 if (fd < 0) return -1;
01653 if (tcgetattr(fd, &mode)) {
01654 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01655 return -1;
01656 }
01657 if (enable)
01658 {
01659 cfsetspeed(&mode, B9600);
01660 }
01661 else
01662 {
01663 cfsetspeed(&mode, B0);
01664 usleep(100000);
01665 }
01666 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01667 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01668 return -1;
01669 }
01670 if (enable) usleep(100000);
01671 return 0;
01672 }
01673
01674 static int openserial(struct rpt *myrpt,char *fname)
01675 {
01676 struct termios mode;
01677 int fd;
01678
01679 fd = open(fname,O_RDWR);
01680 if (fd == -1)
01681 {
01682 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01683 return -1;
01684 }
01685 memset(&mode, 0, sizeof(mode));
01686 if (tcgetattr(fd, &mode)) {
01687 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01688 return -1;
01689 }
01690 #ifndef SOLARIS
01691 cfmakeraw(&mode);
01692 #else
01693 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01694 |INLCR|IGNCR|ICRNL|IXON);
01695 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01696 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01697 mode.c_cflag |= CS8;
01698 mode.c_cc[VTIME] = 3;
01699 mode.c_cc[VMIN] = 1;
01700 #endif
01701
01702 cfsetispeed(&mode, B9600);
01703 cfsetospeed(&mode, B9600);
01704 if (tcsetattr(fd, TCSANOW, &mode))
01705 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01706 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01707 usleep(100000);
01708 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01709 return(fd);
01710 }
01711
01712 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01713 {
01714 if (!fromnode)
01715 {
01716 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01717 unit,myrpt->name);
01718 }
01719 else
01720 {
01721 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01722 unit,fromnode,myrpt->name);
01723 }
01724 }
01725
01726 #ifdef _MDC_DECODE_H_
01727
01728 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01729 {
01730 struct rpt_link *l;
01731 struct ast_frame wf;
01732 char str[200];
01733
01734
01735 sprintf(str,"I %s %04X",myrpt->name,unit);
01736
01737 wf.frametype = AST_FRAME_TEXT;
01738 wf.subclass.integer = 0;
01739 wf.offset = 0;
01740 wf.mallocd = 0;
01741 wf.datalen = strlen(str) + 1;
01742 wf.samples = 0;
01743
01744
01745 l = myrpt->links.next;
01746
01747 while(l != &myrpt->links)
01748 {
01749 if (l->name[0] == '0')
01750 {
01751 l = l->next;
01752 continue;
01753 }
01754 wf.data = str;
01755 if (l->chan) ast_write(l->chan,&wf);
01756 l = l->next;
01757 }
01758 return;
01759 }
01760
01761 #endif
01762
01763 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01764 {
01765 time_t now;
01766 int gotone;
01767
01768 time(&now);
01769 gotone = 0;
01770
01771 if ((now - xlat->lastone) > MAXXLATTIME)
01772 {
01773 xlat->funcindex = xlat->endindex = 0;
01774 }
01775 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01776 {
01777 time(&xlat->lastone);
01778 gotone = 1;
01779 if (!xlat->funccharseq[xlat->funcindex])
01780 {
01781 xlat->funcindex = xlat->endindex = 0;
01782 return(myrpt->p.funcchar);
01783 }
01784 } else xlat->funcindex = 0;
01785 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01786 {
01787 time(&xlat->lastone);
01788 gotone = 1;
01789 if (!xlat->endcharseq[xlat->endindex])
01790 {
01791 xlat->funcindex = xlat->endindex = 0;
01792 return(myrpt->p.endchar);
01793 }
01794 } else xlat->endindex = 0;
01795
01796 if (gotone) return(0);
01797
01798 if (!xlat->passchars[0]) return(c);
01799
01800 if (strchr(xlat->passchars,c)) return(c);
01801 return(0);
01802 }
01803
01804
01805
01806
01807
01808 static char *eatwhite(char *s)
01809 {
01810 while((*s == ' ') || (*s == 0x09)){
01811 if(!*s)
01812 break;
01813 s++;
01814 }
01815 return s;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static int finddelim(char *str, char *strp[], int limit)
01829 {
01830 int i,l,inquo;
01831
01832 inquo = 0;
01833 i = 0;
01834 strp[i++] = str;
01835 if (!*str)
01836 {
01837 strp[0] = 0;
01838 return(0);
01839 }
01840 for(l = 0; *str && (l < limit) ; str++)
01841 {
01842 if (*str == QUOTECHR)
01843 {
01844 if (inquo)
01845 {
01846 *str = 0;
01847 inquo = 0;
01848 }
01849 else
01850 {
01851 strp[i - 1] = str + 1;
01852 inquo = 1;
01853 }
01854 }
01855 if ((*str == DELIMCHR) && (!inquo))
01856 {
01857 *str = 0;
01858 l++;
01859 strp[i++] = str + 1;
01860 }
01861 }
01862 strp[i] = 0;
01863 return(i);
01864
01865 }
01866
01867
01868
01869 static int send_usb_txt(struct rpt *myrpt, char *txt)
01870 {
01871 struct ast_frame wf;
01872
01873 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01874 wf.frametype = AST_FRAME_TEXT;
01875 wf.subclass.integer = 0;
01876 wf.offset = 0;
01877 wf.mallocd = 0;
01878 wf.datalen = strlen(txt) + 1;
01879 wf.data.ptr = txt;
01880 wf.samples = 0;
01881 ast_write(myrpt->txchannel,&wf);
01882 return 0;
01883 }
01884
01885 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01886 {
01887 struct rpt_link *l;
01888 char mode;
01889 int i,spos;
01890
01891 buf[0] = 0;
01892 if (myrpt->remote) return;
01893
01894 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01895 {
01896
01897 if (l->name[0] == '0') continue;
01898
01899 if (l == mylink) continue;
01900 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01901
01902 mode = 'T';
01903 if (!l->mode) mode = 'R';
01904 if (!l->thisconnected) mode = 'C';
01905 spos = strlen(buf);
01906 if (spos)
01907 {
01908 strcat(buf,",");
01909 spos++;
01910 }
01911
01912 if (l->linklist[0])
01913 {
01914 snprintf(buf + spos,MAXLINKLIST - spos,
01915 "%c%s,%s",mode,l->name,l->linklist);
01916 }
01917 else
01918 {
01919 snprintf(buf + spos,MAXLINKLIST - spos,
01920 "%c%s",mode,l->name);
01921 }
01922
01923 if (mode == 'T') continue;
01924
01925 for(i = spos; buf[i]; i++)
01926 {
01927 if (buf[i] == 'T') buf[i] = mode;
01928 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01929 }
01930 }
01931 return;
01932 }
01933
01934
01935 static void __kickshort(struct rpt *myrpt)
01936 {
01937 struct rpt_link *l;
01938
01939 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01940 {
01941
01942 if (l->name[0] == '0') continue;
01943 l->linklisttimer = LINKLISTSHORTTIME;
01944 }
01945 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01946 return;
01947 }
01948
01949 static void statpost(struct rpt *myrpt,char *pairs)
01950 {
01951 char *str,*astr;
01952 char *astrs[100];
01953 int n,pid;
01954 time_t now;
01955 unsigned int seq;
01956
01957 if (!myrpt->p.statpost_url) return;
01958 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01959 astr = ast_strdup(myrpt->p.statpost_program);
01960 if ((!str) || (!astr)) {
01961 ast_free(str);
01962 ast_free(astr);
01963 return;
01964 }
01965 n = finddelim(astr,astrs,100);
01966 if (n < 1) {
01967 ast_free(str);
01968 ast_free(astr);
01969 return;
01970 }
01971 ast_mutex_lock(&myrpt->statpost_lock);
01972 seq = ++myrpt->statpost_seqno;
01973 ast_mutex_unlock(&myrpt->statpost_lock);
01974 astrs[n++] = str;
01975 astrs[n] = NULL;
01976 time(&now);
01977 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01978 myrpt->name,(unsigned int) now,seq);
01979 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01980 if (!(pid = ast_safe_fork(0)))
01981 {
01982 execv(astrs[0],astrs);
01983 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01984 perror("asterisk");
01985 exit(0);
01986 }
01987 ast_free(astr);
01988 ast_free(str);
01989 return;
01990 }
01991
01992 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01993 {
01994
01995 char *val;
01996 int longestnode,j;
01997 struct stat mystat;
01998 static time_t last = 0;
01999 static struct ast_config *ourcfg = NULL;
02000 struct ast_variable *vp;
02001
02002
02003 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
02004 if (val) return(val);
02005 ast_mutex_lock(&nodelookuplock);
02006
02007 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02008 {
02009 if (ourcfg) ast_config_destroy(ourcfg);
02010 ourcfg = NULL;
02011 ast_mutex_unlock(&nodelookuplock);
02012 return(NULL);
02013 }
02014
02015 if (mystat.st_mtime > last)
02016 {
02017 if (ourcfg) ast_config_destroy(ourcfg);
02018 #ifdef NEW_ASTERISK
02019 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02020 #else
02021 ourcfg = ast_config_load(myrpt->p.extnodefile);
02022 #endif
02023
02024 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02025 {
02026 ast_mutex_unlock(&nodelookuplock);
02027 return(NULL);
02028 }
02029
02030 last = mystat.st_mtime;
02031
02032
02033 longestnode = 0;
02034 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02035 while(vp){
02036 j = strlen(vp->name);
02037 if (j > longestnode)
02038 longestnode = j;
02039 vp = vp->next;
02040 }
02041
02042 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02043 while(vp){
02044 j = strlen(vp->name);
02045 if (j > longestnode)
02046 longestnode = j;
02047 vp = vp->next;
02048 }
02049
02050 myrpt->longestnode = longestnode;
02051 }
02052 val = NULL;
02053 if (ourcfg)
02054 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02055 ast_mutex_unlock(&nodelookuplock);
02056 return(val);
02057 }
02058
02059
02060
02061
02062
02063
02064 static int matchkeyword(char *string, char **param, char *keywords[])
02065 {
02066 int i,ls;
02067 for( i = 0 ; keywords[i] ; i++){
02068 ls = strlen(keywords[i]);
02069 if(!ls){
02070 *param = NULL;
02071 return 0;
02072 }
02073 if(!strncmp(string, keywords[i], ls)){
02074 if(param)
02075 *param = string + ls;
02076 return i + 1;
02077 }
02078 }
02079 *param = NULL;
02080 return 0;
02081 }
02082
02083
02084
02085
02086
02087
02088 static char *skipchars(char *string, char *charlist)
02089 {
02090 int i;
02091 while(*string){
02092 for(i = 0; charlist[i] ; i++){
02093 if(*string == charlist[i]){
02094 string++;
02095 break;
02096 }
02097 }
02098 if(!charlist[i])
02099 return string;
02100 }
02101 return string;
02102 }
02103
02104 static int myatoi(const char *str)
02105 {
02106 int ret;
02107
02108 if (!str) {
02109 return -1;
02110 }
02111
02112
02113 if (sscanf(str, "%30i", &ret) != 1) {
02114 return -1;
02115 }
02116
02117 return ret;
02118 }
02119
02120 static int mycompar(const void *a, const void *b)
02121 {
02122 char **x = (char **) a;
02123 char **y = (char **) b;
02124 int xoff,yoff;
02125
02126 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02127 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02128 return(strcmp((*x) + xoff,(*y) + yoff));
02129 }
02130
02131 static int topcompar(const void *a, const void *b)
02132 {
02133 struct rpt_topkey *x = (struct rpt_topkey *) a;
02134 struct rpt_topkey *y = (struct rpt_topkey *) b;
02135
02136 return(x->timesince - y->timesince);
02137 }
02138
02139 #ifdef __RPT_NOTCH
02140
02141
02142 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02143 {
02144 int i,j;
02145 struct rptfilter *f;
02146
02147 for(i = 0; i < len; i++)
02148 {
02149 for(j = 0; j < MAXFILTERS; j++)
02150 {
02151 f = &myrpt->filters[j];
02152 if (!*f->desc) continue;
02153 f->x0 = f->x1; f->x1 = f->x2;
02154 f->x2 = ((float)buf[i]) / f->gain;
02155 f->y0 = f->y1; f->y1 = f->y2;
02156 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02157 + (f->const1 * f->y0) + (f->const2 * f->y1);
02158 buf[i] = (short)f->y2;
02159 }
02160 }
02161 }
02162
02163 #endif
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182 #ifdef NEW_ASTERISK
02183 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02184 {
02185 struct timeval when;
02186
02187 when.tv_sec = *t;
02188 when.tv_usec = 0;
02189 ast_localtime(&when, lt, NULL);
02190 }
02191
02192 #else
02193 static void rpt_localtime( time_t * t, struct tm *lt)
02194 {
02195 #ifdef OLD_ASTERISK
02196 localtime_r(t, lt);
02197 #else
02198 ast_localtime(t, lt, NULL);
02199 #endif
02200 }
02201 #endif
02202
02203
02204
02205
02206 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02207 {
02208 char *var;
02209 int ret;
02210 char include_zero = 0;
02211
02212 if(min < 0){
02213 min = -min;
02214 include_zero = 1;
02215 }
02216
02217 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02218 if(var){
02219 ret = myatoi(var);
02220 if(include_zero && !ret)
02221 return 0;
02222 if(ret < min)
02223 ret = min;
02224 if(ret > max)
02225 ret = max;
02226 }
02227 else
02228 ret = defl;
02229 return ret;
02230 }
02231
02232
02233 static void load_rpt_vars(int n,int init)
02234 {
02235 char *this,*val;
02236 int i,j,longestnode;
02237 struct ast_variable *vp;
02238 struct ast_config *cfg;
02239 char *strs[100];
02240 char s1[256];
02241 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02242 "ufena","ufdis","atena","atdis",NULL};
02243
02244 if (option_verbose > 2)
02245 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02246 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02247 ast_mutex_lock(&rpt_vars[n].lock);
02248 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02249 #ifdef NEW_ASTERISK
02250 cfg = ast_config_load("rpt.conf",config_flags);
02251 #else
02252 cfg = ast_config_load("rpt.conf");
02253 #endif
02254 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02255 ast_mutex_unlock(&rpt_vars[n].lock);
02256 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02257 pthread_exit(NULL);
02258 }
02259 rpt_vars[n].cfg = cfg;
02260 this = rpt_vars[n].name;
02261 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02262 if (init)
02263 {
02264 char *cp;
02265 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02266
02267 cp = (char *) &rpt_vars[n].p;
02268 memset(cp + sizeof(rpt_vars[n].p),0,
02269 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02270 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02271 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02272 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02273 rpt_vars[n].tailmessagen = 0;
02274 }
02275 #ifdef __RPT_NOTCH
02276
02277 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02278 #endif
02279 val = (char *) ast_variable_retrieve(cfg,this,"context");
02280 if (val) rpt_vars[n].p.ourcontext = val;
02281 else rpt_vars[n].p.ourcontext = this;
02282 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02283 if (val) rpt_vars[n].p.ourcallerid = val;
02284 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02285 if (val) rpt_vars[n].p.acctcode = val;
02286 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02287 if (val) rpt_vars[n].p.ident = val;
02288 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02289 if (val) rpt_vars[n].p.hangtime = atoi(val);
02290 else rpt_vars[n].p.hangtime = HANGTIME;
02291 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02292 if (val) rpt_vars[n].p.althangtime = atoi(val);
02293 else rpt_vars[n].p.althangtime = HANGTIME;
02294 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02295 if (val) rpt_vars[n].p.totime = atoi(val);
02296 else rpt_vars[n].p.totime = TOTIME;
02297 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02298 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02299 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02300 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02301 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02302 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02303 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02304 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02305 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02306 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02307 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02308 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02309 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02310 if (val) rpt_vars[n].p.statpost_program = val;
02311 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02312 rpt_vars[n].p.statpost_url =
02313 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02314 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02315 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02316 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02317 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02318 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02319 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02320 if (val) rpt_vars[n].p.tonezone = val;
02321 rpt_vars[n].p.tailmessages[0] = 0;
02322 rpt_vars[n].p.tailmessagemax = 0;
02323 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02324 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02325 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02326 if (!val) val = MEMORY;
02327 rpt_vars[n].p.memory = val;
02328 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02329 if (!val) val = MACRO;
02330 rpt_vars[n].p.macro = val;
02331 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02332 if (!val) val = TONEMACRO;
02333 rpt_vars[n].p.tonemacro = val;
02334 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02335 if (val) rpt_vars[n].p.startupmacro = val;
02336 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02337
02338
02339
02340 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02341 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02342 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02343 rpt_vars[n].p.ioport = val;
02344 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02345 if (!val)
02346 {
02347 val = FUNCTIONS;
02348 rpt_vars[n].p.simple = 1;
02349 }
02350 rpt_vars[n].p.functions = val;
02351 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02352 if (val) rpt_vars[n].p.link_functions = val;
02353 else
02354 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02355 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02356 if (val) rpt_vars[n].p.phone_functions = val;
02357 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02358 if (val) rpt_vars[n].p.dphone_functions = val;
02359 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02360 if (val) rpt_vars[n].p.alt_functions = val;
02361 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02362 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02363 rpt_vars[n].p.funcchar = *val;
02364 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02365 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02366 rpt_vars[n].p.endchar = *val;
02367 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02368 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02369 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02370 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02371 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02372 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02373 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02374 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02375 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02376 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02377 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02378 if (!val) val = NODES;
02379 rpt_vars[n].p.nodes = val;
02380 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02381 if (!val) val = EXTNODES;
02382 rpt_vars[n].p.extnodes = val;
02383 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02384 if (!val) val = EXTNODEFILE;
02385 rpt_vars[n].p.extnodefile = val;
02386 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02387 if (val) rpt_vars[n].p.archivedir = val;
02388 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02389 if (val) rpt_vars[n].p.authlevel = atoi(val);
02390 else rpt_vars[n].p.authlevel = 0;
02391 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02392 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02393 else rpt_vars[n].p.parrotmode = 0;
02394 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02395 if (val) rpt_vars[n].p.parrottime = atoi(val);
02396 else rpt_vars[n].p.parrottime = PARROTTIME;
02397 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02398 rpt_vars[n].p.rptnode = val;
02399 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02400 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02401 else rpt_vars[n].p.remote_mars = 0;
02402 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02403 if (val) rpt_vars[n].p.monminblocks = atol(val);
02404 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02405 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02406 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02407 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02408 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02409 if (val) rpt_vars[n].p.civaddr = atoi(val);
02410 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02411 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02412 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02413 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02414 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02415 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02416 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02417 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02418 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02419 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02420 #ifdef __RPT_NOTCH
02421 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02422 if (val) {
02423 i = finddelim(val,strs,MAXFILTERS * 2);
02424 i &= ~1;
02425 if (i >= 2) for(j = 0; j < i; j += 2)
02426 {
02427 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02428 &rpt_vars[n].filters[j >> 1].gain,
02429 &rpt_vars[n].filters[j >> 1].const0,
02430 &rpt_vars[n].filters[j >> 1].const1,
02431 &rpt_vars[n].filters[j >> 1].const2);
02432 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02433 strs[j],strs[j + 1]);
02434 }
02435
02436 }
02437 #endif
02438 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02439 if (val) {
02440 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02441 i = finddelim(val,strs,3);
02442 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02443 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02444 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02445 }
02446 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02447 if (val) {
02448 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02449 i = finddelim(val,strs,3);
02450 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02451 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02452 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02453 }
02454
02455 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02456 rpt_vars[n].p.csstanzaname = val;
02457
02458
02459 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02460 rpt_vars[n].p.skedstanzaname = val;
02461
02462
02463 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02464 rpt_vars[n].p.txlimitsstanzaname = val;
02465
02466 longestnode = 0;
02467
02468 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02469
02470 while(vp){
02471 j = strlen(vp->name);
02472 if (j > longestnode)
02473 longestnode = j;
02474 vp = vp->next;
02475 }
02476
02477 rpt_vars[n].longestnode = longestnode;
02478
02479
02480
02481
02482 rpt_vars[n].longestfunc = 0;
02483 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02484 while(vp){
02485 j = strlen(vp->name);
02486 if (j > rpt_vars[n].longestfunc)
02487 rpt_vars[n].longestfunc = j;
02488 vp = vp->next;
02489 }
02490
02491
02492
02493 rpt_vars[n].link_longestfunc = 0;
02494 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02495 while(vp){
02496 j = strlen(vp->name);
02497 if (j > rpt_vars[n].link_longestfunc)
02498 rpt_vars[n].link_longestfunc = j;
02499 vp = vp->next;
02500 }
02501 rpt_vars[n].phone_longestfunc = 0;
02502 if (rpt_vars[n].p.phone_functions)
02503 {
02504 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02505 while(vp){
02506 j = strlen(vp->name);
02507 if (j > rpt_vars[n].phone_longestfunc)
02508 rpt_vars[n].phone_longestfunc = j;
02509 vp = vp->next;
02510 }
02511 }
02512 rpt_vars[n].dphone_longestfunc = 0;
02513 if (rpt_vars[n].p.dphone_functions)
02514 {
02515 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02516 while(vp){
02517 j = strlen(vp->name);
02518 if (j > rpt_vars[n].dphone_longestfunc)
02519 rpt_vars[n].dphone_longestfunc = j;
02520 vp = vp->next;
02521 }
02522 }
02523 rpt_vars[n].alt_longestfunc = 0;
02524 if (rpt_vars[n].p.alt_functions)
02525 {
02526 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02527 while(vp){
02528 j = strlen(vp->name);
02529 if (j > rpt_vars[n].alt_longestfunc)
02530 rpt_vars[n].alt_longestfunc = j;
02531 vp = vp->next;
02532 }
02533 }
02534 rpt_vars[n].macro_longest = 1;
02535 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02536 while(vp){
02537 j = strlen(vp->name);
02538 if (j > rpt_vars[n].macro_longest)
02539 rpt_vars[n].macro_longest = j;
02540 vp = vp->next;
02541 }
02542
02543
02544 if(rpt_vars[n].p.csstanzaname)
02545 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02546 else
02547 vp = NULL;
02548 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02549 int k,nukw,statenum;
02550 statenum=atoi(vp->name);
02551 strncpy(s1, vp->value, 255);
02552 s1[255] = 0;
02553 nukw = finddelim(s1,strs,32);
02554
02555 for (k = 0 ; k < nukw ; k++){
02556 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02557 if(!strcmp(strs[k],cs_keywords[j])){
02558 switch(j){
02559 case 0:
02560 rpt_vars[n].p.s[statenum].txdisable = 0;
02561 break;
02562 case 1:
02563 rpt_vars[n].p.s[statenum].txdisable = 1;
02564 break;
02565
02566 case 2:
02567 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02568 break;
02569
02570 case 3:
02571 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02572 break;
02573
02574 case 4:
02575 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02576 break;
02577
02578 case 5:
02579 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02580 break;
02581
02582 case 6:
02583 rpt_vars[n].p.s[statenum].totdisable = 0;
02584 break;
02585
02586 case 7:
02587 rpt_vars[n].p.s[statenum].totdisable = 1;
02588 break;
02589
02590 case 8:
02591 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02592 break;
02593
02594 case 9:
02595 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02596 break;
02597
02598 case 10:
02599 rpt_vars[n].p.s[statenum].userfundisable = 0;
02600 break;
02601
02602 case 11:
02603 rpt_vars[n].p.s[statenum].userfundisable = 1;
02604 break;
02605
02606 case 12:
02607 rpt_vars[n].p.s[statenum].alternatetail = 1;
02608 break;
02609
02610 case 13:
02611 rpt_vars[n].p.s[statenum].alternatetail = 0;
02612 break;
02613
02614 default:
02615 ast_log(LOG_WARNING,
02616 "Unhandled control state keyword %s", cs_keywords[i]);
02617 break;
02618 }
02619 }
02620 }
02621 }
02622 vp = vp->next;
02623 }
02624 ast_mutex_unlock(&rpt_vars[n].lock);
02625 }
02626
02627
02628
02629
02630 static int rpt_do_debug(int fd, int argc, const char * const *argv)
02631 {
02632 int newlevel;
02633
02634 if (argc != 4) {
02635 return RESULT_SHOWUSAGE;
02636 }
02637
02638 newlevel = myatoi(argv[3]);
02639
02640 if (newlevel < 0 || newlevel > 7) {
02641 return RESULT_SHOWUSAGE;
02642 }
02643
02644 if (newlevel) {
02645 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02646 } else {
02647 ast_cli(fd, "app_rpt Debugging disabled\n");
02648 }
02649
02650 debug = newlevel;
02651
02652 return RESULT_SUCCESS;
02653 }
02654
02655
02656
02657
02658
02659 static int rpt_do_dump(int fd, int argc, const char * const *argv)
02660 {
02661 int i;
02662
02663 if (argc != 3)
02664 return RESULT_SHOWUSAGE;
02665
02666 for(i = 0; i < nrpts; i++)
02667 {
02668 if (!strcmp(argv[2],rpt_vars[i].name))
02669 {
02670 rpt_vars[i].disgorgetime = time(NULL) + 10;
02671 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02672 return RESULT_SUCCESS;
02673 }
02674 }
02675 return RESULT_FAILURE;
02676 }
02677
02678
02679
02680
02681
02682 static int rpt_do_stats(int fd, int argc, const char * const *argv)
02683 {
02684 int i,j,numoflinks;
02685 int dailytxtime, dailykerchunks;
02686 time_t now;
02687 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02688 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02689 int uptime;
02690 long long totaltxtime;
02691 struct rpt_link *l;
02692 char *listoflinks[MAX_STAT_LINKS];
02693 char *lastdtmfcommand,*parrot_ena;
02694 char *tot_state, *ider_state, *patch_state;
02695 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02696 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02697 struct rpt *myrpt;
02698
02699 static char *not_applicable = "N/A";
02700
02701 if(argc != 3)
02702 return RESULT_SHOWUSAGE;
02703
02704 tot_state = ider_state =
02705 patch_state = reverse_patch_state =
02706 input_signal = not_applicable;
02707 called_number = lastdtmfcommand = NULL;
02708
02709 time(&now);
02710 for(i = 0; i < nrpts; i++)
02711 {
02712 if (!strcmp(argv[2],rpt_vars[i].name)){
02713
02714 myrpt = &rpt_vars[i];
02715 rpt_mutex_lock(&myrpt->lock);
02716 uptime = (int)(now - starttime);
02717 dailytxtime = myrpt->dailytxtime;
02718 totaltxtime = myrpt->totaltxtime;
02719 dailykeyups = myrpt->dailykeyups;
02720 totalkeyups = myrpt->totalkeyups;
02721 dailykerchunks = myrpt->dailykerchunks;
02722 totalkerchunks = myrpt->totalkerchunks;
02723 dailyexecdcommands = myrpt->dailyexecdcommands;
02724 totalexecdcommands = myrpt->totalexecdcommands;
02725 timeouts = myrpt->timeouts;
02726
02727
02728 reverse_patch_state = "DOWN";
02729 numoflinks = 0;
02730 l = myrpt->links.next;
02731 while(l && (l != &myrpt->links)){
02732 if(numoflinks >= MAX_STAT_LINKS){
02733 ast_log(LOG_NOTICE,
02734 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02735 break;
02736 }
02737 if (l->name[0] == '0'){
02738 reverse_patch_state = "UP";
02739 l = l->next;
02740 continue;
02741 }
02742 listoflinks[numoflinks] = ast_strdup(l->name);
02743 if(listoflinks[numoflinks] == NULL){
02744 break;
02745 }
02746 else{
02747 numoflinks++;
02748 }
02749 l = l->next;
02750 }
02751
02752 if(myrpt->keyed)
02753 input_signal = "YES";
02754 else
02755 input_signal = "NO";
02756
02757 if(myrpt->p.parrotmode)
02758 parrot_ena = "ENABLED";
02759 else
02760 parrot_ena = "DISABLED";
02761
02762 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02763 sys_ena = "DISABLED";
02764 else
02765 sys_ena = "ENABLED";
02766
02767 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02768 tot_ena = "DISABLED";
02769 else
02770 tot_ena = "ENABLED";
02771
02772 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02773 link_ena = "DISABLED";
02774 else
02775 link_ena = "ENABLED";
02776
02777 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02778 patch_ena = "DISABLED";
02779 else
02780 patch_ena = "ENABLED";
02781
02782 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02783 sch_ena = "DISABLED";
02784 else
02785 sch_ena = "ENABLED";
02786
02787 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02788 user_funs = "DISABLED";
02789 else
02790 user_funs = "ENABLED";
02791
02792 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02793 tail_type = "ALTERNATE";
02794 else
02795 tail_type = "STANDARD";
02796
02797 if(!myrpt->totimer)
02798 tot_state = "TIMED OUT!";
02799 else if(myrpt->totimer != myrpt->p.totime)
02800 tot_state = "ARMED";
02801 else
02802 tot_state = "RESET";
02803
02804 if(myrpt->tailid)
02805 ider_state = "QUEUED IN TAIL";
02806 else if(myrpt->mustid)
02807 ider_state = "QUEUED FOR CLEANUP";
02808 else
02809 ider_state = "CLEAN";
02810
02811 switch(myrpt->callmode){
02812 case 1:
02813 patch_state = "DIALING";
02814 break;
02815 case 2:
02816 patch_state = "CONNECTING";
02817 break;
02818 case 3:
02819 patch_state = "UP";
02820 break;
02821
02822 case 4:
02823 patch_state = "CALL FAILED";
02824 break;
02825
02826 default:
02827 patch_state = "DOWN";
02828 }
02829
02830 if(strlen(myrpt->exten)){
02831 called_number = ast_strdup(myrpt->exten);
02832 }
02833
02834 if(strlen(myrpt->lastdtmfcommand)){
02835 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02836 }
02837 rpt_mutex_unlock(&myrpt->lock);
02838
02839 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02840 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02841 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02842 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02843 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02844 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02845 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02846 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02847 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02848 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02849 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02850 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02851 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02852 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02853 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02854 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02855 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02856 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02857 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02858 hours = dailytxtime/3600000;
02859 dailytxtime %= 3600000;
02860 minutes = dailytxtime/60000;
02861 dailytxtime %= 60000;
02862 seconds = dailytxtime/1000;
02863 dailytxtime %= 1000;
02864
02865 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02866 hours, minutes, seconds, dailytxtime);
02867
02868 hours = (int) totaltxtime/3600000;
02869 totaltxtime %= 3600000;
02870 minutes = (int) totaltxtime/60000;
02871 totaltxtime %= 60000;
02872 seconds = (int) totaltxtime/1000;
02873 totaltxtime %= 1000;
02874
02875 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02876 hours, minutes, seconds, (int) totaltxtime);
02877
02878 hours = uptime/3600;
02879 uptime %= 3600;
02880 minutes = uptime/60;
02881 uptime %= 60;
02882
02883 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02884 hours, minutes, uptime);
02885
02886 ast_cli(fd, "Nodes currently connected to us..................: ");
02887 if(!numoflinks){
02888 ast_cli(fd,"<NONE>");
02889 }
02890 else{
02891 for(j = 0 ;j < numoflinks; j++){
02892 ast_cli(fd, "%s", listoflinks[j]);
02893 if(j % 4 == 3){
02894 ast_cli(fd, "\n");
02895 ast_cli(fd, " : ");
02896 }
02897 else{
02898 if((numoflinks - 1) - j > 0)
02899 ast_cli(fd, ", ");
02900 }
02901 }
02902 }
02903 ast_cli(fd,"\n");
02904
02905 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02906 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02907 ast_cli(fd, "Autopatch called number..........................: %s\n",
02908 (called_number && strlen(called_number)) ? called_number : not_applicable);
02909 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02910 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02911 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02912
02913 for(j = 0; j < numoflinks; j++){
02914 ast_free(listoflinks[j]);
02915 }
02916 ast_free(called_number);
02917 ast_free(lastdtmfcommand);
02918 return RESULT_SUCCESS;
02919 }
02920 }
02921 return RESULT_FAILURE;
02922 }
02923
02924
02925
02926
02927
02928 static int rpt_do_lstats(int fd, int argc, const char * const *argv)
02929 {
02930 int i,j;
02931 char *connstate;
02932 struct rpt *myrpt;
02933 struct rpt_link *l;
02934 struct rpt_lstat *s,*t;
02935 struct rpt_lstat s_head;
02936 if(argc != 3)
02937 return RESULT_SHOWUSAGE;
02938
02939 s = NULL;
02940 s_head.next = &s_head;
02941 s_head.prev = &s_head;
02942
02943 for(i = 0; i < nrpts; i++)
02944 {
02945 if (!strcmp(argv[2],rpt_vars[i].name)){
02946
02947 myrpt = &rpt_vars[i];
02948 rpt_mutex_lock(&myrpt->lock);
02949
02950 j = 0;
02951 l = myrpt->links.next;
02952 while(l && (l != &myrpt->links)){
02953 if (l->name[0] == '0'){
02954 l = l->next;
02955 continue;
02956 }
02957 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02958 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02959 rpt_mutex_unlock(&myrpt->lock);
02960 return RESULT_FAILURE;
02961 }
02962 memset(s, 0, sizeof(struct rpt_lstat));
02963 strncpy(s->name, l->name, MAXREMSTR - 1);
02964 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02965 else strcpy(s->peer,"(none)");
02966 s->mode = l->mode;
02967 s->outbound = l->outbound;
02968 s->reconnects = l->reconnects;
02969 s->connecttime = l->connecttime;
02970 s->thisconnected = l->thisconnected;
02971 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02972 insque((struct qelem *) s, (struct qelem *) s_head.next);
02973 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02974 l = l->next;
02975 }
02976 rpt_mutex_unlock(&myrpt->lock);
02977 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02978 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02979
02980 for(s = s_head.next; s != &s_head; s = s->next){
02981 int hours, minutes, seconds;
02982 long long connecttime = s->connecttime;
02983 char conntime[21];
02984 hours = (int) connecttime/3600000;
02985 connecttime %= 3600000;
02986 minutes = (int) connecttime/60000;
02987 connecttime %= 60000;
02988 seconds = (int) connecttime/1000;
02989 connecttime %= 1000;
02990 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02991 hours, minutes, seconds, (int) connecttime);
02992 conntime[20] = 0;
02993 if(s->thisconnected)
02994 connstate = "ESTABLISHED";
02995 else
02996 connstate = "CONNECTING";
02997 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02998 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02999 }
03000
03001 s = s_head.next;
03002 while(s != &s_head){
03003 t = s;
03004 s = s->next;
03005 remque((struct qelem *)t);
03006 ast_free(t);
03007 }
03008 return RESULT_SUCCESS;
03009 }
03010 }
03011 return RESULT_FAILURE;
03012 }
03013
03014
03015
03016
03017
03018 static int rpt_do_nodes(int fd, int argc, const char * const *argv)
03019 {
03020 int i,j;
03021 char ns;
03022 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03023 struct rpt *myrpt;
03024 if(argc != 3)
03025 return RESULT_SHOWUSAGE;
03026
03027 for(i = 0; i < nrpts; i++)
03028 {
03029 if (!strcmp(argv[2],rpt_vars[i].name)){
03030
03031 myrpt = &rpt_vars[i];
03032 rpt_mutex_lock(&myrpt->lock);
03033 __mklinklist(myrpt,NULL,lbuf);
03034 rpt_mutex_unlock(&myrpt->lock);
03035
03036 ns = finddelim(lbuf,strs,MAXLINKLIST);
03037
03038 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03039 ast_cli(fd,"\n");
03040 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03041 for(j = 0 ;; j++){
03042 if(!strs[j]){
03043 if(!j){
03044 ast_cli(fd,"<NONE>");
03045 }
03046 break;
03047 }
03048 ast_cli(fd, "%s", strs[j]);
03049 if(j % 8 == 7){
03050 ast_cli(fd, "\n");
03051 }
03052 else{
03053 if(strs[j + 1])
03054 ast_cli(fd, ", ");
03055 }
03056 }
03057 ast_cli(fd,"\n\n");
03058 return RESULT_SUCCESS;
03059 }
03060 }
03061 return RESULT_FAILURE;
03062 }
03063
03064
03065
03066
03067
03068 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv)
03069 {
03070
03071 int i;
03072 ast_cli(fd, "\nNode\n----\n");
03073 for (i=0; i< nrpts; i++)
03074 {
03075 ast_cli(fd, "%s\n", rpt_vars[i].name);
03076 }
03077 ast_cli(fd,"\n");
03078 return RESULT_SUCCESS;
03079 }
03080
03081
03082
03083
03084
03085
03086 static int rpt_do_reload(int fd, int argc, const char * const *argv)
03087 {
03088 int n;
03089
03090 if (argc > 2) return RESULT_SHOWUSAGE;
03091
03092 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03093
03094 return RESULT_FAILURE;
03095 }
03096
03097
03098
03099
03100
03101 static int rpt_do_restart(int fd, int argc, const char * const *argv)
03102 {
03103 int i;
03104
03105 if (argc > 2) return RESULT_SHOWUSAGE;
03106 for(i = 0; i < nrpts; i++)
03107 {
03108 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03109 }
03110 return RESULT_FAILURE;
03111 }
03112
03113
03114
03115
03116
03117
03118 static int rpt_do_fun(int fd, int argc, const char * const *argv)
03119 {
03120 int i,busy=0;
03121
03122 if (argc != 4) return RESULT_SHOWUSAGE;
03123
03124 for(i = 0; i < nrpts; i++){
03125 if(!strcmp(argv[2], rpt_vars[i].name)){
03126 struct rpt *myrpt = &rpt_vars[i];
03127 rpt_mutex_lock(&myrpt->lock);
03128 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03129 rpt_mutex_unlock(&myrpt->lock);
03130 busy=1;
03131 }
03132 if(!busy){
03133 myrpt->macrotimer = MACROTIME;
03134 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03135 }
03136 rpt_mutex_unlock(&myrpt->lock);
03137 }
03138 }
03139 if(busy){
03140 ast_cli(fd, "Function decoder busy");
03141 }
03142 return RESULT_FAILURE;
03143 }
03144
03145
03146
03147
03148
03149
03150
03151
03152 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03153 {
03154 int busy=0;
03155
03156 rpt_mutex_lock(&myrpt->lock);
03157 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03158 rpt_mutex_unlock(&myrpt->lock);
03159 busy=1;
03160 }
03161 if(!busy){
03162 int x;
03163 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03164 myrpt->macrotimer = MACROTIME;
03165 for(x = 0; *(sptr + x); x++)
03166 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03167 *(sptr + x) = 0;
03168 }
03169 rpt_mutex_unlock(&myrpt->lock);
03170
03171 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03172
03173 return busy;
03174 }
03175
03176
03177
03178 static int rpt_do_fun1(int fd, int argc, const char * const *argv)
03179 {
03180 int i;
03181
03182 if (argc != 4) return RESULT_SHOWUSAGE;
03183
03184 for(i = 0; i < nrpts; i++){
03185 if(!strcmp(argv[2], rpt_vars[i].name)){
03186 struct rpt *myrpt = &rpt_vars[i];
03187 rpt_push_alt_macro(myrpt, (char *) argv[3]);
03188 }
03189 }
03190 return RESULT_FAILURE;
03191 }
03192
03193
03194
03195
03196 static int rpt_do_cmd(int fd, int argc, const char * const *argv)
03197 {
03198 int i, l;
03199 int busy=0;
03200 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03201
03202 int thisRpt = -1;
03203 int thisAction = -1;
03204 struct rpt *myrpt = NULL;
03205 if (argc != 6) return RESULT_SHOWUSAGE;
03206
03207 for(i = 0; i < nrpts; i++)
03208 {
03209 if(!strcmp(argv[2], rpt_vars[i].name))
03210 {
03211 thisRpt = i;
03212 myrpt = &rpt_vars[i];
03213 break;
03214 }
03215 }
03216
03217 if (thisRpt < 0)
03218 {
03219 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03220 return RESULT_FAILURE;
03221 }
03222
03223
03224 l = strlen(argv[3]);
03225 for(i = 0 ; i < maxActions; i++)
03226 {
03227 if(!strncasecmp(argv[3], function_table[i].action, l))
03228 {
03229 thisAction = i;
03230 break;
03231 }
03232 }
03233
03234 if (thisAction < 0)
03235 {
03236 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03237 return RESULT_FAILURE;
03238 }
03239
03240
03241
03242 rpt_mutex_lock(&myrpt->lock);
03243
03244 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03245 {
03246 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03247 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03248 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03249 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03250 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03251 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03252 }
03253 else
03254 {
03255 busy = 1;
03256 }
03257 rpt_mutex_unlock(&myrpt->lock);
03258
03259 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03260 }
03261
03262 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03263 {
03264 int res;
03265
03266 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03267 return res;
03268
03269 while(chan->generatordata) {
03270 if (ast_safe_sleep(chan,1)) return -1;
03271 }
03272
03273 return 0;
03274 }
03275
03276 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03277 {
03278 return play_tone_pair(chan, freq, 0, duration, amplitude);
03279 }
03280
03281 static int play_silence(struct ast_channel *chan, int duration)
03282 {
03283 return play_tone_pair(chan, 0, 0, duration, 0);
03284 }
03285
03286 #ifdef NEW_ASTERISK
03287
03288 static char *res2cli(int r)
03289
03290 {
03291 switch (r)
03292 {
03293 case RESULT_SUCCESS:
03294 return(CLI_SUCCESS);
03295 case RESULT_SHOWUSAGE:
03296 return(CLI_SHOWUSAGE);
03297 default:
03298 return(CLI_FAILURE);
03299 }
03300 }
03301
03302 static char *handle_cli_debug(struct ast_cli_entry *e,
03303 int cmd, struct ast_cli_args *a)
03304 {
03305 switch (cmd) {
03306 case CLI_INIT:
03307 e->command = "rpt debug level";
03308 e->usage = debug_usage;
03309 return NULL;
03310 case CLI_GENERATE:
03311 return NULL;
03312 }
03313 return res2cli(rpt_do_debug(a->fd, a->argc, a->argv));
03314 }
03315
03316 static char *handle_cli_dump(struct ast_cli_entry *e,
03317 int cmd, struct ast_cli_args *a)
03318 {
03319 switch (cmd) {
03320 case CLI_INIT:
03321 e->command = "rpt dump level";
03322 e->usage = dump_usage;
03323 return NULL;
03324 case CLI_GENERATE:
03325 return NULL;
03326 }
03327 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03328 }
03329
03330
03331 static char *handle_cli_stats(struct ast_cli_entry *e,
03332 int cmd, struct ast_cli_args *a)
03333 {
03334 switch (cmd) {
03335 case CLI_INIT:
03336 e->command = "rpt stats";
03337 e->usage = dump_stats;
03338 return NULL;
03339 case CLI_GENERATE:
03340 return NULL;
03341 }
03342 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03343 }
03344
03345 static char *handle_cli_nodes(struct ast_cli_entry *e,
03346 int cmd, struct ast_cli_args *a)
03347 {
03348 switch (cmd) {
03349 case CLI_INIT:
03350 e->command = "rpt nodes";
03351 e->usage = dump_nodes;
03352 return NULL;
03353 case CLI_GENERATE:
03354 return NULL;
03355 }
03356 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03357 }
03358
03359 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03360 int cmd, struct ast_cli_args *a)
03361 {
03362 switch (cmd) {
03363 case CLI_INIT:
03364 e->command = "rpt localnodes";
03365 e->usage = usage_local_nodes;
03366 return NULL;
03367 case CLI_GENERATE:
03368 return NULL;
03369 }
03370 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03371 }
03372
03373 static char *handle_cli_lstats(struct ast_cli_entry *e,
03374 int cmd, struct ast_cli_args *a)
03375 {
03376 switch (cmd) {
03377 case CLI_INIT:
03378 e->command = "rpt lstats";
03379 e->usage = dump_lstats;
03380 return NULL;
03381 case CLI_GENERATE:
03382 return NULL;
03383 }
03384 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03385 }
03386
03387 static char *handle_cli_reload(struct ast_cli_entry *e,
03388 int cmd, struct ast_cli_args *a)
03389 {
03390 switch (cmd) {
03391 case CLI_INIT:
03392 e->command = "rpt reload";
03393 e->usage = reload_usage;
03394 return NULL;
03395 case CLI_GENERATE:
03396 return NULL;
03397 }
03398 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03399 }
03400
03401 static char *handle_cli_restart(struct ast_cli_entry *e,
03402 int cmd, struct ast_cli_args *a)
03403 {
03404 switch (cmd) {
03405 case CLI_INIT:
03406 e->command = "rpt restart";
03407 e->usage = restart_usage;
03408 return NULL;
03409 case CLI_GENERATE:
03410 return NULL;
03411 }
03412 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03413 }
03414
03415 static char *handle_cli_fun(struct ast_cli_entry *e,
03416 int cmd, struct ast_cli_args *a)
03417 {
03418 switch (cmd) {
03419 case CLI_INIT:
03420 e->command = "rpt fun";
03421 e->usage = fun_usage;
03422 return NULL;
03423 case CLI_GENERATE:
03424 return NULL;
03425 }
03426 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03427 }
03428
03429 static char *handle_cli_fun1(struct ast_cli_entry *e,
03430 int cmd, struct ast_cli_args *a)
03431 {
03432 switch (cmd) {
03433 case CLI_INIT:
03434 e->command = "rpt fun1";
03435 e->usage = fun_usage;
03436 return NULL;
03437 case CLI_GENERATE:
03438 return NULL;
03439 }
03440 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03441 }
03442
03443 static char *handle_cli_cmd(struct ast_cli_entry *e,
03444 int cmd, struct ast_cli_args *a)
03445 {
03446 switch (cmd) {
03447 case CLI_INIT:
03448 e->command = "rpt cmd";
03449 e->usage = cmd_usage;
03450 return NULL;
03451 case CLI_GENERATE:
03452 return NULL;
03453 }
03454 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03455 }
03456
03457 static struct ast_cli_entry rpt_cli[] = {
03458 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03459 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03460 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03461 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03462 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03463 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03464 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03465 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03466 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03467 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03468 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03469 };
03470
03471 #endif
03472
03473 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03474 {
03475
03476 static struct morse_bits mbits[] = {
03477 {0, 0},
03478 {0, 0},
03479 {6, 18},
03480 {0, 0},
03481 {7, 72},
03482 {0, 0},
03483 {0, 0},
03484 {6, 30},
03485 {5, 13},
03486 {6, 29},
03487 {0, 0},
03488 {5, 10},
03489 {6, 51},
03490 {6, 33},
03491 {6, 42},
03492 {5, 9},
03493 {5, 31},
03494 {5, 30},
03495 {5, 28},
03496 {5, 24},
03497 {5, 16},
03498 {5, 0},
03499 {5, 1},
03500 {5, 3},
03501 {5, 7},
03502 {5, 15},
03503 {6, 7},
03504 {6, 21},
03505 {0, 0},
03506 {5, 33},
03507 {0, 0},
03508 {6, 12},
03509 {0, 0},
03510 {2, 2},
03511 {4, 1},
03512 {4, 5},
03513 {3, 1},
03514 {1, 0},
03515 {4, 4},
03516 {3, 3},
03517 {4, 0},
03518 {2, 0},
03519 {4, 14},
03520 {3, 5},
03521 {4, 2},
03522 {2, 3},
03523 {2, 1},
03524 {3, 7},
03525 {4, 6},
03526 {4, 11},
03527 {3, 2},
03528 {3, 0},
03529 {1, 1},
03530 {3, 4},
03531 {4, 8},
03532 {3, 6},
03533 {4, 9},
03534 {4, 13},
03535 {4, 3}
03536 };
03537
03538
03539 int dottime;
03540 int dashtime;
03541 int intralettertime;
03542 int interlettertime;
03543 int interwordtime;
03544 int len, ddcomb;
03545 int res;
03546 int c;
03547 int i;
03548 int flags;
03549
03550 res = 0;
03551
03552
03553
03554 dottime = 900/speed;
03555
03556
03557
03558 dashtime = 3 * dottime;
03559 intralettertime = dottime;
03560 interlettertime = dottime * 4 ;
03561 interwordtime = dottime * 7;
03562
03563 for(;(*string) && (!res); string++){
03564
03565 c = *string;
03566
03567
03568
03569 if((c >= 'a') && (c <= 'z'))
03570 c -= 0x20;
03571
03572
03573
03574 if(c > 'Z')
03575 continue;
03576
03577
03578
03579 if(c == ' '){
03580 if(!res)
03581 res = play_silence(chan, interwordtime);
03582 continue;
03583 }
03584
03585
03586
03587 c -= 0x20;
03588
03589
03590
03591 len = mbits[c].len;
03592 ddcomb = mbits[c].ddcomb;
03593
03594
03595
03596 for(; len ; len--){
03597 if(!res)
03598 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03599 if(!res)
03600 res = play_silence(chan, intralettertime);
03601 ddcomb >>= 1;
03602 }
03603
03604
03605
03606 if(!res)
03607 res = play_silence(chan, interlettertime - intralettertime);
03608 }
03609
03610
03611
03612 if (!res)
03613 res = ast_waitstream(chan, "");
03614 ast_stopstream(chan);
03615
03616
03617
03618
03619
03620 for(i = 0; i < 20 ; i++){
03621 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03622 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03623 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03624 break;
03625 if( ast_safe_sleep(chan, 50)){
03626 res = -1;
03627 break;
03628 }
03629 }
03630
03631
03632 return res;
03633 }
03634
03635 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03636 {
03637 char *p,*stringp;
03638 char *tonesubset;
03639 int f1,f2;
03640 int duration;
03641 int amplitude;
03642 int res;
03643 int i;
03644 int flags;
03645
03646 res = 0;
03647
03648 if(!tonestring)
03649 return res;
03650
03651 p = stringp = ast_strdup(tonestring);
03652
03653 for(;tonestring;){
03654 tonesubset = strsep(&stringp,")");
03655 if(!tonesubset)
03656 break;
03657 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03658 break;
03659 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03660 if(res)
03661 break;
03662 }
03663 ast_free(p);
03664 if(!res)
03665 res = play_tone_pair(chan, 0, 0, 100, 0);
03666
03667 if (!res)
03668 res = ast_waitstream(chan, "");
03669
03670 ast_stopstream(chan);
03671
03672
03673
03674
03675
03676 for(i = 0; i < 20 ; i++){
03677 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03678 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03679 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03680 break;
03681 if( ast_safe_sleep(chan, 50)){
03682 res = -1;
03683 break;
03684 }
03685 }
03686
03687 return res;
03688
03689 }
03690
03691 static int sayfile(struct ast_channel *mychannel,char *fname)
03692 {
03693 int res;
03694
03695 res = ast_streamfile(mychannel, fname, mychannel->language);
03696 if (!res)
03697 res = ast_waitstream(mychannel, "");
03698 else
03699 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03700 ast_stopstream(mychannel);
03701 return res;
03702 }
03703
03704 static int saycharstr(struct ast_channel *mychannel,char *str)
03705 {
03706 int res;
03707
03708 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03709 if (!res)
03710 res = ast_waitstream(mychannel, "");
03711 else
03712 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03713 ast_stopstream(mychannel);
03714 return res;
03715 }
03716
03717 static int saynum(struct ast_channel *mychannel, int num)
03718 {
03719 int res;
03720 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03721 if(!res)
03722 res = ast_waitstream(mychannel, "");
03723 else
03724 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03725 ast_stopstream(mychannel);
03726 return res;
03727 }
03728
03729
03730
03731
03732 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03733 {
03734 int res;
03735 char *val,fname[300];
03736
03737 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03738 if (!val) val = NODENAMES;
03739 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03740 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03741 return(sayfile(mychannel,fname));
03742 res = sayfile(mychannel,"rpt/node");
03743 if (!res)
03744 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03745 return res;
03746 }
03747
03748 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03749 {
03750 int res;
03751 char c;
03752
03753 static int morsespeed;
03754 static int morsefreq;
03755 static int morseampl;
03756 static int morseidfreq = 0;
03757 static int morseidampl;
03758 static char mcat[] = MORSE;
03759
03760 res = 0;
03761
03762 if(!morseidfreq){
03763 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03764 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03765 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03766 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03767 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03768 }
03769
03770
03771
03772 if(entry[0] == '|'){
03773 c = entry[1];
03774 if((c >= 'a')&&(c <= 'z'))
03775 c -= 0x20;
03776
03777 switch(c){
03778 case 'I':
03779 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03780 break;
03781
03782 case 'M':
03783 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03784 break;
03785
03786 case 'T':
03787 res = send_tone_telemetry(chan, entry + 2);
03788 break;
03789 default:
03790 res = -1;
03791 }
03792 }
03793 else
03794 res = sayfile(chan, entry);
03795 return res;
03796 }
03797
03798
03799
03800
03801
03802
03803
03804 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03805 {
03806
03807 int res;
03808 int i;
03809 char *entry;
03810 char *telemetry;
03811 char *telemetry_save;
03812
03813 res = 0;
03814 telemetry_save = NULL;
03815 entry = NULL;
03816
03817
03818 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03819 if(telemetry ){
03820 telemetry_save = ast_strdup(telemetry);
03821 if(!telemetry_save){
03822 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03823 return res;
03824 }
03825 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03826 }
03827
03828
03829
03830 if(!entry){
03831
03832 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03833 if(!strcasecmp(tele_defs[i].name, name))
03834 entry = tele_defs[i].value;
03835 }
03836 }
03837 if(entry){
03838 if(strlen(entry))
03839 if (chan) telem_any(myrpt,chan, entry);
03840 }
03841 else{
03842 res = -1;
03843 }
03844 ast_free(telemetry_save);
03845 return res;
03846 }
03847
03848
03849
03850
03851
03852 static int get_wait_interval(struct rpt *myrpt, int type)
03853 {
03854 int interval;
03855 char *wait_times;
03856 char *wait_times_save;
03857
03858 wait_times_save = NULL;
03859 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03860
03861 if(wait_times){
03862 wait_times_save = ast_strdup(wait_times);
03863 if(!wait_times_save)
03864 return 0;
03865
03866 }
03867
03868 switch(type){
03869 case DLY_TELEM:
03870 if(wait_times)
03871 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03872 else
03873 interval = 1000;
03874 break;
03875
03876 case DLY_ID:
03877 if(wait_times)
03878 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03879 else
03880 interval = 500;
03881 break;
03882
03883 case DLY_UNKEY:
03884 if(wait_times)
03885 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03886 else
03887 interval = 1000;
03888 break;
03889
03890 case DLY_LINKUNKEY:
03891 if(wait_times)
03892 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03893 else
03894 interval = 1000;
03895 break;
03896
03897 case DLY_CALLTERM:
03898 if(wait_times)
03899 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03900 else
03901 interval = 1500;
03902 break;
03903
03904 case DLY_COMP:
03905 if(wait_times)
03906 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03907 else
03908 interval = 200;
03909 break;
03910
03911 case DLY_PARROT:
03912 if(wait_times)
03913 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03914 else
03915 interval = 200;
03916 break;
03917
03918 default:
03919 interval = 0;
03920 break;
03921 }
03922 ast_free(wait_times_save);
03923 return interval;
03924 }
03925
03926
03927
03928
03929
03930 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03931 {
03932 int interval;
03933 interval = get_wait_interval(myrpt, type);
03934 if(debug)
03935 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03936 if(interval)
03937 ast_safe_sleep(chan,interval);
03938 if(debug)
03939 ast_log(LOG_NOTICE,"Delay complete\n");
03940 return;
03941 }
03942
03943 static int split_freq(char *mhz, char *decimals, char *freq);
03944
03945 static void *rpt_tele_thread(void *this)
03946 {
03947 struct dahdi_confinfo ci;
03948 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03949 struct rpt_tele *mytele = (struct rpt_tele *)this;
03950 struct rpt_tele *tlist;
03951 struct rpt *myrpt;
03952 struct rpt_link *l,*l1,linkbase;
03953 struct ast_channel *mychannel;
03954 int vmajor, vminor, m;
03955 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03956 time_t t;
03957 #ifdef NEW_ASTERISK
03958 struct ast_tm localtm;
03959 #else
03960 struct tm localtm;
03961 #endif
03962 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03963 int i,ns,rbimode;
03964 char mhz[MAXREMSTR];
03965 char decimals[MAXREMSTR];
03966 char mystr[200];
03967 struct dahdi_params par;
03968
03969
03970
03971 myrpt = mytele->rpt;
03972
03973
03974 rpt_mutex_lock(&myrpt->lock);
03975 nodename = ast_strdup(myrpt->name);
03976 if(!nodename)
03977 {
03978 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03979 rpt_mutex_lock(&myrpt->lock);
03980 remque((struct qelem *)mytele);
03981 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03982 rpt_mutex_unlock(&myrpt->lock);
03983 ast_free(mytele);
03984 pthread_exit(NULL);
03985 }
03986
03987 if (myrpt->p.ident){
03988 ident = ast_strdup(myrpt->p.ident);
03989 if(!ident)
03990 {
03991 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03992 rpt_mutex_lock(&myrpt->lock);
03993 remque((struct qelem *)mytele);
03994 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03995 __LINE__, mytele->mode);
03996 rpt_mutex_unlock(&myrpt->lock);
03997 ast_free(nodename);
03998 ast_free(mytele);
03999 pthread_exit(NULL);
04000 }
04001 }
04002 else
04003 {
04004 ident = "";
04005 }
04006 rpt_mutex_unlock(&myrpt->lock);
04007
04008
04009
04010
04011 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
04012 if (!mychannel)
04013 {
04014 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04015 rpt_mutex_lock(&myrpt->lock);
04016 remque((struct qelem *)mytele);
04017 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04018 rpt_mutex_unlock(&myrpt->lock);
04019 ast_free(nodename);
04020 ast_free(ident);
04021 ast_free(mytele);
04022 pthread_exit(NULL);
04023 }
04024 #ifdef AST_CDR_FLAG_POST_DISABLED
04025 if (mychannel->cdr)
04026 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04027 #endif
04028 rpt_mutex_lock(&myrpt->lock);
04029 mytele->chan = mychannel;
04030 rpt_mutex_unlock(&myrpt->lock);
04031
04032 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04033 (mytele->mode != LINKUNKEY))
04034 {
04035 rpt_mutex_lock(&myrpt->lock);
04036 if (!myrpt->active_telem)
04037 {
04038 myrpt->active_telem = mytele;
04039 rpt_mutex_unlock(&myrpt->lock);
04040 break;
04041 }
04042 rpt_mutex_unlock(&myrpt->lock);
04043 usleep(100000);
04044 }
04045
04046
04047 ci.chan = 0;
04048
04049
04050
04051 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04052 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04053 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04054 myrpt->txconf : myrpt->conf);
04055 ci.confmode = DAHDI_CONF_CONFANN;
04056
04057 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04058 {
04059 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04060 rpt_mutex_lock(&myrpt->lock);
04061 myrpt->active_telem = NULL;
04062 remque((struct qelem *)mytele);
04063 rpt_mutex_unlock(&myrpt->lock);
04064 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04065 ast_free(nodename);
04066 ast_free(ident);
04067 ast_free(mytele);
04068 ast_hangup(mychannel);
04069 pthread_exit(NULL);
04070 }
04071 ast_stopstream(mychannel);
04072 switch(mytele->mode)
04073 {
04074 case ID:
04075 case ID1:
04076
04077 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04078 res = telem_any(myrpt,mychannel, ident);
04079 imdone=1;
04080 break;
04081
04082 case TAILMSG:
04083 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04084 break;
04085
04086 case IDTALKOVER:
04087 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04088 if(p)
04089 res = telem_any(myrpt,mychannel, p);
04090 imdone=1;
04091 break;
04092
04093 case PROC:
04094
04095 wait_interval(myrpt, DLY_TELEM, mychannel);
04096 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04097 if(res < 0){
04098 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04099 }
04100 break;
04101 case TERM:
04102
04103 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04104 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04105 if(res < 0){
04106 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04107 }
04108 break;
04109 case COMPLETE:
04110
04111 wait_interval(myrpt, DLY_TELEM, mychannel);
04112 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04113 break;
04114 case MACRO_NOTFOUND:
04115
04116 wait_interval(myrpt, DLY_TELEM, mychannel);
04117 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04118 break;
04119 case MACRO_BUSY:
04120
04121 wait_interval(myrpt, DLY_TELEM, mychannel);
04122 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04123 break;
04124 case UNKEY:
04125 if(myrpt->patchnoct && myrpt->callmode){
04126 imdone = 1;
04127 break;
04128 }
04129
04130
04131
04132
04133
04134 x = get_wait_interval(myrpt, DLY_UNKEY);
04135 rpt_mutex_lock(&myrpt->lock);
04136 myrpt->unkeytocttimer = x;
04137 rpt_mutex_unlock(&myrpt->lock);
04138
04139
04140
04141
04142
04143 tlist = myrpt->tele.next;
04144 unkeys_queued = 0;
04145 if (tlist != &myrpt->tele)
04146 {
04147 rpt_mutex_lock(&myrpt->lock);
04148 while(tlist != &myrpt->tele){
04149 if (tlist->mode == UNKEY) unkeys_queued++;
04150 tlist = tlist->next;
04151 }
04152 rpt_mutex_unlock(&myrpt->lock);
04153 }
04154 if( unkeys_queued > 1){
04155 imdone = 1;
04156 break;
04157 }
04158
04159
04160
04161 while(myrpt->unkeytocttimer)
04162 {
04163 int ctint;
04164 if(myrpt->unkeytocttimer > 100)
04165 ctint = 100;
04166 else
04167 ctint = myrpt->unkeytocttimer;
04168 ast_safe_sleep(mychannel, ctint);
04169 rpt_mutex_lock(&myrpt->lock);
04170 if(myrpt->unkeytocttimer < ctint)
04171 myrpt->unkeytocttimer = 0;
04172 else
04173 myrpt->unkeytocttimer -= ctint;
04174 rpt_mutex_unlock(&myrpt->lock);
04175 }
04176
04177
04178
04179
04180
04181 if(myrpt->keyed){
04182 imdone = 1;
04183 break;
04184 }
04185
04186 rpt_mutex_lock(&myrpt->lock);
04187 myrpt->dailykerchunks++;
04188 myrpt->totalkerchunks++;
04189 rpt_mutex_unlock(&myrpt->lock);
04190
04191 haslink = 0;
04192 hastx = 0;
04193 hasremote = 0;
04194 l = myrpt->links.next;
04195 if (l != &myrpt->links)
04196 {
04197 rpt_mutex_lock(&myrpt->lock);
04198 while(l != &myrpt->links)
04199 {
04200 if (l->name[0] == '0')
04201 {
04202 l = l->next;
04203 continue;
04204 }
04205 haslink = 1;
04206 if (l->mode) {
04207 hastx++;
04208 if (l->isremote) hasremote++;
04209 }
04210 l = l->next;
04211 }
04212 rpt_mutex_unlock(&myrpt->lock);
04213 }
04214 if (haslink)
04215 {
04216
04217 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04218 if(res)
04219 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04220
04221
04222
04223 if (myrpt->cmdnode[0])
04224 {
04225 ast_safe_sleep(mychannel,200);
04226 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04227 if(res)
04228 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04229 ast_stopstream(mychannel);
04230 }
04231 }
04232 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04233 ct_copy = ast_strdup(ct);
04234 if(ct_copy)
04235 {
04236 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04237 ast_free(ct_copy);
04238 }
04239 else
04240 res = -1;
04241 if(res)
04242 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04243 }
04244 if (hasremote && (!myrpt->cmdnode[0]))
04245 {
04246
04247 ci.chan = 0;
04248 ci.confno = myrpt->conf;
04249 ci.confmode = DAHDI_CONF_CONFANN;
04250
04251 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04252 {
04253 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04254 rpt_mutex_lock(&myrpt->lock);
04255 myrpt->active_telem = NULL;
04256 remque((struct qelem *)mytele);
04257 rpt_mutex_unlock(&myrpt->lock);
04258 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04259 ast_free(nodename);
04260 ast_free(ident);
04261 ast_free(mytele);
04262 ast_hangup(mychannel);
04263 pthread_exit(NULL);
04264 }
04265 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04266 ast_safe_sleep(mychannel,200);
04267 ct_copy = ast_strdup(ct);
04268 if(ct_copy)
04269 {
04270 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04271 ast_free(ct_copy);
04272 }
04273 else
04274 res = -1;
04275
04276 if(res)
04277 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04278 }
04279 }
04280 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04281 if (myrpt->lastunit)
04282 {
04283 char mystr[10];
04284
04285 ast_safe_sleep(mychannel,200);
04286
04287 ci.chan = 0;
04288 ci.confno = myrpt->txconf;
04289 ci.confmode = DAHDI_CONF_CONFANN;
04290
04291 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04292 {
04293 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04294 rpt_mutex_lock(&myrpt->lock);
04295 myrpt->active_telem = NULL;
04296 remque((struct qelem *)mytele);
04297 rpt_mutex_unlock(&myrpt->lock);
04298 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04299 ast_free(nodename);
04300 ast_free(ident);
04301 ast_free(mytele);
04302 ast_hangup(mychannel);
04303 pthread_exit(NULL);
04304 }
04305 sprintf(mystr,"%04x",myrpt->lastunit);
04306 myrpt->lastunit = 0;
04307 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04308 break;
04309 }
04310 #endif
04311 imdone = 1;
04312 break;
04313 case LINKUNKEY:
04314 if(myrpt->patchnoct && myrpt->callmode){
04315 imdone = 1;
04316 break;
04317 }
04318
04319
04320
04321
04322
04323 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04324 mytele->mylink.linkunkeytocttimer = x;
04325
04326
04327
04328
04329
04330 tlist = myrpt->tele.next;
04331 unkeys_queued = 0;
04332 if (tlist != &myrpt->tele)
04333 {
04334 rpt_mutex_lock(&myrpt->lock);
04335 while(tlist != &myrpt->tele){
04336 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04337 tlist = tlist->next;
04338 }
04339 rpt_mutex_unlock(&myrpt->lock);
04340 }
04341 if( unkeys_queued > 1){
04342 imdone = 1;
04343 break;
04344 }
04345
04346
04347
04348 while(mytele->mylink.linkunkeytocttimer)
04349 {
04350 int ctint;
04351 if(mytele->mylink.linkunkeytocttimer > 100)
04352 ctint = 100;
04353 else
04354 ctint = mytele->mylink.linkunkeytocttimer;
04355 ast_safe_sleep(mychannel, ctint);
04356 rpt_mutex_lock(&myrpt->lock);
04357 if(mytele->mylink.linkunkeytocttimer < ctint)
04358 mytele->mylink.linkunkeytocttimer = 0;
04359 else
04360 mytele->mylink.linkunkeytocttimer -= ctint;
04361 rpt_mutex_unlock(&myrpt->lock);
04362 }
04363
04364 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04365 ct_copy = ast_strdup(ct);
04366 if(ct_copy){
04367 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04368 ast_free(ct_copy);
04369 }
04370 else
04371 res = -1;
04372 if(res)
04373 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04374 }
04375 imdone = 1;
04376 break;
04377 case REMDISC:
04378
04379 wait_interval(myrpt, DLY_TELEM, mychannel);
04380 l = myrpt->links.next;
04381 haslink = 0;
04382
04383 if (l != &myrpt->links)
04384 {
04385 rpt_mutex_lock(&myrpt->lock);
04386 while(l != &myrpt->links)
04387 {
04388 if (l->name[0] == '0')
04389 {
04390 l = l->next;
04391 continue;
04392 }
04393 if (!strcmp(l->name,mytele->mylink.name))
04394 {
04395 haslink = 1;
04396 break;
04397 }
04398 l = l->next;
04399 }
04400 rpt_mutex_unlock(&myrpt->lock);
04401 }
04402 if (haslink)
04403 {
04404 imdone = 1;
04405 break;
04406 }
04407 res = saynode(myrpt,mychannel,mytele->mylink.name);
04408 if (!res)
04409 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04410 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04411 break;
04412 case REMALREADY:
04413
04414 wait_interval(myrpt, DLY_TELEM, mychannel);
04415 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04416 break;
04417 case REMNOTFOUND:
04418
04419 wait_interval(myrpt, DLY_TELEM, mychannel);
04420 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04421 break;
04422 case REMGO:
04423
04424 wait_interval(myrpt, DLY_TELEM, mychannel);
04425 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04426 break;
04427 case CONNECTED:
04428
04429 wait_interval(myrpt, DLY_TELEM, mychannel);
04430 res = saynode(myrpt,mychannel,mytele->mylink.name);
04431 if (!res)
04432 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04433 if (!res)
04434 res = ast_waitstream(mychannel, "");
04435 else
04436 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04437 ast_stopstream(mychannel);
04438 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04439 if (!res)
04440 res = ast_waitstream(mychannel, "");
04441 else
04442 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04443 ast_stopstream(mychannel);
04444 res = saynode(myrpt,mychannel,myrpt->name);
04445 imdone = 1;
04446 break;
04447 case CONNFAIL:
04448 res = saynode(myrpt,mychannel,mytele->mylink.name);
04449 if (!res)
04450 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04451 break;
04452 case MEMNOTFOUND:
04453
04454 wait_interval(myrpt, DLY_TELEM, mychannel);
04455 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04456 break;
04457 case PLAYBACK:
04458
04459 wait_interval(myrpt, DLY_TELEM, mychannel);
04460 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04461 break;
04462 case TOPKEY:
04463
04464 wait_interval(myrpt, DLY_TELEM, mychannel);
04465 for(i = 0; i < TOPKEYN; i++)
04466 {
04467 if (!myrpt->topkey[i].node[0]) continue;
04468 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04469 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04470 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04471 "rpt/keyedfor" : "rpt/unkeyedfor");
04472 if (!res) res = saynum(mychannel,
04473 myrpt->topkey[i].timesince);
04474 if (!res) res = sayfile(mychannel,"rpt/seconds");
04475 if (!myrpt->topkeylong) break;
04476 }
04477 imdone = 1;
04478 break;
04479 case SETREMOTE:
04480 ast_mutex_lock(&myrpt->remlock);
04481 res = 0;
04482 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04483 {
04484 res = set_ft897(myrpt);
04485 }
04486 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04487 {
04488 res = set_tm271(myrpt);
04489 }
04490 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04491 {
04492 res = set_ic706(myrpt);
04493 }
04494 #ifdef HAVE_IOPERM
04495 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04496 {
04497 if (ioperm(myrpt->p.iobase,1,1) == -1)
04498 {
04499 rpt_mutex_unlock(&myrpt->lock);
04500 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04501 res = -1;
04502 }
04503 else res = setrbi(myrpt);
04504 }
04505 #endif
04506 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04507 {
04508 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04509 res = setkenwood(myrpt);
04510 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04511 if (ast_safe_sleep(mychannel,200) == -1)
04512 {
04513 ast_mutex_unlock(&myrpt->remlock);
04514 res = -1;
04515 break;
04516 }
04517 if (myrpt->iofd < 0)
04518 {
04519 i = DAHDI_FLUSH_EVENT;
04520 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04521 {
04522 ast_mutex_unlock(&myrpt->remlock);
04523 ast_log(LOG_ERROR,"Cant flush events");
04524 res = -1;
04525 break;
04526 }
04527 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04528 {
04529 ast_mutex_unlock(&myrpt->remlock);
04530 ast_log(LOG_ERROR,"Cant get params");
04531 res = -1;
04532 break;
04533 }
04534 myrpt->remoterx =
04535 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04536 }
04537 }
04538
04539 ast_mutex_unlock(&myrpt->remlock);
04540 if (!res)
04541 {
04542 imdone = 1;
04543 break;
04544 }
04545
04546 case INVFREQ:
04547
04548 wait_interval(myrpt, DLY_TELEM, mychannel);
04549 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04550 break;
04551 case REMMODE:
04552 cp = 0;
04553 wait_interval(myrpt, DLY_TELEM, mychannel);
04554 switch(myrpt->remmode)
04555 {
04556 case REM_MODE_FM:
04557 saycharstr(mychannel,"FM");
04558 break;
04559 case REM_MODE_USB:
04560 saycharstr(mychannel,"USB");
04561 break;
04562 case REM_MODE_LSB:
04563 saycharstr(mychannel,"LSB");
04564 break;
04565 case REM_MODE_AM:
04566 saycharstr(mychannel,"AM");
04567 break;
04568 }
04569 wait_interval(myrpt, DLY_COMP, mychannel);
04570 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04571 break;
04572 case LOGINREQ:
04573 wait_interval(myrpt, DLY_TELEM, mychannel);
04574 sayfile(mychannel,"rpt/login");
04575 saycharstr(mychannel,myrpt->name);
04576 break;
04577 case REMLOGIN:
04578 wait_interval(myrpt, DLY_TELEM, mychannel);
04579 saycharstr(mychannel,myrpt->loginuser);
04580 saynode(myrpt,mychannel,myrpt->name);
04581 wait_interval(myrpt, DLY_COMP, mychannel);
04582 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04583 break;
04584 case REMXXX:
04585 wait_interval(myrpt, DLY_TELEM, mychannel);
04586 res = 0;
04587 switch(mytele->submode)
04588 {
04589 case 100:
04590 sayfile(mychannel, "rpt/rxpl");
04591 sayfile(mychannel, "rpt/off");
04592 break;
04593 case 101:
04594 sayfile(mychannel, "rpt/rxpl");
04595 sayfile(mychannel, "rpt/on");
04596 break;
04597 case 102:
04598 sayfile(mychannel, "rpt/txpl");
04599 sayfile(mychannel, "rpt/off");
04600 break;
04601 case 103:
04602 sayfile(mychannel, "rpt/txpl");
04603 sayfile(mychannel, "rpt/on");
04604 break;
04605 case 104:
04606 sayfile(mychannel, "rpt/lopwr");
04607 break;
04608 case 105:
04609 sayfile(mychannel, "rpt/medpwr");
04610 break;
04611 case 106:
04612 sayfile(mychannel, "rpt/hipwr");
04613 break;
04614 case 113:
04615 sayfile(mychannel,"rpt/down");
04616 sayfile(mychannel, "rpt/slow");
04617 break;
04618 case 114:
04619 sayfile(mychannel,"rpt/down");
04620 sayfile(mychannel, "rpt/quick");
04621 break;
04622 case 115:
04623 sayfile(mychannel,"rpt/down");
04624 sayfile(mychannel, "rpt/fast");
04625 break;
04626 case 116:
04627 sayfile(mychannel,"rpt/up");
04628 sayfile(mychannel, "rpt/slow");
04629 break;
04630 case 117:
04631 sayfile(mychannel,"rpt/up");
04632 sayfile(mychannel, "rpt/quick");
04633 break;
04634 case 118:
04635 sayfile(mychannel,"rpt/up");
04636 sayfile(mychannel, "rpt/fast");
04637 break;
04638 default:
04639 res = -1;
04640 }
04641 wait_interval(myrpt, DLY_COMP, mychannel);
04642 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04643 break;
04644 case SCAN:
04645 ast_mutex_lock(&myrpt->remlock);
04646 if (myrpt->hfscanstop)
04647 {
04648 myrpt->hfscanstatus = 0;
04649 myrpt->hfscanmode = 0;
04650 myrpt->hfscanstop = 0;
04651 mytele->mode = SCANSTAT;
04652 ast_mutex_unlock(&myrpt->remlock);
04653 if (ast_safe_sleep(mychannel,1000) == -1) break;
04654 sayfile(mychannel, "rpt/stop");
04655 imdone = 1;
04656 break;
04657 }
04658 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04659 i = myrpt->hfscanstatus;
04660 myrpt->hfscanstatus = 0;
04661 if (i) mytele->mode = SCANSTAT;
04662 ast_mutex_unlock(&myrpt->remlock);
04663 if (i < 0) sayfile(mychannel, "rpt/stop");
04664 else if (i > 0) saynum(mychannel,i);
04665 imdone = 1;
04666 break;
04667 case TUNE:
04668 ast_mutex_lock(&myrpt->remlock);
04669 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04670 {
04671 set_mode_ic706(myrpt, REM_MODE_AM);
04672 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04673 ast_safe_sleep(mychannel,500);
04674 set_mode_ic706(myrpt, myrpt->remmode);
04675 myrpt->tunerequest = 0;
04676 ast_mutex_unlock(&myrpt->remlock);
04677 imdone = 1;
04678 break;
04679 }
04680 set_mode_ft897(myrpt, REM_MODE_AM);
04681 simple_command_ft897(myrpt, 8);
04682 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04683 simple_command_ft897(myrpt, 0x88);
04684 ast_safe_sleep(mychannel,500);
04685 set_mode_ft897(myrpt, myrpt->remmode);
04686 myrpt->tunerequest = 0;
04687 ast_mutex_unlock(&myrpt->remlock);
04688 imdone = 1;
04689 break;
04690 case REMSHORTSTATUS:
04691 case REMLONGSTATUS:
04692 wait_interval(myrpt, DLY_TELEM, mychannel);
04693 res = saynode(myrpt,mychannel,myrpt->name);
04694 if(!res)
04695 res = sayfile(mychannel,"rpt/frequency");
04696 if(!res)
04697 res = split_freq(mhz, decimals, myrpt->freq);
04698 if (!multimode_capable(myrpt)) decimals[3] = 0;
04699 if(!res){
04700 m = atoi(mhz);
04701 if(m < 100)
04702 res = saynum(mychannel, m);
04703 else
04704 res = saycharstr(mychannel, mhz);
04705 }
04706 if(!res)
04707 res = sayfile(mychannel, "letters/dot");
04708 if(!res)
04709 res = saycharstr(mychannel, decimals);
04710
04711 if(res) break;
04712 if(myrpt->remmode == REM_MODE_FM){
04713 switch(myrpt->offset){
04714
04715 case REM_MINUS:
04716 res = sayfile(mychannel,"rpt/minus");
04717 break;
04718
04719 case REM_SIMPLEX:
04720 res = sayfile(mychannel,"rpt/simplex");
04721 break;
04722
04723 case REM_PLUS:
04724 res = sayfile(mychannel,"rpt/plus");
04725 break;
04726
04727 default:
04728 break;
04729 }
04730 }
04731 else{
04732 switch(myrpt->remmode){
04733
04734 case REM_MODE_USB:
04735 res = saycharstr(mychannel, "USB");
04736 break;
04737
04738 case REM_MODE_LSB:
04739 res = saycharstr(mychannel, "LSB");
04740 break;
04741
04742 case REM_MODE_AM:
04743 res = saycharstr(mychannel, "AM");
04744 break;
04745
04746
04747 default:
04748 break;
04749 }
04750 }
04751
04752 if (res == -1) break;
04753
04754 if(mytele->mode == REMSHORTSTATUS){
04755 wait_interval(myrpt, DLY_COMP, mychannel);
04756 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04757 break;
04758 }
04759
04760 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04761 {
04762 switch(myrpt->powerlevel){
04763
04764 case REM_LOWPWR:
04765 res = sayfile(mychannel,"rpt/lopwr") ;
04766 break;
04767 case REM_MEDPWR:
04768 res = sayfile(mychannel,"rpt/medpwr");
04769 break;
04770 case REM_HIPWR:
04771 res = sayfile(mychannel,"rpt/hipwr");
04772 break;
04773 }
04774 }
04775
04776 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04777 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04778 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04779 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04780 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04781 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04782 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04783 (sayfile(mychannel,"rpt/frequency") == -1) ||
04784 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04785 if(myrpt->remmode == REM_MODE_FM){
04786 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04787 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04788 (sayfile(mychannel,"rpt/txpl") == -1) ||
04789 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04790 {
04791 break;
04792 }
04793 }
04794 wait_interval(myrpt, DLY_COMP, mychannel);
04795 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04796 break;
04797 case STATUS:
04798
04799 wait_interval(myrpt, DLY_TELEM, mychannel);
04800 hastx = 0;
04801 linkbase.next = &linkbase;
04802 linkbase.prev = &linkbase;
04803 rpt_mutex_lock(&myrpt->lock);
04804
04805 l = myrpt->links.next;
04806 while(l != &myrpt->links)
04807 {
04808 if (l->name[0] == '0')
04809 {
04810 l = l->next;
04811 continue;
04812 }
04813 l1 = ast_malloc(sizeof(struct rpt_link));
04814 if (!l1)
04815 {
04816 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04817 remque((struct qelem *)mytele);
04818 myrpt->active_telem = NULL;
04819 rpt_mutex_unlock(&myrpt->lock);
04820 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04821 ast_free(nodename);
04822 ast_free(ident);
04823 ast_free(mytele);
04824 ast_hangup(mychannel);
04825 pthread_exit(NULL);
04826 }
04827 memcpy(l1,l,sizeof(struct rpt_link));
04828 l1->next = l1->prev = NULL;
04829 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04830 l = l->next;
04831 }
04832 rpt_mutex_unlock(&myrpt->lock);
04833 res = saynode(myrpt,mychannel,myrpt->name);
04834 if (myrpt->callmode)
04835 {
04836 hastx = 1;
04837 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04838 if (!res)
04839 res = ast_waitstream(mychannel, "");
04840 else
04841 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04842 ast_stopstream(mychannel);
04843 }
04844 l = linkbase.next;
04845 while(l != &linkbase)
04846 {
04847 char *s;
04848
04849 hastx = 1;
04850 res = saynode(myrpt,mychannel,l->name);
04851 s = "rpt/tranceive";
04852 if (!l->mode) s = "rpt/monitor";
04853 if (!l->thisconnected) s = "rpt/connecting";
04854 res = ast_streamfile(mychannel, s, mychannel->language);
04855 if (!res)
04856 res = ast_waitstream(mychannel, "");
04857 else
04858 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04859 ast_stopstream(mychannel);
04860 l = l->next;
04861 }
04862 if (!hastx)
04863 {
04864 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04865 if (!res)
04866 res = ast_waitstream(mychannel, "");
04867 else
04868 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04869 ast_stopstream(mychannel);
04870 }
04871
04872 l = linkbase.next;
04873 while(l != &linkbase)
04874 {
04875 l1 = l;
04876 l = l->next;
04877 remque((struct qelem *)l1);
04878 ast_free(l1);
04879 }
04880 imdone = 1;
04881 break;
04882 case FULLSTATUS:
04883 rpt_mutex_lock(&myrpt->lock);
04884
04885 __mklinklist(myrpt,NULL,lbuf);
04886 rpt_mutex_unlock(&myrpt->lock);
04887
04888 ns = finddelim(lbuf,strs,MAXLINKLIST);
04889
04890 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04891
04892 wait_interval(myrpt, DLY_TELEM, mychannel);
04893 hastx = 0;
04894 res = saynode(myrpt,mychannel,myrpt->name);
04895 if (myrpt->callmode)
04896 {
04897 hastx = 1;
04898 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04899 if (!res)
04900 res = ast_waitstream(mychannel, "");
04901 else
04902 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04903 ast_stopstream(mychannel);
04904 }
04905
04906 for(i = 0; i < ns; i++)
04907 {
04908 char *s,mode = 'T';
04909
04910
04911 if ((*strs[i] < '0') || (*strs[i] > '9'))
04912 {
04913 mode = *strs[i];
04914 strs[i]++;
04915 }
04916
04917 hastx = 1;
04918 res = saynode(myrpt,mychannel,strs[i]);
04919 s = "rpt/tranceive";
04920 if (mode == 'R') s = "rpt/monitor";
04921 if (mode == 'C') s = "rpt/connecting";
04922 res = ast_streamfile(mychannel, s, 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 if (!hastx)
04930 {
04931 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04932 if (!res)
04933 res = ast_waitstream(mychannel, "");
04934 else
04935 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04936 ast_stopstream(mychannel);
04937 }
04938 imdone = 1;
04939 break;
04940
04941 case LASTNODEKEY:
04942 rpt_mutex_lock(&myrpt->lock);
04943 if(myrpt->lastnodewhichkeyedusup){
04944 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04945 if(!p){
04946 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04947 imdone = 1;
04948 break;
04949 }
04950 }
04951 else
04952 p = NULL;
04953 rpt_mutex_unlock(&myrpt->lock);
04954 if(!p){
04955 imdone = 1;
04956 break;
04957 }
04958 wait_interval(myrpt, DLY_TELEM, mychannel);
04959 res = saynode(myrpt,mychannel,p);
04960 ast_free(p);
04961 imdone = 1;
04962 break;
04963
04964 case UNAUTHTX:
04965 wait_interval(myrpt, DLY_TELEM, mychannel);
04966 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04967 if (!res)
04968 res = ast_waitstream(mychannel, "");
04969 else
04970 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04971 ast_stopstream(mychannel);
04972 imdone = 1;
04973 break;
04974
04975 case PARROT:
04976
04977 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04978 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04979 {
04980 imdone = 1;
04981 myrpt->parrotstate = 0;
04982 break;
04983 }
04984 wait_interval(myrpt, DLY_PARROT, mychannel);
04985 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04986 res = ast_streamfile(mychannel, mystr, mychannel->language);
04987 if (!res)
04988 res = ast_waitstream(mychannel, "");
04989 else
04990 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04991 ast_stopstream(mychannel);
04992 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04993 strcat(mystr,".wav");
04994 unlink(mystr);
04995 imdone = 1;
04996 myrpt->parrotstate = 0;
04997 break;
04998
04999 case TIMEOUT:
05000 res = saynode(myrpt,mychannel,myrpt->name);
05001 if (!res)
05002 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
05003 break;
05004
05005 case TIMEOUT_WARNING:
05006 time(&t);
05007 res = saynode(myrpt,mychannel,myrpt->name);
05008 if (!res)
05009 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05010 if (!res)
05011 res = ast_waitstream(mychannel, "");
05012 else
05013 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05014 ast_stopstream(mychannel);
05015 if(!res)
05016 ast_say_number(mychannel, myrpt->p.remotetimeout -
05017 (t - myrpt->last_activity_time),
05018 "", mychannel->language, (char *) NULL);
05019 if (!res)
05020 res = ast_waitstream(mychannel, "");
05021 ast_stopstream(mychannel);
05022 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05023 break;
05024
05025 case ACT_TIMEOUT_WARNING:
05026 time(&t);
05027 res = saynode(myrpt,mychannel,myrpt->name);
05028 if (!res)
05029 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05030 if (!res)
05031 res = ast_waitstream(mychannel, "");
05032 else
05033 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05034 ast_stopstream(mychannel);
05035 if(!res)
05036 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05037 (t - myrpt->last_activity_time),
05038 "", mychannel->language, (char *) NULL);
05039 if (!res)
05040 res = ast_waitstream(mychannel, "");
05041 ast_stopstream(mychannel);
05042 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05043 break;
05044
05045 case STATS_TIME:
05046 case STATS_TIME_LOCAL:
05047 wait_interval(myrpt, DLY_TELEM, mychannel);
05048 t = time(NULL);
05049 rpt_localtime(&t, &localtm);
05050
05051 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05052 p = "rpt/goodmorning";
05053 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05054 p = "rpt/goodafternoon";
05055 else
05056 p = "rpt/goodevening";
05057 if (sayfile(mychannel,p) == -1)
05058 {
05059 imdone = 1;
05060 break;
05061 }
05062
05063 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05064 {
05065 imdone = 1;
05066 break;
05067 }
05068
05069 res = ast_say_time(mychannel, t, "", mychannel->language);
05070 if (!res)
05071 res = ast_waitstream(mychannel, "");
05072 ast_stopstream(mychannel);
05073 imdone = 1;
05074 break;
05075 case STATS_VERSION:
05076 p = strstr(tdesc, "version");
05077 if(!p)
05078 break;
05079 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05080 break;
05081 wait_interval(myrpt, DLY_TELEM, mychannel);
05082
05083 if (sayfile(mychannel,"rpt/version") == -1)
05084 {
05085 imdone = 1;
05086 break;
05087 }
05088 if(!res)
05089 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05090 if (!res)
05091 res = ast_waitstream(mychannel, "");
05092 ast_stopstream(mychannel);
05093 if (saycharstr(mychannel,".") == -1)
05094 {
05095 imdone = 1;
05096 break;
05097 }
05098 if(!res)
05099 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05100 if (!res){
05101 res = ast_waitstream(mychannel, "");
05102 ast_stopstream(mychannel);
05103 }
05104 else
05105 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05106 imdone = 1;
05107 break;
05108 case ARB_ALPHA:
05109 wait_interval(myrpt, DLY_TELEM, mychannel);
05110 if(mytele->param)
05111 saycharstr(mychannel, mytele->param);
05112 imdone = 1;
05113 break;
05114 case REV_PATCH:
05115 wait_interval(myrpt, DLY_TELEM, mychannel);
05116 if(mytele->param) {
05117
05118
05119 char *tpl_working, *tpl_current;
05120 char *tmp[100], *myparm;
05121 int looptemp=0,idx=0, dres = 0;
05122
05123
05124 tpl_working = ast_strdup(mytele->param);
05125 myparm = strsep(&tpl_working,",");
05126 tpl_current=strsep(&tpl_working, ":");
05127
05128 while(tpl_current && looptemp < sizeof(tmp)) {
05129 tmp[looptemp]=tpl_current;
05130 looptemp++;
05131 tpl_current=strsep(&tpl_working,":");
05132 }
05133
05134 for(idx=0; idx<looptemp; idx++) {
05135 if(!strcmp(tmp[idx], "PARKED")) {
05136 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05137 } else if(!strcmp(tmp[idx], "NODE")) {
05138 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05139 } else {
05140 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05141 if(!dres) {
05142 dres = ast_waitstream(mychannel, "");
05143 } else {
05144 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05145 dres = 0;
05146 }
05147 }
05148 }
05149 ast_free(tpl_working);
05150 }
05151 imdone = 1;
05152 break;
05153 case TEST_TONE:
05154 imdone = 1;
05155 if (myrpt->stopgen) break;
05156 myrpt->stopgen = -1;
05157 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05158 {
05159 myrpt->stopgen = 0;
05160 break;
05161 }
05162 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05163 if (ast_safe_sleep(mychannel,1)) break;
05164 imdone = 1;
05165 }
05166 myrpt->stopgen = 0;
05167 break;
05168 default:
05169 break;
05170 }
05171 if (!imdone)
05172 {
05173 if (!res)
05174 res = ast_waitstream(mychannel, "");
05175 else {
05176 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05177 res = 0;
05178 }
05179 }
05180 ast_stopstream(mychannel);
05181 rpt_mutex_lock(&myrpt->lock);
05182 if (mytele->mode == TAILMSG)
05183 {
05184 if (!res)
05185 {
05186 myrpt->tailmessagen++;
05187 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05188 }
05189 else
05190 {
05191 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05192 }
05193 }
05194 remque((struct qelem *)mytele);
05195 myrpt->active_telem = NULL;
05196 rpt_mutex_unlock(&myrpt->lock);
05197 ast_free(nodename);
05198 ast_free(ident);
05199 ast_free(mytele);
05200 ast_hangup(mychannel);
05201 #ifdef APP_RPT_LOCK_DEBUG
05202 {
05203 struct lockthread *t;
05204
05205 sleep(5);
05206 ast_mutex_lock(&locklock);
05207 t = get_lockthread(pthread_self());
05208 if (t) memset(t,0,sizeof(struct lockthread));
05209 ast_mutex_unlock(&locklock);
05210 }
05211 #endif
05212 pthread_exit(NULL);
05213 }
05214
05215 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05216 {
05217 struct rpt_tele *tele;
05218 struct rpt_link *mylink = NULL;
05219 int res;
05220 pthread_attr_t attr;
05221 char *v1, *v2;
05222
05223 if(debug > 6)
05224 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05225
05226 switch(mode)
05227 {
05228 case UNKEY:
05229
05230
05231 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05232 "unlinkedct");
05233 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05234 "remotect");
05235 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05236 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05237 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05238 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05239 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05240 break;
05241 case LINKUNKEY:
05242 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05243 return;
05244 break;
05245 default:
05246 break;
05247 }
05248 tele = ast_malloc(sizeof(struct rpt_tele));
05249 if (!tele)
05250 {
05251 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05252 pthread_exit(NULL);
05253 return;
05254 }
05255
05256 memset((char *)tele,0,sizeof(struct rpt_tele));
05257 tele->rpt = myrpt;
05258 tele->mode = mode;
05259 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05260 else mylink = (struct rpt_link *) data;
05261 rpt_mutex_lock(&myrpt->lock);
05262 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05263 (mode == LINKUNKEY)){
05264 memset(&tele->mylink,0,sizeof(struct rpt_link));
05265 if (mylink){
05266 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05267 }
05268 }
05269 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05270 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05271 tele->param[TELEPARAMSIZE - 1] = 0;
05272 }
05273 if (mode == REMXXX) tele->submode = (intptr_t) data;
05274 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05275 rpt_mutex_unlock(&myrpt->lock);
05276 pthread_attr_init(&attr);
05277 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05278 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05279 if(res < 0){
05280 rpt_mutex_lock(&myrpt->lock);
05281 remque((struct qlem *) tele);
05282 rpt_mutex_unlock(&myrpt->lock);
05283 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05284 }
05285 return;
05286 }
05287
05288 static void *rpt_call(void *this)
05289 {
05290 struct dahdi_confinfo ci;
05291 struct rpt *myrpt = (struct rpt *)this;
05292 int res;
05293 int stopped,congstarted,dialtimer,lastcidx,aborted;
05294 struct ast_channel *mychannel,*genchannel;
05295
05296 myrpt->mydtmf = 0;
05297
05298 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05299 if (!mychannel)
05300 {
05301 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05302 pthread_exit(NULL);
05303 }
05304 #ifdef AST_CDR_FLAG_POST_DISABLED
05305 if (mychannel->cdr)
05306 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05307 #endif
05308 ci.chan = 0;
05309 ci.confno = myrpt->conf;
05310 #if 0
05311 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05312 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05313 #endif
05314 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05315
05316 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05317 {
05318 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05319 ast_hangup(mychannel);
05320 myrpt->callmode = 0;
05321 pthread_exit(NULL);
05322 }
05323
05324 genchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05325 if (!genchannel)
05326 {
05327 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05328 ast_hangup(mychannel);
05329 pthread_exit(NULL);
05330 }
05331 #ifdef AST_CDR_FLAG_POST_DISABLED
05332 if (genchannel->cdr)
05333 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05334 #endif
05335 ci.chan = 0;
05336 ci.confno = myrpt->conf;
05337 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05338 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05339
05340 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05341 {
05342 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05343 ast_hangup(mychannel);
05344 ast_hangup(genchannel);
05345 myrpt->callmode = 0;
05346 pthread_exit(NULL);
05347 }
05348 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05349 {
05350 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05351 ast_hangup(mychannel);
05352 ast_hangup(genchannel);
05353 myrpt->callmode = 0;
05354 pthread_exit(NULL);
05355 }
05356 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05357 {
05358 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05359 ast_hangup(mychannel);
05360 ast_hangup(genchannel);
05361 myrpt->callmode = 0;
05362 pthread_exit(NULL);
05363 }
05364
05365 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05366 {
05367 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05368 ast_hangup(mychannel);
05369 ast_hangup(genchannel);
05370 myrpt->callmode = 0;
05371 pthread_exit(NULL);
05372 }
05373 stopped = 0;
05374 congstarted = 0;
05375 dialtimer = 0;
05376 lastcidx = 0;
05377 myrpt->calldigittimer = 0;
05378 aborted = 0;
05379
05380 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05381 {
05382 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05383 dialtimer = 0;
05384 lastcidx = myrpt->cidx;
05385 }
05386
05387 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05388 if(debug)
05389 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05390 rpt_mutex_lock(&myrpt->lock);
05391 aborted = 1;
05392 myrpt->callmode = 0;
05393 rpt_mutex_unlock(&myrpt->lock);
05394 break;
05395 }
05396
05397 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05398 {
05399 stopped = 1;
05400
05401 tone_zone_play_tone(genchannel->fds[0],-1);
05402 }
05403 if (myrpt->callmode == 1)
05404 {
05405 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05406 {
05407 myrpt->callmode = 2;
05408 break;
05409 }
05410
05411 if (myrpt->calldigittimer)
05412 myrpt->calldigittimer += MSWAIT;
05413 }
05414 if (myrpt->callmode == 4)
05415 {
05416 if(!congstarted){
05417 congstarted = 1;
05418
05419 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05420 }
05421 }
05422 res = ast_safe_sleep(mychannel, MSWAIT);
05423 if (res < 0)
05424 {
05425 if(debug)
05426 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05427 ast_hangup(mychannel);
05428 ast_hangup(genchannel);
05429 rpt_mutex_lock(&myrpt->lock);
05430 myrpt->callmode = 0;
05431 rpt_mutex_unlock(&myrpt->lock);
05432 pthread_exit(NULL);
05433 }
05434 dialtimer += MSWAIT;
05435 }
05436
05437 tone_zone_play_tone(genchannel->fds[0],-1);
05438
05439 if (!myrpt->callmode)
05440 {
05441 if(debug)
05442 ast_log(LOG_NOTICE, "callmode==0\n");
05443 ast_hangup(mychannel);
05444 ast_hangup(genchannel);
05445 rpt_mutex_lock(&myrpt->lock);
05446 myrpt->callmode = 0;
05447 myrpt->macropatch=0;
05448 channel_revert(myrpt);
05449 rpt_mutex_unlock(&myrpt->lock);
05450 if((!myrpt->patchquiet) && aborted)
05451 rpt_telemetry(myrpt, TERM, NULL);
05452 pthread_exit(NULL);
05453 }
05454
05455 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05456 char *name, *loc, *instr;
05457 instr = ast_strdup(myrpt->p.ourcallerid);
05458 if(instr){
05459 ast_callerid_parse(instr, &name, &loc);
05460 if(loc){
05461 mychannel->caller.id.number.valid = 1;
05462 ast_free(mychannel->caller.id.number.str);
05463 mychannel->caller.id.number.str = ast_strdup(loc);
05464 }
05465 if(name){
05466 mychannel->caller.id.name.valid = 1;
05467 ast_free(mychannel->caller.id.name.str);
05468 mychannel->caller.id.name.str = ast_strdup(name);
05469 }
05470 ast_free(instr);
05471 }
05472 }
05473
05474 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05475 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05476
05477 if (myrpt->p.acctcode)
05478 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05479 mychannel->priority = 1;
05480 ast_channel_undefer_dtmf(mychannel);
05481 if (ast_pbx_start(mychannel) < 0)
05482 {
05483 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05484 ast_hangup(mychannel);
05485 ast_hangup(genchannel);
05486 rpt_mutex_lock(&myrpt->lock);
05487 myrpt->callmode = 0;
05488 rpt_mutex_unlock(&myrpt->lock);
05489 pthread_exit(NULL);
05490 }
05491 usleep(10000);
05492 rpt_mutex_lock(&myrpt->lock);
05493 myrpt->callmode = 3;
05494
05495 ci.chan = 0;
05496 ci.confno = myrpt->conf;
05497 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05498 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05499
05500 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05501 {
05502 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05503 ast_hangup(mychannel);
05504 ast_hangup(genchannel);
05505 myrpt->callmode = 0;
05506 pthread_exit(NULL);
05507 }
05508
05509 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05510 {
05511 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05512 ast_hangup(mychannel);
05513 myrpt->callmode = 0;
05514 pthread_exit(NULL);
05515 }
05516 ci.chan = 0;
05517 ci.confno = res;
05518 ci.confmode = DAHDI_CONF_MONITOR;
05519
05520 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05521 {
05522 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05523 ast_hangup(mychannel);
05524 myrpt->callmode = 0;
05525 pthread_exit(NULL);
05526 }
05527 while(myrpt->callmode)
05528 {
05529 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05530 {
05531
05532 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05533 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05534 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05535 myrpt->callmode = 0;
05536 myrpt->macropatch=0;
05537 if(!myrpt->patchquiet){
05538 rpt_mutex_unlock(&myrpt->lock);
05539 rpt_telemetry(myrpt, TERM, NULL);
05540 rpt_mutex_lock(&myrpt->lock);
05541 }
05542 }
05543 else{
05544 myrpt->callmode = 4;
05545 rpt_mutex_unlock(&myrpt->lock);
05546
05547 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05548 rpt_mutex_lock(&myrpt->lock);
05549 }
05550 }
05551 if (myrpt->mydtmf)
05552 {
05553 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05554 wf.subclass.integer = myrpt->mydtmf;
05555 rpt_mutex_unlock(&myrpt->lock);
05556 ast_queue_frame(mychannel,&wf);
05557 #ifdef NEW_ASTERISK
05558 ast_senddigit(genchannel,myrpt->mydtmf,0);
05559 #else
05560 ast_senddigit(genchannel,myrpt->mydtmf);
05561 #endif
05562 rpt_mutex_lock(&myrpt->lock);
05563 myrpt->mydtmf = 0;
05564 }
05565 rpt_mutex_unlock(&myrpt->lock);
05566 usleep(MSWAIT * 1000);
05567 rpt_mutex_lock(&myrpt->lock);
05568 }
05569 if(debug)
05570 ast_log(LOG_NOTICE, "exit channel loop\n");
05571 rpt_mutex_unlock(&myrpt->lock);
05572 tone_zone_play_tone(genchannel->fds[0],-1);
05573 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05574 ast_hangup(genchannel);
05575 rpt_mutex_lock(&myrpt->lock);
05576 myrpt->callmode = 0;
05577 myrpt->macropatch=0;
05578 channel_revert(myrpt);
05579 rpt_mutex_unlock(&myrpt->lock);
05580
05581 ci.chan = 0;
05582 ci.confno = myrpt->conf;
05583 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05584 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05585
05586 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05587 {
05588 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05589 }
05590 pthread_exit(NULL);
05591 }
05592
05593 static void send_link_dtmf(struct rpt *myrpt,char c)
05594 {
05595 char str[300];
05596 struct ast_frame wf;
05597 struct rpt_link *l;
05598
05599 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05600 wf.frametype = AST_FRAME_TEXT;
05601 wf.subclass.integer = 0;
05602 wf.offset = 0;
05603 wf.mallocd = 0;
05604 wf.datalen = strlen(str) + 1;
05605 wf.samples = 0;
05606 l = myrpt->links.next;
05607
05608 while(l != &myrpt->links)
05609 {
05610 if (l->name[0] == '0')
05611 {
05612 l = l->next;
05613 continue;
05614 }
05615
05616 if (!strcmp(l->name,myrpt->cmdnode))
05617 {
05618 wf.data.ptr = str;
05619 if (l->chan) ast_write(l->chan,&wf);
05620 return;
05621 }
05622 l = l->next;
05623 }
05624 l = myrpt->links.next;
05625
05626 while(l != &myrpt->links)
05627 {
05628 wf.data.ptr = str;
05629 if (l->chan) ast_write(l->chan,&wf);
05630 l = l->next;
05631 }
05632 return;
05633 }
05634
05635 static void send_link_keyquery(struct rpt *myrpt)
05636 {
05637 char str[300];
05638 struct ast_frame wf;
05639 struct rpt_link *l;
05640
05641 rpt_mutex_lock(&myrpt->lock);
05642 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05643 myrpt->topkeystate = 1;
05644 time(&myrpt->topkeytime);
05645 rpt_mutex_unlock(&myrpt->lock);
05646 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05647 wf.frametype = AST_FRAME_TEXT;
05648 wf.subclass.integer = 0;
05649 wf.offset = 0;
05650 wf.mallocd = 0;
05651 wf.datalen = strlen(str) + 1;
05652 wf.samples = 0;
05653 l = myrpt->links.next;
05654
05655 while(l != &myrpt->links)
05656 {
05657 wf.data.ptr = str;
05658 if (l->chan) ast_write(l->chan,&wf);
05659 l = l->next;
05660 }
05661 return;
05662 }
05663
05664
05665
05666 static void send_newkey(struct ast_channel *chan)
05667 {
05668
05669
05670 ast_sendtext(chan,newkeystr);
05671 return;
05672 }
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05687 {
05688 char *val, *s, *s1, *s2, *tele;
05689 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05690 char tmp[300], deststr[300] = "",modechange = 0;
05691 char sx[320],*sy;
05692 struct rpt_link *l;
05693 int reconnects = 0;
05694 int i,n;
05695 struct dahdi_confinfo ci;
05696
05697 val = node_lookup(myrpt,node);
05698 if (!val){
05699 if(strlen(node) >= myrpt->longestnode)
05700 return -1;
05701 return 1;
05702 }
05703
05704 if(!strcmp(myrpt->name,node))
05705 return -2;
05706
05707 if(debug > 3){
05708 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05709 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05710 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05711 }
05712
05713 strncpy(tmp,val,sizeof(tmp) - 1);
05714 s = tmp;
05715 s1 = strsep(&s,",");
05716 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05717 {
05718 sy = strchr(s1,'/');
05719 *sy = 0;
05720 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05721 s1 = sx;
05722 }
05723 s2 = strsep(&s,",");
05724 rpt_mutex_lock(&myrpt->lock);
05725 l = myrpt->links.next;
05726
05727 while(l != &myrpt->links){
05728 if (l->name[0] == '0')
05729 {
05730 l = l->next;
05731 continue;
05732 }
05733
05734 if (!strcmp(l->name, node))
05735 break;
05736 l = l->next;
05737 }
05738
05739 if (l != &myrpt->links){
05740
05741 if ((l->mode) || (!l->chan)) {
05742 rpt_mutex_unlock(&myrpt->lock);
05743 return 2;
05744 }
05745 reconnects = l->reconnects;
05746 rpt_mutex_unlock(&myrpt->lock);
05747 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05748 l->retries = l->max_retries + 1;
05749 l->disced = 2;
05750 modechange = 1;
05751 } else
05752 {
05753 __mklinklist(myrpt,NULL,lstr);
05754 rpt_mutex_unlock(&myrpt->lock);
05755 n = finddelim(lstr,strs,MAXLINKLIST);
05756 for(i = 0; i < n; i++)
05757 {
05758 if ((*strs[i] < '0') ||
05759 (*strs[i] > '9')) strs[i]++;
05760 if (!strcmp(strs[i],node))
05761 {
05762 return 2;
05763 }
05764 }
05765 }
05766 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05767
05768 l = ast_malloc(sizeof(struct rpt_link));
05769 if (!l)
05770 {
05771 ast_log(LOG_WARNING, "Unable to malloc\n");
05772 return -1;
05773 }
05774
05775 memset((char *)l,0,sizeof(struct rpt_link));
05776 l->mode = mode;
05777 l->outbound = 1;
05778 l->thisconnected = 0;
05779 voxinit_link(l,1);
05780 strncpy(l->name, node, MAXNODESTR - 1);
05781 l->isremote = (s && ast_true(s));
05782 if (modechange) l->connected = 1;
05783 l->hasconnected = l->perma = perma;
05784 #ifdef ALLOW_LOCAL_CHANNELS
05785 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05786 strncpy(deststr, s1, sizeof(deststr));
05787 else
05788 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05789 #else
05790 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05791 #endif
05792 tele = strchr(deststr, '/');
05793 if (!tele){
05794 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05795 ast_free(l);
05796 return -1;
05797 }
05798 *tele++ = 0;
05799 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
05800 if (l->chan){
05801 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05802 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05803 #ifdef AST_CDR_FLAG_POST_DISABLED
05804 if (l->chan->cdr)
05805 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05806 #endif
05807 #ifndef NEW_ASTERISK
05808 l->chan->whentohangup = 0;
05809 #endif
05810 l->chan->appl = "Apprpt";
05811 l->chan->data = "(Remote Rx)";
05812 if (debug > 3)
05813 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05814 deststr, tele, l->chan->name);
05815 l->chan->caller.id.number.valid = 1;
05816 ast_free(l->chan->caller.id.number.str);
05817 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
05818 ast_call(l->chan,tele,999);
05819 }
05820 else {
05821 if(debug > 3)
05822 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05823 deststr,tele,l->chan->name);
05824 if (myrpt->p.archivedir)
05825 {
05826 char str[100];
05827 sprintf(str,"LINKFAIL,%s",l->name);
05828 donodelog(myrpt,str);
05829 }
05830 ast_free(l);
05831 return -1;
05832 }
05833
05834 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05835 if (!l->pchan){
05836 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05837 ast_hangup(l->chan);
05838 ast_free(l);
05839 return -1;
05840 }
05841 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05842 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05843 #ifdef AST_CDR_FLAG_POST_DISABLED
05844 if (l->pchan->cdr)
05845 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05846 #endif
05847
05848 ci.chan = 0;
05849 ci.confno = myrpt->conf;
05850 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05851
05852 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05853 {
05854 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05855 ast_hangup(l->chan);
05856 ast_hangup(l->pchan);
05857 ast_free(l);
05858 return -1;
05859 }
05860 rpt_mutex_lock(&myrpt->lock);
05861 l->reconnects = reconnects;
05862
05863 l->max_retries = MAX_RETRIES;
05864 if (perma)
05865 l->max_retries = MAX_RETRIES_PERM;
05866 if (l->isremote) l->retries = l->max_retries + 1;
05867 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05868 __kickshort(myrpt);
05869 rpt_mutex_unlock(&myrpt->lock);
05870 if (!l->phonemode) send_newkey(l->chan);
05871 return 0;
05872 }
05873
05874
05875
05876
05877
05878
05879
05880 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05881 {
05882
05883 char *val, *s, *s1, *s2;
05884 char tmp[300];
05885 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05886 char mode,perma;
05887 char sx[320],*sy;
05888 struct rpt_link *l;
05889 int i,r;
05890
05891 if(!param)
05892 return DC_ERROR;
05893
05894
05895 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05896 return DC_ERROR;
05897
05898 strncpy(digitbuf,digits,MAXNODESTR - 1);
05899
05900 if(debug > 6)
05901 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05902
05903 switch(myatoi(param)){
05904 case 11:
05905 case 1:
05906 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05907 strcpy(digitbuf,myrpt->lastlinknode);
05908 val = node_lookup(myrpt,digitbuf);
05909 if (!val){
05910 if(strlen(digitbuf) >= myrpt->longestnode)
05911 return DC_ERROR;
05912 break;
05913 }
05914 strncpy(tmp,val,sizeof(tmp) - 1);
05915 s = tmp;
05916 s1 = strsep(&s,",");
05917 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05918 {
05919 sy = strchr(s1,'/');
05920 *sy = 0;
05921 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05922 s1 = sx;
05923 }
05924 s2 = strsep(&s,",");
05925 rpt_mutex_lock(&myrpt->lock);
05926 l = myrpt->links.next;
05927
05928 while(l != &myrpt->links){
05929 if (l->name[0] == '0')
05930 {
05931 l = l->next;
05932 continue;
05933 }
05934
05935 if (!strcmp(l->name, digitbuf))
05936 break;
05937 l = l->next;
05938 }
05939 if (l != &myrpt->links){
05940 struct ast_frame wf;
05941
05942
05943 if ((myatoi(param) < 10) &&
05944 (l->max_retries > MAX_RETRIES))
05945 {
05946 rpt_mutex_unlock(&myrpt->lock);
05947 return DC_COMPLETE;
05948 }
05949 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05950 l->retries = l->max_retries + 1;
05951 l->disced = 1;
05952 rpt_mutex_unlock(&myrpt->lock);
05953 wf.frametype = AST_FRAME_TEXT;
05954 wf.subclass.integer = 0;
05955 wf.offset = 0;
05956 wf.mallocd = 0;
05957 wf.datalen = strlen(discstr) + 1;
05958 wf.samples = 0;
05959 wf.data.ptr = discstr;
05960 if (l->chan)
05961 {
05962 ast_write(l->chan,&wf);
05963 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05964 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05965 }
05966 rpt_telemetry(myrpt, COMPLETE, NULL);
05967 return DC_COMPLETE;
05968 }
05969 rpt_mutex_unlock(&myrpt->lock);
05970 return DC_COMPLETE;
05971 case 2:
05972 case 3:
05973 case 12:
05974 case 13:
05975 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05976 strcpy(digitbuf,myrpt->lastlinknode);
05977
05978 perma = (atoi(param) > 10) ? 1 : 0;
05979 mode = (atoi(param) & 1) ? 1 : 0;
05980 r = connect_link(myrpt, digitbuf, mode, perma);
05981 switch(r){
05982 case -2:
05983 return DC_COMPLETE;
05984
05985 case 0:
05986 rpt_telemetry(myrpt, COMPLETE, NULL);
05987 return DC_COMPLETE;
05988
05989 case 1:
05990 break;
05991
05992 case 2:
05993 rpt_telemetry(myrpt, REMALREADY, NULL);
05994 return DC_COMPLETE;
05995
05996 default:
05997 rpt_telemetry(myrpt, CONNFAIL, NULL);
05998 return DC_COMPLETE;
05999 }
06000 break;
06001
06002 case 4:
06003
06004
06005 if (((command_source != SOURCE_RPT) &&
06006 (command_source != SOURCE_PHONE) &&
06007 (command_source != SOURCE_ALT) &&
06008 (command_source != SOURCE_DPHONE)) ||
06009 (myrpt->links.next == &myrpt->links))
06010 return DC_COMPLETE;
06011
06012
06013 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06014
06015 rpt_telemetry(myrpt, REMALREADY, NULL);
06016 return DC_COMPLETE;
06017 }
06018 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06019 strcpy(digitbuf,myrpt->lastlinknode);
06020
06021 val = node_lookup(myrpt,digitbuf);
06022 if (!val){
06023 if(strlen(digitbuf) >= myrpt->longestnode)
06024 return DC_ERROR;
06025 break;
06026
06027 }
06028 rpt_mutex_lock(&myrpt->lock);
06029 strcpy(myrpt->lastlinknode,digitbuf);
06030 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06031 rpt_mutex_unlock(&myrpt->lock);
06032 rpt_telemetry(myrpt, REMGO, NULL);
06033 return DC_COMPLETE;
06034
06035 case 5:
06036 rpt_telemetry(myrpt, STATUS, NULL);
06037 return DC_COMPLETE;
06038
06039 case 15:
06040 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06041 return DC_COMPLETE;
06042
06043
06044 case 6:
06045 rpt_mutex_lock(&myrpt->lock);
06046 myrpt->savednodes[0] = 0;
06047 l = myrpt->links.next;
06048
06049 while(l != &myrpt->links){
06050 struct ast_frame wf;
06051 if (l->name[0] == '0')
06052 {
06053 l = l->next;
06054 continue;
06055 }
06056
06057 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06058 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06059 if(myrpt->savednodes[0])
06060 strcat(myrpt->savednodes, ",");
06061 strcat(myrpt->savednodes, tmp);
06062 }
06063 l->retries = l->max_retries + 1;
06064 l->disced = 2;
06065 rpt_mutex_unlock(&myrpt->lock);
06066
06067
06068 wf.frametype = AST_FRAME_TEXT;
06069 wf.subclass.integer = 0;
06070 wf.offset = 0;
06071 wf.mallocd = 0;
06072 wf.datalen = strlen(discstr) + 1;
06073 wf.samples = 0;
06074 wf.data.ptr = discstr;
06075 if (l->chan)
06076 {
06077 ast_write(l->chan,&wf);
06078 ast_safe_sleep(l->chan,250);
06079 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06080 }
06081 rpt_mutex_lock(&myrpt->lock);
06082 l = l->next;
06083 }
06084 rpt_mutex_unlock(&myrpt->lock);
06085 if(debug > 3)
06086 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06087 rpt_telemetry(myrpt, COMPLETE, NULL);
06088 return DC_COMPLETE;
06089
06090 case 7:
06091 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06092 break;
06093
06094
06095 #ifdef _MDC_DECODE_H_
06096 case 8:
06097 myrpt->lastunit = 0xd00d;
06098 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06099 mdc1200_send(myrpt,myrpt->lastunit);
06100 break;
06101 #endif
06102
06103 case 16:
06104 strcpy(tmp, myrpt->savednodes);
06105 finddelim(tmp, strs, MAXLINKLIST);
06106 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06107 s1 = strs[i];
06108 mode = (s1[0] == 'X') ? 1 : 0;
06109 perma = (s1[1] == 'P') ? 1 : 0;
06110 connect_link(myrpt, s1 + 2, mode, perma);
06111 }
06112 rpt_telemetry(myrpt, COMPLETE, NULL);
06113 break;
06114
06115 case 200:
06116 case 201:
06117 case 202:
06118 case 203:
06119 case 204:
06120 case 205:
06121 case 206:
06122 case 207:
06123 case 208:
06124 case 209:
06125 case 210:
06126 case 211:
06127 case 212:
06128 case 213:
06129 case 214:
06130 case 215:
06131 if (((myrpt->p.propagate_dtmf) &&
06132 (command_source == SOURCE_LNK)) ||
06133 ((myrpt->p.propagate_phonedtmf) &&
06134 ((command_source == SOURCE_PHONE) ||
06135 (command_source == SOURCE_ALT) ||
06136 (command_source == SOURCE_DPHONE))))
06137 do_dtmf_local(myrpt,
06138 remdtmfstr[myatoi(param) - 200]);
06139 default:
06140 return DC_ERROR;
06141
06142 }
06143
06144 return DC_INDETERMINATE;
06145 }
06146
06147
06148
06149
06150
06151 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06152 {
06153 pthread_attr_t attr;
06154 int i, idx, paramlength;
06155 char *lparam;
06156 char *value = NULL;
06157 char *paramlist[20];
06158
06159 static char *keywords[] = {
06160 "context",
06161 "dialtime",
06162 "farenddisconnect",
06163 "noct",
06164 "quiet",
06165 NULL
06166 };
06167
06168 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06169 return DC_ERROR;
06170
06171 if(debug)
06172 printf("@@@@ Autopatch up\n");
06173
06174 if(!myrpt->callmode){
06175
06176 myrpt->patchnoct = 0;
06177 myrpt->patchdialtime = 0;
06178 myrpt->patchfarenddisconnect = 0;
06179 myrpt->patchquiet = 0;
06180 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06181
06182 if(param){
06183
06184 lparam = ast_strdup(param);
06185 if(!lparam){
06186 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06187 return DC_ERROR;
06188 }
06189 paramlength = finddelim(lparam, paramlist, 20);
06190 for(i = 0; i < paramlength; i++){
06191 idx = matchkeyword(paramlist[i], &value, keywords);
06192 if(value)
06193 value = skipchars(value, "= ");
06194 switch(idx){
06195
06196 case 1:
06197 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06198 break;
06199
06200 case 2:
06201 myrpt->patchdialtime = atoi(value);
06202 break;
06203
06204 case 3:
06205 myrpt->patchfarenddisconnect = atoi(value);
06206 break;
06207
06208 case 4:
06209 myrpt->patchnoct = atoi(value);
06210 break;
06211
06212 case 5:
06213 myrpt->patchquiet = atoi(value);
06214 break;
06215
06216 default:
06217 break;
06218 }
06219 }
06220 ast_free(lparam);
06221 }
06222 }
06223
06224 rpt_mutex_lock(&myrpt->lock);
06225
06226
06227
06228 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06229 myrpt->mydtmf = myrpt->p.endchar;
06230 }
06231 if (myrpt->callmode){
06232 rpt_mutex_unlock(&myrpt->lock);
06233 return DC_COMPLETE;
06234 }
06235 myrpt->callmode = 1;
06236 myrpt->cidx = 0;
06237 myrpt->exten[myrpt->cidx] = 0;
06238 rpt_mutex_unlock(&myrpt->lock);
06239 pthread_attr_init(&attr);
06240 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06241 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06242 return DC_COMPLETE;
06243 }
06244
06245
06246
06247
06248
06249 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06250 {
06251 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06252 return DC_ERROR;
06253
06254 if(debug)
06255 printf("@@@@ Autopatch down\n");
06256
06257 rpt_mutex_lock(&myrpt->lock);
06258
06259 myrpt->macropatch=0;
06260
06261 if (!myrpt->callmode){
06262 rpt_mutex_unlock(&myrpt->lock);
06263 return DC_COMPLETE;
06264 }
06265
06266 myrpt->callmode = 0;
06267 channel_revert(myrpt);
06268 rpt_mutex_unlock(&myrpt->lock);
06269 rpt_telemetry(myrpt, TERM, NULL);
06270 return DC_COMPLETE;
06271 }
06272
06273
06274
06275
06276
06277 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06278 {
06279
06280 if (!param)
06281 return DC_ERROR;
06282
06283 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06284 return DC_ERROR;
06285
06286 if(debug)
06287 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06288
06289 switch(myatoi(param)){
06290 case 1:
06291 rpt_telemetry(myrpt, ID1, NULL);
06292 return DC_COMPLETE;
06293 case 2:
06294 rpt_telemetry(myrpt, STATS_TIME, NULL);
06295 return DC_COMPLETE;
06296 case 3:
06297 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06298 return DC_COMPLETE;
06299 case 11:
06300 rpt_telemetry(myrpt, ID , NULL);
06301 return DC_COMPLETE;
06302 case 12:
06303 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06304 return DC_COMPLETE;
06305 default:
06306 return DC_ERROR;
06307 }
06308 return DC_INDETERMINATE;
06309 }
06310
06311
06312
06313 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06314 {
06315 char *val;
06316 int i;
06317 if (myrpt->remote)
06318 return DC_ERROR;
06319
06320 if(debug)
06321 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06322
06323 if(strlen(digitbuf) < 1)
06324 return DC_INDETERMINATE;
06325
06326 for(i = 0 ; i < digitbuf[i] ; i++) {
06327 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06328 return DC_ERROR;
06329 }
06330
06331 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06332 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06333
06334 if (!val){
06335 if (strlen(digitbuf) < myrpt->macro_longest)
06336 return DC_INDETERMINATE;
06337 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06338 return DC_COMPLETE;
06339 }
06340 rpt_mutex_lock(&myrpt->lock);
06341 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06342 {
06343 rpt_mutex_unlock(&myrpt->lock);
06344 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06345 return DC_ERROR;
06346 }
06347 myrpt->macrotimer = MACROTIME;
06348 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06349 rpt_mutex_unlock(&myrpt->lock);
06350 return DC_COMPLETE;
06351 }
06352
06353
06354
06355
06356
06357 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06358 {
06359
06360 if (myrpt->remote)
06361 return DC_ERROR;
06362
06363 if(debug)
06364 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06365
06366 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06367 return DC_ERROR;
06368
06369 rpt_telemetry(myrpt,PLAYBACK,param);
06370 return DC_COMPLETE;
06371 }
06372
06373
06374
06375
06376
06377 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06378 {
06379 char string[16];
06380 int res;
06381
06382 int i, r;
06383
06384 if(!param)
06385 return DC_ERROR;
06386
06387 switch(myatoi(param)){
06388 case 1:
06389 res = system("killall -9 asterisk");
06390 return DC_COMPLETE;
06391
06392 case 2:
06393 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06394 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06395 return DC_COMPLETE;
06396
06397 case 3:
06398 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06399 return DC_COMPLETE;
06400
06401 case 4:
06402 if (myrpt->stopgen < 0)
06403 {
06404 myrpt->stopgen = 1;
06405 }
06406 else
06407 {
06408 myrpt->stopgen = 0;
06409 rpt_telemetry(myrpt, TEST_TONE, NULL);
06410 }
06411 return DC_COMPLETE;
06412
06413 case 5:
06414 myrpt->disgorgetime = time(NULL) + 10;
06415 return DC_COMPLETE;
06416
06417 case 6:
06418 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06419 return DC_DOKEY;
06420
06421
06422 case 7:
06423 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06424 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06425 return DC_COMPLETE;
06426
06427 case 8:
06428 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06429 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06430 return DC_COMPLETE;
06431
06432 case 9:
06433 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06434 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06435 return DC_COMPLETE;
06436
06437 case 10:
06438 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06439 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06440 return DC_COMPLETE;
06441
06442 case 11:
06443 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06444 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06445 return DC_COMPLETE;
06446
06447 case 12:
06448 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06449 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06450 return DC_COMPLETE;
06451
06452 case 13:
06453 string[0] = string[1] = 'S';
06454 string[2] = myrpt->p.sysstate_cur + '0';
06455 string[3] = '\0';
06456 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06457 return DC_COMPLETE;
06458
06459 case 14:
06460 if(strlen(digitbuf) == 0)
06461 break;
06462 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06463 return DC_ERROR;
06464 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06465 string[0] = string[1] = 'S';
06466 string[2] = myrpt->p.sysstate_cur + '0';
06467 string[3] = '\0';
06468 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06469 return DC_COMPLETE;
06470
06471 case 15:
06472 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06473 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06474 return DC_COMPLETE;
06475
06476 case 16:
06477 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06478 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06479 return DC_COMPLETE;
06480
06481 case 17:
06482 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06483 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06484 return DC_COMPLETE;
06485
06486 case 18:
06487 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06488 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06489 return DC_COMPLETE;
06490
06491 case 19:
06492 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06493 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06494 return DC_COMPLETE;
06495
06496 case 20:
06497 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06498 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06499 return DC_COMPLETE;
06500
06501 case 21:
06502 birdbath(myrpt);
06503 if (myrpt->p.parrotmode < 2)
06504 {
06505 myrpt->p.parrotmode = 0;
06506 rpt_telemetry(myrpt,COMPLETE,NULL);
06507 return DC_COMPLETE;
06508 }
06509 break;
06510
06511 case 22:
06512 birdbath(myrpt);
06513 if (myrpt->p.parrotmode < 2)
06514 {
06515 myrpt->p.parrotmode = 1;
06516 rpt_telemetry(myrpt,COMPLETE,NULL);
06517 return DC_COMPLETE;
06518 }
06519 break;
06520 case 23:
06521 birdbath(myrpt);
06522 rpt_telemetry(myrpt,COMPLETE,NULL);
06523 return DC_COMPLETE;
06524 case 24:
06525 flush_telem(myrpt);
06526 rpt_telemetry(myrpt,COMPLETE,NULL);
06527 return DC_COMPLETE;
06528 case 25:
06529 send_link_keyquery(myrpt);
06530 myrpt->topkeylong = 0;
06531 rpt_telemetry(myrpt,COMPLETE,NULL);
06532 return DC_COMPLETE;
06533 case 26:
06534 send_link_keyquery(myrpt);
06535 myrpt->topkeylong = 1;
06536 rpt_telemetry(myrpt,COMPLETE,NULL);
06537 return DC_COMPLETE;
06538
06539 case 30:
06540
06541 if(strlen(digitbuf) < 2)
06542 break;
06543
06544 for(i = 0 ; i < 2 ; i++){
06545 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06546 return DC_ERROR;
06547 }
06548
06549 r = retreive_memory(myrpt, digitbuf);
06550 if (r < 0){
06551 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06552 return DC_COMPLETE;
06553 }
06554 if (r > 0){
06555 return DC_ERROR;
06556 }
06557 if (setrem(myrpt) == -1) return DC_ERROR;
06558 return DC_COMPLETE;
06559
06560 case 31:
06561
06562
06563 if(strlen(digitbuf) < 2)
06564 break;
06565
06566 for(i = 0 ; i < 2 ; i++){
06567 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06568 return DC_ERROR;
06569 }
06570 channel_steer(myrpt,digitbuf);
06571 return DC_COMPLETE;
06572
06573 case 32:
06574 i = strlen(digitbuf);
06575 if(!i){
06576 if(debug > 3)
06577 ast_log(LOG_NOTICE,"Padtest entered");
06578 myrpt->inpadtest = 1;
06579 }
06580 else{
06581 if(debug > 3)
06582 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06583 if(digitbuf[i-1] != myrpt->p.endchar)
06584 break;
06585 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06586 myrpt->inpadtest = 0;
06587 if(debug > 3)
06588 ast_log(LOG_NOTICE,"Padtest exited");
06589 return DC_COMPLETE;
06590 }
06591 }
06592 return DC_INDETERMINATE;
06593 }
06594
06595
06596
06597 static int collect_function_digits(struct rpt *myrpt, char *digits,
06598 int command_source, struct rpt_link *mylink)
06599 {
06600 int i,rv;
06601 char *stringp,*action,*param,*functiondigits;
06602 char function_table_name[30] = "";
06603 char workstring[200];
06604
06605 struct ast_variable *vp;
06606
06607 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06608
06609
06610
06611
06612 if (command_source == SOURCE_DPHONE) {
06613 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06614 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06615 }
06616 else if (command_source == SOURCE_ALT) {
06617 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06618 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06619 }
06620 else if (command_source == SOURCE_PHONE) {
06621 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06622 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06623 }
06624 else if (command_source == SOURCE_LNK)
06625 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06626 else
06627 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06628
06629 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06630 while(vp) {
06631 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06632 break;
06633 vp = vp->next;
06634 }
06635
06636 if(!vp) {
06637 int n;
06638
06639 n = myrpt->longestfunc;
06640 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06641 else
06642 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06643 else
06644 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06645 else
06646 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06647
06648 if(strlen(digits) >= n)
06649 return DC_ERROR;
06650 else
06651 return DC_INDETERMINATE;
06652 }
06653
06654 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06655 stringp = workstring;
06656 action = strsep(&stringp, ",");
06657 param = stringp;
06658 if(debug)
06659 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06660
06661 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06662 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06663 break;
06664 }
06665 if(debug)
06666 printf("@@@@ table index i = %d\n",i);
06667 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06668
06669 return DC_ERROR;
06670 }
06671 if(function_table[i].function == NULL){
06672
06673 if(debug)
06674 printf("@@@@ NULL for action: %s\n",action);
06675 return DC_ERROR;
06676 }
06677 functiondigits = digits + strlen(vp->name);
06678 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06679 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06680 return(rv);
06681 }
06682
06683
06684 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06685 char *str)
06686 {
06687
06688
06689 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06690 int i,seq, res, ts;
06691 struct rpt_link *l;
06692 struct ast_frame wf;
06693
06694 wf.frametype = AST_FRAME_TEXT;
06695 wf.subclass.integer = 0;
06696 wf.offset = 0;
06697 wf.mallocd = 0;
06698 wf.datalen = strlen(str) + 1;
06699 wf.samples = 0;
06700
06701 strncpy(tmp,str,sizeof(tmp) - 1);
06702
06703 if (!strcmp(tmp,discstr))
06704 {
06705 mylink->disced = 1;
06706 mylink->retries = mylink->max_retries + 1;
06707 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06708 return;
06709 }
06710 if (!strcmp(tmp,newkeystr))
06711 {
06712 mylink->newkey = 1;
06713 return;
06714 }
06715 if (tmp[0] == 'L')
06716 {
06717 rpt_mutex_lock(&myrpt->lock);
06718 strcpy(mylink->linklist,tmp + 2);
06719 time(&mylink->linklistreceived);
06720 rpt_mutex_unlock(&myrpt->lock);
06721 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06722 myrpt->name,tmp,mylink->name);
06723 return;
06724 }
06725 if (tmp[0] == 'K')
06726 {
06727 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06728 {
06729 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06730 return;
06731 }
06732 if (dest[0] == '0')
06733 {
06734 strcpy(dest,myrpt->name);
06735 }
06736
06737 if (strcmp(dest,myrpt->name))
06738 {
06739 l = myrpt->links.next;
06740
06741 while(l != &myrpt->links)
06742 {
06743 if (l->name[0] == '0')
06744 {
06745 l = l->next;
06746 continue;
06747 }
06748
06749 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06750 {
06751 l = l->next;
06752 continue;
06753 }
06754
06755 if (!strcmp(l->name,dest))
06756 {
06757
06758 if (strcmp(l->name,src)) {
06759 wf.data.ptr = str;
06760 if (l->chan) ast_write(l->chan,&wf);
06761 }
06762 return;
06763 }
06764 l = l->next;
06765 }
06766 }
06767
06768 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06769 {
06770 l = myrpt->links.next;
06771
06772 while(l != &myrpt->links)
06773 {
06774 if (l->name[0] == '0')
06775 {
06776 l = l->next;
06777 continue;
06778 }
06779
06780 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06781 {
06782 l = l->next;
06783 continue;
06784 }
06785
06786 if (strcmp(l->name,src)) {
06787 wf.data.ptr = str;
06788 if (l->chan) ast_write(l->chan,&wf);
06789 }
06790 l = l->next;
06791 }
06792 }
06793
06794 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06795 if (cmd[1] == '?')
06796 {
06797 time_t now;
06798 int n = 0;
06799
06800 time(&now);
06801 if (myrpt->lastkeyedtime)
06802 {
06803 n = (int)(now - myrpt->lastkeyedtime);
06804 }
06805 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06806 wf.data.ptr = tmp1;
06807 wf.datalen = strlen(tmp1) + 1;
06808 if (mylink->chan) ast_write(mylink->chan,&wf);
06809 return;
06810 }
06811 if (myrpt->topkeystate != 1) return;
06812 rpt_mutex_lock(&myrpt->lock);
06813 for(i = 0; i < TOPKEYN; i++)
06814 {
06815 if (!strcmp(myrpt->topkey[i].node,src)) break;
06816 }
06817 if (i >= TOPKEYN)
06818 {
06819 for(i = 0; i < TOPKEYN; i++)
06820 {
06821 if (!myrpt->topkey[i].node[0]) break;
06822 }
06823 }
06824 if (i < TOPKEYN)
06825 {
06826 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06827 myrpt->topkey[i].timesince = ts;
06828 myrpt->topkey[i].keyed = seq;
06829 }
06830 rpt_mutex_unlock(&myrpt->lock);
06831 return;
06832 }
06833 if (tmp[0] == 'I')
06834 {
06835
06836
06837 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06838 {
06839 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06840 return;
06841 }
06842 mdc1200_notify(myrpt,src,seq);
06843 strcpy(dest,"*");
06844 }
06845 else
06846 {
06847
06848
06849 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06850 {
06851 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06852 return;
06853 }
06854 if (strcmp(cmd,"D"))
06855 {
06856 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06857 return;
06858 }
06859 }
06860 if (dest[0] == '0')
06861 {
06862 strcpy(dest,myrpt->name);
06863 }
06864
06865
06866 if (strcmp(dest,myrpt->name))
06867 {
06868 l = myrpt->links.next;
06869
06870 while(l != &myrpt->links)
06871 {
06872 if (l->name[0] == '0')
06873 {
06874 l = l->next;
06875 continue;
06876 }
06877
06878 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06879 {
06880 l = l->next;
06881 continue;
06882 }
06883
06884 if (!strcmp(l->name,dest))
06885 {
06886
06887 if (strcmp(l->name,src)) {
06888 wf.data.ptr = str;
06889 if (l->chan) ast_write(l->chan,&wf);
06890 }
06891 return;
06892 }
06893 l = l->next;
06894 }
06895 l = myrpt->links.next;
06896
06897 while(l != &myrpt->links)
06898 {
06899 if (l->name[0] == '0')
06900 {
06901 l = l->next;
06902 continue;
06903 }
06904
06905 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06906 {
06907 l = l->next;
06908 continue;
06909 }
06910
06911 if (strcmp(l->name,src)) {
06912 wf.data.ptr = str;
06913 if (l->chan) ast_write(l->chan,&wf);
06914 }
06915 l = l->next;
06916 }
06917 return;
06918 }
06919 if (myrpt->p.archivedir)
06920 {
06921 char dtmfstr[100];
06922
06923 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06924 donodelog(myrpt,dtmfstr);
06925 }
06926 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06927 if (!c) return;
06928 rpt_mutex_lock(&myrpt->lock);
06929 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06930 if (myrpt->callmode == 1)
06931 {
06932 myrpt->exten[myrpt->cidx++] = c;
06933 myrpt->exten[myrpt->cidx] = 0;
06934
06935 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06936 {
06937
06938 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06939 myrpt->exten,1,NULL))
06940 {
06941 myrpt->callmode = 2;
06942 if(!myrpt->patchquiet)
06943 {
06944 rpt_mutex_unlock(&myrpt->lock);
06945 rpt_telemetry(myrpt,PROC,NULL);
06946 rpt_mutex_lock(&myrpt->lock);
06947 }
06948 }
06949 else
06950 {
06951 myrpt->calldigittimer = 1;
06952 }
06953 }
06954
06955 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06956 {
06957
06958 myrpt->callmode = 4;
06959 }
06960 }
06961 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06962 {
06963 myrpt->rem_dtmfidx = 0;
06964 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06965 time(&myrpt->rem_dtmf_time);
06966 rpt_mutex_unlock(&myrpt->lock);
06967 return;
06968 }
06969 else if (myrpt->rem_dtmfidx < 0)
06970 {
06971 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06972 {
06973 myrpt->mydtmf = c;
06974 }
06975 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06976 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06977 rpt_mutex_unlock(&myrpt->lock);
06978 return;
06979 }
06980 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06981 {
06982 time(&myrpt->rem_dtmf_time);
06983 if (myrpt->rem_dtmfidx < MAXDTMF)
06984 {
06985 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06986 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06987
06988 rpt_mutex_unlock(&myrpt->lock);
06989 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06990 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06991 rpt_mutex_lock(&myrpt->lock);
06992
06993 switch(res){
06994
06995 case DC_INDETERMINATE:
06996 break;
06997
06998 case DC_REQ_FLUSH:
06999 myrpt->rem_dtmfidx = 0;
07000 myrpt->rem_dtmfbuf[0] = 0;
07001 break;
07002
07003
07004 case DC_COMPLETE:
07005 case DC_COMPLETEQUIET:
07006 myrpt->totalexecdcommands++;
07007 myrpt->dailyexecdcommands++;
07008 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07009 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07010 myrpt->rem_dtmfbuf[0] = 0;
07011 myrpt->rem_dtmfidx = -1;
07012 myrpt->rem_dtmf_time = 0;
07013 break;
07014
07015 case DC_ERROR:
07016 default:
07017 myrpt->rem_dtmfbuf[0] = 0;
07018 myrpt->rem_dtmfidx = -1;
07019 myrpt->rem_dtmf_time = 0;
07020 break;
07021 }
07022 }
07023
07024 }
07025 rpt_mutex_unlock(&myrpt->lock);
07026 return;
07027 }
07028
07029 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07030 char c)
07031 {
07032
07033 char cmd[300];
07034 int res;
07035
07036 if (myrpt->p.archivedir)
07037 {
07038 char str[100];
07039
07040 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07041 donodelog(myrpt,str);
07042 }
07043 rpt_mutex_lock(&myrpt->lock);
07044
07045 if (mylink->phonemode == 3)
07046 {
07047 if(c == myrpt->p.endchar)
07048 {
07049 mylink->lastrealrx = 0;
07050 rpt_mutex_unlock(&myrpt->lock);
07051 return;
07052 }
07053
07054 if(c == myrpt->p.funcchar)
07055 {
07056 mylink->lastrealrx = !mylink->lastrealrx;
07057 rpt_mutex_unlock(&myrpt->lock);
07058 return;
07059 }
07060 }
07061 else
07062 {
07063 if (c == myrpt->p.endchar)
07064 {
07065 if (mylink->lastrx)
07066 {
07067 mylink->lastrealrx = 0;
07068 rpt_mutex_unlock(&myrpt->lock);
07069 return;
07070 }
07071 myrpt->stopgen = 1;
07072 if (myrpt->cmdnode[0])
07073 {
07074 myrpt->cmdnode[0] = 0;
07075 myrpt->dtmfidx = -1;
07076 myrpt->dtmfbuf[0] = 0;
07077 rpt_mutex_unlock(&myrpt->lock);
07078 rpt_telemetry(myrpt,COMPLETE,NULL);
07079 return;
07080 }
07081 }
07082 }
07083 if (myrpt->cmdnode[0])
07084 {
07085 rpt_mutex_unlock(&myrpt->lock);
07086 send_link_dtmf(myrpt,c);
07087 return;
07088 }
07089 if (myrpt->callmode == 1)
07090 {
07091 myrpt->exten[myrpt->cidx++] = c;
07092 myrpt->exten[myrpt->cidx] = 0;
07093
07094 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07095 {
07096
07097 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07098 myrpt->exten,1,NULL))
07099 {
07100 myrpt->callmode = 2;
07101 if(!myrpt->patchquiet)
07102 {
07103 rpt_mutex_unlock(&myrpt->lock);
07104 rpt_telemetry(myrpt,PROC,NULL);
07105 rpt_mutex_lock(&myrpt->lock);
07106 }
07107 }
07108 else
07109 {
07110 myrpt->calldigittimer = 1;
07111 }
07112 }
07113
07114 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07115 {
07116
07117 myrpt->callmode = 4;
07118 }
07119 }
07120 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07121 {
07122 myrpt->mydtmf = c;
07123 }
07124 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07125 {
07126 myrpt->rem_dtmfidx = 0;
07127 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07128 time(&myrpt->rem_dtmf_time);
07129 rpt_mutex_unlock(&myrpt->lock);
07130 return;
07131 }
07132 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07133 {
07134 time(&myrpt->rem_dtmf_time);
07135 if (myrpt->rem_dtmfidx < MAXDTMF)
07136 {
07137 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07138 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07139
07140 rpt_mutex_unlock(&myrpt->lock);
07141 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07142 switch(mylink->phonemode)
07143 {
07144 case 1:
07145 res = collect_function_digits(myrpt, cmd,
07146 SOURCE_PHONE, mylink);
07147 break;
07148 case 2:
07149 res = collect_function_digits(myrpt, cmd,
07150 SOURCE_DPHONE,mylink);
07151 break;
07152 case 4:
07153 res = collect_function_digits(myrpt, cmd,
07154 SOURCE_ALT,mylink);
07155 break;
07156 default:
07157 res = collect_function_digits(myrpt, cmd,
07158 SOURCE_LNK, mylink);
07159 break;
07160 }
07161
07162 rpt_mutex_lock(&myrpt->lock);
07163
07164 switch(res){
07165
07166 case DC_INDETERMINATE:
07167 break;
07168
07169 case DC_DOKEY:
07170 mylink->lastrealrx = 1;
07171 break;
07172
07173 case DC_REQ_FLUSH:
07174 myrpt->rem_dtmfidx = 0;
07175 myrpt->rem_dtmfbuf[0] = 0;
07176 break;
07177
07178
07179 case DC_COMPLETE:
07180 case DC_COMPLETEQUIET:
07181 myrpt->totalexecdcommands++;
07182 myrpt->dailyexecdcommands++;
07183 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07184 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07185 myrpt->rem_dtmfbuf[0] = 0;
07186 myrpt->rem_dtmfidx = -1;
07187 myrpt->rem_dtmf_time = 0;
07188 break;
07189
07190 case DC_ERROR:
07191 default:
07192 myrpt->rem_dtmfbuf[0] = 0;
07193 myrpt->rem_dtmfidx = -1;
07194 myrpt->rem_dtmf_time = 0;
07195 break;
07196 }
07197 }
07198
07199 }
07200 rpt_mutex_unlock(&myrpt->lock);
07201 return;
07202 }
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233
07234
07235 static int rbi_mhztoband(char *str)
07236 {
07237 int i;
07238
07239 i = atoi(str) / 10;
07240 switch(i)
07241 {
07242 case 2:
07243 return 10;
07244 case 5:
07245 return 11;
07246 case 14:
07247 return 2;
07248 case 22:
07249 return 3;
07250 case 44:
07251 return 4;
07252 case 124:
07253 return 0;
07254 case 125:
07255 return 1;
07256 case 126:
07257 return 8;
07258 case 127:
07259 return 5;
07260 case 128:
07261 return 6;
07262 case 129:
07263 return 7;
07264 default:
07265 break;
07266 }
07267 return -1;
07268 }
07269
07270
07271 static int rbi_pltocode(char *str)
07272 {
07273 int i;
07274 char *s;
07275
07276 s = strchr(str,'.');
07277 i = 0;
07278 if (s) i = atoi(s + 1);
07279 i += atoi(str) * 10;
07280 switch(i)
07281 {
07282 case 670:
07283 return 0;
07284 case 719:
07285 return 1;
07286 case 744:
07287 return 2;
07288 case 770:
07289 return 3;
07290 case 797:
07291 return 4;
07292 case 825:
07293 return 5;
07294 case 854:
07295 return 6;
07296 case 885:
07297 return 7;
07298 case 915:
07299 return 8;
07300 case 948:
07301 return 9;
07302 case 974:
07303 return 10;
07304 case 1000:
07305 return 11;
07306 case 1035:
07307 return 12;
07308 case 1072:
07309 return 13;
07310 case 1109:
07311 return 14;
07312 case 1148:
07313 return 15;
07314 case 1188:
07315 return 16;
07316 case 1230:
07317 return 17;
07318 case 1273:
07319 return 18;
07320 case 1318:
07321 return 19;
07322 case 1365:
07323 return 20;
07324 case 1413:
07325 return 21;
07326 case 1462:
07327 return 22;
07328 case 1514:
07329 return 23;
07330 case 1567:
07331 return 24;
07332 case 1622:
07333 return 25;
07334 case 1679:
07335 return 26;
07336 case 1738:
07337 return 27;
07338 case 1799:
07339 return 28;
07340 case 1862:
07341 return 29;
07342 case 1928:
07343 return 30;
07344 case 2035:
07345 return 31;
07346 case 2107:
07347 return 32;
07348 case 2181:
07349 return 33;
07350 case 2257:
07351 return 34;
07352 case 2336:
07353 return 35;
07354 case 2418:
07355 return 36;
07356 case 2503:
07357 return 37;
07358 }
07359 return -1;
07360 }
07361
07362
07363
07364
07365
07366 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07367 {
07368 #ifdef __i386__
07369 int i,j;
07370 unsigned char od,d;
07371 static volatile long long delayvar;
07372
07373 for(i = 0 ; i < 5 ; i++){
07374 od = *data++;
07375 for(j = 0 ; j < 8 ; j++){
07376 d = od & 1;
07377 outb(d,myrpt->p.iobase);
07378
07379 for(delayvar = 1; delayvar < 15000; delayvar++);
07380 od >>= 1;
07381 outb(d | 2,myrpt->p.iobase);
07382
07383 for(delayvar = 1; delayvar < 30000; delayvar++);
07384 outb(d,myrpt->p.iobase);
07385
07386 for(delayvar = 1; delayvar < 10000; delayvar++);
07387 }
07388 }
07389
07390 for(delayvar = 1; delayvar < 50000; delayvar++);
07391 #endif
07392 }
07393
07394 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07395 {
07396 struct dahdi_radio_param r;
07397
07398 memset(&r,0,sizeof(struct dahdi_radio_param));
07399 r.radpar = DAHDI_RADPAR_REMMODE;
07400 r.data = DAHDI_RADPAR_REM_RBI1;
07401
07402 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07403 {
07404 rbi_out_parallel(myrpt,data);
07405 return;
07406 }
07407 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07408 memcpy(&r.data,data,5);
07409 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07410 {
07411 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07412 return;
07413 }
07414 }
07415
07416 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07417 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07418 {
07419 int i,j,idx,oldmode,olddata;
07420 struct dahdi_radio_param prm;
07421 char c;
07422
07423 if(debug) {
07424 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07425 printf("String output was:\n");
07426 for(i = 0; i < txbytes; i++)
07427 printf("%02X ", (unsigned char ) txbuf[i]);
07428 printf("\n");
07429 }
07430
07431 if (myrpt->iofd >= 0)
07432 {
07433 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07434 {
07435 return -1;
07436 }
07437 if ((!rxmaxbytes) || (rxbuf == NULL))
07438 {
07439 return(0);
07440 }
07441 memset(rxbuf,0,rxmaxbytes);
07442 for(i = 0; i < rxmaxbytes; i++)
07443 {
07444 j = read(myrpt->iofd,&c,1);
07445 if (j < 1)
07446 {
07447 return(i);
07448 }
07449 rxbuf[i] = c;
07450 if (asciiflag & 1)
07451 {
07452 rxbuf[i + 1] = 0;
07453 if (c == '\r') break;
07454 }
07455 }
07456 if(debug) {
07457 printf("String returned was:\n");
07458 for(j = 0; j < i; j++)
07459 printf("%02X ", (unsigned char ) rxbuf[j]);
07460 printf("\n");
07461 }
07462 return(i);
07463 }
07464
07465
07466 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07467
07468 prm.radpar = DAHDI_RADPAR_UIOMODE;
07469 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07470 oldmode = prm.data;
07471 prm.radpar = DAHDI_RADPAR_UIODATA;
07472 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07473 olddata = prm.data;
07474 prm.radpar = DAHDI_RADPAR_REMMODE;
07475 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07476 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07477 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07478 if (asciiflag & 2)
07479 {
07480 i = DAHDI_ONHOOK;
07481 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07482 usleep(100000);
07483 }
07484 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07485 prm.data = rxmaxbytes;
07486 memcpy(prm.buf,txbuf,txbytes);
07487 prm.index = txbytes;
07488 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07489 if (rxbuf)
07490 {
07491 *rxbuf = 0;
07492 memcpy(rxbuf,prm.buf,prm.index);
07493 }
07494 idx = prm.index;
07495 prm.radpar = DAHDI_RADPAR_REMMODE;
07496 prm.data = DAHDI_RADPAR_REM_NONE;
07497 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07498 if (asciiflag & 2)
07499 {
07500 i = DAHDI_OFFHOOK;
07501 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07502 }
07503 prm.radpar = DAHDI_RADPAR_UIOMODE;
07504 prm.data = oldmode;
07505 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07506 prm.radpar = DAHDI_RADPAR_UIODATA;
07507 prm.data = olddata;
07508 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07509 return(idx);
07510 }
07511
07512 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07513 {
07514 unsigned char rxbuf[100];
07515 int i,rv ;
07516
07517 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07518 if (rv == -1) return(-1);
07519 if (rv != (cmdlen + 6)) return(1);
07520 for(i = 0; i < 6; i++)
07521 if (rxbuf[i] != cmd[i]) return(1);
07522 if (rxbuf[cmdlen] != 0xfe) return(1);
07523 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07524 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07525 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07526 return(0);
07527 }
07528
07529 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07530 {
07531 int i;
07532
07533 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07534 if (debug) printf("Send to kenwood: %s\n",txstr);
07535 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07536 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07537 if (i < 0) return -1;
07538 if ((i > 0) && (rxstr[i - 1] == '\r'))
07539 rxstr[i-- - 1] = 0;
07540 if (debug) printf("Got from kenwood: %s\n",rxstr);
07541 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07542 return(i);
07543 }
07544
07545
07546 static int kenwood_pltocode(char *str)
07547 {
07548 int i;
07549 char *s;
07550
07551 s = strchr(str,'.');
07552 i = 0;
07553 if (s) i = atoi(s + 1);
07554 i += atoi(str) * 10;
07555 switch(i)
07556 {
07557 case 670:
07558 return 1;
07559 case 719:
07560 return 3;
07561 case 744:
07562 return 4;
07563 case 770:
07564 return 5;
07565 case 797:
07566 return 6;
07567 case 825:
07568 return 7;
07569 case 854:
07570 return 8;
07571 case 885:
07572 return 9;
07573 case 915:
07574 return 10;
07575 case 948:
07576 return 11;
07577 case 974:
07578 return 12;
07579 case 1000:
07580 return 13;
07581 case 1035:
07582 return 14;
07583 case 1072:
07584 return 15;
07585 case 1109:
07586 return 16;
07587 case 1148:
07588 return 17;
07589 case 1188:
07590 return 18;
07591 case 1230:
07592 return 19;
07593 case 1273:
07594 return 20;
07595 case 1318:
07596 return 21;
07597 case 1365:
07598 return 22;
07599 case 1413:
07600 return 23;
07601 case 1462:
07602 return 24;
07603 case 1514:
07604 return 25;
07605 case 1567:
07606 return 26;
07607 case 1622:
07608 return 27;
07609 case 1679:
07610 return 28;
07611 case 1738:
07612 return 29;
07613 case 1799:
07614 return 30;
07615 case 1862:
07616 return 31;
07617 case 1928:
07618 return 32;
07619 case 2035:
07620 return 33;
07621 case 2107:
07622 return 34;
07623 case 2181:
07624 return 35;
07625 case 2257:
07626 return 36;
07627 case 2336:
07628 return 37;
07629 case 2418:
07630 return 38;
07631 case 2503:
07632 return 39;
07633 }
07634 return -1;
07635 }
07636
07637 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07638 char *cmpstr)
07639 {
07640 int i,j;
07641
07642 for(i = 0;i < KENWOOD_RETRIES;i++)
07643 {
07644 j = sendkenwood(myrpt,txstr,rxstr);
07645 if (j < 0) return(j);
07646 if (j == 0) continue;
07647 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07648 }
07649 return(-1);
07650 }
07651
07652 static int setkenwood(struct rpt *myrpt)
07653 {
07654 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07655 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07656 int myrxpl;
07657
07658 int offsets[] = {0,2,1};
07659 int powers[] = {2,1,0};
07660
07661 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07662 split_freq(mhz, decimals, myrpt->freq);
07663 if (atoi(mhz) > 400)
07664 {
07665 band = '6';
07666 band1 = '1';
07667 band2 = '5';
07668 strcpy(offset,"005000000");
07669 }
07670 else
07671 {
07672 band = '2';
07673 band1 = '0';
07674 band2 = '2';
07675 strcpy(offset,"000600000");
07676 }
07677 strcpy(freq,"000000");
07678 strncpy(freq,decimals,strlen(decimals));
07679 myrxpl = myrpt->rxplon;
07680 if (IS_XPMR(myrpt)) myrxpl = 0;
07681 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07682 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07683 (myrpt->txplon != 0),myrxpl,
07684 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07685 offset);
07686 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07687 sprintf(txstr,"RBN %c\r",band2);
07688 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07689 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07690 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07691 return 0;
07692 }
07693
07694 static int set_tm271(struct rpt *myrpt)
07695 {
07696 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07697 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07698
07699 int offsets[] = {0,2,1};
07700 int powers[] = {2,1,0};
07701
07702 split_freq(mhz, decimals, myrpt->freq);
07703 strcpy(freq,"000000");
07704 strncpy(freq,decimals,strlen(decimals));
07705
07706 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07707 atoi(mhz),freq,offsets[(int)myrpt->offset],
07708 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07709 kenwood_pltocode(myrpt->rxpl));
07710
07711 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07712 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07713 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07714 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07715 return 0;
07716 }
07717
07718 static int setrbi(struct rpt *myrpt)
07719 {
07720 char tmp[MAXREMSTR] = "",*s;
07721 unsigned char rbicmd[5];
07722 int band,txoffset = 0,txpower = 0,rxpl;
07723
07724
07725 if (!myrpt->remoterig) return(0);
07726 if (!myrpt->remoterig[0]) return(0);
07727
07728 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07729 if (setrbi_check(myrpt) == -1) return(-1);
07730 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07731 s = strchr(tmp,'.');
07732
07733
07734 if (s == NULL){
07735 if(debug)
07736 printf("@@@@ Frequency needs a decimal\n");
07737 return -1;
07738 }
07739
07740 *s++ = 0;
07741 if (strlen(tmp) < 2){
07742 if(debug)
07743 printf("@@@@ Bad MHz digits: %s\n", tmp);
07744 return -1;
07745 }
07746
07747 if (strlen(s) < 3){
07748 if(debug)
07749 printf("@@@@ Bad KHz digits: %s\n", s);
07750 return -1;
07751 }
07752
07753 if ((s[2] != '0') && (s[2] != '5')){
07754 if(debug)
07755 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07756 return -1;
07757 }
07758
07759 band = rbi_mhztoband(tmp);
07760 if (band == -1){
07761 if(debug)
07762 printf("@@@@ Bad Band: %s\n", tmp);
07763 return -1;
07764 }
07765
07766 rxpl = rbi_pltocode(myrpt->rxpl);
07767
07768 if (rxpl == -1){
07769 if(debug)
07770 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07771 return -1;
07772 }
07773
07774
07775 switch(myrpt->offset)
07776 {
07777 case REM_MINUS:
07778 txoffset = 0;
07779 break;
07780 case REM_PLUS:
07781 txoffset = 0x10;
07782 break;
07783 case REM_SIMPLEX:
07784 txoffset = 0x20;
07785 break;
07786 }
07787 switch(myrpt->powerlevel)
07788 {
07789 case REM_LOWPWR:
07790 txpower = 0;
07791 break;
07792 case REM_MEDPWR:
07793 txpower = 0x20;
07794 break;
07795 case REM_HIPWR:
07796 txpower = 0x10;
07797 break;
07798 }
07799 rbicmd[0] = 0;
07800 rbicmd[1] = band | txpower | 0xc0;
07801 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07802 if (s[2] == '5') rbicmd[2] |= 0x40;
07803 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07804 rbicmd[4] = rxpl;
07805 if (myrpt->txplon) rbicmd[4] |= 0x40;
07806 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07807 rbi_out(myrpt,rbicmd);
07808 return 0;
07809 }
07810
07811 static int setrtx(struct rpt *myrpt)
07812 {
07813 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07814 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07815 float ofac;
07816 double txfreq;
07817
07818
07819 if (!myrpt->remoterig) return(0);
07820 if (!myrpt->remoterig[0]) return(0);
07821
07822 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07823
07824 if (!IS_XPMR(myrpt)) return(0);
07825 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07826 s = strchr(tmp,'.');
07827
07828
07829 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07830
07831 if (s == NULL){
07832 if(debug)
07833 printf("@@@@ Frequency needs a decimal\n");
07834 return -1;
07835 }
07836 *s++ = 0;
07837 if (strlen(tmp) < 2){
07838 if(debug)
07839 printf("@@@@ Bad MHz digits: %s\n", tmp);
07840 return -1;
07841 }
07842
07843 if (strlen(s) < 3){
07844 if(debug)
07845 printf("@@@@ Bad KHz digits: %s\n", s);
07846 return -1;
07847 }
07848
07849 if ((s[2] != '0') && (s[2] != '5')){
07850 if(debug)
07851 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07852 return -1;
07853 }
07854
07855 band = rbi_mhztoband(tmp);
07856 if (band == -1){
07857 if(debug)
07858 printf("@@@@ Bad Band: %s\n", tmp);
07859 return -1;
07860 }
07861
07862 rxpl = rbi_pltocode(myrpt->rxpl);
07863
07864 if (rxpl == -1){
07865 if(debug)
07866 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07867 return -1;
07868 }
07869
07870 txpl = rbi_pltocode(myrpt->txpl);
07871
07872 if (txpl == -1){
07873 if(debug)
07874 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07875 return -1;
07876 }
07877
07878 switch(myrpt->offset)
07879 {
07880 case REM_MINUS:
07881 txoffset = 0;
07882 break;
07883 case REM_PLUS:
07884 txoffset = 0x10;
07885 break;
07886 case REM_SIMPLEX:
07887 txoffset = 0x20;
07888 break;
07889 }
07890 switch(myrpt->powerlevel)
07891 {
07892 case REM_LOWPWR:
07893 txpower = 0;
07894 break;
07895 case REM_MEDPWR:
07896 txpower = 0x20;
07897 break;
07898 case REM_HIPWR:
07899 txpower = 0x10;
07900 break;
07901 }
07902
07903 res = setrtx_check(myrpt);
07904 if (res < 0) return res;
07905 ofac = 0.0;
07906 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07907 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07908
07909 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07910 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07911 else
07912 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07913
07914 pwr = 'L';
07915 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07916 if (!res)
07917 {
07918 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07919 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07920 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07921 send_usb_txt(myrpt,rigstr);
07922 rpt_telemetry(myrpt,COMPLETE,NULL);
07923 res = 0;
07924 }
07925 return 0;
07926 }
07927 #if 0
07928
07929
07930
07931
07932 static int setxpmr(struct rpt *myrpt)
07933 {
07934 char rigstr[200];
07935 int rxpl,txpl;
07936
07937
07938 if (!myrpt->remoterig) return(0);
07939 if (!myrpt->remoterig[0]) return(0);
07940
07941 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07942
07943 if (!IS_XPMR(myrpt)) return(0);
07944
07945 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07946
07947 rxpl = rbi_pltocode(myrpt->rxpl);
07948
07949 if (rxpl == -1){
07950 if(debug)
07951 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07952 return -1;
07953 }
07954
07955 txpl = rbi_pltocode(myrpt->txpl);
07956 if (txpl == -1){
07957 if(debug)
07958 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07959 return -1;
07960 }
07961 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07962 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07963 (myrpt->txplon) ? myrpt->txpl : "0.0");
07964 send_usb_txt(myrpt,rigstr);
07965 return 0;
07966 }
07967 #endif
07968
07969 static int setrbi_check(struct rpt *myrpt)
07970 {
07971 char tmp[MAXREMSTR] = "",*s;
07972 int band,txpl;
07973
07974
07975 if (!myrpt->remote) return(0);
07976
07977 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07978 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07979 s = strchr(tmp,'.');
07980
07981
07982 if (s == NULL){
07983 if(debug)
07984 printf("@@@@ Frequency needs a decimal\n");
07985 return -1;
07986 }
07987
07988 *s++ = 0;
07989 if (strlen(tmp) < 2){
07990 if(debug)
07991 printf("@@@@ Bad MHz digits: %s\n", tmp);
07992 return -1;
07993 }
07994
07995 if (strlen(s) < 3){
07996 if(debug)
07997 printf("@@@@ Bad KHz digits: %s\n", s);
07998 return -1;
07999 }
08000
08001 if ((s[2] != '0') && (s[2] != '5')){
08002 if(debug)
08003 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08004 return -1;
08005 }
08006
08007 band = rbi_mhztoband(tmp);
08008 if (band == -1){
08009 if(debug)
08010 printf("@@@@ Bad Band: %s\n", tmp);
08011 return -1;
08012 }
08013
08014 txpl = rbi_pltocode(myrpt->txpl);
08015
08016 if (txpl == -1){
08017 if(debug)
08018 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08019 return -1;
08020 }
08021 return 0;
08022 }
08023
08024 static int setrtx_check(struct rpt *myrpt)
08025 {
08026 char tmp[MAXREMSTR] = "",*s;
08027 int band,txpl,rxpl;
08028
08029
08030 if (!myrpt->remote) return(0);
08031
08032 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08033 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08034 s = strchr(tmp,'.');
08035
08036
08037 if (s == NULL){
08038 if(debug)
08039 printf("@@@@ Frequency needs a decimal\n");
08040 return -1;
08041 }
08042
08043 *s++ = 0;
08044 if (strlen(tmp) < 2){
08045 if(debug)
08046 printf("@@@@ Bad MHz digits: %s\n", tmp);
08047 return -1;
08048 }
08049
08050 if (strlen(s) < 3){
08051 if(debug)
08052 printf("@@@@ Bad KHz digits: %s\n", s);
08053 return -1;
08054 }
08055
08056 if ((s[2] != '0') && (s[2] != '5')){
08057 if(debug)
08058 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08059 return -1;
08060 }
08061
08062 band = rbi_mhztoband(tmp);
08063 if (band == -1){
08064 if(debug)
08065 printf("@@@@ Bad Band: %s\n", tmp);
08066 return -1;
08067 }
08068
08069 txpl = rbi_pltocode(myrpt->txpl);
08070
08071 if (txpl == -1){
08072 if(debug)
08073 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08074 return -1;
08075 }
08076
08077 rxpl = rbi_pltocode(myrpt->rxpl);
08078
08079 if (rxpl == -1){
08080 if(debug)
08081 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08082 return -1;
08083 }
08084 return 0;
08085 }
08086
08087 static int check_freq_kenwood(int m, int d, int *defmode)
08088 {
08089 int dflmd = REM_MODE_FM;
08090
08091 if (m == 144){
08092 if(d < 10100)
08093 return -1;
08094 }
08095 else if((m >= 145) && (m < 148)){
08096 ;
08097 }
08098 else if((m >= 430) && (m < 450)){
08099 ;
08100 }
08101 else
08102 return -1;
08103
08104 if(defmode)
08105 *defmode = dflmd;
08106
08107
08108 return 0;
08109 }
08110
08111
08112 static int check_freq_tm271(int m, int d, int *defmode)
08113 {
08114 int dflmd = REM_MODE_FM;
08115
08116 if (m == 144){
08117 if(d < 10100)
08118 return -1;
08119 }
08120 else if((m >= 145) && (m < 148)){
08121 ;
08122 }
08123 return -1;
08124
08125 if(defmode)
08126 *defmode = dflmd;
08127
08128
08129 return 0;
08130 }
08131
08132
08133
08134
08135
08136 static int check_freq_rbi(int m, int d, int *defmode)
08137 {
08138 int dflmd = REM_MODE_FM;
08139
08140 if(m == 50){
08141 if(d < 10100)
08142 return -1;
08143 }
08144 else if((m >= 51) && ( m < 54)){
08145 ;
08146 }
08147 else if(m == 144){
08148 if(d < 10100)
08149 return -1;
08150 }
08151 else if((m >= 145) && (m < 148)){
08152 ;
08153 }
08154 else if((m >= 222) && (m < 225)){
08155 ;
08156 }
08157 else if((m >= 430) && (m < 450)){
08158 ;
08159 }
08160 else if((m >= 1240) && (m < 1300)){
08161 ;
08162 }
08163 else
08164 return -1;
08165
08166 if(defmode)
08167 *defmode = dflmd;
08168
08169
08170 return 0;
08171 }
08172
08173
08174
08175
08176 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08177 {
08178 int dflmd = REM_MODE_FM;
08179
08180 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08181 {
08182
08183 if(m == 144){
08184 if(d < 10100)
08185 return -1;
08186 }
08187 else if((m >= 145) && (m < 148)){
08188 ;
08189 }
08190 else
08191 return -1;
08192 }
08193 else
08194 {
08195 if((m >= 430) && (m < 450)){
08196 ;
08197 }
08198 else
08199 return -1;
08200 }
08201 if(defmode)
08202 *defmode = dflmd;
08203
08204
08205 return 0;
08206 }
08207
08208
08209
08210
08211
08212 static int decimals2int(char *fraction)
08213 {
08214 int i;
08215 char len = strlen(fraction);
08216 int multiplier = 100000;
08217 int res = 0;
08218
08219 if(!len)
08220 return 0;
08221 for( i = 0 ; i < len ; i++, multiplier /= 10)
08222 res += (fraction[i] - '0') * multiplier;
08223 return res;
08224 }
08225
08226
08227
08228
08229
08230
08231 static int split_freq(char *mhz, char *decimals, char *freq)
08232 {
08233 char freq_copy[MAXREMSTR];
08234 char *decp;
08235
08236 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08237 if(decp){
08238 *decp++ = 0;
08239 strncpy(mhz, freq_copy, MAXREMSTR);
08240 strcpy(decimals, "00000");
08241 strncpy(decimals, decp, strlen(decp));
08242 decimals[5] = 0;
08243 return 0;
08244 }
08245 else
08246 return -1;
08247
08248 }
08249
08250
08251
08252
08253
08254 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08255 {
08256 char freq_copy[MAXREMSTR];
08257 char *decp;
08258
08259 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08260 if(decp){
08261 *decp++ = 0;
08262 strncpy(hertz, freq_copy, MAXREMSTR);
08263 strncpy(decimal, decp, strlen(decp));
08264 decimal[strlen(decp)] = '\0';
08265 return 0;
08266 }
08267 else
08268 return -1;
08269 }
08270
08271
08272
08273
08274
08275
08276
08277
08278
08279
08280
08281 static int check_freq_ft897(int m, int d, int *defmode)
08282 {
08283 int dflmd = REM_MODE_FM;
08284
08285 if(m == 1){
08286 dflmd = REM_MODE_LSB;
08287 if(d < 80000)
08288 return -1;
08289 }
08290 else if(m == 3){
08291 dflmd = REM_MODE_LSB;
08292 if(d < 50000)
08293 return -1;
08294 }
08295 else if(m == 7){
08296 dflmd = REM_MODE_LSB;
08297 if(d > 30000)
08298 return -1;
08299 }
08300 else if(m == 14){
08301 dflmd = REM_MODE_USB;
08302 if(d > 35000)
08303 return -1;
08304 }
08305 else if(m == 18){
08306 dflmd = REM_MODE_USB;
08307 if((d < 6800) || (d > 16800))
08308 return -1;
08309 }
08310 else if(m == 21){
08311 dflmd = REM_MODE_USB;
08312 if((d < 20000) || (d > 45000))
08313 return -1;
08314 }
08315 else if(m == 24){
08316 dflmd = REM_MODE_USB;
08317 if((d < 89000) || (d > 99000))
08318 return -1;
08319 }
08320 else if(m == 28){
08321 dflmd = REM_MODE_USB;
08322 }
08323 else if(m == 29){
08324 if(d >= 51000)
08325 dflmd = REM_MODE_FM;
08326 else
08327 dflmd = REM_MODE_USB;
08328 if(d > 70000)
08329 return -1;
08330 }
08331 else if(m == 50){
08332 if(d >= 30000)
08333 dflmd = REM_MODE_FM;
08334 else
08335 dflmd = REM_MODE_USB;
08336
08337 }
08338 else if((m >= 51) && ( m < 54)){
08339 dflmd = REM_MODE_FM;
08340 }
08341 else if(m == 144){
08342 if(d >= 30000)
08343 dflmd = REM_MODE_FM;
08344 else
08345 dflmd = REM_MODE_USB;
08346 }
08347 else if((m >= 145) && (m < 148)){
08348 dflmd = REM_MODE_FM;
08349 }
08350 else if((m >= 430) && (m < 450)){
08351 if(m < 438)
08352 dflmd = REM_MODE_USB;
08353 else
08354 dflmd = REM_MODE_FM;
08355 ;
08356 }
08357 else
08358 return -1;
08359
08360 if(defmode)
08361 *defmode = dflmd;
08362
08363 return 0;
08364 }
08365
08366
08367
08368
08369
08370 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08371 {
08372 unsigned char cmdstr[5];
08373 int fd,m,d;
08374 char mhz[MAXREMSTR];
08375 char decimals[MAXREMSTR];
08376
08377 fd = 0;
08378 if(debug)
08379 printf("New frequency: %s\n",newfreq);
08380
08381 if(split_freq(mhz, decimals, newfreq))
08382 return -1;
08383
08384 m = atoi(mhz);
08385 d = atoi(decimals);
08386
08387
08388
08389 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08390 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08391 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08392 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08393 cmdstr[4] = 0x01;
08394
08395 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08396
08397 }
08398
08399
08400
08401 static int simple_command_ft897(struct rpt *myrpt, char command)
08402 {
08403 unsigned char cmdstr[5];
08404
08405 memset(cmdstr, 0, 5);
08406
08407 cmdstr[4] = command;
08408
08409 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08410
08411 }
08412
08413
08414
08415 static int set_offset_ft897(struct rpt *myrpt, char offset)
08416 {
08417 unsigned char cmdstr[5];
08418
08419 memset(cmdstr, 0, 5);
08420
08421 switch(offset){
08422 case REM_SIMPLEX:
08423 cmdstr[0] = 0x89;
08424 break;
08425
08426 case REM_MINUS:
08427 cmdstr[0] = 0x09;
08428 break;
08429
08430 case REM_PLUS:
08431 cmdstr[0] = 0x49;
08432 break;
08433
08434 default:
08435 return -1;
08436 }
08437
08438 cmdstr[4] = 0x09;
08439
08440 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08441 }
08442
08443
08444
08445 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08446 {
08447 unsigned char cmdstr[5];
08448
08449 memset(cmdstr, 0, 5);
08450
08451 switch(newmode){
08452 case REM_MODE_FM:
08453 cmdstr[0] = 0x08;
08454 break;
08455
08456 case REM_MODE_USB:
08457 cmdstr[0] = 0x01;
08458 break;
08459
08460 case REM_MODE_LSB:
08461 cmdstr[0] = 0x00;
08462 break;
08463
08464 case REM_MODE_AM:
08465 cmdstr[0] = 0x04;
08466 break;
08467
08468 default:
08469 return -1;
08470 }
08471 cmdstr[4] = 0x07;
08472
08473 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08474 }
08475
08476
08477
08478 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08479 {
08480 unsigned char cmdstr[5];
08481
08482 memset(cmdstr, 0, 5);
08483
08484 if(rxplon && txplon)
08485 cmdstr[0] = 0x2A;
08486 else if (!rxplon && txplon)
08487 cmdstr[0] = 0x4A;
08488 else if (rxplon && !txplon)
08489 cmdstr[0] = 0x3A;
08490 else
08491 cmdstr[0] = 0x8A;
08492
08493 cmdstr[4] = 0x0A;
08494
08495 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08496 }
08497
08498
08499
08500
08501 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08502 {
08503 unsigned char cmdstr[5];
08504 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08505 int h,d;
08506
08507 memset(cmdstr, 0, 5);
08508
08509 if(split_ctcss_freq(hertz, decimal, txtone))
08510 return -1;
08511
08512 h = atoi(hertz);
08513 d = atoi(decimal);
08514
08515 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08516 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08517
08518 if(rxtone){
08519
08520 if(split_ctcss_freq(hertz, decimal, rxtone))
08521 return -1;
08522
08523 h = atoi(hertz);
08524 d = atoi(decimal);
08525
08526 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08527 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08528 }
08529 cmdstr[4] = 0x0B;
08530
08531 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08532 }
08533
08534
08535
08536 static int set_ft897(struct rpt *myrpt)
08537 {
08538 int res;
08539
08540 if(debug)
08541 printf("@@@@ lock on\n");
08542
08543 res = simple_command_ft897(myrpt, 0x00);
08544
08545 if(debug)
08546 printf("@@@@ ptt off\n");
08547
08548 if(!res)
08549 res = simple_command_ft897(myrpt, 0x88);
08550
08551 if(debug)
08552 printf("Modulation mode\n");
08553
08554 if(!res)
08555 res = set_mode_ft897(myrpt, myrpt->remmode);
08556
08557 if(debug)
08558 printf("Split off\n");
08559
08560 if(!res)
08561 simple_command_ft897(myrpt, 0x82);
08562
08563 if(debug)
08564 printf("Frequency\n");
08565
08566 if(!res)
08567 res = set_freq_ft897(myrpt, myrpt->freq);
08568 if((myrpt->remmode == REM_MODE_FM)){
08569 if(debug)
08570 printf("Offset\n");
08571 if(!res)
08572 res = set_offset_ft897(myrpt, myrpt->offset);
08573 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08574 if(debug)
08575 printf("CTCSS tone freqs.\n");
08576 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08577 }
08578 if(!res){
08579 if(debug)
08580 printf("CTCSS mode\n");
08581 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08582 }
08583 }
08584 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08585 if(debug)
08586 printf("Clarifier off\n");
08587 simple_command_ft897(myrpt, 0x85);
08588 }
08589 return res;
08590 }
08591
08592 static int closerem_ft897(struct rpt *myrpt)
08593 {
08594 simple_command_ft897(myrpt, 0x88);
08595 return 0;
08596 }
08597
08598
08599
08600
08601
08602
08603
08604 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08605 {
08606 int m,d;
08607 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08608
08609 if(debug)
08610 printf("Before bump: %s\n", myrpt->freq);
08611
08612 if(split_freq(mhz, decimals, myrpt->freq))
08613 return -1;
08614
08615 m = atoi(mhz);
08616 d = atoi(decimals);
08617
08618 d += (interval / 10);
08619 if(d < 0){
08620 m--;
08621 d += 100000;
08622 }
08623 else if(d >= 100000){
08624 m++;
08625 d -= 100000;
08626 }
08627
08628 if(check_freq_ft897(m, d, NULL)){
08629 if(debug)
08630 printf("Bump freq invalid\n");
08631 return -1;
08632 }
08633
08634 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08635
08636 if(debug)
08637 printf("After bump: %s\n", myrpt->freq);
08638
08639 return set_freq_ft897(myrpt, myrpt->freq);
08640 }
08641
08642
08643
08644
08645
08646
08647
08648
08649
08650
08651 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08652 {
08653 int dflmd = REM_MODE_FM;
08654 int rv=0;
08655
08656 if(debug > 6)
08657 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08658
08659
08660
08661 if(m == 1){
08662 dflmd = REM_MODE_LSB;
08663 if(d < 80000)rv=-1;
08664 }
08665 else if(m == 3){
08666 dflmd = REM_MODE_LSB;
08667 if(d < 50000)rv=-1;
08668 }
08669 else if(m == 7){
08670 dflmd = REM_MODE_LSB;
08671 if(d > 30000)rv=-1;
08672 }
08673 else if(m == 14){
08674 dflmd = REM_MODE_USB;
08675 if(d > 35000)rv=-1;
08676 }
08677 else if(m == 18){
08678 dflmd = REM_MODE_USB;
08679 if((d < 6800) || (d > 16800))rv=-1;
08680 }
08681 else if(m == 21){
08682 dflmd = REM_MODE_USB;
08683 if((d < 20000) || (d > 45000))rv=-1;
08684 }
08685 else if(m == 24){
08686 dflmd = REM_MODE_USB;
08687 if((d < 89000) || (d > 99000))rv=-1;
08688 }
08689 else if(m == 28){
08690 dflmd = REM_MODE_USB;
08691 }
08692 else if(m == 29){
08693 if(d >= 51000)
08694 dflmd = REM_MODE_FM;
08695 else
08696 dflmd = REM_MODE_USB;
08697 if(d > 70000)rv=-1;
08698 }
08699 else if(m == 50){
08700 if(d >= 30000)
08701 dflmd = REM_MODE_FM;
08702 else
08703 dflmd = REM_MODE_USB;
08704 }
08705 else if((m >= 51) && ( m < 54)){
08706 dflmd = REM_MODE_FM;
08707 }
08708 else if(m == 144){
08709 if(d >= 30000)
08710 dflmd = REM_MODE_FM;
08711 else
08712 dflmd = REM_MODE_USB;
08713 }
08714 else if((m >= 145) && (m < 148)){
08715 dflmd = REM_MODE_FM;
08716 }
08717 else if((m >= 430) && (m < 450)){
08718 if(m < 438)
08719 dflmd = REM_MODE_USB;
08720 else
08721 dflmd = REM_MODE_FM;
08722 }
08723
08724
08725 if(mars && rv<0){
08726 if((m >= 450) && (m < 470)){
08727 dflmd = REM_MODE_FM;
08728 rv=0;
08729 }
08730 else if((m >= 148) && (m < 174)){
08731 dflmd = REM_MODE_FM;
08732 rv=0;
08733 }
08734 else if((m >= 138) && (m < 144)){
08735 dflmd = REM_MODE_AM;
08736 rv=0;
08737 }
08738 else if((m >= 108) && (m < 138)){
08739 dflmd = REM_MODE_AM;
08740 rv=0;
08741 }
08742 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08743 dflmd = REM_MODE_AM;
08744 rv=0;
08745 }
08746 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08747 dflmd = REM_MODE_AM;
08748 rv=0;
08749 }
08750 }
08751
08752 if(defmode)
08753 *defmode = dflmd;
08754
08755 if(debug > 1)
08756 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08757
08758 return rv;
08759 }
08760
08761
08762 static int ic706_pltocode(char *str)
08763 {
08764 int i;
08765 char *s;
08766 int rv=-1;
08767
08768 s = strchr(str,'.');
08769 i = 0;
08770 if (s) i = atoi(s + 1);
08771 i += atoi(str) * 10;
08772 switch(i)
08773 {
08774 case 670:
08775 rv=0;
08776 case 693:
08777 rv=1;
08778 case 719:
08779 rv=2;
08780 case 744:
08781 rv=3;
08782 case 770:
08783 rv=4;
08784 case 797:
08785 rv=5;
08786 case 825:
08787 rv=6;
08788 case 854:
08789 rv=7;
08790 case 885:
08791 rv=8;
08792 case 915:
08793 rv=9;
08794 case 948:
08795 rv=10;
08796 case 974:
08797 rv=11;
08798 case 1000:
08799 rv=12;
08800 case 1035:
08801 rv=13;
08802 case 1072:
08803 rv=14;
08804 case 1109:
08805 rv=15;
08806 case 1148:
08807 rv=16;
08808 case 1188:
08809 rv=17;
08810 case 1230:
08811 rv=18;
08812 case 1273:
08813 rv=19;
08814 case 1318:
08815 rv=20;
08816 case 1365:
08817 rv=21;
08818 case 1413:
08819 rv=22;
08820 case 1462:
08821 rv=23;
08822 case 1514:
08823 rv=24;
08824 case 1567:
08825 rv=25;
08826 case 1598:
08827 rv=26;
08828 case 1622:
08829 rv=27;
08830 case 1655:
08831 rv=28;
08832 case 1679:
08833 rv=29;
08834 case 1713:
08835 rv=30;
08836 case 1738:
08837 rv=31;
08838 case 1773:
08839 rv=32;
08840 case 1799:
08841 rv=33;
08842 case 1835:
08843 rv=34;
08844 case 1862:
08845 rv=35;
08846 case 1899:
08847 rv=36;
08848 case 1928:
08849 rv=37;
08850 case 1966:
08851 rv=38;
08852 case 1995:
08853 rv=39;
08854 case 2035:
08855 rv=40;
08856 case 2065:
08857 rv=41;
08858 case 2107:
08859 rv=42;
08860 case 2181:
08861 rv=43;
08862 case 2257:
08863 rv=44;
08864 case 2291:
08865 rv=45;
08866 case 2336:
08867 rv=46;
08868 case 2418:
08869 rv=47;
08870 case 2503:
08871 rv=48;
08872 case 2541:
08873 rv=49;
08874 }
08875 if(debug > 1)
08876 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08877
08878 return rv;
08879 }
08880
08881
08882
08883 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08884 {
08885 unsigned char cmdstr[10];
08886
08887 cmdstr[0] = cmdstr[1] = 0xfe;
08888 cmdstr[2] = myrpt->p.civaddr;
08889 cmdstr[3] = 0xe0;
08890 cmdstr[4] = command;
08891 cmdstr[5] = subcommand;
08892 cmdstr[6] = 0xfd;
08893
08894 return(civ_cmd(myrpt,cmdstr,7));
08895 }
08896
08897
08898
08899
08900
08901 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08902 {
08903 unsigned char cmdstr[20];
08904 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08905 int fd,m,d;
08906
08907 fd = 0;
08908 if(debug)
08909 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08910
08911 if(split_freq(mhz, decimals, newfreq))
08912 return -1;
08913
08914 m = atoi(mhz);
08915 d = atoi(decimals);
08916
08917
08918
08919 cmdstr[0] = cmdstr[1] = 0xfe;
08920 cmdstr[2] = myrpt->p.civaddr;
08921 cmdstr[3] = 0xe0;
08922 cmdstr[4] = 5;
08923 cmdstr[5] = ((d % 10) << 4);
08924 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08925 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08926 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08927 cmdstr[9] = (m / 100);
08928 cmdstr[10] = 0xfd;
08929
08930 return(civ_cmd(myrpt,cmdstr,11));
08931 }
08932
08933
08934
08935 static int set_offset_ic706(struct rpt *myrpt, char offset)
08936 {
08937 unsigned char c;
08938
08939 if(debug > 6)
08940 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08941
08942 switch(offset){
08943 case REM_SIMPLEX:
08944 c = 0x10;
08945 break;
08946
08947 case REM_MINUS:
08948 c = 0x11;
08949 break;
08950
08951 case REM_PLUS:
08952 c = 0x12;
08953 break;
08954
08955 default:
08956 return -1;
08957 }
08958
08959 return simple_command_ic706(myrpt,0x0f,c);
08960
08961 }
08962
08963
08964
08965 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08966 {
08967 unsigned char c;
08968
08969 if(debug > 6)
08970 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08971
08972 switch(newmode){
08973 case REM_MODE_FM:
08974 c = 5;
08975 break;
08976
08977 case REM_MODE_USB:
08978 c = 1;
08979 break;
08980
08981 case REM_MODE_LSB:
08982 c = 0;
08983 break;
08984
08985 case REM_MODE_AM:
08986 c = 2;
08987 break;
08988
08989 default:
08990 return -1;
08991 }
08992 return simple_command_ic706(myrpt,6,c);
08993 }
08994
08995
08996
08997 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08998 {
08999 unsigned char cmdstr[10];
09000 int rv;
09001
09002 if(debug > 6)
09003 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
09004
09005 cmdstr[0] = cmdstr[1] = 0xfe;
09006 cmdstr[2] = myrpt->p.civaddr;
09007 cmdstr[3] = 0xe0;
09008 cmdstr[4] = 0x16;
09009 cmdstr[5] = 0x42;
09010 cmdstr[6] = (txplon != 0);
09011 cmdstr[7] = 0xfd;
09012
09013 rv = civ_cmd(myrpt,cmdstr,8);
09014 if (rv) return(-1);
09015
09016 cmdstr[0] = cmdstr[1] = 0xfe;
09017 cmdstr[2] = myrpt->p.civaddr;
09018 cmdstr[3] = 0xe0;
09019 cmdstr[4] = 0x16;
09020 cmdstr[5] = 0x43;
09021 cmdstr[6] = (rxplon != 0);
09022 cmdstr[7] = 0xfd;
09023
09024 return(civ_cmd(myrpt,cmdstr,8));
09025 }
09026
09027 #if 0
09028
09029
09030 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09031 {
09032 unsigned char cmdstr[10];
09033 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09034 int h,d,rv;
09035
09036 memset(cmdstr, 0, 5);
09037
09038 if(debug > 6)
09039 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09040
09041 if(split_ctcss_freq(hertz, decimal, txtone))
09042 return -1;
09043
09044 h = atoi(hertz);
09045 d = atoi(decimal);
09046
09047 cmdstr[0] = cmdstr[1] = 0xfe;
09048 cmdstr[2] = myrpt->p.civaddr;
09049 cmdstr[3] = 0xe0;
09050 cmdstr[4] = 0x1b;
09051 cmdstr[5] = 0;
09052 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09053 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09054 cmdstr[8] = 0xfd;
09055
09056 rv = civ_cmd(myrpt,cmdstr,9);
09057 if (rv) return(-1);
09058
09059 if (!rxtone) return(0);
09060
09061 if(split_ctcss_freq(hertz, decimal, rxtone))
09062 return -1;
09063
09064 h = atoi(hertz);
09065 d = atoi(decimal);
09066
09067 cmdstr[0] = cmdstr[1] = 0xfe;
09068 cmdstr[2] = myrpt->p.civaddr;
09069 cmdstr[3] = 0xe0;
09070 cmdstr[4] = 0x1b;
09071 cmdstr[5] = 1;
09072 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09073 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09074 cmdstr[8] = 0xfd;
09075 return(civ_cmd(myrpt,cmdstr,9));
09076 }
09077 #endif
09078
09079 static int vfo_ic706(struct rpt *myrpt)
09080 {
09081 unsigned char cmdstr[10];
09082
09083 cmdstr[0] = cmdstr[1] = 0xfe;
09084 cmdstr[2] = myrpt->p.civaddr;
09085 cmdstr[3] = 0xe0;
09086 cmdstr[4] = 7;
09087 cmdstr[5] = 0xfd;
09088
09089 return(civ_cmd(myrpt,cmdstr,6));
09090 }
09091
09092 static int mem2vfo_ic706(struct rpt *myrpt)
09093 {
09094 unsigned char cmdstr[10];
09095
09096 cmdstr[0] = cmdstr[1] = 0xfe;
09097 cmdstr[2] = myrpt->p.civaddr;
09098 cmdstr[3] = 0xe0;
09099 cmdstr[4] = 0x0a;
09100 cmdstr[5] = 0xfd;
09101
09102 return(civ_cmd(myrpt,cmdstr,6));
09103 }
09104
09105 static int select_mem_ic706(struct rpt *myrpt, int slot)
09106 {
09107 unsigned char cmdstr[10];
09108
09109 cmdstr[0] = cmdstr[1] = 0xfe;
09110 cmdstr[2] = myrpt->p.civaddr;
09111 cmdstr[3] = 0xe0;
09112 cmdstr[4] = 8;
09113 cmdstr[5] = 0;
09114 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09115 cmdstr[7] = 0xfd;
09116
09117 return(civ_cmd(myrpt,cmdstr,8));
09118 }
09119
09120 static int set_ic706(struct rpt *myrpt)
09121 {
09122 int res = 0,i;
09123
09124 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09125
09126 if (!res)
09127 res = simple_command_ic706(myrpt,7,0);
09128
09129 if((myrpt->remmode == REM_MODE_FM))
09130 {
09131 i = ic706_pltocode(myrpt->rxpl);
09132 if (i == -1) return -1;
09133 if(debug)
09134 printf("Select memory number\n");
09135 if (!res)
09136 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09137 if(debug)
09138 printf("Transfer memory to VFO\n");
09139 if (!res)
09140 res = mem2vfo_ic706(myrpt);
09141 }
09142
09143 if(debug)
09144 printf("Set to VFO\n");
09145
09146 if (!res)
09147 res = vfo_ic706(myrpt);
09148
09149 if(debug)
09150 printf("Modulation mode\n");
09151
09152 if (!res)
09153 res = set_mode_ic706(myrpt, myrpt->remmode);
09154
09155 if(debug)
09156 printf("Split off\n");
09157
09158 if(!res)
09159 simple_command_ic706(myrpt, 0x82,0);
09160
09161 if(debug)
09162 printf("Frequency\n");
09163
09164 if(!res)
09165 res = set_freq_ic706(myrpt, myrpt->freq);
09166 if((myrpt->remmode == REM_MODE_FM)){
09167 if(debug)
09168 printf("Offset\n");
09169 if(!res)
09170 res = set_offset_ic706(myrpt, myrpt->offset);
09171 if(!res){
09172 if(debug)
09173 printf("CTCSS mode\n");
09174 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09175 }
09176 }
09177 return res;
09178 }
09179
09180
09181
09182
09183
09184
09185
09186 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09187 {
09188 int m,d;
09189 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09190 unsigned char cmdstr[20];
09191
09192 if(debug)
09193 printf("Before bump: %s\n", myrpt->freq);
09194
09195 if(split_freq(mhz, decimals, myrpt->freq))
09196 return -1;
09197
09198 m = atoi(mhz);
09199 d = atoi(decimals);
09200
09201 d += (interval / 10);
09202 if(d < 0){
09203 m--;
09204 d += 100000;
09205 }
09206 else if(d >= 100000){
09207 m++;
09208 d -= 100000;
09209 }
09210
09211 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09212 if(debug)
09213 printf("Bump freq invalid\n");
09214 return -1;
09215 }
09216
09217 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09218
09219 if(debug)
09220 printf("After bump: %s\n", myrpt->freq);
09221
09222
09223
09224 cmdstr[0] = cmdstr[1] = 0xfe;
09225 cmdstr[2] = myrpt->p.civaddr;
09226 cmdstr[3] = 0xe0;
09227 cmdstr[4] = 0;
09228 cmdstr[5] = ((d % 10) << 4);
09229 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09230 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09231 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09232 cmdstr[9] = (m / 100);
09233 cmdstr[10] = 0xfd;
09234
09235 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09236 }
09237
09238
09239
09240
09241
09242
09243 static int setrem(struct rpt *myrpt)
09244 {
09245 char str[300];
09246 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09247 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09248 char *modes[] = {"FM","USB","LSB","AM"};
09249 int res = -1;
09250
09251 #if 0
09252 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09253 modes[(int)myrpt->remmode],
09254 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09255 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09256 myrpt->rxplon);
09257 #endif
09258 if (myrpt->p.archivedir)
09259 {
09260 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09261 modes[(int)myrpt->remmode],
09262 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09263 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09264 myrpt->rxplon);
09265 donodelog(myrpt,str);
09266 }
09267 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09268 {
09269 rpt_telemetry(myrpt,SETREMOTE,NULL);
09270 res = 0;
09271 }
09272 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09273 {
09274 rpt_telemetry(myrpt,SETREMOTE,NULL);
09275 res = 0;
09276 }
09277 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09278 {
09279 rpt_telemetry(myrpt,SETREMOTE,NULL);
09280 res = 0;
09281 }
09282 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09283 {
09284 res = setrbi_check(myrpt);
09285 if (!res)
09286 {
09287 rpt_telemetry(myrpt,SETREMOTE,NULL);
09288 res = 0;
09289 }
09290 }
09291 else if(ISRIG_RTX(myrpt->remoterig))
09292 {
09293 setrtx(myrpt);
09294 res = 0;
09295 }
09296 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09297 rpt_telemetry(myrpt,SETREMOTE,NULL);
09298 res = 0;
09299 }
09300 else
09301 res = 0;
09302
09303 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09304
09305 return res;
09306 }
09307
09308 static int closerem(struct rpt *myrpt)
09309 {
09310 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09311 return closerem_ft897(myrpt);
09312 else
09313 return 0;
09314 }
09315
09316
09317
09318
09319
09320 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09321 {
09322 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09323 return check_freq_ft897(m, d, defmode);
09324 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09325 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09326 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09327 return check_freq_rbi(m, d, defmode);
09328 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09329 return check_freq_kenwood(m, d, defmode);
09330 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09331 return check_freq_tm271(m, d, defmode);
09332 else if(ISRIG_RTX(myrpt->remoterig))
09333 return check_freq_rtx(m, d, defmode, myrpt);
09334 else
09335 return -1;
09336 }
09337
09338
09339
09340
09341
09342
09343 static char check_tx_freq(struct rpt *myrpt)
09344 {
09345 int i,rv=0;
09346 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09347 char radio_mhz_char[MAXREMSTR];
09348 char radio_decimals_char[MAXREMSTR];
09349 char limit_mhz_char[MAXREMSTR];
09350 char limit_decimals_char[MAXREMSTR];
09351 char limits[256];
09352 char *limit_ranges[40];
09353 struct ast_variable *limitlist;
09354
09355 if(debug > 3){
09356 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09357 }
09358
09359
09360
09361 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09362 if(debug > 3){
09363 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09364 }
09365 rv=1;
09366 return 1;
09367 }
09368
09369
09370 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09371
09372 if(!limitlist){
09373 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09374 rv=0;
09375 return 0;
09376 }
09377
09378 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09379 radio_mhz = atoi(radio_mhz_char);
09380 radio_decimals = decimals2int(radio_decimals_char);
09381
09382 if(debug > 3){
09383 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09384 }
09385
09386
09387
09388 for(;limitlist; limitlist=limitlist->next){
09389 if(!strcmp(limitlist->name, myrpt->loginlevel))
09390 break;
09391 }
09392
09393 if(!limitlist){
09394 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09395 rv=0;
09396 return 0;
09397 }
09398
09399 if(debug > 3){
09400 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09401 }
09402
09403
09404
09405 strncpy(limits, limitlist->value, 256);
09406 limits[255] = 0;
09407 finddelim(limits, limit_ranges, 40);
09408 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09409 char range[40];
09410 char *r,*s;
09411 strncpy(range, limit_ranges[i], 40);
09412 range[39] = 0;
09413 if(debug > 3)
09414 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09415
09416 r = strchr(range, '-');
09417 if(!r){
09418 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09419 rv=0;
09420 break;
09421 }
09422 *r++ = 0;
09423 s = eatwhite(range);
09424 r = eatwhite(r);
09425 split_freq(limit_mhz_char, limit_decimals_char, s);
09426 llimit_mhz = atoi(limit_mhz_char);
09427 llimit_decimals = decimals2int(limit_decimals_char);
09428 split_freq(limit_mhz_char, limit_decimals_char, r);
09429 ulimit_mhz = atoi(limit_mhz_char);
09430 ulimit_decimals = decimals2int(limit_decimals_char);
09431
09432 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09433 if(radio_mhz == llimit_mhz){
09434 if(radio_decimals >= llimit_decimals){
09435 if(llimit_mhz == ulimit_mhz){
09436 if(radio_decimals <= ulimit_decimals){
09437 rv=1;
09438 break;
09439 }
09440 else{
09441 if(debug > 3)
09442 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09443 rv=0;
09444 break;
09445 }
09446 }
09447 else{
09448 rv=1;
09449 break;
09450 }
09451 }
09452 else{
09453 if(debug > 3)
09454 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09455 rv=0;
09456 break;
09457 }
09458 }
09459 else if(radio_mhz == ulimit_mhz){
09460 if(radio_decimals <= ulimit_decimals){
09461 if(debug > 3)
09462 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09463 rv=1;
09464 break;
09465 }
09466 else{
09467 if(debug > 3)
09468 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09469 rv=0;
09470 break;
09471 }
09472 }
09473 else
09474 if(debug > 3)
09475 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09476 rv=1;
09477 break;
09478 }
09479 }
09480 if(debug > 3)
09481 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09482
09483 return rv;
09484 }
09485
09486
09487
09488
09489
09490
09491 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09492 {
09493 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09494 return multimode_bump_freq_ft897(myrpt, interval);
09495 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09496 return multimode_bump_freq_ic706(myrpt, interval);
09497 else
09498 return -1;
09499 }
09500
09501
09502
09503
09504
09505
09506 static void stop_scan(struct rpt *myrpt)
09507 {
09508 myrpt->hfscanstop = 1;
09509 rpt_telemetry(myrpt,SCAN,0);
09510 }
09511
09512
09513
09514
09515
09516
09517 static int service_scan(struct rpt *myrpt)
09518 {
09519 int res, interval;
09520 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09521
09522 switch(myrpt->hfscanmode){
09523
09524 case HF_SCAN_DOWN_SLOW:
09525 interval = -10;
09526 break;
09527
09528 case HF_SCAN_DOWN_QUICK:
09529 interval = -50;
09530 break;
09531
09532 case HF_SCAN_DOWN_FAST:
09533 interval = -200;
09534 break;
09535
09536 case HF_SCAN_UP_SLOW:
09537 interval = 10;
09538 break;
09539
09540 case HF_SCAN_UP_QUICK:
09541 interval = 50;
09542 break;
09543
09544 case HF_SCAN_UP_FAST:
09545 interval = 200;
09546 break;
09547
09548 default:
09549 myrpt->hfscanmode = 0;
09550 return -1;
09551 }
09552
09553 res = split_freq(mhz, decimals, myrpt->freq);
09554
09555 if(!res){
09556 k100 =decimals[0];
09557 k10 = decimals[1];
09558 res = multimode_bump_freq(myrpt, interval);
09559 }
09560
09561 if(!res)
09562 res = split_freq(mhz, decimals, myrpt->freq);
09563
09564
09565 if(res){
09566 myrpt->hfscanmode = 0;
09567 myrpt->hfscanstatus = -2;
09568 return -1;
09569 }
09570
09571
09572 if(k10 != decimals[1]){
09573 int myhund = (interval < 0) ? k100 : decimals[0];
09574 int myten = (interval < 0) ? k10 : decimals[1];
09575 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09576 } else myrpt->hfscanstatus = 0;
09577 return res;
09578
09579 }
09580
09581
09582
09583 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09584 {
09585 int res=0;
09586 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09587 res = retreive_memory(myrpt, digitbuf);
09588 if(!res)res=setrem(myrpt);
09589 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09590 return res;
09591 }
09592
09593
09594
09595
09596 static int channel_steer(struct rpt *myrpt, char *data)
09597 {
09598 int res=0;
09599
09600 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09601 if (!myrpt->remoterig) return(0);
09602 if(data<=0)
09603 {
09604 res=-1;
09605 }
09606 else
09607 {
09608 myrpt->nowchan=strtod(data,NULL);
09609 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09610 {
09611 char string[16];
09612 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09613 send_usb_txt(myrpt,string);
09614 }
09615 else
09616 {
09617 if(get_mem_set(myrpt, data))res=-1;
09618 }
09619 }
09620 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09621 return res;
09622 }
09623
09624
09625 static int channel_revert(struct rpt *myrpt)
09626 {
09627 int res=0;
09628 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09629 if (!myrpt->remoterig) return(0);
09630 if(myrpt->nowchan!=myrpt->waschan)
09631 {
09632 char data[8];
09633 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09634 sprintf(data,"%02d",myrpt->waschan);
09635 myrpt->nowchan=myrpt->waschan;
09636 channel_steer(myrpt,data);
09637 res=1;
09638 }
09639 return(res);
09640 }
09641
09642
09643
09644
09645 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09646 {
09647 char *s,*s1,*s2;
09648 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09649 intptr_t p;
09650 char multimode = 0;
09651 char oc,*cp,*cp1,*cp2;
09652 char tmp[20], freq[20] = "", savestr[20] = "";
09653 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09654
09655 if(debug > 6) {
09656 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09657 }
09658
09659 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09660 return DC_ERROR;
09661
09662 p = myatoi(param);
09663
09664 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09665 (!myrpt->loginlevel[0])) return DC_ERROR;
09666 multimode = multimode_capable(myrpt);
09667
09668 switch(p){
09669
09670 case 1:
09671 if(strlen(digitbuf) < 2)
09672 break;
09673
09674 for(i = 0 ; i < 2 ; i++){
09675 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09676 return DC_ERROR;
09677 }
09678 r=get_mem_set(myrpt, digitbuf);
09679 if (r < 0){
09680 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09681 return DC_COMPLETE;
09682 }
09683 else if (r > 0){
09684 return DC_ERROR;
09685 }
09686 return DC_COMPLETE;
09687
09688 case 2:
09689
09690
09691 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09692 if(digitbuf[i] == '*'){
09693 j++;
09694 continue;
09695 }
09696 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09697 goto invalid_freq;
09698 else{
09699 if(j == 0)
09700 l++;
09701 if(j == 1)
09702 k++;
09703 }
09704 }
09705
09706 i = strlen(digitbuf) - 1;
09707 if(multimode){
09708 if((j > 2) || (l > 3) || (k > 6))
09709 goto invalid_freq;
09710 }
09711 else{
09712 if((j > 2) || (l > 4) || (k > 3))
09713 goto invalid_freq;
09714 }
09715
09716
09717
09718 if(j < 2)
09719 break;
09720
09721
09722
09723 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09724
09725 s = tmp;
09726 s1 = strsep(&s, "*");
09727 s2 = strsep(&s,"*");
09728 ls2 = strlen(s2);
09729
09730 switch(ls2){
09731 case 1:
09732 ht = 0;
09733 k = 100 * atoi(s2);
09734 break;
09735
09736 case 2:
09737 ht = 0;
09738 k = 10 * atoi(s2);
09739 break;
09740
09741 case 3:
09742 if(!multimode){
09743 if((s2[2] != '0')&&(s2[2] != '5'))
09744 goto invalid_freq;
09745 }
09746 ht = 0;
09747 k = atoi(s2);
09748 break;
09749 case 4:
09750 k = atoi(s2)/10;
09751 ht = 10 * (atoi(s2+(ls2-1)));
09752 break;
09753
09754 case 5:
09755 k = atoi(s2)/100;
09756 ht = (atoi(s2+(ls2-2)));
09757 break;
09758
09759 default:
09760 goto invalid_freq;
09761 }
09762
09763
09764
09765 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09766
09767 if(debug)
09768 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09769
09770 split_freq(mhz, decimals, freq);
09771 m = atoi(mhz);
09772 d = atoi(decimals);
09773
09774 if(check_freq(myrpt, m, d, &defmode))
09775 goto invalid_freq;
09776
09777
09778 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09779 break;
09780
09781
09782 offset = REM_SIMPLEX;
09783
09784 if(defmode == REM_MODE_FM){
09785 oc = *s;
09786
09787 if (oc){
09788 switch(oc){
09789 case '1':
09790 offset = REM_MINUS;
09791 break;
09792
09793 case '2':
09794 offset = REM_SIMPLEX;
09795 break;
09796
09797 case '3':
09798 offset = REM_PLUS;
09799 break;
09800
09801 default:
09802 goto invalid_freq;
09803 }
09804 }
09805 }
09806 offsave = myrpt->offset;
09807 modesave = myrpt->remmode;
09808 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09809 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09810 myrpt->offset = offset;
09811 myrpt->remmode = defmode;
09812
09813 if (setrem(myrpt) == -1){
09814 myrpt->offset = offsave;
09815 myrpt->remmode = modesave;
09816 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09817 goto invalid_freq;
09818 }
09819
09820 return DC_COMPLETE;
09821
09822 invalid_freq:
09823 rpt_telemetry(myrpt,INVFREQ,NULL);
09824 return DC_ERROR;
09825
09826 case 3:
09827 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09828 if(digitbuf[i] == '*'){
09829 j++;
09830 continue;
09831 }
09832 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09833 return DC_ERROR;
09834 else{
09835 if(j)
09836 l++;
09837 else
09838 k++;
09839 }
09840 }
09841 if((j > 1) || (k > 3) || (l > 1))
09842 return DC_ERROR;
09843 i = strlen(digitbuf) - 1;
09844 if((j != 1) || (k < 2)|| (l != 1))
09845 break;
09846 if(debug)
09847 printf("PL digits entered %s\n", digitbuf);
09848
09849 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09850
09851 s = strchr(tmp,'*');
09852 if(s)
09853 *s = '.';
09854 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09855 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09856 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09857 {
09858 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09859 }
09860 if (setrem(myrpt) == -1){
09861 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09862 return DC_ERROR;
09863 }
09864 return DC_COMPLETE;
09865
09866 case 4:
09867
09868 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09869 return DC_ERROR;
09870
09871
09872
09873
09874
09875 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09876 {
09877 if(debug)
09878 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09879 return DC_ERROR;
09880 }
09881 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09882 if(digitbuf[i] == '*'){
09883 j++;
09884 continue;
09885 }
09886 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09887 return DC_ERROR;
09888 else{
09889 if(j)
09890 l++;
09891 else
09892 k++;
09893 }
09894 }
09895 if((j > 1) || (k > 3) || (l > 1))
09896 return DC_ERROR;
09897 i = strlen(digitbuf) - 1;
09898 if((j != 1) || (k < 2)|| (l != 1))
09899 break;
09900 if(debug)
09901 printf("PL digits entered %s\n", digitbuf);
09902
09903 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09904
09905 s = strchr(tmp,'*');
09906 if(s)
09907 *s = '.';
09908 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09909 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09910
09911 if (setrem(myrpt) == -1){
09912 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09913 return DC_ERROR;
09914 }
09915 return DC_COMPLETE;
09916
09917
09918 case 6:
09919 if(strlen(digitbuf) < 1)
09920 break;
09921
09922 if(!multimode)
09923 return DC_ERROR;
09924
09925 switch(*digitbuf){
09926 case '1':
09927 split_freq(mhz, decimals, myrpt->freq);
09928 m=atoi(mhz);
09929 if(m < 29)
09930 return DC_ERROR;
09931 myrpt->remmode = REM_MODE_FM;
09932
09933 rpt_telemetry(myrpt,REMMODE,NULL);
09934 break;
09935
09936 case '2':
09937 myrpt->remmode = REM_MODE_USB;
09938 rpt_telemetry(myrpt,REMMODE,NULL);
09939 break;
09940
09941 case '3':
09942 myrpt->remmode = REM_MODE_LSB;
09943 rpt_telemetry(myrpt,REMMODE,NULL);
09944 break;
09945
09946 case '4':
09947 myrpt->remmode = REM_MODE_AM;
09948 rpt_telemetry(myrpt,REMMODE,NULL);
09949 break;
09950
09951 default:
09952 return DC_ERROR;
09953 }
09954
09955 if(setrem(myrpt))
09956 return DC_ERROR;
09957 return DC_COMPLETEQUIET;
09958 case 99:
09959
09960 if (myrpt->loginlevel[0])
09961 return DC_ERROR;
09962 *myrpt->loginuser = 0;
09963 myrpt->loginlevel[0] = 0;
09964 cp = ast_strdup(param);
09965 cp1 = strchr(cp,',');
09966 ast_mutex_lock(&myrpt->lock);
09967 if (cp1)
09968 {
09969 *cp1 = 0;
09970 cp2 = strchr(cp1 + 1,',');
09971 if (cp2)
09972 {
09973 *cp2 = 0;
09974 strncpy(myrpt->loginlevel,cp2 + 1,
09975 sizeof(myrpt->loginlevel) - 1);
09976 }
09977 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09978 ast_mutex_unlock(&myrpt->lock);
09979 if (myrpt->p.archivedir)
09980 {
09981 char str[100];
09982
09983 sprintf(str,"LOGIN,%s,%s",
09984 myrpt->loginuser,myrpt->loginlevel);
09985 donodelog(myrpt,str);
09986 }
09987 if (debug)
09988 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09989 rpt_telemetry(myrpt,REMLOGIN,NULL);
09990 }
09991 ast_free(cp);
09992 return DC_COMPLETEQUIET;
09993 case 100:
09994 myrpt->rxplon = 0;
09995 setrem(myrpt);
09996 rpt_telemetry(myrpt,REMXXX,(void *)p);
09997 return DC_COMPLETEQUIET;
09998 case 101:
09999 myrpt->rxplon = 1;
10000 setrem(myrpt);
10001 rpt_telemetry(myrpt,REMXXX,(void *)p);
10002 return DC_COMPLETEQUIET;
10003 case 102:
10004 myrpt->txplon = 0;
10005 setrem(myrpt);
10006 rpt_telemetry(myrpt,REMXXX,(void *)p);
10007 return DC_COMPLETEQUIET;
10008 case 103:
10009 myrpt->txplon = 1;
10010 setrem(myrpt);
10011 rpt_telemetry(myrpt,REMXXX,(void *)p);
10012 return DC_COMPLETEQUIET;
10013 case 104:
10014 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10015 return DC_ERROR;
10016 myrpt->powerlevel = REM_LOWPWR;
10017 setrem(myrpt);
10018 rpt_telemetry(myrpt,REMXXX,(void *)p);
10019 return DC_COMPLETEQUIET;
10020 case 105:
10021 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10022 return DC_ERROR;
10023 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10024 myrpt->powerlevel = REM_MEDPWR;
10025 setrem(myrpt);
10026 rpt_telemetry(myrpt,REMXXX,(void *)p);
10027 return DC_COMPLETEQUIET;
10028 case 106:
10029 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10030 return DC_ERROR;
10031 myrpt->powerlevel = REM_HIPWR;
10032 setrem(myrpt);
10033 rpt_telemetry(myrpt,REMXXX,(void *)p);
10034 return DC_COMPLETEQUIET;
10035 case 107:
10036 multimode_bump_freq(myrpt, -20);
10037 return DC_COMPLETE;
10038 case 108:
10039 multimode_bump_freq(myrpt, -100);
10040 return DC_COMPLETE;
10041 case 109:
10042 multimode_bump_freq(myrpt, -500);
10043 return DC_COMPLETE;
10044 case 110:
10045 multimode_bump_freq(myrpt, 20);
10046 return DC_COMPLETE;
10047 case 111:
10048 multimode_bump_freq(myrpt, 100);
10049 return DC_COMPLETE;
10050 case 112:
10051 multimode_bump_freq(myrpt, 500);
10052 return DC_COMPLETE;
10053 case 113:
10054 myrpt->scantimer = REM_SCANTIME;
10055 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10056 rpt_telemetry(myrpt,REMXXX,(void *)p);
10057 return DC_COMPLETEQUIET;
10058 case 114:
10059 myrpt->scantimer = REM_SCANTIME;
10060 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10061 rpt_telemetry(myrpt,REMXXX,(void *)p);
10062 return DC_COMPLETEQUIET;
10063 case 115:
10064 myrpt->scantimer = REM_SCANTIME;
10065 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10066 rpt_telemetry(myrpt,REMXXX,(void *)p);
10067 return DC_COMPLETEQUIET;
10068 case 116:
10069 myrpt->scantimer = REM_SCANTIME;
10070 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10071 rpt_telemetry(myrpt,REMXXX,(void *)p);
10072 return DC_COMPLETEQUIET;
10073 case 117:
10074 myrpt->scantimer = REM_SCANTIME;
10075 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10076 rpt_telemetry(myrpt,REMXXX,(void *)p);
10077 return DC_COMPLETEQUIET;
10078 case 118:
10079 myrpt->scantimer = REM_SCANTIME;
10080 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10081 rpt_telemetry(myrpt,REMXXX,(void *)p);
10082 return DC_COMPLETEQUIET;
10083 case 119:
10084 if(debug > 3)
10085 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10086
10087 if((!myrpt->tunerequest) &&
10088 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10089 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10090 myrpt->remotetx = 0;
10091 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10092 myrpt->tunerequest = 1;
10093 rpt_telemetry(myrpt,TUNE,NULL);
10094 return DC_COMPLETEQUIET;
10095 }
10096 return DC_ERROR;
10097 case 5:
10098 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10099 return DC_COMPLETEQUIET;
10100 case 140:
10101 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10102 return DC_COMPLETEQUIET;
10103 case 200:
10104 case 201:
10105 case 202:
10106 case 203:
10107 case 204:
10108 case 205:
10109 case 206:
10110 case 207:
10111 case 208:
10112 case 209:
10113 case 210:
10114 case 211:
10115 case 212:
10116 case 213:
10117 case 214:
10118 case 215:
10119 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10120 return DC_COMPLETEQUIET;
10121 default:
10122 break;
10123 }
10124 return DC_INDETERMINATE;
10125 }
10126
10127
10128 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10129 {
10130 time_t now;
10131 int ret,res = 0,src;
10132
10133 if(debug > 6)
10134 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10135
10136 time(&myrpt->last_activity_time);
10137
10138 if(myrpt->hfscanmode){
10139 stop_scan(myrpt);
10140 return 0;
10141 }
10142
10143 time(&now);
10144
10145 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10146 {
10147 myrpt->dtmfidx = -1;
10148 myrpt->dtmfbuf[0] = 0;
10149 myrpt->dtmf_time_rem = 0;
10150 }
10151
10152 if (myrpt->dtmfidx == -1)
10153 {
10154
10155 if (c != myrpt->p.funcchar)
10156 {
10157 if (!myrpt->p.propagate_dtmf)
10158 {
10159 rpt_mutex_lock(&myrpt->lock);
10160 do_dtmf_local(myrpt,c);
10161 rpt_mutex_unlock(&myrpt->lock);
10162 }
10163 return 0;
10164 }
10165 myrpt->dtmfidx = 0;
10166 myrpt->dtmfbuf[0] = 0;
10167 myrpt->dtmf_time_rem = now;
10168 return 0;
10169 }
10170
10171 if (myrpt->dtmfidx >= MAXDTMF)
10172 {
10173 myrpt->dtmfidx = 0;
10174 myrpt->dtmfbuf[0] = 0;
10175 myrpt->dtmf_time_rem = now;
10176 }
10177 if (c == myrpt->p.funcchar)
10178 {
10179
10180 if ((myrpt->dtmfidx < 1) ||
10181 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10182 {
10183 myrpt->dtmfidx = 0;
10184 myrpt->dtmfbuf[0] = 0;
10185 myrpt->dtmf_time_rem = now;
10186 return 0;
10187 }
10188 }
10189 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10190 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10191 myrpt->dtmf_time_rem = now;
10192
10193
10194 src = SOURCE_RMT;
10195 if (phonemode == 2) src = SOURCE_DPHONE;
10196 else if (phonemode) src = SOURCE_PHONE;
10197 else if (phonemode == 4) src = SOURCE_ALT;
10198 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10199
10200 switch(ret){
10201
10202 case DC_INDETERMINATE:
10203 res = 0;
10204 break;
10205
10206 case DC_DOKEY:
10207 if (keyed) *keyed = 1;
10208 res = 0;
10209 break;
10210
10211 case DC_REQ_FLUSH:
10212 myrpt->dtmfidx = 0;
10213 myrpt->dtmfbuf[0] = 0;
10214 res = 0;
10215 break;
10216
10217
10218 case DC_COMPLETE:
10219 res = 1;
10220 case DC_COMPLETEQUIET:
10221 myrpt->totalexecdcommands++;
10222 myrpt->dailyexecdcommands++;
10223 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10224 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10225 myrpt->dtmfbuf[0] = 0;
10226 myrpt->dtmfidx = -1;
10227 myrpt->dtmf_time_rem = 0;
10228 break;
10229
10230 case DC_ERROR:
10231 default:
10232 myrpt->dtmfbuf[0] = 0;
10233 myrpt->dtmfidx = -1;
10234 myrpt->dtmf_time_rem = 0;
10235 res = 0;
10236 break;
10237 }
10238
10239 return res;
10240 }
10241
10242 static int handle_remote_data(struct rpt *myrpt, char *str)
10243 {
10244
10245
10246 char tmp[300],cmd[300],dest[300],src[300],c;
10247 int seq,res;
10248
10249
10250 strncpy(tmp,str,sizeof(tmp) - 1);
10251 if (!strcmp(tmp,discstr)) return 0;
10252 if (!strcmp(tmp,newkeystr))
10253 {
10254 myrpt->newkey = 1;
10255 return 0;
10256 }
10257
10258 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10259 if (tmp[0] == 'I')
10260 {
10261
10262
10263 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10264 {
10265 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10266 return 0;
10267 }
10268 mdc1200_notify(myrpt,src,seq);
10269 return 0;
10270 }
10271 #endif
10272
10273
10274 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10275 {
10276 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10277 return 0;
10278 }
10279 if (strcmp(cmd,"D"))
10280 {
10281 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10282 return 0;
10283 }
10284
10285 if (strcmp(dest,myrpt->name)) return 0;
10286 if (myrpt->p.archivedir)
10287 {
10288 char dtmfstr[100];
10289
10290 sprintf(dtmfstr,"DTMF,%c",c);
10291 donodelog(myrpt,dtmfstr);
10292 }
10293 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10294 if (!c) return(0);
10295 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10296 if (res != 1)
10297 return res;
10298 rpt_telemetry(myrpt,COMPLETE,NULL);
10299 return 0;
10300 }
10301
10302 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10303 {
10304 int res;
10305
10306
10307 if(phonemode == 3)
10308 {
10309 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10310 {
10311 *keyed = 0;
10312 return 0;
10313 }
10314 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10315 {
10316 *keyed = 1;
10317 return 0;
10318 }
10319 }
10320 else
10321 {
10322
10323 if (keyed && *keyed && (c == myrpt->p.endchar))
10324 {
10325 *keyed = 0;
10326 return DC_INDETERMINATE;
10327 }
10328 }
10329 if (myrpt->p.archivedir)
10330 {
10331 char str[100];
10332
10333 sprintf(str,"DTMF(P),%c",c);
10334 donodelog(myrpt,str);
10335 }
10336 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10337 if (res != 1)
10338 return res;
10339 rpt_telemetry(myrpt,COMPLETE,NULL);
10340 return 0;
10341 }
10342
10343 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10344 {
10345 char *val, *s, *s1, *s2, *tele;
10346 char tmp[300], deststr[300] = "";
10347 char sx[320],*sy;
10348
10349
10350 val = node_lookup(myrpt,l->name);
10351 if (!val)
10352 {
10353 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10354 return -1;
10355 }
10356
10357 rpt_mutex_lock(&myrpt->lock);
10358
10359 remque((struct qelem *) l);
10360 rpt_mutex_unlock(&myrpt->lock);
10361 strncpy(tmp,val,sizeof(tmp) - 1);
10362 s = tmp;
10363 s1 = strsep(&s,",");
10364 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10365 {
10366 sy = strchr(s1,'/');
10367 *sy = 0;
10368 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10369 s1 = sx;
10370 }
10371 s2 = strsep(&s,",");
10372 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10373 tele = strchr(deststr, '/');
10374 if (!tele) {
10375 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10376 return -1;
10377 }
10378 *tele++ = 0;
10379 l->elaptime = 0;
10380 l->connecttime = 0;
10381 l->thisconnected = 0;
10382 l->newkey = 0;
10383 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10384 if (l->chan){
10385 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10386 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10387 #ifndef NEW_ASTERISK
10388 l->chan->whentohangup = 0;
10389 #endif
10390 l->chan->appl = "Apprpt";
10391 l->chan->data = "(Remote Rx)";
10392 if (option_verbose > 2)
10393 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10394 deststr, tele, l->chan->name);
10395 l->chan->caller.id.number.valid = 1;
10396 ast_free(l->chan->caller.id.number.str);
10397 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
10398 ast_call(l->chan,tele,999);
10399
10400 }
10401 else
10402 {
10403 if (option_verbose > 2)
10404 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10405 deststr,tele,l->chan->name);
10406 return -1;
10407 }
10408 rpt_mutex_lock(&myrpt->lock);
10409
10410 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10411 rpt_mutex_unlock(&myrpt->lock);
10412 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10413 if (!l->phonemode) send_newkey(l->chan);
10414 return 0;
10415 }
10416
10417
10418 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10419 {
10420 int res;
10421 pthread_attr_t attr;
10422 char cmd[MAXDTMF+1] = "",c;
10423
10424
10425 c = c_in & 0x7f;
10426 if (myrpt->p.archivedir)
10427 {
10428 char str[100];
10429
10430 sprintf(str,"DTMF,MAIN,%c",c);
10431 donodelog(myrpt,str);
10432 }
10433 if (c == myrpt->p.endchar)
10434 {
10435
10436 if (myrpt->p.simple && myrpt->callmode)
10437 {
10438 if(debug)
10439 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10440 rpt_mutex_lock(&myrpt->lock);
10441 myrpt->callmode = 0;
10442 myrpt->macropatch=0;
10443 channel_revert(myrpt);
10444 rpt_mutex_unlock(&myrpt->lock);
10445 rpt_telemetry(myrpt,TERM,NULL);
10446 return;
10447 }
10448 rpt_mutex_lock(&myrpt->lock);
10449 myrpt->stopgen = 1;
10450 if (myrpt->cmdnode[0])
10451 {
10452 myrpt->cmdnode[0] = 0;
10453 myrpt->dtmfidx = -1;
10454 myrpt->dtmfbuf[0] = 0;
10455 rpt_mutex_unlock(&myrpt->lock);
10456 rpt_telemetry(myrpt,COMPLETE,NULL);
10457 return;
10458 }
10459 else if(!myrpt->inpadtest)
10460 {
10461 rpt_mutex_unlock(&myrpt->lock);
10462 if (myrpt->p.propagate_phonedtmf)
10463 do_dtmf_phone(myrpt,NULL,c);
10464 return;
10465 }
10466 else
10467 rpt_mutex_unlock(&myrpt->lock);
10468 }
10469 rpt_mutex_lock(&myrpt->lock);
10470 if (myrpt->cmdnode[0])
10471 {
10472 rpt_mutex_unlock(&myrpt->lock);
10473 send_link_dtmf(myrpt,c);
10474 return;
10475 }
10476 if (!myrpt->p.simple)
10477 {
10478 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10479 {
10480 myrpt->dtmfidx = 0;
10481 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10482 rpt_mutex_unlock(&myrpt->lock);
10483 time(&myrpt->dtmf_time);
10484 return;
10485 }
10486 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10487 {
10488 time(&myrpt->dtmf_time);
10489
10490 if (myrpt->dtmfidx < MAXDTMF)
10491 {
10492 int src;
10493
10494 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10495 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10496
10497 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10498
10499 rpt_mutex_unlock(&myrpt->lock);
10500 src = SOURCE_RPT;
10501 if (c_in & 0x80) src = SOURCE_ALT;
10502 res = collect_function_digits(myrpt, cmd, src, NULL);
10503 rpt_mutex_lock(&myrpt->lock);
10504 switch(res){
10505 case DC_INDETERMINATE:
10506 break;
10507 case DC_REQ_FLUSH:
10508 myrpt->dtmfidx = 0;
10509 myrpt->dtmfbuf[0] = 0;
10510 break;
10511 case DC_COMPLETE:
10512 case DC_COMPLETEQUIET:
10513 myrpt->totalexecdcommands++;
10514 myrpt->dailyexecdcommands++;
10515 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10516 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10517 myrpt->dtmfbuf[0] = 0;
10518 myrpt->dtmfidx = -1;
10519 myrpt->dtmf_time = 0;
10520 break;
10521
10522 case DC_ERROR:
10523 default:
10524 myrpt->dtmfbuf[0] = 0;
10525 myrpt->dtmfidx = -1;
10526 myrpt->dtmf_time = 0;
10527 break;
10528 }
10529 if(res != DC_INDETERMINATE) {
10530 rpt_mutex_unlock(&myrpt->lock);
10531 return;
10532 }
10533 }
10534 }
10535 }
10536 else
10537 {
10538 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10539 {
10540 myrpt->callmode = 1;
10541 myrpt->patchnoct = 0;
10542 myrpt->patchquiet = 0;
10543 myrpt->patchfarenddisconnect = 0;
10544 myrpt->patchdialtime = 0;
10545 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10546 myrpt->cidx = 0;
10547 myrpt->exten[myrpt->cidx] = 0;
10548 rpt_mutex_unlock(&myrpt->lock);
10549 pthread_attr_init(&attr);
10550 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10551 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10552 return;
10553 }
10554 }
10555 if (myrpt->callmode == 1)
10556 {
10557 myrpt->exten[myrpt->cidx++] = c;
10558 myrpt->exten[myrpt->cidx] = 0;
10559
10560 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10561 {
10562
10563 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10564 myrpt->exten,1,NULL))
10565 {
10566 myrpt->callmode = 2;
10567 rpt_mutex_unlock(&myrpt->lock);
10568 if(!myrpt->patchquiet)
10569 rpt_telemetry(myrpt,PROC,NULL);
10570 return;
10571 }
10572 else
10573 {
10574 myrpt->calldigittimer = 1;
10575 }
10576 }
10577
10578 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10579 {
10580
10581 myrpt->callmode = 4;
10582 }
10583 rpt_mutex_unlock(&myrpt->lock);
10584 return;
10585 }
10586 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10587 {
10588 myrpt->mydtmf = c;
10589 }
10590 rpt_mutex_unlock(&myrpt->lock);
10591 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10592 do_dtmf_phone(myrpt,NULL,c);
10593 return;
10594 }
10595
10596
10597
10598
10599 static void queue_id(struct rpt *myrpt)
10600 {
10601 if(myrpt->p.idtime){
10602 myrpt->mustid = myrpt->tailid = 0;
10603 myrpt->idtimer = myrpt->p.idtime;
10604 rpt_mutex_unlock(&myrpt->lock);
10605 rpt_telemetry(myrpt,ID,NULL);
10606 rpt_mutex_lock(&myrpt->lock);
10607 }
10608 }
10609
10610
10611
10612
10613 static void do_scheduler(struct rpt *myrpt)
10614 {
10615 int i,res;
10616
10617 #ifdef NEW_ASTERISK
10618 struct ast_tm tmnow;
10619 #else
10620 struct tm tmnow;
10621 #endif
10622 struct ast_variable *skedlist;
10623 char *strs[5],*vp,*val,value[100];
10624
10625 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10626
10627 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10628 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10629
10630
10631
10632 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10633 return;
10634
10635 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10636
10637
10638
10639 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10640 myrpt->dailykeyups = 0;
10641 myrpt->dailytxtime = 0;
10642 myrpt->dailykerchunks = 0;
10643 myrpt->dailyexecdcommands = 0;
10644 }
10645
10646 if(tmnow.tm_sec != 0)
10647 return;
10648
10649
10650
10651
10652
10653
10654 if (myrpt->remote)
10655 return;
10656
10657
10658
10659 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10660 if(debug > 6)
10661 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10662 return;
10663 }
10664
10665 if(!myrpt->p.skedstanzaname){
10666 if(debug > 6)
10667 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10668 return;
10669 }
10670
10671
10672 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10673
10674 if(debug > 6){
10675 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10676 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10677 }
10678
10679 for(; skedlist; skedlist = skedlist->next){
10680 if(debug > 6)
10681 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10682 strncpy(value,skedlist->value,99);
10683 value[99] = 0;
10684
10685 for( i = 0, vp = value ; i < 5; i++){
10686 if(!*vp)
10687 break;
10688 while((*vp == ' ') || (*vp == 0x09))
10689 vp++;
10690 strs[i] = vp;
10691 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10692 vp++;
10693 if(*vp)
10694 *vp++ = 0;
10695 }
10696 if(debug > 6)
10697 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10698 strs[0], strs[1], strs[2], strs[3], strs[4]);
10699 if(i == 5){
10700 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10701 continue;
10702 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10703 continue;
10704 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10705 continue;
10706 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10707 continue;
10708 if(atoi(strs[4]) == 7)
10709 strs[4] = "0";
10710 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10711 continue;
10712 if(debug)
10713 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10714 if(atoi(skedlist->name) == 0)
10715 return;
10716 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10717 if (!val){
10718 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10719 return;
10720 }
10721 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10722 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10723 skedlist->name);
10724 return;
10725 }
10726 myrpt->macrotimer = MACROTIME;
10727 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10728 }
10729 else{
10730 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10731 skedlist->name, skedlist->value);
10732 }
10733 }
10734
10735 }
10736
10737
10738 static void *rpt(void *this)
10739 {
10740 struct rpt *myrpt = (struct rpt *)this;
10741 char *tele,*idtalkover,c,myfirst,*p;
10742 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10743 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10744 struct ast_channel *who;
10745 struct dahdi_confinfo ci;
10746 time_t t;
10747 struct rpt_link *l,*m;
10748 struct rpt_tele *telem;
10749 char tmpstr[300],lstr[MAXLINKLIST];
10750
10751
10752 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10753 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10754 mkdir(tmpstr,0600);
10755 rpt_mutex_lock(&myrpt->lock);
10756
10757 telem = myrpt->tele.next;
10758 while(telem != &myrpt->tele)
10759 {
10760 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10761 telem = telem->next;
10762 }
10763 rpt_mutex_unlock(&myrpt->lock);
10764
10765 for(i = 0; i < nrpts; i++)
10766 {
10767 if (&rpt_vars[i] == myrpt)
10768 {
10769 load_rpt_vars(i,0);
10770 break;
10771 }
10772 }
10773
10774 rpt_mutex_lock(&myrpt->lock);
10775 while(myrpt->xlink)
10776 {
10777 myrpt->xlink = 3;
10778 rpt_mutex_unlock(&myrpt->lock);
10779 usleep(100000);
10780 rpt_mutex_lock(&myrpt->lock);
10781 }
10782 #ifdef HAVE_IOPERM
10783 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10784 (ioperm(myrpt->p.iobase,1,1) == -1))
10785 {
10786 rpt_mutex_unlock(&myrpt->lock);
10787 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10788 myrpt->rpt_thread = AST_PTHREADT_STOP;
10789 pthread_exit(NULL);
10790 }
10791 #endif
10792 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10793 tele = strchr(tmpstr,'/');
10794 if (!tele)
10795 {
10796 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10797 rpt_mutex_unlock(&myrpt->lock);
10798 myrpt->rpt_thread = AST_PTHREADT_STOP;
10799 pthread_exit(NULL);
10800 }
10801 *tele++ = 0;
10802 myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10803 myrpt->dahdirxchannel = NULL;
10804 if (!strcasecmp(tmpstr,"DAHDI"))
10805 myrpt->dahdirxchannel = myrpt->rxchannel;
10806 if (myrpt->rxchannel)
10807 {
10808 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10809 {
10810 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10811 rpt_mutex_unlock(&myrpt->lock);
10812 ast_hangup(myrpt->rxchannel);
10813 myrpt->rpt_thread = AST_PTHREADT_STOP;
10814 pthread_exit(NULL);
10815 }
10816 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10817 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10818 #ifdef AST_CDR_FLAG_POST_DISABLED
10819 if (myrpt->rxchannel->cdr)
10820 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10821 #endif
10822 #ifndef NEW_ASTERISK
10823 myrpt->rxchannel->whentohangup = 0;
10824 #endif
10825 myrpt->rxchannel->appl = "Apprpt";
10826 myrpt->rxchannel->data = "(Repeater Rx)";
10827 if (option_verbose > 2)
10828 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10829 tmpstr,tele,myrpt->rxchannel->name);
10830 ast_call(myrpt->rxchannel,tele,999);
10831 if (myrpt->rxchannel->_state != AST_STATE_UP)
10832 {
10833 rpt_mutex_unlock(&myrpt->lock);
10834 ast_hangup(myrpt->rxchannel);
10835 myrpt->rpt_thread = AST_PTHREADT_STOP;
10836 pthread_exit(NULL);
10837 }
10838 }
10839 else
10840 {
10841 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10842 rpt_mutex_unlock(&myrpt->lock);
10843 myrpt->rpt_thread = AST_PTHREADT_STOP;
10844 pthread_exit(NULL);
10845 }
10846 myrpt->dahditxchannel = NULL;
10847 if (myrpt->txchanname)
10848 {
10849 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10850 tele = strchr(tmpstr,'/');
10851 if (!tele)
10852 {
10853 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10854 rpt_mutex_unlock(&myrpt->lock);
10855 ast_hangup(myrpt->rxchannel);
10856 myrpt->rpt_thread = AST_PTHREADT_STOP;
10857 pthread_exit(NULL);
10858 }
10859 *tele++ = 0;
10860 myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10861 if (!strcasecmp(tmpstr,"DAHDI"))
10862 myrpt->dahditxchannel = myrpt->txchannel;
10863 if (myrpt->txchannel)
10864 {
10865 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10866 {
10867 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10868 rpt_mutex_unlock(&myrpt->lock);
10869 ast_hangup(myrpt->txchannel);
10870 ast_hangup(myrpt->rxchannel);
10871 myrpt->rpt_thread = AST_PTHREADT_STOP;
10872 pthread_exit(NULL);
10873 }
10874 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10875 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10876 #ifdef AST_CDR_FLAG_POST_DISABLED
10877 if (myrpt->txchannel->cdr)
10878 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10879 #endif
10880 #ifndef NEW_ASTERISK
10881 myrpt->txchannel->whentohangup = 0;
10882 #endif
10883 myrpt->txchannel->appl = "Apprpt";
10884 myrpt->txchannel->data = "(Repeater Tx)";
10885 if (option_verbose > 2)
10886 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10887 tmpstr,tele,myrpt->txchannel->name);
10888 ast_call(myrpt->txchannel,tele,999);
10889 if (myrpt->rxchannel->_state != AST_STATE_UP)
10890 {
10891 rpt_mutex_unlock(&myrpt->lock);
10892 ast_hangup(myrpt->rxchannel);
10893 ast_hangup(myrpt->txchannel);
10894 myrpt->rpt_thread = AST_PTHREADT_STOP;
10895 pthread_exit(NULL);
10896 }
10897 }
10898 else
10899 {
10900 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10901 rpt_mutex_unlock(&myrpt->lock);
10902 ast_hangup(myrpt->rxchannel);
10903 myrpt->rpt_thread = AST_PTHREADT_STOP;
10904 pthread_exit(NULL);
10905 }
10906 }
10907 else
10908 {
10909 myrpt->txchannel = myrpt->rxchannel;
10910 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10911 myrpt->dahditxchannel = myrpt->txchannel;
10912 }
10913 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10914 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10915
10916 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10917 if (!myrpt->pchannel)
10918 {
10919 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10920 rpt_mutex_unlock(&myrpt->lock);
10921 if (myrpt->txchannel != myrpt->rxchannel)
10922 ast_hangup(myrpt->txchannel);
10923 ast_hangup(myrpt->rxchannel);
10924 myrpt->rpt_thread = AST_PTHREADT_STOP;
10925 pthread_exit(NULL);
10926 }
10927 #ifdef AST_CDR_FLAG_POST_DISABLED
10928 if (myrpt->pchannel->cdr)
10929 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10930 #endif
10931 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10932 if (!myrpt->dahditxchannel)
10933 {
10934
10935 myrpt->dahditxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10936 if (!myrpt->dahditxchannel)
10937 {
10938 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10939 rpt_mutex_unlock(&myrpt->lock);
10940 if (myrpt->txchannel != myrpt->rxchannel)
10941 ast_hangup(myrpt->txchannel);
10942 ast_hangup(myrpt->rxchannel);
10943 myrpt->rpt_thread = AST_PTHREADT_STOP;
10944 pthread_exit(NULL);
10945 }
10946 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10947 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10948 #ifdef AST_CDR_FLAG_POST_DISABLED
10949 if (myrpt->dahditxchannel->cdr)
10950 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10951 #endif
10952 }
10953
10954 myrpt->monchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10955 if (!myrpt->monchannel)
10956 {
10957 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10958 rpt_mutex_unlock(&myrpt->lock);
10959 if (myrpt->txchannel != myrpt->rxchannel)
10960 ast_hangup(myrpt->txchannel);
10961 ast_hangup(myrpt->rxchannel);
10962 myrpt->rpt_thread = AST_PTHREADT_STOP;
10963 pthread_exit(NULL);
10964 }
10965 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10966 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10967 #ifdef AST_CDR_FLAG_POST_DISABLED
10968 if (myrpt->monchannel->cdr)
10969 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10970 #endif
10971
10972 ci.chan = 0;
10973 ci.confno = -1;
10974 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10975
10976 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10977 {
10978 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10979 rpt_mutex_unlock(&myrpt->lock);
10980 ast_hangup(myrpt->pchannel);
10981 ast_hangup(myrpt->monchannel);
10982 if (myrpt->txchannel != myrpt->rxchannel)
10983 ast_hangup(myrpt->txchannel);
10984 ast_hangup(myrpt->rxchannel);
10985 myrpt->rpt_thread = AST_PTHREADT_STOP;
10986 pthread_exit(NULL);
10987 }
10988
10989 myrpt->txconf = ci.confno;
10990
10991 ci.chan = 0;
10992 ci.confno = -1;
10993 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10994 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10995
10996 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10997 {
10998 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10999 rpt_mutex_unlock(&myrpt->lock);
11000 ast_hangup(myrpt->pchannel);
11001 ast_hangup(myrpt->monchannel);
11002 if (myrpt->txchannel != myrpt->rxchannel)
11003 ast_hangup(myrpt->txchannel);
11004 ast_hangup(myrpt->rxchannel);
11005 myrpt->rpt_thread = AST_PTHREADT_STOP;
11006 pthread_exit(NULL);
11007 }
11008
11009 myrpt->conf = ci.confno;
11010
11011 ci.chan = 0;
11012 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11013 (myrpt->dahditxchannel == myrpt->txchannel))
11014 {
11015
11016 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11017 {
11018 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11019 rpt_mutex_unlock(&myrpt->lock);
11020 ast_hangup(myrpt->pchannel);
11021 ast_hangup(myrpt->monchannel);
11022 if (myrpt->txchannel != myrpt->rxchannel)
11023 ast_hangup(myrpt->txchannel);
11024 ast_hangup(myrpt->rxchannel);
11025 myrpt->rpt_thread = AST_PTHREADT_STOP;
11026 pthread_exit(NULL);
11027 }
11028 ci.confmode = DAHDI_CONF_MONITORTX;
11029 }
11030 else
11031 {
11032 ci.confno = myrpt->txconf;
11033 ci.confmode = DAHDI_CONF_CONFANNMON;
11034 }
11035
11036 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11037 {
11038 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11039 rpt_mutex_unlock(&myrpt->lock);
11040 ast_hangup(myrpt->pchannel);
11041 ast_hangup(myrpt->monchannel);
11042 if (myrpt->txchannel != myrpt->rxchannel)
11043 ast_hangup(myrpt->txchannel);
11044 ast_hangup(myrpt->rxchannel);
11045 myrpt->rpt_thread = AST_PTHREADT_STOP;
11046 pthread_exit(NULL);
11047 }
11048
11049 myrpt->parrotchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11050 if (!myrpt->parrotchannel)
11051 {
11052 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11053 rpt_mutex_unlock(&myrpt->lock);
11054 if (myrpt->txchannel != myrpt->rxchannel)
11055 ast_hangup(myrpt->txchannel);
11056 ast_hangup(myrpt->rxchannel);
11057 myrpt->rpt_thread = AST_PTHREADT_STOP;
11058 pthread_exit(NULL);
11059 }
11060 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11061 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11062 #ifdef AST_CDR_FLAG_POST_DISABLED
11063 if (myrpt->parrotchannel->cdr)
11064 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11065 #endif
11066
11067 myrpt->voxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11068 if (!myrpt->voxchannel)
11069 {
11070 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11071 rpt_mutex_unlock(&myrpt->lock);
11072 if (myrpt->txchannel != myrpt->rxchannel)
11073 ast_hangup(myrpt->txchannel);
11074 ast_hangup(myrpt->rxchannel);
11075 myrpt->rpt_thread = AST_PTHREADT_STOP;
11076 pthread_exit(NULL);
11077 }
11078 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11079 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11080 #ifdef AST_CDR_FLAG_POST_DISABLED
11081 if (myrpt->voxchannel->cdr)
11082 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11083 #endif
11084
11085 myrpt->txpchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11086 if (!myrpt->txpchannel)
11087 {
11088 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11089 rpt_mutex_unlock(&myrpt->lock);
11090 ast_hangup(myrpt->pchannel);
11091 ast_hangup(myrpt->monchannel);
11092 if (myrpt->txchannel != myrpt->rxchannel)
11093 ast_hangup(myrpt->txchannel);
11094 ast_hangup(myrpt->rxchannel);
11095 myrpt->rpt_thread = AST_PTHREADT_STOP;
11096 pthread_exit(NULL);
11097 }
11098 #ifdef AST_CDR_FLAG_POST_DISABLED
11099 if (myrpt->txpchannel->cdr)
11100 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11101 #endif
11102
11103 ci.chan = 0;
11104 ci.confno = myrpt->txconf;
11105 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11106
11107 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11108 {
11109 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11110 rpt_mutex_unlock(&myrpt->lock);
11111 ast_hangup(myrpt->txpchannel);
11112 ast_hangup(myrpt->monchannel);
11113 if (myrpt->txchannel != myrpt->rxchannel)
11114 ast_hangup(myrpt->txchannel);
11115 ast_hangup(myrpt->rxchannel);
11116 myrpt->rpt_thread = AST_PTHREADT_STOP;
11117 pthread_exit(NULL);
11118 }
11119
11120 myrpt->iofd = -1;
11121 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11122 {
11123 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11124 rpt_mutex_unlock(&myrpt->lock);
11125 ast_hangup(myrpt->pchannel);
11126 if (myrpt->txchannel != myrpt->rxchannel)
11127 ast_hangup(myrpt->txchannel);
11128 ast_hangup(myrpt->rxchannel);
11129 pthread_exit(NULL);
11130 }
11131
11132
11133
11134 myrpt->links.next = &myrpt->links;
11135 myrpt->links.prev = &myrpt->links;
11136 myrpt->tailtimer = 0;
11137 myrpt->totimer = 0;
11138 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11139 myrpt->idtimer = myrpt->p.politeid;
11140 myrpt->mustid = myrpt->tailid = 0;
11141 myrpt->callmode = 0;
11142 myrpt->tounkeyed = 0;
11143 myrpt->tonotify = 0;
11144 myrpt->retxtimer = 0;
11145 myrpt->rerxtimer = 0;
11146 myrpt->skedtimer = 0;
11147 myrpt->tailevent = 0;
11148 lasttx = 0;
11149 myrpt->keyed = 0;
11150 myrpt->txkeyed = 0;
11151 time(&myrpt->lastkeyedtime);
11152 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11153 time(&myrpt->lasttxkeyedtime);
11154 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11155 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11156 myrpt->dtmfidx = -1;
11157 myrpt->dtmfbuf[0] = 0;
11158 myrpt->rem_dtmfidx = -1;
11159 myrpt->rem_dtmfbuf[0] = 0;
11160 myrpt->dtmf_time = 0;
11161 myrpt->rem_dtmf_time = 0;
11162 myrpt->inpadtest = 0;
11163 myrpt->disgorgetime = 0;
11164 myrpt->lastnodewhichkeyedusup[0] = '\0';
11165 myrpt->dailytxtime = 0;
11166 myrpt->totaltxtime = 0;
11167 myrpt->dailykeyups = 0;
11168 myrpt->totalkeyups = 0;
11169 myrpt->dailykerchunks = 0;
11170 myrpt->totalkerchunks = 0;
11171 myrpt->dailyexecdcommands = 0;
11172 myrpt->totalexecdcommands = 0;
11173 myrpt->timeouts = 0;
11174 myrpt->exten[0] = '\0';
11175 myrpt->lastdtmfcommand[0] = '\0';
11176 voxinit_rpt(myrpt,1);
11177 myrpt->wasvox = 0;
11178 if (myrpt->p.startupmacro)
11179 {
11180 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11181 }
11182 rpt_mutex_unlock(&myrpt->lock);
11183 val = 1;
11184 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11185 val = 1;
11186 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11187 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11188 dtmfed = 0;
11189 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11190 lastmyrx = 0;
11191 myfirst = 0;
11192 while (ms >= 0)
11193 {
11194 struct ast_frame *f,*f1,*f2;
11195 struct ast_channel *cs[300],*cs1[300];
11196 int totx=0,elap=0,n,x,toexit=0;
11197
11198
11199 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11200 struct rpt_link *dl;
11201 struct rpt_tele *dt;
11202
11203 myrpt->disgorgetime = 0;
11204 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11205 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11206 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11207 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11208 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11209 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11210
11211 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11212 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11213 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11214 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11215 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11216 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11217 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11218 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11219 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11220 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11221
11222 dl = myrpt->links.next;
11223 while(dl != &myrpt->links){
11224 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11225 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11226 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11227 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11228 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11229 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11230 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11231 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11232 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11233 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11234 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11235 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11236 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11237 dl = dl->next;
11238 }
11239
11240 dt = myrpt->tele.next;
11241 if(dt != &myrpt->tele)
11242 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11243 while(dt != &myrpt->tele){
11244 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11245 dt = dt->next;
11246 }
11247 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11248
11249 }
11250
11251
11252 if (myrpt->reload)
11253 {
11254 struct rpt_tele *inner_telem;
11255
11256 rpt_mutex_lock(&myrpt->lock);
11257 inner_telem = myrpt->tele.next;
11258 while(inner_telem != &myrpt->tele)
11259 {
11260 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11261 inner_telem = inner_telem->next;
11262 }
11263 myrpt->reload = 0;
11264 rpt_mutex_unlock(&myrpt->lock);
11265 usleep(10000);
11266
11267 for(i = 0; i < nrpts; i++)
11268 {
11269 if (&rpt_vars[i] == myrpt)
11270 {
11271 load_rpt_vars(i,0);
11272 break;
11273 }
11274 }
11275 }
11276
11277 rpt_mutex_lock(&myrpt->lock);
11278 if (ast_check_hangup(myrpt->rxchannel)) break;
11279 if (ast_check_hangup(myrpt->txchannel)) break;
11280 if (ast_check_hangup(myrpt->pchannel)) break;
11281 if (ast_check_hangup(myrpt->monchannel)) break;
11282 if (myrpt->parrotchannel &&
11283 ast_check_hangup(myrpt->parrotchannel)) break;
11284 if (myrpt->voxchannel &&
11285 ast_check_hangup(myrpt->voxchannel)) break;
11286 if (ast_check_hangup(myrpt->txpchannel)) break;
11287 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11288
11289
11290 myrpt->localtx = myrpt->keyed;
11291
11292 l = myrpt->links.next;
11293 remrx = 0;
11294 while(l != &myrpt->links)
11295 {
11296 if (l->lastrx){
11297 remrx = 1;
11298 if(l->name[0] != '0')
11299 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11300 }
11301 l = l->next;
11302 }
11303
11304 if(myrpt->p.idtime)
11305 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11306
11307
11308 if (myrpt->p.duplex > 1)
11309 {
11310 totx = myrpt->callmode;
11311 totx = totx || myrpt->localtx;
11312 }
11313 else
11314 {
11315 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11316
11317 if (lastmyrx != myrx)
11318 {
11319 voxinit_rpt(myrpt,!myrx);
11320 lastmyrx = myrx;
11321 }
11322 totx = 0;
11323 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11324 {
11325 if (myrpt->voxtostate)
11326 {
11327 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11328 myrpt->voxtostate = 0;
11329 }
11330 else
11331 {
11332 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11333 myrpt->voxtostate = 1;
11334 }
11335 }
11336 if (!myrpt->voxtostate)
11337 totx = myrpt->callmode && myrpt->wasvox;
11338 }
11339
11340 identqueued = 0;
11341 localmsgqueued = 0;
11342 othertelemqueued = 0;
11343 tailmessagequeued = 0;
11344 ctqueued = 0;
11345 telem = myrpt->tele.next;
11346 while(telem != &myrpt->tele)
11347 {
11348 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11349 identqueued = 1;
11350 }
11351 else if(telem->mode == TAILMSG)
11352 {
11353 tailmessagequeued = 1;
11354 }
11355 else if(telem->mode == STATS_TIME_LOCAL)
11356 {
11357 localmsgqueued = 1;
11358 }
11359 else
11360 {
11361 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11362 othertelemqueued = 1;
11363 else
11364 ctqueued = 1;
11365 }
11366 telem = telem->next;
11367 }
11368
11369
11370 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11371
11372
11373 myrpt->exttx = totx;
11374 totx = totx || myrpt->dtmf_local_timer;
11375
11376 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11377
11378 totx = totx || remrx;
11379
11380 if (myrpt->p.duplex > 0)
11381 totx = totx || identqueued || ctqueued || localmsgqueued;
11382
11383 if (myrpt->p.duplex > 1)
11384 {
11385 totx = totx || (myrpt->dtmfidx > -1) ||
11386 myrpt->cmdnode[0];
11387 }
11388
11389 totx = totx || (myrpt->parrotstate > 1);
11390
11391 if (!totx)
11392 {
11393 myrpt->totimer = myrpt->p.totime;
11394 myrpt->tounkeyed = 0;
11395 myrpt->tonotify = 0;
11396 }
11397 else{
11398 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11399 myrpt->p.althangtime :
11400 myrpt->p.hangtime;
11401 }
11402
11403 totx = totx && myrpt->totimer;
11404
11405 if ((!myrpt->totimer) && (!myrpt->tonotify))
11406 {
11407 myrpt->tonotify = 1;
11408 myrpt->timeouts++;
11409 rpt_mutex_unlock(&myrpt->lock);
11410 rpt_telemetry(myrpt,TIMEOUT,NULL);
11411 rpt_mutex_lock(&myrpt->lock);
11412 }
11413
11414
11415 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11416 {
11417 myrpt->tounkeyed = 1;
11418 }
11419 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11420 {
11421 myrpt->totimer = myrpt->p.totime;
11422 myrpt->tounkeyed = 0;
11423 myrpt->tonotify = 0;
11424 rpt_mutex_unlock(&myrpt->lock);
11425 continue;
11426 }
11427
11428 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11429 {
11430 if(debug)
11431 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11432 myrpt->callmode = 0;
11433 myrpt->macropatch=0;
11434 channel_revert(myrpt);
11435 }
11436
11437 if (!myrpt->totimer) myrpt->tailtimer = 0;
11438
11439 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11440
11441
11442 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11443 int hasid = 0,hastalkover = 0;
11444
11445 telem = myrpt->tele.next;
11446 while(telem != &myrpt->tele){
11447 if(telem->mode == ID){
11448 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11449 hasid = 1;
11450 }
11451 if(telem->mode == TAILMSG){
11452 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11453 }
11454 if (telem->mode == IDTALKOVER) hastalkover = 1;
11455 telem = telem->next;
11456 }
11457 rpt_mutex_unlock(&myrpt->lock);
11458 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11459 rpt_mutex_lock(&myrpt->lock);
11460 }
11461
11462
11463
11464
11465
11466 if(myrpt->mustid && (!myrpt->idtimer))
11467 queue_id(myrpt);
11468
11469 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11470 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11471 {
11472 myrpt->tailid = 1;
11473 }
11474
11475
11476
11477 if(myrpt->tailevent){
11478 myrpt->tailevent = 0;
11479 if(myrpt->tailid){
11480 totx = 1;
11481 queue_id(myrpt);
11482 }
11483 else if ((myrpt->p.tailmessages[0]) &&
11484 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11485 totx = 1;
11486 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11487 rpt_mutex_unlock(&myrpt->lock);
11488 rpt_telemetry(myrpt, TAILMSG, NULL);
11489 rpt_mutex_lock(&myrpt->lock);
11490 }
11491 }
11492
11493
11494
11495
11496 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11497 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11498 myrpt->txrealkeyed = totx;
11499 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11500 if (totx && (!lasttx))
11501 {
11502 char mydate[100],myfname[100];
11503 time_t myt;
11504
11505 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11506 if (myrpt->p.archivedir)
11507 {
11508 long blocksleft;
11509
11510 time(&myt);
11511 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11512 localtime(&myt));
11513 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11514 myrpt->name,mydate);
11515 myrpt->monstream = ast_writefile(myfname,"wav49",
11516 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11517 if (myrpt->p.monminblocks)
11518 {
11519 blocksleft = diskavail(myrpt);
11520 if (blocksleft >= myrpt->p.monminblocks)
11521 donodelog(myrpt,"TXKEY,MAIN");
11522 } else donodelog(myrpt,"TXKEY,MAIN");
11523 }
11524 lasttx = 1;
11525 myrpt->txkeyed = 1;
11526 time(&myrpt->lasttxkeyedtime);
11527 myrpt->dailykeyups++;
11528 myrpt->totalkeyups++;
11529 rpt_mutex_unlock(&myrpt->lock);
11530 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11531 rpt_mutex_lock(&myrpt->lock);
11532 }
11533 if ((!totx) && lasttx)
11534 {
11535 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11536 myrpt->monstream = NULL;
11537
11538 lasttx = 0;
11539 myrpt->txkeyed = 0;
11540 time(&myrpt->lasttxkeyedtime);
11541 rpt_mutex_unlock(&myrpt->lock);
11542 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11543 rpt_mutex_lock(&myrpt->lock);
11544 donodelog(myrpt,"TXUNKEY,MAIN");
11545 }
11546 time(&t);
11547
11548 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11549 {
11550 myrpt->inpadtest = 0;
11551 myrpt->dtmfidx = -1;
11552 myrpt->dtmfbuf[0] = 0;
11553 }
11554
11555 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11556 {
11557 myrpt->inpadtest = 0;
11558 myrpt->rem_dtmfidx = -1;
11559 myrpt->rem_dtmfbuf[0] = 0;
11560 }
11561
11562 if (myrpt->exttx && myrpt->parrotchannel &&
11563 myrpt->p.parrotmode && (!myrpt->parrotstate))
11564 {
11565 char myfname[300];
11566
11567 ci.confno = myrpt->conf;
11568 ci.confmode = DAHDI_CONF_CONFANNMON;
11569 ci.chan = 0;
11570
11571
11572 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11573 {
11574 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11575 break;
11576 }
11577
11578 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11579 strcat(myfname,".wav");
11580 unlink(myfname);
11581 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11582 myrpt->parrotstate = 1;
11583 myrpt->parrottimer = myrpt->p.parrottime;
11584 if (myrpt->parrotstream)
11585 ast_closestream(myrpt->parrotstream);
11586 myrpt->parrotstream = NULL;
11587 myrpt->parrotstream = ast_writefile(myfname,"wav",
11588 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11589 }
11590
11591
11592
11593 l = myrpt->links.next;
11594 while(l != &myrpt->links)
11595 {
11596 if (l->killme)
11597 {
11598
11599 remque((struct qelem *) l);
11600 if (!strcmp(myrpt->cmdnode,l->name))
11601 myrpt->cmdnode[0] = 0;
11602 rpt_mutex_unlock(&myrpt->lock);
11603
11604 if (l->chan) ast_hangup(l->chan);
11605 ast_hangup(l->pchan);
11606 ast_free(l);
11607 rpt_mutex_lock(&myrpt->lock);
11608
11609 l = myrpt->links.next;
11610 continue;
11611 }
11612 l = l->next;
11613 }
11614 n = 0;
11615 cs[n++] = myrpt->rxchannel;
11616 cs[n++] = myrpt->pchannel;
11617 cs[n++] = myrpt->monchannel;
11618 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11619 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11620 cs[n++] = myrpt->txpchannel;
11621 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11622 if (myrpt->dahditxchannel != myrpt->txchannel)
11623 cs[n++] = myrpt->dahditxchannel;
11624 l = myrpt->links.next;
11625 while(l != &myrpt->links)
11626 {
11627 if ((!l->killme) && (!l->disctime) && l->chan)
11628 {
11629 cs[n++] = l->chan;
11630 cs[n++] = l->pchan;
11631 }
11632 l = l->next;
11633 }
11634 if ((myrpt->topkeystate == 1) &&
11635 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11636 {
11637 myrpt->topkeystate = 2;
11638 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11639 topcompar);
11640 }
11641 rpt_mutex_unlock(&myrpt->lock);
11642
11643 if (myrpt->topkeystate == 2)
11644 {
11645 rpt_telemetry(myrpt,TOPKEY,NULL);
11646 myrpt->topkeystate = 3;
11647 }
11648 ms = MSWAIT;
11649 for(x = 0; x < n; x++)
11650 {
11651 int s = -(-x - myrpt->scram - 1) % n;
11652 cs1[x] = cs[s];
11653 }
11654 myrpt->scram++;
11655 who = ast_waitfor_n(cs1,n,&ms);
11656 if (who == NULL) ms = 0;
11657 elap = MSWAIT - ms;
11658 rpt_mutex_lock(&myrpt->lock);
11659 l = myrpt->links.next;
11660 while(l != &myrpt->links)
11661 {
11662 int myrx;
11663
11664 if (l->voxtotimer) l->voxtotimer -= elap;
11665 if (l->voxtotimer < 0) l->voxtotimer = 0;
11666
11667 if (l->lasttx != l->lasttx1)
11668 {
11669 voxinit_link(l,!l->lasttx);
11670 l->lasttx1 = l->lasttx;
11671 }
11672 myrx = l->lastrealrx;
11673 if ((l->phonemode) && (l->phonevox))
11674 {
11675 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11676 if (l->voxtotimer <= 0)
11677 {
11678 if (l->voxtostate)
11679 {
11680 l->voxtotimer = myrpt->p.voxtimeout_ms;
11681 l->voxtostate = 0;
11682 }
11683 else
11684 {
11685 l->voxtotimer = myrpt->p.voxrecover_ms;
11686 l->voxtostate = 1;
11687 }
11688 }
11689 if (!l->voxtostate)
11690 myrx = myrx || l->wasvox ;
11691 }
11692 l->lastrx = myrx;
11693 if (l->linklisttimer)
11694 {
11695 l->linklisttimer -= elap;
11696 if (l->linklisttimer < 0) l->linklisttimer = 0;
11697 }
11698 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11699 {
11700 struct ast_frame lf;
11701
11702 memset(&lf,0,sizeof(lf));
11703 lf.frametype = AST_FRAME_TEXT;
11704 lf.subclass.integer = 0;
11705 lf.offset = 0;
11706 lf.mallocd = 0;
11707 lf.samples = 0;
11708 l->linklisttimer = LINKLISTTIME;
11709 strcpy(lstr,"L ");
11710 __mklinklist(myrpt,l,lstr + 2);
11711 if (l->chan)
11712 {
11713 lf.datalen = strlen(lstr) + 1;
11714 lf.data.ptr = lstr;
11715 ast_write(l->chan,&lf);
11716 if (debug > 6) ast_log(LOG_NOTICE,
11717 "@@@@ node %s sent node string %s to node %s\n",
11718 myrpt->name,lstr,l->name);
11719 }
11720 }
11721 if (l->newkey)
11722 {
11723 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11724 {
11725 l->retxtimer = 0;
11726 if (l->chan && l->phonemode == 0)
11727 {
11728 if (l->lasttx)
11729 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11730 else
11731 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11732 }
11733 }
11734 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11735 {
11736 if (debug == 7) printf("@@@@ rx un-key\n");
11737 l->lastrealrx = 0;
11738 l->rerxtimer = 0;
11739 if (l->lastrx1)
11740 {
11741 if (myrpt->p.archivedir)
11742 {
11743 char str[100];
11744
11745 sprintf(str,"RXUNKEY(T),%s",l->name);
11746 donodelog(myrpt,str);
11747 }
11748 if(myrpt->p.duplex)
11749 rpt_telemetry(myrpt,LINKUNKEY,l);
11750 l->lastrx1 = 0;
11751 }
11752 }
11753 }
11754 if (l->disctime)
11755 {
11756 l->disctime -= elap;
11757 if (l->disctime <= 0)
11758 l->disctime = 0;
11759 }
11760
11761 if (l->retrytimer)
11762 {
11763 l->retrytimer -= elap;
11764 if (l->retrytimer < 0) l->retrytimer = 0;
11765 }
11766
11767
11768 l->connecttime += elap;
11769
11770
11771 if (l->elaptime < 0)
11772 {
11773 l = l->next;
11774 continue;
11775 }
11776 l->elaptime += elap;
11777
11778 if ((l->elaptime > MAXCONNECTTIME) &&
11779 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11780 {
11781 l->elaptime = 0;
11782 rpt_mutex_unlock(&myrpt->lock);
11783 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11784 rpt_mutex_lock(&myrpt->lock);
11785 break;
11786 }
11787 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11788 (l->retries++ < l->max_retries) && (l->hasconnected))
11789 {
11790 if (l->chan) ast_hangup(l->chan);
11791 l->chan = 0;
11792 rpt_mutex_unlock(&myrpt->lock);
11793 if ((l->name[0] != '0') && (!l->isremote))
11794 {
11795 if (attempt_reconnect(myrpt,l) == -1)
11796 {
11797 l->retrytimer = RETRY_TIMER_MS;
11798 }
11799 }
11800 else
11801 {
11802 l->retrytimer = l->max_retries + 1;
11803 }
11804
11805 rpt_mutex_lock(&myrpt->lock);
11806 break;
11807 }
11808 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11809 (l->retries >= l->max_retries))
11810 {
11811
11812 remque((struct qelem *) l);
11813 if (!strcmp(myrpt->cmdnode,l->name))
11814 myrpt->cmdnode[0] = 0;
11815 rpt_mutex_unlock(&myrpt->lock);
11816 if (l->name[0] != '0')
11817 {
11818 if (!l->hasconnected)
11819 rpt_telemetry(myrpt,CONNFAIL,l);
11820 else rpt_telemetry(myrpt,REMDISC,l);
11821 }
11822 if (myrpt->p.archivedir)
11823 {
11824 char str[100];
11825
11826 if (!l->hasconnected)
11827 sprintf(str,"LINKFAIL,%s",l->name);
11828 else
11829 sprintf(str,"LINKDISC,%s",l->name);
11830 donodelog(myrpt,str);
11831 }
11832
11833 ast_hangup(l->pchan);
11834 ast_free(l);
11835 rpt_mutex_lock(&myrpt->lock);
11836 break;
11837 }
11838 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11839 {
11840 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11841
11842 remque((struct qelem *) l);
11843 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11844 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11845 rpt_mutex_unlock(&myrpt->lock);
11846 if (l->name[0] != '0')
11847 {
11848 rpt_telemetry(myrpt,REMDISC,l);
11849 }
11850 if (myrpt->p.archivedir)
11851 {
11852 char str[100];
11853 sprintf(str,"LINKDISC,%s",l->name);
11854 donodelog(myrpt,str);
11855 }
11856
11857 ast_hangup(l->pchan);
11858 ast_free(l);
11859 rpt_mutex_lock(&myrpt->lock);
11860 break;
11861 }
11862 l = l->next;
11863 }
11864 if (myrpt->linkposttimer)
11865 {
11866 myrpt->linkposttimer -= elap;
11867 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11868 }
11869 if (myrpt->linkposttimer <= 0)
11870 {
11871 int nstr;
11872 char lst,*str;
11873 time_t now;
11874
11875 myrpt->linkposttimer = LINKPOSTTIME;
11876 nstr = 0;
11877 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11878 {
11879
11880 if (l->name[0] == '0') continue;
11881 nstr += strlen(l->name) + 1;
11882 }
11883 str = ast_malloc(nstr + 256);
11884 if (!str)
11885 {
11886 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11887 break;
11888 }
11889 nstr = 0;
11890 strcpy(str,"nodes=");
11891 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11892 {
11893
11894 if (l->name[0] == '0') continue;
11895 lst = 'T';
11896 if (!l->mode) lst = 'R';
11897 if (!l->thisconnected) lst = 'C';
11898 if (nstr) strcat(str,",");
11899 sprintf(str + strlen(str),"%c%s",lst,l->name);
11900 nstr = 1;
11901 }
11902 p = strstr(tdesc, "version");
11903 if(p){
11904 int vmajor,vminor;
11905 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11906 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11907 }
11908 time(&now);
11909 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11910 sprintf(str + strlen(str),
11911 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11912 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11913 myrpt->timeouts,myrpt->totalexecdcommands);
11914 rpt_mutex_unlock(&myrpt->lock);
11915 statpost(myrpt,str);
11916 rpt_mutex_lock(&myrpt->lock);
11917 ast_free(str);
11918 }
11919 if (myrpt->keyposttimer)
11920 {
11921 myrpt->keyposttimer -= elap;
11922 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11923 }
11924 if (myrpt->keyposttimer <= 0)
11925 {
11926 char str[100];
11927 int diff = 0;
11928 time_t now;
11929
11930 myrpt->keyposttimer = KEYPOSTTIME;
11931 time(&now);
11932 if (myrpt->lastkeyedtime)
11933 {
11934 diff = (int)(now - myrpt->lastkeyedtime);
11935 }
11936 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11937 rpt_mutex_unlock(&myrpt->lock);
11938 statpost(myrpt,str);
11939 rpt_mutex_lock(&myrpt->lock);
11940 }
11941 if(totx){
11942 myrpt->dailytxtime += elap;
11943 myrpt->totaltxtime += elap;
11944 }
11945 i = myrpt->tailtimer;
11946 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11947 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11948 if((i) && (myrpt->tailtimer == 0))
11949 myrpt->tailevent = 1;
11950 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11951 if (myrpt->totimer < 0) myrpt->totimer = 0;
11952 if (myrpt->idtimer) myrpt->idtimer -= elap;
11953 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11954 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11955 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11956 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11957 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11958 if (myrpt->exttx)
11959 {
11960 myrpt->parrottimer = myrpt->p.parrottime;
11961 }
11962 else
11963 {
11964 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11965 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11966 }
11967
11968 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11969 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11970
11971 if (myrpt->dtmf_local_timer)
11972 {
11973 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11974 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11975 }
11976 do_dtmf_local(myrpt,0);
11977
11978 if (myrpt->skedtimer <= 0){
11979 myrpt->skedtimer = 200;
11980 do_scheduler(myrpt);
11981 }
11982 else
11983 myrpt->skedtimer -=elap;
11984 if (!ms)
11985 {
11986 rpt_mutex_unlock(&myrpt->lock);
11987 continue;
11988 }
11989 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11990 (myrpt->parrottimer <= 0))
11991 {
11992
11993 ci.confno = 0;
11994 ci.confmode = 0;
11995 ci.chan = 0;
11996
11997
11998 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11999 {
12000 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
12001 break;
12002 }
12003 if (myrpt->parrotstream)
12004 ast_closestream(myrpt->parrotstream);
12005 myrpt->parrotstream = NULL;
12006 myrpt->parrotstate = 2;
12007 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
12008 }
12009 if (myrpt->cmdAction.state == CMD_STATE_READY)
12010 {
12011 int status;
12012 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12013
12014 rpt_mutex_unlock(&myrpt->lock);
12015
12016 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12017
12018 rpt_mutex_lock(&myrpt->lock);
12019 myrpt->cmdAction.state = CMD_STATE_IDLE;
12020 }
12021
12022 c = myrpt->macrobuf[0];
12023 time(&t);
12024 if (c && (!myrpt->macrotimer) &&
12025 starttime && (t > (starttime + START_DELAY)))
12026 {
12027 char cin = c & 0x7f;
12028 myrpt->macrotimer = MACROTIME;
12029 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12030 if ((cin == 'p') || (cin == 'P'))
12031 myrpt->macrotimer = MACROPTIME;
12032 rpt_mutex_unlock(&myrpt->lock);
12033 if (myrpt->p.archivedir)
12034 {
12035 char str[100];
12036
12037 sprintf(str,"DTMF(M),MAIN,%c",cin);
12038 donodelog(myrpt,str);
12039 }
12040 local_dtmf_helper(myrpt,c);
12041 } else rpt_mutex_unlock(&myrpt->lock);
12042 if (who == myrpt->rxchannel)
12043 {
12044 int ismuted;
12045
12046 f = ast_read(myrpt->rxchannel);
12047 if (!f)
12048 {
12049 if (debug) printf("@@@@ rpt:Hung Up\n");
12050 break;
12051 }
12052 if (f->frametype == AST_FRAME_VOICE)
12053 {
12054 #ifdef _MDC_DECODE_H_
12055 unsigned char ubuf[2560];
12056 short *sp;
12057 int n;
12058 #endif
12059
12060 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12061 memset(f->data.ptr,0,f->datalen);
12062 }
12063
12064 #ifdef _MDC_DECODE_H_
12065 sp = (short *) f->data;
12066
12067 for(n = 0; n < f->datalen / 2; n++)
12068 {
12069 ubuf[n] = (*sp++ >> 8) + 128;
12070 }
12071 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12072 if (n == 1)
12073 {
12074 unsigned char op,arg;
12075 unsigned short unitID;
12076
12077 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12078 if (debug > 2)
12079 {
12080 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12081 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12082 op & 255,arg & 255,unitID);
12083 }
12084 if ((op == 1) && (arg == 0))
12085 {
12086 myrpt->lastunit = unitID;
12087 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12088 mdc1200_send(myrpt,myrpt->lastunit);
12089 }
12090 }
12091 if ((debug > 2) && (i == 2))
12092 {
12093 unsigned char op,arg,ex1,ex2,ex3,ex4;
12094 unsigned short unitID;
12095
12096 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12097 &ex1,&ex2,&ex3,&ex4);
12098 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12099 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12100 op & 255,arg & 255,unitID);
12101 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12102 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12103 }
12104 #endif
12105 #ifdef __RPT_NOTCH
12106
12107 rpt_filter(myrpt,f->data,f->datalen / 2);
12108 #endif
12109 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12110 {
12111 ismuted = 0;
12112 }
12113 if (dtmfed) ismuted = 1;
12114 dtmfed = 0;
12115 if (ismuted)
12116 {
12117 memset(f->data.ptr,0,f->datalen);
12118 if (myrpt->lastf1)
12119 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12120 if (myrpt->lastf2)
12121 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12122 }
12123 if (f) f2 = ast_frdup(f);
12124 else f2 = NULL;
12125 f1 = myrpt->lastf2;
12126 myrpt->lastf2 = myrpt->lastf1;
12127 myrpt->lastf1 = f2;
12128 if (ismuted)
12129 {
12130 if (myrpt->lastf1)
12131 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12132 if (myrpt->lastf2)
12133 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12134 }
12135 if (f1)
12136 {
12137 ast_write(myrpt->pchannel,f1);
12138 ast_frfree(f1);
12139 }
12140 }
12141 #ifndef OLD_ASTERISK
12142 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12143 {
12144 if (myrpt->lastf1)
12145 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12146 if (myrpt->lastf2)
12147 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12148 dtmfed = 1;
12149 }
12150 #endif
12151 else if (f->frametype == AST_FRAME_DTMF)
12152 {
12153 c = (char) f->subclass.integer;
12154 ast_frfree(f);
12155 if (myrpt->lastf1)
12156 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12157 if (myrpt->lastf2)
12158 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12159 dtmfed = 1;
12160 if (!myrpt->keyed) continue;
12161 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12162 if (c) local_dtmf_helper(myrpt,c);
12163 continue;
12164 }
12165 else if (f->frametype == AST_FRAME_CONTROL)
12166 {
12167 if (f->subclass.integer == AST_CONTROL_HANGUP)
12168 {
12169 if (debug) printf("@@@@ rpt:Hung Up\n");
12170 ast_frfree(f);
12171 break;
12172 }
12173
12174 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12175 {
12176 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12177 {
12178 if (debug == 7) printf("@@@@ rx key\n");
12179 myrpt->keyed = 1;
12180 time(&myrpt->lastkeyedtime);
12181 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12182 }
12183 if (myrpt->p.archivedir)
12184 {
12185 donodelog(myrpt,"RXKEY,MAIN");
12186 }
12187 if (f->datalen && f->data.ptr)
12188 {
12189 char busy = 0;
12190
12191 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12192
12193 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12194 {
12195 char value[16] = "";
12196 strcat(value,"*6");
12197 myrpt->macropatch=1;
12198 rpt_mutex_lock(&myrpt->lock);
12199 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12200 rpt_mutex_unlock(&myrpt->lock);
12201 busy=1;
12202 }
12203 if(!busy){
12204 myrpt->macrotimer = MACROTIME;
12205 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12206 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12207 }
12208 rpt_mutex_unlock(&myrpt->lock);
12209 }
12210 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12211 {
12212 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12213 if (value)
12214 {
12215 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12216 rpt_mutex_lock(&myrpt->lock);
12217 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12218 rpt_mutex_unlock(&myrpt->lock);
12219 busy=1;
12220 }
12221 if(!busy){
12222 myrpt->macrotimer = MACROTIME;
12223 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12224 }
12225 rpt_mutex_unlock(&myrpt->lock);
12226 }
12227 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12228 }
12229 } else myrpt->lasttone[0] = 0;
12230 }
12231
12232 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12233 {
12234 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12235 {
12236 if (debug == 7) printf("@@@@ rx un-key\n");
12237 if(myrpt->p.duplex && myrpt->keyed) {
12238 rpt_telemetry(myrpt,UNKEY,NULL);
12239 }
12240 }
12241 myrpt->keyed = 0;
12242 time(&myrpt->lastkeyedtime);
12243 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12244 if (myrpt->p.archivedir)
12245 {
12246 donodelog(myrpt,"RXUNKEY,MAIN");
12247 }
12248 }
12249 }
12250 ast_frfree(f);
12251 continue;
12252 }
12253 if (who == myrpt->pchannel)
12254 {
12255 f = ast_read(myrpt->pchannel);
12256 if (!f)
12257 {
12258 if (debug) printf("@@@@ rpt:Hung Up\n");
12259 break;
12260 }
12261 if (f->frametype == AST_FRAME_VOICE)
12262 {
12263 ast_write(myrpt->txpchannel,f);
12264 }
12265 if (f->frametype == AST_FRAME_CONTROL)
12266 {
12267 if (f->subclass.integer == AST_CONTROL_HANGUP)
12268 {
12269 if (debug) printf("@@@@ rpt:Hung Up\n");
12270 ast_frfree(f);
12271 break;
12272 }
12273 }
12274 ast_frfree(f);
12275 continue;
12276 }
12277 if (who == myrpt->txchannel)
12278 {
12279 f = ast_read(myrpt->txchannel);
12280 if (!f)
12281 {
12282 if (debug) printf("@@@@ rpt:Hung Up\n");
12283 break;
12284 }
12285 if (f->frametype == AST_FRAME_CONTROL)
12286 {
12287 if (f->subclass.integer == AST_CONTROL_HANGUP)
12288 {
12289 if (debug) printf("@@@@ rpt:Hung Up\n");
12290 ast_frfree(f);
12291 break;
12292 }
12293 }
12294 ast_frfree(f);
12295 continue;
12296 }
12297 if (who == myrpt->dahditxchannel)
12298 {
12299 f = ast_read(myrpt->dahditxchannel);
12300 if (!f)
12301 {
12302 if (debug) printf("@@@@ rpt:Hung Up\n");
12303 break;
12304 }
12305 if (f->frametype == AST_FRAME_VOICE)
12306 {
12307 struct ast_frame *vframe;
12308
12309 if (myrpt->p.duplex < 2)
12310 {
12311 if (myrpt->txrealkeyed)
12312 {
12313 if ((!myfirst) && myrpt->callmode)
12314 {
12315 x = 0;
12316 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12317 frame_list) x++;
12318 for(;x < myrpt->p.simplexpatchdelay; x++)
12319 {
12320 vframe = ast_frdup(f);
12321 memset(vframe->data.ptr,0,vframe->datalen);
12322 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12323 }
12324 myfirst = 1;
12325 }
12326 vframe = ast_frdup(f);
12327 AST_LIST_INSERT_TAIL(&myrpt->txq,
12328 vframe,frame_list);
12329 } else myfirst = 0;
12330 x = 0;
12331 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12332 frame_list) x++;
12333 if (!x)
12334 {
12335 memset(f->data.ptr,0,f->datalen);
12336 }
12337 else
12338 {
12339 ast_frfree(f);
12340 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12341 frame_list);
12342 }
12343 }
12344 else
12345 {
12346 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12347 frame_list))) ast_frfree(vframe);
12348 }
12349 ast_write(myrpt->txchannel,f);
12350 }
12351 if (f->frametype == AST_FRAME_CONTROL)
12352 {
12353 if (f->subclass.integer == AST_CONTROL_HANGUP)
12354 {
12355 if (debug) printf("@@@@ rpt:Hung Up\n");
12356 ast_frfree(f);
12357 break;
12358 }
12359 }
12360 ast_frfree(f);
12361 continue;
12362 }
12363 toexit = 0;
12364 rpt_mutex_lock(&myrpt->lock);
12365 l = myrpt->links.next;
12366 while(l != &myrpt->links)
12367 {
12368 int remnomute;
12369 struct timeval now;
12370
12371 if (l->disctime)
12372 {
12373 l = l->next;
12374 continue;
12375 }
12376
12377 remrx = 0;
12378
12379 m = myrpt->links.next;
12380 while(m != &myrpt->links)
12381 {
12382
12383 if ((m != l) && (m->lastrx)) remrx = 1;
12384 m = m->next;
12385 }
12386 rpt_mutex_unlock(&myrpt->lock);
12387 now = ast_tvnow();
12388 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12389 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12390 {
12391 l->lastlinktv = now;
12392 remnomute = myrpt->localtx &&
12393 (!(myrpt->cmdnode[0] ||
12394 (myrpt->dtmfidx > -1)));
12395 totx = (((l->isremote) ? (remnomute) :
12396 myrpt->exttx) || remrx) && l->mode;
12397 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12398 {
12399 if (totx)
12400 {
12401 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12402 }
12403 else
12404 {
12405 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12406 }
12407 if (myrpt->p.archivedir)
12408 {
12409 char str[100];
12410
12411 if (totx)
12412 sprintf(str,"TXKEY,%s",l->name);
12413 else
12414 sprintf(str,"TXUNKEY,%s",l->name);
12415 donodelog(myrpt,str);
12416 }
12417 }
12418 l->lasttx = totx;
12419 }
12420 rpt_mutex_lock(&myrpt->lock);
12421 if (who == l->chan)
12422 {
12423 rpt_mutex_unlock(&myrpt->lock);
12424 f = ast_read(l->chan);
12425 if (!f)
12426 {
12427 rpt_mutex_lock(&myrpt->lock);
12428 __kickshort(myrpt);
12429 rpt_mutex_unlock(&myrpt->lock);
12430 if ((!l->disced) && (!l->outbound))
12431 {
12432 if ((l->name[0] == '0') || l->isremote)
12433 l->disctime = 1;
12434 else
12435 l->disctime = DISC_TIME;
12436 rpt_mutex_lock(&myrpt->lock);
12437 ast_hangup(l->chan);
12438 l->chan = 0;
12439 break;
12440 }
12441
12442 if (l->retrytimer)
12443 {
12444 ast_hangup(l->chan);
12445 l->chan = 0;
12446 rpt_mutex_lock(&myrpt->lock);
12447 break;
12448 }
12449 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12450 {
12451 rpt_mutex_lock(&myrpt->lock);
12452 if (l->chan) ast_hangup(l->chan);
12453 l->chan = 0;
12454 l->hasconnected = 1;
12455 l->retrytimer = RETRY_TIMER_MS;
12456 l->elaptime = 0;
12457 l->connecttime = 0;
12458 l->thisconnected = 0;
12459 break;
12460 }
12461 rpt_mutex_lock(&myrpt->lock);
12462
12463 remque((struct qelem *) l);
12464 if (!strcmp(myrpt->cmdnode,l->name))
12465 myrpt->cmdnode[0] = 0;
12466 __kickshort(myrpt);
12467 rpt_mutex_unlock(&myrpt->lock);
12468 if (!l->hasconnected)
12469 rpt_telemetry(myrpt,CONNFAIL,l);
12470 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12471 if (myrpt->p.archivedir)
12472 {
12473 char str[100];
12474
12475 if (!l->hasconnected)
12476 sprintf(str,"LINKFAIL,%s",l->name);
12477 else
12478 sprintf(str,"LINKDISC,%s",l->name);
12479 donodelog(myrpt,str);
12480 }
12481 if (l->lastf1) ast_frfree(l->lastf1);
12482 l->lastf1 = NULL;
12483 if (l->lastf2) ast_frfree(l->lastf2);
12484 l->lastf2 = NULL;
12485
12486 ast_hangup(l->chan);
12487 ast_hangup(l->pchan);
12488 ast_free(l);
12489 rpt_mutex_lock(&myrpt->lock);
12490 break;
12491 }
12492 if (f->frametype == AST_FRAME_VOICE)
12493 {
12494 int ismuted,n1;
12495
12496 if ((l->phonemode) && (l->phonevox))
12497 {
12498 n1 = dovox(&l->vox,
12499 f->data.ptr,f->datalen / 2);
12500 if (n1 != l->wasvox)
12501 {
12502 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12503 l->wasvox = n1;
12504 l->voxtostate = 0;
12505 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12506 else l->voxtotimer = 0;
12507 }
12508 if (l->lastrealrx || n1)
12509 {
12510 if (!myfirst)
12511 {
12512 x = 0;
12513 AST_LIST_TRAVERSE(&l->rxq, f1,
12514 frame_list) x++;
12515 for(;x < myrpt->p.simplexphonedelay; x++)
12516 {
12517 f1 = ast_frdup(f);
12518 memset(f1->data.ptr,0,f1->datalen);
12519 AST_LIST_INSERT_TAIL(&l->rxq,
12520 f1,frame_list);
12521 }
12522 myfirst = 1;
12523 }
12524 f1 = ast_frdup(f);
12525 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12526 } else myfirst = 0;
12527 x = 0;
12528 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12529 if (!x)
12530 {
12531 memset(f->data.ptr,0,f->datalen);
12532 }
12533 else
12534 {
12535 ast_frfree(f);
12536 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12537 }
12538 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12539 {
12540 ismuted = 0;
12541 }
12542
12543 ismuted |= (!l->lastrx);
12544 if (l->dtmfed && l->phonemode) ismuted = 1;
12545 l->dtmfed = 0;
12546 if (ismuted)
12547 {
12548 memset(f->data.ptr,0,f->datalen);
12549 if (l->lastf1)
12550 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12551 if (l->lastf2)
12552 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12553 }
12554 if (f) f2 = ast_frdup(f);
12555 else f2 = NULL;
12556 f1 = l->lastf2;
12557 l->lastf2 = l->lastf1;
12558 l->lastf1 = f2;
12559 if (ismuted)
12560 {
12561 if (l->lastf1)
12562 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12563 if (l->lastf2)
12564 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12565 }
12566 if (f1)
12567 {
12568 ast_write(l->pchan,f1);
12569 ast_frfree(f1);
12570 }
12571 }
12572 else
12573 {
12574 if (!l->lastrx)
12575 memset(f->data.ptr,0,f->datalen);
12576 ast_write(l->pchan,f);
12577 }
12578 }
12579 #ifndef OLD_ASTERISK
12580 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12581 {
12582 if (l->lastf1)
12583 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12584 if (l->lastf2)
12585 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12586 l->dtmfed = 1;
12587 }
12588 #endif
12589 if (f->frametype == AST_FRAME_TEXT)
12590 {
12591 handle_link_data(myrpt,l,f->data.ptr);
12592 }
12593 if (f->frametype == AST_FRAME_DTMF)
12594 {
12595 if (l->lastf1)
12596 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12597 if (l->lastf2)
12598 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12599 l->dtmfed = 1;
12600 handle_link_phone_dtmf(myrpt,l,f->subclass.integer);
12601 }
12602 if (f->frametype == AST_FRAME_CONTROL)
12603 {
12604 if (f->subclass.integer == AST_CONTROL_ANSWER)
12605 {
12606 char lconnected = l->connected;
12607
12608 __kickshort(myrpt);
12609 l->connected = 1;
12610 l->hasconnected = 1;
12611 l->thisconnected = 1;
12612 l->elaptime = -1;
12613 if (!l->phonemode) send_newkey(l->chan);
12614 if (!l->isremote) l->retries = 0;
12615 if (!lconnected)
12616 {
12617 rpt_telemetry(myrpt,CONNECTED,l);
12618 if (myrpt->p.archivedir)
12619 {
12620 char str[100];
12621
12622 if (l->mode)
12623 sprintf(str,"LINKTRX,%s",l->name);
12624 else
12625 sprintf(str,"LINKMONITOR,%s",l->name);
12626 donodelog(myrpt,str);
12627 }
12628 }
12629 else
12630 l->reconnects++;
12631 }
12632
12633 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12634 {
12635 if (debug == 7 ) printf("@@@@ rx key\n");
12636 l->lastrealrx = 1;
12637 l->rerxtimer = 0;
12638 if (!l->lastrx1)
12639 {
12640 if (myrpt->p.archivedir)
12641 {
12642 char str[100];
12643
12644 sprintf(str,"RXKEY,%s",l->name);
12645 donodelog(myrpt,str);
12646 }
12647 l->lastrx1 = 1;
12648 }
12649 }
12650
12651 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12652 {
12653 if (debug == 7) printf("@@@@ rx un-key\n");
12654 l->lastrealrx = 0;
12655 l->rerxtimer = 0;
12656 if (l->lastrx1)
12657 {
12658 if (myrpt->p.archivedir)
12659 {
12660 char str[100];
12661
12662 sprintf(str,"RXUNKEY,%s",l->name);
12663 donodelog(myrpt,str);
12664 }
12665 l->lastrx1 = 0;
12666 if(myrpt->p.duplex)
12667 rpt_telemetry(myrpt,LINKUNKEY,l);
12668 }
12669 }
12670 if (f->subclass.integer == AST_CONTROL_HANGUP)
12671 {
12672 ast_frfree(f);
12673 rpt_mutex_lock(&myrpt->lock);
12674 __kickshort(myrpt);
12675 rpt_mutex_unlock(&myrpt->lock);
12676 if ((!l->outbound) && (!l->disced))
12677 {
12678 if ((l->name[0] == '0') || l->isremote)
12679 l->disctime = 1;
12680 else
12681 l->disctime = DISC_TIME;
12682 rpt_mutex_lock(&myrpt->lock);
12683 ast_hangup(l->chan);
12684 l->chan = 0;
12685 break;
12686 }
12687 if (l->retrytimer)
12688 {
12689 if (l->chan) ast_hangup(l->chan);
12690 l->chan = 0;
12691 rpt_mutex_lock(&myrpt->lock);
12692 break;
12693 }
12694 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12695 {
12696 rpt_mutex_lock(&myrpt->lock);
12697 if (l->chan) ast_hangup(l->chan);
12698 l->chan = 0;
12699 l->hasconnected = 1;
12700 l->elaptime = 0;
12701 l->retrytimer = RETRY_TIMER_MS;
12702 l->connecttime = 0;
12703 l->thisconnected = 0;
12704 break;
12705 }
12706 rpt_mutex_lock(&myrpt->lock);
12707
12708 remque((struct qelem *) l);
12709 if (!strcmp(myrpt->cmdnode,l->name))
12710 myrpt->cmdnode[0] = 0;
12711 __kickshort(myrpt);
12712 rpt_mutex_unlock(&myrpt->lock);
12713 if (!l->hasconnected)
12714 rpt_telemetry(myrpt,CONNFAIL,l);
12715 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12716 if (myrpt->p.archivedir)
12717 {
12718 char str[100];
12719
12720 if (!l->hasconnected)
12721 sprintf(str,"LINKFAIL,%s",l->name);
12722 else
12723 sprintf(str,"LINKDISC,%s",l->name);
12724 donodelog(myrpt,str);
12725 }
12726 if (l->lastf1) ast_frfree(l->lastf1);
12727 l->lastf1 = NULL;
12728 if (l->lastf2) ast_frfree(l->lastf2);
12729 l->lastf2 = NULL;
12730
12731 ast_hangup(l->chan);
12732 ast_hangup(l->pchan);
12733 ast_free(l);
12734 rpt_mutex_lock(&myrpt->lock);
12735 break;
12736 }
12737 }
12738 ast_frfree(f);
12739 rpt_mutex_lock(&myrpt->lock);
12740 break;
12741 }
12742 if (who == l->pchan)
12743 {
12744 rpt_mutex_unlock(&myrpt->lock);
12745 f = ast_read(l->pchan);
12746 if (!f)
12747 {
12748 if (debug) printf("@@@@ rpt:Hung Up\n");
12749 toexit = 1;
12750 rpt_mutex_lock(&myrpt->lock);
12751 break;
12752 }
12753 if (f->frametype == AST_FRAME_VOICE)
12754 {
12755 if (l->chan) ast_write(l->chan,f);
12756 }
12757 if (f->frametype == AST_FRAME_CONTROL)
12758 {
12759 if (f->subclass.integer == AST_CONTROL_HANGUP)
12760 {
12761 if (debug) printf("@@@@ rpt:Hung Up\n");
12762 ast_frfree(f);
12763 toexit = 1;
12764 rpt_mutex_lock(&myrpt->lock);
12765 break;
12766 }
12767 }
12768 ast_frfree(f);
12769 rpt_mutex_lock(&myrpt->lock);
12770 break;
12771 }
12772 l = l->next;
12773 }
12774 rpt_mutex_unlock(&myrpt->lock);
12775 if (toexit) break;
12776 if (who == myrpt->monchannel)
12777 {
12778 f = ast_read(myrpt->monchannel);
12779 if (!f)
12780 {
12781 if (debug) printf("@@@@ rpt:Hung Up\n");
12782 break;
12783 }
12784 if (f->frametype == AST_FRAME_VOICE)
12785 {
12786 if (myrpt->monstream)
12787 ast_writestream(myrpt->monstream,f);
12788 }
12789 if (f->frametype == AST_FRAME_CONTROL)
12790 {
12791 if (f->subclass.integer == AST_CONTROL_HANGUP)
12792 {
12793 if (debug) printf("@@@@ rpt:Hung Up\n");
12794 ast_frfree(f);
12795 break;
12796 }
12797 }
12798 ast_frfree(f);
12799 continue;
12800 }
12801 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12802 {
12803 f = ast_read(myrpt->parrotchannel);
12804 if (!f)
12805 {
12806 if (debug) printf("@@@@ rpt:Hung Up\n");
12807 break;
12808 }
12809 if (!myrpt->p.parrotmode)
12810 {
12811 char myfname[300];
12812
12813 if (myrpt->parrotstream)
12814 {
12815 ast_closestream(myrpt->parrotstream);
12816 myrpt->parrotstream = 0;
12817 }
12818 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12819 strcat(myfname,".wav");
12820 unlink(myfname);
12821 } else if (f->frametype == AST_FRAME_VOICE)
12822 {
12823 if (myrpt->parrotstream)
12824 ast_writestream(myrpt->parrotstream,f);
12825 }
12826 if (f->frametype == AST_FRAME_CONTROL)
12827 {
12828 if (f->subclass.integer == AST_CONTROL_HANGUP)
12829 {
12830 if (debug) printf("@@@@ rpt:Hung Up\n");
12831 ast_frfree(f);
12832 break;
12833 }
12834 }
12835 ast_frfree(f);
12836 continue;
12837 }
12838 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12839 {
12840 f = ast_read(myrpt->voxchannel);
12841 if (!f)
12842 {
12843 if (debug) printf("@@@@ rpt:Hung Up\n");
12844 break;
12845 }
12846 if (f->frametype == AST_FRAME_VOICE)
12847 {
12848 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12849 if (n != myrpt->wasvox)
12850 {
12851 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12852 myrpt->wasvox = n;
12853 myrpt->voxtostate = 0;
12854 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12855 else myrpt->voxtotimer = 0;
12856 }
12857 }
12858 if (f->frametype == AST_FRAME_CONTROL)
12859 {
12860 if (f->subclass.integer == AST_CONTROL_HANGUP)
12861 {
12862 if (debug) printf("@@@@ rpt:Hung Up\n");
12863 ast_frfree(f);
12864 break;
12865 }
12866 }
12867 ast_frfree(f);
12868 continue;
12869 }
12870 if (who == myrpt->txpchannel)
12871 {
12872 f = ast_read(myrpt->txpchannel);
12873 if (!f)
12874 {
12875 if (debug) printf("@@@@ rpt:Hung Up\n");
12876 break;
12877 }
12878 if (f->frametype == AST_FRAME_CONTROL)
12879 {
12880 if (f->subclass.integer == AST_CONTROL_HANGUP)
12881 {
12882 if (debug) printf("@@@@ rpt:Hung Up\n");
12883 ast_frfree(f);
12884 break;
12885 }
12886 }
12887 ast_frfree(f);
12888 continue;
12889 }
12890 }
12891 usleep(100000);
12892 ast_hangup(myrpt->pchannel);
12893 ast_hangup(myrpt->monchannel);
12894 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12895 myrpt->parrotstate = 0;
12896 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12897 ast_hangup(myrpt->txpchannel);
12898 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12899 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12900 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12901 myrpt->lastf1 = NULL;
12902 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12903 myrpt->lastf2 = NULL;
12904 ast_hangup(myrpt->rxchannel);
12905 rpt_mutex_lock(&myrpt->lock);
12906 l = myrpt->links.next;
12907 while(l != &myrpt->links)
12908 {
12909 struct rpt_link *ll = l;
12910
12911 remque((struct qelem *) l);
12912
12913 if (l->chan) ast_hangup(l->chan);
12914 ast_hangup(l->pchan);
12915 l = l->next;
12916 ast_free(ll);
12917 }
12918 if (myrpt->xlink == 1) myrpt->xlink = 2;
12919 rpt_mutex_unlock(&myrpt->lock);
12920 if (debug) printf("@@@@ rpt:Hung up channel\n");
12921 myrpt->rpt_thread = AST_PTHREADT_STOP;
12922 pthread_exit(NULL);
12923 return NULL;
12924 }
12925
12926
12927 static void *rpt_master(void *ignore)
12928 {
12929 int i,n;
12930 pthread_attr_t attr;
12931 struct ast_config *cfg;
12932 char *this,*val;
12933
12934
12935 nodelog.next = nodelog.prev = &nodelog;
12936
12937 this = NULL;
12938 n = 0;
12939 #ifndef OLD_ASTERISK
12940
12941 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12942 usleep(250000);
12943 #endif
12944 #ifdef NEW_ASTERISK
12945 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12946 #else
12947 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12948 #endif
12949 cfg = rpt_vars[n].cfg;
12950 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12951 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12952 pthread_exit(NULL);
12953 }
12954 while((this = ast_category_browse(cfg,this)) != NULL)
12955 {
12956 for(i = 0 ; i < strlen(this) ; i++){
12957 if((this[i] < '0') || (this[i] > '9'))
12958 break;
12959 }
12960 if(i != strlen(this)) continue;
12961 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12962 rpt_vars[n].name = ast_strdup(this);
12963 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12964 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12965 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12966 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12967 rpt_vars[n].remote = 0;
12968 rpt_vars[n].remoterig = "";
12969 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12970 if (val)
12971 {
12972 rpt_vars[n].remoterig = ast_strdup(val);
12973 rpt_vars[n].remote = 1;
12974 }
12975 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12976 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12977 ast_mutex_init(&rpt_vars[n].lock);
12978 ast_mutex_init(&rpt_vars[n].remlock);
12979 ast_mutex_init(&rpt_vars[n].statpost_lock);
12980 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12981 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12982 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12983 rpt_vars[n].tailmessagen = 0;
12984 #ifdef _MDC_DECODE_H_
12985 rpt_vars[n].mdc = mdc_decoder_new(8000);
12986 #endif
12987 n++;
12988 }
12989 nrpts = n;
12990 ast_config_destroy(cfg);
12991
12992
12993 for(i = 0; i < n; i++)
12994 {
12995 load_rpt_vars(i,1);
12996
12997
12998 if (rpt_vars[i].remote)
12999 {
13000 if(retreive_memory(&rpt_vars[i],"init")){
13001 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13002 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13003 else
13004 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13005 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13006
13007 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13008 rpt_vars[i].remmode = REM_MODE_FM;
13009 rpt_vars[i].offset = REM_SIMPLEX;
13010 rpt_vars[i].powerlevel = REM_LOWPWR;
13011 }
13012 continue;
13013 }
13014 else
13015 {
13016 rpt_vars[i].p.memory = rpt_vars[i].name;
13017 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13018 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13019 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13020 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13021 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13022 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13023
13024 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13025 rpt_vars[i].remmode = REM_MODE_FM;
13026 rpt_vars[i].offset = REM_SIMPLEX;
13027 rpt_vars[i].powerlevel = REM_LOWPWR;
13028 }
13029 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13030 }
13031 if (!rpt_vars[i].p.ident)
13032 {
13033 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13034 ast_config_destroy(cfg);
13035 pthread_exit(NULL);
13036 }
13037 pthread_attr_init(&attr);
13038 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13039 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13040 }
13041 usleep(500000);
13042 time(&starttime);
13043 for(;;)
13044 {
13045
13046 for(i = 0; i < n; i++)
13047 {
13048 int rv;
13049 if (rpt_vars[i].remote) continue;
13050 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13051 rv = -1;
13052 else
13053 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13054 if (rv)
13055 {
13056 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13057 {
13058 if(rpt_vars[i].threadrestarts >= 5)
13059 {
13060 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13061 exit(1);
13062 }
13063 else
13064 {
13065 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13066 rpt_vars[i].threadrestarts++;
13067 }
13068 }
13069 else
13070 rpt_vars[i].threadrestarts = 0;
13071
13072 rpt_vars[i].lastthreadrestarttime = time(NULL);
13073 pthread_attr_init(&attr);
13074 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13075 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13076
13077 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13078 }
13079
13080 }
13081 for(;;)
13082 {
13083 struct nodelog *nodep;
13084 char *space,datestr[100],fname[300];
13085 int fd;
13086
13087 ast_mutex_lock(&nodeloglock);
13088 nodep = nodelog.next;
13089 if(nodep == &nodelog)
13090 {
13091 ast_mutex_unlock(&nodeloglock);
13092 break;
13093 }
13094 remque((struct qelem *)nodep);
13095 ast_mutex_unlock(&nodeloglock);
13096 space = strchr(nodep->str,' ');
13097 if (!space)
13098 {
13099 ast_free(nodep);
13100 continue;
13101 }
13102 *space = 0;
13103 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13104 localtime(&nodep->timestamp));
13105 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13106 nodep->str,datestr);
13107 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13108 if (fd == -1)
13109 {
13110 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13111 ast_free(nodep);
13112 continue;
13113 }
13114 if (write(fd,space + 1,strlen(space + 1)) !=
13115 strlen(space + 1))
13116 {
13117 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13118 ast_free(nodep);
13119 continue;
13120 }
13121 close(fd);
13122 ast_free(nodep);
13123 }
13124 sleep(2);
13125 }
13126 ast_config_destroy(cfg);
13127 pthread_exit(NULL);
13128 }
13129
13130 static int rpt_exec(struct ast_channel *chan, const char *data)
13131 {
13132 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13133 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13134 int ismuted,dtmfed,phone_vox = 0;
13135 #ifdef OLD_ASTERISK
13136 struct localuser *u;
13137 #endif
13138 char tmp[256], keyed = 0,keyed1 = 0;
13139 char *options,*stringp,*tele,c,*altp,*memp;
13140 char sx[320],*sy;
13141 struct rpt *myrpt;
13142 struct ast_frame *f,*f1,*f2;
13143 struct ast_channel *who;
13144 struct ast_channel *cs[20];
13145 struct rpt_link *l;
13146 struct dahdi_confinfo ci;
13147 struct dahdi_params par;
13148 int ms,elap,nullfd;
13149 time_t t,last_timeout_warning;
13150 struct dahdi_radio_param z;
13151 struct rpt_tele *telem;
13152 int numlinks;
13153
13154 nullfd = open("/dev/null",O_RDWR);
13155 if (ast_strlen_zero(data)) {
13156 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13157 return -1;
13158 }
13159
13160 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13161 time(&t);
13162
13163 if (t < starttime) t = starttime + START_DELAY;
13164 if ((!starttime) || (t < (starttime + START_DELAY)))
13165 {
13166 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13167 ast_safe_sleep(chan,3000);
13168 return -1;
13169 }
13170
13171 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13172
13173 altp=strstr(tmp, "|*");
13174 if(altp){
13175 altp[0]=0;
13176 altp++;
13177 }
13178
13179 memp=strstr(tmp, "|M");
13180 if(memp){
13181 memp[0]=0;
13182 memp+=2;
13183 }
13184
13185 stringp=tmp;
13186 strsep(&stringp, "|");
13187 options = stringp;
13188
13189 ast_log(LOG_NOTICE,"options=%s \n",options);
13190 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13191 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13192
13193 myrpt = NULL;
13194
13195 for(i = 0; i < nrpts; i++)
13196 {
13197
13198 if (!strcmp(tmp,rpt_vars[i].name))
13199 {
13200 myrpt = &rpt_vars[i];
13201 break;
13202 }
13203 }
13204
13205 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13206
13207 if (myrpt == NULL)
13208 {
13209 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13210 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13211 return (priority_jump(NULL,chan));
13212 }
13213
13214 numlinks=linkcount(myrpt);
13215
13216 if(options && *options == 'q')
13217 {
13218 char buf2[128];
13219
13220 if(myrpt->keyed)
13221 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13222 else
13223 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13224
13225 if(myrpt->txkeyed)
13226 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13227 else
13228 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13229
13230 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13231 pbx_builtin_setvar(chan, buf2);
13232 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13233 pbx_builtin_setvar(chan, buf2);
13234 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13235 pbx_builtin_setvar(chan, buf2);
13236 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13237 pbx_builtin_setvar(chan, buf2);
13238 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13239 pbx_builtin_setvar(chan, buf2);
13240 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13241 pbx_builtin_setvar(chan, buf2);
13242
13243
13244
13245
13246 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13247 pbx_builtin_setvar(chan, buf2);
13248 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13249 pbx_builtin_setvar(chan, buf2);
13250
13251 return priority_jump(myrpt,chan);
13252 }
13253
13254 if(options && *options == 'o')
13255 {
13256 return(channel_revert(myrpt));
13257 }
13258
13259 #if 0
13260 if((altp)&&(*options == 'Z'))
13261 {
13262 rpt_push_alt_macro(myrpt,altp);
13263 return 0;
13264 }
13265 #endif
13266
13267
13268
13269 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13270 {
13271 int val;
13272
13273 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13274
13275 myrpt->bargechan=0;
13276 if(options && strstr(options, "f")>0)
13277 {
13278 myrpt->bargechan=1;
13279 }
13280
13281 if(memp>0)
13282 {
13283 char radiochan;
13284 radiochan=strtod(data,NULL);
13285
13286
13287 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13288 {
13289 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13290 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13291 return (priority_jump(myrpt,chan));
13292 }
13293 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13294 {
13295 channel_steer(myrpt,memp);
13296 }
13297 }
13298 if(altp)rpt_push_alt_macro(myrpt,altp);
13299 phone_mode = 1;
13300 if (*options == 'D') phone_mode = 2;
13301 if (*options == 'S') phone_mode = 3;
13302 ast_set_callerid(chan,"0","app_rpt user","0");
13303 val = 1;
13304 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13305 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13306 }
13307 else
13308 {
13309 #ifdef ALLOW_LOCAL_CHANNELS
13310
13311 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13312 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13313 return -1;
13314 }
13315 #else
13316 if (strncmp(chan->name,"IAX2",4))
13317 {
13318 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13319 return -1;
13320 }
13321 #endif
13322 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13323 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13324 return -1;
13325 }
13326 }
13327 if (options && (*options == 'R'))
13328 {
13329
13330 char *return_context;
13331 int length, m, lot, timeout = 0;
13332 char buffer[256],*template;
13333 char *working, *context, *exten, *priority;
13334 char *s,*orig_s;
13335
13336 rpt_mutex_lock(&myrpt->lock);
13337 m = myrpt->callmode;
13338 rpt_mutex_unlock(&myrpt->lock);
13339
13340 if ((!myrpt->p.nobusyout) && m)
13341 {
13342 if (chan->_state != AST_STATE_UP)
13343 {
13344 ast_indicate(chan,AST_CONTROL_BUSY);
13345 }
13346 while(ast_safe_sleep(chan,10000) != -1);
13347 return -1;
13348 }
13349
13350 if (chan->_state != AST_STATE_UP)
13351 {
13352 ast_answer(chan);
13353 if (!phone_mode) send_newkey(chan);
13354 }
13355
13356 length=strlen(options)+2;
13357 orig_s=ast_malloc(length);
13358 if(!orig_s) {
13359 ast_log(LOG_WARNING, "Out of memory\n");
13360 return -1;
13361 }
13362 s=orig_s;
13363 strncpy(s,options,length);
13364
13365 template=strsep(&s,"|");
13366 if(!template) {
13367 ast_log(LOG_WARNING, "An announce template must be defined\n");
13368 ast_free(orig_s);
13369 return -1;
13370 }
13371
13372 if(s) {
13373 timeout = atoi(strsep(&s, "|"));
13374 timeout *= 1000;
13375 }
13376
13377 return_context = s;
13378
13379 if(return_context != NULL) {
13380
13381
13382 working = return_context;
13383 context = strsep(&working, "|");
13384 exten = strsep(&working, "|");
13385 if(!exten) {
13386
13387 priority = context;
13388 exten = NULL;
13389 context = NULL;
13390 } else {
13391 priority = strsep(&working, "|");
13392 if(!priority) {
13393
13394 priority = exten;
13395 exten = context;
13396 context = NULL;
13397 }
13398 }
13399 if(atoi(priority) < 0) {
13400 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13401 ast_free(orig_s);
13402 return -1;
13403 }
13404
13405 chan->priority = atoi(priority);
13406 #ifdef OLD_ASTERISK
13407 if(exten && strcasecmp(exten, "BYEXTENSION"))
13408 #else
13409 if(exten)
13410 #endif
13411 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13412 if(context)
13413 strncpy(chan->context, context, sizeof(chan->context)-1);
13414 } else {
13415 chan->priority++;
13416 }
13417
13418 if(option_verbose > 2) {
13419 ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n",
13420 chan->context, chan->exten, chan->priority,
13421 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
13422 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
13423 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
13424 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13425 }
13426 }
13427
13428
13429
13430
13431 ast_masq_park_call(chan, NULL, timeout, &lot);
13432
13433 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13434
13435 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13436
13437 rpt_telemetry(myrpt,REV_PATCH,buffer);
13438
13439 ast_free(orig_s);
13440
13441 return 0;
13442
13443 }
13444
13445 if (!options)
13446 {
13447 struct ast_hostent ahp;
13448 struct hostent *hp;
13449 struct in_addr ia;
13450 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13451
13452
13453 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13454 if (!b)
13455 {
13456 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13457 return -1;
13458 }
13459
13460 memset(hisip,0,sizeof(hisip));
13461 #ifdef ALLOW_LOCAL_CHANNELS
13462
13463 if (strncmp(chan->name,"Local",5)==0) {
13464 strcpy(hisip,"127.0.0.1");
13465 } else {
13466 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13467 }
13468 #else
13469 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13470 #endif
13471
13472 if (!hisip[0])
13473 {
13474 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13475 return -1;
13476 }
13477
13478 b1 = ast_strdupa(b);
13479 ast_shrink_phone_number(b1);
13480 if (!strcmp(myrpt->name,b1))
13481 {
13482 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13483 return -1;
13484 }
13485
13486 if (*b1 < '1')
13487 {
13488 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13489 return -1;
13490 }
13491
13492
13493
13494 val = node_lookup(myrpt,b1);
13495 if (!val)
13496 {
13497 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13498 return -1;
13499 }
13500 strncpy(tmp,val,sizeof(tmp) - 1);
13501 s = tmp;
13502 s1 = strsep(&s,",");
13503 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13504 {
13505 sy = strchr(s1,'/');
13506 *sy = 0;
13507 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13508 s1 = sx;
13509 }
13510 s2 = strsep(&s,",");
13511 if (!s2)
13512 {
13513 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13514 return -1;
13515 }
13516 if (strcmp(s2,"NONE")) {
13517 hp = ast_gethostbyname(s2, &ahp);
13518 if (!hp)
13519 {
13520 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13521 return -1;
13522 }
13523 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13524 #ifdef OLD_ASTERISK
13525 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13526 #else
13527 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13528 #endif
13529 s3 = strchr(hisip,':');
13530 if (s3) *s3 = 0;
13531 if (strcmp(hisip,nodeip))
13532 {
13533 s3 = strchr(s1,'@');
13534 if (s3) s1 = s3 + 1;
13535 s3 = strchr(s1,'/');
13536 if (s3) *s3 = 0;
13537 s3 = strchr(s1,':');
13538 if (s3) *s3 = 0;
13539 hp = ast_gethostbyname(s1, &ahp);
13540 if (!hp)
13541 {
13542 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13543 return -1;
13544 }
13545 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13546 #ifdef OLD_ASTERISK
13547 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13548 #else
13549 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13550 #endif
13551 if (strcmp(hisip,nodeip))
13552 {
13553 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13554 return -1;
13555 }
13556 }
13557 }
13558 }
13559
13560
13561 if (!myrpt->remote)
13562 {
13563 char *b,*b1;
13564 int reconnects = 0;
13565
13566 rpt_mutex_lock(&myrpt->lock);
13567 i = myrpt->xlink;
13568 rpt_mutex_unlock(&myrpt->lock);
13569 if (i)
13570 {
13571 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13572 return -1;
13573 }
13574
13575 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13576 if (!b)
13577 {
13578 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13579 return -1;
13580 }
13581
13582 b1 = ast_strdupa(b);
13583 ast_shrink_phone_number(b1);
13584 if (!strcmp(myrpt->name,b1))
13585 {
13586 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13587 return -1;
13588 }
13589 rpt_mutex_lock(&myrpt->lock);
13590 l = myrpt->links.next;
13591
13592 while(l != &myrpt->links)
13593 {
13594 if (l->name[0] == '0')
13595 {
13596 l = l->next;
13597 continue;
13598 }
13599
13600 if (!strcmp(l->name,b1)) break;
13601 l = l->next;
13602 }
13603
13604 if (l != &myrpt->links)
13605 {
13606 l->killme = 1;
13607 l->retries = l->max_retries + 1;
13608 l->disced = 2;
13609 reconnects = l->reconnects;
13610 reconnects++;
13611 rpt_mutex_unlock(&myrpt->lock);
13612 usleep(500000);
13613 } else
13614 rpt_mutex_unlock(&myrpt->lock);
13615
13616 l = ast_malloc(sizeof(struct rpt_link));
13617 if (!l)
13618 {
13619 ast_log(LOG_WARNING, "Unable to malloc\n");
13620 pthread_exit(NULL);
13621 }
13622
13623 memset((char *)l,0,sizeof(struct rpt_link));
13624 l->mode = 1;
13625 strncpy(l->name,b1,MAXNODESTR - 1);
13626 l->isremote = 0;
13627 l->chan = chan;
13628 l->connected = 1;
13629 l->thisconnected = 1;
13630 l->hasconnected = 1;
13631 l->reconnects = reconnects;
13632 l->phonemode = phone_mode;
13633 l->phonevox = phone_vox;
13634 l->lastf1 = NULL;
13635 l->lastf2 = NULL;
13636 l->dtmfed = 0;
13637 voxinit_link(l,1);
13638 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13639 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13640
13641 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13642 if (!l->pchan)
13643 {
13644 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13645 pthread_exit(NULL);
13646 }
13647 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13648 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13649 #ifdef AST_CDR_FLAG_POST_DISABLED
13650 if (l->pchan->cdr)
13651 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13652 #endif
13653
13654 ci.chan = 0;
13655 ci.confno = myrpt->conf;
13656 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13657
13658 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13659 {
13660 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13661 pthread_exit(NULL);
13662 }
13663 rpt_mutex_lock(&myrpt->lock);
13664 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13665 l->max_retries = MAX_RETRIES;
13666
13667 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13668 __kickshort(myrpt);
13669 rpt_mutex_unlock(&myrpt->lock);
13670 if (chan->_state != AST_STATE_UP) {
13671 ast_answer(chan);
13672 if (!phone_mode) send_newkey(chan);
13673 }
13674 if (myrpt->p.archivedir)
13675 {
13676 char str[100];
13677
13678 if (l->phonemode)
13679 sprintf(str,"LINK(P),%s",l->name);
13680 else
13681 sprintf(str,"LINK,%s",l->name);
13682 donodelog(myrpt,str);
13683 }
13684 if (!phone_mode) send_newkey(chan);
13685 return 0;
13686 }
13687
13688 rpt_mutex_lock(&myrpt->lock);
13689
13690 if (myrpt->remoteon)
13691 {
13692 rpt_mutex_unlock(&myrpt->lock);
13693 usleep(500000);
13694 if (myrpt->remoteon)
13695 {
13696 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13697 #ifdef AST_CDR_FLAG_POST_DISABLED
13698 if (chan->cdr)
13699 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13700 #endif
13701 return -1;
13702 }
13703 rpt_mutex_lock(&myrpt->lock);
13704 }
13705 if (myrpt->p.rptnode)
13706 {
13707 char killedit = 0;
13708 time_t now;
13709
13710 time(&now);
13711 for(i = 0; i < nrpts; i++)
13712 {
13713 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13714 {
13715 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13716 rpt_vars[i].keyed ||
13717 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13718 rpt_vars[i].txkeyed ||
13719 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13720 {
13721 rpt_mutex_unlock(&myrpt->lock);
13722 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13723 #ifdef AST_CDR_FLAG_POST_DISABLED
13724 if (chan->cdr)
13725 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13726 #endif
13727 return -1;
13728 }
13729 while(rpt_vars[i].xlink != 3)
13730 {
13731 if (!killedit)
13732 {
13733 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13734 rpt_vars[i].xlink = 1;
13735 killedit = 1;
13736 }
13737 rpt_mutex_unlock(&myrpt->lock);
13738 if (ast_safe_sleep(chan,500) == -1)
13739 {
13740 #ifdef AST_CDR_FLAG_POST_DISABLED
13741 if (chan->cdr)
13742 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13743 #endif
13744 return -1;
13745 }
13746 rpt_mutex_lock(&myrpt->lock);
13747 }
13748 break;
13749 }
13750 }
13751 }
13752
13753 #ifdef HAVE_IOPERM
13754 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13755 (ioperm(myrpt->p.iobase,1,1) == -1))
13756 {
13757 rpt_mutex_unlock(&myrpt->lock);
13758 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13759 return -1;
13760 }
13761 #endif
13762 myrpt->remoteon = 1;
13763 #ifdef OLD_ASTERISK
13764 LOCAL_USER_ADD(u);
13765 #endif
13766 rpt_mutex_unlock(&myrpt->lock);
13767
13768 for(i = 0; i < nrpts; i++)
13769 {
13770 if (&rpt_vars[i] == myrpt)
13771 {
13772 load_rpt_vars(i,0);
13773 break;
13774 }
13775 }
13776 rpt_mutex_lock(&myrpt->lock);
13777 tele = strchr(myrpt->rxchanname,'/');
13778 if (!tele)
13779 {
13780 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13781 rpt_mutex_unlock(&myrpt->lock);
13782 pthread_exit(NULL);
13783 }
13784 *tele++ = 0;
13785 myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13786 myrpt->dahdirxchannel = NULL;
13787 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13788 myrpt->dahdirxchannel = myrpt->rxchannel;
13789 if (myrpt->rxchannel)
13790 {
13791 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13792 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13793 #ifdef AST_CDR_FLAG_POST_DISABLED
13794 if (myrpt->rxchannel->cdr)
13795 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13796 #endif
13797 #ifndef NEW_ASTERISK
13798 myrpt->rxchannel->whentohangup = 0;
13799 #endif
13800 myrpt->rxchannel->appl = "Apprpt";
13801 myrpt->rxchannel->data = "(Link Rx)";
13802 if (option_verbose > 2)
13803 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13804 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13805 rpt_mutex_unlock(&myrpt->lock);
13806 ast_call(myrpt->rxchannel,tele,999);
13807 rpt_mutex_lock(&myrpt->lock);
13808 }
13809 else
13810 {
13811 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13812 rpt_mutex_unlock(&myrpt->lock);
13813 pthread_exit(NULL);
13814 }
13815 *--tele = '/';
13816 myrpt->dahditxchannel = NULL;
13817 if (myrpt->txchanname)
13818 {
13819 tele = strchr(myrpt->txchanname,'/');
13820 if (!tele)
13821 {
13822 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13823 rpt_mutex_unlock(&myrpt->lock);
13824 ast_hangup(myrpt->rxchannel);
13825 pthread_exit(NULL);
13826 }
13827 *tele++ = 0;
13828 myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13829 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13830 myrpt->dahditxchannel = myrpt->txchannel;
13831 if (myrpt->txchannel)
13832 {
13833 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13834 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13835 #ifdef AST_CDR_FLAG_POST_DISABLED
13836 if (myrpt->txchannel->cdr)
13837 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13838 #endif
13839 #ifndef NEW_ASTERISK
13840 myrpt->txchannel->whentohangup = 0;
13841 #endif
13842 myrpt->txchannel->appl = "Apprpt";
13843 myrpt->txchannel->data = "(Link Tx)";
13844 if (option_verbose > 2)
13845 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13846 myrpt->txchanname,tele,myrpt->txchannel->name);
13847 rpt_mutex_unlock(&myrpt->lock);
13848 ast_call(myrpt->txchannel,tele,999);
13849 rpt_mutex_lock(&myrpt->lock);
13850 }
13851 else
13852 {
13853 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13854 rpt_mutex_unlock(&myrpt->lock);
13855 ast_hangup(myrpt->rxchannel);
13856 pthread_exit(NULL);
13857 }
13858 *--tele = '/';
13859 }
13860 else
13861 {
13862 myrpt->txchannel = myrpt->rxchannel;
13863 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13864 myrpt->dahditxchannel = myrpt->rxchannel;
13865 }
13866
13867 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13868 if (!myrpt->pchannel)
13869 {
13870 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13871 rpt_mutex_unlock(&myrpt->lock);
13872 if (myrpt->txchannel != myrpt->rxchannel)
13873 ast_hangup(myrpt->txchannel);
13874 ast_hangup(myrpt->rxchannel);
13875 pthread_exit(NULL);
13876 }
13877 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13878 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13879 #ifdef AST_CDR_FLAG_POST_DISABLED
13880 if (myrpt->pchannel->cdr)
13881 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13882 #endif
13883 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13884 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13885
13886 ci.chan = 0;
13887 ci.confno = -1;
13888 ci.confmode = DAHDI_CONF_CONFANNMON ;
13889
13890 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13891 {
13892 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13893 rpt_mutex_unlock(&myrpt->lock);
13894 ast_hangup(myrpt->pchannel);
13895 if (myrpt->txchannel != myrpt->rxchannel)
13896 ast_hangup(myrpt->txchannel);
13897 ast_hangup(myrpt->rxchannel);
13898 pthread_exit(NULL);
13899 }
13900
13901 myrpt->conf = myrpt->txconf = ci.confno;
13902
13903 myrpt->iofd = -1;
13904 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13905 {
13906 rpt_mutex_unlock(&myrpt->lock);
13907 ast_hangup(myrpt->pchannel);
13908 if (myrpt->txchannel != myrpt->rxchannel)
13909 ast_hangup(myrpt->txchannel);
13910 ast_hangup(myrpt->rxchannel);
13911 pthread_exit(NULL);
13912 }
13913 iskenwood_pci4 = 0;
13914 memset(&z,0,sizeof(z));
13915 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13916 {
13917 z.radpar = DAHDI_RADPAR_REMMODE;
13918 z.data = DAHDI_RADPAR_REM_NONE;
13919 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13920
13921 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13922 {
13923 z.radpar = DAHDI_RADPAR_UIOMODE;
13924 z.data = 1;
13925 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13926 {
13927 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13928 return -1;
13929 }
13930 z.radpar = DAHDI_RADPAR_UIODATA;
13931 z.data = 3;
13932 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13933 {
13934 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13935 return -1;
13936 }
13937 i = DAHDI_OFFHOOK;
13938 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13939 {
13940 ast_log(LOG_ERROR,"Cannot set hook\n");
13941 return -1;
13942 }
13943 iskenwood_pci4 = 1;
13944 }
13945 }
13946 if (myrpt->txchannel == myrpt->dahditxchannel)
13947 {
13948 i = DAHDI_ONHOOK;
13949 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13950
13951 if ((myrpt->iofd < 1) && (!res) &&
13952 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13953 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13954 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13955 {
13956 z.radpar = DAHDI_RADPAR_UIOMODE;
13957 z.data = 1;
13958 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13959 {
13960 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13961 return -1;
13962 }
13963 z.radpar = DAHDI_RADPAR_UIODATA;
13964 z.data = 3;
13965 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13966 {
13967 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13968 return -1;
13969 }
13970 }
13971 }
13972 myrpt->remoterx = 0;
13973 myrpt->remotetx = 0;
13974 myrpt->retxtimer = 0;
13975 myrpt->rerxtimer = 0;
13976 myrpt->remoteon = 1;
13977 myrpt->dtmfidx = -1;
13978 myrpt->dtmfbuf[0] = 0;
13979 myrpt->dtmf_time_rem = 0;
13980 myrpt->hfscanmode = 0;
13981 myrpt->hfscanstatus = 0;
13982 if (myrpt->p.startupmacro)
13983 {
13984 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13985 }
13986 time(&myrpt->start_time);
13987 myrpt->last_activity_time = myrpt->start_time;
13988 last_timeout_warning = 0;
13989 myrpt->reload = 0;
13990 myrpt->tele.next = &myrpt->tele;
13991 myrpt->tele.prev = &myrpt->tele;
13992 myrpt->newkey = 0;
13993 rpt_mutex_unlock(&myrpt->lock);
13994 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13995 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13996 rem_rx = 0;
13997 remkeyed = 0;
13998
13999 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
14000 {
14001 i = 128;
14002 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
14003 }
14004 if (chan->_state != AST_STATE_UP) {
14005 ast_answer(chan);
14006 if (!phone_mode) send_newkey(chan);
14007 }
14008
14009 if (myrpt->rxchannel == myrpt->dahdirxchannel)
14010 {
14011 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
14012 {
14013 if (par.rxisoffhook)
14014 {
14015 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14016 myrpt->remoterx = 1;
14017 remkeyed = 1;
14018 }
14019 }
14020 }
14021 if (myrpt->p.archivedir)
14022 {
14023 char mycmd[100],mydate[100],*b,*b1;
14024 time_t myt;
14025 long blocksleft;
14026
14027
14028 mkdir(myrpt->p.archivedir,0600);
14029 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14030 mkdir(mycmd,0600);
14031 time(&myt);
14032 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14033 localtime(&myt));
14034 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14035 myrpt->p.archivedir,myrpt->name,mydate);
14036 if (myrpt->p.monminblocks)
14037 {
14038 blocksleft = diskavail(myrpt);
14039 if (myrpt->p.remotetimeout)
14040 {
14041 blocksleft -= (myrpt->p.remotetimeout *
14042 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14043 }
14044 if (blocksleft >= myrpt->p.monminblocks)
14045 ast_cli_command(nullfd,mycmd);
14046 } else ast_cli_command(nullfd,mycmd);
14047
14048 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14049 if (!b)
14050 {
14051 b1 = "0";
14052 } else {
14053 b1 = ast_strdupa(b);
14054 ast_shrink_phone_number(b1);
14055 }
14056 sprintf(mycmd,"CONNECT,%s",b1);
14057 donodelog(myrpt,mycmd);
14058 }
14059 myrpt->loginuser[0] = 0;
14060 myrpt->loginlevel[0] = 0;
14061 myrpt->authtelltimer = 0;
14062 myrpt->authtimer = 0;
14063 authtold = 0;
14064 authreq = 0;
14065 if (myrpt->p.authlevel > 1) authreq = 1;
14066 setrem(myrpt);
14067 n = 0;
14068 dtmfed = 0;
14069 cs[n++] = chan;
14070 cs[n++] = myrpt->rxchannel;
14071 cs[n++] = myrpt->pchannel;
14072 if (myrpt->rxchannel != myrpt->txchannel)
14073 cs[n++] = myrpt->txchannel;
14074 if (!phone_mode) send_newkey(chan);
14075
14076 for(;;)
14077 {
14078 if (ast_check_hangup(chan)) break;
14079 if (ast_check_hangup(myrpt->rxchannel)) break;
14080 notremming = 0;
14081 setting = 0;
14082 reming = 0;
14083 telem = myrpt->tele.next;
14084 while(telem != &myrpt->tele)
14085 {
14086 if (telem->mode == SETREMOTE) setting = 1;
14087 if ((telem->mode == SETREMOTE) ||
14088 (telem->mode == SCAN) ||
14089 (telem->mode == TUNE)) reming = 1;
14090 else notremming = 1;
14091 telem = telem->next;
14092 }
14093 if (myrpt->reload)
14094 {
14095 myrpt->reload = 0;
14096
14097 for(i = 0; i < nrpts; i++)
14098 {
14099 if (&rpt_vars[i] == myrpt)
14100 {
14101 load_rpt_vars(i,0);
14102 break;
14103 }
14104 }
14105 }
14106 time(&t);
14107 if (myrpt->p.remotetimeout)
14108 {
14109 time_t r;
14110
14111 r = (t - myrpt->start_time);
14112 if (r >= myrpt->p.remotetimeout)
14113 {
14114 saynode(myrpt,chan,myrpt->name);
14115 sayfile(chan,"rpt/timeout");
14116 ast_safe_sleep(chan,1000);
14117 break;
14118 }
14119 if ((myrpt->p.remotetimeoutwarning) &&
14120 (r >= (myrpt->p.remotetimeout -
14121 myrpt->p.remotetimeoutwarning)) &&
14122 (r <= (myrpt->p.remotetimeout -
14123 myrpt->p.remotetimeoutwarningfreq)))
14124 {
14125 if (myrpt->p.remotetimeoutwarningfreq)
14126 {
14127 if ((t - last_timeout_warning) >=
14128 myrpt->p.remotetimeoutwarningfreq)
14129 {
14130 time(&last_timeout_warning);
14131 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14132 }
14133 }
14134 else
14135 {
14136 if (!last_timeout_warning)
14137 {
14138 time(&last_timeout_warning);
14139 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14140 }
14141 }
14142 }
14143 }
14144 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14145 {
14146 time_t r;
14147
14148 r = (t - myrpt->last_activity_time);
14149 if (r >= myrpt->p.remoteinacttimeout)
14150 {
14151 saynode(myrpt,chan,myrpt->name);
14152 ast_safe_sleep(chan,1000);
14153 break;
14154 }
14155 if ((myrpt->p.remotetimeoutwarning) &&
14156 (r >= (myrpt->p.remoteinacttimeout -
14157 myrpt->p.remotetimeoutwarning)) &&
14158 (r <= (myrpt->p.remoteinacttimeout -
14159 myrpt->p.remotetimeoutwarningfreq)))
14160 {
14161 if (myrpt->p.remotetimeoutwarningfreq)
14162 {
14163 if ((t - last_timeout_warning) >=
14164 myrpt->p.remotetimeoutwarningfreq)
14165 {
14166 time(&last_timeout_warning);
14167 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14168 }
14169 }
14170 else
14171 {
14172 if (!last_timeout_warning)
14173 {
14174 time(&last_timeout_warning);
14175 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14176 }
14177 }
14178 }
14179 }
14180 ms = MSWAIT;
14181 who = ast_waitfor_n(cs,n,&ms);
14182 if (who == NULL) ms = 0;
14183 elap = MSWAIT - ms;
14184 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14185 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14186 if (!ms) continue;
14187
14188 if (myrpt->dtmf_local_timer)
14189 {
14190 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14191 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14192 }
14193 rpt_mutex_lock(&myrpt->lock);
14194 do_dtmf_local(myrpt,0);
14195 rpt_mutex_unlock(&myrpt->lock);
14196
14197 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14198 rem_totx |= keyed && (!myrpt->tunerequest);
14199 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14200 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14201 rem_totx |= myrpt->tunerequest;
14202
14203 if((debug > 6) && rem_totx) {
14204 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);
14205 }
14206 if (keyed && (!keyed1))
14207 {
14208 keyed1 = 1;
14209 }
14210
14211 if (!keyed && (keyed1))
14212 {
14213 time_t myt;
14214
14215 keyed1 = 0;
14216 time(&myt);
14217
14218 if ((myrpt->p.authlevel) &&
14219 (!myrpt->loginlevel[0]) &&
14220 (myt > (t + 3)))
14221 {
14222 authreq = 1;
14223 authtold = 0;
14224 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14225 }
14226 }
14227
14228 if (rem_rx && (!myrpt->remoterx))
14229 {
14230 myrpt->remoterx = 1;
14231 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14232 }
14233 if ((!rem_rx) && (myrpt->remoterx))
14234 {
14235 myrpt->remoterx = 0;
14236 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14237 }
14238
14239 if (authreq && (!myrpt->loginlevel[0]))
14240 {
14241 if ((!authtold) && ((myrpt->authtelltimer += elap)
14242 >= AUTHTELLTIME))
14243 {
14244 authtold = 1;
14245 rpt_telemetry(myrpt,LOGINREQ,NULL);
14246 }
14247 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14248 {
14249 break;
14250 }
14251 }
14252 if (myrpt->newkey)
14253 {
14254 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14255 {
14256 myrpt->retxtimer = 0;
14257 if ((myrpt->remoterx) && (!myrpt->remotetx))
14258 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14259 else
14260 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14261 }
14262
14263 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14264 {
14265 keyed = 0;
14266 myrpt->rerxtimer = 0;
14267 }
14268 }
14269 if (rem_totx && (!myrpt->remotetx))
14270 {
14271
14272 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14273 {
14274 if(debug > 6)
14275 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14276
14277 myrpt->remotetx = 1;
14278
14279 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14280 {
14281 time(&myrpt->last_activity_time);
14282 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14283 {
14284 z.radpar = DAHDI_RADPAR_UIODATA;
14285 z.data = 1;
14286 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14287 {
14288 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14289 return -1;
14290 }
14291 }
14292 else
14293 {
14294 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14295 }
14296 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14297 }
14298 }
14299 }
14300 if ((!rem_totx) && myrpt->remotetx)
14301 {
14302 myrpt->remotetx = 0;
14303 if(!myrpt->remtxfreqok){
14304 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14305 }
14306 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14307 {
14308 z.radpar = DAHDI_RADPAR_UIODATA;
14309 z.data = 3;
14310 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14311 {
14312 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14313 return -1;
14314 }
14315 }
14316 else
14317 {
14318 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14319 }
14320 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14321 }
14322 if (myrpt->hfscanmode){
14323 myrpt->scantimer -= elap;
14324 if(myrpt->scantimer <= 0){
14325 if (!reming)
14326 {
14327 myrpt->scantimer = REM_SCANTIME;
14328 rpt_telemetry(myrpt,SCAN,0);
14329 } else myrpt->scantimer = 1;
14330 }
14331 }
14332 rpt_mutex_lock(&myrpt->lock);
14333 c = myrpt->macrobuf[0];
14334 if (c && (!myrpt->macrotimer))
14335 {
14336 myrpt->macrotimer = MACROTIME;
14337 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14338 if ((c == 'p') || (c == 'P'))
14339 myrpt->macrotimer = MACROPTIME;
14340 rpt_mutex_unlock(&myrpt->lock);
14341 if (myrpt->p.archivedir)
14342 {
14343 char str[100];
14344 sprintf(str,"DTMF(M),%c",c);
14345 donodelog(myrpt,str);
14346 }
14347 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14348 continue;
14349 } else rpt_mutex_unlock(&myrpt->lock);
14350 if (who == chan)
14351 {
14352 f = ast_read(chan);
14353 if (!f)
14354 {
14355 if (debug) printf("@@@@ link:Hung Up\n");
14356 break;
14357 }
14358 if (f->frametype == AST_FRAME_VOICE)
14359 {
14360 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14361 {
14362 ismuted = 0;
14363 }
14364
14365 ismuted |= (!myrpt->remotetx);
14366 if (dtmfed && phone_mode) ismuted = 1;
14367 dtmfed = 0;
14368 if (ismuted)
14369 {
14370 memset(f->data.ptr,0,f->datalen);
14371 if (myrpt->lastf1)
14372 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14373 if (myrpt->lastf2)
14374 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14375 }
14376 if (f) f2 = ast_frdup(f);
14377 else f2 = NULL;
14378 f1 = myrpt->lastf2;
14379 myrpt->lastf2 = myrpt->lastf1;
14380 myrpt->lastf1 = f2;
14381 if (ismuted)
14382 {
14383 if (myrpt->lastf1)
14384 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14385 if (myrpt->lastf2)
14386 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14387 }
14388 if (f1)
14389 {
14390 if (phone_mode)
14391 ast_write(myrpt->txchannel,f1);
14392 else
14393 ast_write(myrpt->txchannel,f);
14394 ast_frfree(f1);
14395 }
14396 }
14397 #ifndef OLD_ASTERISK
14398 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14399 {
14400 if (myrpt->lastf1)
14401 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14402 if (myrpt->lastf2)
14403 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14404 dtmfed = 1;
14405 }
14406 #endif
14407 if (f->frametype == AST_FRAME_DTMF)
14408 {
14409 if (myrpt->lastf1)
14410 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14411 if (myrpt->lastf2)
14412 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14413 dtmfed = 1;
14414 if (handle_remote_phone_dtmf(myrpt,f->subclass.integer,&keyed,phone_mode) == -1)
14415 {
14416 if (debug) printf("@@@@ rpt:Hung Up\n");
14417 ast_frfree(f);
14418 break;
14419 }
14420 }
14421 if (f->frametype == AST_FRAME_TEXT)
14422 {
14423 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14424 {
14425 if (debug) printf("@@@@ rpt:Hung Up\n");
14426 ast_frfree(f);
14427 break;
14428 }
14429 }
14430 if (f->frametype == AST_FRAME_CONTROL)
14431 {
14432 if (f->subclass.integer == AST_CONTROL_HANGUP)
14433 {
14434 if (debug) printf("@@@@ rpt:Hung Up\n");
14435 ast_frfree(f);
14436 break;
14437 }
14438
14439 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14440 {
14441 if (debug == 7) printf("@@@@ rx key\n");
14442 keyed = 1;
14443 myrpt->rerxtimer = 0;
14444 }
14445
14446 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14447 {
14448 myrpt->rerxtimer = 0;
14449 if (debug == 7) printf("@@@@ rx un-key\n");
14450 keyed = 0;
14451 }
14452 }
14453 ast_frfree(f);
14454 continue;
14455 }
14456 if (who == myrpt->rxchannel)
14457 {
14458 f = ast_read(myrpt->rxchannel);
14459 if (!f)
14460 {
14461 if (debug) printf("@@@@ link:Hung Up\n");
14462 break;
14463 }
14464 if (f->frametype == AST_FRAME_VOICE)
14465 {
14466 int myreming = 0;
14467
14468 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14469 myreming = reming;
14470
14471 if (myreming || (!remkeyed) ||
14472 ((myrpt->remote) && (myrpt->remotetx)) ||
14473 ((myrpt->remmode != REM_MODE_FM) &&
14474 notremming))
14475 memset(f->data.ptr,0,f->datalen);
14476 ast_write(myrpt->pchannel,f);
14477 }
14478 else if (f->frametype == AST_FRAME_CONTROL)
14479 {
14480 if (f->subclass.integer == AST_CONTROL_HANGUP)
14481 {
14482 if (debug) printf("@@@@ rpt:Hung Up\n");
14483 ast_frfree(f);
14484 break;
14485 }
14486
14487 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14488 {
14489 if (debug == 7) printf("@@@@ remote rx key\n");
14490 if (!myrpt->remotetx)
14491 {
14492 remkeyed = 1;
14493 }
14494 }
14495
14496 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14497 {
14498 if (debug == 7) printf("@@@@ remote rx un-key\n");
14499 if (!myrpt->remotetx)
14500 {
14501 remkeyed = 0;
14502 }
14503 }
14504 }
14505 ast_frfree(f);
14506 continue;
14507 }
14508 if (who == myrpt->pchannel)
14509 {
14510 f = ast_read(myrpt->pchannel);
14511 if (!f)
14512 {
14513 if (debug) printf("@@@@ link:Hung Up\n");
14514 break;
14515 }
14516 if (f->frametype == AST_FRAME_VOICE)
14517 {
14518 ast_write(chan,f);
14519 }
14520 if (f->frametype == AST_FRAME_CONTROL)
14521 {
14522 if (f->subclass.integer == AST_CONTROL_HANGUP)
14523 {
14524 if (debug) printf("@@@@ rpt:Hung Up\n");
14525 ast_frfree(f);
14526 break;
14527 }
14528 }
14529 ast_frfree(f);
14530 continue;
14531 }
14532 if ((myrpt->rxchannel != myrpt->txchannel) &&
14533 (who == myrpt->txchannel))
14534 {
14535 f = ast_read(myrpt->txchannel);
14536 if (!f)
14537 {
14538 if (debug) printf("@@@@ link:Hung Up\n");
14539 break;
14540 }
14541 if (f->frametype == AST_FRAME_CONTROL)
14542 {
14543 if (f->subclass.integer == AST_CONTROL_HANGUP)
14544 {
14545 if (debug) printf("@@@@ rpt:Hung Up\n");
14546 ast_frfree(f);
14547 break;
14548 }
14549 }
14550 ast_frfree(f);
14551 continue;
14552 }
14553 }
14554 if (myrpt->p.archivedir)
14555 {
14556 char mycmd[100],*b,*b1;
14557
14558
14559 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14560 if (!b)
14561 {
14562 b1 = "0";
14563 } else {
14564 b1 = ast_strdupa(b);
14565 ast_shrink_phone_number(b1);
14566 }
14567 sprintf(mycmd,"DISCONNECT,%s",b1);
14568 donodelog(myrpt,mycmd);
14569 }
14570
14571 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14572 sprintf(tmp,"mixmonitor stop %s",chan->name);
14573 ast_cli_command(nullfd,tmp);
14574 close(nullfd);
14575 rpt_mutex_lock(&myrpt->lock);
14576 myrpt->hfscanmode = 0;
14577 myrpt->hfscanstatus = 0;
14578 myrpt->remoteon = 0;
14579 rpt_mutex_unlock(&myrpt->lock);
14580 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14581 myrpt->lastf1 = NULL;
14582 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14583 myrpt->lastf2 = NULL;
14584 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14585 {
14586 z.radpar = DAHDI_RADPAR_UIOMODE;
14587 z.data = 3;
14588 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14589 {
14590 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14591 return -1;
14592 }
14593 z.radpar = DAHDI_RADPAR_UIODATA;
14594 z.data = 3;
14595 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14596 {
14597 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14598 return -1;
14599 }
14600 i = DAHDI_OFFHOOK;
14601 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14602 {
14603 ast_log(LOG_ERROR,"Cannot set hook\n");
14604 return -1;
14605 }
14606 }
14607 if (myrpt->iofd) close(myrpt->iofd);
14608 myrpt->iofd = -1;
14609 ast_hangup(myrpt->pchannel);
14610 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14611 ast_hangup(myrpt->rxchannel);
14612 closerem(myrpt);
14613 if (myrpt->p.rptnode)
14614 {
14615 rpt_mutex_lock(&myrpt->lock);
14616 for(i = 0; i < nrpts; i++)
14617 {
14618 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14619 {
14620 rpt_vars[i].xlink = 0;
14621 break;
14622 }
14623 }
14624 rpt_mutex_unlock(&myrpt->lock);
14625 }
14626 #ifdef OLD_ASTERISK
14627 LOCAL_USER_REMOVE(u);
14628 #endif
14629 return res;
14630 }
14631
14632 #ifndef OLD_ASTERISK
14633
14634
14635
14636 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14637 {
14638 int i;
14639 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14640 astman_append(s, "<nodes>\r\n");
14641 for (i=0; i< nrpts; i++)
14642 {
14643 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14644 }
14645 astman_append(s, "</nodes>\r\n");
14646 astman_append(s, "\r\n");
14647 return RESULT_SUCCESS;
14648 }
14649
14650
14651
14652
14653
14654
14655
14656 static void rpt_manager_success(struct mansession *s, const struct message *m)
14657 {
14658 const char *id = astman_get_header(m, "ActionID");
14659 if (!ast_strlen_zero(id))
14660 astman_append(s, "ActionID: %s\r\n", id);
14661 astman_append(s, "Response: Success\r\n");
14662 }
14663
14664
14665
14666
14667
14668 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14669 {
14670 int i,j,numoflinks;
14671 int dailytxtime, dailykerchunks;
14672 time_t now;
14673 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14674 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14675 long long totaltxtime;
14676 struct rpt_link *l;
14677 char *listoflinks[MAX_STAT_LINKS];
14678 char *lastdtmfcommand,*parrot_ena;
14679 char *tot_state, *ider_state, *patch_state;
14680 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14681 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14682 char *transmitterkeyed;
14683 const char *node = astman_get_header(m, "Node");
14684 struct rpt *myrpt;
14685
14686 static char *not_applicable = "N/A";
14687
14688 tot_state = ider_state =
14689 patch_state = reverse_patch_state =
14690 input_signal = not_applicable;
14691 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14692
14693 time(&now);
14694 for(i = 0; i < nrpts; i++)
14695 {
14696 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14697 rpt_manager_success(s,m);
14698
14699 myrpt = &rpt_vars[i];
14700
14701 if(myrpt->remote){
14702 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14703 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14704 char offsetc,powerlevelc;
14705
14706 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14707
14708 rpt_mutex_lock(&myrpt->lock);
14709 if((remoteon = myrpt->remoteon)){
14710 if(!ast_strlen_zero(myrpt->loginuser))
14711 loginuser = ast_strdup(myrpt->loginuser);
14712 if(!ast_strlen_zero(myrpt->loginlevel))
14713 loginlevel = ast_strdup(myrpt->loginlevel);
14714 if(!ast_strlen_zero(myrpt->freq))
14715 freq = ast_strdup(myrpt->freq);
14716 if(!ast_strlen_zero(myrpt->rxpl))
14717 rxpl = ast_strdup(myrpt->rxpl);
14718 if(!ast_strlen_zero(myrpt->txpl))
14719 txpl = ast_strdup(myrpt->txpl);
14720 remmode = myrpt->remmode;
14721 offset = myrpt->offset;
14722 powerlevel = myrpt->powerlevel;
14723 rxplon = myrpt->rxplon;
14724 txplon = myrpt->txplon;
14725 }
14726 rpt_mutex_unlock(&myrpt->lock);
14727 astman_append(s, "IsRemoteBase: YES\r\n");
14728 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14729 if(remoteon){
14730 if(loginuser){
14731 astman_append(s, "LogInUser: %s\r\n", loginuser);
14732 ast_free(loginuser);
14733 }
14734 if(loginlevel){
14735 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14736 ast_free(loginlevel);
14737 }
14738 if(freq){
14739 astman_append(s, "Freq: %s\r\n", freq);
14740 ast_free(freq);
14741 }
14742 reportfmstuff = 0;
14743 switch(remmode){
14744 case REM_MODE_FM:
14745 modestr = "FM";
14746 reportfmstuff = 1;
14747 break;
14748 case REM_MODE_AM:
14749 modestr = "AM";
14750 break;
14751 case REM_MODE_USB:
14752 modestr = "USB";
14753 break;
14754 default:
14755 modestr = "LSB";
14756 break;
14757 }
14758 astman_append(s, "RemMode: %s\r\n", modestr);
14759 if(reportfmstuff){
14760 switch(offset){
14761 case REM_SIMPLEX:
14762 offsetc = 'S';
14763 break;
14764 case REM_MINUS:
14765 offsetc = '-';
14766 break;
14767 default:
14768 offsetc = '+';
14769 break;
14770 }
14771 astman_append(s, "RemOffset: %c\r\n", offsetc);
14772 if(rxplon && rxpl){
14773 astman_append(s, "RxPl: %s\r\n",rxpl);
14774 ast_free(rxpl);
14775 }
14776 if(txplon && txpl){
14777 astman_append(s, "TxPl: %s\r\n",txpl);
14778 ast_free(txpl);
14779 }
14780 }
14781 switch(powerlevel){
14782 case REM_LOWPWR:
14783 powerlevelc = 'L';
14784 break;
14785 case REM_MEDPWR:
14786 powerlevelc = 'M';
14787 break;
14788 default:
14789 powerlevelc = 'H';
14790 break;
14791 }
14792 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14793 }
14794 astman_append(s, "\r\n");
14795 return 0;
14796 }
14797
14798
14799
14800 rpt_mutex_lock(&myrpt->lock);
14801 dailytxtime = myrpt->dailytxtime;
14802 totaltxtime = myrpt->totaltxtime;
14803 dailykeyups = myrpt->dailykeyups;
14804 totalkeyups = myrpt->totalkeyups;
14805 dailykerchunks = myrpt->dailykerchunks;
14806 totalkerchunks = myrpt->totalkerchunks;
14807 dailyexecdcommands = myrpt->dailyexecdcommands;
14808 totalexecdcommands = myrpt->totalexecdcommands;
14809 timeouts = myrpt->timeouts;
14810
14811
14812
14813 reverse_patch_state = "DOWN";
14814 numoflinks = 0;
14815 l = myrpt->links.next;
14816 while(l && (l != &myrpt->links)){
14817 if(numoflinks >= MAX_STAT_LINKS){
14818 ast_log(LOG_NOTICE,
14819 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14820 break;
14821 }
14822 if (l->name[0] == '0'){
14823 reverse_patch_state = "UP";
14824 l = l->next;
14825 continue;
14826 }
14827 listoflinks[numoflinks] = ast_strdup(l->name);
14828 if(listoflinks[numoflinks] == NULL){
14829 break;
14830 }
14831 else{
14832 numoflinks++;
14833 }
14834 l = l->next;
14835 }
14836
14837 if(myrpt->keyed)
14838 input_signal = "YES";
14839 else
14840 input_signal = "NO";
14841
14842 if(myrpt->txkeyed)
14843 transmitterkeyed = "YES";
14844 else
14845 transmitterkeyed = "NO";
14846
14847 if(myrpt->p.parrotmode)
14848 parrot_ena = "ENABLED";
14849 else
14850 parrot_ena = "DISABLED";
14851
14852 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14853 sys_ena = "DISABLED";
14854 else
14855 sys_ena = "ENABLED";
14856
14857 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14858 tot_ena = "DISABLED";
14859 else
14860 tot_ena = "ENABLED";
14861
14862 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14863 link_ena = "DISABLED";
14864 else
14865 link_ena = "ENABLED";
14866
14867 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14868 patch_ena = "DISABLED";
14869 else
14870 patch_ena = "ENABLED";
14871
14872 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14873 sch_ena = "DISABLED";
14874 else
14875 sch_ena = "ENABLED";
14876
14877 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14878 user_funs = "DISABLED";
14879 else
14880 user_funs = "ENABLED";
14881
14882 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14883 tail_type = "ALTERNATE";
14884 else
14885 tail_type = "STANDARD";
14886
14887 if(!myrpt->totimer)
14888 tot_state = "TIMED OUT!";
14889 else if(myrpt->totimer != myrpt->p.totime)
14890 tot_state = "ARMED";
14891 else
14892 tot_state = "RESET";
14893
14894 if(myrpt->tailid)
14895 ider_state = "QUEUED IN TAIL";
14896 else if(myrpt->mustid)
14897 ider_state = "QUEUED FOR CLEANUP";
14898 else
14899 ider_state = "CLEAN";
14900
14901 switch(myrpt->callmode){
14902 case 1:
14903 patch_state = "DIALING";
14904 break;
14905 case 2:
14906 patch_state = "CONNECTING";
14907 break;
14908 case 3:
14909 patch_state = "UP";
14910 break;
14911
14912 case 4:
14913 patch_state = "CALL FAILED";
14914 break;
14915
14916 default:
14917 patch_state = "DOWN";
14918 }
14919
14920 if(strlen(myrpt->exten)){
14921 called_number = ast_strdup(myrpt->exten);
14922 }
14923
14924 if(strlen(myrpt->lastdtmfcommand)){
14925 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14926 }
14927 rpt_mutex_unlock(&myrpt->lock);
14928
14929 astman_append(s, "IsRemoteBase: NO\r\n");
14930 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14931 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14932 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14933 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14934 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14935 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14936 astman_append(s, "TailLength: %s\r\n", tail_type);
14937 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14938 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14939 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14940 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14941 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14942 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14943 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14944 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14945 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14946 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14947 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14948 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14949 hours = dailytxtime/3600000;
14950 dailytxtime %= 3600000;
14951 minutes = dailytxtime/60000;
14952 dailytxtime %= 60000;
14953 seconds = dailytxtime/1000;
14954 dailytxtime %= 1000;
14955
14956 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14957 hours, minutes, seconds, dailytxtime);
14958
14959 hours = (int) totaltxtime/3600000;
14960 totaltxtime %= 3600000;
14961 minutes = (int) totaltxtime/60000;
14962 totaltxtime %= 60000;
14963 seconds = (int) totaltxtime/1000;
14964 totaltxtime %= 1000;
14965
14966 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14967 hours, minutes, seconds, (int) totaltxtime);
14968
14969 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14970 if(!numoflinks){
14971 strcat(str,"<NONE>");
14972 }
14973 else{
14974 for(j = 0 ;j < numoflinks; j++){
14975 sprintf(str+strlen(str), "%s", listoflinks[j]);
14976 if(j < numoflinks - 1)
14977 strcat(str,",");
14978 }
14979 }
14980 astman_append(s,"%s\r\n", str);
14981
14982 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14983 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14984 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14985 (called_number && strlen(called_number)) ? called_number : not_applicable);
14986 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14987 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14988 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14989
14990 for(j = 0; j < numoflinks; j++){
14991 ast_free(listoflinks[j]);
14992 }
14993 if(called_number){
14994 ast_free(called_number);
14995 }
14996 if(lastdtmfcommand){
14997 ast_free(lastdtmfcommand);
14998 }
14999 astman_append(s, "\r\n");
15000 return 0;
15001 }
15002 }
15003 astman_send_error(s, m, "RptStatus unknown or missing node");
15004 return -1;
15005 }
15006
15007
15008
15009
15010
15011
15012
15013 static int manager_rpt_status(struct mansession *s, const struct message *m)
15014 {
15015 int i,res,len,idx;
15016 int uptime,hours,minutes;
15017 time_t now;
15018 const char *cmd = astman_get_header(m, "Command");
15019 char *str;
15020 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15021 struct mgrcmdtbl{
15022 const char *cmd;
15023 int index;
15024 };
15025 static struct mgrcmdtbl mct[] = {
15026 {"RptStat",MGRCMD_RPTSTAT},
15027 {"NodeStat",MGRCMD_NODESTAT},
15028 {NULL,0}
15029 };
15030
15031 time(&now);
15032
15033 len = 1024;
15034 if(!(str = ast_malloc(len)))
15035 return -1;
15036
15037
15038 if(ast_strlen_zero(cmd)){
15039 astman_send_error(s, m, "RptStatus missing command");
15040 ast_free(str);
15041 return 0;
15042 }
15043
15044 for(i = 0 ; mct[i].cmd ; i++){
15045 if(!strcmp(mct[i].cmd, cmd))
15046 break;
15047 }
15048
15049 if(!mct[i].cmd){
15050 astman_send_error(s, m, "RptStatus unknown command");
15051 ast_free(str);
15052 return 0;
15053 }
15054 else
15055 idx = mct[i].index;
15056
15057 switch(idx){
15058
15059 case MGRCMD_RPTSTAT:
15060
15061 if((res = snprintf(str, len, "Nodes: ")) > -1)
15062 len -= res;
15063 else{
15064 ast_free(str);
15065 return 0;
15066 }
15067 for(i = 0; i < nrpts; i++){
15068 if(i < nrpts - 1){
15069 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15070 ast_free(str);
15071 return 0;
15072 }
15073 }
15074 else{
15075 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15076 ast_free(str);
15077 return 0;
15078 }
15079 }
15080 len -= res;
15081 }
15082
15083 rpt_manager_success(s,m);
15084
15085 if(!nrpts)
15086 astman_append(s, "<NONE>\r\n");
15087 else
15088 astman_append(s, "%s\r\n", str);
15089
15090 uptime = (int)(now - starttime);
15091 hours = uptime/3600;
15092 uptime %= 3600;
15093 minutes = uptime/60;
15094 uptime %= 60;
15095
15096 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15097 hours, minutes, uptime);
15098
15099 astman_append(s, "\r\n");
15100 break;
15101
15102 case MGRCMD_NODESTAT:
15103 res = rpt_manager_do_stats(s,m,str);
15104 ast_free(str);
15105 return res;
15106
15107 default:
15108 astman_send_error(s, m, "RptStatus invalid command");
15109 break;
15110 }
15111 ast_free(str);
15112 return 0;
15113 }
15114
15115 #endif
15116
15117 #ifdef OLD_ASTERISK
15118 int unload_module()
15119 #else
15120 static int unload_module(void)
15121 #endif
15122 {
15123 int i, res;
15124
15125 #ifdef OLD_ASTERISK
15126 STANDARD_HANGUP_LOCALUSERS;
15127 #endif
15128 for(i = 0; i < nrpts; i++) {
15129 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15130 ast_mutex_destroy(&rpt_vars[i].lock);
15131 ast_mutex_destroy(&rpt_vars[i].remlock);
15132 }
15133 res = ast_unregister_application(app);
15134
15135 #ifdef NEW_ASTERISK
15136 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15137 #else
15138
15139 ast_cli_unregister(&cli_debug);
15140 ast_cli_unregister(&cli_dump);
15141 ast_cli_unregister(&cli_stats);
15142 ast_cli_unregister(&cli_lstats);
15143 ast_cli_unregister(&cli_nodes);
15144 ast_cli_unregister(&cli_local_nodes);
15145 ast_cli_unregister(&cli_reload);
15146 ast_cli_unregister(&cli_restart);
15147 ast_cli_unregister(&cli_fun);
15148 ast_cli_unregister(&cli_fun1);
15149 res |= ast_cli_unregister(&cli_cmd);
15150 #endif
15151 #ifndef OLD_ASTERISK
15152 res |= ast_manager_unregister("RptLocalNodes");
15153 res |= ast_manager_unregister("RptStatus");
15154 #endif
15155 return res;
15156 }
15157
15158 #ifdef OLD_ASTERISK
15159 int load_module()
15160 #else
15161 static int load_module(void)
15162 #endif
15163 {
15164 int res;
15165 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15166
15167 #ifdef NEW_ASTERISK
15168 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15169 res = 0;
15170 #else
15171
15172 ast_cli_register(&cli_debug);
15173 ast_cli_register(&cli_dump);
15174 ast_cli_register(&cli_stats);
15175 ast_cli_register(&cli_lstats);
15176 ast_cli_register(&cli_nodes);
15177 ast_cli_register(&cli_local_nodes);
15178 ast_cli_register(&cli_reload);
15179 ast_cli_register(&cli_restart);
15180 ast_cli_register(&cli_fun);
15181 ast_cli_register(&cli_fun1);
15182 res = ast_cli_register(&cli_cmd);
15183 #endif
15184 #ifndef OLD_ASTERISK
15185 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15186 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15187
15188 #endif
15189 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15190 return res;
15191 }
15192
15193 #ifdef OLD_ASTERISK
15194 char *description()
15195 {
15196 return tdesc;
15197 }
15198 int usecount(void)
15199 {
15200 int res;
15201 STANDARD_USECOUNT(res);
15202 return res;
15203 }
15204
15205 char *key()
15206 {
15207 return ASTERISK_GPL_KEY;
15208 }
15209 #endif
15210
15211 #ifdef OLD_ASTERISK
15212 int reload()
15213 #else
15214 static int reload(void)
15215 #endif
15216 {
15217 int n;
15218
15219 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15220 return(0);
15221 }
15222
15223
15224 #ifndef OLD_ASTERISK
15225
15226 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15227 .load = load_module,
15228 .unload = unload_module,
15229 .reload = reload,
15230 );
15231 #endif
15232