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
00171 #ifdef OLD_ASTERISK
00172 #define ast_free free
00173 #define ast_malloc malloc
00174 #define ast_strdup strdup
00175 #endif
00176
00177
00178 #define MAXDTMF 32
00179 #define MAXMACRO 2048
00180 #define MAXLINKLIST 512
00181 #define LINKLISTTIME 10000
00182 #define LINKLISTSHORTTIME 200
00183 #define LINKPOSTTIME 30000
00184 #define LINKPOSTSHORTTIME 200
00185 #define KEYPOSTTIME 30000
00186 #define KEYPOSTSHORTTIME 200
00187 #define MACROTIME 100
00188 #define MACROPTIME 500
00189 #define DTMF_TIMEOUT 3
00190 #define KENWOOD_RETRIES 5
00191 #define TOPKEYN 32
00192 #define TOPKEYWAIT 3
00193 #define TOPKEYMAXSTR 30
00194
00195 #define AUTHTELLTIME 7000
00196 #define AUTHTXTIME 1000
00197 #define AUTHLOGOUTTIME 25000
00198
00199 #ifdef __RPT_NOTCH
00200 #define MAXFILTERS 10
00201 #endif
00202
00203 #define DISC_TIME 10000
00204 #define MAX_RETRIES 5
00205 #define MAX_RETRIES_PERM 1000000000
00206
00207 #define REDUNDANT_TX_TIME 2000
00208
00209 #define RETRY_TIMER_MS 5000
00210
00211 #define PATCH_DIALPLAN_TIMEOUT 1500
00212
00213 #ifdef OLD_ASTERISK
00214 #define START_DELAY 10
00215 #else
00216 #define START_DELAY 2
00217 #endif
00218
00219 #define RPT_LOCKOUT_SECS 10
00220
00221 #define MAXPEERSTR 31
00222 #define MAXREMSTR 15
00223
00224 #define DELIMCHR ','
00225 #define QUOTECHR 34
00226
00227 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00228
00229 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00230 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00232 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00233 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00234
00235 #define NODES "nodes"
00236 #define EXTNODES "extnodes"
00237 #define MEMORY "memory"
00238 #define MACRO "macro"
00239 #define FUNCTIONS "functions"
00240 #define TELEMETRY "telemetry"
00241 #define MORSE "morse"
00242 #define TONEMACRO "tonemacro"
00243 #define FUNCCHAR '*'
00244 #define ENDCHAR '#'
00245 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00246 #define NODENAMES "rpt/nodenames"
00247 #define PARROTFILE "/tmp/parrot_%s_%u"
00248
00249 #define PARROTTIME 1000
00250
00251 #define DEFAULT_IOBASE 0x378
00252
00253 #define DEFAULT_CIV_ADDR 0x58
00254
00255 #define MAXCONNECTTIME 5000
00256
00257 #define MAXNODESTR 300
00258
00259 #define MAXNODELEN 16
00260
00261 #define MAXIDENTLEN 32
00262
00263 #define MAXPATCHCONTEXT 100
00264
00265 #define ACTIONSIZE 32
00266
00267 #define TELEPARAMSIZE 256
00268
00269 #define REM_SCANTIME 100
00270
00271 #define DTMF_LOCAL_TIME 250
00272 #define DTMF_LOCAL_STARTTIME 500
00273
00274 #define IC706_PL_MEMORY_OFFSET 50
00275
00276 #define VOX_ON_DEBOUNCE_COUNT 3
00277 #define VOX_OFF_DEBOUNCE_COUNT 20
00278 #define VOX_MAX_THRESHOLD 10000.0
00279 #define VOX_MIN_THRESHOLD 3000.0
00280 #define VOX_TIMEOUT_MS 5000
00281 #define VOX_RECOVER_MS 500
00282 #define SIMPLEX_PATCH_DELAY 25
00283 #define SIMPLEX_PHONE_DELAY 25
00284
00285 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00286
00287 #define ALLOW_LOCAL_CHANNELS
00288
00289 enum {REM_OFF,REM_MONITOR,REM_TX};
00290
00291 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00292 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00293 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00294 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00295 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00296 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00297 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00298 STATS_TIME_LOCAL};
00299
00300
00301 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00302
00303 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00304
00305 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00306
00307 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00308
00309 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00310
00311 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00312
00313 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00314 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00315
00316 #include "asterisk.h"
00317
00318 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 352348 $")
00319
00320 #include <signal.h>
00321 #include <stdio.h>
00322 #include <stdint.h>
00323 #include <unistd.h>
00324 #include <string.h>
00325 #include <stdlib.h>
00326 #include <search.h>
00327 #include <sys/types.h>
00328 #include <sys/stat.h>
00329 #include <errno.h>
00330 #include <dirent.h>
00331 #include <ctype.h>
00332 #include <sys/stat.h>
00333 #include <sys/time.h>
00334 #include <sys/file.h>
00335 #include <sys/ioctl.h>
00336 #ifdef HAVE_SYS_IO_H
00337 #include <sys/io.h>
00338 #endif
00339 #include <sys/vfs.h>
00340 #include <math.h>
00341 #include <dahdi/user.h>
00342 #include <dahdi/tonezone.h>
00343 #include <netinet/in.h>
00344 #include <arpa/inet.h>
00345
00346 #include "asterisk/utils.h"
00347 #include "asterisk/lock.h"
00348 #include "asterisk/file.h"
00349 #include "asterisk/logger.h"
00350 #include "asterisk/channel.h"
00351 #include "asterisk/callerid.h"
00352 #include "asterisk/pbx.h"
00353 #include "asterisk/module.h"
00354 #include "asterisk/translate.h"
00355 #include "asterisk/features.h"
00356 #include "asterisk/options.h"
00357 #include "asterisk/cli.h"
00358 #include "asterisk/config.h"
00359 #include "asterisk/say.h"
00360 #include "asterisk/localtime.h"
00361 #include "asterisk/cdr.h"
00362 #include "asterisk/options.h"
00363 #include "asterisk/manager.h"
00364 #include "asterisk/app.h"
00365
00366 #include <termios.h>
00367
00368 #ifdef NEW_ASTERISK
00369 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00370 #endif
00371
00372
00373
00374 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00375
00376 void ast_playtones_stop(struct ast_channel *chan);
00377
00378 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00379
00380 static char *app = "Rpt";
00381
00382 static char *synopsis = "Radio Repeater/Remote Base Control System";
00383
00384 static char *descrip =
00385 " Rpt(nodename[|options][|M][|*]): \n"
00386 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00387 "\n"
00388 " Not specifying an option puts it in normal endpoint mode (where source\n"
00389 " IP and nodename are verified).\n"
00390 "\n"
00391 " Options are as follows:\n"
00392 "\n"
00393 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00394 " this if you have checked security already (like with an IAX2\n"
00395 " user/password or something).\n"
00396 "\n"
00397 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00398 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00399 " specified by the 'announce-string') is played on radio system.\n"
00400 " Users of radio system can access autopatch, dial specified\n"
00401 " code, and pick up call. Announce-string is list of names of\n"
00402 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00403 " or \"NODE\" to substitute node number.\n"
00404 "\n"
00405 " P - Phone Control mode. This allows a regular phone user to have\n"
00406 " full control and audio access to the radio system. For the\n"
00407 " user to have DTMF control, the 'phone_functions' parameter\n"
00408 " must be specified for the node in 'rpt.conf'. An additional\n"
00409 " function (cop,6) must be listed so that PTT control is available.\n"
00410 "\n"
00411 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00412 " have full control and audio access to the radio system. In this\n"
00413 " mode, the PTT is activated for the entire length of the call.\n"
00414 " For the user to have DTMF control (not generally recomended in\n"
00415 " this mode), the 'dphone_functions' parameter must be specified\n"
00416 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00417 " available to the phone user.\n"
00418 "\n"
00419 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00420 " audio-only access to the radio system. In this mode, the\n"
00421 " transmitter is toggled on and off when the phone user presses the\n"
00422 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00423 " will turn off if the endchar (#) key is pressed. When a user first\n"
00424 " calls in, the transmitter will be off, and the user can listen for\n"
00425 " radio traffic. When the user wants to transmit, they press the *\n"
00426 " key, start talking, then press the * key again or the # key to turn\n"
00427 " the transmitter off. No other functions can be executed by the\n"
00428 " user on the phone when this mode is selected. Note: If your\n"
00429 " radio system is full-duplex, we recommend using either P or D\n"
00430 " modes as they provide more flexibility.\n"
00431 "\n"
00432 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00433 "\n"
00434 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00435 "\n"
00436 " * - Alt Macro to execute (e.g. *7 for status)\n"
00437 "\n";
00438 ;
00439
00440 static int debug = 0;
00441 static int nrpts = 0;
00442
00443 static const char remdtmfstr[] = "0123456789*#ABCD";
00444
00445 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00446
00447 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00448
00449 #define NRPTSTAT 7
00450
00451 struct rpt_chan_stat
00452 {
00453 struct timeval last;
00454 long long total;
00455 unsigned long count;
00456 unsigned long largest;
00457 struct timeval largest_time;
00458 };
00459
00460 char *discstr = "!!DISCONNECT!!";
00461 char *newkeystr = "!NEWKEY!";
00462 static char *remote_rig_ft897="ft897";
00463 static char *remote_rig_rbi="rbi";
00464 static char *remote_rig_kenwood="kenwood";
00465 static char *remote_rig_tm271="tm271";
00466 static char *remote_rig_ic706="ic706";
00467 static char *remote_rig_rtx150="rtx150";
00468 static char *remote_rig_rtx450="rtx450";
00469 static char *remote_rig_ppp16="ppp16";
00470
00471 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00472 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00473
00474 #ifdef OLD_ASTERISK
00475 STANDARD_LOCAL_USER;
00476 LOCAL_USER_DECL;
00477 #endif
00478
00479 #define MSWAIT 200
00480 #define HANGTIME 5000
00481 #define TOTIME 180000
00482 #define IDTIME 300000
00483 #define MAXRPTS 20
00484 #define MAX_STAT_LINKS 32
00485 #define POLITEID 30000
00486 #define FUNCTDELAY 1500
00487
00488 #define MAXXLAT 20
00489 #define MAXXLATTIME 3
00490
00491 #define MAX_SYSSTATES 10
00492
00493 struct vox {
00494 float speech_energy;
00495 float noise_energy;
00496 int enacount;
00497 char voxena;
00498 char lastvox;
00499 int offdebcnt;
00500 int ondebcnt;
00501 } ;
00502
00503 #define mymax(x,y) ((x > y) ? x : y)
00504 #define mymin(x,y) ((x < y) ? x : y)
00505
00506 struct rpt_topkey
00507 {
00508 char node[TOPKEYMAXSTR];
00509 int timesince;
00510 int keyed;
00511 } ;
00512
00513 struct rpt_xlat
00514 {
00515 char funccharseq[MAXXLAT];
00516 char endcharseq[MAXXLAT];
00517 char passchars[MAXXLAT];
00518 int funcindex;
00519 int endindex;
00520 time_t lastone;
00521 } ;
00522
00523 static time_t starttime = 0;
00524
00525 static pthread_t rpt_master_thread;
00526
00527 struct rpt;
00528
00529 struct rpt_link
00530 {
00531 struct rpt_link *next;
00532 struct rpt_link *prev;
00533 char mode;
00534 char isremote;
00535 char phonemode;
00536 char phonevox;
00537 char name[MAXNODESTR];
00538 char lasttx;
00539 char lasttx1;
00540 char lastrx;
00541 char lastrealrx;
00542 char lastrx1;
00543 char connected;
00544 char hasconnected;
00545 char perma;
00546 char thisconnected;
00547 char outbound;
00548 char disced;
00549 char killme;
00550 long elaptime;
00551 long disctime;
00552 long retrytimer;
00553 long retxtimer;
00554 long rerxtimer;
00555 int retries;
00556 int max_retries;
00557 int reconnects;
00558 long long connecttime;
00559 struct ast_channel *chan;
00560 struct ast_channel *pchan;
00561 char linklist[MAXLINKLIST];
00562 time_t linklistreceived;
00563 long linklisttimer;
00564 int dtmfed;
00565 int linkunkeytocttimer;
00566 struct timeval lastlinktv;
00567 struct ast_frame *lastf1,*lastf2;
00568 struct rpt_chan_stat chan_stat[NRPTSTAT];
00569 struct vox vox;
00570 char wasvox;
00571 int voxtotimer;
00572 char voxtostate;
00573 char newkey;
00574 #ifdef OLD_ASTERISK
00575 AST_LIST_HEAD(, ast_frame) rxq;
00576 #else
00577 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00578 #endif
00579 } ;
00580
00581 struct rpt_lstat
00582 {
00583 struct rpt_lstat *next;
00584 struct rpt_lstat *prev;
00585 char peer[MAXPEERSTR];
00586 char name[MAXNODESTR];
00587 char mode;
00588 char outbound;
00589 char reconnects;
00590 char thisconnected;
00591 long long connecttime;
00592 struct rpt_chan_stat chan_stat[NRPTSTAT];
00593 } ;
00594
00595 struct rpt_tele
00596 {
00597 struct rpt_tele *next;
00598 struct rpt_tele *prev;
00599 struct rpt *rpt;
00600 struct ast_channel *chan;
00601 int mode;
00602 struct rpt_link mylink;
00603 char param[TELEPARAMSIZE];
00604 intptr_t submode;
00605 uintptr_t parrot;
00606 pthread_t threadid;
00607 } ;
00608
00609 struct function_table_tag
00610 {
00611 char action[ACTIONSIZE];
00612 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00613 int command_source, struct rpt_link *mylink);
00614 } ;
00615
00616
00617
00618 struct morse_bits
00619 {
00620 int len;
00621 int ddcomb;
00622 } ;
00623
00624 struct telem_defaults
00625 {
00626 char name[20];
00627 char value[80];
00628 } ;
00629
00630
00631 struct sysstate
00632 {
00633 char txdisable;
00634 char totdisable;
00635 char linkfundisable;
00636 char autopatchdisable;
00637 char schedulerdisable;
00638 char userfundisable;
00639 char alternatetail;
00640 };
00641
00642
00643 #define CMD_DEPTH 1
00644 #define CMD_STATE_IDLE 0
00645 #define CMD_STATE_BUSY 1
00646 #define CMD_STATE_READY 2
00647 #define CMD_STATE_EXECUTING 3
00648
00649 struct rpt_cmd_struct
00650 {
00651 int state;
00652 int functionNumber;
00653 char param[MAXDTMF];
00654 char digits[MAXDTMF];
00655 int command_source;
00656 };
00657
00658 static struct rpt
00659 {
00660 ast_mutex_t lock;
00661 ast_mutex_t remlock;
00662 ast_mutex_t statpost_lock;
00663 struct ast_config *cfg;
00664 char reload;
00665 char xlink;
00666 unsigned int statpost_seqno;
00667
00668 char *name;
00669 char *rxchanname;
00670 char *txchanname;
00671 char remote;
00672 char *remoterig;
00673 struct rpt_chan_stat chan_stat[NRPTSTAT];
00674 unsigned int scram;
00675
00676 struct {
00677 char *ourcontext;
00678 char *ourcallerid;
00679 char *acctcode;
00680 char *ident;
00681 char *tonezone;
00682 char simple;
00683 char *functions;
00684 char *link_functions;
00685 char *phone_functions;
00686 char *dphone_functions;
00687 char *alt_functions;
00688 char *nodes;
00689 char *extnodes;
00690 char *extnodefile;
00691 int hangtime;
00692 int althangtime;
00693 int totime;
00694 int idtime;
00695 int tailmessagetime;
00696 int tailsquashedtime;
00697 int duplex;
00698 int politeid;
00699 char *tailmessages[500];
00700 int tailmessagemax;
00701 char *memory;
00702 char *macro;
00703 char *tonemacro;
00704 char *startupmacro;
00705 int iobase;
00706 char *ioport;
00707 char funcchar;
00708 char endchar;
00709 char nobusyout;
00710 char notelemtx;
00711 char propagate_dtmf;
00712 char propagate_phonedtmf;
00713 char linktolink;
00714 unsigned char civaddr;
00715 struct rpt_xlat inxlat;
00716 struct rpt_xlat outxlat;
00717 char *archivedir;
00718 int authlevel;
00719 char *csstanzaname;
00720 char *skedstanzaname;
00721 char *txlimitsstanzaname;
00722 long monminblocks;
00723 int remoteinacttimeout;
00724 int remotetimeout;
00725 int remotetimeoutwarning;
00726 int remotetimeoutwarningfreq;
00727 int sysstate_cur;
00728 struct sysstate s[MAX_SYSSTATES];
00729 char parrotmode;
00730 int parrottime;
00731 char *rptnode;
00732 char remote_mars;
00733 int voxtimeout_ms;
00734 int voxrecover_ms;
00735 int simplexpatchdelay;
00736 int simplexphonedelay;
00737 char *statpost_program;
00738 char *statpost_url;
00739 } p;
00740 struct rpt_link links;
00741 int unkeytocttimer;
00742 time_t lastkeyedtime;
00743 time_t lasttxkeyedtime;
00744 char keyed;
00745 char txkeyed;
00746 char exttx;
00747 char localtx;
00748 char remoterx;
00749 char remotetx;
00750 char remoteon;
00751 char remtxfreqok;
00752 char tounkeyed;
00753 char tonotify;
00754 char dtmfbuf[MAXDTMF];
00755 char macrobuf[MAXMACRO];
00756 char rem_dtmfbuf[MAXDTMF];
00757 char lastdtmfcommand[MAXDTMF];
00758 char cmdnode[50];
00759 char nowchan;
00760 char waschan;
00761 char bargechan;
00762 char macropatch;
00763 char parrotstate;
00764 int parrottimer;
00765 unsigned int parrotcnt;
00766 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00767 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00768 struct ast_channel *voxchannel;
00769 struct ast_frame *lastf1,*lastf2;
00770 struct rpt_tele tele;
00771 struct timeval lasttv,curtv;
00772 pthread_t rpt_call_thread,rpt_thread;
00773 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00774 int calldigittimer;
00775 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00776 int mustid,tailid;
00777 int tailevent;
00778 int telemrefcount;
00779 int dtmfidx,rem_dtmfidx;
00780 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00781 int totalexecdcommands, dailyexecdcommands;
00782 long retxtimer;
00783 long rerxtimer;
00784 long long totaltxtime;
00785 char mydtmf;
00786 char exten[AST_MAX_EXTENSION];
00787 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00788 char offset;
00789 char powerlevel;
00790 char txplon;
00791 char rxplon;
00792 char remmode;
00793 char tunerequest;
00794 char hfscanmode;
00795 int hfscanstatus;
00796 char hfscanstop;
00797 char lastlinknode[MAXNODESTR];
00798 char savednodes[MAXNODESTR];
00799 int stopgen;
00800 char patchfarenddisconnect;
00801 char patchnoct;
00802 char patchquiet;
00803 char patchcontext[MAXPATCHCONTEXT];
00804 int patchdialtime;
00805 int macro_longest;
00806 int phone_longestfunc;
00807 int alt_longestfunc;
00808 int dphone_longestfunc;
00809 int link_longestfunc;
00810 int longestfunc;
00811 int longestnode;
00812 int threadrestarts;
00813 int tailmessagen;
00814 time_t disgorgetime;
00815 time_t lastthreadrestarttime;
00816 long macrotimer;
00817 char lastnodewhichkeyedusup[MAXNODESTR];
00818 int dtmf_local_timer;
00819 char dtmf_local_str[100];
00820 struct ast_filestream *monstream,*parrotstream;
00821 char loginuser[50];
00822 char loginlevel[10];
00823 long authtelltimer;
00824 long authtimer;
00825 int iofd;
00826 time_t start_time,last_activity_time;
00827 char lasttone[32];
00828 struct rpt_tele *active_telem;
00829 struct rpt_topkey topkey[TOPKEYN];
00830 int topkeystate;
00831 time_t topkeytime;
00832 int topkeylong;
00833 struct vox vox;
00834 char wasvox;
00835 int voxtotimer;
00836 char voxtostate;
00837 int linkposttimer;
00838 int keyposttimer;
00839 char newkey;
00840 char inpadtest;
00841 #ifdef OLD_ASTERISK
00842 AST_LIST_HEAD(, ast_frame) txq;
00843 #else
00844 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00845 #endif
00846 char txrealkeyed;
00847 #ifdef __RPT_NOTCH
00848 struct rptfilter
00849 {
00850 char desc[100];
00851 float x0;
00852 float x1;
00853 float x2;
00854 float y0;
00855 float y1;
00856 float y2;
00857 float gain;
00858 float const0;
00859 float const1;
00860 float const2;
00861 } filters[MAXFILTERS];
00862 #endif
00863 #ifdef _MDC_DECODE_H_
00864 mdc_decoder_t *mdc;
00865 unsigned short lastunit;
00866 #endif
00867 struct rpt_cmd_struct cmdAction;
00868 } rpt_vars[MAXRPTS];
00869
00870 struct nodelog {
00871 struct nodelog *next;
00872 struct nodelog *prev;
00873 time_t timestamp;
00874 char archivedir[MAXNODESTR];
00875 char str[MAXNODESTR * 2];
00876 } nodelog;
00877
00878 static int service_scan(struct rpt *myrpt);
00879 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00880 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00881 static int simple_command_ft897(struct rpt *myrpt, char command);
00882 static int setrem(struct rpt *myrpt);
00883 static int setrtx_check(struct rpt *myrpt);
00884 static int channel_revert(struct rpt *myrpt);
00885 static int channel_steer(struct rpt *myrpt, char *data);
00886 static struct ast_format_cap *get_slin_cap(struct ast_format_cap *cap);
00887
00888 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00889
00890 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00891
00892 #ifdef APP_RPT_LOCK_DEBUG
00893
00894 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00895
00896 #define MAXLOCKTHREAD 100
00897
00898 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00899 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00900
00901 struct lockthread
00902 {
00903 pthread_t id;
00904 int lockcount;
00905 int lastlock;
00906 int lastunlock;
00907 } lockthreads[MAXLOCKTHREAD];
00908
00909
00910 struct by_lightning
00911 {
00912 int line;
00913 struct timeval tv;
00914 struct rpt *rpt;
00915 struct lockthread lockthread;
00916 } lock_ring[32];
00917
00918 int lock_ring_index = 0;
00919
00920 AST_MUTEX_DEFINE_STATIC(locklock);
00921
00922 static struct lockthread *get_lockthread(pthread_t id)
00923 {
00924 int i;
00925
00926 for(i = 0; i < MAXLOCKTHREAD; i++)
00927 {
00928 if (lockthreads[i].id == id) return(&lockthreads[i]);
00929 }
00930 return(NULL);
00931 }
00932
00933 static struct lockthread *put_lockthread(pthread_t id)
00934 {
00935 int i;
00936
00937 for(i = 0; i < MAXLOCKTHREAD; i++)
00938 {
00939 if (lockthreads[i].id == id)
00940 return(&lockthreads[i]);
00941 }
00942 for(i = 0; i < MAXLOCKTHREAD; i++)
00943 {
00944 if (!lockthreads[i].id)
00945 {
00946 lockthreads[i].lockcount = 0;
00947 lockthreads[i].lastlock = 0;
00948 lockthreads[i].lastunlock = 0;
00949 lockthreads[i].id = id;
00950 return(&lockthreads[i]);
00951 }
00952 }
00953 return(NULL);
00954 }
00955
00956 static void rpt_mutex_spew(void)
00957 {
00958 struct by_lightning lock_ring_copy[32];
00959 int lock_ring_index_copy;
00960 int i,j;
00961 long long diff;
00962 char a[100];
00963 struct timeval lasttv;
00964
00965 ast_mutex_lock(&locklock);
00966 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00967 lock_ring_index_copy = lock_ring_index;
00968 ast_mutex_unlock(&locklock);
00969
00970 lasttv.tv_sec = lasttv.tv_usec = 0;
00971 for(i = 0 ; i < 32 ; i++)
00972 {
00973 j = (i + lock_ring_index_copy) % 32;
00974 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00975 localtime(&lock_ring_copy[j].tv.tv_sec));
00976 diff = 0;
00977 if(lasttv.tv_sec)
00978 {
00979 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00980 * 1000000;
00981 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00982 }
00983 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00984 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00985 if (!lock_ring_copy[j].tv.tv_sec) continue;
00986 if (lock_ring_copy[j].line < 0)
00987 {
00988 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00989 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);
00990 }
00991 else
00992 {
00993 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00994 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);
00995 }
00996 }
00997 }
00998
00999
01000 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01001 {
01002 struct lockthread *t;
01003 pthread_t id;
01004
01005 id = pthread_self();
01006 ast_mutex_lock(&locklock);
01007 t = put_lockthread(id);
01008 if (!t)
01009 {
01010 ast_mutex_unlock(&locklock);
01011 return;
01012 }
01013 if (t->lockcount)
01014 {
01015 int lastline = t->lastlock;
01016 ast_mutex_unlock(&locklock);
01017 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);
01018 rpt_mutex_spew();
01019 return;
01020 }
01021 t->lastlock = line;
01022 t->lockcount = 1;
01023 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01024 lock_ring[lock_ring_index].rpt = myrpt;
01025 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01026 lock_ring[lock_ring_index++].line = line;
01027 if(lock_ring_index == 32)
01028 lock_ring_index = 0;
01029 ast_mutex_unlock(&locklock);
01030 ast_mutex_lock(lockp);
01031 }
01032
01033
01034 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01035 {
01036 struct lockthread *t;
01037 pthread_t id;
01038
01039 id = pthread_self();
01040 ast_mutex_lock(&locklock);
01041 t = put_lockthread(id);
01042 if (!t)
01043 {
01044 ast_mutex_unlock(&locklock);
01045 return;
01046 }
01047 if (!t->lockcount)
01048 {
01049 int lastline = t->lastunlock;
01050 ast_mutex_unlock(&locklock);
01051 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);
01052 rpt_mutex_spew();
01053 return;
01054 }
01055 t->lastunlock = line;
01056 t->lockcount = 0;
01057 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01058 lock_ring[lock_ring_index].rpt = myrpt;
01059 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01060 lock_ring[lock_ring_index++].line = -line;
01061 if(lock_ring_index == 32)
01062 lock_ring_index = 0;
01063 ast_mutex_unlock(&locklock);
01064 ast_mutex_unlock(lockp);
01065 }
01066
01067 #else
01068
01069 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01070 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01071
01072 #endif
01073
01074 static struct ast_format_cap *get_slin_cap(struct ast_format_cap *cap)
01075 {
01076 struct ast_format tmp;
01077 cap = ast_format_cap_alloc_nolock();
01078 if (!cap) {
01079 return NULL;
01080 }
01081 ast_format_cap_add(cap, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0));
01082
01083 return cap;
01084 }
01085
01086
01087
01088
01089
01090 static int multimode_capable(struct rpt *myrpt)
01091 {
01092 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01093 return 1;
01094 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01095 return 1;
01096 return 0;
01097 }
01098
01099 static void voxinit_rpt(struct rpt *myrpt,char enable)
01100 {
01101
01102 myrpt->vox.speech_energy = 0.0;
01103 myrpt->vox.noise_energy = 0.0;
01104 myrpt->vox.enacount = 0;
01105 myrpt->vox.voxena = 0;
01106 if (!enable) myrpt->vox.voxena = -1;
01107 myrpt->vox.lastvox = 0;
01108 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01109 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01110 myrpt->wasvox = 0;
01111 myrpt->voxtotimer = 0;
01112 myrpt->voxtostate = 0;
01113 }
01114
01115 static void voxinit_link(struct rpt_link *mylink,char enable)
01116 {
01117
01118 mylink->vox.speech_energy = 0.0;
01119 mylink->vox.noise_energy = 0.0;
01120 mylink->vox.enacount = 0;
01121 mylink->vox.voxena = 0;
01122 if (!enable) mylink->vox.voxena = -1;
01123 mylink->vox.lastvox = 0;
01124 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01125 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01126 mylink->wasvox = 0;
01127 mylink->voxtotimer = 0;
01128 mylink->voxtostate = 0;
01129 }
01130
01131 static int dovox(struct vox *v,short *buf,int bs)
01132 {
01133
01134 int i;
01135 float esquare = 0.0;
01136 float energy = 0.0;
01137 float threshold = 0.0;
01138
01139 if (v->voxena < 0) return(v->lastvox);
01140 for(i = 0; i < bs; i++)
01141 {
01142 esquare += (float) buf[i] * (float) buf[i];
01143 }
01144 energy = sqrt(esquare);
01145
01146 if (energy >= v->speech_energy)
01147 v->speech_energy += (energy - v->speech_energy) / 4;
01148 else
01149 v->speech_energy += (energy - v->speech_energy) / 64;
01150
01151 if (energy >= v->noise_energy)
01152 v->noise_energy += (energy - v->noise_energy) / 64;
01153 else
01154 v->noise_energy += (energy - v->noise_energy) / 4;
01155
01156 if (v->voxena) threshold = v->speech_energy / 8;
01157 else
01158 {
01159 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01160 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01161 }
01162 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01163 if (energy > threshold)
01164 {
01165 if (v->voxena) v->noise_energy *= 0.75;
01166 v->voxena = 1;
01167 } else v->voxena = 0;
01168 if (v->lastvox != v->voxena)
01169 {
01170 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01171 {
01172 v->lastvox = v->voxena;
01173 v->enacount = 0;
01174 }
01175 } else v->enacount = 0;
01176 return(v->lastvox);
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187 static int rpt_do_debug(int fd, int argc, const char * const *argv);
01188 static int rpt_do_dump(int fd, int argc, const char * const *argv);
01189 static int rpt_do_stats(int fd, int argc, const char * const *argv);
01190 static int rpt_do_lstats(int fd, int argc, const char * const *argv);
01191 static int rpt_do_nodes(int fd, int argc, const char * const *argv);
01192 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv);
01193 static int rpt_do_reload(int fd, int argc, const char * const *argv);
01194 static int rpt_do_restart(int fd, int argc, const char * const *argv);
01195 static int rpt_do_fun(int fd, int argc, const char * const *argv);
01196 static int rpt_do_fun1(int fd, int argc, const char * const *argv);
01197 static int rpt_do_cmd(int fd, int argc, const char * const *argv);
01198
01199 static char debug_usage[] =
01200 "Usage: rpt debug level {0-7}\n"
01201 " Enables debug messages in app_rpt\n";
01202
01203 static char dump_usage[] =
01204 "Usage: rpt dump <nodename>\n"
01205 " Dumps struct debug info to log\n";
01206
01207 static char dump_stats[] =
01208 "Usage: rpt stats <nodename>\n"
01209 " Dumps node statistics to console\n";
01210
01211 static char dump_lstats[] =
01212 "Usage: rpt lstats <nodename>\n"
01213 " Dumps link statistics to console\n";
01214
01215 static char dump_nodes[] =
01216 "Usage: rpt nodes <nodename>\n"
01217 " Dumps a list of directly and indirectly connected nodes to the console\n";
01218
01219 static char usage_local_nodes[] =
01220 "Usage: rpt localnodes\n"
01221 " Dumps a list of the locally configured node numbers to the console.\n";
01222
01223 static char reload_usage[] =
01224 "Usage: rpt reload\n"
01225 " Reloads app_rpt running config parameters\n";
01226
01227 static char restart_usage[] =
01228 "Usage: rpt restart\n"
01229 " Restarts app_rpt\n";
01230
01231 static char fun_usage[] =
01232 "Usage: rpt fun <nodename> <command>\n"
01233 " Send a DTMF function to a node\n";
01234
01235 static char cmd_usage[] =
01236 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01237 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01238
01239 #ifndef NEW_ASTERISK
01240
01241 static struct ast_cli_entry cli_debug =
01242 { { "rpt", "debug", "level" }, rpt_do_debug,
01243 "Enable app_rpt debugging", debug_usage };
01244
01245 static struct ast_cli_entry cli_dump =
01246 { { "rpt", "dump" }, rpt_do_dump,
01247 "Dump app_rpt structs for debugging", dump_usage };
01248
01249 static struct ast_cli_entry cli_stats =
01250 { { "rpt", "stats" }, rpt_do_stats,
01251 "Dump node statistics", dump_stats };
01252
01253 static struct ast_cli_entry cli_nodes =
01254 { { "rpt", "nodes" }, rpt_do_nodes,
01255 "Dump node list", dump_nodes };
01256
01257 static struct ast_cli_entry cli_local_nodes =
01258 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01259 "Dump list of local node numbers", usage_local_nodes };
01260
01261 static struct ast_cli_entry cli_lstats =
01262 { { "rpt", "lstats" }, rpt_do_lstats,
01263 "Dump link statistics", dump_lstats };
01264
01265 static struct ast_cli_entry cli_reload =
01266 { { "rpt", "reload" }, rpt_do_reload,
01267 "Reload app_rpt config", reload_usage };
01268
01269 static struct ast_cli_entry cli_restart =
01270 { { "rpt", "restart" }, rpt_do_restart,
01271 "Restart app_rpt", restart_usage };
01272
01273 static struct ast_cli_entry cli_fun =
01274 { { "rpt", "fun" }, rpt_do_fun,
01275 "Execute a DTMF function", fun_usage };
01276
01277 static struct ast_cli_entry cli_fun1 =
01278 { { "rpt", "fun1" }, rpt_do_fun1,
01279 "Execute a DTMF function", fun_usage };
01280
01281 static struct ast_cli_entry cli_cmd =
01282 { { "rpt", "cmd" }, rpt_do_cmd,
01283 "Execute a DTMF function", cmd_usage };
01284
01285 #endif
01286
01287
01288
01289
01290
01291
01292 static struct telem_defaults tele_defs[] = {
01293 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01294 {"ct2","|t(660,880,150,3072)"},
01295 {"ct3","|t(440,0,150,3072)"},
01296 {"ct4","|t(550,0,150,3072)"},
01297 {"ct5","|t(660,0,150,3072)"},
01298 {"ct6","|t(880,0,150,3072)"},
01299 {"ct7","|t(660,440,150,3072)"},
01300 {"ct8","|t(700,1100,150,3072)"},
01301 {"remotemon","|t(1600,0,75,2048)"},
01302 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01303 {"cmdmode","|t(900,904,200,2048)"},
01304 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01305 } ;
01306
01307
01308
01309
01310
01311 static int setrbi(struct rpt *myrpt);
01312 static int set_ft897(struct rpt *myrpt);
01313 static int set_ic706(struct rpt *myrpt);
01314 static int setkenwood(struct rpt *myrpt);
01315 static int set_tm271(struct rpt *myrpt);
01316 static int setrbi_check(struct rpt *myrpt);
01317
01318
01319
01320
01321
01322
01323
01324 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01325 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01326 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01327 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01328 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01329 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01330 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01331 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01332
01333
01334
01335
01336 static struct function_table_tag function_table[] = {
01337 {"cop", function_cop},
01338 {"autopatchup", function_autopatchup},
01339 {"autopatchdn", function_autopatchdn},
01340 {"ilink", function_ilink},
01341 {"status", function_status},
01342 {"remote", function_remote},
01343 {"macro", function_macro},
01344 {"playback", function_playback}
01345 } ;
01346
01347 static long diskavail(struct rpt *myrpt)
01348 {
01349 struct statfs statfsbuf;
01350
01351 if (!myrpt->p.archivedir) return(0);
01352 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01353 {
01354 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01355 myrpt->p.archivedir,myrpt->name);
01356 return(-1);
01357 }
01358 return(statfsbuf.f_bavail);
01359 }
01360
01361 static void flush_telem(struct rpt *myrpt)
01362 {
01363 struct rpt_tele *telem;
01364 if(debug > 2)
01365 ast_log(LOG_NOTICE, "flush_telem()!!");
01366 rpt_mutex_lock(&myrpt->lock);
01367 telem = myrpt->tele.next;
01368 while(telem != &myrpt->tele)
01369 {
01370 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01371 telem = telem->next;
01372 }
01373 rpt_mutex_unlock(&myrpt->lock);
01374 }
01375
01376
01377
01378 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01379 {
01380 int res=0;
01381
01382
01383 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01384 res = 0;
01385 } else {
01386 res = -1;
01387 }
01388 return res;
01389 }
01390
01391
01392 static int linkcount(struct rpt *myrpt)
01393 {
01394 struct rpt_link *l;
01395 char *reverse_patch_state;
01396 int numoflinks;
01397
01398 reverse_patch_state = "DOWN";
01399 numoflinks = 0;
01400 l = myrpt->links.next;
01401 while(l && (l != &myrpt->links)){
01402 if(numoflinks >= MAX_STAT_LINKS){
01403 ast_log(LOG_WARNING,
01404 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01405 break;
01406 }
01407
01408
01409
01410
01411
01412 numoflinks++;
01413
01414 l = l->next;
01415 }
01416 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01417 return numoflinks;
01418 }
01419
01420
01421
01422
01423
01424
01425 static int retreive_memory(struct rpt *myrpt, char *memory)
01426 {
01427 char tmp[30], *s, *s1, *val;
01428
01429 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01430
01431 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01432 if (!val){
01433 return -1;
01434 }
01435 strncpy(tmp,val,sizeof(tmp) - 1);
01436 tmp[sizeof(tmp)-1] = 0;
01437
01438 s = strchr(tmp,',');
01439 if (!s)
01440 return 1;
01441 *s++ = 0;
01442 s1 = strchr(s,',');
01443 if (!s1)
01444 return 1;
01445 *s1++ = 0;
01446 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01447 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01448 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01449 myrpt->remmode = REM_MODE_FM;
01450 myrpt->offset = REM_SIMPLEX;
01451 myrpt->powerlevel = REM_MEDPWR;
01452 myrpt->txplon = myrpt->rxplon = 0;
01453 while(*s1){
01454 switch(*s1++){
01455 case 'A':
01456 case 'a':
01457 strcpy(myrpt->rxpl, "100.0");
01458 strcpy(myrpt->txpl, "100.0");
01459 myrpt->remmode = REM_MODE_AM;
01460 break;
01461 case 'B':
01462 case 'b':
01463 strcpy(myrpt->rxpl, "100.0");
01464 strcpy(myrpt->txpl, "100.0");
01465 myrpt->remmode = REM_MODE_LSB;
01466 break;
01467 case 'F':
01468 myrpt->remmode = REM_MODE_FM;
01469 break;
01470 case 'L':
01471 case 'l':
01472 myrpt->powerlevel = REM_LOWPWR;
01473 break;
01474 case 'H':
01475 case 'h':
01476 myrpt->powerlevel = REM_HIPWR;
01477 break;
01478
01479 case 'M':
01480 case 'm':
01481 myrpt->powerlevel = REM_MEDPWR;
01482 break;
01483
01484 case '-':
01485 myrpt->offset = REM_MINUS;
01486 break;
01487
01488 case '+':
01489 myrpt->offset = REM_PLUS;
01490 break;
01491
01492 case 'S':
01493 case 's':
01494 myrpt->offset = REM_SIMPLEX;
01495 break;
01496
01497 case 'T':
01498 case 't':
01499 myrpt->txplon = 1;
01500 break;
01501
01502 case 'R':
01503 case 'r':
01504 myrpt->rxplon = 1;
01505 break;
01506
01507 case 'U':
01508 case 'u':
01509 strcpy(myrpt->rxpl, "100.0");
01510 strcpy(myrpt->txpl, "100.0");
01511 myrpt->remmode = REM_MODE_USB;
01512 break;
01513 default:
01514 return 1;
01515 }
01516 }
01517 return 0;
01518 }
01519
01520
01521
01522 static void birdbath(struct rpt *myrpt)
01523 {
01524 struct rpt_tele *telem;
01525 if(debug > 2)
01526 ast_log(LOG_NOTICE, "birdbath!!");
01527 rpt_mutex_lock(&myrpt->lock);
01528 telem = myrpt->tele.next;
01529 while(telem != &myrpt->tele)
01530 {
01531 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01532 telem = telem->next;
01533 }
01534 rpt_mutex_unlock(&myrpt->lock);
01535 }
01536
01537 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01538 {
01539 struct rpt_link *l;
01540
01541 l = myrpt->links.next;
01542
01543 while(l != &myrpt->links)
01544 {
01545 if (!l->phonemode)
01546 {
01547 l = l->next;
01548 continue;
01549 }
01550
01551 if (mylink && (l == mylink))
01552 {
01553 l = l->next;
01554 continue;
01555 }
01556 #ifdef NEW_ASTERISK
01557 if (l->chan) ast_senddigit(l->chan,c,0);
01558 #else
01559 if (l->chan) ast_senddigit(l->chan,c);
01560 #endif
01561 l = l->next;
01562 }
01563 return;
01564 }
01565
01566
01567 static void donodelog(struct rpt *myrpt,char *str)
01568 {
01569 struct nodelog *nodep;
01570 char datestr[100];
01571
01572 if (!myrpt->p.archivedir) return;
01573 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01574 if (nodep == NULL)
01575 {
01576 ast_log(LOG_ERROR,"Cannot get memory for node log");
01577 return;
01578 }
01579 time(&nodep->timestamp);
01580 strncpy(nodep->archivedir,myrpt->p.archivedir,
01581 sizeof(nodep->archivedir) - 1);
01582 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01583 localtime(&nodep->timestamp));
01584 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01585 myrpt->name,datestr,str);
01586 ast_mutex_lock(&nodeloglock);
01587 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01588 ast_mutex_unlock(&nodeloglock);
01589 }
01590
01591
01592 static void do_dtmf_local(struct rpt *myrpt, char c)
01593 {
01594 int i;
01595 char digit;
01596 static const char* dtmf_tones[] = {
01597 "!941+1336/200,!0/200",
01598 "!697+1209/200,!0/200",
01599 "!697+1336/200,!0/200",
01600 "!697+1477/200,!0/200",
01601 "!770+1209/200,!0/200",
01602 "!770+1336/200,!0/200",
01603 "!770+1477/200,!0/200",
01604 "!852+1209/200,!0/200",
01605 "!852+1336/200,!0/200",
01606 "!852+1477/200,!0/200",
01607 "!697+1633/200,!0/200",
01608 "!770+1633/200,!0/200",
01609 "!852+1633/200,!0/200",
01610 "!941+1633/200,!0/200",
01611 "!941+1209/200,!0/200",
01612 "!941+1477/200,!0/200" };
01613
01614
01615 if (c)
01616 {
01617 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01618 if (!myrpt->dtmf_local_timer)
01619 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01620 }
01621
01622 if (myrpt->dtmf_local_timer == 1)
01623 {
01624 if(debug > 6)
01625 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01626
01627
01628 if (myrpt->dtmf_local_str[0])
01629 {
01630 digit = myrpt->dtmf_local_str[0];
01631 myrpt->dtmf_local_str[0] = 0;
01632 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01633 {
01634 myrpt->dtmf_local_str[i - 1] =
01635 myrpt->dtmf_local_str[i];
01636 }
01637 myrpt->dtmf_local_str[i - 1] = 0;
01638 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01639 rpt_mutex_unlock(&myrpt->lock);
01640 if (digit >= '0' && digit <='9')
01641 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01642 else if (digit >= 'A' && digit <= 'D')
01643 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01644 else if (digit == '*')
01645 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01646 else if (digit == '#')
01647 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01648 else {
01649
01650 ast_debug(1, "Unable to generate DTMF tone '%c' for '%s'\n", digit, ast_channel_name(myrpt->txchannel));
01651 }
01652 rpt_mutex_lock(&myrpt->lock);
01653 }
01654 else
01655 {
01656 myrpt->dtmf_local_timer = 0;
01657 }
01658 }
01659 }
01660
01661 static int setdtr(int fd, int enable)
01662 {
01663 struct termios mode;
01664
01665 if (fd < 0) return -1;
01666 if (tcgetattr(fd, &mode)) {
01667 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01668 return -1;
01669 }
01670 if (enable)
01671 {
01672 cfsetspeed(&mode, B9600);
01673 }
01674 else
01675 {
01676 cfsetspeed(&mode, B0);
01677 usleep(100000);
01678 }
01679 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01680 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01681 return -1;
01682 }
01683 if (enable) usleep(100000);
01684 return 0;
01685 }
01686
01687 static int openserial(struct rpt *myrpt,char *fname)
01688 {
01689 struct termios mode;
01690 int fd;
01691
01692 fd = open(fname,O_RDWR);
01693 if (fd == -1)
01694 {
01695 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01696 return -1;
01697 }
01698 memset(&mode, 0, sizeof(mode));
01699 if (tcgetattr(fd, &mode)) {
01700 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01701 return -1;
01702 }
01703 #ifndef SOLARIS
01704 cfmakeraw(&mode);
01705 #else
01706 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01707 |INLCR|IGNCR|ICRNL|IXON);
01708 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01709 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01710 mode.c_cflag |= CS8;
01711 mode.c_cc[VTIME] = 3;
01712 mode.c_cc[VMIN] = 1;
01713 #endif
01714
01715 cfsetispeed(&mode, B9600);
01716 cfsetospeed(&mode, B9600);
01717 if (tcsetattr(fd, TCSANOW, &mode))
01718 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01719 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01720 usleep(100000);
01721 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01722 return(fd);
01723 }
01724
01725 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01726 {
01727 if (!fromnode)
01728 {
01729 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01730 unit,myrpt->name);
01731 }
01732 else
01733 {
01734 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01735 unit,fromnode,myrpt->name);
01736 }
01737 }
01738
01739 #ifdef _MDC_DECODE_H_
01740
01741 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01742 {
01743 struct rpt_link *l;
01744 struct ast_frame wf;
01745 char str[200];
01746
01747
01748 sprintf(str,"I %s %04X",myrpt->name,unit);
01749
01750 wf.frametype = AST_FRAME_TEXT;
01751 wf.subclass.integer = 0;
01752 wf.offset = 0;
01753 wf.mallocd = 0;
01754 wf.datalen = strlen(str) + 1;
01755 wf.samples = 0;
01756
01757
01758 l = myrpt->links.next;
01759
01760 while(l != &myrpt->links)
01761 {
01762 if (l->name[0] == '0')
01763 {
01764 l = l->next;
01765 continue;
01766 }
01767 wf.data = str;
01768 if (l->chan) ast_write(l->chan,&wf);
01769 l = l->next;
01770 }
01771 return;
01772 }
01773
01774 #endif
01775
01776 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01777 {
01778 time_t now;
01779 int gotone;
01780
01781 time(&now);
01782 gotone = 0;
01783
01784 if ((now - xlat->lastone) > MAXXLATTIME)
01785 {
01786 xlat->funcindex = xlat->endindex = 0;
01787 }
01788 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01789 {
01790 time(&xlat->lastone);
01791 gotone = 1;
01792 if (!xlat->funccharseq[xlat->funcindex])
01793 {
01794 xlat->funcindex = xlat->endindex = 0;
01795 return(myrpt->p.funcchar);
01796 }
01797 } else xlat->funcindex = 0;
01798 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01799 {
01800 time(&xlat->lastone);
01801 gotone = 1;
01802 if (!xlat->endcharseq[xlat->endindex])
01803 {
01804 xlat->funcindex = xlat->endindex = 0;
01805 return(myrpt->p.endchar);
01806 }
01807 } else xlat->endindex = 0;
01808
01809 if (gotone) return(0);
01810
01811 if (!xlat->passchars[0]) return(c);
01812
01813 if (strchr(xlat->passchars,c)) return(c);
01814 return(0);
01815 }
01816
01817
01818
01819
01820
01821 static char *eatwhite(char *s)
01822 {
01823 while((*s == ' ') || (*s == 0x09)){
01824 if(!*s)
01825 break;
01826 s++;
01827 }
01828 return s;
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841 static int finddelim(char *str, char *strp[], int limit)
01842 {
01843 int i,l,inquo;
01844
01845 inquo = 0;
01846 i = 0;
01847 strp[i++] = str;
01848 if (!*str)
01849 {
01850 strp[0] = 0;
01851 return(0);
01852 }
01853 for(l = 0; *str && (l < limit) ; str++)
01854 {
01855 if (*str == QUOTECHR)
01856 {
01857 if (inquo)
01858 {
01859 *str = 0;
01860 inquo = 0;
01861 }
01862 else
01863 {
01864 strp[i - 1] = str + 1;
01865 inquo = 1;
01866 }
01867 }
01868 if ((*str == DELIMCHR) && (!inquo))
01869 {
01870 *str = 0;
01871 l++;
01872 strp[i++] = str + 1;
01873 }
01874 }
01875 strp[i] = 0;
01876 return(i);
01877
01878 }
01879
01880
01881
01882 static int send_usb_txt(struct rpt *myrpt, char *txt)
01883 {
01884 struct ast_frame wf;
01885
01886 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01887 wf.frametype = AST_FRAME_TEXT;
01888 wf.subclass.integer = 0;
01889 wf.offset = 0;
01890 wf.mallocd = 0;
01891 wf.datalen = strlen(txt) + 1;
01892 wf.data.ptr = txt;
01893 wf.samples = 0;
01894 ast_write(myrpt->txchannel,&wf);
01895 return 0;
01896 }
01897
01898 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01899 {
01900 struct rpt_link *l;
01901 char mode;
01902 int i,spos;
01903
01904 buf[0] = 0;
01905 if (myrpt->remote) return;
01906
01907 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01908 {
01909
01910 if (l->name[0] == '0') continue;
01911
01912 if (l == mylink) continue;
01913 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01914
01915 mode = 'T';
01916 if (!l->mode) mode = 'R';
01917 if (!l->thisconnected) mode = 'C';
01918 spos = strlen(buf);
01919 if (spos)
01920 {
01921 strcat(buf,",");
01922 spos++;
01923 }
01924
01925 if (l->linklist[0])
01926 {
01927 snprintf(buf + spos,MAXLINKLIST - spos,
01928 "%c%s,%s",mode,l->name,l->linklist);
01929 }
01930 else
01931 {
01932 snprintf(buf + spos,MAXLINKLIST - spos,
01933 "%c%s",mode,l->name);
01934 }
01935
01936 if (mode == 'T') continue;
01937
01938 for(i = spos; buf[i]; i++)
01939 {
01940 if (buf[i] == 'T') buf[i] = mode;
01941 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01942 }
01943 }
01944 return;
01945 }
01946
01947
01948 static void __kickshort(struct rpt *myrpt)
01949 {
01950 struct rpt_link *l;
01951
01952 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01953 {
01954
01955 if (l->name[0] == '0') continue;
01956 l->linklisttimer = LINKLISTSHORTTIME;
01957 }
01958 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01959 return;
01960 }
01961
01962 static void statpost(struct rpt *myrpt,char *pairs)
01963 {
01964 char *str,*astr;
01965 char *astrs[100];
01966 int n,pid;
01967 time_t now;
01968 unsigned int seq;
01969
01970 if (!myrpt->p.statpost_url) return;
01971 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01972 astr = ast_strdup(myrpt->p.statpost_program);
01973 if ((!str) || (!astr)) {
01974 ast_free(str);
01975 ast_free(astr);
01976 return;
01977 }
01978 n = finddelim(astr,astrs,100);
01979 if (n < 1) {
01980 ast_free(str);
01981 ast_free(astr);
01982 return;
01983 }
01984 ast_mutex_lock(&myrpt->statpost_lock);
01985 seq = ++myrpt->statpost_seqno;
01986 ast_mutex_unlock(&myrpt->statpost_lock);
01987 astrs[n++] = str;
01988 astrs[n] = NULL;
01989 time(&now);
01990 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01991 myrpt->name,(unsigned int) now,seq);
01992 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01993 if (!(pid = ast_safe_fork(0)))
01994 {
01995 execv(astrs[0],astrs);
01996 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01997 perror("asterisk");
01998 exit(0);
01999 }
02000 ast_free(astr);
02001 ast_free(str);
02002 return;
02003 }
02004
02005 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
02006 {
02007
02008 char *val;
02009 int longestnode,j;
02010 struct stat mystat;
02011 static time_t last = 0;
02012 static struct ast_config *ourcfg = NULL;
02013 struct ast_variable *vp;
02014
02015
02016 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
02017 if (val) return(val);
02018 ast_mutex_lock(&nodelookuplock);
02019
02020 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02021 {
02022 if (ourcfg) ast_config_destroy(ourcfg);
02023 ourcfg = NULL;
02024 ast_mutex_unlock(&nodelookuplock);
02025 return(NULL);
02026 }
02027
02028 if (mystat.st_mtime > last)
02029 {
02030 if (ourcfg) ast_config_destroy(ourcfg);
02031 #ifdef NEW_ASTERISK
02032 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02033 #else
02034 ourcfg = ast_config_load(myrpt->p.extnodefile);
02035 #endif
02036
02037 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02038 {
02039 ast_mutex_unlock(&nodelookuplock);
02040 return(NULL);
02041 }
02042
02043 last = mystat.st_mtime;
02044
02045
02046 longestnode = 0;
02047 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02048 while(vp){
02049 j = strlen(vp->name);
02050 if (j > longestnode)
02051 longestnode = j;
02052 vp = vp->next;
02053 }
02054
02055 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02056 while(vp){
02057 j = strlen(vp->name);
02058 if (j > longestnode)
02059 longestnode = j;
02060 vp = vp->next;
02061 }
02062
02063 myrpt->longestnode = longestnode;
02064 }
02065 val = NULL;
02066 if (ourcfg)
02067 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02068 ast_mutex_unlock(&nodelookuplock);
02069 return(val);
02070 }
02071
02072
02073
02074
02075
02076
02077 static int matchkeyword(char *string, char **param, char *keywords[])
02078 {
02079 int i,ls;
02080 for( i = 0 ; keywords[i] ; i++){
02081 ls = strlen(keywords[i]);
02082 if(!ls){
02083 *param = NULL;
02084 return 0;
02085 }
02086 if(!strncmp(string, keywords[i], ls)){
02087 if(param)
02088 *param = string + ls;
02089 return i + 1;
02090 }
02091 }
02092 *param = NULL;
02093 return 0;
02094 }
02095
02096
02097
02098
02099
02100
02101 static char *skipchars(char *string, char *charlist)
02102 {
02103 int i;
02104 while(*string){
02105 for(i = 0; charlist[i] ; i++){
02106 if(*string == charlist[i]){
02107 string++;
02108 break;
02109 }
02110 }
02111 if(!charlist[i])
02112 return string;
02113 }
02114 return string;
02115 }
02116
02117 static int myatoi(const char *str)
02118 {
02119 int ret;
02120
02121 if (!str) {
02122 return -1;
02123 }
02124
02125
02126 if (sscanf(str, "%30i", &ret) != 1) {
02127 return -1;
02128 }
02129
02130 return ret;
02131 }
02132
02133 static int mycompar(const void *a, const void *b)
02134 {
02135 char **x = (char **) a;
02136 char **y = (char **) b;
02137 int xoff,yoff;
02138
02139 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02140 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02141 return(strcmp((*x) + xoff,(*y) + yoff));
02142 }
02143
02144 static int topcompar(const void *a, const void *b)
02145 {
02146 struct rpt_topkey *x = (struct rpt_topkey *) a;
02147 struct rpt_topkey *y = (struct rpt_topkey *) b;
02148
02149 return(x->timesince - y->timesince);
02150 }
02151
02152 #ifdef __RPT_NOTCH
02153
02154
02155 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02156 {
02157 int i,j;
02158 struct rptfilter *f;
02159
02160 for(i = 0; i < len; i++)
02161 {
02162 for(j = 0; j < MAXFILTERS; j++)
02163 {
02164 f = &myrpt->filters[j];
02165 if (!*f->desc) continue;
02166 f->x0 = f->x1; f->x1 = f->x2;
02167 f->x2 = ((float)buf[i]) / f->gain;
02168 f->y0 = f->y1; f->y1 = f->y2;
02169 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02170 + (f->const1 * f->y0) + (f->const2 * f->y1);
02171 buf[i] = (short)f->y2;
02172 }
02173 }
02174 }
02175
02176 #endif
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 #ifdef NEW_ASTERISK
02196 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02197 {
02198 struct timeval when;
02199
02200 when.tv_sec = *t;
02201 when.tv_usec = 0;
02202 ast_localtime(&when, lt, NULL);
02203 }
02204
02205 #else
02206 static void rpt_localtime( time_t * t, struct tm *lt)
02207 {
02208 #ifdef OLD_ASTERISK
02209 localtime_r(t, lt);
02210 #else
02211 ast_localtime(t, lt, NULL);
02212 #endif
02213 }
02214 #endif
02215
02216
02217
02218
02219 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02220 {
02221 char *var;
02222 int ret;
02223 char include_zero = 0;
02224
02225 if(min < 0){
02226 min = -min;
02227 include_zero = 1;
02228 }
02229
02230 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02231 if(var){
02232 ret = myatoi(var);
02233 if(include_zero && !ret)
02234 return 0;
02235 if(ret < min)
02236 ret = min;
02237 if(ret > max)
02238 ret = max;
02239 }
02240 else
02241 ret = defl;
02242 return ret;
02243 }
02244
02245
02246 static void load_rpt_vars(int n,int init)
02247 {
02248 char *this,*val;
02249 int i,j,longestnode;
02250 struct ast_variable *vp;
02251 struct ast_config *cfg;
02252 char *strs[100];
02253 char s1[256];
02254 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02255 "ufena","ufdis","atena","atdis",NULL};
02256
02257 ast_verb(3, "%s config for repeater %s\n",
02258 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02259 ast_mutex_lock(&rpt_vars[n].lock);
02260 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02261 #ifdef NEW_ASTERISK
02262 cfg = ast_config_load("rpt.conf",config_flags);
02263 #else
02264 cfg = ast_config_load("rpt.conf");
02265 #endif
02266 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02267 ast_mutex_unlock(&rpt_vars[n].lock);
02268 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02269 pthread_exit(NULL);
02270 }
02271 rpt_vars[n].cfg = cfg;
02272 this = rpt_vars[n].name;
02273 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02274 if (init)
02275 {
02276 char *cp;
02277 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02278
02279 cp = (char *) &rpt_vars[n].p;
02280 memset(cp + sizeof(rpt_vars[n].p),0,
02281 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02282 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02283 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02284 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02285 rpt_vars[n].tailmessagen = 0;
02286 }
02287 #ifdef __RPT_NOTCH
02288
02289 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02290 #endif
02291 val = (char *) ast_variable_retrieve(cfg,this,"context");
02292 if (val) rpt_vars[n].p.ourcontext = val;
02293 else rpt_vars[n].p.ourcontext = this;
02294 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02295 if (val) rpt_vars[n].p.ourcallerid = val;
02296 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02297 if (val) rpt_vars[n].p.acctcode = val;
02298 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02299 if (val) rpt_vars[n].p.ident = val;
02300 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02301 if (val) rpt_vars[n].p.hangtime = atoi(val);
02302 else rpt_vars[n].p.hangtime = HANGTIME;
02303 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02304 if (val) rpt_vars[n].p.althangtime = atoi(val);
02305 else rpt_vars[n].p.althangtime = HANGTIME;
02306 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02307 if (val) rpt_vars[n].p.totime = atoi(val);
02308 else rpt_vars[n].p.totime = TOTIME;
02309 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02310 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02311 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02312 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02313 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02314 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02315 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02316 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02317 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02318 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02319 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02320 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02321 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02322 if (val) rpt_vars[n].p.statpost_program = val;
02323 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02324 rpt_vars[n].p.statpost_url =
02325 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02326 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02327 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02328 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02329 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02330 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02331 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02332 if (val) rpt_vars[n].p.tonezone = val;
02333 rpt_vars[n].p.tailmessages[0] = 0;
02334 rpt_vars[n].p.tailmessagemax = 0;
02335 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02336 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02337 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02338 if (!val) val = MEMORY;
02339 rpt_vars[n].p.memory = val;
02340 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02341 if (!val) val = MACRO;
02342 rpt_vars[n].p.macro = val;
02343 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02344 if (!val) val = TONEMACRO;
02345 rpt_vars[n].p.tonemacro = val;
02346 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02347 if (val) rpt_vars[n].p.startupmacro = val;
02348 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02349
02350
02351
02352 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02353 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02354 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02355 rpt_vars[n].p.ioport = val;
02356 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02357 if (!val)
02358 {
02359 val = FUNCTIONS;
02360 rpt_vars[n].p.simple = 1;
02361 }
02362 rpt_vars[n].p.functions = val;
02363 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02364 if (val) rpt_vars[n].p.link_functions = val;
02365 else
02366 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02367 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02368 if (val) rpt_vars[n].p.phone_functions = val;
02369 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02370 if (val) rpt_vars[n].p.dphone_functions = val;
02371 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02372 if (val) rpt_vars[n].p.alt_functions = val;
02373 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02374 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02375 rpt_vars[n].p.funcchar = *val;
02376 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02377 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02378 rpt_vars[n].p.endchar = *val;
02379 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02380 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02381 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02382 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02383 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02384 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02385 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02386 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02387 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02388 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02389 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02390 if (!val) val = NODES;
02391 rpt_vars[n].p.nodes = val;
02392 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02393 if (!val) val = EXTNODES;
02394 rpt_vars[n].p.extnodes = val;
02395 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02396 if (!val) val = EXTNODEFILE;
02397 rpt_vars[n].p.extnodefile = val;
02398 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02399 if (val) rpt_vars[n].p.archivedir = val;
02400 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02401 if (val) rpt_vars[n].p.authlevel = atoi(val);
02402 else rpt_vars[n].p.authlevel = 0;
02403 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02404 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02405 else rpt_vars[n].p.parrotmode = 0;
02406 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02407 if (val) rpt_vars[n].p.parrottime = atoi(val);
02408 else rpt_vars[n].p.parrottime = PARROTTIME;
02409 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02410 rpt_vars[n].p.rptnode = val;
02411 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02412 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02413 else rpt_vars[n].p.remote_mars = 0;
02414 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02415 if (val) rpt_vars[n].p.monminblocks = atol(val);
02416 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02417 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02418 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02419 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02420 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02421 if (val) rpt_vars[n].p.civaddr = atoi(val);
02422 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02423 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02424 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02425 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02426 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02427 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02428 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02429 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02430 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02431 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02432 #ifdef __RPT_NOTCH
02433 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02434 if (val) {
02435 i = finddelim(val,strs,MAXFILTERS * 2);
02436 i &= ~1;
02437 if (i >= 2) for(j = 0; j < i; j += 2)
02438 {
02439 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02440 &rpt_vars[n].filters[j >> 1].gain,
02441 &rpt_vars[n].filters[j >> 1].const0,
02442 &rpt_vars[n].filters[j >> 1].const1,
02443 &rpt_vars[n].filters[j >> 1].const2);
02444 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02445 strs[j],strs[j + 1]);
02446 }
02447
02448 }
02449 #endif
02450 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02451 if (val) {
02452 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02453 i = finddelim(val,strs,3);
02454 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02455 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02456 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02457 }
02458 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02459 if (val) {
02460 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02461 i = finddelim(val,strs,3);
02462 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02463 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02464 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02465 }
02466
02467 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02468 rpt_vars[n].p.csstanzaname = val;
02469
02470
02471 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02472 rpt_vars[n].p.skedstanzaname = val;
02473
02474
02475 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02476 rpt_vars[n].p.txlimitsstanzaname = val;
02477
02478 longestnode = 0;
02479
02480 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02481
02482 while(vp){
02483 j = strlen(vp->name);
02484 if (j > longestnode)
02485 longestnode = j;
02486 vp = vp->next;
02487 }
02488
02489 rpt_vars[n].longestnode = longestnode;
02490
02491
02492
02493
02494 rpt_vars[n].longestfunc = 0;
02495 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02496 while(vp){
02497 j = strlen(vp->name);
02498 if (j > rpt_vars[n].longestfunc)
02499 rpt_vars[n].longestfunc = j;
02500 vp = vp->next;
02501 }
02502
02503
02504
02505 rpt_vars[n].link_longestfunc = 0;
02506 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02507 while(vp){
02508 j = strlen(vp->name);
02509 if (j > rpt_vars[n].link_longestfunc)
02510 rpt_vars[n].link_longestfunc = j;
02511 vp = vp->next;
02512 }
02513 rpt_vars[n].phone_longestfunc = 0;
02514 if (rpt_vars[n].p.phone_functions)
02515 {
02516 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02517 while(vp){
02518 j = strlen(vp->name);
02519 if (j > rpt_vars[n].phone_longestfunc)
02520 rpt_vars[n].phone_longestfunc = j;
02521 vp = vp->next;
02522 }
02523 }
02524 rpt_vars[n].dphone_longestfunc = 0;
02525 if (rpt_vars[n].p.dphone_functions)
02526 {
02527 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02528 while(vp){
02529 j = strlen(vp->name);
02530 if (j > rpt_vars[n].dphone_longestfunc)
02531 rpt_vars[n].dphone_longestfunc = j;
02532 vp = vp->next;
02533 }
02534 }
02535 rpt_vars[n].alt_longestfunc = 0;
02536 if (rpt_vars[n].p.alt_functions)
02537 {
02538 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02539 while(vp){
02540 j = strlen(vp->name);
02541 if (j > rpt_vars[n].alt_longestfunc)
02542 rpt_vars[n].alt_longestfunc = j;
02543 vp = vp->next;
02544 }
02545 }
02546 rpt_vars[n].macro_longest = 1;
02547 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02548 while(vp){
02549 j = strlen(vp->name);
02550 if (j > rpt_vars[n].macro_longest)
02551 rpt_vars[n].macro_longest = j;
02552 vp = vp->next;
02553 }
02554
02555
02556 if(rpt_vars[n].p.csstanzaname)
02557 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02558 else
02559 vp = NULL;
02560 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02561 int k,nukw,statenum;
02562 statenum=atoi(vp->name);
02563 strncpy(s1, vp->value, 255);
02564 s1[255] = 0;
02565 nukw = finddelim(s1,strs,32);
02566
02567 for (k = 0 ; k < nukw ; k++){
02568 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02569 if(!strcmp(strs[k],cs_keywords[j])){
02570 switch(j){
02571 case 0:
02572 rpt_vars[n].p.s[statenum].txdisable = 0;
02573 break;
02574 case 1:
02575 rpt_vars[n].p.s[statenum].txdisable = 1;
02576 break;
02577
02578 case 2:
02579 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02580 break;
02581
02582 case 3:
02583 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02584 break;
02585
02586 case 4:
02587 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02588 break;
02589
02590 case 5:
02591 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02592 break;
02593
02594 case 6:
02595 rpt_vars[n].p.s[statenum].totdisable = 0;
02596 break;
02597
02598 case 7:
02599 rpt_vars[n].p.s[statenum].totdisable = 1;
02600 break;
02601
02602 case 8:
02603 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02604 break;
02605
02606 case 9:
02607 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02608 break;
02609
02610 case 10:
02611 rpt_vars[n].p.s[statenum].userfundisable = 0;
02612 break;
02613
02614 case 11:
02615 rpt_vars[n].p.s[statenum].userfundisable = 1;
02616 break;
02617
02618 case 12:
02619 rpt_vars[n].p.s[statenum].alternatetail = 1;
02620 break;
02621
02622 case 13:
02623 rpt_vars[n].p.s[statenum].alternatetail = 0;
02624 break;
02625
02626 default:
02627 ast_log(LOG_WARNING,
02628 "Unhandled control state keyword %s", cs_keywords[i]);
02629 break;
02630 }
02631 }
02632 }
02633 }
02634 vp = vp->next;
02635 }
02636 ast_mutex_unlock(&rpt_vars[n].lock);
02637 }
02638
02639
02640
02641
02642 static int rpt_do_debug(int fd, int argc, const char * const *argv)
02643 {
02644 int newlevel;
02645
02646 if (argc != 4) {
02647 return RESULT_SHOWUSAGE;
02648 }
02649
02650 newlevel = myatoi(argv[3]);
02651
02652 if (newlevel < 0 || newlevel > 7) {
02653 return RESULT_SHOWUSAGE;
02654 }
02655
02656 if (newlevel) {
02657 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02658 } else {
02659 ast_cli(fd, "app_rpt Debugging disabled\n");
02660 }
02661
02662 debug = newlevel;
02663
02664 return RESULT_SUCCESS;
02665 }
02666
02667
02668
02669
02670
02671 static int rpt_do_dump(int fd, int argc, const char * const *argv)
02672 {
02673 int i;
02674
02675 if (argc != 3)
02676 return RESULT_SHOWUSAGE;
02677
02678 for(i = 0; i < nrpts; i++)
02679 {
02680 if (!strcmp(argv[2],rpt_vars[i].name))
02681 {
02682 rpt_vars[i].disgorgetime = time(NULL) + 10;
02683 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02684 return RESULT_SUCCESS;
02685 }
02686 }
02687 return RESULT_FAILURE;
02688 }
02689
02690
02691
02692
02693
02694 static int rpt_do_stats(int fd, int argc, const char * const *argv)
02695 {
02696 int i,j,numoflinks;
02697 int dailytxtime, dailykerchunks;
02698 time_t now;
02699 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02700 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02701 int uptime;
02702 long long totaltxtime;
02703 struct rpt_link *l;
02704 char *listoflinks[MAX_STAT_LINKS];
02705 char *lastdtmfcommand,*parrot_ena;
02706 char *tot_state, *ider_state, *patch_state;
02707 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02708 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02709 struct rpt *myrpt;
02710
02711 static char *not_applicable = "N/A";
02712
02713 if(argc != 3)
02714 return RESULT_SHOWUSAGE;
02715
02716 tot_state = ider_state =
02717 patch_state = reverse_patch_state =
02718 input_signal = not_applicable;
02719 called_number = lastdtmfcommand = NULL;
02720
02721 time(&now);
02722 for(i = 0; i < nrpts; i++)
02723 {
02724 if (!strcmp(argv[2],rpt_vars[i].name)){
02725
02726 myrpt = &rpt_vars[i];
02727 rpt_mutex_lock(&myrpt->lock);
02728 uptime = (int)(now - starttime);
02729 dailytxtime = myrpt->dailytxtime;
02730 totaltxtime = myrpt->totaltxtime;
02731 dailykeyups = myrpt->dailykeyups;
02732 totalkeyups = myrpt->totalkeyups;
02733 dailykerchunks = myrpt->dailykerchunks;
02734 totalkerchunks = myrpt->totalkerchunks;
02735 dailyexecdcommands = myrpt->dailyexecdcommands;
02736 totalexecdcommands = myrpt->totalexecdcommands;
02737 timeouts = myrpt->timeouts;
02738
02739
02740 reverse_patch_state = "DOWN";
02741 numoflinks = 0;
02742 l = myrpt->links.next;
02743 while(l && (l != &myrpt->links)){
02744 if(numoflinks >= MAX_STAT_LINKS){
02745 ast_log(LOG_NOTICE,
02746 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02747 break;
02748 }
02749 if (l->name[0] == '0'){
02750 reverse_patch_state = "UP";
02751 l = l->next;
02752 continue;
02753 }
02754 listoflinks[numoflinks] = ast_strdup(l->name);
02755 if(listoflinks[numoflinks] == NULL){
02756 break;
02757 }
02758 else{
02759 numoflinks++;
02760 }
02761 l = l->next;
02762 }
02763
02764 if(myrpt->keyed)
02765 input_signal = "YES";
02766 else
02767 input_signal = "NO";
02768
02769 if(myrpt->p.parrotmode)
02770 parrot_ena = "ENABLED";
02771 else
02772 parrot_ena = "DISABLED";
02773
02774 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02775 sys_ena = "DISABLED";
02776 else
02777 sys_ena = "ENABLED";
02778
02779 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02780 tot_ena = "DISABLED";
02781 else
02782 tot_ena = "ENABLED";
02783
02784 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02785 link_ena = "DISABLED";
02786 else
02787 link_ena = "ENABLED";
02788
02789 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02790 patch_ena = "DISABLED";
02791 else
02792 patch_ena = "ENABLED";
02793
02794 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02795 sch_ena = "DISABLED";
02796 else
02797 sch_ena = "ENABLED";
02798
02799 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02800 user_funs = "DISABLED";
02801 else
02802 user_funs = "ENABLED";
02803
02804 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02805 tail_type = "ALTERNATE";
02806 else
02807 tail_type = "STANDARD";
02808
02809 if(!myrpt->totimer)
02810 tot_state = "TIMED OUT!";
02811 else if(myrpt->totimer != myrpt->p.totime)
02812 tot_state = "ARMED";
02813 else
02814 tot_state = "RESET";
02815
02816 if(myrpt->tailid)
02817 ider_state = "QUEUED IN TAIL";
02818 else if(myrpt->mustid)
02819 ider_state = "QUEUED FOR CLEANUP";
02820 else
02821 ider_state = "CLEAN";
02822
02823 switch(myrpt->callmode){
02824 case 1:
02825 patch_state = "DIALING";
02826 break;
02827 case 2:
02828 patch_state = "CONNECTING";
02829 break;
02830 case 3:
02831 patch_state = "UP";
02832 break;
02833
02834 case 4:
02835 patch_state = "CALL FAILED";
02836 break;
02837
02838 default:
02839 patch_state = "DOWN";
02840 }
02841
02842 if(strlen(myrpt->exten)){
02843 called_number = ast_strdup(myrpt->exten);
02844 }
02845
02846 if(strlen(myrpt->lastdtmfcommand)){
02847 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02848 }
02849 rpt_mutex_unlock(&myrpt->lock);
02850
02851 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02852 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02853 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02854 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02855 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02856 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02857 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02858 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02859 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02860 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02861 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02862 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02863 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02864 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02865 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02866 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02867 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02868 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02869 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02870 hours = dailytxtime/3600000;
02871 dailytxtime %= 3600000;
02872 minutes = dailytxtime/60000;
02873 dailytxtime %= 60000;
02874 seconds = dailytxtime/1000;
02875 dailytxtime %= 1000;
02876
02877 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02878 hours, minutes, seconds, dailytxtime);
02879
02880 hours = (int) totaltxtime/3600000;
02881 totaltxtime %= 3600000;
02882 minutes = (int) totaltxtime/60000;
02883 totaltxtime %= 60000;
02884 seconds = (int) totaltxtime/1000;
02885 totaltxtime %= 1000;
02886
02887 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02888 hours, minutes, seconds, (int) totaltxtime);
02889
02890 hours = uptime/3600;
02891 uptime %= 3600;
02892 minutes = uptime/60;
02893 uptime %= 60;
02894
02895 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02896 hours, minutes, uptime);
02897
02898 ast_cli(fd, "Nodes currently connected to us..................: ");
02899 if(!numoflinks){
02900 ast_cli(fd,"<NONE>");
02901 }
02902 else{
02903 for(j = 0 ;j < numoflinks; j++){
02904 ast_cli(fd, "%s", listoflinks[j]);
02905 if(j % 4 == 3){
02906 ast_cli(fd, "\n");
02907 ast_cli(fd, " : ");
02908 }
02909 else{
02910 if((numoflinks - 1) - j > 0)
02911 ast_cli(fd, ", ");
02912 }
02913 }
02914 }
02915 ast_cli(fd,"\n");
02916
02917 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02918 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02919 ast_cli(fd, "Autopatch called number..........................: %s\n",
02920 (called_number && strlen(called_number)) ? called_number : not_applicable);
02921 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02922 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02923 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02924
02925 for(j = 0; j < numoflinks; j++){
02926 ast_free(listoflinks[j]);
02927 }
02928 ast_free(called_number);
02929 ast_free(lastdtmfcommand);
02930 return RESULT_SUCCESS;
02931 }
02932 }
02933 return RESULT_FAILURE;
02934 }
02935
02936
02937
02938
02939
02940 static int rpt_do_lstats(int fd, int argc, const char * const *argv)
02941 {
02942 int i,j;
02943 char *connstate;
02944 struct rpt *myrpt;
02945 struct rpt_link *l;
02946 struct rpt_lstat *s,*t;
02947 struct rpt_lstat s_head;
02948 if(argc != 3)
02949 return RESULT_SHOWUSAGE;
02950
02951 s = NULL;
02952 s_head.next = &s_head;
02953 s_head.prev = &s_head;
02954
02955 for(i = 0; i < nrpts; i++)
02956 {
02957 if (!strcmp(argv[2],rpt_vars[i].name)){
02958
02959 myrpt = &rpt_vars[i];
02960 rpt_mutex_lock(&myrpt->lock);
02961
02962 j = 0;
02963 l = myrpt->links.next;
02964 while(l && (l != &myrpt->links)){
02965 if (l->name[0] == '0'){
02966 l = l->next;
02967 continue;
02968 }
02969 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02970 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02971 rpt_mutex_unlock(&myrpt->lock);
02972 return RESULT_FAILURE;
02973 }
02974 memset(s, 0, sizeof(struct rpt_lstat));
02975 strncpy(s->name, l->name, MAXREMSTR - 1);
02976 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02977 else strcpy(s->peer,"(none)");
02978 s->mode = l->mode;
02979 s->outbound = l->outbound;
02980 s->reconnects = l->reconnects;
02981 s->connecttime = l->connecttime;
02982 s->thisconnected = l->thisconnected;
02983 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02984 insque((struct qelem *) s, (struct qelem *) s_head.next);
02985 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02986 l = l->next;
02987 }
02988 rpt_mutex_unlock(&myrpt->lock);
02989 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02990 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02991
02992 for(s = s_head.next; s != &s_head; s = s->next){
02993 int hours, minutes, seconds;
02994 long long connecttime = s->connecttime;
02995 char conntime[21];
02996 hours = (int) connecttime/3600000;
02997 connecttime %= 3600000;
02998 minutes = (int) connecttime/60000;
02999 connecttime %= 60000;
03000 seconds = (int) connecttime/1000;
03001 connecttime %= 1000;
03002 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
03003 hours, minutes, seconds, (int) connecttime);
03004 conntime[20] = 0;
03005 if(s->thisconnected)
03006 connstate = "ESTABLISHED";
03007 else
03008 connstate = "CONNECTING";
03009 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
03010 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
03011 }
03012
03013 s = s_head.next;
03014 while(s != &s_head){
03015 t = s;
03016 s = s->next;
03017 remque((struct qelem *)t);
03018 ast_free(t);
03019 }
03020 return RESULT_SUCCESS;
03021 }
03022 }
03023 return RESULT_FAILURE;
03024 }
03025
03026
03027
03028
03029
03030 static int rpt_do_nodes(int fd, int argc, const char * const *argv)
03031 {
03032 int i,j;
03033 char ns;
03034 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03035 struct rpt *myrpt;
03036 if(argc != 3)
03037 return RESULT_SHOWUSAGE;
03038
03039 for(i = 0; i < nrpts; i++)
03040 {
03041 if (!strcmp(argv[2],rpt_vars[i].name)){
03042
03043 myrpt = &rpt_vars[i];
03044 rpt_mutex_lock(&myrpt->lock);
03045 __mklinklist(myrpt,NULL,lbuf);
03046 rpt_mutex_unlock(&myrpt->lock);
03047
03048 ns = finddelim(lbuf,strs,MAXLINKLIST);
03049
03050 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03051 ast_cli(fd,"\n");
03052 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03053 for(j = 0 ;; j++){
03054 if(!strs[j]){
03055 if(!j){
03056 ast_cli(fd,"<NONE>");
03057 }
03058 break;
03059 }
03060 ast_cli(fd, "%s", strs[j]);
03061 if(j % 8 == 7){
03062 ast_cli(fd, "\n");
03063 }
03064 else{
03065 if(strs[j + 1])
03066 ast_cli(fd, ", ");
03067 }
03068 }
03069 ast_cli(fd,"\n\n");
03070 return RESULT_SUCCESS;
03071 }
03072 }
03073 return RESULT_FAILURE;
03074 }
03075
03076
03077
03078
03079
03080 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv)
03081 {
03082
03083 int i;
03084 ast_cli(fd, "\nNode\n----\n");
03085 for (i=0; i< nrpts; i++)
03086 {
03087 ast_cli(fd, "%s\n", rpt_vars[i].name);
03088 }
03089 ast_cli(fd,"\n");
03090 return RESULT_SUCCESS;
03091 }
03092
03093
03094
03095
03096
03097
03098 static int rpt_do_reload(int fd, int argc, const char * const *argv)
03099 {
03100 int n;
03101
03102 if (argc > 2) return RESULT_SHOWUSAGE;
03103
03104 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03105
03106 return RESULT_FAILURE;
03107 }
03108
03109
03110
03111
03112
03113 static int rpt_do_restart(int fd, int argc, const char * const *argv)
03114 {
03115 int i;
03116
03117 if (argc > 2) return RESULT_SHOWUSAGE;
03118 for(i = 0; i < nrpts; i++)
03119 {
03120 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03121 }
03122 return RESULT_FAILURE;
03123 }
03124
03125
03126
03127
03128
03129
03130 static int rpt_do_fun(int fd, int argc, const char * const *argv)
03131 {
03132 int i,busy=0;
03133
03134 if (argc != 4) return RESULT_SHOWUSAGE;
03135
03136 for(i = 0; i < nrpts; i++){
03137 if(!strcmp(argv[2], rpt_vars[i].name)){
03138 struct rpt *myrpt = &rpt_vars[i];
03139 rpt_mutex_lock(&myrpt->lock);
03140 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03141 rpt_mutex_unlock(&myrpt->lock);
03142 busy=1;
03143 }
03144 if(!busy){
03145 myrpt->macrotimer = MACROTIME;
03146 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03147 }
03148 rpt_mutex_unlock(&myrpt->lock);
03149 }
03150 }
03151 if(busy){
03152 ast_cli(fd, "Function decoder busy");
03153 }
03154 return RESULT_FAILURE;
03155 }
03156
03157
03158
03159
03160
03161
03162
03163
03164 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03165 {
03166 int busy=0;
03167
03168 rpt_mutex_lock(&myrpt->lock);
03169 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03170 rpt_mutex_unlock(&myrpt->lock);
03171 busy=1;
03172 }
03173 if(!busy){
03174 int x;
03175 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03176 myrpt->macrotimer = MACROTIME;
03177 for(x = 0; *(sptr + x); x++)
03178 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03179 *(sptr + x) = 0;
03180 }
03181 rpt_mutex_unlock(&myrpt->lock);
03182
03183 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03184
03185 return busy;
03186 }
03187
03188
03189
03190 static int rpt_do_fun1(int fd, int argc, const char * const *argv)
03191 {
03192 int i;
03193
03194 if (argc != 4) return RESULT_SHOWUSAGE;
03195
03196 for(i = 0; i < nrpts; i++){
03197 if(!strcmp(argv[2], rpt_vars[i].name)){
03198 struct rpt *myrpt = &rpt_vars[i];
03199 rpt_push_alt_macro(myrpt, (char *) argv[3]);
03200 }
03201 }
03202 return RESULT_FAILURE;
03203 }
03204
03205
03206
03207
03208 static int rpt_do_cmd(int fd, int argc, const char * const *argv)
03209 {
03210 int i, l;
03211 int busy=0;
03212 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03213
03214 int thisRpt = -1;
03215 int thisAction = -1;
03216 struct rpt *myrpt = NULL;
03217 if (argc != 6) return RESULT_SHOWUSAGE;
03218
03219 for(i = 0; i < nrpts; i++)
03220 {
03221 if(!strcmp(argv[2], rpt_vars[i].name))
03222 {
03223 thisRpt = i;
03224 myrpt = &rpt_vars[i];
03225 break;
03226 }
03227 }
03228
03229 if (thisRpt < 0)
03230 {
03231 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03232 return RESULT_FAILURE;
03233 }
03234
03235
03236 l = strlen(argv[3]);
03237 for(i = 0 ; i < maxActions; i++)
03238 {
03239 if(!strncasecmp(argv[3], function_table[i].action, l))
03240 {
03241 thisAction = i;
03242 break;
03243 }
03244 }
03245
03246 if (thisAction < 0)
03247 {
03248 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03249 return RESULT_FAILURE;
03250 }
03251
03252
03253
03254 rpt_mutex_lock(&myrpt->lock);
03255
03256 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03257 {
03258 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03259 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03260 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03261 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03262 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03263 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03264 }
03265 else
03266 {
03267 busy = 1;
03268 }
03269 rpt_mutex_unlock(&myrpt->lock);
03270
03271 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03272 }
03273
03274 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03275 {
03276 int res;
03277
03278 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03279 return res;
03280
03281 while(chan->generatordata) {
03282 if (ast_safe_sleep(chan,1)) return -1;
03283 }
03284
03285 return 0;
03286 }
03287
03288 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03289 {
03290 return play_tone_pair(chan, freq, 0, duration, amplitude);
03291 }
03292
03293 static int play_silence(struct ast_channel *chan, int duration)
03294 {
03295 return play_tone_pair(chan, 0, 0, duration, 0);
03296 }
03297
03298 #ifdef NEW_ASTERISK
03299
03300 static char *res2cli(int r)
03301
03302 {
03303 switch (r)
03304 {
03305 case RESULT_SUCCESS:
03306 return(CLI_SUCCESS);
03307 case RESULT_SHOWUSAGE:
03308 return(CLI_SHOWUSAGE);
03309 default:
03310 return(CLI_FAILURE);
03311 }
03312 }
03313
03314 static char *handle_cli_debug(struct ast_cli_entry *e,
03315 int cmd, struct ast_cli_args *a)
03316 {
03317 switch (cmd) {
03318 case CLI_INIT:
03319 e->command = "rpt debug level";
03320 e->usage = debug_usage;
03321 return NULL;
03322 case CLI_GENERATE:
03323 return NULL;
03324 }
03325 return res2cli(rpt_do_debug(a->fd, a->argc, a->argv));
03326 }
03327
03328 static char *handle_cli_dump(struct ast_cli_entry *e,
03329 int cmd, struct ast_cli_args *a)
03330 {
03331 switch (cmd) {
03332 case CLI_INIT:
03333 e->command = "rpt dump level";
03334 e->usage = dump_usage;
03335 return NULL;
03336 case CLI_GENERATE:
03337 return NULL;
03338 }
03339 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03340 }
03341
03342
03343 static char *handle_cli_stats(struct ast_cli_entry *e,
03344 int cmd, struct ast_cli_args *a)
03345 {
03346 switch (cmd) {
03347 case CLI_INIT:
03348 e->command = "rpt stats";
03349 e->usage = dump_stats;
03350 return NULL;
03351 case CLI_GENERATE:
03352 return NULL;
03353 }
03354 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03355 }
03356
03357 static char *handle_cli_nodes(struct ast_cli_entry *e,
03358 int cmd, struct ast_cli_args *a)
03359 {
03360 switch (cmd) {
03361 case CLI_INIT:
03362 e->command = "rpt nodes";
03363 e->usage = dump_nodes;
03364 return NULL;
03365 case CLI_GENERATE:
03366 return NULL;
03367 }
03368 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03369 }
03370
03371 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03372 int cmd, struct ast_cli_args *a)
03373 {
03374 switch (cmd) {
03375 case CLI_INIT:
03376 e->command = "rpt localnodes";
03377 e->usage = usage_local_nodes;
03378 return NULL;
03379 case CLI_GENERATE:
03380 return NULL;
03381 }
03382 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03383 }
03384
03385 static char *handle_cli_lstats(struct ast_cli_entry *e,
03386 int cmd, struct ast_cli_args *a)
03387 {
03388 switch (cmd) {
03389 case CLI_INIT:
03390 e->command = "rpt lstats";
03391 e->usage = dump_lstats;
03392 return NULL;
03393 case CLI_GENERATE:
03394 return NULL;
03395 }
03396 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03397 }
03398
03399 static char *handle_cli_reload(struct ast_cli_entry *e,
03400 int cmd, struct ast_cli_args *a)
03401 {
03402 switch (cmd) {
03403 case CLI_INIT:
03404 e->command = "rpt reload";
03405 e->usage = reload_usage;
03406 return NULL;
03407 case CLI_GENERATE:
03408 return NULL;
03409 }
03410 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03411 }
03412
03413 static char *handle_cli_restart(struct ast_cli_entry *e,
03414 int cmd, struct ast_cli_args *a)
03415 {
03416 switch (cmd) {
03417 case CLI_INIT:
03418 e->command = "rpt restart";
03419 e->usage = restart_usage;
03420 return NULL;
03421 case CLI_GENERATE:
03422 return NULL;
03423 }
03424 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03425 }
03426
03427 static char *handle_cli_fun(struct ast_cli_entry *e,
03428 int cmd, struct ast_cli_args *a)
03429 {
03430 switch (cmd) {
03431 case CLI_INIT:
03432 e->command = "rpt fun";
03433 e->usage = fun_usage;
03434 return NULL;
03435 case CLI_GENERATE:
03436 return NULL;
03437 }
03438 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03439 }
03440
03441 static char *handle_cli_fun1(struct ast_cli_entry *e,
03442 int cmd, struct ast_cli_args *a)
03443 {
03444 switch (cmd) {
03445 case CLI_INIT:
03446 e->command = "rpt fun1";
03447 e->usage = fun_usage;
03448 return NULL;
03449 case CLI_GENERATE:
03450 return NULL;
03451 }
03452 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03453 }
03454
03455 static char *handle_cli_cmd(struct ast_cli_entry *e,
03456 int cmd, struct ast_cli_args *a)
03457 {
03458 switch (cmd) {
03459 case CLI_INIT:
03460 e->command = "rpt cmd";
03461 e->usage = cmd_usage;
03462 return NULL;
03463 case CLI_GENERATE:
03464 return NULL;
03465 }
03466 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03467 }
03468
03469 static struct ast_cli_entry rpt_cli[] = {
03470 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03471 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03472 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03473 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03474 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03475 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03476 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03477 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03478 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03479 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03480 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03481 };
03482
03483 #endif
03484
03485 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03486 {
03487
03488 static struct morse_bits mbits[] = {
03489 {0, 0},
03490 {0, 0},
03491 {6, 18},
03492 {0, 0},
03493 {7, 72},
03494 {0, 0},
03495 {0, 0},
03496 {6, 30},
03497 {5, 13},
03498 {6, 29},
03499 {0, 0},
03500 {5, 10},
03501 {6, 51},
03502 {6, 33},
03503 {6, 42},
03504 {5, 9},
03505 {5, 31},
03506 {5, 30},
03507 {5, 28},
03508 {5, 24},
03509 {5, 16},
03510 {5, 0},
03511 {5, 1},
03512 {5, 3},
03513 {5, 7},
03514 {5, 15},
03515 {6, 7},
03516 {6, 21},
03517 {0, 0},
03518 {5, 33},
03519 {0, 0},
03520 {6, 12},
03521 {0, 0},
03522 {2, 2},
03523 {4, 1},
03524 {4, 5},
03525 {3, 1},
03526 {1, 0},
03527 {4, 4},
03528 {3, 3},
03529 {4, 0},
03530 {2, 0},
03531 {4, 14},
03532 {3, 5},
03533 {4, 2},
03534 {2, 3},
03535 {2, 1},
03536 {3, 7},
03537 {4, 6},
03538 {4, 11},
03539 {3, 2},
03540 {3, 0},
03541 {1, 1},
03542 {3, 4},
03543 {4, 8},
03544 {3, 6},
03545 {4, 9},
03546 {4, 13},
03547 {4, 3}
03548 };
03549
03550
03551 int dottime;
03552 int dashtime;
03553 int intralettertime;
03554 int interlettertime;
03555 int interwordtime;
03556 int len, ddcomb;
03557 int res;
03558 int c;
03559 int i;
03560 int flags;
03561
03562 res = 0;
03563
03564
03565
03566 dottime = 900/speed;
03567
03568
03569
03570 dashtime = 3 * dottime;
03571 intralettertime = dottime;
03572 interlettertime = dottime * 4 ;
03573 interwordtime = dottime * 7;
03574
03575 for(;(*string) && (!res); string++){
03576
03577 c = *string;
03578
03579
03580
03581 if((c >= 'a') && (c <= 'z'))
03582 c -= 0x20;
03583
03584
03585
03586 if(c > 'Z')
03587 continue;
03588
03589
03590
03591 if(c == ' '){
03592 if(!res)
03593 res = play_silence(chan, interwordtime);
03594 continue;
03595 }
03596
03597
03598
03599 c -= 0x20;
03600
03601
03602
03603 len = mbits[c].len;
03604 ddcomb = mbits[c].ddcomb;
03605
03606
03607
03608 for(; len ; len--){
03609 if(!res)
03610 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03611 if(!res)
03612 res = play_silence(chan, intralettertime);
03613 ddcomb >>= 1;
03614 }
03615
03616
03617
03618 if(!res)
03619 res = play_silence(chan, interlettertime - intralettertime);
03620 }
03621
03622
03623
03624 if (!res)
03625 res = ast_waitstream(chan, "");
03626 ast_stopstream(chan);
03627
03628
03629
03630
03631
03632 for(i = 0; i < 20 ; i++){
03633 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03634 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03635 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03636 break;
03637 if( ast_safe_sleep(chan, 50)){
03638 res = -1;
03639 break;
03640 }
03641 }
03642
03643
03644 return res;
03645 }
03646
03647 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03648 {
03649 char *p,*stringp;
03650 char *tonesubset;
03651 int f1,f2;
03652 int duration;
03653 int amplitude;
03654 int res;
03655 int i;
03656 int flags;
03657
03658 res = 0;
03659
03660 if(!tonestring)
03661 return res;
03662
03663 p = stringp = ast_strdup(tonestring);
03664
03665 for(;tonestring;){
03666 tonesubset = strsep(&stringp,")");
03667 if(!tonesubset)
03668 break;
03669 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03670 break;
03671 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03672 if(res)
03673 break;
03674 }
03675 ast_free(p);
03676 if(!res)
03677 res = play_tone_pair(chan, 0, 0, 100, 0);
03678
03679 if (!res)
03680 res = ast_waitstream(chan, "");
03681
03682 ast_stopstream(chan);
03683
03684
03685
03686
03687
03688 for(i = 0; i < 20 ; i++){
03689 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03690 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03691 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03692 break;
03693 if( ast_safe_sleep(chan, 50)){
03694 res = -1;
03695 break;
03696 }
03697 }
03698
03699 return res;
03700
03701 }
03702
03703 static int sayfile(struct ast_channel *mychannel,char *fname)
03704 {
03705 int res;
03706
03707 res = ast_streamfile(mychannel, fname, ast_channel_language(mychannel));
03708 if (!res)
03709 res = ast_waitstream(mychannel, "");
03710 else
03711 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
03712 ast_stopstream(mychannel);
03713 return res;
03714 }
03715
03716 static int saycharstr(struct ast_channel *mychannel,char *str)
03717 {
03718 int res;
03719
03720 res = ast_say_character_str(mychannel,str,NULL,ast_channel_language(mychannel));
03721 if (!res)
03722 res = ast_waitstream(mychannel, "");
03723 else
03724 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
03725 ast_stopstream(mychannel);
03726 return res;
03727 }
03728
03729 static int saynum(struct ast_channel *mychannel, int num)
03730 {
03731 int res;
03732 res = ast_say_number(mychannel, num, NULL, ast_channel_language(mychannel), NULL);
03733 if(!res)
03734 res = ast_waitstream(mychannel, "");
03735 else
03736 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
03737 ast_stopstream(mychannel);
03738 return res;
03739 }
03740
03741
03742
03743
03744 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03745 {
03746 int res;
03747 char *val,fname[300];
03748
03749 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03750 if (!val) val = NODENAMES;
03751 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03752 if (ast_fileexists(fname,NULL,ast_channel_language(mychannel)) > 0)
03753 return(sayfile(mychannel,fname));
03754 res = sayfile(mychannel,"rpt/node");
03755 if (!res)
03756 res = ast_say_character_str(mychannel,name,NULL,ast_channel_language(mychannel));
03757 return res;
03758 }
03759
03760 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03761 {
03762 int res;
03763 char c;
03764
03765 static int morsespeed;
03766 static int morsefreq;
03767 static int morseampl;
03768 static int morseidfreq = 0;
03769 static int morseidampl;
03770 static char mcat[] = MORSE;
03771
03772 res = 0;
03773
03774 if(!morseidfreq){
03775 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03776 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03777 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03778 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03779 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03780 }
03781
03782
03783
03784 if(entry[0] == '|'){
03785 c = entry[1];
03786 if((c >= 'a')&&(c <= 'z'))
03787 c -= 0x20;
03788
03789 switch(c){
03790 case 'I':
03791 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03792 break;
03793
03794 case 'M':
03795 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03796 break;
03797
03798 case 'T':
03799 res = send_tone_telemetry(chan, entry + 2);
03800 break;
03801 default:
03802 res = -1;
03803 }
03804 }
03805 else
03806 res = sayfile(chan, entry);
03807 return res;
03808 }
03809
03810
03811
03812
03813
03814
03815
03816 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03817 {
03818
03819 int res;
03820 int i;
03821 char *entry;
03822 char *telemetry;
03823 char *telemetry_save;
03824
03825 res = 0;
03826 telemetry_save = NULL;
03827 entry = NULL;
03828
03829
03830 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03831 if(telemetry ){
03832 telemetry_save = ast_strdup(telemetry);
03833 if(!telemetry_save){
03834 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03835 return res;
03836 }
03837 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03838 }
03839
03840
03841
03842 if(!entry){
03843
03844 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03845 if(!strcasecmp(tele_defs[i].name, name))
03846 entry = tele_defs[i].value;
03847 }
03848 }
03849 if(entry){
03850 if(strlen(entry))
03851 if (chan) telem_any(myrpt,chan, entry);
03852 }
03853 else{
03854 res = -1;
03855 }
03856 ast_free(telemetry_save);
03857 return res;
03858 }
03859
03860
03861
03862
03863
03864 static int get_wait_interval(struct rpt *myrpt, int type)
03865 {
03866 int interval;
03867 char *wait_times;
03868 char *wait_times_save;
03869
03870 wait_times_save = NULL;
03871 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03872
03873 if(wait_times){
03874 wait_times_save = ast_strdup(wait_times);
03875 if(!wait_times_save)
03876 return 0;
03877
03878 }
03879
03880 switch(type){
03881 case DLY_TELEM:
03882 if(wait_times)
03883 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03884 else
03885 interval = 1000;
03886 break;
03887
03888 case DLY_ID:
03889 if(wait_times)
03890 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03891 else
03892 interval = 500;
03893 break;
03894
03895 case DLY_UNKEY:
03896 if(wait_times)
03897 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03898 else
03899 interval = 1000;
03900 break;
03901
03902 case DLY_LINKUNKEY:
03903 if(wait_times)
03904 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03905 else
03906 interval = 1000;
03907 break;
03908
03909 case DLY_CALLTERM:
03910 if(wait_times)
03911 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03912 else
03913 interval = 1500;
03914 break;
03915
03916 case DLY_COMP:
03917 if(wait_times)
03918 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03919 else
03920 interval = 200;
03921 break;
03922
03923 case DLY_PARROT:
03924 if(wait_times)
03925 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03926 else
03927 interval = 200;
03928 break;
03929
03930 default:
03931 interval = 0;
03932 break;
03933 }
03934 ast_free(wait_times_save);
03935 return interval;
03936 }
03937
03938
03939
03940
03941
03942 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03943 {
03944 int interval;
03945 interval = get_wait_interval(myrpt, type);
03946 if(debug)
03947 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03948 if(interval)
03949 ast_safe_sleep(chan,interval);
03950 if(debug)
03951 ast_log(LOG_NOTICE,"Delay complete\n");
03952 return;
03953 }
03954
03955 static int split_freq(char *mhz, char *decimals, char *freq);
03956
03957 static void *rpt_tele_thread(void *this)
03958 {
03959 struct dahdi_confinfo ci;
03960 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03961 struct rpt_tele *mytele = (struct rpt_tele *)this;
03962 struct rpt_tele *tlist;
03963 struct rpt *myrpt;
03964 struct rpt_link *l,*l1,linkbase;
03965 struct ast_channel *mychannel;
03966 int vmajor, vminor, m;
03967 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03968 time_t t;
03969 #ifdef NEW_ASTERISK
03970 struct ast_tm localtm;
03971 #else
03972 struct tm localtm;
03973 #endif
03974 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03975 int i,ns,rbimode;
03976 char mhz[MAXREMSTR];
03977 char decimals[MAXREMSTR];
03978 char mystr[200];
03979 struct dahdi_params par;
03980 struct ast_format_cap *cap = NULL;
03981
03982
03983 myrpt = mytele->rpt;
03984
03985
03986 rpt_mutex_lock(&myrpt->lock);
03987 nodename = ast_strdup(myrpt->name);
03988 if(!nodename)
03989 {
03990 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03991 rpt_mutex_lock(&myrpt->lock);
03992 remque((struct qelem *)mytele);
03993 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03994 rpt_mutex_unlock(&myrpt->lock);
03995 ast_free(mytele);
03996 pthread_exit(NULL);
03997 }
03998
03999 if (myrpt->p.ident){
04000 ident = ast_strdup(myrpt->p.ident);
04001 if(!ident)
04002 {
04003 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
04004 rpt_mutex_lock(&myrpt->lock);
04005 remque((struct qelem *)mytele);
04006 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
04007 __LINE__, mytele->mode);
04008 rpt_mutex_unlock(&myrpt->lock);
04009 ast_free(nodename);
04010 ast_free(mytele);
04011 pthread_exit(NULL);
04012 }
04013 }
04014 else
04015 {
04016 ident = "";
04017 }
04018 rpt_mutex_unlock(&myrpt->lock);
04019
04020
04021
04022
04023 mychannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
04024 cap = ast_format_cap_destroy(cap);
04025 if (!mychannel)
04026 {
04027 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04028 rpt_mutex_lock(&myrpt->lock);
04029 remque((struct qelem *)mytele);
04030 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04031 rpt_mutex_unlock(&myrpt->lock);
04032 ast_free(nodename);
04033 ast_free(ident);
04034 ast_free(mytele);
04035 pthread_exit(NULL);
04036 }
04037 #ifdef AST_CDR_FLAG_POST_DISABLED
04038 if (mychannel->cdr)
04039 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04040 #endif
04041 rpt_mutex_lock(&myrpt->lock);
04042 mytele->chan = mychannel;
04043 rpt_mutex_unlock(&myrpt->lock);
04044
04045 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04046 (mytele->mode != LINKUNKEY))
04047 {
04048 rpt_mutex_lock(&myrpt->lock);
04049 if (!myrpt->active_telem)
04050 {
04051 myrpt->active_telem = mytele;
04052 rpt_mutex_unlock(&myrpt->lock);
04053 break;
04054 }
04055 rpt_mutex_unlock(&myrpt->lock);
04056 usleep(100000);
04057 }
04058
04059
04060 ci.chan = 0;
04061
04062
04063
04064 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04065 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04066 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04067 myrpt->txconf : myrpt->conf);
04068 ci.confmode = DAHDI_CONF_CONFANN;
04069
04070 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04071 {
04072 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04073 rpt_mutex_lock(&myrpt->lock);
04074 myrpt->active_telem = NULL;
04075 remque((struct qelem *)mytele);
04076 rpt_mutex_unlock(&myrpt->lock);
04077 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04078 ast_free(nodename);
04079 ast_free(ident);
04080 ast_free(mytele);
04081 ast_hangup(mychannel);
04082 pthread_exit(NULL);
04083 }
04084 ast_stopstream(mychannel);
04085 switch(mytele->mode)
04086 {
04087 case ID:
04088 case ID1:
04089
04090 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04091 res = telem_any(myrpt,mychannel, ident);
04092 imdone=1;
04093 break;
04094
04095 case TAILMSG:
04096 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], ast_channel_language(mychannel));
04097 break;
04098
04099 case IDTALKOVER:
04100 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04101 if(p)
04102 res = telem_any(myrpt,mychannel, p);
04103 imdone=1;
04104 break;
04105
04106 case PROC:
04107
04108 wait_interval(myrpt, DLY_TELEM, mychannel);
04109 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04110 if(res < 0){
04111 res = ast_streamfile(mychannel, "rpt/callproceeding", ast_channel_language(mychannel));
04112 }
04113 break;
04114 case TERM:
04115
04116 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04117 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04118 if(res < 0){
04119 res = ast_streamfile(mychannel, "rpt/callterminated", ast_channel_language(mychannel));
04120 }
04121 break;
04122 case COMPLETE:
04123
04124 wait_interval(myrpt, DLY_TELEM, mychannel);
04125 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04126 break;
04127 case MACRO_NOTFOUND:
04128
04129 wait_interval(myrpt, DLY_TELEM, mychannel);
04130 res = ast_streamfile(mychannel, "rpt/macro_notfound", ast_channel_language(mychannel));
04131 break;
04132 case MACRO_BUSY:
04133
04134 wait_interval(myrpt, DLY_TELEM, mychannel);
04135 res = ast_streamfile(mychannel, "rpt/macro_busy", ast_channel_language(mychannel));
04136 break;
04137 case UNKEY:
04138 if(myrpt->patchnoct && myrpt->callmode){
04139 imdone = 1;
04140 break;
04141 }
04142
04143
04144
04145
04146
04147 x = get_wait_interval(myrpt, DLY_UNKEY);
04148 rpt_mutex_lock(&myrpt->lock);
04149 myrpt->unkeytocttimer = x;
04150 rpt_mutex_unlock(&myrpt->lock);
04151
04152
04153
04154
04155
04156 tlist = myrpt->tele.next;
04157 unkeys_queued = 0;
04158 if (tlist != &myrpt->tele)
04159 {
04160 rpt_mutex_lock(&myrpt->lock);
04161 while(tlist != &myrpt->tele){
04162 if (tlist->mode == UNKEY) unkeys_queued++;
04163 tlist = tlist->next;
04164 }
04165 rpt_mutex_unlock(&myrpt->lock);
04166 }
04167 if( unkeys_queued > 1){
04168 imdone = 1;
04169 break;
04170 }
04171
04172
04173
04174 while(myrpt->unkeytocttimer)
04175 {
04176 int ctint;
04177 if(myrpt->unkeytocttimer > 100)
04178 ctint = 100;
04179 else
04180 ctint = myrpt->unkeytocttimer;
04181 ast_safe_sleep(mychannel, ctint);
04182 rpt_mutex_lock(&myrpt->lock);
04183 if(myrpt->unkeytocttimer < ctint)
04184 myrpt->unkeytocttimer = 0;
04185 else
04186 myrpt->unkeytocttimer -= ctint;
04187 rpt_mutex_unlock(&myrpt->lock);
04188 }
04189
04190
04191
04192
04193
04194 if(myrpt->keyed){
04195 imdone = 1;
04196 break;
04197 }
04198
04199 rpt_mutex_lock(&myrpt->lock);
04200 myrpt->dailykerchunks++;
04201 myrpt->totalkerchunks++;
04202 rpt_mutex_unlock(&myrpt->lock);
04203
04204 haslink = 0;
04205 hastx = 0;
04206 hasremote = 0;
04207 l = myrpt->links.next;
04208 if (l != &myrpt->links)
04209 {
04210 rpt_mutex_lock(&myrpt->lock);
04211 while(l != &myrpt->links)
04212 {
04213 if (l->name[0] == '0')
04214 {
04215 l = l->next;
04216 continue;
04217 }
04218 haslink = 1;
04219 if (l->mode) {
04220 hastx++;
04221 if (l->isremote) hasremote++;
04222 }
04223 l = l->next;
04224 }
04225 rpt_mutex_unlock(&myrpt->lock);
04226 }
04227 if (haslink)
04228 {
04229
04230 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04231 if(res)
04232 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", ast_channel_name(mychannel));
04233
04234
04235
04236 if (myrpt->cmdnode[0])
04237 {
04238 ast_safe_sleep(mychannel,200);
04239 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04240 if(res)
04241 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", ast_channel_name(mychannel));
04242 ast_stopstream(mychannel);
04243 }
04244 }
04245 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04246 ct_copy = ast_strdup(ct);
04247 if(ct_copy)
04248 {
04249 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04250 ast_free(ct_copy);
04251 }
04252 else
04253 res = -1;
04254 if(res)
04255 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", ast_channel_name(mychannel));
04256 }
04257 if (hasremote && (!myrpt->cmdnode[0]))
04258 {
04259
04260 ci.chan = 0;
04261 ci.confno = myrpt->conf;
04262 ci.confmode = DAHDI_CONF_CONFANN;
04263
04264 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04265 {
04266 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04267 rpt_mutex_lock(&myrpt->lock);
04268 myrpt->active_telem = NULL;
04269 remque((struct qelem *)mytele);
04270 rpt_mutex_unlock(&myrpt->lock);
04271 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04272 ast_free(nodename);
04273 ast_free(ident);
04274 ast_free(mytele);
04275 ast_hangup(mychannel);
04276 pthread_exit(NULL);
04277 }
04278 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04279 ast_safe_sleep(mychannel,200);
04280 ct_copy = ast_strdup(ct);
04281 if(ct_copy)
04282 {
04283 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04284 ast_free(ct_copy);
04285 }
04286 else
04287 res = -1;
04288
04289 if(res)
04290 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", ast_channel_name(mychannel));
04291 }
04292 }
04293 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04294 if (myrpt->lastunit)
04295 {
04296 char mystr[10];
04297
04298 ast_safe_sleep(mychannel,200);
04299
04300 ci.chan = 0;
04301 ci.confno = myrpt->txconf;
04302 ci.confmode = DAHDI_CONF_CONFANN;
04303
04304 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04305 {
04306 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04307 rpt_mutex_lock(&myrpt->lock);
04308 myrpt->active_telem = NULL;
04309 remque((struct qelem *)mytele);
04310 rpt_mutex_unlock(&myrpt->lock);
04311 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04312 ast_free(nodename);
04313 ast_free(ident);
04314 ast_free(mytele);
04315 ast_hangup(mychannel);
04316 pthread_exit(NULL);
04317 }
04318 sprintf(mystr,"%04x",myrpt->lastunit);
04319 myrpt->lastunit = 0;
04320 ast_say_character_str(mychannel,mystr,NULL,ast_channel_language(mychannel));
04321 break;
04322 }
04323 #endif
04324 imdone = 1;
04325 break;
04326 case LINKUNKEY:
04327 if(myrpt->patchnoct && myrpt->callmode){
04328 imdone = 1;
04329 break;
04330 }
04331
04332
04333
04334
04335
04336 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04337 mytele->mylink.linkunkeytocttimer = x;
04338
04339
04340
04341
04342
04343 tlist = myrpt->tele.next;
04344 unkeys_queued = 0;
04345 if (tlist != &myrpt->tele)
04346 {
04347 rpt_mutex_lock(&myrpt->lock);
04348 while(tlist != &myrpt->tele){
04349 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04350 tlist = tlist->next;
04351 }
04352 rpt_mutex_unlock(&myrpt->lock);
04353 }
04354 if( unkeys_queued > 1){
04355 imdone = 1;
04356 break;
04357 }
04358
04359
04360
04361 while(mytele->mylink.linkunkeytocttimer)
04362 {
04363 int ctint;
04364 if(mytele->mylink.linkunkeytocttimer > 100)
04365 ctint = 100;
04366 else
04367 ctint = mytele->mylink.linkunkeytocttimer;
04368 ast_safe_sleep(mychannel, ctint);
04369 rpt_mutex_lock(&myrpt->lock);
04370 if(mytele->mylink.linkunkeytocttimer < ctint)
04371 mytele->mylink.linkunkeytocttimer = 0;
04372 else
04373 mytele->mylink.linkunkeytocttimer -= ctint;
04374 rpt_mutex_unlock(&myrpt->lock);
04375 }
04376
04377 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04378 ct_copy = ast_strdup(ct);
04379 if(ct_copy){
04380 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04381 ast_free(ct_copy);
04382 }
04383 else
04384 res = -1;
04385 if(res)
04386 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", ast_channel_name(mychannel));
04387 }
04388 imdone = 1;
04389 break;
04390 case REMDISC:
04391
04392 wait_interval(myrpt, DLY_TELEM, mychannel);
04393 l = myrpt->links.next;
04394 haslink = 0;
04395
04396 if (l != &myrpt->links)
04397 {
04398 rpt_mutex_lock(&myrpt->lock);
04399 while(l != &myrpt->links)
04400 {
04401 if (l->name[0] == '0')
04402 {
04403 l = l->next;
04404 continue;
04405 }
04406 if (!strcmp(l->name,mytele->mylink.name))
04407 {
04408 haslink = 1;
04409 break;
04410 }
04411 l = l->next;
04412 }
04413 rpt_mutex_unlock(&myrpt->lock);
04414 }
04415 if (haslink)
04416 {
04417 imdone = 1;
04418 break;
04419 }
04420 res = saynode(myrpt,mychannel,mytele->mylink.name);
04421 if (!res)
04422 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04423 "rpt/remote_disc" : "rpt/remote_busy"), ast_channel_language(mychannel));
04424 break;
04425 case REMALREADY:
04426
04427 wait_interval(myrpt, DLY_TELEM, mychannel);
04428 res = ast_streamfile(mychannel, "rpt/remote_already", ast_channel_language(mychannel));
04429 break;
04430 case REMNOTFOUND:
04431
04432 wait_interval(myrpt, DLY_TELEM, mychannel);
04433 res = ast_streamfile(mychannel, "rpt/remote_notfound", ast_channel_language(mychannel));
04434 break;
04435 case REMGO:
04436
04437 wait_interval(myrpt, DLY_TELEM, mychannel);
04438 res = ast_streamfile(mychannel, "rpt/remote_go", ast_channel_language(mychannel));
04439 break;
04440 case CONNECTED:
04441
04442 wait_interval(myrpt, DLY_TELEM, mychannel);
04443 res = saynode(myrpt,mychannel,mytele->mylink.name);
04444 if (!res)
04445 res = ast_streamfile(mychannel, "rpt/connected", ast_channel_language(mychannel));
04446 if (!res)
04447 res = ast_waitstream(mychannel, "");
04448 else
04449 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04450 ast_stopstream(mychannel);
04451 res = ast_streamfile(mychannel, "digits/2", ast_channel_language(mychannel));
04452 if (!res)
04453 res = ast_waitstream(mychannel, "");
04454 else
04455 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04456 ast_stopstream(mychannel);
04457 res = saynode(myrpt,mychannel,myrpt->name);
04458 imdone = 1;
04459 break;
04460 case CONNFAIL:
04461 res = saynode(myrpt,mychannel,mytele->mylink.name);
04462 if (!res)
04463 res = ast_streamfile(mychannel, "rpt/connection_failed", ast_channel_language(mychannel));
04464 break;
04465 case MEMNOTFOUND:
04466
04467 wait_interval(myrpt, DLY_TELEM, mychannel);
04468 res = ast_streamfile(mychannel, "rpt/memory_notfound", ast_channel_language(mychannel));
04469 break;
04470 case PLAYBACK:
04471
04472 wait_interval(myrpt, DLY_TELEM, mychannel);
04473 res = ast_streamfile(mychannel, mytele->param, ast_channel_language(mychannel));
04474 break;
04475 case TOPKEY:
04476
04477 wait_interval(myrpt, DLY_TELEM, mychannel);
04478 for(i = 0; i < TOPKEYN; i++)
04479 {
04480 if (!myrpt->topkey[i].node[0]) continue;
04481 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04482 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04483 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04484 "rpt/keyedfor" : "rpt/unkeyedfor");
04485 if (!res) res = saynum(mychannel,
04486 myrpt->topkey[i].timesince);
04487 if (!res) res = sayfile(mychannel,"rpt/seconds");
04488 if (!myrpt->topkeylong) break;
04489 }
04490 imdone = 1;
04491 break;
04492 case SETREMOTE:
04493 ast_mutex_lock(&myrpt->remlock);
04494 res = 0;
04495 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04496 {
04497 res = set_ft897(myrpt);
04498 }
04499 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04500 {
04501 res = set_tm271(myrpt);
04502 }
04503 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04504 {
04505 res = set_ic706(myrpt);
04506 }
04507 #ifdef HAVE_IOPERM
04508 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04509 {
04510 if (ioperm(myrpt->p.iobase,1,1) == -1)
04511 {
04512 rpt_mutex_unlock(&myrpt->lock);
04513 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04514 res = -1;
04515 }
04516 else res = setrbi(myrpt);
04517 }
04518 #endif
04519 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04520 {
04521 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04522 res = setkenwood(myrpt);
04523 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04524 if (ast_safe_sleep(mychannel,200) == -1)
04525 {
04526 ast_mutex_unlock(&myrpt->remlock);
04527 res = -1;
04528 break;
04529 }
04530 if (myrpt->iofd < 0)
04531 {
04532 i = DAHDI_FLUSH_EVENT;
04533 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04534 {
04535 ast_mutex_unlock(&myrpt->remlock);
04536 ast_log(LOG_ERROR,"Cant flush events");
04537 res = -1;
04538 break;
04539 }
04540 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04541 {
04542 ast_mutex_unlock(&myrpt->remlock);
04543 ast_log(LOG_ERROR,"Cant get params");
04544 res = -1;
04545 break;
04546 }
04547 myrpt->remoterx =
04548 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04549 }
04550 }
04551
04552 ast_mutex_unlock(&myrpt->remlock);
04553 if (!res)
04554 {
04555 imdone = 1;
04556 break;
04557 }
04558
04559 case INVFREQ:
04560
04561 wait_interval(myrpt, DLY_TELEM, mychannel);
04562 res = ast_streamfile(mychannel, "rpt/invalid-freq", ast_channel_language(mychannel));
04563 break;
04564 case REMMODE:
04565 cp = 0;
04566 wait_interval(myrpt, DLY_TELEM, mychannel);
04567 switch(myrpt->remmode)
04568 {
04569 case REM_MODE_FM:
04570 saycharstr(mychannel,"FM");
04571 break;
04572 case REM_MODE_USB:
04573 saycharstr(mychannel,"USB");
04574 break;
04575 case REM_MODE_LSB:
04576 saycharstr(mychannel,"LSB");
04577 break;
04578 case REM_MODE_AM:
04579 saycharstr(mychannel,"AM");
04580 break;
04581 }
04582 wait_interval(myrpt, DLY_COMP, mychannel);
04583 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04584 break;
04585 case LOGINREQ:
04586 wait_interval(myrpt, DLY_TELEM, mychannel);
04587 sayfile(mychannel,"rpt/login");
04588 saycharstr(mychannel,myrpt->name);
04589 break;
04590 case REMLOGIN:
04591 wait_interval(myrpt, DLY_TELEM, mychannel);
04592 saycharstr(mychannel,myrpt->loginuser);
04593 saynode(myrpt,mychannel,myrpt->name);
04594 wait_interval(myrpt, DLY_COMP, mychannel);
04595 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04596 break;
04597 case REMXXX:
04598 wait_interval(myrpt, DLY_TELEM, mychannel);
04599 res = 0;
04600 switch(mytele->submode)
04601 {
04602 case 100:
04603 sayfile(mychannel, "rpt/rxpl");
04604 sayfile(mychannel, "rpt/off");
04605 break;
04606 case 101:
04607 sayfile(mychannel, "rpt/rxpl");
04608 sayfile(mychannel, "rpt/on");
04609 break;
04610 case 102:
04611 sayfile(mychannel, "rpt/txpl");
04612 sayfile(mychannel, "rpt/off");
04613 break;
04614 case 103:
04615 sayfile(mychannel, "rpt/txpl");
04616 sayfile(mychannel, "rpt/on");
04617 break;
04618 case 104:
04619 sayfile(mychannel, "rpt/lopwr");
04620 break;
04621 case 105:
04622 sayfile(mychannel, "rpt/medpwr");
04623 break;
04624 case 106:
04625 sayfile(mychannel, "rpt/hipwr");
04626 break;
04627 case 113:
04628 sayfile(mychannel,"rpt/down");
04629 sayfile(mychannel, "rpt/slow");
04630 break;
04631 case 114:
04632 sayfile(mychannel,"rpt/down");
04633 sayfile(mychannel, "rpt/quick");
04634 break;
04635 case 115:
04636 sayfile(mychannel,"rpt/down");
04637 sayfile(mychannel, "rpt/fast");
04638 break;
04639 case 116:
04640 sayfile(mychannel,"rpt/up");
04641 sayfile(mychannel, "rpt/slow");
04642 break;
04643 case 117:
04644 sayfile(mychannel,"rpt/up");
04645 sayfile(mychannel, "rpt/quick");
04646 break;
04647 case 118:
04648 sayfile(mychannel,"rpt/up");
04649 sayfile(mychannel, "rpt/fast");
04650 break;
04651 default:
04652 res = -1;
04653 }
04654 wait_interval(myrpt, DLY_COMP, mychannel);
04655 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04656 break;
04657 case SCAN:
04658 ast_mutex_lock(&myrpt->remlock);
04659 if (myrpt->hfscanstop)
04660 {
04661 myrpt->hfscanstatus = 0;
04662 myrpt->hfscanmode = 0;
04663 myrpt->hfscanstop = 0;
04664 mytele->mode = SCANSTAT;
04665 ast_mutex_unlock(&myrpt->remlock);
04666 if (ast_safe_sleep(mychannel,1000) == -1) break;
04667 sayfile(mychannel, "rpt/stop");
04668 imdone = 1;
04669 break;
04670 }
04671 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04672 i = myrpt->hfscanstatus;
04673 myrpt->hfscanstatus = 0;
04674 if (i) mytele->mode = SCANSTAT;
04675 ast_mutex_unlock(&myrpt->remlock);
04676 if (i < 0) sayfile(mychannel, "rpt/stop");
04677 else if (i > 0) saynum(mychannel,i);
04678 imdone = 1;
04679 break;
04680 case TUNE:
04681 ast_mutex_lock(&myrpt->remlock);
04682 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04683 {
04684 set_mode_ic706(myrpt, REM_MODE_AM);
04685 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04686 ast_safe_sleep(mychannel,500);
04687 set_mode_ic706(myrpt, myrpt->remmode);
04688 myrpt->tunerequest = 0;
04689 ast_mutex_unlock(&myrpt->remlock);
04690 imdone = 1;
04691 break;
04692 }
04693 set_mode_ft897(myrpt, REM_MODE_AM);
04694 simple_command_ft897(myrpt, 8);
04695 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04696 simple_command_ft897(myrpt, 0x88);
04697 ast_safe_sleep(mychannel,500);
04698 set_mode_ft897(myrpt, myrpt->remmode);
04699 myrpt->tunerequest = 0;
04700 ast_mutex_unlock(&myrpt->remlock);
04701 imdone = 1;
04702 break;
04703 case REMSHORTSTATUS:
04704 case REMLONGSTATUS:
04705 wait_interval(myrpt, DLY_TELEM, mychannel);
04706 res = saynode(myrpt,mychannel,myrpt->name);
04707 if(!res)
04708 res = sayfile(mychannel,"rpt/frequency");
04709 if(!res)
04710 res = split_freq(mhz, decimals, myrpt->freq);
04711 if (!multimode_capable(myrpt)) decimals[3] = 0;
04712 if(!res){
04713 m = atoi(mhz);
04714 if(m < 100)
04715 res = saynum(mychannel, m);
04716 else
04717 res = saycharstr(mychannel, mhz);
04718 }
04719 if(!res)
04720 res = sayfile(mychannel, "letters/dot");
04721 if(!res)
04722 res = saycharstr(mychannel, decimals);
04723
04724 if(res) break;
04725 if(myrpt->remmode == REM_MODE_FM){
04726 switch(myrpt->offset){
04727
04728 case REM_MINUS:
04729 res = sayfile(mychannel,"rpt/minus");
04730 break;
04731
04732 case REM_SIMPLEX:
04733 res = sayfile(mychannel,"rpt/simplex");
04734 break;
04735
04736 case REM_PLUS:
04737 res = sayfile(mychannel,"rpt/plus");
04738 break;
04739
04740 default:
04741 break;
04742 }
04743 }
04744 else{
04745 switch(myrpt->remmode){
04746
04747 case REM_MODE_USB:
04748 res = saycharstr(mychannel, "USB");
04749 break;
04750
04751 case REM_MODE_LSB:
04752 res = saycharstr(mychannel, "LSB");
04753 break;
04754
04755 case REM_MODE_AM:
04756 res = saycharstr(mychannel, "AM");
04757 break;
04758
04759
04760 default:
04761 break;
04762 }
04763 }
04764
04765 if (res == -1) break;
04766
04767 if(mytele->mode == REMSHORTSTATUS){
04768 wait_interval(myrpt, DLY_COMP, mychannel);
04769 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04770 break;
04771 }
04772
04773 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04774 {
04775 switch(myrpt->powerlevel){
04776
04777 case REM_LOWPWR:
04778 res = sayfile(mychannel,"rpt/lopwr") ;
04779 break;
04780 case REM_MEDPWR:
04781 res = sayfile(mychannel,"rpt/medpwr");
04782 break;
04783 case REM_HIPWR:
04784 res = sayfile(mychannel,"rpt/hipwr");
04785 break;
04786 }
04787 }
04788
04789 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04790 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04791 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04792 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04793 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04794 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04795 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04796 (sayfile(mychannel,"rpt/frequency") == -1) ||
04797 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04798 if(myrpt->remmode == REM_MODE_FM){
04799 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04800 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04801 (sayfile(mychannel,"rpt/txpl") == -1) ||
04802 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04803 {
04804 break;
04805 }
04806 }
04807 wait_interval(myrpt, DLY_COMP, mychannel);
04808 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04809 break;
04810 case STATUS:
04811
04812 wait_interval(myrpt, DLY_TELEM, mychannel);
04813 hastx = 0;
04814 linkbase.next = &linkbase;
04815 linkbase.prev = &linkbase;
04816 rpt_mutex_lock(&myrpt->lock);
04817
04818 l = myrpt->links.next;
04819 while(l != &myrpt->links)
04820 {
04821 if (l->name[0] == '0')
04822 {
04823 l = l->next;
04824 continue;
04825 }
04826 l1 = ast_malloc(sizeof(struct rpt_link));
04827 if (!l1)
04828 {
04829 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", ast_channel_name(mychannel));
04830 remque((struct qelem *)mytele);
04831 myrpt->active_telem = NULL;
04832 rpt_mutex_unlock(&myrpt->lock);
04833 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04834 ast_free(nodename);
04835 ast_free(ident);
04836 ast_free(mytele);
04837 ast_hangup(mychannel);
04838 pthread_exit(NULL);
04839 }
04840 memcpy(l1,l,sizeof(struct rpt_link));
04841 l1->next = l1->prev = NULL;
04842 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04843 l = l->next;
04844 }
04845 rpt_mutex_unlock(&myrpt->lock);
04846 res = saynode(myrpt,mychannel,myrpt->name);
04847 if (myrpt->callmode)
04848 {
04849 hastx = 1;
04850 res = ast_streamfile(mychannel, "rpt/autopatch_on", ast_channel_language(mychannel));
04851 if (!res)
04852 res = ast_waitstream(mychannel, "");
04853 else
04854 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04855 ast_stopstream(mychannel);
04856 }
04857 l = linkbase.next;
04858 while(l != &linkbase)
04859 {
04860 char *s;
04861
04862 hastx = 1;
04863 res = saynode(myrpt,mychannel,l->name);
04864 s = "rpt/tranceive";
04865 if (!l->mode) s = "rpt/monitor";
04866 if (!l->thisconnected) s = "rpt/connecting";
04867 res = ast_streamfile(mychannel, s, ast_channel_language(mychannel));
04868 if (!res)
04869 res = ast_waitstream(mychannel, "");
04870 else
04871 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04872 ast_stopstream(mychannel);
04873 l = l->next;
04874 }
04875 if (!hastx)
04876 {
04877 res = ast_streamfile(mychannel, "rpt/repeat_only", ast_channel_language(mychannel));
04878 if (!res)
04879 res = ast_waitstream(mychannel, "");
04880 else
04881 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04882 ast_stopstream(mychannel);
04883 }
04884
04885 l = linkbase.next;
04886 while(l != &linkbase)
04887 {
04888 l1 = l;
04889 l = l->next;
04890 remque((struct qelem *)l1);
04891 ast_free(l1);
04892 }
04893 imdone = 1;
04894 break;
04895 case FULLSTATUS:
04896 rpt_mutex_lock(&myrpt->lock);
04897
04898 __mklinklist(myrpt,NULL,lbuf);
04899 rpt_mutex_unlock(&myrpt->lock);
04900
04901 ns = finddelim(lbuf,strs,MAXLINKLIST);
04902
04903 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04904
04905 wait_interval(myrpt, DLY_TELEM, mychannel);
04906 hastx = 0;
04907 res = saynode(myrpt,mychannel,myrpt->name);
04908 if (myrpt->callmode)
04909 {
04910 hastx = 1;
04911 res = ast_streamfile(mychannel, "rpt/autopatch_on", ast_channel_language(mychannel));
04912 if (!res)
04913 res = ast_waitstream(mychannel, "");
04914 else
04915 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04916 ast_stopstream(mychannel);
04917 }
04918
04919 for(i = 0; i < ns; i++)
04920 {
04921 char *s,mode = 'T';
04922
04923
04924 if ((*strs[i] < '0') || (*strs[i] > '9'))
04925 {
04926 mode = *strs[i];
04927 strs[i]++;
04928 }
04929
04930 hastx = 1;
04931 res = saynode(myrpt,mychannel,strs[i]);
04932 s = "rpt/tranceive";
04933 if (mode == 'R') s = "rpt/monitor";
04934 if (mode == 'C') s = "rpt/connecting";
04935 res = ast_streamfile(mychannel, s, ast_channel_language(mychannel));
04936 if (!res)
04937 res = ast_waitstream(mychannel, "");
04938 else
04939 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04940 ast_stopstream(mychannel);
04941 }
04942 if (!hastx)
04943 {
04944 res = ast_streamfile(mychannel, "rpt/repeat_only", ast_channel_language(mychannel));
04945 if (!res)
04946 res = ast_waitstream(mychannel, "");
04947 else
04948 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04949 ast_stopstream(mychannel);
04950 }
04951 imdone = 1;
04952 break;
04953
04954 case LASTNODEKEY:
04955 rpt_mutex_lock(&myrpt->lock);
04956 if(myrpt->lastnodewhichkeyedusup){
04957 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04958 if(!p){
04959 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04960 imdone = 1;
04961 break;
04962 }
04963 }
04964 else
04965 p = NULL;
04966 rpt_mutex_unlock(&myrpt->lock);
04967 if(!p){
04968 imdone = 1;
04969 break;
04970 }
04971 wait_interval(myrpt, DLY_TELEM, mychannel);
04972 res = saynode(myrpt,mychannel,p);
04973 ast_free(p);
04974 imdone = 1;
04975 break;
04976
04977 case UNAUTHTX:
04978 wait_interval(myrpt, DLY_TELEM, mychannel);
04979 res = ast_streamfile(mychannel, "rpt/unauthtx", ast_channel_language(mychannel));
04980 if (!res)
04981 res = ast_waitstream(mychannel, "");
04982 else
04983 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
04984 ast_stopstream(mychannel);
04985 imdone = 1;
04986 break;
04987
04988 case PARROT:
04989
04990 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04991 if (ast_fileexists(mystr,NULL,ast_channel_language(mychannel)) <= 0)
04992 {
04993 imdone = 1;
04994 myrpt->parrotstate = 0;
04995 break;
04996 }
04997 wait_interval(myrpt, DLY_PARROT, mychannel);
04998 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04999 res = ast_streamfile(mychannel, mystr, ast_channel_language(mychannel));
05000 if (!res)
05001 res = ast_waitstream(mychannel, "");
05002 else
05003 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
05004 ast_stopstream(mychannel);
05005 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
05006 strcat(mystr,".wav");
05007 unlink(mystr);
05008 imdone = 1;
05009 myrpt->parrotstate = 0;
05010 break;
05011
05012 case TIMEOUT:
05013 res = saynode(myrpt,mychannel,myrpt->name);
05014 if (!res)
05015 res = ast_streamfile(mychannel, "rpt/timeout", ast_channel_language(mychannel));
05016 break;
05017
05018 case TIMEOUT_WARNING:
05019 time(&t);
05020 res = saynode(myrpt,mychannel,myrpt->name);
05021 if (!res)
05022 res = ast_streamfile(mychannel, "rpt/timeout-warning", ast_channel_language(mychannel));
05023 if (!res)
05024 res = ast_waitstream(mychannel, "");
05025 else
05026 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
05027 ast_stopstream(mychannel);
05028 if(!res)
05029 ast_say_number(mychannel, myrpt->p.remotetimeout -
05030 (t - myrpt->last_activity_time),
05031 "", ast_channel_language(mychannel), (char *) NULL);
05032 if (!res)
05033 res = ast_waitstream(mychannel, "");
05034 ast_stopstream(mychannel);
05035 res = ast_streamfile(mychannel, "queue-seconds", ast_channel_language(mychannel));
05036 break;
05037
05038 case ACT_TIMEOUT_WARNING:
05039 time(&t);
05040 res = saynode(myrpt,mychannel,myrpt->name);
05041 if (!res)
05042 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", ast_channel_language(mychannel));
05043 if (!res)
05044 res = ast_waitstream(mychannel, "");
05045 else
05046 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
05047 ast_stopstream(mychannel);
05048 if(!res)
05049 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05050 (t - myrpt->last_activity_time),
05051 "", ast_channel_language(mychannel), (char *) NULL);
05052 if (!res)
05053 res = ast_waitstream(mychannel, "");
05054 ast_stopstream(mychannel);
05055 res = ast_streamfile(mychannel, "queue-seconds", ast_channel_language(mychannel));
05056 break;
05057
05058 case STATS_TIME:
05059 case STATS_TIME_LOCAL:
05060 wait_interval(myrpt, DLY_TELEM, mychannel);
05061 t = time(NULL);
05062 rpt_localtime(&t, &localtm);
05063
05064 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05065 p = "rpt/goodmorning";
05066 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05067 p = "rpt/goodafternoon";
05068 else
05069 p = "rpt/goodevening";
05070 if (sayfile(mychannel,p) == -1)
05071 {
05072 imdone = 1;
05073 break;
05074 }
05075
05076 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05077 {
05078 imdone = 1;
05079 break;
05080 }
05081
05082 res = ast_say_time(mychannel, t, "", ast_channel_language(mychannel));
05083 if (!res)
05084 res = ast_waitstream(mychannel, "");
05085 ast_stopstream(mychannel);
05086 imdone = 1;
05087 break;
05088 case STATS_VERSION:
05089 p = strstr(tdesc, "version");
05090 if(!p)
05091 break;
05092 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05093 break;
05094 wait_interval(myrpt, DLY_TELEM, mychannel);
05095
05096 if (sayfile(mychannel,"rpt/version") == -1)
05097 {
05098 imdone = 1;
05099 break;
05100 }
05101 if(!res)
05102 ast_say_number(mychannel, vmajor, "", ast_channel_language(mychannel), (char *) NULL);
05103 if (!res)
05104 res = ast_waitstream(mychannel, "");
05105 ast_stopstream(mychannel);
05106 if (saycharstr(mychannel,".") == -1)
05107 {
05108 imdone = 1;
05109 break;
05110 }
05111 if(!res)
05112 ast_say_number(mychannel, vminor, "", ast_channel_language(mychannel), (char *) NULL);
05113 if (!res){
05114 res = ast_waitstream(mychannel, "");
05115 ast_stopstream(mychannel);
05116 }
05117 else
05118 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
05119 imdone = 1;
05120 break;
05121 case ARB_ALPHA:
05122 wait_interval(myrpt, DLY_TELEM, mychannel);
05123 if(mytele->param)
05124 saycharstr(mychannel, mytele->param);
05125 imdone = 1;
05126 break;
05127 case REV_PATCH:
05128 wait_interval(myrpt, DLY_TELEM, mychannel);
05129 if(mytele->param) {
05130
05131
05132 char *tpl_working, *tpl_current;
05133 char *tmp[100], *myparm;
05134 int looptemp=0,idx=0, dres = 0;
05135
05136
05137 tpl_working = ast_strdup(mytele->param);
05138 myparm = strsep(&tpl_working,",");
05139 tpl_current=strsep(&tpl_working, ":");
05140
05141 while(tpl_current && looptemp < sizeof(tmp)) {
05142 tmp[looptemp]=tpl_current;
05143 looptemp++;
05144 tpl_current=strsep(&tpl_working,":");
05145 }
05146
05147 for(idx=0; idx<looptemp; idx++) {
05148 if(!strcmp(tmp[idx], "PARKED")) {
05149 ast_say_digits(mychannel, atoi(myparm), "", ast_channel_language(mychannel));
05150 } else if(!strcmp(tmp[idx], "NODE")) {
05151 ast_say_digits(mychannel, atoi(myrpt->name), "", ast_channel_language(mychannel));
05152 } else {
05153 dres = ast_streamfile(mychannel, tmp[idx], ast_channel_language(mychannel));
05154 if(!dres) {
05155 dres = ast_waitstream(mychannel, "");
05156 } else {
05157 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], ast_channel_name(mychannel));
05158 dres = 0;
05159 }
05160 }
05161 }
05162 ast_free(tpl_working);
05163 }
05164 imdone = 1;
05165 break;
05166 case TEST_TONE:
05167 imdone = 1;
05168 if (myrpt->stopgen) break;
05169 myrpt->stopgen = -1;
05170 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05171 {
05172 myrpt->stopgen = 0;
05173 break;
05174 }
05175 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05176 if (ast_safe_sleep(mychannel,1)) break;
05177 imdone = 1;
05178 }
05179 myrpt->stopgen = 0;
05180 break;
05181 default:
05182 break;
05183 }
05184 if (!imdone)
05185 {
05186 if (!res)
05187 res = ast_waitstream(mychannel, "");
05188 else {
05189 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(mychannel));
05190 res = 0;
05191 }
05192 }
05193 ast_stopstream(mychannel);
05194 rpt_mutex_lock(&myrpt->lock);
05195 if (mytele->mode == TAILMSG)
05196 {
05197 if (!res)
05198 {
05199 myrpt->tailmessagen++;
05200 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05201 }
05202 else
05203 {
05204 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05205 }
05206 }
05207 remque((struct qelem *)mytele);
05208 myrpt->active_telem = NULL;
05209 rpt_mutex_unlock(&myrpt->lock);
05210 ast_free(nodename);
05211 ast_free(ident);
05212 ast_free(mytele);
05213 ast_hangup(mychannel);
05214 #ifdef APP_RPT_LOCK_DEBUG
05215 {
05216 struct lockthread *t;
05217
05218 sleep(5);
05219 ast_mutex_lock(&locklock);
05220 t = get_lockthread(pthread_self());
05221 if (t) memset(t,0,sizeof(struct lockthread));
05222 ast_mutex_unlock(&locklock);
05223 }
05224 #endif
05225 pthread_exit(NULL);
05226 }
05227
05228 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05229 {
05230 struct rpt_tele *tele;
05231 struct rpt_link *mylink = NULL;
05232 int res;
05233 pthread_attr_t attr;
05234 char *v1, *v2;
05235
05236 if(debug > 6)
05237 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05238
05239 switch(mode)
05240 {
05241 case UNKEY:
05242
05243
05244 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05245 "unlinkedct");
05246 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05247 "remotect");
05248 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05249 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05250 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05251 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05252 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05253 break;
05254 case LINKUNKEY:
05255 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05256 return;
05257 break;
05258 default:
05259 break;
05260 }
05261 tele = ast_malloc(sizeof(struct rpt_tele));
05262 if (!tele)
05263 {
05264 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05265 pthread_exit(NULL);
05266 return;
05267 }
05268
05269 memset((char *)tele,0,sizeof(struct rpt_tele));
05270 tele->rpt = myrpt;
05271 tele->mode = mode;
05272 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05273 else mylink = (struct rpt_link *) data;
05274 rpt_mutex_lock(&myrpt->lock);
05275 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05276 (mode == LINKUNKEY)){
05277 memset(&tele->mylink,0,sizeof(struct rpt_link));
05278 if (mylink){
05279 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05280 }
05281 }
05282 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05283 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05284 tele->param[TELEPARAMSIZE - 1] = 0;
05285 }
05286 if (mode == REMXXX) tele->submode = (intptr_t) data;
05287 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05288 rpt_mutex_unlock(&myrpt->lock);
05289 pthread_attr_init(&attr);
05290 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05291 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05292 if(res < 0){
05293 rpt_mutex_lock(&myrpt->lock);
05294 remque((struct qlem *) tele);
05295 rpt_mutex_unlock(&myrpt->lock);
05296 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05297 }
05298 return;
05299 }
05300
05301 static void *rpt_call(void *this)
05302 {
05303 struct dahdi_confinfo ci;
05304 struct rpt *myrpt = (struct rpt *)this;
05305 int res;
05306 int stopped,congstarted,dialtimer,lastcidx,aborted;
05307 struct ast_channel *mychannel,*genchannel;
05308 struct ast_format_cap *cap = NULL;
05309
05310 myrpt->mydtmf = 0;
05311
05312 mychannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
05313 cap = ast_format_cap_destroy(cap);
05314 if (!mychannel)
05315 {
05316 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05317 pthread_exit(NULL);
05318 }
05319 #ifdef AST_CDR_FLAG_POST_DISABLED
05320 if (mychannel->cdr)
05321 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05322 #endif
05323 ci.chan = 0;
05324 ci.confno = myrpt->conf;
05325 #if 0
05326 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05327 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05328 #endif
05329 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05330
05331 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05332 {
05333 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05334 ast_hangup(mychannel);
05335 myrpt->callmode = 0;
05336 pthread_exit(NULL);
05337 }
05338
05339 genchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
05340 cap = ast_format_cap_destroy(cap);
05341 if (!genchannel)
05342 {
05343 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05344 ast_hangup(mychannel);
05345 pthread_exit(NULL);
05346 }
05347 #ifdef AST_CDR_FLAG_POST_DISABLED
05348 if (genchannel->cdr)
05349 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05350 #endif
05351 ci.chan = 0;
05352 ci.confno = myrpt->conf;
05353 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05354 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05355
05356 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05357 {
05358 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05359 ast_hangup(mychannel);
05360 ast_hangup(genchannel);
05361 myrpt->callmode = 0;
05362 pthread_exit(NULL);
05363 }
05364 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05365 {
05366 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05367 ast_hangup(mychannel);
05368 ast_hangup(genchannel);
05369 myrpt->callmode = 0;
05370 pthread_exit(NULL);
05371 }
05372 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05373 {
05374 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05375 ast_hangup(mychannel);
05376 ast_hangup(genchannel);
05377 myrpt->callmode = 0;
05378 pthread_exit(NULL);
05379 }
05380
05381 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05382 {
05383 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05384 ast_hangup(mychannel);
05385 ast_hangup(genchannel);
05386 myrpt->callmode = 0;
05387 pthread_exit(NULL);
05388 }
05389 stopped = 0;
05390 congstarted = 0;
05391 dialtimer = 0;
05392 lastcidx = 0;
05393 myrpt->calldigittimer = 0;
05394 aborted = 0;
05395
05396 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05397 {
05398 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05399 dialtimer = 0;
05400 lastcidx = myrpt->cidx;
05401 }
05402
05403 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05404 if(debug)
05405 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05406 rpt_mutex_lock(&myrpt->lock);
05407 aborted = 1;
05408 myrpt->callmode = 0;
05409 rpt_mutex_unlock(&myrpt->lock);
05410 break;
05411 }
05412
05413 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05414 {
05415 stopped = 1;
05416
05417 tone_zone_play_tone(genchannel->fds[0],-1);
05418 }
05419 if (myrpt->callmode == 1)
05420 {
05421 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05422 {
05423 myrpt->callmode = 2;
05424 break;
05425 }
05426
05427 if (myrpt->calldigittimer)
05428 myrpt->calldigittimer += MSWAIT;
05429 }
05430 if (myrpt->callmode == 4)
05431 {
05432 if(!congstarted){
05433 congstarted = 1;
05434
05435 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05436 }
05437 }
05438 res = ast_safe_sleep(mychannel, MSWAIT);
05439 if (res < 0)
05440 {
05441 if(debug)
05442 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05443 ast_hangup(mychannel);
05444 ast_hangup(genchannel);
05445 rpt_mutex_lock(&myrpt->lock);
05446 myrpt->callmode = 0;
05447 rpt_mutex_unlock(&myrpt->lock);
05448 pthread_exit(NULL);
05449 }
05450 dialtimer += MSWAIT;
05451 }
05452
05453 tone_zone_play_tone(genchannel->fds[0],-1);
05454
05455 if (!myrpt->callmode)
05456 {
05457 if(debug)
05458 ast_log(LOG_NOTICE, "callmode==0\n");
05459 ast_hangup(mychannel);
05460 ast_hangup(genchannel);
05461 rpt_mutex_lock(&myrpt->lock);
05462 myrpt->callmode = 0;
05463 myrpt->macropatch=0;
05464 channel_revert(myrpt);
05465 rpt_mutex_unlock(&myrpt->lock);
05466 if((!myrpt->patchquiet) && aborted)
05467 rpt_telemetry(myrpt, TERM, NULL);
05468 pthread_exit(NULL);
05469 }
05470
05471 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05472 char *name, *loc, *instr;
05473 instr = ast_strdup(myrpt->p.ourcallerid);
05474 if(instr){
05475 ast_callerid_parse(instr, &name, &loc);
05476 if(loc){
05477 mychannel->caller.id.number.valid = 1;
05478 ast_free(mychannel->caller.id.number.str);
05479 mychannel->caller.id.number.str = ast_strdup(loc);
05480 }
05481 if(name){
05482 mychannel->caller.id.name.valid = 1;
05483 ast_free(mychannel->caller.id.name.str);
05484 mychannel->caller.id.name.str = ast_strdup(name);
05485 }
05486 ast_free(instr);
05487 }
05488 }
05489
05490 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05491 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05492
05493 if (myrpt->p.acctcode)
05494 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05495 mychannel->priority = 1;
05496 ast_channel_undefer_dtmf(mychannel);
05497 if (ast_pbx_start(mychannel) < 0)
05498 {
05499 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05500 ast_hangup(mychannel);
05501 ast_hangup(genchannel);
05502 rpt_mutex_lock(&myrpt->lock);
05503 myrpt->callmode = 0;
05504 rpt_mutex_unlock(&myrpt->lock);
05505 pthread_exit(NULL);
05506 }
05507 usleep(10000);
05508 rpt_mutex_lock(&myrpt->lock);
05509 myrpt->callmode = 3;
05510
05511 ci.chan = 0;
05512 ci.confno = myrpt->conf;
05513 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05514 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05515
05516 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05517 {
05518 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05519 ast_hangup(mychannel);
05520 ast_hangup(genchannel);
05521 myrpt->callmode = 0;
05522 pthread_exit(NULL);
05523 }
05524
05525 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05526 {
05527 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05528 ast_hangup(mychannel);
05529 myrpt->callmode = 0;
05530 pthread_exit(NULL);
05531 }
05532 ci.chan = 0;
05533 ci.confno = res;
05534 ci.confmode = DAHDI_CONF_MONITOR;
05535
05536 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05537 {
05538 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05539 ast_hangup(mychannel);
05540 myrpt->callmode = 0;
05541 pthread_exit(NULL);
05542 }
05543 while(myrpt->callmode)
05544 {
05545 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05546 {
05547
05548 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05549 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05550 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05551 myrpt->callmode = 0;
05552 myrpt->macropatch=0;
05553 if(!myrpt->patchquiet){
05554 rpt_mutex_unlock(&myrpt->lock);
05555 rpt_telemetry(myrpt, TERM, NULL);
05556 rpt_mutex_lock(&myrpt->lock);
05557 }
05558 }
05559 else{
05560 myrpt->callmode = 4;
05561 rpt_mutex_unlock(&myrpt->lock);
05562
05563 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05564 rpt_mutex_lock(&myrpt->lock);
05565 }
05566 }
05567 if (myrpt->mydtmf)
05568 {
05569 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05570 wf.subclass.integer = myrpt->mydtmf;
05571 rpt_mutex_unlock(&myrpt->lock);
05572 ast_queue_frame(mychannel,&wf);
05573 #ifdef NEW_ASTERISK
05574 ast_senddigit(genchannel,myrpt->mydtmf,0);
05575 #else
05576 ast_senddigit(genchannel,myrpt->mydtmf);
05577 #endif
05578 rpt_mutex_lock(&myrpt->lock);
05579 myrpt->mydtmf = 0;
05580 }
05581 rpt_mutex_unlock(&myrpt->lock);
05582 usleep(MSWAIT * 1000);
05583 rpt_mutex_lock(&myrpt->lock);
05584 }
05585 if(debug)
05586 ast_log(LOG_NOTICE, "exit channel loop\n");
05587 rpt_mutex_unlock(&myrpt->lock);
05588 tone_zone_play_tone(genchannel->fds[0],-1);
05589 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05590 ast_hangup(genchannel);
05591 rpt_mutex_lock(&myrpt->lock);
05592 myrpt->callmode = 0;
05593 myrpt->macropatch=0;
05594 channel_revert(myrpt);
05595 rpt_mutex_unlock(&myrpt->lock);
05596
05597 ci.chan = 0;
05598 ci.confno = myrpt->conf;
05599 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05600 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05601
05602 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05603 {
05604 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05605 }
05606 pthread_exit(NULL);
05607 }
05608
05609 static void send_link_dtmf(struct rpt *myrpt,char c)
05610 {
05611 char str[300];
05612 struct ast_frame wf;
05613 struct rpt_link *l;
05614
05615 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05616 wf.frametype = AST_FRAME_TEXT;
05617 wf.subclass.integer = 0;
05618 wf.offset = 0;
05619 wf.mallocd = 0;
05620 wf.datalen = strlen(str) + 1;
05621 wf.samples = 0;
05622 l = myrpt->links.next;
05623
05624 while(l != &myrpt->links)
05625 {
05626 if (l->name[0] == '0')
05627 {
05628 l = l->next;
05629 continue;
05630 }
05631
05632 if (!strcmp(l->name,myrpt->cmdnode))
05633 {
05634 wf.data.ptr = str;
05635 if (l->chan) ast_write(l->chan,&wf);
05636 return;
05637 }
05638 l = l->next;
05639 }
05640 l = myrpt->links.next;
05641
05642 while(l != &myrpt->links)
05643 {
05644 wf.data.ptr = str;
05645 if (l->chan) ast_write(l->chan,&wf);
05646 l = l->next;
05647 }
05648 return;
05649 }
05650
05651 static void send_link_keyquery(struct rpt *myrpt)
05652 {
05653 char str[300];
05654 struct ast_frame wf;
05655 struct rpt_link *l;
05656
05657 rpt_mutex_lock(&myrpt->lock);
05658 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05659 myrpt->topkeystate = 1;
05660 time(&myrpt->topkeytime);
05661 rpt_mutex_unlock(&myrpt->lock);
05662 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05663 wf.frametype = AST_FRAME_TEXT;
05664 wf.subclass.integer = 0;
05665 wf.offset = 0;
05666 wf.mallocd = 0;
05667 wf.datalen = strlen(str) + 1;
05668 wf.samples = 0;
05669 l = myrpt->links.next;
05670
05671 while(l != &myrpt->links)
05672 {
05673 wf.data.ptr = str;
05674 if (l->chan) ast_write(l->chan,&wf);
05675 l = l->next;
05676 }
05677 return;
05678 }
05679
05680
05681
05682 static void send_newkey(struct ast_channel *chan)
05683 {
05684
05685
05686 ast_sendtext(chan,newkeystr);
05687 return;
05688 }
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05703 {
05704 char *val, *s, *s1, *s2, *tele;
05705 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05706 char tmp[300], deststr[300] = "",modechange = 0;
05707 char sx[320],*sy;
05708 struct rpt_link *l;
05709 int reconnects = 0;
05710 int i,n;
05711 struct dahdi_confinfo ci;
05712 struct ast_format_cap *cap = NULL;
05713
05714 val = node_lookup(myrpt,node);
05715 if (!val){
05716 if(strlen(node) >= myrpt->longestnode)
05717 return -1;
05718 return 1;
05719 }
05720
05721 if(!strcmp(myrpt->name,node))
05722 return -2;
05723
05724 if(debug > 3){
05725 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05726 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05727 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05728 }
05729
05730 strncpy(tmp,val,sizeof(tmp) - 1);
05731 s = tmp;
05732 s1 = strsep(&s,",");
05733 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05734 {
05735 sy = strchr(s1,'/');
05736 *sy = 0;
05737 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05738 s1 = sx;
05739 }
05740 s2 = strsep(&s,",");
05741 rpt_mutex_lock(&myrpt->lock);
05742 l = myrpt->links.next;
05743
05744 while(l != &myrpt->links){
05745 if (l->name[0] == '0')
05746 {
05747 l = l->next;
05748 continue;
05749 }
05750
05751 if (!strcmp(l->name, node))
05752 break;
05753 l = l->next;
05754 }
05755
05756 if (l != &myrpt->links){
05757
05758 if ((l->mode) || (!l->chan)) {
05759 rpt_mutex_unlock(&myrpt->lock);
05760 return 2;
05761 }
05762 reconnects = l->reconnects;
05763 rpt_mutex_unlock(&myrpt->lock);
05764 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05765 l->retries = l->max_retries + 1;
05766 l->disced = 2;
05767 modechange = 1;
05768 } else
05769 {
05770 __mklinklist(myrpt,NULL,lstr);
05771 rpt_mutex_unlock(&myrpt->lock);
05772 n = finddelim(lstr,strs,MAXLINKLIST);
05773 for(i = 0; i < n; i++)
05774 {
05775 if ((*strs[i] < '0') ||
05776 (*strs[i] > '9')) strs[i]++;
05777 if (!strcmp(strs[i],node))
05778 {
05779 return 2;
05780 }
05781 }
05782 }
05783 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05784
05785 l = ast_malloc(sizeof(struct rpt_link));
05786 if (!l)
05787 {
05788 ast_log(LOG_WARNING, "Unable to malloc\n");
05789 return -1;
05790 }
05791
05792 memset((char *)l,0,sizeof(struct rpt_link));
05793 l->mode = mode;
05794 l->outbound = 1;
05795 l->thisconnected = 0;
05796 voxinit_link(l,1);
05797 strncpy(l->name, node, MAXNODESTR - 1);
05798 l->isremote = (s && ast_true(s));
05799 if (modechange) l->connected = 1;
05800 l->hasconnected = l->perma = perma;
05801 #ifdef ALLOW_LOCAL_CHANNELS
05802 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05803 strncpy(deststr, s1, sizeof(deststr));
05804 else
05805 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05806 #else
05807 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05808 #endif
05809 tele = strchr(deststr, '/');
05810 if (!tele){
05811 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05812 ast_free(l);
05813 return -1;
05814 }
05815 *tele++ = 0;
05816 l->chan = ast_request(deststr, get_slin_cap(cap), NULL, tele, NULL);
05817 cap = ast_format_cap_destroy(cap);
05818 if (l->chan){
05819 ast_set_read_format_by_id(l->chan, AST_FORMAT_SLINEAR);
05820 ast_set_write_format_by_id(l->chan, AST_FORMAT_SLINEAR);
05821 #ifdef AST_CDR_FLAG_POST_DISABLED
05822 if (l->chan->cdr)
05823 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05824 #endif
05825 #ifndef NEW_ASTERISK
05826 l->chan->whentohangup = 0;
05827 #endif
05828 l->chan->appl = "Apprpt";
05829 l->chan->data = "(Remote Rx)";
05830 if (debug > 3)
05831 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05832 deststr, tele, ast_channel_name(l->chan));
05833 l->chan->caller.id.number.valid = 1;
05834 ast_free(l->chan->caller.id.number.str);
05835 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
05836 ast_call(l->chan,tele,999);
05837 }
05838 else {
05839 if(debug > 3)
05840 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05841 deststr,tele,ast_channel_name(l->chan));
05842 if (myrpt->p.archivedir)
05843 {
05844 char str[100];
05845 sprintf(str,"LINKFAIL,%s",l->name);
05846 donodelog(myrpt,str);
05847 }
05848 ast_free(l);
05849 return -1;
05850 }
05851
05852 l->pchan = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
05853 cap = ast_format_cap_destroy(cap);
05854 if (!l->pchan){
05855 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05856 ast_hangup(l->chan);
05857 ast_free(l);
05858 return -1;
05859 }
05860 ast_set_read_format_by_id(l->pchan, AST_FORMAT_SLINEAR);
05861 ast_set_write_format_by_id(l->pchan, AST_FORMAT_SLINEAR);
05862 #ifdef AST_CDR_FLAG_POST_DISABLED
05863 if (l->pchan->cdr)
05864 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05865 #endif
05866
05867 ci.chan = 0;
05868 ci.confno = myrpt->conf;
05869 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05870
05871 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05872 {
05873 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05874 ast_hangup(l->chan);
05875 ast_hangup(l->pchan);
05876 ast_free(l);
05877 return -1;
05878 }
05879 rpt_mutex_lock(&myrpt->lock);
05880 l->reconnects = reconnects;
05881
05882 l->max_retries = MAX_RETRIES;
05883 if (perma)
05884 l->max_retries = MAX_RETRIES_PERM;
05885 if (l->isremote) l->retries = l->max_retries + 1;
05886 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05887 __kickshort(myrpt);
05888 rpt_mutex_unlock(&myrpt->lock);
05889 if (!l->phonemode) send_newkey(l->chan);
05890 return 0;
05891 }
05892
05893
05894
05895
05896
05897
05898
05899 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05900 {
05901
05902 char *val, *s, *s1, *s2;
05903 char tmp[300];
05904 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05905 char mode,perma;
05906 char sx[320],*sy;
05907 struct rpt_link *l;
05908 int i,r;
05909
05910 if(!param)
05911 return DC_ERROR;
05912
05913
05914 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05915 return DC_ERROR;
05916
05917 strncpy(digitbuf,digits,MAXNODESTR - 1);
05918
05919 if(debug > 6)
05920 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05921
05922 switch(myatoi(param)){
05923 case 11:
05924 case 1:
05925 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05926 strcpy(digitbuf,myrpt->lastlinknode);
05927 val = node_lookup(myrpt,digitbuf);
05928 if (!val){
05929 if(strlen(digitbuf) >= myrpt->longestnode)
05930 return DC_ERROR;
05931 break;
05932 }
05933 strncpy(tmp,val,sizeof(tmp) - 1);
05934 s = tmp;
05935 s1 = strsep(&s,",");
05936 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05937 {
05938 sy = strchr(s1,'/');
05939 *sy = 0;
05940 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05941 s1 = sx;
05942 }
05943 s2 = strsep(&s,",");
05944 rpt_mutex_lock(&myrpt->lock);
05945 l = myrpt->links.next;
05946
05947 while(l != &myrpt->links){
05948 if (l->name[0] == '0')
05949 {
05950 l = l->next;
05951 continue;
05952 }
05953
05954 if (!strcmp(l->name, digitbuf))
05955 break;
05956 l = l->next;
05957 }
05958 if (l != &myrpt->links){
05959 struct ast_frame wf;
05960
05961
05962 if ((myatoi(param) < 10) &&
05963 (l->max_retries > MAX_RETRIES))
05964 {
05965 rpt_mutex_unlock(&myrpt->lock);
05966 return DC_COMPLETE;
05967 }
05968 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05969 l->retries = l->max_retries + 1;
05970 l->disced = 1;
05971 rpt_mutex_unlock(&myrpt->lock);
05972 wf.frametype = AST_FRAME_TEXT;
05973 wf.subclass.integer = 0;
05974 wf.offset = 0;
05975 wf.mallocd = 0;
05976 wf.datalen = strlen(discstr) + 1;
05977 wf.samples = 0;
05978 wf.data.ptr = discstr;
05979 if (l->chan)
05980 {
05981 ast_write(l->chan,&wf);
05982 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05983 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05984 }
05985 rpt_telemetry(myrpt, COMPLETE, NULL);
05986 return DC_COMPLETE;
05987 }
05988 rpt_mutex_unlock(&myrpt->lock);
05989 return DC_COMPLETE;
05990 case 2:
05991 case 3:
05992 case 12:
05993 case 13:
05994 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05995 strcpy(digitbuf,myrpt->lastlinknode);
05996
05997 perma = (atoi(param) > 10) ? 1 : 0;
05998 mode = (atoi(param) & 1) ? 1 : 0;
05999 r = connect_link(myrpt, digitbuf, mode, perma);
06000 switch(r){
06001 case -2:
06002 return DC_COMPLETE;
06003
06004 case 0:
06005 rpt_telemetry(myrpt, COMPLETE, NULL);
06006 return DC_COMPLETE;
06007
06008 case 1:
06009 break;
06010
06011 case 2:
06012 rpt_telemetry(myrpt, REMALREADY, NULL);
06013 return DC_COMPLETE;
06014
06015 default:
06016 rpt_telemetry(myrpt, CONNFAIL, NULL);
06017 return DC_COMPLETE;
06018 }
06019 break;
06020
06021 case 4:
06022
06023
06024 if (((command_source != SOURCE_RPT) &&
06025 (command_source != SOURCE_PHONE) &&
06026 (command_source != SOURCE_ALT) &&
06027 (command_source != SOURCE_DPHONE)) ||
06028 (myrpt->links.next == &myrpt->links))
06029 return DC_COMPLETE;
06030
06031
06032 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06033
06034 rpt_telemetry(myrpt, REMALREADY, NULL);
06035 return DC_COMPLETE;
06036 }
06037 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06038 strcpy(digitbuf,myrpt->lastlinknode);
06039
06040 val = node_lookup(myrpt,digitbuf);
06041 if (!val){
06042 if(strlen(digitbuf) >= myrpt->longestnode)
06043 return DC_ERROR;
06044 break;
06045
06046 }
06047 rpt_mutex_lock(&myrpt->lock);
06048 strcpy(myrpt->lastlinknode,digitbuf);
06049 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06050 rpt_mutex_unlock(&myrpt->lock);
06051 rpt_telemetry(myrpt, REMGO, NULL);
06052 return DC_COMPLETE;
06053
06054 case 5:
06055 rpt_telemetry(myrpt, STATUS, NULL);
06056 return DC_COMPLETE;
06057
06058 case 15:
06059 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06060 return DC_COMPLETE;
06061
06062
06063 case 6:
06064 rpt_mutex_lock(&myrpt->lock);
06065 myrpt->savednodes[0] = 0;
06066 l = myrpt->links.next;
06067
06068 while(l != &myrpt->links){
06069 struct ast_frame wf;
06070 if (l->name[0] == '0')
06071 {
06072 l = l->next;
06073 continue;
06074 }
06075
06076 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06077 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06078 if(myrpt->savednodes[0])
06079 strcat(myrpt->savednodes, ",");
06080 strcat(myrpt->savednodes, tmp);
06081 }
06082 l->retries = l->max_retries + 1;
06083 l->disced = 2;
06084 rpt_mutex_unlock(&myrpt->lock);
06085
06086
06087 wf.frametype = AST_FRAME_TEXT;
06088 wf.subclass.integer = 0;
06089 wf.offset = 0;
06090 wf.mallocd = 0;
06091 wf.datalen = strlen(discstr) + 1;
06092 wf.samples = 0;
06093 wf.data.ptr = discstr;
06094 if (l->chan)
06095 {
06096 ast_write(l->chan,&wf);
06097 ast_safe_sleep(l->chan,250);
06098 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06099 }
06100 rpt_mutex_lock(&myrpt->lock);
06101 l = l->next;
06102 }
06103 rpt_mutex_unlock(&myrpt->lock);
06104 if(debug > 3)
06105 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06106 rpt_telemetry(myrpt, COMPLETE, NULL);
06107 return DC_COMPLETE;
06108
06109 case 7:
06110 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06111 break;
06112
06113
06114 #ifdef _MDC_DECODE_H_
06115 case 8:
06116 myrpt->lastunit = 0xd00d;
06117 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06118 mdc1200_send(myrpt,myrpt->lastunit);
06119 break;
06120 #endif
06121
06122 case 16:
06123 strcpy(tmp, myrpt->savednodes);
06124 finddelim(tmp, strs, MAXLINKLIST);
06125 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06126 s1 = strs[i];
06127 mode = (s1[0] == 'X') ? 1 : 0;
06128 perma = (s1[1] == 'P') ? 1 : 0;
06129 connect_link(myrpt, s1 + 2, mode, perma);
06130 }
06131 rpt_telemetry(myrpt, COMPLETE, NULL);
06132 break;
06133
06134 case 200:
06135 case 201:
06136 case 202:
06137 case 203:
06138 case 204:
06139 case 205:
06140 case 206:
06141 case 207:
06142 case 208:
06143 case 209:
06144 case 210:
06145 case 211:
06146 case 212:
06147 case 213:
06148 case 214:
06149 case 215:
06150 if (((myrpt->p.propagate_dtmf) &&
06151 (command_source == SOURCE_LNK)) ||
06152 ((myrpt->p.propagate_phonedtmf) &&
06153 ((command_source == SOURCE_PHONE) ||
06154 (command_source == SOURCE_ALT) ||
06155 (command_source == SOURCE_DPHONE))))
06156 do_dtmf_local(myrpt,
06157 remdtmfstr[myatoi(param) - 200]);
06158 default:
06159 return DC_ERROR;
06160
06161 }
06162
06163 return DC_INDETERMINATE;
06164 }
06165
06166
06167
06168
06169
06170 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06171 {
06172 pthread_attr_t attr;
06173 int i, idx, paramlength;
06174 char *lparam;
06175 char *value = NULL;
06176 char *paramlist[20];
06177
06178 static char *keywords[] = {
06179 "context",
06180 "dialtime",
06181 "farenddisconnect",
06182 "noct",
06183 "quiet",
06184 NULL
06185 };
06186
06187 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06188 return DC_ERROR;
06189
06190 if(debug)
06191 printf("@@@@ Autopatch up\n");
06192
06193 if(!myrpt->callmode){
06194
06195 myrpt->patchnoct = 0;
06196 myrpt->patchdialtime = 0;
06197 myrpt->patchfarenddisconnect = 0;
06198 myrpt->patchquiet = 0;
06199 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06200
06201 if(param){
06202
06203 lparam = ast_strdup(param);
06204 if(!lparam){
06205 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06206 return DC_ERROR;
06207 }
06208 paramlength = finddelim(lparam, paramlist, 20);
06209 for(i = 0; i < paramlength; i++){
06210 idx = matchkeyword(paramlist[i], &value, keywords);
06211 if(value)
06212 value = skipchars(value, "= ");
06213 switch(idx){
06214
06215 case 1:
06216 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06217 break;
06218
06219 case 2:
06220 myrpt->patchdialtime = atoi(value);
06221 break;
06222
06223 case 3:
06224 myrpt->patchfarenddisconnect = atoi(value);
06225 break;
06226
06227 case 4:
06228 myrpt->patchnoct = atoi(value);
06229 break;
06230
06231 case 5:
06232 myrpt->patchquiet = atoi(value);
06233 break;
06234
06235 default:
06236 break;
06237 }
06238 }
06239 ast_free(lparam);
06240 }
06241 }
06242
06243 rpt_mutex_lock(&myrpt->lock);
06244
06245
06246
06247 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06248 myrpt->mydtmf = myrpt->p.endchar;
06249 }
06250 if (myrpt->callmode){
06251 rpt_mutex_unlock(&myrpt->lock);
06252 return DC_COMPLETE;
06253 }
06254 myrpt->callmode = 1;
06255 myrpt->cidx = 0;
06256 myrpt->exten[myrpt->cidx] = 0;
06257 rpt_mutex_unlock(&myrpt->lock);
06258 pthread_attr_init(&attr);
06259 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06260 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06261 return DC_COMPLETE;
06262 }
06263
06264
06265
06266
06267
06268 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06269 {
06270 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06271 return DC_ERROR;
06272
06273 if(debug)
06274 printf("@@@@ Autopatch down\n");
06275
06276 rpt_mutex_lock(&myrpt->lock);
06277
06278 myrpt->macropatch=0;
06279
06280 if (!myrpt->callmode){
06281 rpt_mutex_unlock(&myrpt->lock);
06282 return DC_COMPLETE;
06283 }
06284
06285 myrpt->callmode = 0;
06286 channel_revert(myrpt);
06287 rpt_mutex_unlock(&myrpt->lock);
06288 rpt_telemetry(myrpt, TERM, NULL);
06289 return DC_COMPLETE;
06290 }
06291
06292
06293
06294
06295
06296 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06297 {
06298
06299 if (!param)
06300 return DC_ERROR;
06301
06302 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06303 return DC_ERROR;
06304
06305 if(debug)
06306 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06307
06308 switch(myatoi(param)){
06309 case 1:
06310 rpt_telemetry(myrpt, ID1, NULL);
06311 return DC_COMPLETE;
06312 case 2:
06313 rpt_telemetry(myrpt, STATS_TIME, NULL);
06314 return DC_COMPLETE;
06315 case 3:
06316 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06317 return DC_COMPLETE;
06318 case 11:
06319 rpt_telemetry(myrpt, ID , NULL);
06320 return DC_COMPLETE;
06321 case 12:
06322 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06323 return DC_COMPLETE;
06324 default:
06325 return DC_ERROR;
06326 }
06327 return DC_INDETERMINATE;
06328 }
06329
06330
06331
06332 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06333 {
06334 char *val;
06335 int i;
06336 if (myrpt->remote)
06337 return DC_ERROR;
06338
06339 if(debug)
06340 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06341
06342 if(strlen(digitbuf) < 1)
06343 return DC_INDETERMINATE;
06344
06345 for(i = 0 ; i < digitbuf[i] ; i++) {
06346 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06347 return DC_ERROR;
06348 }
06349
06350 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06351 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06352
06353 if (!val){
06354 if (strlen(digitbuf) < myrpt->macro_longest)
06355 return DC_INDETERMINATE;
06356 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06357 return DC_COMPLETE;
06358 }
06359 rpt_mutex_lock(&myrpt->lock);
06360 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06361 {
06362 rpt_mutex_unlock(&myrpt->lock);
06363 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06364 return DC_ERROR;
06365 }
06366 myrpt->macrotimer = MACROTIME;
06367 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06368 rpt_mutex_unlock(&myrpt->lock);
06369 return DC_COMPLETE;
06370 }
06371
06372
06373
06374
06375
06376 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06377 {
06378
06379 if (myrpt->remote)
06380 return DC_ERROR;
06381
06382 if(debug)
06383 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06384
06385 if (ast_fileexists(param,NULL,ast_channel_language(myrpt->rxchannel)) <= 0)
06386 return DC_ERROR;
06387
06388 rpt_telemetry(myrpt,PLAYBACK,param);
06389 return DC_COMPLETE;
06390 }
06391
06392
06393
06394
06395
06396 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06397 {
06398 char string[16];
06399 int res;
06400
06401 int i, r;
06402
06403 if(!param)
06404 return DC_ERROR;
06405
06406 switch(myatoi(param)){
06407 case 1:
06408 res = system("killall -9 asterisk");
06409 return DC_COMPLETE;
06410
06411 case 2:
06412 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06413 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06414 return DC_COMPLETE;
06415
06416 case 3:
06417 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06418 return DC_COMPLETE;
06419
06420 case 4:
06421 if (myrpt->stopgen < 0)
06422 {
06423 myrpt->stopgen = 1;
06424 }
06425 else
06426 {
06427 myrpt->stopgen = 0;
06428 rpt_telemetry(myrpt, TEST_TONE, NULL);
06429 }
06430 return DC_COMPLETE;
06431
06432 case 5:
06433 myrpt->disgorgetime = time(NULL) + 10;
06434 return DC_COMPLETE;
06435
06436 case 6:
06437 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06438 return DC_DOKEY;
06439
06440
06441 case 7:
06442 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06443 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06444 return DC_COMPLETE;
06445
06446 case 8:
06447 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06448 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06449 return DC_COMPLETE;
06450
06451 case 9:
06452 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06453 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06454 return DC_COMPLETE;
06455
06456 case 10:
06457 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06458 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06459 return DC_COMPLETE;
06460
06461 case 11:
06462 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06463 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06464 return DC_COMPLETE;
06465
06466 case 12:
06467 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06468 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06469 return DC_COMPLETE;
06470
06471 case 13:
06472 string[0] = string[1] = 'S';
06473 string[2] = myrpt->p.sysstate_cur + '0';
06474 string[3] = '\0';
06475 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06476 return DC_COMPLETE;
06477
06478 case 14:
06479 if(strlen(digitbuf) == 0)
06480 break;
06481 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06482 return DC_ERROR;
06483 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06484 string[0] = string[1] = 'S';
06485 string[2] = myrpt->p.sysstate_cur + '0';
06486 string[3] = '\0';
06487 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06488 return DC_COMPLETE;
06489
06490 case 15:
06491 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06492 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06493 return DC_COMPLETE;
06494
06495 case 16:
06496 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06497 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06498 return DC_COMPLETE;
06499
06500 case 17:
06501 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06502 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06503 return DC_COMPLETE;
06504
06505 case 18:
06506 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06507 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06508 return DC_COMPLETE;
06509
06510 case 19:
06511 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06512 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06513 return DC_COMPLETE;
06514
06515 case 20:
06516 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06517 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06518 return DC_COMPLETE;
06519
06520 case 21:
06521 birdbath(myrpt);
06522 if (myrpt->p.parrotmode < 2)
06523 {
06524 myrpt->p.parrotmode = 0;
06525 rpt_telemetry(myrpt,COMPLETE,NULL);
06526 return DC_COMPLETE;
06527 }
06528 break;
06529
06530 case 22:
06531 birdbath(myrpt);
06532 if (myrpt->p.parrotmode < 2)
06533 {
06534 myrpt->p.parrotmode = 1;
06535 rpt_telemetry(myrpt,COMPLETE,NULL);
06536 return DC_COMPLETE;
06537 }
06538 break;
06539 case 23:
06540 birdbath(myrpt);
06541 rpt_telemetry(myrpt,COMPLETE,NULL);
06542 return DC_COMPLETE;
06543 case 24:
06544 flush_telem(myrpt);
06545 rpt_telemetry(myrpt,COMPLETE,NULL);
06546 return DC_COMPLETE;
06547 case 25:
06548 send_link_keyquery(myrpt);
06549 myrpt->topkeylong = 0;
06550 rpt_telemetry(myrpt,COMPLETE,NULL);
06551 return DC_COMPLETE;
06552 case 26:
06553 send_link_keyquery(myrpt);
06554 myrpt->topkeylong = 1;
06555 rpt_telemetry(myrpt,COMPLETE,NULL);
06556 return DC_COMPLETE;
06557
06558 case 30:
06559
06560 if(strlen(digitbuf) < 2)
06561 break;
06562
06563 for(i = 0 ; i < 2 ; i++){
06564 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06565 return DC_ERROR;
06566 }
06567
06568 r = retreive_memory(myrpt, digitbuf);
06569 if (r < 0){
06570 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06571 return DC_COMPLETE;
06572 }
06573 if (r > 0){
06574 return DC_ERROR;
06575 }
06576 if (setrem(myrpt) == -1) return DC_ERROR;
06577 return DC_COMPLETE;
06578
06579 case 31:
06580
06581
06582 if(strlen(digitbuf) < 2)
06583 break;
06584
06585 for(i = 0 ; i < 2 ; i++){
06586 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06587 return DC_ERROR;
06588 }
06589 channel_steer(myrpt,digitbuf);
06590 return DC_COMPLETE;
06591
06592 case 32:
06593 i = strlen(digitbuf);
06594 if(!i){
06595 if(debug > 3)
06596 ast_log(LOG_NOTICE,"Padtest entered");
06597 myrpt->inpadtest = 1;
06598 }
06599 else{
06600 if(debug > 3)
06601 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06602 if(digitbuf[i-1] != myrpt->p.endchar)
06603 break;
06604 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06605 myrpt->inpadtest = 0;
06606 if(debug > 3)
06607 ast_log(LOG_NOTICE,"Padtest exited");
06608 return DC_COMPLETE;
06609 }
06610 }
06611 return DC_INDETERMINATE;
06612 }
06613
06614
06615
06616 static int collect_function_digits(struct rpt *myrpt, char *digits,
06617 int command_source, struct rpt_link *mylink)
06618 {
06619 int i,rv;
06620 char *stringp,*action,*param,*functiondigits;
06621 char function_table_name[30] = "";
06622 char workstring[200];
06623
06624 struct ast_variable *vp;
06625
06626 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06627
06628
06629
06630
06631 if (command_source == SOURCE_DPHONE) {
06632 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06633 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06634 }
06635 else if (command_source == SOURCE_ALT) {
06636 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06637 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06638 }
06639 else if (command_source == SOURCE_PHONE) {
06640 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06641 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06642 }
06643 else if (command_source == SOURCE_LNK)
06644 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06645 else
06646 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06647
06648 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06649 while(vp) {
06650 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06651 break;
06652 vp = vp->next;
06653 }
06654
06655 if(!vp) {
06656 int n;
06657
06658 n = myrpt->longestfunc;
06659 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06660 else
06661 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06662 else
06663 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06664 else
06665 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06666
06667 if(strlen(digits) >= n)
06668 return DC_ERROR;
06669 else
06670 return DC_INDETERMINATE;
06671 }
06672
06673 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06674 stringp = workstring;
06675 action = strsep(&stringp, ",");
06676 param = stringp;
06677 if(debug)
06678 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06679
06680 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06681 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06682 break;
06683 }
06684 if(debug)
06685 printf("@@@@ table index i = %d\n",i);
06686 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06687
06688 return DC_ERROR;
06689 }
06690 if(function_table[i].function == NULL){
06691
06692 if(debug)
06693 printf("@@@@ NULL for action: %s\n",action);
06694 return DC_ERROR;
06695 }
06696 functiondigits = digits + strlen(vp->name);
06697 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06698 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06699 return(rv);
06700 }
06701
06702
06703 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06704 char *str)
06705 {
06706
06707
06708 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06709 int i,seq, res, ts;
06710 struct rpt_link *l;
06711 struct ast_frame wf;
06712
06713 wf.frametype = AST_FRAME_TEXT;
06714 wf.subclass.integer = 0;
06715 wf.offset = 0;
06716 wf.mallocd = 0;
06717 wf.datalen = strlen(str) + 1;
06718 wf.samples = 0;
06719
06720 strncpy(tmp,str,sizeof(tmp) - 1);
06721
06722 if (!strcmp(tmp,discstr))
06723 {
06724 mylink->disced = 1;
06725 mylink->retries = mylink->max_retries + 1;
06726 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06727 return;
06728 }
06729 if (!strcmp(tmp,newkeystr))
06730 {
06731 mylink->newkey = 1;
06732 return;
06733 }
06734 if (tmp[0] == 'L')
06735 {
06736 rpt_mutex_lock(&myrpt->lock);
06737 strcpy(mylink->linklist,tmp + 2);
06738 time(&mylink->linklistreceived);
06739 rpt_mutex_unlock(&myrpt->lock);
06740 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06741 myrpt->name,tmp,mylink->name);
06742 return;
06743 }
06744 if (tmp[0] == 'K')
06745 {
06746 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06747 {
06748 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06749 return;
06750 }
06751 if (dest[0] == '0')
06752 {
06753 strcpy(dest,myrpt->name);
06754 }
06755
06756 if (strcmp(dest,myrpt->name))
06757 {
06758 l = myrpt->links.next;
06759
06760 while(l != &myrpt->links)
06761 {
06762 if (l->name[0] == '0')
06763 {
06764 l = l->next;
06765 continue;
06766 }
06767
06768 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06769 {
06770 l = l->next;
06771 continue;
06772 }
06773
06774 if (!strcmp(l->name,dest))
06775 {
06776
06777 if (strcmp(l->name,src)) {
06778 wf.data.ptr = str;
06779 if (l->chan) ast_write(l->chan,&wf);
06780 }
06781 return;
06782 }
06783 l = l->next;
06784 }
06785 }
06786
06787 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06788 {
06789 l = myrpt->links.next;
06790
06791 while(l != &myrpt->links)
06792 {
06793 if (l->name[0] == '0')
06794 {
06795 l = l->next;
06796 continue;
06797 }
06798
06799 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06800 {
06801 l = l->next;
06802 continue;
06803 }
06804
06805 if (strcmp(l->name,src)) {
06806 wf.data.ptr = str;
06807 if (l->chan) ast_write(l->chan,&wf);
06808 }
06809 l = l->next;
06810 }
06811 }
06812
06813 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06814 if (cmd[1] == '?')
06815 {
06816 time_t now;
06817 int n = 0;
06818
06819 time(&now);
06820 if (myrpt->lastkeyedtime)
06821 {
06822 n = (int)(now - myrpt->lastkeyedtime);
06823 }
06824 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06825 wf.data.ptr = tmp1;
06826 wf.datalen = strlen(tmp1) + 1;
06827 if (mylink->chan) ast_write(mylink->chan,&wf);
06828 return;
06829 }
06830 if (myrpt->topkeystate != 1) return;
06831 rpt_mutex_lock(&myrpt->lock);
06832 for(i = 0; i < TOPKEYN; i++)
06833 {
06834 if (!strcmp(myrpt->topkey[i].node,src)) break;
06835 }
06836 if (i >= TOPKEYN)
06837 {
06838 for(i = 0; i < TOPKEYN; i++)
06839 {
06840 if (!myrpt->topkey[i].node[0]) break;
06841 }
06842 }
06843 if (i < TOPKEYN)
06844 {
06845 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06846 myrpt->topkey[i].timesince = ts;
06847 myrpt->topkey[i].keyed = seq;
06848 }
06849 rpt_mutex_unlock(&myrpt->lock);
06850 return;
06851 }
06852 if (tmp[0] == 'I')
06853 {
06854
06855
06856 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06857 {
06858 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06859 return;
06860 }
06861 mdc1200_notify(myrpt,src,seq);
06862 strcpy(dest,"*");
06863 }
06864 else
06865 {
06866
06867
06868 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06869 {
06870 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06871 return;
06872 }
06873 if (strcmp(cmd,"D"))
06874 {
06875 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06876 return;
06877 }
06878 }
06879 if (dest[0] == '0')
06880 {
06881 strcpy(dest,myrpt->name);
06882 }
06883
06884
06885 if (strcmp(dest,myrpt->name))
06886 {
06887 l = myrpt->links.next;
06888
06889 while(l != &myrpt->links)
06890 {
06891 if (l->name[0] == '0')
06892 {
06893 l = l->next;
06894 continue;
06895 }
06896
06897 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06898 {
06899 l = l->next;
06900 continue;
06901 }
06902
06903 if (!strcmp(l->name,dest))
06904 {
06905
06906 if (strcmp(l->name,src)) {
06907 wf.data.ptr = str;
06908 if (l->chan) ast_write(l->chan,&wf);
06909 }
06910 return;
06911 }
06912 l = l->next;
06913 }
06914 l = myrpt->links.next;
06915
06916 while(l != &myrpt->links)
06917 {
06918 if (l->name[0] == '0')
06919 {
06920 l = l->next;
06921 continue;
06922 }
06923
06924 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06925 {
06926 l = l->next;
06927 continue;
06928 }
06929
06930 if (strcmp(l->name,src)) {
06931 wf.data.ptr = str;
06932 if (l->chan) ast_write(l->chan,&wf);
06933 }
06934 l = l->next;
06935 }
06936 return;
06937 }
06938 if (myrpt->p.archivedir)
06939 {
06940 char dtmfstr[100];
06941
06942 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06943 donodelog(myrpt,dtmfstr);
06944 }
06945 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06946 if (!c) return;
06947 rpt_mutex_lock(&myrpt->lock);
06948 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06949 if (myrpt->callmode == 1)
06950 {
06951 myrpt->exten[myrpt->cidx++] = c;
06952 myrpt->exten[myrpt->cidx] = 0;
06953
06954 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06955 {
06956
06957 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06958 myrpt->exten,1,NULL))
06959 {
06960 myrpt->callmode = 2;
06961 if(!myrpt->patchquiet)
06962 {
06963 rpt_mutex_unlock(&myrpt->lock);
06964 rpt_telemetry(myrpt,PROC,NULL);
06965 rpt_mutex_lock(&myrpt->lock);
06966 }
06967 }
06968 else
06969 {
06970 myrpt->calldigittimer = 1;
06971 }
06972 }
06973
06974 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06975 {
06976
06977 myrpt->callmode = 4;
06978 }
06979 }
06980 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06981 {
06982 myrpt->rem_dtmfidx = 0;
06983 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06984 time(&myrpt->rem_dtmf_time);
06985 rpt_mutex_unlock(&myrpt->lock);
06986 return;
06987 }
06988 else if (myrpt->rem_dtmfidx < 0)
06989 {
06990 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06991 {
06992 myrpt->mydtmf = c;
06993 }
06994 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06995 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06996 rpt_mutex_unlock(&myrpt->lock);
06997 return;
06998 }
06999 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07000 {
07001 time(&myrpt->rem_dtmf_time);
07002 if (myrpt->rem_dtmfidx < MAXDTMF)
07003 {
07004 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07005 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07006
07007 rpt_mutex_unlock(&myrpt->lock);
07008 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07009 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
07010 rpt_mutex_lock(&myrpt->lock);
07011
07012 switch(res){
07013
07014 case DC_INDETERMINATE:
07015 break;
07016
07017 case DC_REQ_FLUSH:
07018 myrpt->rem_dtmfidx = 0;
07019 myrpt->rem_dtmfbuf[0] = 0;
07020 break;
07021
07022
07023 case DC_COMPLETE:
07024 case DC_COMPLETEQUIET:
07025 myrpt->totalexecdcommands++;
07026 myrpt->dailyexecdcommands++;
07027 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07028 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07029 myrpt->rem_dtmfbuf[0] = 0;
07030 myrpt->rem_dtmfidx = -1;
07031 myrpt->rem_dtmf_time = 0;
07032 break;
07033
07034 case DC_ERROR:
07035 default:
07036 myrpt->rem_dtmfbuf[0] = 0;
07037 myrpt->rem_dtmfidx = -1;
07038 myrpt->rem_dtmf_time = 0;
07039 break;
07040 }
07041 }
07042
07043 }
07044 rpt_mutex_unlock(&myrpt->lock);
07045 return;
07046 }
07047
07048 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07049 char c)
07050 {
07051
07052 char cmd[300];
07053 int res;
07054
07055 if (myrpt->p.archivedir)
07056 {
07057 char str[100];
07058
07059 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07060 donodelog(myrpt,str);
07061 }
07062 rpt_mutex_lock(&myrpt->lock);
07063
07064 if (mylink->phonemode == 3)
07065 {
07066 if(c == myrpt->p.endchar)
07067 {
07068 mylink->lastrealrx = 0;
07069 rpt_mutex_unlock(&myrpt->lock);
07070 return;
07071 }
07072
07073 if(c == myrpt->p.funcchar)
07074 {
07075 mylink->lastrealrx = !mylink->lastrealrx;
07076 rpt_mutex_unlock(&myrpt->lock);
07077 return;
07078 }
07079 }
07080 else
07081 {
07082 if (c == myrpt->p.endchar)
07083 {
07084 if (mylink->lastrx)
07085 {
07086 mylink->lastrealrx = 0;
07087 rpt_mutex_unlock(&myrpt->lock);
07088 return;
07089 }
07090 myrpt->stopgen = 1;
07091 if (myrpt->cmdnode[0])
07092 {
07093 myrpt->cmdnode[0] = 0;
07094 myrpt->dtmfidx = -1;
07095 myrpt->dtmfbuf[0] = 0;
07096 rpt_mutex_unlock(&myrpt->lock);
07097 rpt_telemetry(myrpt,COMPLETE,NULL);
07098 return;
07099 }
07100 }
07101 }
07102 if (myrpt->cmdnode[0])
07103 {
07104 rpt_mutex_unlock(&myrpt->lock);
07105 send_link_dtmf(myrpt,c);
07106 return;
07107 }
07108 if (myrpt->callmode == 1)
07109 {
07110 myrpt->exten[myrpt->cidx++] = c;
07111 myrpt->exten[myrpt->cidx] = 0;
07112
07113 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07114 {
07115
07116 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07117 myrpt->exten,1,NULL))
07118 {
07119 myrpt->callmode = 2;
07120 if(!myrpt->patchquiet)
07121 {
07122 rpt_mutex_unlock(&myrpt->lock);
07123 rpt_telemetry(myrpt,PROC,NULL);
07124 rpt_mutex_lock(&myrpt->lock);
07125 }
07126 }
07127 else
07128 {
07129 myrpt->calldigittimer = 1;
07130 }
07131 }
07132
07133 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07134 {
07135
07136 myrpt->callmode = 4;
07137 }
07138 }
07139 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07140 {
07141 myrpt->mydtmf = c;
07142 }
07143 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07144 {
07145 myrpt->rem_dtmfidx = 0;
07146 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07147 time(&myrpt->rem_dtmf_time);
07148 rpt_mutex_unlock(&myrpt->lock);
07149 return;
07150 }
07151 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07152 {
07153 time(&myrpt->rem_dtmf_time);
07154 if (myrpt->rem_dtmfidx < MAXDTMF)
07155 {
07156 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07157 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07158
07159 rpt_mutex_unlock(&myrpt->lock);
07160 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07161 switch(mylink->phonemode)
07162 {
07163 case 1:
07164 res = collect_function_digits(myrpt, cmd,
07165 SOURCE_PHONE, mylink);
07166 break;
07167 case 2:
07168 res = collect_function_digits(myrpt, cmd,
07169 SOURCE_DPHONE,mylink);
07170 break;
07171 case 4:
07172 res = collect_function_digits(myrpt, cmd,
07173 SOURCE_ALT,mylink);
07174 break;
07175 default:
07176 res = collect_function_digits(myrpt, cmd,
07177 SOURCE_LNK, mylink);
07178 break;
07179 }
07180
07181 rpt_mutex_lock(&myrpt->lock);
07182
07183 switch(res){
07184
07185 case DC_INDETERMINATE:
07186 break;
07187
07188 case DC_DOKEY:
07189 mylink->lastrealrx = 1;
07190 break;
07191
07192 case DC_REQ_FLUSH:
07193 myrpt->rem_dtmfidx = 0;
07194 myrpt->rem_dtmfbuf[0] = 0;
07195 break;
07196
07197
07198 case DC_COMPLETE:
07199 case DC_COMPLETEQUIET:
07200 myrpt->totalexecdcommands++;
07201 myrpt->dailyexecdcommands++;
07202 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07203 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07204 myrpt->rem_dtmfbuf[0] = 0;
07205 myrpt->rem_dtmfidx = -1;
07206 myrpt->rem_dtmf_time = 0;
07207 break;
07208
07209 case DC_ERROR:
07210 default:
07211 myrpt->rem_dtmfbuf[0] = 0;
07212 myrpt->rem_dtmfidx = -1;
07213 myrpt->rem_dtmf_time = 0;
07214 break;
07215 }
07216 }
07217
07218 }
07219 rpt_mutex_unlock(&myrpt->lock);
07220 return;
07221 }
07222
07223
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233
07234
07235
07236
07237
07238
07239
07240
07241
07242
07243
07244
07245
07246
07247
07248
07249
07250
07251
07252
07253
07254 static int rbi_mhztoband(char *str)
07255 {
07256 int i;
07257
07258 i = atoi(str) / 10;
07259 switch(i)
07260 {
07261 case 2:
07262 return 10;
07263 case 5:
07264 return 11;
07265 case 14:
07266 return 2;
07267 case 22:
07268 return 3;
07269 case 44:
07270 return 4;
07271 case 124:
07272 return 0;
07273 case 125:
07274 return 1;
07275 case 126:
07276 return 8;
07277 case 127:
07278 return 5;
07279 case 128:
07280 return 6;
07281 case 129:
07282 return 7;
07283 default:
07284 break;
07285 }
07286 return -1;
07287 }
07288
07289
07290 static int rbi_pltocode(char *str)
07291 {
07292 int i;
07293 char *s;
07294
07295 s = strchr(str,'.');
07296 i = 0;
07297 if (s) i = atoi(s + 1);
07298 i += atoi(str) * 10;
07299 switch(i)
07300 {
07301 case 670:
07302 return 0;
07303 case 719:
07304 return 1;
07305 case 744:
07306 return 2;
07307 case 770:
07308 return 3;
07309 case 797:
07310 return 4;
07311 case 825:
07312 return 5;
07313 case 854:
07314 return 6;
07315 case 885:
07316 return 7;
07317 case 915:
07318 return 8;
07319 case 948:
07320 return 9;
07321 case 974:
07322 return 10;
07323 case 1000:
07324 return 11;
07325 case 1035:
07326 return 12;
07327 case 1072:
07328 return 13;
07329 case 1109:
07330 return 14;
07331 case 1148:
07332 return 15;
07333 case 1188:
07334 return 16;
07335 case 1230:
07336 return 17;
07337 case 1273:
07338 return 18;
07339 case 1318:
07340 return 19;
07341 case 1365:
07342 return 20;
07343 case 1413:
07344 return 21;
07345 case 1462:
07346 return 22;
07347 case 1514:
07348 return 23;
07349 case 1567:
07350 return 24;
07351 case 1622:
07352 return 25;
07353 case 1679:
07354 return 26;
07355 case 1738:
07356 return 27;
07357 case 1799:
07358 return 28;
07359 case 1862:
07360 return 29;
07361 case 1928:
07362 return 30;
07363 case 2035:
07364 return 31;
07365 case 2107:
07366 return 32;
07367 case 2181:
07368 return 33;
07369 case 2257:
07370 return 34;
07371 case 2336:
07372 return 35;
07373 case 2418:
07374 return 36;
07375 case 2503:
07376 return 37;
07377 }
07378 return -1;
07379 }
07380
07381
07382
07383
07384
07385 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07386 {
07387 #ifdef __i386__
07388 int i,j;
07389 unsigned char od,d;
07390 static volatile long long delayvar;
07391
07392 for(i = 0 ; i < 5 ; i++){
07393 od = *data++;
07394 for(j = 0 ; j < 8 ; j++){
07395 d = od & 1;
07396 outb(d,myrpt->p.iobase);
07397
07398 for(delayvar = 1; delayvar < 15000; delayvar++);
07399 od >>= 1;
07400 outb(d | 2,myrpt->p.iobase);
07401
07402 for(delayvar = 1; delayvar < 30000; delayvar++);
07403 outb(d,myrpt->p.iobase);
07404
07405 for(delayvar = 1; delayvar < 10000; delayvar++);
07406 }
07407 }
07408
07409 for(delayvar = 1; delayvar < 50000; delayvar++);
07410 #endif
07411 }
07412
07413 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07414 {
07415 struct dahdi_radio_param r;
07416
07417 memset(&r,0,sizeof(struct dahdi_radio_param));
07418 r.radpar = DAHDI_RADPAR_REMMODE;
07419 r.data = DAHDI_RADPAR_REM_RBI1;
07420
07421 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07422 {
07423 rbi_out_parallel(myrpt,data);
07424 return;
07425 }
07426 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07427 memcpy(&r.data,data,5);
07428 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07429 {
07430 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",ast_channel_name(myrpt->dahdirxchannel));
07431 return;
07432 }
07433 }
07434
07435 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07436 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07437 {
07438 int i,j,idx,oldmode,olddata;
07439 struct dahdi_radio_param prm;
07440 char c;
07441
07442 if(debug) {
07443 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07444 printf("String output was:\n");
07445 for(i = 0; i < txbytes; i++)
07446 printf("%02X ", (unsigned char ) txbuf[i]);
07447 printf("\n");
07448 }
07449
07450 if (myrpt->iofd >= 0)
07451 {
07452 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07453 {
07454 return -1;
07455 }
07456 if ((!rxmaxbytes) || (rxbuf == NULL))
07457 {
07458 return(0);
07459 }
07460 memset(rxbuf,0,rxmaxbytes);
07461 for(i = 0; i < rxmaxbytes; i++)
07462 {
07463 j = read(myrpt->iofd,&c,1);
07464 if (j < 1)
07465 {
07466 return(i);
07467 }
07468 rxbuf[i] = c;
07469 if (asciiflag & 1)
07470 {
07471 rxbuf[i + 1] = 0;
07472 if (c == '\r') break;
07473 }
07474 }
07475 if(debug) {
07476 printf("String returned was:\n");
07477 for(j = 0; j < i; j++)
07478 printf("%02X ", (unsigned char ) rxbuf[j]);
07479 printf("\n");
07480 }
07481 return(i);
07482 }
07483
07484
07485 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07486
07487 prm.radpar = DAHDI_RADPAR_UIOMODE;
07488 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07489 oldmode = prm.data;
07490 prm.radpar = DAHDI_RADPAR_UIODATA;
07491 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07492 olddata = prm.data;
07493 prm.radpar = DAHDI_RADPAR_REMMODE;
07494 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07495 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07496 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07497 if (asciiflag & 2)
07498 {
07499 i = DAHDI_ONHOOK;
07500 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07501 usleep(100000);
07502 }
07503 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07504 prm.data = rxmaxbytes;
07505 memcpy(prm.buf,txbuf,txbytes);
07506 prm.index = txbytes;
07507 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07508 if (rxbuf)
07509 {
07510 *rxbuf = 0;
07511 memcpy(rxbuf,prm.buf,prm.index);
07512 }
07513 idx = prm.index;
07514 prm.radpar = DAHDI_RADPAR_REMMODE;
07515 prm.data = DAHDI_RADPAR_REM_NONE;
07516 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07517 if (asciiflag & 2)
07518 {
07519 i = DAHDI_OFFHOOK;
07520 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07521 }
07522 prm.radpar = DAHDI_RADPAR_UIOMODE;
07523 prm.data = oldmode;
07524 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07525 prm.radpar = DAHDI_RADPAR_UIODATA;
07526 prm.data = olddata;
07527 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07528 return(idx);
07529 }
07530
07531 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07532 {
07533 unsigned char rxbuf[100];
07534 int i,rv ;
07535
07536 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07537 if (rv == -1) return(-1);
07538 if (rv != (cmdlen + 6)) return(1);
07539 for(i = 0; i < 6; i++)
07540 if (rxbuf[i] != cmd[i]) return(1);
07541 if (rxbuf[cmdlen] != 0xfe) return(1);
07542 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07543 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07544 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07545 return(0);
07546 }
07547
07548 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07549 {
07550 int i;
07551
07552 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07553 if (debug) printf("Send to kenwood: %s\n",txstr);
07554 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07555 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07556 if (i < 0) return -1;
07557 if ((i > 0) && (rxstr[i - 1] == '\r'))
07558 rxstr[i-- - 1] = 0;
07559 if (debug) printf("Got from kenwood: %s\n",rxstr);
07560 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07561 return(i);
07562 }
07563
07564
07565 static int kenwood_pltocode(char *str)
07566 {
07567 int i;
07568 char *s;
07569
07570 s = strchr(str,'.');
07571 i = 0;
07572 if (s) i = atoi(s + 1);
07573 i += atoi(str) * 10;
07574 switch(i)
07575 {
07576 case 670:
07577 return 1;
07578 case 719:
07579 return 3;
07580 case 744:
07581 return 4;
07582 case 770:
07583 return 5;
07584 case 797:
07585 return 6;
07586 case 825:
07587 return 7;
07588 case 854:
07589 return 8;
07590 case 885:
07591 return 9;
07592 case 915:
07593 return 10;
07594 case 948:
07595 return 11;
07596 case 974:
07597 return 12;
07598 case 1000:
07599 return 13;
07600 case 1035:
07601 return 14;
07602 case 1072:
07603 return 15;
07604 case 1109:
07605 return 16;
07606 case 1148:
07607 return 17;
07608 case 1188:
07609 return 18;
07610 case 1230:
07611 return 19;
07612 case 1273:
07613 return 20;
07614 case 1318:
07615 return 21;
07616 case 1365:
07617 return 22;
07618 case 1413:
07619 return 23;
07620 case 1462:
07621 return 24;
07622 case 1514:
07623 return 25;
07624 case 1567:
07625 return 26;
07626 case 1622:
07627 return 27;
07628 case 1679:
07629 return 28;
07630 case 1738:
07631 return 29;
07632 case 1799:
07633 return 30;
07634 case 1862:
07635 return 31;
07636 case 1928:
07637 return 32;
07638 case 2035:
07639 return 33;
07640 case 2107:
07641 return 34;
07642 case 2181:
07643 return 35;
07644 case 2257:
07645 return 36;
07646 case 2336:
07647 return 37;
07648 case 2418:
07649 return 38;
07650 case 2503:
07651 return 39;
07652 }
07653 return -1;
07654 }
07655
07656 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07657 char *cmpstr)
07658 {
07659 int i,j;
07660
07661 for(i = 0;i < KENWOOD_RETRIES;i++)
07662 {
07663 j = sendkenwood(myrpt,txstr,rxstr);
07664 if (j < 0) return(j);
07665 if (j == 0) continue;
07666 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07667 }
07668 return(-1);
07669 }
07670
07671 static int setkenwood(struct rpt *myrpt)
07672 {
07673 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07674 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07675 int myrxpl;
07676
07677 int offsets[] = {0,2,1};
07678 int powers[] = {2,1,0};
07679
07680 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07681 split_freq(mhz, decimals, myrpt->freq);
07682 if (atoi(mhz) > 400)
07683 {
07684 band = '6';
07685 band1 = '1';
07686 band2 = '5';
07687 strcpy(offset,"005000000");
07688 }
07689 else
07690 {
07691 band = '2';
07692 band1 = '0';
07693 band2 = '2';
07694 strcpy(offset,"000600000");
07695 }
07696 strcpy(freq,"000000");
07697 strncpy(freq,decimals,strlen(decimals));
07698 myrxpl = myrpt->rxplon;
07699 if (IS_XPMR(myrpt)) myrxpl = 0;
07700 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07701 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07702 (myrpt->txplon != 0),myrxpl,
07703 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07704 offset);
07705 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07706 sprintf(txstr,"RBN %c\r",band2);
07707 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07708 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07709 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07710 return 0;
07711 }
07712
07713 static int set_tm271(struct rpt *myrpt)
07714 {
07715 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07716 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07717
07718 int offsets[] = {0,2,1};
07719 int powers[] = {2,1,0};
07720
07721 split_freq(mhz, decimals, myrpt->freq);
07722 strcpy(freq,"000000");
07723 strncpy(freq,decimals,strlen(decimals));
07724
07725 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07726 atoi(mhz),freq,offsets[(int)myrpt->offset],
07727 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07728 kenwood_pltocode(myrpt->rxpl));
07729
07730 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07731 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07732 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07733 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07734 return 0;
07735 }
07736
07737 static int setrbi(struct rpt *myrpt)
07738 {
07739 char tmp[MAXREMSTR] = "",*s;
07740 unsigned char rbicmd[5];
07741 int band,txoffset = 0,txpower = 0,rxpl;
07742
07743
07744 if (!myrpt->remoterig) return(0);
07745 if (!myrpt->remoterig[0]) return(0);
07746
07747 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07748 if (setrbi_check(myrpt) == -1) return(-1);
07749 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07750 s = strchr(tmp,'.');
07751
07752
07753 if (s == NULL){
07754 if(debug)
07755 printf("@@@@ Frequency needs a decimal\n");
07756 return -1;
07757 }
07758
07759 *s++ = 0;
07760 if (strlen(tmp) < 2){
07761 if(debug)
07762 printf("@@@@ Bad MHz digits: %s\n", tmp);
07763 return -1;
07764 }
07765
07766 if (strlen(s) < 3){
07767 if(debug)
07768 printf("@@@@ Bad KHz digits: %s\n", s);
07769 return -1;
07770 }
07771
07772 if ((s[2] != '0') && (s[2] != '5')){
07773 if(debug)
07774 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07775 return -1;
07776 }
07777
07778 band = rbi_mhztoband(tmp);
07779 if (band == -1){
07780 if(debug)
07781 printf("@@@@ Bad Band: %s\n", tmp);
07782 return -1;
07783 }
07784
07785 rxpl = rbi_pltocode(myrpt->rxpl);
07786
07787 if (rxpl == -1){
07788 if(debug)
07789 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07790 return -1;
07791 }
07792
07793
07794 switch(myrpt->offset)
07795 {
07796 case REM_MINUS:
07797 txoffset = 0;
07798 break;
07799 case REM_PLUS:
07800 txoffset = 0x10;
07801 break;
07802 case REM_SIMPLEX:
07803 txoffset = 0x20;
07804 break;
07805 }
07806 switch(myrpt->powerlevel)
07807 {
07808 case REM_LOWPWR:
07809 txpower = 0;
07810 break;
07811 case REM_MEDPWR:
07812 txpower = 0x20;
07813 break;
07814 case REM_HIPWR:
07815 txpower = 0x10;
07816 break;
07817 }
07818 rbicmd[0] = 0;
07819 rbicmd[1] = band | txpower | 0xc0;
07820 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07821 if (s[2] == '5') rbicmd[2] |= 0x40;
07822 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07823 rbicmd[4] = rxpl;
07824 if (myrpt->txplon) rbicmd[4] |= 0x40;
07825 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07826 rbi_out(myrpt,rbicmd);
07827 return 0;
07828 }
07829
07830 static int setrtx(struct rpt *myrpt)
07831 {
07832 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07833 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07834 float ofac;
07835 double txfreq;
07836
07837
07838 if (!myrpt->remoterig) return(0);
07839 if (!myrpt->remoterig[0]) return(0);
07840
07841 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07842
07843 if (!IS_XPMR(myrpt)) return(0);
07844 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07845 s = strchr(tmp,'.');
07846
07847
07848 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07849
07850 if (s == NULL){
07851 if(debug)
07852 printf("@@@@ Frequency needs a decimal\n");
07853 return -1;
07854 }
07855 *s++ = 0;
07856 if (strlen(tmp) < 2){
07857 if(debug)
07858 printf("@@@@ Bad MHz digits: %s\n", tmp);
07859 return -1;
07860 }
07861
07862 if (strlen(s) < 3){
07863 if(debug)
07864 printf("@@@@ Bad KHz digits: %s\n", s);
07865 return -1;
07866 }
07867
07868 if ((s[2] != '0') && (s[2] != '5')){
07869 if(debug)
07870 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07871 return -1;
07872 }
07873
07874 band = rbi_mhztoband(tmp);
07875 if (band == -1){
07876 if(debug)
07877 printf("@@@@ Bad Band: %s\n", tmp);
07878 return -1;
07879 }
07880
07881 rxpl = rbi_pltocode(myrpt->rxpl);
07882
07883 if (rxpl == -1){
07884 if(debug)
07885 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07886 return -1;
07887 }
07888
07889 txpl = rbi_pltocode(myrpt->txpl);
07890
07891 if (txpl == -1){
07892 if(debug)
07893 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07894 return -1;
07895 }
07896
07897 switch(myrpt->offset)
07898 {
07899 case REM_MINUS:
07900 txoffset = 0;
07901 break;
07902 case REM_PLUS:
07903 txoffset = 0x10;
07904 break;
07905 case REM_SIMPLEX:
07906 txoffset = 0x20;
07907 break;
07908 }
07909 switch(myrpt->powerlevel)
07910 {
07911 case REM_LOWPWR:
07912 txpower = 0;
07913 break;
07914 case REM_MEDPWR:
07915 txpower = 0x20;
07916 break;
07917 case REM_HIPWR:
07918 txpower = 0x10;
07919 break;
07920 }
07921
07922 res = setrtx_check(myrpt);
07923 if (res < 0) return res;
07924 ofac = 0.0;
07925 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07926 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07927
07928 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07929 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07930 else
07931 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07932
07933 pwr = 'L';
07934 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07935 if (!res)
07936 {
07937 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07938 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07939 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07940 send_usb_txt(myrpt,rigstr);
07941 rpt_telemetry(myrpt,COMPLETE,NULL);
07942 res = 0;
07943 }
07944 return 0;
07945 }
07946 #if 0
07947
07948
07949
07950
07951 static int setxpmr(struct rpt *myrpt)
07952 {
07953 char rigstr[200];
07954 int rxpl,txpl;
07955
07956
07957 if (!myrpt->remoterig) return(0);
07958 if (!myrpt->remoterig[0]) return(0);
07959
07960 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07961
07962 if (!IS_XPMR(myrpt)) return(0);
07963
07964 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07965
07966 rxpl = rbi_pltocode(myrpt->rxpl);
07967
07968 if (rxpl == -1){
07969 if(debug)
07970 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07971 return -1;
07972 }
07973
07974 txpl = rbi_pltocode(myrpt->txpl);
07975 if (txpl == -1){
07976 if(debug)
07977 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07978 return -1;
07979 }
07980 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07981 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07982 (myrpt->txplon) ? myrpt->txpl : "0.0");
07983 send_usb_txt(myrpt,rigstr);
07984 return 0;
07985 }
07986 #endif
07987
07988 static int setrbi_check(struct rpt *myrpt)
07989 {
07990 char tmp[MAXREMSTR] = "",*s;
07991 int band,txpl;
07992
07993
07994 if (!myrpt->remote) return(0);
07995
07996 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07997 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07998 s = strchr(tmp,'.');
07999
08000
08001 if (s == NULL){
08002 if(debug)
08003 printf("@@@@ Frequency needs a decimal\n");
08004 return -1;
08005 }
08006
08007 *s++ = 0;
08008 if (strlen(tmp) < 2){
08009 if(debug)
08010 printf("@@@@ Bad MHz digits: %s\n", tmp);
08011 return -1;
08012 }
08013
08014 if (strlen(s) < 3){
08015 if(debug)
08016 printf("@@@@ Bad KHz digits: %s\n", s);
08017 return -1;
08018 }
08019
08020 if ((s[2] != '0') && (s[2] != '5')){
08021 if(debug)
08022 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08023 return -1;
08024 }
08025
08026 band = rbi_mhztoband(tmp);
08027 if (band == -1){
08028 if(debug)
08029 printf("@@@@ Bad Band: %s\n", tmp);
08030 return -1;
08031 }
08032
08033 txpl = rbi_pltocode(myrpt->txpl);
08034
08035 if (txpl == -1){
08036 if(debug)
08037 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08038 return -1;
08039 }
08040 return 0;
08041 }
08042
08043 static int setrtx_check(struct rpt *myrpt)
08044 {
08045 char tmp[MAXREMSTR] = "",*s;
08046 int band,txpl,rxpl;
08047
08048
08049 if (!myrpt->remote) return(0);
08050
08051 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08052 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08053 s = strchr(tmp,'.');
08054
08055
08056 if (s == NULL){
08057 if(debug)
08058 printf("@@@@ Frequency needs a decimal\n");
08059 return -1;
08060 }
08061
08062 *s++ = 0;
08063 if (strlen(tmp) < 2){
08064 if(debug)
08065 printf("@@@@ Bad MHz digits: %s\n", tmp);
08066 return -1;
08067 }
08068
08069 if (strlen(s) < 3){
08070 if(debug)
08071 printf("@@@@ Bad KHz digits: %s\n", s);
08072 return -1;
08073 }
08074
08075 if ((s[2] != '0') && (s[2] != '5')){
08076 if(debug)
08077 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08078 return -1;
08079 }
08080
08081 band = rbi_mhztoband(tmp);
08082 if (band == -1){
08083 if(debug)
08084 printf("@@@@ Bad Band: %s\n", tmp);
08085 return -1;
08086 }
08087
08088 txpl = rbi_pltocode(myrpt->txpl);
08089
08090 if (txpl == -1){
08091 if(debug)
08092 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08093 return -1;
08094 }
08095
08096 rxpl = rbi_pltocode(myrpt->rxpl);
08097
08098 if (rxpl == -1){
08099 if(debug)
08100 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08101 return -1;
08102 }
08103 return 0;
08104 }
08105
08106 static int check_freq_kenwood(int m, int d, int *defmode)
08107 {
08108 int dflmd = REM_MODE_FM;
08109
08110 if (m == 144){
08111 if(d < 10100)
08112 return -1;
08113 }
08114 else if((m >= 145) && (m < 148)){
08115 ;
08116 }
08117 else if((m >= 430) && (m < 450)){
08118 ;
08119 }
08120 else
08121 return -1;
08122
08123 if(defmode)
08124 *defmode = dflmd;
08125
08126
08127 return 0;
08128 }
08129
08130
08131 static int check_freq_tm271(int m, int d, int *defmode)
08132 {
08133 int dflmd = REM_MODE_FM;
08134
08135 if (m == 144){
08136 if(d < 10100)
08137 return -1;
08138 }
08139 else if((m >= 145) && (m < 148)){
08140 ;
08141 }
08142 return -1;
08143
08144 if(defmode)
08145 *defmode = dflmd;
08146
08147
08148 return 0;
08149 }
08150
08151
08152
08153
08154
08155 static int check_freq_rbi(int m, int d, int *defmode)
08156 {
08157 int dflmd = REM_MODE_FM;
08158
08159 if(m == 50){
08160 if(d < 10100)
08161 return -1;
08162 }
08163 else if((m >= 51) && ( m < 54)){
08164 ;
08165 }
08166 else if(m == 144){
08167 if(d < 10100)
08168 return -1;
08169 }
08170 else if((m >= 145) && (m < 148)){
08171 ;
08172 }
08173 else if((m >= 222) && (m < 225)){
08174 ;
08175 }
08176 else if((m >= 430) && (m < 450)){
08177 ;
08178 }
08179 else if((m >= 1240) && (m < 1300)){
08180 ;
08181 }
08182 else
08183 return -1;
08184
08185 if(defmode)
08186 *defmode = dflmd;
08187
08188
08189 return 0;
08190 }
08191
08192
08193
08194
08195 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08196 {
08197 int dflmd = REM_MODE_FM;
08198
08199 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08200 {
08201
08202 if(m == 144){
08203 if(d < 10100)
08204 return -1;
08205 }
08206 else if((m >= 145) && (m < 148)){
08207 ;
08208 }
08209 else
08210 return -1;
08211 }
08212 else
08213 {
08214 if((m >= 430) && (m < 450)){
08215 ;
08216 }
08217 else
08218 return -1;
08219 }
08220 if(defmode)
08221 *defmode = dflmd;
08222
08223
08224 return 0;
08225 }
08226
08227
08228
08229
08230
08231 static int decimals2int(char *fraction)
08232 {
08233 int i;
08234 char len = strlen(fraction);
08235 int multiplier = 100000;
08236 int res = 0;
08237
08238 if(!len)
08239 return 0;
08240 for( i = 0 ; i < len ; i++, multiplier /= 10)
08241 res += (fraction[i] - '0') * multiplier;
08242 return res;
08243 }
08244
08245
08246
08247
08248
08249
08250 static int split_freq(char *mhz, char *decimals, char *freq)
08251 {
08252 char freq_copy[MAXREMSTR];
08253 char *decp;
08254
08255 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08256 if(decp){
08257 *decp++ = 0;
08258 strncpy(mhz, freq_copy, MAXREMSTR);
08259 strcpy(decimals, "00000");
08260 strncpy(decimals, decp, strlen(decp));
08261 decimals[5] = 0;
08262 return 0;
08263 }
08264 else
08265 return -1;
08266
08267 }
08268
08269
08270
08271
08272
08273 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08274 {
08275 char freq_copy[MAXREMSTR];
08276 char *decp;
08277
08278 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08279 if(decp){
08280 *decp++ = 0;
08281 strncpy(hertz, freq_copy, MAXREMSTR);
08282 strncpy(decimal, decp, strlen(decp));
08283 decimal[strlen(decp)] = '\0';
08284 return 0;
08285 }
08286 else
08287 return -1;
08288 }
08289
08290
08291
08292
08293
08294
08295
08296
08297
08298
08299
08300 static int check_freq_ft897(int m, int d, int *defmode)
08301 {
08302 int dflmd = REM_MODE_FM;
08303
08304 if(m == 1){
08305 dflmd = REM_MODE_LSB;
08306 if(d < 80000)
08307 return -1;
08308 }
08309 else if(m == 3){
08310 dflmd = REM_MODE_LSB;
08311 if(d < 50000)
08312 return -1;
08313 }
08314 else if(m == 7){
08315 dflmd = REM_MODE_LSB;
08316 if(d > 30000)
08317 return -1;
08318 }
08319 else if(m == 14){
08320 dflmd = REM_MODE_USB;
08321 if(d > 35000)
08322 return -1;
08323 }
08324 else if(m == 18){
08325 dflmd = REM_MODE_USB;
08326 if((d < 6800) || (d > 16800))
08327 return -1;
08328 }
08329 else if(m == 21){
08330 dflmd = REM_MODE_USB;
08331 if((d < 20000) || (d > 45000))
08332 return -1;
08333 }
08334 else if(m == 24){
08335 dflmd = REM_MODE_USB;
08336 if((d < 89000) || (d > 99000))
08337 return -1;
08338 }
08339 else if(m == 28){
08340 dflmd = REM_MODE_USB;
08341 }
08342 else if(m == 29){
08343 if(d >= 51000)
08344 dflmd = REM_MODE_FM;
08345 else
08346 dflmd = REM_MODE_USB;
08347 if(d > 70000)
08348 return -1;
08349 }
08350 else if(m == 50){
08351 if(d >= 30000)
08352 dflmd = REM_MODE_FM;
08353 else
08354 dflmd = REM_MODE_USB;
08355
08356 }
08357 else if((m >= 51) && ( m < 54)){
08358 dflmd = REM_MODE_FM;
08359 }
08360 else if(m == 144){
08361 if(d >= 30000)
08362 dflmd = REM_MODE_FM;
08363 else
08364 dflmd = REM_MODE_USB;
08365 }
08366 else if((m >= 145) && (m < 148)){
08367 dflmd = REM_MODE_FM;
08368 }
08369 else if((m >= 430) && (m < 450)){
08370 if(m < 438)
08371 dflmd = REM_MODE_USB;
08372 else
08373 dflmd = REM_MODE_FM;
08374 ;
08375 }
08376 else
08377 return -1;
08378
08379 if(defmode)
08380 *defmode = dflmd;
08381
08382 return 0;
08383 }
08384
08385
08386
08387
08388
08389 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08390 {
08391 unsigned char cmdstr[5];
08392 int fd,m,d;
08393 char mhz[MAXREMSTR];
08394 char decimals[MAXREMSTR];
08395
08396 fd = 0;
08397 if(debug)
08398 printf("New frequency: %s\n",newfreq);
08399
08400 if(split_freq(mhz, decimals, newfreq))
08401 return -1;
08402
08403 m = atoi(mhz);
08404 d = atoi(decimals);
08405
08406
08407
08408 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08409 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08410 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08411 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08412 cmdstr[4] = 0x01;
08413
08414 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08415
08416 }
08417
08418
08419
08420 static int simple_command_ft897(struct rpt *myrpt, char command)
08421 {
08422 unsigned char cmdstr[5];
08423
08424 memset(cmdstr, 0, 5);
08425
08426 cmdstr[4] = command;
08427
08428 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08429
08430 }
08431
08432
08433
08434 static int set_offset_ft897(struct rpt *myrpt, char offset)
08435 {
08436 unsigned char cmdstr[5];
08437
08438 memset(cmdstr, 0, 5);
08439
08440 switch(offset){
08441 case REM_SIMPLEX:
08442 cmdstr[0] = 0x89;
08443 break;
08444
08445 case REM_MINUS:
08446 cmdstr[0] = 0x09;
08447 break;
08448
08449 case REM_PLUS:
08450 cmdstr[0] = 0x49;
08451 break;
08452
08453 default:
08454 return -1;
08455 }
08456
08457 cmdstr[4] = 0x09;
08458
08459 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08460 }
08461
08462
08463
08464 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08465 {
08466 unsigned char cmdstr[5];
08467
08468 memset(cmdstr, 0, 5);
08469
08470 switch(newmode){
08471 case REM_MODE_FM:
08472 cmdstr[0] = 0x08;
08473 break;
08474
08475 case REM_MODE_USB:
08476 cmdstr[0] = 0x01;
08477 break;
08478
08479 case REM_MODE_LSB:
08480 cmdstr[0] = 0x00;
08481 break;
08482
08483 case REM_MODE_AM:
08484 cmdstr[0] = 0x04;
08485 break;
08486
08487 default:
08488 return -1;
08489 }
08490 cmdstr[4] = 0x07;
08491
08492 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08493 }
08494
08495
08496
08497 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08498 {
08499 unsigned char cmdstr[5];
08500
08501 memset(cmdstr, 0, 5);
08502
08503 if(rxplon && txplon)
08504 cmdstr[0] = 0x2A;
08505 else if (!rxplon && txplon)
08506 cmdstr[0] = 0x4A;
08507 else if (rxplon && !txplon)
08508 cmdstr[0] = 0x3A;
08509 else
08510 cmdstr[0] = 0x8A;
08511
08512 cmdstr[4] = 0x0A;
08513
08514 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08515 }
08516
08517
08518
08519
08520 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08521 {
08522 unsigned char cmdstr[5];
08523 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08524 int h,d;
08525
08526 memset(cmdstr, 0, 5);
08527
08528 if(split_ctcss_freq(hertz, decimal, txtone))
08529 return -1;
08530
08531 h = atoi(hertz);
08532 d = atoi(decimal);
08533
08534 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08535 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08536
08537 if(rxtone){
08538
08539 if(split_ctcss_freq(hertz, decimal, rxtone))
08540 return -1;
08541
08542 h = atoi(hertz);
08543 d = atoi(decimal);
08544
08545 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08546 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08547 }
08548 cmdstr[4] = 0x0B;
08549
08550 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08551 }
08552
08553
08554
08555 static int set_ft897(struct rpt *myrpt)
08556 {
08557 int res;
08558
08559 if(debug)
08560 printf("@@@@ lock on\n");
08561
08562 res = simple_command_ft897(myrpt, 0x00);
08563
08564 if(debug)
08565 printf("@@@@ ptt off\n");
08566
08567 if(!res)
08568 res = simple_command_ft897(myrpt, 0x88);
08569
08570 if(debug)
08571 printf("Modulation mode\n");
08572
08573 if(!res)
08574 res = set_mode_ft897(myrpt, myrpt->remmode);
08575
08576 if(debug)
08577 printf("Split off\n");
08578
08579 if(!res)
08580 simple_command_ft897(myrpt, 0x82);
08581
08582 if(debug)
08583 printf("Frequency\n");
08584
08585 if(!res)
08586 res = set_freq_ft897(myrpt, myrpt->freq);
08587 if((myrpt->remmode == REM_MODE_FM)){
08588 if(debug)
08589 printf("Offset\n");
08590 if(!res)
08591 res = set_offset_ft897(myrpt, myrpt->offset);
08592 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08593 if(debug)
08594 printf("CTCSS tone freqs.\n");
08595 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08596 }
08597 if(!res){
08598 if(debug)
08599 printf("CTCSS mode\n");
08600 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08601 }
08602 }
08603 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08604 if(debug)
08605 printf("Clarifier off\n");
08606 simple_command_ft897(myrpt, 0x85);
08607 }
08608 return res;
08609 }
08610
08611 static int closerem_ft897(struct rpt *myrpt)
08612 {
08613 simple_command_ft897(myrpt, 0x88);
08614 return 0;
08615 }
08616
08617
08618
08619
08620
08621
08622
08623 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08624 {
08625 int m,d;
08626 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08627
08628 if(debug)
08629 printf("Before bump: %s\n", myrpt->freq);
08630
08631 if(split_freq(mhz, decimals, myrpt->freq))
08632 return -1;
08633
08634 m = atoi(mhz);
08635 d = atoi(decimals);
08636
08637 d += (interval / 10);
08638 if(d < 0){
08639 m--;
08640 d += 100000;
08641 }
08642 else if(d >= 100000){
08643 m++;
08644 d -= 100000;
08645 }
08646
08647 if(check_freq_ft897(m, d, NULL)){
08648 if(debug)
08649 printf("Bump freq invalid\n");
08650 return -1;
08651 }
08652
08653 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08654
08655 if(debug)
08656 printf("After bump: %s\n", myrpt->freq);
08657
08658 return set_freq_ft897(myrpt, myrpt->freq);
08659 }
08660
08661
08662
08663
08664
08665
08666
08667
08668
08669
08670 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08671 {
08672 int dflmd = REM_MODE_FM;
08673 int rv=0;
08674
08675 if(debug > 6)
08676 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08677
08678
08679
08680 if(m == 1){
08681 dflmd = REM_MODE_LSB;
08682 if(d < 80000)rv=-1;
08683 }
08684 else if(m == 3){
08685 dflmd = REM_MODE_LSB;
08686 if(d < 50000)rv=-1;
08687 }
08688 else if(m == 7){
08689 dflmd = REM_MODE_LSB;
08690 if(d > 30000)rv=-1;
08691 }
08692 else if(m == 14){
08693 dflmd = REM_MODE_USB;
08694 if(d > 35000)rv=-1;
08695 }
08696 else if(m == 18){
08697 dflmd = REM_MODE_USB;
08698 if((d < 6800) || (d > 16800))rv=-1;
08699 }
08700 else if(m == 21){
08701 dflmd = REM_MODE_USB;
08702 if((d < 20000) || (d > 45000))rv=-1;
08703 }
08704 else if(m == 24){
08705 dflmd = REM_MODE_USB;
08706 if((d < 89000) || (d > 99000))rv=-1;
08707 }
08708 else if(m == 28){
08709 dflmd = REM_MODE_USB;
08710 }
08711 else if(m == 29){
08712 if(d >= 51000)
08713 dflmd = REM_MODE_FM;
08714 else
08715 dflmd = REM_MODE_USB;
08716 if(d > 70000)rv=-1;
08717 }
08718 else if(m == 50){
08719 if(d >= 30000)
08720 dflmd = REM_MODE_FM;
08721 else
08722 dflmd = REM_MODE_USB;
08723 }
08724 else if((m >= 51) && ( m < 54)){
08725 dflmd = REM_MODE_FM;
08726 }
08727 else if(m == 144){
08728 if(d >= 30000)
08729 dflmd = REM_MODE_FM;
08730 else
08731 dflmd = REM_MODE_USB;
08732 }
08733 else if((m >= 145) && (m < 148)){
08734 dflmd = REM_MODE_FM;
08735 }
08736 else if((m >= 430) && (m < 450)){
08737 if(m < 438)
08738 dflmd = REM_MODE_USB;
08739 else
08740 dflmd = REM_MODE_FM;
08741 }
08742
08743
08744 if(mars && rv<0){
08745 if((m >= 450) && (m < 470)){
08746 dflmd = REM_MODE_FM;
08747 rv=0;
08748 }
08749 else if((m >= 148) && (m < 174)){
08750 dflmd = REM_MODE_FM;
08751 rv=0;
08752 }
08753 else if((m >= 138) && (m < 144)){
08754 dflmd = REM_MODE_AM;
08755 rv=0;
08756 }
08757 else if((m >= 108) && (m < 138)){
08758 dflmd = REM_MODE_AM;
08759 rv=0;
08760 }
08761 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08762 dflmd = REM_MODE_AM;
08763 rv=0;
08764 }
08765 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08766 dflmd = REM_MODE_AM;
08767 rv=0;
08768 }
08769 }
08770
08771 if(defmode)
08772 *defmode = dflmd;
08773
08774 if(debug > 1)
08775 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08776
08777 return rv;
08778 }
08779
08780
08781 static int ic706_pltocode(char *str)
08782 {
08783 int i;
08784 char *s;
08785 int rv=-1;
08786
08787 s = strchr(str,'.');
08788 i = 0;
08789 if (s) i = atoi(s + 1);
08790 i += atoi(str) * 10;
08791 switch(i)
08792 {
08793 case 670:
08794 rv=0;
08795 case 693:
08796 rv=1;
08797 case 719:
08798 rv=2;
08799 case 744:
08800 rv=3;
08801 case 770:
08802 rv=4;
08803 case 797:
08804 rv=5;
08805 case 825:
08806 rv=6;
08807 case 854:
08808 rv=7;
08809 case 885:
08810 rv=8;
08811 case 915:
08812 rv=9;
08813 case 948:
08814 rv=10;
08815 case 974:
08816 rv=11;
08817 case 1000:
08818 rv=12;
08819 case 1035:
08820 rv=13;
08821 case 1072:
08822 rv=14;
08823 case 1109:
08824 rv=15;
08825 case 1148:
08826 rv=16;
08827 case 1188:
08828 rv=17;
08829 case 1230:
08830 rv=18;
08831 case 1273:
08832 rv=19;
08833 case 1318:
08834 rv=20;
08835 case 1365:
08836 rv=21;
08837 case 1413:
08838 rv=22;
08839 case 1462:
08840 rv=23;
08841 case 1514:
08842 rv=24;
08843 case 1567:
08844 rv=25;
08845 case 1598:
08846 rv=26;
08847 case 1622:
08848 rv=27;
08849 case 1655:
08850 rv=28;
08851 case 1679:
08852 rv=29;
08853 case 1713:
08854 rv=30;
08855 case 1738:
08856 rv=31;
08857 case 1773:
08858 rv=32;
08859 case 1799:
08860 rv=33;
08861 case 1835:
08862 rv=34;
08863 case 1862:
08864 rv=35;
08865 case 1899:
08866 rv=36;
08867 case 1928:
08868 rv=37;
08869 case 1966:
08870 rv=38;
08871 case 1995:
08872 rv=39;
08873 case 2035:
08874 rv=40;
08875 case 2065:
08876 rv=41;
08877 case 2107:
08878 rv=42;
08879 case 2181:
08880 rv=43;
08881 case 2257:
08882 rv=44;
08883 case 2291:
08884 rv=45;
08885 case 2336:
08886 rv=46;
08887 case 2418:
08888 rv=47;
08889 case 2503:
08890 rv=48;
08891 case 2541:
08892 rv=49;
08893 }
08894 if(debug > 1)
08895 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08896
08897 return rv;
08898 }
08899
08900
08901
08902 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08903 {
08904 unsigned char cmdstr[10];
08905
08906 cmdstr[0] = cmdstr[1] = 0xfe;
08907 cmdstr[2] = myrpt->p.civaddr;
08908 cmdstr[3] = 0xe0;
08909 cmdstr[4] = command;
08910 cmdstr[5] = subcommand;
08911 cmdstr[6] = 0xfd;
08912
08913 return(civ_cmd(myrpt,cmdstr,7));
08914 }
08915
08916
08917
08918
08919
08920 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08921 {
08922 unsigned char cmdstr[20];
08923 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08924 int fd,m,d;
08925
08926 fd = 0;
08927 if(debug)
08928 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08929
08930 if(split_freq(mhz, decimals, newfreq))
08931 return -1;
08932
08933 m = atoi(mhz);
08934 d = atoi(decimals);
08935
08936
08937
08938 cmdstr[0] = cmdstr[1] = 0xfe;
08939 cmdstr[2] = myrpt->p.civaddr;
08940 cmdstr[3] = 0xe0;
08941 cmdstr[4] = 5;
08942 cmdstr[5] = ((d % 10) << 4);
08943 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08944 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08945 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08946 cmdstr[9] = (m / 100);
08947 cmdstr[10] = 0xfd;
08948
08949 return(civ_cmd(myrpt,cmdstr,11));
08950 }
08951
08952
08953
08954 static int set_offset_ic706(struct rpt *myrpt, char offset)
08955 {
08956 unsigned char c;
08957
08958 if(debug > 6)
08959 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08960
08961 switch(offset){
08962 case REM_SIMPLEX:
08963 c = 0x10;
08964 break;
08965
08966 case REM_MINUS:
08967 c = 0x11;
08968 break;
08969
08970 case REM_PLUS:
08971 c = 0x12;
08972 break;
08973
08974 default:
08975 return -1;
08976 }
08977
08978 return simple_command_ic706(myrpt,0x0f,c);
08979
08980 }
08981
08982
08983
08984 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08985 {
08986 unsigned char c;
08987
08988 if(debug > 6)
08989 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08990
08991 switch(newmode){
08992 case REM_MODE_FM:
08993 c = 5;
08994 break;
08995
08996 case REM_MODE_USB:
08997 c = 1;
08998 break;
08999
09000 case REM_MODE_LSB:
09001 c = 0;
09002 break;
09003
09004 case REM_MODE_AM:
09005 c = 2;
09006 break;
09007
09008 default:
09009 return -1;
09010 }
09011 return simple_command_ic706(myrpt,6,c);
09012 }
09013
09014
09015
09016 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
09017 {
09018 unsigned char cmdstr[10];
09019 int rv;
09020
09021 if(debug > 6)
09022 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
09023
09024 cmdstr[0] = cmdstr[1] = 0xfe;
09025 cmdstr[2] = myrpt->p.civaddr;
09026 cmdstr[3] = 0xe0;
09027 cmdstr[4] = 0x16;
09028 cmdstr[5] = 0x42;
09029 cmdstr[6] = (txplon != 0);
09030 cmdstr[7] = 0xfd;
09031
09032 rv = civ_cmd(myrpt,cmdstr,8);
09033 if (rv) return(-1);
09034
09035 cmdstr[0] = cmdstr[1] = 0xfe;
09036 cmdstr[2] = myrpt->p.civaddr;
09037 cmdstr[3] = 0xe0;
09038 cmdstr[4] = 0x16;
09039 cmdstr[5] = 0x43;
09040 cmdstr[6] = (rxplon != 0);
09041 cmdstr[7] = 0xfd;
09042
09043 return(civ_cmd(myrpt,cmdstr,8));
09044 }
09045
09046 #if 0
09047
09048
09049 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09050 {
09051 unsigned char cmdstr[10];
09052 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09053 int h,d,rv;
09054
09055 memset(cmdstr, 0, 5);
09056
09057 if(debug > 6)
09058 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09059
09060 if(split_ctcss_freq(hertz, decimal, txtone))
09061 return -1;
09062
09063 h = atoi(hertz);
09064 d = atoi(decimal);
09065
09066 cmdstr[0] = cmdstr[1] = 0xfe;
09067 cmdstr[2] = myrpt->p.civaddr;
09068 cmdstr[3] = 0xe0;
09069 cmdstr[4] = 0x1b;
09070 cmdstr[5] = 0;
09071 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09072 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09073 cmdstr[8] = 0xfd;
09074
09075 rv = civ_cmd(myrpt,cmdstr,9);
09076 if (rv) return(-1);
09077
09078 if (!rxtone) return(0);
09079
09080 if(split_ctcss_freq(hertz, decimal, rxtone))
09081 return -1;
09082
09083 h = atoi(hertz);
09084 d = atoi(decimal);
09085
09086 cmdstr[0] = cmdstr[1] = 0xfe;
09087 cmdstr[2] = myrpt->p.civaddr;
09088 cmdstr[3] = 0xe0;
09089 cmdstr[4] = 0x1b;
09090 cmdstr[5] = 1;
09091 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09092 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09093 cmdstr[8] = 0xfd;
09094 return(civ_cmd(myrpt,cmdstr,9));
09095 }
09096 #endif
09097
09098 static int vfo_ic706(struct rpt *myrpt)
09099 {
09100 unsigned char cmdstr[10];
09101
09102 cmdstr[0] = cmdstr[1] = 0xfe;
09103 cmdstr[2] = myrpt->p.civaddr;
09104 cmdstr[3] = 0xe0;
09105 cmdstr[4] = 7;
09106 cmdstr[5] = 0xfd;
09107
09108 return(civ_cmd(myrpt,cmdstr,6));
09109 }
09110
09111 static int mem2vfo_ic706(struct rpt *myrpt)
09112 {
09113 unsigned char cmdstr[10];
09114
09115 cmdstr[0] = cmdstr[1] = 0xfe;
09116 cmdstr[2] = myrpt->p.civaddr;
09117 cmdstr[3] = 0xe0;
09118 cmdstr[4] = 0x0a;
09119 cmdstr[5] = 0xfd;
09120
09121 return(civ_cmd(myrpt,cmdstr,6));
09122 }
09123
09124 static int select_mem_ic706(struct rpt *myrpt, int slot)
09125 {
09126 unsigned char cmdstr[10];
09127
09128 cmdstr[0] = cmdstr[1] = 0xfe;
09129 cmdstr[2] = myrpt->p.civaddr;
09130 cmdstr[3] = 0xe0;
09131 cmdstr[4] = 8;
09132 cmdstr[5] = 0;
09133 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09134 cmdstr[7] = 0xfd;
09135
09136 return(civ_cmd(myrpt,cmdstr,8));
09137 }
09138
09139 static int set_ic706(struct rpt *myrpt)
09140 {
09141 int res = 0,i;
09142
09143 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09144
09145 if (!res)
09146 res = simple_command_ic706(myrpt,7,0);
09147
09148 if((myrpt->remmode == REM_MODE_FM))
09149 {
09150 i = ic706_pltocode(myrpt->rxpl);
09151 if (i == -1) return -1;
09152 if(debug)
09153 printf("Select memory number\n");
09154 if (!res)
09155 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09156 if(debug)
09157 printf("Transfer memory to VFO\n");
09158 if (!res)
09159 res = mem2vfo_ic706(myrpt);
09160 }
09161
09162 if(debug)
09163 printf("Set to VFO\n");
09164
09165 if (!res)
09166 res = vfo_ic706(myrpt);
09167
09168 if(debug)
09169 printf("Modulation mode\n");
09170
09171 if (!res)
09172 res = set_mode_ic706(myrpt, myrpt->remmode);
09173
09174 if(debug)
09175 printf("Split off\n");
09176
09177 if(!res)
09178 simple_command_ic706(myrpt, 0x82,0);
09179
09180 if(debug)
09181 printf("Frequency\n");
09182
09183 if(!res)
09184 res = set_freq_ic706(myrpt, myrpt->freq);
09185 if((myrpt->remmode == REM_MODE_FM)){
09186 if(debug)
09187 printf("Offset\n");
09188 if(!res)
09189 res = set_offset_ic706(myrpt, myrpt->offset);
09190 if(!res){
09191 if(debug)
09192 printf("CTCSS mode\n");
09193 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09194 }
09195 }
09196 return res;
09197 }
09198
09199
09200
09201
09202
09203
09204
09205 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09206 {
09207 int m,d;
09208 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09209 unsigned char cmdstr[20];
09210
09211 if(debug)
09212 printf("Before bump: %s\n", myrpt->freq);
09213
09214 if(split_freq(mhz, decimals, myrpt->freq))
09215 return -1;
09216
09217 m = atoi(mhz);
09218 d = atoi(decimals);
09219
09220 d += (interval / 10);
09221 if(d < 0){
09222 m--;
09223 d += 100000;
09224 }
09225 else if(d >= 100000){
09226 m++;
09227 d -= 100000;
09228 }
09229
09230 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09231 if(debug)
09232 printf("Bump freq invalid\n");
09233 return -1;
09234 }
09235
09236 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09237
09238 if(debug)
09239 printf("After bump: %s\n", myrpt->freq);
09240
09241
09242
09243 cmdstr[0] = cmdstr[1] = 0xfe;
09244 cmdstr[2] = myrpt->p.civaddr;
09245 cmdstr[3] = 0xe0;
09246 cmdstr[4] = 0;
09247 cmdstr[5] = ((d % 10) << 4);
09248 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09249 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09250 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09251 cmdstr[9] = (m / 100);
09252 cmdstr[10] = 0xfd;
09253
09254 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09255 }
09256
09257
09258
09259
09260
09261
09262 static int setrem(struct rpt *myrpt)
09263 {
09264 char str[300];
09265 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09266 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09267 char *modes[] = {"FM","USB","LSB","AM"};
09268 int res = -1;
09269
09270 #if 0
09271 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09272 modes[(int)myrpt->remmode],
09273 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09274 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09275 myrpt->rxplon);
09276 #endif
09277 if (myrpt->p.archivedir)
09278 {
09279 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09280 modes[(int)myrpt->remmode],
09281 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09282 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09283 myrpt->rxplon);
09284 donodelog(myrpt,str);
09285 }
09286 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09287 {
09288 rpt_telemetry(myrpt,SETREMOTE,NULL);
09289 res = 0;
09290 }
09291 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09292 {
09293 rpt_telemetry(myrpt,SETREMOTE,NULL);
09294 res = 0;
09295 }
09296 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09297 {
09298 rpt_telemetry(myrpt,SETREMOTE,NULL);
09299 res = 0;
09300 }
09301 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09302 {
09303 res = setrbi_check(myrpt);
09304 if (!res)
09305 {
09306 rpt_telemetry(myrpt,SETREMOTE,NULL);
09307 res = 0;
09308 }
09309 }
09310 else if(ISRIG_RTX(myrpt->remoterig))
09311 {
09312 setrtx(myrpt);
09313 res = 0;
09314 }
09315 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09316 rpt_telemetry(myrpt,SETREMOTE,NULL);
09317 res = 0;
09318 }
09319 else
09320 res = 0;
09321
09322 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09323
09324 return res;
09325 }
09326
09327 static int closerem(struct rpt *myrpt)
09328 {
09329 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09330 return closerem_ft897(myrpt);
09331 else
09332 return 0;
09333 }
09334
09335
09336
09337
09338
09339 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09340 {
09341 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09342 return check_freq_ft897(m, d, defmode);
09343 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09344 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09345 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09346 return check_freq_rbi(m, d, defmode);
09347 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09348 return check_freq_kenwood(m, d, defmode);
09349 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09350 return check_freq_tm271(m, d, defmode);
09351 else if(ISRIG_RTX(myrpt->remoterig))
09352 return check_freq_rtx(m, d, defmode, myrpt);
09353 else
09354 return -1;
09355 }
09356
09357
09358
09359
09360
09361
09362 static char check_tx_freq(struct rpt *myrpt)
09363 {
09364 int i,rv=0;
09365 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09366 char radio_mhz_char[MAXREMSTR];
09367 char radio_decimals_char[MAXREMSTR];
09368 char limit_mhz_char[MAXREMSTR];
09369 char limit_decimals_char[MAXREMSTR];
09370 char limits[256];
09371 char *limit_ranges[40];
09372 struct ast_variable *limitlist;
09373
09374 if(debug > 3){
09375 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09376 }
09377
09378
09379
09380 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09381 if(debug > 3){
09382 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09383 }
09384 rv=1;
09385 return 1;
09386 }
09387
09388
09389 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09390
09391 if(!limitlist){
09392 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09393 rv=0;
09394 return 0;
09395 }
09396
09397 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09398 radio_mhz = atoi(radio_mhz_char);
09399 radio_decimals = decimals2int(radio_decimals_char);
09400
09401 if(debug > 3){
09402 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09403 }
09404
09405
09406
09407 for(;limitlist; limitlist=limitlist->next){
09408 if(!strcmp(limitlist->name, myrpt->loginlevel))
09409 break;
09410 }
09411
09412 if(!limitlist){
09413 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09414 rv=0;
09415 return 0;
09416 }
09417
09418 if(debug > 3){
09419 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09420 }
09421
09422
09423
09424 strncpy(limits, limitlist->value, 256);
09425 limits[255] = 0;
09426 finddelim(limits, limit_ranges, 40);
09427 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09428 char range[40];
09429 char *r,*s;
09430 strncpy(range, limit_ranges[i], 40);
09431 range[39] = 0;
09432 if(debug > 3)
09433 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09434
09435 r = strchr(range, '-');
09436 if(!r){
09437 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09438 rv=0;
09439 break;
09440 }
09441 *r++ = 0;
09442 s = eatwhite(range);
09443 r = eatwhite(r);
09444 split_freq(limit_mhz_char, limit_decimals_char, s);
09445 llimit_mhz = atoi(limit_mhz_char);
09446 llimit_decimals = decimals2int(limit_decimals_char);
09447 split_freq(limit_mhz_char, limit_decimals_char, r);
09448 ulimit_mhz = atoi(limit_mhz_char);
09449 ulimit_decimals = decimals2int(limit_decimals_char);
09450
09451 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09452 if(radio_mhz == llimit_mhz){
09453 if(radio_decimals >= llimit_decimals){
09454 if(llimit_mhz == ulimit_mhz){
09455 if(radio_decimals <= ulimit_decimals){
09456 rv=1;
09457 break;
09458 }
09459 else{
09460 if(debug > 3)
09461 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09462 rv=0;
09463 break;
09464 }
09465 }
09466 else{
09467 rv=1;
09468 break;
09469 }
09470 }
09471 else{
09472 if(debug > 3)
09473 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09474 rv=0;
09475 break;
09476 }
09477 }
09478 else if(radio_mhz == ulimit_mhz){
09479 if(radio_decimals <= ulimit_decimals){
09480 if(debug > 3)
09481 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09482 rv=1;
09483 break;
09484 }
09485 else{
09486 if(debug > 3)
09487 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09488 rv=0;
09489 break;
09490 }
09491 }
09492 else
09493 if(debug > 3)
09494 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09495 rv=1;
09496 break;
09497 }
09498 }
09499 if(debug > 3)
09500 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09501
09502 return rv;
09503 }
09504
09505
09506
09507
09508
09509
09510 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09511 {
09512 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09513 return multimode_bump_freq_ft897(myrpt, interval);
09514 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09515 return multimode_bump_freq_ic706(myrpt, interval);
09516 else
09517 return -1;
09518 }
09519
09520
09521
09522
09523
09524
09525 static void stop_scan(struct rpt *myrpt)
09526 {
09527 myrpt->hfscanstop = 1;
09528 rpt_telemetry(myrpt,SCAN,0);
09529 }
09530
09531
09532
09533
09534
09535
09536 static int service_scan(struct rpt *myrpt)
09537 {
09538 int res, interval;
09539 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09540
09541 switch(myrpt->hfscanmode){
09542
09543 case HF_SCAN_DOWN_SLOW:
09544 interval = -10;
09545 break;
09546
09547 case HF_SCAN_DOWN_QUICK:
09548 interval = -50;
09549 break;
09550
09551 case HF_SCAN_DOWN_FAST:
09552 interval = -200;
09553 break;
09554
09555 case HF_SCAN_UP_SLOW:
09556 interval = 10;
09557 break;
09558
09559 case HF_SCAN_UP_QUICK:
09560 interval = 50;
09561 break;
09562
09563 case HF_SCAN_UP_FAST:
09564 interval = 200;
09565 break;
09566
09567 default:
09568 myrpt->hfscanmode = 0;
09569 return -1;
09570 }
09571
09572 res = split_freq(mhz, decimals, myrpt->freq);
09573
09574 if(!res){
09575 k100 =decimals[0];
09576 k10 = decimals[1];
09577 res = multimode_bump_freq(myrpt, interval);
09578 }
09579
09580 if(!res)
09581 res = split_freq(mhz, decimals, myrpt->freq);
09582
09583
09584 if(res){
09585 myrpt->hfscanmode = 0;
09586 myrpt->hfscanstatus = -2;
09587 return -1;
09588 }
09589
09590
09591 if(k10 != decimals[1]){
09592 int myhund = (interval < 0) ? k100 : decimals[0];
09593 int myten = (interval < 0) ? k10 : decimals[1];
09594 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09595 } else myrpt->hfscanstatus = 0;
09596 return res;
09597
09598 }
09599
09600
09601
09602 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09603 {
09604 int res=0;
09605 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09606 res = retreive_memory(myrpt, digitbuf);
09607 if(!res)res=setrem(myrpt);
09608 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09609 return res;
09610 }
09611
09612
09613
09614
09615 static int channel_steer(struct rpt *myrpt, char *data)
09616 {
09617 int res=0;
09618
09619 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09620 if (!myrpt->remoterig) return(0);
09621 if(data<=0)
09622 {
09623 res=-1;
09624 }
09625 else
09626 {
09627 myrpt->nowchan=strtod(data,NULL);
09628 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09629 {
09630 char string[16];
09631 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09632 send_usb_txt(myrpt,string);
09633 }
09634 else
09635 {
09636 if(get_mem_set(myrpt, data))res=-1;
09637 }
09638 }
09639 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09640 return res;
09641 }
09642
09643
09644 static int channel_revert(struct rpt *myrpt)
09645 {
09646 int res=0;
09647 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09648 if (!myrpt->remoterig) return(0);
09649 if(myrpt->nowchan!=myrpt->waschan)
09650 {
09651 char data[8];
09652 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09653 sprintf(data,"%02d",myrpt->waschan);
09654 myrpt->nowchan=myrpt->waschan;
09655 channel_steer(myrpt,data);
09656 res=1;
09657 }
09658 return(res);
09659 }
09660
09661
09662
09663
09664 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09665 {
09666 char *s,*s1,*s2;
09667 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09668 intptr_t p;
09669 char multimode = 0;
09670 char oc,*cp,*cp1,*cp2;
09671 char tmp[20], freq[20] = "", savestr[20] = "";
09672 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09673
09674 if(debug > 6) {
09675 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09676 }
09677
09678 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09679 return DC_ERROR;
09680
09681 p = myatoi(param);
09682
09683 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09684 (!myrpt->loginlevel[0])) return DC_ERROR;
09685 multimode = multimode_capable(myrpt);
09686
09687 switch(p){
09688
09689 case 1:
09690 if(strlen(digitbuf) < 2)
09691 break;
09692
09693 for(i = 0 ; i < 2 ; i++){
09694 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09695 return DC_ERROR;
09696 }
09697 r=get_mem_set(myrpt, digitbuf);
09698 if (r < 0){
09699 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09700 return DC_COMPLETE;
09701 }
09702 else if (r > 0){
09703 return DC_ERROR;
09704 }
09705 return DC_COMPLETE;
09706
09707 case 2:
09708
09709
09710 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09711 if(digitbuf[i] == '*'){
09712 j++;
09713 continue;
09714 }
09715 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09716 goto invalid_freq;
09717 else{
09718 if(j == 0)
09719 l++;
09720 if(j == 1)
09721 k++;
09722 }
09723 }
09724
09725 i = strlen(digitbuf) - 1;
09726 if(multimode){
09727 if((j > 2) || (l > 3) || (k > 6))
09728 goto invalid_freq;
09729 }
09730 else{
09731 if((j > 2) || (l > 4) || (k > 3))
09732 goto invalid_freq;
09733 }
09734
09735
09736
09737 if(j < 2)
09738 break;
09739
09740
09741
09742 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09743
09744 s = tmp;
09745 s1 = strsep(&s, "*");
09746 s2 = strsep(&s,"*");
09747 ls2 = strlen(s2);
09748
09749 switch(ls2){
09750 case 1:
09751 ht = 0;
09752 k = 100 * atoi(s2);
09753 break;
09754
09755 case 2:
09756 ht = 0;
09757 k = 10 * atoi(s2);
09758 break;
09759
09760 case 3:
09761 if(!multimode){
09762 if((s2[2] != '0')&&(s2[2] != '5'))
09763 goto invalid_freq;
09764 }
09765 ht = 0;
09766 k = atoi(s2);
09767 break;
09768 case 4:
09769 k = atoi(s2)/10;
09770 ht = 10 * (atoi(s2+(ls2-1)));
09771 break;
09772
09773 case 5:
09774 k = atoi(s2)/100;
09775 ht = (atoi(s2+(ls2-2)));
09776 break;
09777
09778 default:
09779 goto invalid_freq;
09780 }
09781
09782
09783
09784 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09785
09786 if(debug)
09787 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09788
09789 split_freq(mhz, decimals, freq);
09790 m = atoi(mhz);
09791 d = atoi(decimals);
09792
09793 if(check_freq(myrpt, m, d, &defmode))
09794 goto invalid_freq;
09795
09796
09797 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09798 break;
09799
09800
09801 offset = REM_SIMPLEX;
09802
09803 if(defmode == REM_MODE_FM){
09804 oc = *s;
09805
09806 if (oc){
09807 switch(oc){
09808 case '1':
09809 offset = REM_MINUS;
09810 break;
09811
09812 case '2':
09813 offset = REM_SIMPLEX;
09814 break;
09815
09816 case '3':
09817 offset = REM_PLUS;
09818 break;
09819
09820 default:
09821 goto invalid_freq;
09822 }
09823 }
09824 }
09825 offsave = myrpt->offset;
09826 modesave = myrpt->remmode;
09827 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09828 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09829 myrpt->offset = offset;
09830 myrpt->remmode = defmode;
09831
09832 if (setrem(myrpt) == -1){
09833 myrpt->offset = offsave;
09834 myrpt->remmode = modesave;
09835 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09836 goto invalid_freq;
09837 }
09838
09839 return DC_COMPLETE;
09840
09841 invalid_freq:
09842 rpt_telemetry(myrpt,INVFREQ,NULL);
09843 return DC_ERROR;
09844
09845 case 3:
09846 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09847 if(digitbuf[i] == '*'){
09848 j++;
09849 continue;
09850 }
09851 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09852 return DC_ERROR;
09853 else{
09854 if(j)
09855 l++;
09856 else
09857 k++;
09858 }
09859 }
09860 if((j > 1) || (k > 3) || (l > 1))
09861 return DC_ERROR;
09862 i = strlen(digitbuf) - 1;
09863 if((j != 1) || (k < 2)|| (l != 1))
09864 break;
09865 if(debug)
09866 printf("PL digits entered %s\n", digitbuf);
09867
09868 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09869
09870 s = strchr(tmp,'*');
09871 if(s)
09872 *s = '.';
09873 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09874 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09875 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09876 {
09877 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09878 }
09879 if (setrem(myrpt) == -1){
09880 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09881 return DC_ERROR;
09882 }
09883 return DC_COMPLETE;
09884
09885 case 4:
09886
09887 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09888 return DC_ERROR;
09889
09890
09891
09892
09893
09894 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09895 {
09896 if(debug)
09897 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09898 return DC_ERROR;
09899 }
09900 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09901 if(digitbuf[i] == '*'){
09902 j++;
09903 continue;
09904 }
09905 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09906 return DC_ERROR;
09907 else{
09908 if(j)
09909 l++;
09910 else
09911 k++;
09912 }
09913 }
09914 if((j > 1) || (k > 3) || (l > 1))
09915 return DC_ERROR;
09916 i = strlen(digitbuf) - 1;
09917 if((j != 1) || (k < 2)|| (l != 1))
09918 break;
09919 if(debug)
09920 printf("PL digits entered %s\n", digitbuf);
09921
09922 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09923
09924 s = strchr(tmp,'*');
09925 if(s)
09926 *s = '.';
09927 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09928 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09929
09930 if (setrem(myrpt) == -1){
09931 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09932 return DC_ERROR;
09933 }
09934 return DC_COMPLETE;
09935
09936
09937 case 6:
09938 if(strlen(digitbuf) < 1)
09939 break;
09940
09941 if(!multimode)
09942 return DC_ERROR;
09943
09944 switch(*digitbuf){
09945 case '1':
09946 split_freq(mhz, decimals, myrpt->freq);
09947 m=atoi(mhz);
09948 if(m < 29)
09949 return DC_ERROR;
09950 myrpt->remmode = REM_MODE_FM;
09951
09952 rpt_telemetry(myrpt,REMMODE,NULL);
09953 break;
09954
09955 case '2':
09956 myrpt->remmode = REM_MODE_USB;
09957 rpt_telemetry(myrpt,REMMODE,NULL);
09958 break;
09959
09960 case '3':
09961 myrpt->remmode = REM_MODE_LSB;
09962 rpt_telemetry(myrpt,REMMODE,NULL);
09963 break;
09964
09965 case '4':
09966 myrpt->remmode = REM_MODE_AM;
09967 rpt_telemetry(myrpt,REMMODE,NULL);
09968 break;
09969
09970 default:
09971 return DC_ERROR;
09972 }
09973
09974 if(setrem(myrpt))
09975 return DC_ERROR;
09976 return DC_COMPLETEQUIET;
09977 case 99:
09978
09979 if (myrpt->loginlevel[0])
09980 return DC_ERROR;
09981 *myrpt->loginuser = 0;
09982 myrpt->loginlevel[0] = 0;
09983 cp = ast_strdup(param);
09984 cp1 = strchr(cp,',');
09985 ast_mutex_lock(&myrpt->lock);
09986 if (cp1)
09987 {
09988 *cp1 = 0;
09989 cp2 = strchr(cp1 + 1,',');
09990 if (cp2)
09991 {
09992 *cp2 = 0;
09993 strncpy(myrpt->loginlevel,cp2 + 1,
09994 sizeof(myrpt->loginlevel) - 1);
09995 }
09996 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09997 ast_mutex_unlock(&myrpt->lock);
09998 if (myrpt->p.archivedir)
09999 {
10000 char str[100];
10001
10002 sprintf(str,"LOGIN,%s,%s",
10003 myrpt->loginuser,myrpt->loginlevel);
10004 donodelog(myrpt,str);
10005 }
10006 if (debug)
10007 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
10008 rpt_telemetry(myrpt,REMLOGIN,NULL);
10009 }
10010 ast_free(cp);
10011 return DC_COMPLETEQUIET;
10012 case 100:
10013 myrpt->rxplon = 0;
10014 setrem(myrpt);
10015 rpt_telemetry(myrpt,REMXXX,(void *)p);
10016 return DC_COMPLETEQUIET;
10017 case 101:
10018 myrpt->rxplon = 1;
10019 setrem(myrpt);
10020 rpt_telemetry(myrpt,REMXXX,(void *)p);
10021 return DC_COMPLETEQUIET;
10022 case 102:
10023 myrpt->txplon = 0;
10024 setrem(myrpt);
10025 rpt_telemetry(myrpt,REMXXX,(void *)p);
10026 return DC_COMPLETEQUIET;
10027 case 103:
10028 myrpt->txplon = 1;
10029 setrem(myrpt);
10030 rpt_telemetry(myrpt,REMXXX,(void *)p);
10031 return DC_COMPLETEQUIET;
10032 case 104:
10033 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10034 return DC_ERROR;
10035 myrpt->powerlevel = REM_LOWPWR;
10036 setrem(myrpt);
10037 rpt_telemetry(myrpt,REMXXX,(void *)p);
10038 return DC_COMPLETEQUIET;
10039 case 105:
10040 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10041 return DC_ERROR;
10042 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10043 myrpt->powerlevel = REM_MEDPWR;
10044 setrem(myrpt);
10045 rpt_telemetry(myrpt,REMXXX,(void *)p);
10046 return DC_COMPLETEQUIET;
10047 case 106:
10048 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10049 return DC_ERROR;
10050 myrpt->powerlevel = REM_HIPWR;
10051 setrem(myrpt);
10052 rpt_telemetry(myrpt,REMXXX,(void *)p);
10053 return DC_COMPLETEQUIET;
10054 case 107:
10055 multimode_bump_freq(myrpt, -20);
10056 return DC_COMPLETE;
10057 case 108:
10058 multimode_bump_freq(myrpt, -100);
10059 return DC_COMPLETE;
10060 case 109:
10061 multimode_bump_freq(myrpt, -500);
10062 return DC_COMPLETE;
10063 case 110:
10064 multimode_bump_freq(myrpt, 20);
10065 return DC_COMPLETE;
10066 case 111:
10067 multimode_bump_freq(myrpt, 100);
10068 return DC_COMPLETE;
10069 case 112:
10070 multimode_bump_freq(myrpt, 500);
10071 return DC_COMPLETE;
10072 case 113:
10073 myrpt->scantimer = REM_SCANTIME;
10074 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10075 rpt_telemetry(myrpt,REMXXX,(void *)p);
10076 return DC_COMPLETEQUIET;
10077 case 114:
10078 myrpt->scantimer = REM_SCANTIME;
10079 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10080 rpt_telemetry(myrpt,REMXXX,(void *)p);
10081 return DC_COMPLETEQUIET;
10082 case 115:
10083 myrpt->scantimer = REM_SCANTIME;
10084 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10085 rpt_telemetry(myrpt,REMXXX,(void *)p);
10086 return DC_COMPLETEQUIET;
10087 case 116:
10088 myrpt->scantimer = REM_SCANTIME;
10089 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10090 rpt_telemetry(myrpt,REMXXX,(void *)p);
10091 return DC_COMPLETEQUIET;
10092 case 117:
10093 myrpt->scantimer = REM_SCANTIME;
10094 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10095 rpt_telemetry(myrpt,REMXXX,(void *)p);
10096 return DC_COMPLETEQUIET;
10097 case 118:
10098 myrpt->scantimer = REM_SCANTIME;
10099 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10100 rpt_telemetry(myrpt,REMXXX,(void *)p);
10101 return DC_COMPLETEQUIET;
10102 case 119:
10103 if(debug > 3)
10104 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10105
10106 if((!myrpt->tunerequest) &&
10107 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10108 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10109 myrpt->remotetx = 0;
10110 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10111 myrpt->tunerequest = 1;
10112 rpt_telemetry(myrpt,TUNE,NULL);
10113 return DC_COMPLETEQUIET;
10114 }
10115 return DC_ERROR;
10116 case 5:
10117 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10118 return DC_COMPLETEQUIET;
10119 case 140:
10120 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10121 return DC_COMPLETEQUIET;
10122 case 200:
10123 case 201:
10124 case 202:
10125 case 203:
10126 case 204:
10127 case 205:
10128 case 206:
10129 case 207:
10130 case 208:
10131 case 209:
10132 case 210:
10133 case 211:
10134 case 212:
10135 case 213:
10136 case 214:
10137 case 215:
10138 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10139 return DC_COMPLETEQUIET;
10140 default:
10141 break;
10142 }
10143 return DC_INDETERMINATE;
10144 }
10145
10146
10147 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10148 {
10149 time_t now;
10150 int ret,res = 0,src;
10151
10152 if(debug > 6)
10153 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10154
10155 time(&myrpt->last_activity_time);
10156
10157 if(myrpt->hfscanmode){
10158 stop_scan(myrpt);
10159 return 0;
10160 }
10161
10162 time(&now);
10163
10164 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10165 {
10166 myrpt->dtmfidx = -1;
10167 myrpt->dtmfbuf[0] = 0;
10168 myrpt->dtmf_time_rem = 0;
10169 }
10170
10171 if (myrpt->dtmfidx == -1)
10172 {
10173
10174 if (c != myrpt->p.funcchar)
10175 {
10176 if (!myrpt->p.propagate_dtmf)
10177 {
10178 rpt_mutex_lock(&myrpt->lock);
10179 do_dtmf_local(myrpt,c);
10180 rpt_mutex_unlock(&myrpt->lock);
10181 }
10182 return 0;
10183 }
10184 myrpt->dtmfidx = 0;
10185 myrpt->dtmfbuf[0] = 0;
10186 myrpt->dtmf_time_rem = now;
10187 return 0;
10188 }
10189
10190 if (myrpt->dtmfidx >= MAXDTMF)
10191 {
10192 myrpt->dtmfidx = 0;
10193 myrpt->dtmfbuf[0] = 0;
10194 myrpt->dtmf_time_rem = now;
10195 }
10196 if (c == myrpt->p.funcchar)
10197 {
10198
10199 if ((myrpt->dtmfidx < 1) ||
10200 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10201 {
10202 myrpt->dtmfidx = 0;
10203 myrpt->dtmfbuf[0] = 0;
10204 myrpt->dtmf_time_rem = now;
10205 return 0;
10206 }
10207 }
10208 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10209 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10210 myrpt->dtmf_time_rem = now;
10211
10212
10213 src = SOURCE_RMT;
10214 if (phonemode == 2) src = SOURCE_DPHONE;
10215 else if (phonemode) src = SOURCE_PHONE;
10216 else if (phonemode == 4) src = SOURCE_ALT;
10217 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10218
10219 switch(ret){
10220
10221 case DC_INDETERMINATE:
10222 res = 0;
10223 break;
10224
10225 case DC_DOKEY:
10226 if (keyed) *keyed = 1;
10227 res = 0;
10228 break;
10229
10230 case DC_REQ_FLUSH:
10231 myrpt->dtmfidx = 0;
10232 myrpt->dtmfbuf[0] = 0;
10233 res = 0;
10234 break;
10235
10236
10237 case DC_COMPLETE:
10238 res = 1;
10239 case DC_COMPLETEQUIET:
10240 myrpt->totalexecdcommands++;
10241 myrpt->dailyexecdcommands++;
10242 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10243 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10244 myrpt->dtmfbuf[0] = 0;
10245 myrpt->dtmfidx = -1;
10246 myrpt->dtmf_time_rem = 0;
10247 break;
10248
10249 case DC_ERROR:
10250 default:
10251 myrpt->dtmfbuf[0] = 0;
10252 myrpt->dtmfidx = -1;
10253 myrpt->dtmf_time_rem = 0;
10254 res = 0;
10255 break;
10256 }
10257
10258 return res;
10259 }
10260
10261 static int handle_remote_data(struct rpt *myrpt, char *str)
10262 {
10263
10264
10265 char tmp[300],cmd[300],dest[300],src[300],c;
10266 int seq,res;
10267
10268
10269 strncpy(tmp,str,sizeof(tmp) - 1);
10270 if (!strcmp(tmp,discstr)) return 0;
10271 if (!strcmp(tmp,newkeystr))
10272 {
10273 myrpt->newkey = 1;
10274 return 0;
10275 }
10276
10277 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10278 if (tmp[0] == 'I')
10279 {
10280
10281
10282 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10283 {
10284 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10285 return 0;
10286 }
10287 mdc1200_notify(myrpt,src,seq);
10288 return 0;
10289 }
10290 #endif
10291
10292
10293 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10294 {
10295 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10296 return 0;
10297 }
10298 if (strcmp(cmd,"D"))
10299 {
10300 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10301 return 0;
10302 }
10303
10304 if (strcmp(dest,myrpt->name)) return 0;
10305 if (myrpt->p.archivedir)
10306 {
10307 char dtmfstr[100];
10308
10309 sprintf(dtmfstr,"DTMF,%c",c);
10310 donodelog(myrpt,dtmfstr);
10311 }
10312 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10313 if (!c) return(0);
10314 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10315 if (res != 1)
10316 return res;
10317 rpt_telemetry(myrpt,COMPLETE,NULL);
10318 return 0;
10319 }
10320
10321 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10322 {
10323 int res;
10324
10325
10326 if(phonemode == 3)
10327 {
10328 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10329 {
10330 *keyed = 0;
10331 return 0;
10332 }
10333 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10334 {
10335 *keyed = 1;
10336 return 0;
10337 }
10338 }
10339 else
10340 {
10341
10342 if (keyed && *keyed && (c == myrpt->p.endchar))
10343 {
10344 *keyed = 0;
10345 return DC_INDETERMINATE;
10346 }
10347 }
10348 if (myrpt->p.archivedir)
10349 {
10350 char str[100];
10351
10352 sprintf(str,"DTMF(P),%c",c);
10353 donodelog(myrpt,str);
10354 }
10355 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10356 if (res != 1)
10357 return res;
10358 rpt_telemetry(myrpt,COMPLETE,NULL);
10359 return 0;
10360 }
10361
10362 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10363 {
10364 char *val, *s, *s1, *s2, *tele;
10365 char tmp[300], deststr[300] = "";
10366 char sx[320],*sy;
10367 struct ast_format_cap *cap = NULL;
10368
10369
10370 val = node_lookup(myrpt,l->name);
10371 if (!val)
10372 {
10373 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10374 return -1;
10375 }
10376
10377 rpt_mutex_lock(&myrpt->lock);
10378
10379 remque((struct qelem *) l);
10380 rpt_mutex_unlock(&myrpt->lock);
10381 strncpy(tmp,val,sizeof(tmp) - 1);
10382 s = tmp;
10383 s1 = strsep(&s,",");
10384 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10385 {
10386 sy = strchr(s1,'/');
10387 *sy = 0;
10388 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10389 s1 = sx;
10390 }
10391 s2 = strsep(&s,",");
10392 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10393 tele = strchr(deststr, '/');
10394 if (!tele) {
10395 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10396 return -1;
10397 }
10398 *tele++ = 0;
10399 l->elaptime = 0;
10400 l->connecttime = 0;
10401 l->thisconnected = 0;
10402 l->newkey = 0;
10403 l->chan = ast_request(deststr, get_slin_cap(cap), NULL, tele, NULL);
10404 cap = ast_format_cap_destroy(cap);
10405 if (l->chan){
10406 ast_set_read_format_by_id(l->chan, AST_FORMAT_SLINEAR);
10407 ast_set_write_format_by_id(l->chan, AST_FORMAT_SLINEAR);
10408 #ifndef NEW_ASTERISK
10409 l->chan->whentohangup = 0;
10410 #endif
10411 l->chan->appl = "Apprpt";
10412 l->chan->data = "(Remote Rx)";
10413 ast_verb(3, "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10414 deststr, tele, ast_channel_name(l->chan));
10415 l->chan->caller.id.number.valid = 1;
10416 ast_free(l->chan->caller.id.number.str);
10417 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
10418 ast_call(l->chan,tele,999);
10419
10420 }
10421 else
10422 {
10423 ast_verb(3, "Unable to place call to %s/%s on %s\n",
10424 deststr,tele,ast_channel_name(l->chan));
10425 return -1;
10426 }
10427 rpt_mutex_lock(&myrpt->lock);
10428
10429 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10430 rpt_mutex_unlock(&myrpt->lock);
10431 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10432 if (!l->phonemode) send_newkey(l->chan);
10433 return 0;
10434 }
10435
10436
10437 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10438 {
10439 int res;
10440 pthread_attr_t attr;
10441 char cmd[MAXDTMF+1] = "",c;
10442
10443
10444 c = c_in & 0x7f;
10445 if (myrpt->p.archivedir)
10446 {
10447 char str[100];
10448
10449 sprintf(str,"DTMF,MAIN,%c",c);
10450 donodelog(myrpt,str);
10451 }
10452 if (c == myrpt->p.endchar)
10453 {
10454
10455 if (myrpt->p.simple && myrpt->callmode)
10456 {
10457 if(debug)
10458 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10459 rpt_mutex_lock(&myrpt->lock);
10460 myrpt->callmode = 0;
10461 myrpt->macropatch=0;
10462 channel_revert(myrpt);
10463 rpt_mutex_unlock(&myrpt->lock);
10464 rpt_telemetry(myrpt,TERM,NULL);
10465 return;
10466 }
10467 rpt_mutex_lock(&myrpt->lock);
10468 myrpt->stopgen = 1;
10469 if (myrpt->cmdnode[0])
10470 {
10471 myrpt->cmdnode[0] = 0;
10472 myrpt->dtmfidx = -1;
10473 myrpt->dtmfbuf[0] = 0;
10474 rpt_mutex_unlock(&myrpt->lock);
10475 rpt_telemetry(myrpt,COMPLETE,NULL);
10476 return;
10477 }
10478 else if(!myrpt->inpadtest)
10479 {
10480 rpt_mutex_unlock(&myrpt->lock);
10481 if (myrpt->p.propagate_phonedtmf)
10482 do_dtmf_phone(myrpt,NULL,c);
10483 return;
10484 }
10485 else
10486 rpt_mutex_unlock(&myrpt->lock);
10487 }
10488 rpt_mutex_lock(&myrpt->lock);
10489 if (myrpt->cmdnode[0])
10490 {
10491 rpt_mutex_unlock(&myrpt->lock);
10492 send_link_dtmf(myrpt,c);
10493 return;
10494 }
10495 if (!myrpt->p.simple)
10496 {
10497 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10498 {
10499 myrpt->dtmfidx = 0;
10500 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10501 rpt_mutex_unlock(&myrpt->lock);
10502 time(&myrpt->dtmf_time);
10503 return;
10504 }
10505 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10506 {
10507 time(&myrpt->dtmf_time);
10508
10509 if (myrpt->dtmfidx < MAXDTMF)
10510 {
10511 int src;
10512
10513 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10514 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10515
10516 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10517
10518 rpt_mutex_unlock(&myrpt->lock);
10519 src = SOURCE_RPT;
10520 if (c_in & 0x80) src = SOURCE_ALT;
10521 res = collect_function_digits(myrpt, cmd, src, NULL);
10522 rpt_mutex_lock(&myrpt->lock);
10523 switch(res){
10524 case DC_INDETERMINATE:
10525 break;
10526 case DC_REQ_FLUSH:
10527 myrpt->dtmfidx = 0;
10528 myrpt->dtmfbuf[0] = 0;
10529 break;
10530 case DC_COMPLETE:
10531 case DC_COMPLETEQUIET:
10532 myrpt->totalexecdcommands++;
10533 myrpt->dailyexecdcommands++;
10534 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10535 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10536 myrpt->dtmfbuf[0] = 0;
10537 myrpt->dtmfidx = -1;
10538 myrpt->dtmf_time = 0;
10539 break;
10540
10541 case DC_ERROR:
10542 default:
10543 myrpt->dtmfbuf[0] = 0;
10544 myrpt->dtmfidx = -1;
10545 myrpt->dtmf_time = 0;
10546 break;
10547 }
10548 if(res != DC_INDETERMINATE) {
10549 rpt_mutex_unlock(&myrpt->lock);
10550 return;
10551 }
10552 }
10553 }
10554 }
10555 else
10556 {
10557 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10558 {
10559 myrpt->callmode = 1;
10560 myrpt->patchnoct = 0;
10561 myrpt->patchquiet = 0;
10562 myrpt->patchfarenddisconnect = 0;
10563 myrpt->patchdialtime = 0;
10564 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10565 myrpt->cidx = 0;
10566 myrpt->exten[myrpt->cidx] = 0;
10567 rpt_mutex_unlock(&myrpt->lock);
10568 pthread_attr_init(&attr);
10569 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10570 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10571 return;
10572 }
10573 }
10574 if (myrpt->callmode == 1)
10575 {
10576 myrpt->exten[myrpt->cidx++] = c;
10577 myrpt->exten[myrpt->cidx] = 0;
10578
10579 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10580 {
10581
10582 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10583 myrpt->exten,1,NULL))
10584 {
10585 myrpt->callmode = 2;
10586 rpt_mutex_unlock(&myrpt->lock);
10587 if(!myrpt->patchquiet)
10588 rpt_telemetry(myrpt,PROC,NULL);
10589 return;
10590 }
10591 else
10592 {
10593 myrpt->calldigittimer = 1;
10594 }
10595 }
10596
10597 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10598 {
10599
10600 myrpt->callmode = 4;
10601 }
10602 rpt_mutex_unlock(&myrpt->lock);
10603 return;
10604 }
10605 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10606 {
10607 myrpt->mydtmf = c;
10608 }
10609 rpt_mutex_unlock(&myrpt->lock);
10610 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10611 do_dtmf_phone(myrpt,NULL,c);
10612 return;
10613 }
10614
10615
10616
10617
10618 static void queue_id(struct rpt *myrpt)
10619 {
10620 if(myrpt->p.idtime){
10621 myrpt->mustid = myrpt->tailid = 0;
10622 myrpt->idtimer = myrpt->p.idtime;
10623 rpt_mutex_unlock(&myrpt->lock);
10624 rpt_telemetry(myrpt,ID,NULL);
10625 rpt_mutex_lock(&myrpt->lock);
10626 }
10627 }
10628
10629
10630
10631
10632 static void do_scheduler(struct rpt *myrpt)
10633 {
10634 int i,res;
10635
10636 #ifdef NEW_ASTERISK
10637 struct ast_tm tmnow;
10638 #else
10639 struct tm tmnow;
10640 #endif
10641 struct ast_variable *skedlist;
10642 char *strs[5],*vp,*val,value[100];
10643
10644 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10645
10646 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10647 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10648
10649
10650
10651 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10652 return;
10653
10654 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10655
10656
10657
10658 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10659 myrpt->dailykeyups = 0;
10660 myrpt->dailytxtime = 0;
10661 myrpt->dailykerchunks = 0;
10662 myrpt->dailyexecdcommands = 0;
10663 }
10664
10665 if(tmnow.tm_sec != 0)
10666 return;
10667
10668
10669
10670
10671
10672
10673 if (myrpt->remote)
10674 return;
10675
10676
10677
10678 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10679 if(debug > 6)
10680 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10681 return;
10682 }
10683
10684 if(!myrpt->p.skedstanzaname){
10685 if(debug > 6)
10686 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10687 return;
10688 }
10689
10690
10691 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10692
10693 if(debug > 6){
10694 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10695 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10696 }
10697
10698 for(; skedlist; skedlist = skedlist->next){
10699 if(debug > 6)
10700 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10701 strncpy(value,skedlist->value,99);
10702 value[99] = 0;
10703
10704 for( i = 0, vp = value ; i < 5; i++){
10705 if(!*vp)
10706 break;
10707 while((*vp == ' ') || (*vp == 0x09))
10708 vp++;
10709 strs[i] = vp;
10710 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10711 vp++;
10712 if(*vp)
10713 *vp++ = 0;
10714 }
10715 if(debug > 6)
10716 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10717 strs[0], strs[1], strs[2], strs[3], strs[4]);
10718 if(i == 5){
10719 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10720 continue;
10721 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10722 continue;
10723 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10724 continue;
10725 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10726 continue;
10727 if(atoi(strs[4]) == 7)
10728 strs[4] = "0";
10729 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10730 continue;
10731 if(debug)
10732 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10733 if(atoi(skedlist->name) == 0)
10734 return;
10735 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10736 if (!val){
10737 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10738 return;
10739 }
10740 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10741 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10742 skedlist->name);
10743 return;
10744 }
10745 myrpt->macrotimer = MACROTIME;
10746 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10747 }
10748 else{
10749 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10750 skedlist->name, skedlist->value);
10751 }
10752 }
10753
10754 }
10755
10756
10757 static void *rpt(void *this)
10758 {
10759 struct rpt *myrpt = (struct rpt *)this;
10760 char *tele,*idtalkover,c,myfirst,*p;
10761 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10762 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10763 struct ast_channel *who;
10764 struct dahdi_confinfo ci;
10765 time_t t;
10766 struct rpt_link *l,*m;
10767 struct rpt_tele *telem;
10768 char tmpstr[300],lstr[MAXLINKLIST];
10769 struct ast_format_cap *cap = NULL;
10770
10771
10772 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10773 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10774 mkdir(tmpstr,0600);
10775 rpt_mutex_lock(&myrpt->lock);
10776
10777 telem = myrpt->tele.next;
10778 while(telem != &myrpt->tele)
10779 {
10780 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10781 telem = telem->next;
10782 }
10783 rpt_mutex_unlock(&myrpt->lock);
10784
10785 for(i = 0; i < nrpts; i++)
10786 {
10787 if (&rpt_vars[i] == myrpt)
10788 {
10789 load_rpt_vars(i,0);
10790 break;
10791 }
10792 }
10793
10794 rpt_mutex_lock(&myrpt->lock);
10795 while(myrpt->xlink)
10796 {
10797 myrpt->xlink = 3;
10798 rpt_mutex_unlock(&myrpt->lock);
10799 usleep(100000);
10800 rpt_mutex_lock(&myrpt->lock);
10801 }
10802 #ifdef HAVE_IOPERM
10803 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10804 (ioperm(myrpt->p.iobase,1,1) == -1))
10805 {
10806 rpt_mutex_unlock(&myrpt->lock);
10807 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10808 myrpt->rpt_thread = AST_PTHREADT_STOP;
10809 pthread_exit(NULL);
10810 }
10811 #endif
10812 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10813 tele = strchr(tmpstr,'/');
10814 if (!tele)
10815 {
10816 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10817 rpt_mutex_unlock(&myrpt->lock);
10818 myrpt->rpt_thread = AST_PTHREADT_STOP;
10819 pthread_exit(NULL);
10820 }
10821 *tele++ = 0;
10822 myrpt->rxchannel = ast_request(tmpstr, get_slin_cap(cap), NULL, tele, NULL);
10823 cap = ast_format_cap_destroy(cap);
10824 myrpt->dahdirxchannel = NULL;
10825 if (!strcasecmp(tmpstr,"DAHDI"))
10826 myrpt->dahdirxchannel = myrpt->rxchannel;
10827 if (myrpt->rxchannel)
10828 {
10829 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10830 {
10831 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10832 rpt_mutex_unlock(&myrpt->lock);
10833 ast_hangup(myrpt->rxchannel);
10834 myrpt->rpt_thread = AST_PTHREADT_STOP;
10835 pthread_exit(NULL);
10836 }
10837 ast_set_read_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10838 ast_set_write_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10839 #ifdef AST_CDR_FLAG_POST_DISABLED
10840 if (myrpt->rxchannel->cdr)
10841 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10842 #endif
10843 #ifndef NEW_ASTERISK
10844 myrpt->rxchannel->whentohangup = 0;
10845 #endif
10846 myrpt->rxchannel->appl = "Apprpt";
10847 myrpt->rxchannel->data = "(Repeater Rx)";
10848 ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
10849 tmpstr,tele,myrpt->rxchannel->name);
10850 ast_call(myrpt->rxchannel,tele,999);
10851 if (myrpt->rxchannel->_state != AST_STATE_UP)
10852 {
10853 rpt_mutex_unlock(&myrpt->lock);
10854 ast_hangup(myrpt->rxchannel);
10855 myrpt->rpt_thread = AST_PTHREADT_STOP;
10856 pthread_exit(NULL);
10857 }
10858 }
10859 else
10860 {
10861 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10862 rpt_mutex_unlock(&myrpt->lock);
10863 myrpt->rpt_thread = AST_PTHREADT_STOP;
10864 pthread_exit(NULL);
10865 }
10866 myrpt->dahditxchannel = NULL;
10867 if (myrpt->txchanname)
10868 {
10869 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10870 tele = strchr(tmpstr,'/');
10871 if (!tele)
10872 {
10873 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10874 rpt_mutex_unlock(&myrpt->lock);
10875 ast_hangup(myrpt->rxchannel);
10876 myrpt->rpt_thread = AST_PTHREADT_STOP;
10877 pthread_exit(NULL);
10878 }
10879 *tele++ = 0;
10880 myrpt->txchannel = ast_request(tmpstr, get_slin_cap(cap), NULL, tele, NULL);
10881 cap = ast_format_cap_destroy(cap);
10882 if (!strcasecmp(tmpstr,"DAHDI"))
10883 myrpt->dahditxchannel = myrpt->txchannel;
10884 if (myrpt->txchannel)
10885 {
10886 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10887 {
10888 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10889 rpt_mutex_unlock(&myrpt->lock);
10890 ast_hangup(myrpt->txchannel);
10891 ast_hangup(myrpt->rxchannel);
10892 myrpt->rpt_thread = AST_PTHREADT_STOP;
10893 pthread_exit(NULL);
10894 }
10895 ast_set_read_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR);
10896 ast_set_write_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR);
10897 #ifdef AST_CDR_FLAG_POST_DISABLED
10898 if (myrpt->txchannel->cdr)
10899 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10900 #endif
10901 #ifndef NEW_ASTERISK
10902 myrpt->txchannel->whentohangup = 0;
10903 #endif
10904 myrpt->txchannel->appl = "Apprpt";
10905 myrpt->txchannel->data = "(Repeater Tx)";
10906 ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
10907 tmpstr,tele,myrpt->txchannel->name);
10908 ast_call(myrpt->txchannel,tele,999);
10909 if (myrpt->rxchannel->_state != AST_STATE_UP)
10910 {
10911 rpt_mutex_unlock(&myrpt->lock);
10912 ast_hangup(myrpt->rxchannel);
10913 ast_hangup(myrpt->txchannel);
10914 myrpt->rpt_thread = AST_PTHREADT_STOP;
10915 pthread_exit(NULL);
10916 }
10917 }
10918 else
10919 {
10920 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10921 rpt_mutex_unlock(&myrpt->lock);
10922 ast_hangup(myrpt->rxchannel);
10923 myrpt->rpt_thread = AST_PTHREADT_STOP;
10924 pthread_exit(NULL);
10925 }
10926 }
10927 else
10928 {
10929 myrpt->txchannel = myrpt->rxchannel;
10930 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10931 myrpt->dahditxchannel = myrpt->txchannel;
10932 }
10933 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10934 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10935
10936 myrpt->pchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
10937 cap = ast_format_cap_destroy(cap);
10938 if (!myrpt->pchannel)
10939 {
10940 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10941 rpt_mutex_unlock(&myrpt->lock);
10942 if (myrpt->txchannel != myrpt->rxchannel)
10943 ast_hangup(myrpt->txchannel);
10944 ast_hangup(myrpt->rxchannel);
10945 myrpt->rpt_thread = AST_PTHREADT_STOP;
10946 pthread_exit(NULL);
10947 }
10948 #ifdef AST_CDR_FLAG_POST_DISABLED
10949 if (myrpt->pchannel->cdr)
10950 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10951 #endif
10952 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10953 if (!myrpt->dahditxchannel)
10954 {
10955
10956 myrpt->dahditxchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
10957 cap = ast_format_cap_destroy(cap);
10958 if (!myrpt->dahditxchannel)
10959 {
10960 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10961 rpt_mutex_unlock(&myrpt->lock);
10962 if (myrpt->txchannel != myrpt->rxchannel)
10963 ast_hangup(myrpt->txchannel);
10964 ast_hangup(myrpt->rxchannel);
10965 myrpt->rpt_thread = AST_PTHREADT_STOP;
10966 pthread_exit(NULL);
10967 }
10968 ast_set_read_format_by_id(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10969 ast_set_write_format_by_id(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10970 #ifdef AST_CDR_FLAG_POST_DISABLED
10971 if (myrpt->dahditxchannel->cdr)
10972 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10973 #endif
10974 }
10975
10976 myrpt->monchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
10977 cap = ast_format_cap_destroy(cap);
10978 if (!myrpt->monchannel)
10979 {
10980 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10981 rpt_mutex_unlock(&myrpt->lock);
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 ast_set_read_format_by_id(myrpt->monchannel,AST_FORMAT_SLINEAR);
10989 ast_set_write_format_by_id(myrpt->monchannel,AST_FORMAT_SLINEAR);
10990 #ifdef AST_CDR_FLAG_POST_DISABLED
10991 if (myrpt->monchannel->cdr)
10992 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10993 #endif
10994
10995 ci.chan = 0;
10996 ci.confno = -1;
10997 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10998
10999 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11000 {
11001 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11002 rpt_mutex_unlock(&myrpt->lock);
11003 ast_hangup(myrpt->pchannel);
11004 ast_hangup(myrpt->monchannel);
11005 if (myrpt->txchannel != myrpt->rxchannel)
11006 ast_hangup(myrpt->txchannel);
11007 ast_hangup(myrpt->rxchannel);
11008 myrpt->rpt_thread = AST_PTHREADT_STOP;
11009 pthread_exit(NULL);
11010 }
11011
11012 myrpt->txconf = ci.confno;
11013
11014 ci.chan = 0;
11015 ci.confno = -1;
11016 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
11017 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
11018
11019 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11020 {
11021 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11022 rpt_mutex_unlock(&myrpt->lock);
11023 ast_hangup(myrpt->pchannel);
11024 ast_hangup(myrpt->monchannel);
11025 if (myrpt->txchannel != myrpt->rxchannel)
11026 ast_hangup(myrpt->txchannel);
11027 ast_hangup(myrpt->rxchannel);
11028 myrpt->rpt_thread = AST_PTHREADT_STOP;
11029 pthread_exit(NULL);
11030 }
11031
11032 myrpt->conf = ci.confno;
11033
11034 ci.chan = 0;
11035 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11036 (myrpt->dahditxchannel == myrpt->txchannel))
11037 {
11038
11039 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11040 {
11041 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11042 rpt_mutex_unlock(&myrpt->lock);
11043 ast_hangup(myrpt->pchannel);
11044 ast_hangup(myrpt->monchannel);
11045 if (myrpt->txchannel != myrpt->rxchannel)
11046 ast_hangup(myrpt->txchannel);
11047 ast_hangup(myrpt->rxchannel);
11048 myrpt->rpt_thread = AST_PTHREADT_STOP;
11049 pthread_exit(NULL);
11050 }
11051 ci.confmode = DAHDI_CONF_MONITORTX;
11052 }
11053 else
11054 {
11055 ci.confno = myrpt->txconf;
11056 ci.confmode = DAHDI_CONF_CONFANNMON;
11057 }
11058
11059 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11060 {
11061 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11062 rpt_mutex_unlock(&myrpt->lock);
11063 ast_hangup(myrpt->pchannel);
11064 ast_hangup(myrpt->monchannel);
11065 if (myrpt->txchannel != myrpt->rxchannel)
11066 ast_hangup(myrpt->txchannel);
11067 ast_hangup(myrpt->rxchannel);
11068 myrpt->rpt_thread = AST_PTHREADT_STOP;
11069 pthread_exit(NULL);
11070 }
11071
11072 myrpt->parrotchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
11073 cap = ast_format_cap_destroy(cap);
11074 if (!myrpt->parrotchannel)
11075 {
11076 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11077 rpt_mutex_unlock(&myrpt->lock);
11078 if (myrpt->txchannel != myrpt->rxchannel)
11079 ast_hangup(myrpt->txchannel);
11080 ast_hangup(myrpt->rxchannel);
11081 myrpt->rpt_thread = AST_PTHREADT_STOP;
11082 pthread_exit(NULL);
11083 }
11084 ast_set_read_format_by_id(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11085 ast_set_write_format_by_id(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11086 #ifdef AST_CDR_FLAG_POST_DISABLED
11087 if (myrpt->parrotchannel->cdr)
11088 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11089 #endif
11090
11091 myrpt->voxchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
11092 cap = ast_format_cap_destroy(cap);
11093 if (!myrpt->voxchannel)
11094 {
11095 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11096 rpt_mutex_unlock(&myrpt->lock);
11097 if (myrpt->txchannel != myrpt->rxchannel)
11098 ast_hangup(myrpt->txchannel);
11099 ast_hangup(myrpt->rxchannel);
11100 myrpt->rpt_thread = AST_PTHREADT_STOP;
11101 pthread_exit(NULL);
11102 }
11103 ast_set_read_format_by_id(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11104 ast_set_write_format_by_id(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11105 #ifdef AST_CDR_FLAG_POST_DISABLED
11106 if (myrpt->voxchannel->cdr)
11107 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11108 #endif
11109
11110 myrpt->txpchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
11111 cap = ast_format_cap_destroy(cap);
11112 if (!myrpt->txpchannel)
11113 {
11114 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11115 rpt_mutex_unlock(&myrpt->lock);
11116 ast_hangup(myrpt->pchannel);
11117 ast_hangup(myrpt->monchannel);
11118 if (myrpt->txchannel != myrpt->rxchannel)
11119 ast_hangup(myrpt->txchannel);
11120 ast_hangup(myrpt->rxchannel);
11121 myrpt->rpt_thread = AST_PTHREADT_STOP;
11122 pthread_exit(NULL);
11123 }
11124 #ifdef AST_CDR_FLAG_POST_DISABLED
11125 if (myrpt->txpchannel->cdr)
11126 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11127 #endif
11128
11129 ci.chan = 0;
11130 ci.confno = myrpt->txconf;
11131 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11132
11133 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11134 {
11135 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11136 rpt_mutex_unlock(&myrpt->lock);
11137 ast_hangup(myrpt->txpchannel);
11138 ast_hangup(myrpt->monchannel);
11139 if (myrpt->txchannel != myrpt->rxchannel)
11140 ast_hangup(myrpt->txchannel);
11141 ast_hangup(myrpt->rxchannel);
11142 myrpt->rpt_thread = AST_PTHREADT_STOP;
11143 pthread_exit(NULL);
11144 }
11145
11146 myrpt->iofd = -1;
11147 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11148 {
11149 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11150 rpt_mutex_unlock(&myrpt->lock);
11151 ast_hangup(myrpt->pchannel);
11152 if (myrpt->txchannel != myrpt->rxchannel)
11153 ast_hangup(myrpt->txchannel);
11154 ast_hangup(myrpt->rxchannel);
11155 pthread_exit(NULL);
11156 }
11157
11158
11159
11160 myrpt->links.next = &myrpt->links;
11161 myrpt->links.prev = &myrpt->links;
11162 myrpt->tailtimer = 0;
11163 myrpt->totimer = 0;
11164 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11165 myrpt->idtimer = myrpt->p.politeid;
11166 myrpt->mustid = myrpt->tailid = 0;
11167 myrpt->callmode = 0;
11168 myrpt->tounkeyed = 0;
11169 myrpt->tonotify = 0;
11170 myrpt->retxtimer = 0;
11171 myrpt->rerxtimer = 0;
11172 myrpt->skedtimer = 0;
11173 myrpt->tailevent = 0;
11174 lasttx = 0;
11175 myrpt->keyed = 0;
11176 myrpt->txkeyed = 0;
11177 time(&myrpt->lastkeyedtime);
11178 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11179 time(&myrpt->lasttxkeyedtime);
11180 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11181 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11182 myrpt->dtmfidx = -1;
11183 myrpt->dtmfbuf[0] = 0;
11184 myrpt->rem_dtmfidx = -1;
11185 myrpt->rem_dtmfbuf[0] = 0;
11186 myrpt->dtmf_time = 0;
11187 myrpt->rem_dtmf_time = 0;
11188 myrpt->inpadtest = 0;
11189 myrpt->disgorgetime = 0;
11190 myrpt->lastnodewhichkeyedusup[0] = '\0';
11191 myrpt->dailytxtime = 0;
11192 myrpt->totaltxtime = 0;
11193 myrpt->dailykeyups = 0;
11194 myrpt->totalkeyups = 0;
11195 myrpt->dailykerchunks = 0;
11196 myrpt->totalkerchunks = 0;
11197 myrpt->dailyexecdcommands = 0;
11198 myrpt->totalexecdcommands = 0;
11199 myrpt->timeouts = 0;
11200 myrpt->exten[0] = '\0';
11201 myrpt->lastdtmfcommand[0] = '\0';
11202 voxinit_rpt(myrpt,1);
11203 myrpt->wasvox = 0;
11204 if (myrpt->p.startupmacro)
11205 {
11206 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11207 }
11208 rpt_mutex_unlock(&myrpt->lock);
11209 val = 1;
11210 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11211 val = 1;
11212 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11213 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11214 dtmfed = 0;
11215 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11216 lastmyrx = 0;
11217 myfirst = 0;
11218 while (ms >= 0)
11219 {
11220 struct ast_frame *f,*f1,*f2;
11221 struct ast_channel *cs[300],*cs1[300];
11222 int totx=0,elap=0,n,x,toexit=0;
11223
11224
11225 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11226 struct rpt_link *dl;
11227 struct rpt_tele *dt;
11228
11229 myrpt->disgorgetime = 0;
11230 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11231 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11232 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11233 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11234 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11235 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11236
11237 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11238 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11239 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11240 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11241 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11242 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11243 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11244 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11245 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11246 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11247
11248 dl = myrpt->links.next;
11249 while(dl != &myrpt->links){
11250 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11251 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11252 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11253 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11254 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11255 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11256 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11257 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11258 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11259 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11260 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11261 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11262 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11263 dl = dl->next;
11264 }
11265
11266 dt = myrpt->tele.next;
11267 if(dt != &myrpt->tele)
11268 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11269 while(dt != &myrpt->tele){
11270 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11271 dt = dt->next;
11272 }
11273 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11274
11275 }
11276
11277
11278 if (myrpt->reload)
11279 {
11280 struct rpt_tele *inner_telem;
11281
11282 rpt_mutex_lock(&myrpt->lock);
11283 inner_telem = myrpt->tele.next;
11284 while(inner_telem != &myrpt->tele)
11285 {
11286 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11287 inner_telem = inner_telem->next;
11288 }
11289 myrpt->reload = 0;
11290 rpt_mutex_unlock(&myrpt->lock);
11291 usleep(10000);
11292
11293 for(i = 0; i < nrpts; i++)
11294 {
11295 if (&rpt_vars[i] == myrpt)
11296 {
11297 load_rpt_vars(i,0);
11298 break;
11299 }
11300 }
11301 }
11302
11303 rpt_mutex_lock(&myrpt->lock);
11304 if (ast_check_hangup(myrpt->rxchannel)) break;
11305 if (ast_check_hangup(myrpt->txchannel)) break;
11306 if (ast_check_hangup(myrpt->pchannel)) break;
11307 if (ast_check_hangup(myrpt->monchannel)) break;
11308 if (myrpt->parrotchannel &&
11309 ast_check_hangup(myrpt->parrotchannel)) break;
11310 if (myrpt->voxchannel &&
11311 ast_check_hangup(myrpt->voxchannel)) break;
11312 if (ast_check_hangup(myrpt->txpchannel)) break;
11313 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11314
11315
11316 myrpt->localtx = myrpt->keyed;
11317
11318 l = myrpt->links.next;
11319 remrx = 0;
11320 while(l != &myrpt->links)
11321 {
11322 if (l->lastrx){
11323 remrx = 1;
11324 if(l->name[0] != '0')
11325 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11326 }
11327 l = l->next;
11328 }
11329
11330 if(myrpt->p.idtime)
11331 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11332
11333
11334 if (myrpt->p.duplex > 1)
11335 {
11336 totx = myrpt->callmode;
11337 totx = totx || myrpt->localtx;
11338 }
11339 else
11340 {
11341 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11342
11343 if (lastmyrx != myrx)
11344 {
11345 voxinit_rpt(myrpt,!myrx);
11346 lastmyrx = myrx;
11347 }
11348 totx = 0;
11349 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11350 {
11351 if (myrpt->voxtostate)
11352 {
11353 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11354 myrpt->voxtostate = 0;
11355 }
11356 else
11357 {
11358 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11359 myrpt->voxtostate = 1;
11360 }
11361 }
11362 if (!myrpt->voxtostate)
11363 totx = myrpt->callmode && myrpt->wasvox;
11364 }
11365
11366 identqueued = 0;
11367 localmsgqueued = 0;
11368 othertelemqueued = 0;
11369 tailmessagequeued = 0;
11370 ctqueued = 0;
11371 telem = myrpt->tele.next;
11372 while(telem != &myrpt->tele)
11373 {
11374 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11375 identqueued = 1;
11376 }
11377 else if(telem->mode == TAILMSG)
11378 {
11379 tailmessagequeued = 1;
11380 }
11381 else if(telem->mode == STATS_TIME_LOCAL)
11382 {
11383 localmsgqueued = 1;
11384 }
11385 else
11386 {
11387 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11388 othertelemqueued = 1;
11389 else
11390 ctqueued = 1;
11391 }
11392 telem = telem->next;
11393 }
11394
11395
11396 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11397
11398
11399 myrpt->exttx = totx;
11400 totx = totx || myrpt->dtmf_local_timer;
11401
11402 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11403
11404 totx = totx || remrx;
11405
11406 if (myrpt->p.duplex > 0)
11407 totx = totx || identqueued || ctqueued || localmsgqueued;
11408
11409 if (myrpt->p.duplex > 1)
11410 {
11411 totx = totx || (myrpt->dtmfidx > -1) ||
11412 myrpt->cmdnode[0];
11413 }
11414
11415 totx = totx || (myrpt->parrotstate > 1);
11416
11417 if (!totx)
11418 {
11419 myrpt->totimer = myrpt->p.totime;
11420 myrpt->tounkeyed = 0;
11421 myrpt->tonotify = 0;
11422 }
11423 else{
11424 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11425 myrpt->p.althangtime :
11426 myrpt->p.hangtime;
11427 }
11428
11429 totx = totx && myrpt->totimer;
11430
11431 if ((!myrpt->totimer) && (!myrpt->tonotify))
11432 {
11433 myrpt->tonotify = 1;
11434 myrpt->timeouts++;
11435 rpt_mutex_unlock(&myrpt->lock);
11436 rpt_telemetry(myrpt,TIMEOUT,NULL);
11437 rpt_mutex_lock(&myrpt->lock);
11438 }
11439
11440
11441 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11442 {
11443 myrpt->tounkeyed = 1;
11444 }
11445 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11446 {
11447 myrpt->totimer = myrpt->p.totime;
11448 myrpt->tounkeyed = 0;
11449 myrpt->tonotify = 0;
11450 rpt_mutex_unlock(&myrpt->lock);
11451 continue;
11452 }
11453
11454 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11455 {
11456 if(debug)
11457 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11458 myrpt->callmode = 0;
11459 myrpt->macropatch=0;
11460 channel_revert(myrpt);
11461 }
11462
11463 if (!myrpt->totimer) myrpt->tailtimer = 0;
11464
11465 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11466
11467
11468 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11469 int hasid = 0,hastalkover = 0;
11470
11471 telem = myrpt->tele.next;
11472 while(telem != &myrpt->tele){
11473 if(telem->mode == ID){
11474 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11475 hasid = 1;
11476 }
11477 if(telem->mode == TAILMSG){
11478 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11479 }
11480 if (telem->mode == IDTALKOVER) hastalkover = 1;
11481 telem = telem->next;
11482 }
11483 rpt_mutex_unlock(&myrpt->lock);
11484 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11485 rpt_mutex_lock(&myrpt->lock);
11486 }
11487
11488
11489
11490
11491
11492 if(myrpt->mustid && (!myrpt->idtimer))
11493 queue_id(myrpt);
11494
11495 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11496 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11497 {
11498 myrpt->tailid = 1;
11499 }
11500
11501
11502
11503 if(myrpt->tailevent){
11504 myrpt->tailevent = 0;
11505 if(myrpt->tailid){
11506 totx = 1;
11507 queue_id(myrpt);
11508 }
11509 else if ((myrpt->p.tailmessages[0]) &&
11510 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11511 totx = 1;
11512 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11513 rpt_mutex_unlock(&myrpt->lock);
11514 rpt_telemetry(myrpt, TAILMSG, NULL);
11515 rpt_mutex_lock(&myrpt->lock);
11516 }
11517 }
11518
11519
11520
11521
11522 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11523 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11524 myrpt->txrealkeyed = totx;
11525 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11526 if (totx && (!lasttx))
11527 {
11528 char mydate[100],myfname[100];
11529 time_t myt;
11530
11531 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11532 if (myrpt->p.archivedir)
11533 {
11534 long blocksleft;
11535
11536 time(&myt);
11537 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11538 localtime(&myt));
11539 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11540 myrpt->name,mydate);
11541 myrpt->monstream = ast_writefile(myfname,"wav49",
11542 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11543 if (myrpt->p.monminblocks)
11544 {
11545 blocksleft = diskavail(myrpt);
11546 if (blocksleft >= myrpt->p.monminblocks)
11547 donodelog(myrpt,"TXKEY,MAIN");
11548 } else donodelog(myrpt,"TXKEY,MAIN");
11549 }
11550 lasttx = 1;
11551 myrpt->txkeyed = 1;
11552 time(&myrpt->lasttxkeyedtime);
11553 myrpt->dailykeyups++;
11554 myrpt->totalkeyups++;
11555 rpt_mutex_unlock(&myrpt->lock);
11556 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11557 rpt_mutex_lock(&myrpt->lock);
11558 }
11559 if ((!totx) && lasttx)
11560 {
11561 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11562 myrpt->monstream = NULL;
11563
11564 lasttx = 0;
11565 myrpt->txkeyed = 0;
11566 time(&myrpt->lasttxkeyedtime);
11567 rpt_mutex_unlock(&myrpt->lock);
11568 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11569 rpt_mutex_lock(&myrpt->lock);
11570 donodelog(myrpt,"TXUNKEY,MAIN");
11571 }
11572 time(&t);
11573
11574 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11575 {
11576 myrpt->inpadtest = 0;
11577 myrpt->dtmfidx = -1;
11578 myrpt->dtmfbuf[0] = 0;
11579 }
11580
11581 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11582 {
11583 myrpt->inpadtest = 0;
11584 myrpt->rem_dtmfidx = -1;
11585 myrpt->rem_dtmfbuf[0] = 0;
11586 }
11587
11588 if (myrpt->exttx && myrpt->parrotchannel &&
11589 myrpt->p.parrotmode && (!myrpt->parrotstate))
11590 {
11591 char myfname[300];
11592
11593 ci.confno = myrpt->conf;
11594 ci.confmode = DAHDI_CONF_CONFANNMON;
11595 ci.chan = 0;
11596
11597
11598 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11599 {
11600 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11601 break;
11602 }
11603
11604 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11605 strcat(myfname,".wav");
11606 unlink(myfname);
11607 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11608 myrpt->parrotstate = 1;
11609 myrpt->parrottimer = myrpt->p.parrottime;
11610 if (myrpt->parrotstream)
11611 ast_closestream(myrpt->parrotstream);
11612 myrpt->parrotstream = NULL;
11613 myrpt->parrotstream = ast_writefile(myfname,"wav",
11614 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11615 }
11616
11617
11618
11619 l = myrpt->links.next;
11620 while(l != &myrpt->links)
11621 {
11622 if (l->killme)
11623 {
11624
11625 remque((struct qelem *) l);
11626 if (!strcmp(myrpt->cmdnode,l->name))
11627 myrpt->cmdnode[0] = 0;
11628 rpt_mutex_unlock(&myrpt->lock);
11629
11630 if (l->chan) ast_hangup(l->chan);
11631 ast_hangup(l->pchan);
11632 ast_free(l);
11633 rpt_mutex_lock(&myrpt->lock);
11634
11635 l = myrpt->links.next;
11636 continue;
11637 }
11638 l = l->next;
11639 }
11640 n = 0;
11641 cs[n++] = myrpt->rxchannel;
11642 cs[n++] = myrpt->pchannel;
11643 cs[n++] = myrpt->monchannel;
11644 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11645 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11646 cs[n++] = myrpt->txpchannel;
11647 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11648 if (myrpt->dahditxchannel != myrpt->txchannel)
11649 cs[n++] = myrpt->dahditxchannel;
11650 l = myrpt->links.next;
11651 while(l != &myrpt->links)
11652 {
11653 if ((!l->killme) && (!l->disctime) && l->chan)
11654 {
11655 cs[n++] = l->chan;
11656 cs[n++] = l->pchan;
11657 }
11658 l = l->next;
11659 }
11660 if ((myrpt->topkeystate == 1) &&
11661 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11662 {
11663 myrpt->topkeystate = 2;
11664 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11665 topcompar);
11666 }
11667 rpt_mutex_unlock(&myrpt->lock);
11668
11669 if (myrpt->topkeystate == 2)
11670 {
11671 rpt_telemetry(myrpt,TOPKEY,NULL);
11672 myrpt->topkeystate = 3;
11673 }
11674 ms = MSWAIT;
11675 for(x = 0; x < n; x++)
11676 {
11677 int s = -(-x - myrpt->scram - 1) % n;
11678 cs1[x] = cs[s];
11679 }
11680 myrpt->scram++;
11681 who = ast_waitfor_n(cs1,n,&ms);
11682 if (who == NULL) ms = 0;
11683 elap = MSWAIT - ms;
11684 rpt_mutex_lock(&myrpt->lock);
11685 l = myrpt->links.next;
11686 while(l != &myrpt->links)
11687 {
11688 int myrx;
11689
11690 if (l->voxtotimer) l->voxtotimer -= elap;
11691 if (l->voxtotimer < 0) l->voxtotimer = 0;
11692
11693 if (l->lasttx != l->lasttx1)
11694 {
11695 voxinit_link(l,!l->lasttx);
11696 l->lasttx1 = l->lasttx;
11697 }
11698 myrx = l->lastrealrx;
11699 if ((l->phonemode) && (l->phonevox))
11700 {
11701 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11702 if (l->voxtotimer <= 0)
11703 {
11704 if (l->voxtostate)
11705 {
11706 l->voxtotimer = myrpt->p.voxtimeout_ms;
11707 l->voxtostate = 0;
11708 }
11709 else
11710 {
11711 l->voxtotimer = myrpt->p.voxrecover_ms;
11712 l->voxtostate = 1;
11713 }
11714 }
11715 if (!l->voxtostate)
11716 myrx = myrx || l->wasvox ;
11717 }
11718 l->lastrx = myrx;
11719 if (l->linklisttimer)
11720 {
11721 l->linklisttimer -= elap;
11722 if (l->linklisttimer < 0) l->linklisttimer = 0;
11723 }
11724 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11725 {
11726 struct ast_frame lf;
11727
11728 memset(&lf,0,sizeof(lf));
11729 lf.frametype = AST_FRAME_TEXT;
11730 lf.subclass.integer = 0;
11731 lf.offset = 0;
11732 lf.mallocd = 0;
11733 lf.samples = 0;
11734 l->linklisttimer = LINKLISTTIME;
11735 strcpy(lstr,"L ");
11736 __mklinklist(myrpt,l,lstr + 2);
11737 if (l->chan)
11738 {
11739 lf.datalen = strlen(lstr) + 1;
11740 lf.data.ptr = lstr;
11741 ast_write(l->chan,&lf);
11742 if (debug > 6) ast_log(LOG_NOTICE,
11743 "@@@@ node %s sent node string %s to node %s\n",
11744 myrpt->name,lstr,l->name);
11745 }
11746 }
11747 if (l->newkey)
11748 {
11749 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11750 {
11751 l->retxtimer = 0;
11752 if (l->chan && l->phonemode == 0)
11753 {
11754 if (l->lasttx)
11755 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11756 else
11757 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11758 }
11759 }
11760 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11761 {
11762 if (debug == 7) printf("@@@@ rx un-key\n");
11763 l->lastrealrx = 0;
11764 l->rerxtimer = 0;
11765 if (l->lastrx1)
11766 {
11767 if (myrpt->p.archivedir)
11768 {
11769 char str[100];
11770
11771 sprintf(str,"RXUNKEY(T),%s",l->name);
11772 donodelog(myrpt,str);
11773 }
11774 if(myrpt->p.duplex)
11775 rpt_telemetry(myrpt,LINKUNKEY,l);
11776 l->lastrx1 = 0;
11777 }
11778 }
11779 }
11780 if (l->disctime)
11781 {
11782 l->disctime -= elap;
11783 if (l->disctime <= 0)
11784 l->disctime = 0;
11785 }
11786
11787 if (l->retrytimer)
11788 {
11789 l->retrytimer -= elap;
11790 if (l->retrytimer < 0) l->retrytimer = 0;
11791 }
11792
11793
11794 l->connecttime += elap;
11795
11796
11797 if (l->elaptime < 0)
11798 {
11799 l = l->next;
11800 continue;
11801 }
11802 l->elaptime += elap;
11803
11804 if ((l->elaptime > MAXCONNECTTIME) &&
11805 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11806 {
11807 l->elaptime = 0;
11808 rpt_mutex_unlock(&myrpt->lock);
11809 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11810 rpt_mutex_lock(&myrpt->lock);
11811 break;
11812 }
11813 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11814 (l->retries++ < l->max_retries) && (l->hasconnected))
11815 {
11816 if (l->chan) ast_hangup(l->chan);
11817 l->chan = 0;
11818 rpt_mutex_unlock(&myrpt->lock);
11819 if ((l->name[0] != '0') && (!l->isremote))
11820 {
11821 if (attempt_reconnect(myrpt,l) == -1)
11822 {
11823 l->retrytimer = RETRY_TIMER_MS;
11824 }
11825 }
11826 else
11827 {
11828 l->retrytimer = l->max_retries + 1;
11829 }
11830
11831 rpt_mutex_lock(&myrpt->lock);
11832 break;
11833 }
11834 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11835 (l->retries >= l->max_retries))
11836 {
11837
11838 remque((struct qelem *) l);
11839 if (!strcmp(myrpt->cmdnode,l->name))
11840 myrpt->cmdnode[0] = 0;
11841 rpt_mutex_unlock(&myrpt->lock);
11842 if (l->name[0] != '0')
11843 {
11844 if (!l->hasconnected)
11845 rpt_telemetry(myrpt,CONNFAIL,l);
11846 else rpt_telemetry(myrpt,REMDISC,l);
11847 }
11848 if (myrpt->p.archivedir)
11849 {
11850 char str[100];
11851
11852 if (!l->hasconnected)
11853 sprintf(str,"LINKFAIL,%s",l->name);
11854 else
11855 sprintf(str,"LINKDISC,%s",l->name);
11856 donodelog(myrpt,str);
11857 }
11858
11859 ast_hangup(l->pchan);
11860 ast_free(l);
11861 rpt_mutex_lock(&myrpt->lock);
11862 break;
11863 }
11864 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11865 {
11866 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11867
11868 remque((struct qelem *) l);
11869 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11870 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11871 rpt_mutex_unlock(&myrpt->lock);
11872 if (l->name[0] != '0')
11873 {
11874 rpt_telemetry(myrpt,REMDISC,l);
11875 }
11876 if (myrpt->p.archivedir)
11877 {
11878 char str[100];
11879 sprintf(str,"LINKDISC,%s",l->name);
11880 donodelog(myrpt,str);
11881 }
11882
11883 ast_hangup(l->pchan);
11884 ast_free(l);
11885 rpt_mutex_lock(&myrpt->lock);
11886 break;
11887 }
11888 l = l->next;
11889 }
11890 if (myrpt->linkposttimer)
11891 {
11892 myrpt->linkposttimer -= elap;
11893 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11894 }
11895 if (myrpt->linkposttimer <= 0)
11896 {
11897 int nstr;
11898 char lst,*str;
11899 time_t now;
11900
11901 myrpt->linkposttimer = LINKPOSTTIME;
11902 nstr = 0;
11903 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11904 {
11905
11906 if (l->name[0] == '0') continue;
11907 nstr += strlen(l->name) + 1;
11908 }
11909 str = ast_malloc(nstr + 256);
11910 if (!str)
11911 {
11912 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11913 break;
11914 }
11915 nstr = 0;
11916 strcpy(str,"nodes=");
11917 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11918 {
11919
11920 if (l->name[0] == '0') continue;
11921 lst = 'T';
11922 if (!l->mode) lst = 'R';
11923 if (!l->thisconnected) lst = 'C';
11924 if (nstr) strcat(str,",");
11925 sprintf(str + strlen(str),"%c%s",lst,l->name);
11926 nstr = 1;
11927 }
11928 p = strstr(tdesc, "version");
11929 if(p){
11930 int vmajor,vminor;
11931 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11932 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11933 }
11934 time(&now);
11935 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11936 sprintf(str + strlen(str),
11937 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11938 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11939 myrpt->timeouts,myrpt->totalexecdcommands);
11940 rpt_mutex_unlock(&myrpt->lock);
11941 statpost(myrpt,str);
11942 rpt_mutex_lock(&myrpt->lock);
11943 ast_free(str);
11944 }
11945 if (myrpt->keyposttimer)
11946 {
11947 myrpt->keyposttimer -= elap;
11948 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11949 }
11950 if (myrpt->keyposttimer <= 0)
11951 {
11952 char str[100];
11953 int diff = 0;
11954 time_t now;
11955
11956 myrpt->keyposttimer = KEYPOSTTIME;
11957 time(&now);
11958 if (myrpt->lastkeyedtime)
11959 {
11960 diff = (int)(now - myrpt->lastkeyedtime);
11961 }
11962 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11963 rpt_mutex_unlock(&myrpt->lock);
11964 statpost(myrpt,str);
11965 rpt_mutex_lock(&myrpt->lock);
11966 }
11967 if(totx){
11968 myrpt->dailytxtime += elap;
11969 myrpt->totaltxtime += elap;
11970 }
11971 i = myrpt->tailtimer;
11972 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11973 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11974 if((i) && (myrpt->tailtimer == 0))
11975 myrpt->tailevent = 1;
11976 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11977 if (myrpt->totimer < 0) myrpt->totimer = 0;
11978 if (myrpt->idtimer) myrpt->idtimer -= elap;
11979 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11980 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11981 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11982 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11983 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11984 if (myrpt->exttx)
11985 {
11986 myrpt->parrottimer = myrpt->p.parrottime;
11987 }
11988 else
11989 {
11990 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11991 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11992 }
11993
11994 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11995 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11996
11997 if (myrpt->dtmf_local_timer)
11998 {
11999 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
12000 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
12001 }
12002 do_dtmf_local(myrpt,0);
12003
12004 if (myrpt->skedtimer <= 0){
12005 myrpt->skedtimer = 200;
12006 do_scheduler(myrpt);
12007 }
12008 else
12009 myrpt->skedtimer -=elap;
12010 if (!ms)
12011 {
12012 rpt_mutex_unlock(&myrpt->lock);
12013 continue;
12014 }
12015 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
12016 (myrpt->parrottimer <= 0))
12017 {
12018
12019 ci.confno = 0;
12020 ci.confmode = 0;
12021 ci.chan = 0;
12022
12023
12024 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
12025 {
12026 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
12027 break;
12028 }
12029 if (myrpt->parrotstream)
12030 ast_closestream(myrpt->parrotstream);
12031 myrpt->parrotstream = NULL;
12032 myrpt->parrotstate = 2;
12033 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
12034 }
12035 if (myrpt->cmdAction.state == CMD_STATE_READY)
12036 {
12037 int status;
12038 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12039
12040 rpt_mutex_unlock(&myrpt->lock);
12041
12042 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12043
12044 rpt_mutex_lock(&myrpt->lock);
12045 myrpt->cmdAction.state = CMD_STATE_IDLE;
12046 }
12047
12048 c = myrpt->macrobuf[0];
12049 time(&t);
12050 if (c && (!myrpt->macrotimer) &&
12051 starttime && (t > (starttime + START_DELAY)))
12052 {
12053 char cin = c & 0x7f;
12054 myrpt->macrotimer = MACROTIME;
12055 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12056 if ((cin == 'p') || (cin == 'P'))
12057 myrpt->macrotimer = MACROPTIME;
12058 rpt_mutex_unlock(&myrpt->lock);
12059 if (myrpt->p.archivedir)
12060 {
12061 char str[100];
12062
12063 sprintf(str,"DTMF(M),MAIN,%c",cin);
12064 donodelog(myrpt,str);
12065 }
12066 local_dtmf_helper(myrpt,c);
12067 } else rpt_mutex_unlock(&myrpt->lock);
12068 if (who == myrpt->rxchannel)
12069 {
12070 int ismuted;
12071
12072 f = ast_read(myrpt->rxchannel);
12073 if (!f)
12074 {
12075 if (debug) printf("@@@@ rpt:Hung Up\n");
12076 break;
12077 }
12078 if (f->frametype == AST_FRAME_VOICE)
12079 {
12080 #ifdef _MDC_DECODE_H_
12081 unsigned char ubuf[2560];
12082 short *sp;
12083 int n;
12084 #endif
12085
12086 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12087 memset(f->data.ptr,0,f->datalen);
12088 }
12089
12090 #ifdef _MDC_DECODE_H_
12091 sp = (short *) f->data;
12092
12093 for(n = 0; n < f->datalen / 2; n++)
12094 {
12095 ubuf[n] = (*sp++ >> 8) + 128;
12096 }
12097 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12098 if (n == 1)
12099 {
12100 unsigned char op,arg;
12101 unsigned short unitID;
12102
12103 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12104 if (debug > 2)
12105 {
12106 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12107 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12108 op & 255,arg & 255,unitID);
12109 }
12110 if ((op == 1) && (arg == 0))
12111 {
12112 myrpt->lastunit = unitID;
12113 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12114 mdc1200_send(myrpt,myrpt->lastunit);
12115 }
12116 }
12117 if ((debug > 2) && (i == 2))
12118 {
12119 unsigned char op,arg,ex1,ex2,ex3,ex4;
12120 unsigned short unitID;
12121
12122 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12123 &ex1,&ex2,&ex3,&ex4);
12124 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12125 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12126 op & 255,arg & 255,unitID);
12127 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12128 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12129 }
12130 #endif
12131 #ifdef __RPT_NOTCH
12132
12133 rpt_filter(myrpt,f->data,f->datalen / 2);
12134 #endif
12135 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12136 {
12137 ismuted = 0;
12138 }
12139 if (dtmfed) ismuted = 1;
12140 dtmfed = 0;
12141 if (ismuted)
12142 {
12143 memset(f->data.ptr,0,f->datalen);
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 }
12149 if (f) f2 = ast_frdup(f);
12150 else f2 = NULL;
12151 f1 = myrpt->lastf2;
12152 myrpt->lastf2 = myrpt->lastf1;
12153 myrpt->lastf1 = f2;
12154 if (ismuted)
12155 {
12156 if (myrpt->lastf1)
12157 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12158 if (myrpt->lastf2)
12159 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12160 }
12161 if (f1)
12162 {
12163 ast_write(myrpt->pchannel,f1);
12164 ast_frfree(f1);
12165 }
12166 }
12167 #ifndef OLD_ASTERISK
12168 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12169 {
12170 if (myrpt->lastf1)
12171 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12172 if (myrpt->lastf2)
12173 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12174 dtmfed = 1;
12175 }
12176 #endif
12177 else if (f->frametype == AST_FRAME_DTMF)
12178 {
12179 c = (char) f->subclass.integer;
12180 ast_frfree(f);
12181 if (myrpt->lastf1)
12182 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12183 if (myrpt->lastf2)
12184 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12185 dtmfed = 1;
12186 if (!myrpt->keyed) continue;
12187 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12188 if (c) local_dtmf_helper(myrpt,c);
12189 continue;
12190 }
12191 else if (f->frametype == AST_FRAME_CONTROL)
12192 {
12193 if (f->subclass.integer == AST_CONTROL_HANGUP)
12194 {
12195 if (debug) printf("@@@@ rpt:Hung Up\n");
12196 ast_frfree(f);
12197 break;
12198 }
12199
12200 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12201 {
12202 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12203 {
12204 if (debug == 7) printf("@@@@ rx key\n");
12205 myrpt->keyed = 1;
12206 time(&myrpt->lastkeyedtime);
12207 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12208 }
12209 if (myrpt->p.archivedir)
12210 {
12211 donodelog(myrpt,"RXKEY,MAIN");
12212 }
12213 if (f->datalen && f->data.ptr)
12214 {
12215 char busy = 0;
12216
12217 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12218
12219 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12220 {
12221 char value[16] = "";
12222 strcat(value,"*6");
12223 myrpt->macropatch=1;
12224 rpt_mutex_lock(&myrpt->lock);
12225 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12226 rpt_mutex_unlock(&myrpt->lock);
12227 busy=1;
12228 }
12229 if(!busy){
12230 myrpt->macrotimer = MACROTIME;
12231 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12232 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12233 }
12234 rpt_mutex_unlock(&myrpt->lock);
12235 }
12236 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12237 {
12238 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12239 if (value)
12240 {
12241 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12242 rpt_mutex_lock(&myrpt->lock);
12243 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12244 rpt_mutex_unlock(&myrpt->lock);
12245 busy=1;
12246 }
12247 if(!busy){
12248 myrpt->macrotimer = MACROTIME;
12249 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12250 }
12251 rpt_mutex_unlock(&myrpt->lock);
12252 }
12253 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12254 }
12255 } else myrpt->lasttone[0] = 0;
12256 }
12257
12258 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12259 {
12260 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12261 {
12262 if (debug == 7) printf("@@@@ rx un-key\n");
12263 if(myrpt->p.duplex && myrpt->keyed) {
12264 rpt_telemetry(myrpt,UNKEY,NULL);
12265 }
12266 }
12267 myrpt->keyed = 0;
12268 time(&myrpt->lastkeyedtime);
12269 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12270 if (myrpt->p.archivedir)
12271 {
12272 donodelog(myrpt,"RXUNKEY,MAIN");
12273 }
12274 }
12275 }
12276 ast_frfree(f);
12277 continue;
12278 }
12279 if (who == myrpt->pchannel)
12280 {
12281 f = ast_read(myrpt->pchannel);
12282 if (!f)
12283 {
12284 if (debug) printf("@@@@ rpt:Hung Up\n");
12285 break;
12286 }
12287 if (f->frametype == AST_FRAME_VOICE)
12288 {
12289 ast_write(myrpt->txpchannel,f);
12290 }
12291 if (f->frametype == AST_FRAME_CONTROL)
12292 {
12293 if (f->subclass.integer == AST_CONTROL_HANGUP)
12294 {
12295 if (debug) printf("@@@@ rpt:Hung Up\n");
12296 ast_frfree(f);
12297 break;
12298 }
12299 }
12300 ast_frfree(f);
12301 continue;
12302 }
12303 if (who == myrpt->txchannel)
12304 {
12305 f = ast_read(myrpt->txchannel);
12306 if (!f)
12307 {
12308 if (debug) printf("@@@@ rpt:Hung Up\n");
12309 break;
12310 }
12311 if (f->frametype == AST_FRAME_CONTROL)
12312 {
12313 if (f->subclass.integer == AST_CONTROL_HANGUP)
12314 {
12315 if (debug) printf("@@@@ rpt:Hung Up\n");
12316 ast_frfree(f);
12317 break;
12318 }
12319 }
12320 ast_frfree(f);
12321 continue;
12322 }
12323 if (who == myrpt->dahditxchannel)
12324 {
12325 f = ast_read(myrpt->dahditxchannel);
12326 if (!f)
12327 {
12328 if (debug) printf("@@@@ rpt:Hung Up\n");
12329 break;
12330 }
12331 if (f->frametype == AST_FRAME_VOICE)
12332 {
12333 struct ast_frame *vframe;
12334
12335 if (myrpt->p.duplex < 2)
12336 {
12337 if (myrpt->txrealkeyed)
12338 {
12339 if ((!myfirst) && myrpt->callmode)
12340 {
12341 x = 0;
12342 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12343 frame_list) x++;
12344 for(;x < myrpt->p.simplexpatchdelay; x++)
12345 {
12346 vframe = ast_frdup(f);
12347 memset(vframe->data.ptr,0,vframe->datalen);
12348 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12349 }
12350 myfirst = 1;
12351 }
12352 vframe = ast_frdup(f);
12353 AST_LIST_INSERT_TAIL(&myrpt->txq,
12354 vframe,frame_list);
12355 } else myfirst = 0;
12356 x = 0;
12357 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12358 frame_list) x++;
12359 if (!x)
12360 {
12361 memset(f->data.ptr,0,f->datalen);
12362 }
12363 else
12364 {
12365 ast_frfree(f);
12366 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12367 frame_list);
12368 }
12369 }
12370 else
12371 {
12372 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12373 frame_list))) ast_frfree(vframe);
12374 }
12375 ast_write(myrpt->txchannel,f);
12376 }
12377 if (f->frametype == AST_FRAME_CONTROL)
12378 {
12379 if (f->subclass.integer == AST_CONTROL_HANGUP)
12380 {
12381 if (debug) printf("@@@@ rpt:Hung Up\n");
12382 ast_frfree(f);
12383 break;
12384 }
12385 }
12386 ast_frfree(f);
12387 continue;
12388 }
12389 toexit = 0;
12390 rpt_mutex_lock(&myrpt->lock);
12391 l = myrpt->links.next;
12392 while(l != &myrpt->links)
12393 {
12394 int remnomute;
12395 struct timeval now;
12396
12397 if (l->disctime)
12398 {
12399 l = l->next;
12400 continue;
12401 }
12402
12403 remrx = 0;
12404
12405 m = myrpt->links.next;
12406 while(m != &myrpt->links)
12407 {
12408
12409 if ((m != l) && (m->lastrx)) remrx = 1;
12410 m = m->next;
12411 }
12412 rpt_mutex_unlock(&myrpt->lock);
12413 now = ast_tvnow();
12414 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12415 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12416 {
12417 l->lastlinktv = now;
12418 remnomute = myrpt->localtx &&
12419 (!(myrpt->cmdnode[0] ||
12420 (myrpt->dtmfidx > -1)));
12421 totx = (((l->isremote) ? (remnomute) :
12422 myrpt->exttx) || remrx) && l->mode;
12423 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12424 {
12425 if (totx)
12426 {
12427 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12428 }
12429 else
12430 {
12431 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12432 }
12433 if (myrpt->p.archivedir)
12434 {
12435 char str[100];
12436
12437 if (totx)
12438 sprintf(str,"TXKEY,%s",l->name);
12439 else
12440 sprintf(str,"TXUNKEY,%s",l->name);
12441 donodelog(myrpt,str);
12442 }
12443 }
12444 l->lasttx = totx;
12445 }
12446 rpt_mutex_lock(&myrpt->lock);
12447 if (who == l->chan)
12448 {
12449 rpt_mutex_unlock(&myrpt->lock);
12450 f = ast_read(l->chan);
12451 if (!f)
12452 {
12453 rpt_mutex_lock(&myrpt->lock);
12454 __kickshort(myrpt);
12455 rpt_mutex_unlock(&myrpt->lock);
12456 if ((!l->disced) && (!l->outbound))
12457 {
12458 if ((l->name[0] == '0') || l->isremote)
12459 l->disctime = 1;
12460 else
12461 l->disctime = DISC_TIME;
12462 rpt_mutex_lock(&myrpt->lock);
12463 ast_hangup(l->chan);
12464 l->chan = 0;
12465 break;
12466 }
12467
12468 if (l->retrytimer)
12469 {
12470 ast_hangup(l->chan);
12471 l->chan = 0;
12472 rpt_mutex_lock(&myrpt->lock);
12473 break;
12474 }
12475 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12476 {
12477 rpt_mutex_lock(&myrpt->lock);
12478 if (l->chan) ast_hangup(l->chan);
12479 l->chan = 0;
12480 l->hasconnected = 1;
12481 l->retrytimer = RETRY_TIMER_MS;
12482 l->elaptime = 0;
12483 l->connecttime = 0;
12484 l->thisconnected = 0;
12485 break;
12486 }
12487 rpt_mutex_lock(&myrpt->lock);
12488
12489 remque((struct qelem *) l);
12490 if (!strcmp(myrpt->cmdnode,l->name))
12491 myrpt->cmdnode[0] = 0;
12492 __kickshort(myrpt);
12493 rpt_mutex_unlock(&myrpt->lock);
12494 if (!l->hasconnected)
12495 rpt_telemetry(myrpt,CONNFAIL,l);
12496 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12497 if (myrpt->p.archivedir)
12498 {
12499 char str[100];
12500
12501 if (!l->hasconnected)
12502 sprintf(str,"LINKFAIL,%s",l->name);
12503 else
12504 sprintf(str,"LINKDISC,%s",l->name);
12505 donodelog(myrpt,str);
12506 }
12507 if (l->lastf1) ast_frfree(l->lastf1);
12508 l->lastf1 = NULL;
12509 if (l->lastf2) ast_frfree(l->lastf2);
12510 l->lastf2 = NULL;
12511
12512 ast_hangup(l->chan);
12513 ast_hangup(l->pchan);
12514 ast_free(l);
12515 rpt_mutex_lock(&myrpt->lock);
12516 break;
12517 }
12518 if (f->frametype == AST_FRAME_VOICE)
12519 {
12520 int ismuted,n1;
12521
12522 if ((l->phonemode) && (l->phonevox))
12523 {
12524 n1 = dovox(&l->vox,
12525 f->data.ptr,f->datalen / 2);
12526 if (n1 != l->wasvox)
12527 {
12528 ast_debug(1,"Link Node %s, vox %d\n",l->name,n1);
12529 l->wasvox = n1;
12530 l->voxtostate = 0;
12531 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12532 else l->voxtotimer = 0;
12533 }
12534 if (l->lastrealrx || n1)
12535 {
12536 if (!myfirst)
12537 {
12538 x = 0;
12539 AST_LIST_TRAVERSE(&l->rxq, f1,
12540 frame_list) x++;
12541 for(;x < myrpt->p.simplexphonedelay; x++)
12542 {
12543 f1 = ast_frdup(f);
12544 memset(f1->data.ptr,0,f1->datalen);
12545 AST_LIST_INSERT_TAIL(&l->rxq,
12546 f1,frame_list);
12547 }
12548 myfirst = 1;
12549 }
12550 f1 = ast_frdup(f);
12551 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12552 } else myfirst = 0;
12553 x = 0;
12554 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12555 if (!x)
12556 {
12557 memset(f->data.ptr,0,f->datalen);
12558 }
12559 else
12560 {
12561 ast_frfree(f);
12562 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12563 }
12564 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12565 {
12566 ismuted = 0;
12567 }
12568
12569 ismuted |= (!l->lastrx);
12570 if (l->dtmfed && l->phonemode) ismuted = 1;
12571 l->dtmfed = 0;
12572 if (ismuted)
12573 {
12574 memset(f->data.ptr,0,f->datalen);
12575 if (l->lastf1)
12576 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12577 if (l->lastf2)
12578 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12579 }
12580 if (f) f2 = ast_frdup(f);
12581 else f2 = NULL;
12582 f1 = l->lastf2;
12583 l->lastf2 = l->lastf1;
12584 l->lastf1 = f2;
12585 if (ismuted)
12586 {
12587 if (l->lastf1)
12588 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12589 if (l->lastf2)
12590 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12591 }
12592 if (f1)
12593 {
12594 ast_write(l->pchan,f1);
12595 ast_frfree(f1);
12596 }
12597 }
12598 else
12599 {
12600 if (!l->lastrx)
12601 memset(f->data.ptr,0,f->datalen);
12602 ast_write(l->pchan,f);
12603 }
12604 }
12605 #ifndef OLD_ASTERISK
12606 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12607 {
12608 if (l->lastf1)
12609 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12610 if (l->lastf2)
12611 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12612 l->dtmfed = 1;
12613 }
12614 #endif
12615 if (f->frametype == AST_FRAME_TEXT)
12616 {
12617 handle_link_data(myrpt,l,f->data.ptr);
12618 }
12619 if (f->frametype == AST_FRAME_DTMF)
12620 {
12621 if (l->lastf1)
12622 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12623 if (l->lastf2)
12624 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12625 l->dtmfed = 1;
12626 handle_link_phone_dtmf(myrpt,l,f->subclass.integer);
12627 }
12628 if (f->frametype == AST_FRAME_CONTROL)
12629 {
12630 if (f->subclass.integer == AST_CONTROL_ANSWER)
12631 {
12632 char lconnected = l->connected;
12633
12634 __kickshort(myrpt);
12635 l->connected = 1;
12636 l->hasconnected = 1;
12637 l->thisconnected = 1;
12638 l->elaptime = -1;
12639 if (!l->phonemode) send_newkey(l->chan);
12640 if (!l->isremote) l->retries = 0;
12641 if (!lconnected)
12642 {
12643 rpt_telemetry(myrpt,CONNECTED,l);
12644 if (myrpt->p.archivedir)
12645 {
12646 char str[100];
12647
12648 if (l->mode)
12649 sprintf(str,"LINKTRX,%s",l->name);
12650 else
12651 sprintf(str,"LINKMONITOR,%s",l->name);
12652 donodelog(myrpt,str);
12653 }
12654 }
12655 else
12656 l->reconnects++;
12657 }
12658
12659 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12660 {
12661 if (debug == 7 ) printf("@@@@ rx key\n");
12662 l->lastrealrx = 1;
12663 l->rerxtimer = 0;
12664 if (!l->lastrx1)
12665 {
12666 if (myrpt->p.archivedir)
12667 {
12668 char str[100];
12669
12670 sprintf(str,"RXKEY,%s",l->name);
12671 donodelog(myrpt,str);
12672 }
12673 l->lastrx1 = 1;
12674 }
12675 }
12676
12677 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12678 {
12679 if (debug == 7) printf("@@@@ rx un-key\n");
12680 l->lastrealrx = 0;
12681 l->rerxtimer = 0;
12682 if (l->lastrx1)
12683 {
12684 if (myrpt->p.archivedir)
12685 {
12686 char str[100];
12687
12688 sprintf(str,"RXUNKEY,%s",l->name);
12689 donodelog(myrpt,str);
12690 }
12691 l->lastrx1 = 0;
12692 if(myrpt->p.duplex)
12693 rpt_telemetry(myrpt,LINKUNKEY,l);
12694 }
12695 }
12696 if (f->subclass.integer == AST_CONTROL_HANGUP)
12697 {
12698 ast_frfree(f);
12699 rpt_mutex_lock(&myrpt->lock);
12700 __kickshort(myrpt);
12701 rpt_mutex_unlock(&myrpt->lock);
12702 if ((!l->outbound) && (!l->disced))
12703 {
12704 if ((l->name[0] == '0') || l->isremote)
12705 l->disctime = 1;
12706 else
12707 l->disctime = DISC_TIME;
12708 rpt_mutex_lock(&myrpt->lock);
12709 ast_hangup(l->chan);
12710 l->chan = 0;
12711 break;
12712 }
12713 if (l->retrytimer)
12714 {
12715 if (l->chan) ast_hangup(l->chan);
12716 l->chan = 0;
12717 rpt_mutex_lock(&myrpt->lock);
12718 break;
12719 }
12720 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12721 {
12722 rpt_mutex_lock(&myrpt->lock);
12723 if (l->chan) ast_hangup(l->chan);
12724 l->chan = 0;
12725 l->hasconnected = 1;
12726 l->elaptime = 0;
12727 l->retrytimer = RETRY_TIMER_MS;
12728 l->connecttime = 0;
12729 l->thisconnected = 0;
12730 break;
12731 }
12732 rpt_mutex_lock(&myrpt->lock);
12733
12734 remque((struct qelem *) l);
12735 if (!strcmp(myrpt->cmdnode,l->name))
12736 myrpt->cmdnode[0] = 0;
12737 __kickshort(myrpt);
12738 rpt_mutex_unlock(&myrpt->lock);
12739 if (!l->hasconnected)
12740 rpt_telemetry(myrpt,CONNFAIL,l);
12741 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12742 if (myrpt->p.archivedir)
12743 {
12744 char str[100];
12745
12746 if (!l->hasconnected)
12747 sprintf(str,"LINKFAIL,%s",l->name);
12748 else
12749 sprintf(str,"LINKDISC,%s",l->name);
12750 donodelog(myrpt,str);
12751 }
12752 if (l->lastf1) ast_frfree(l->lastf1);
12753 l->lastf1 = NULL;
12754 if (l->lastf2) ast_frfree(l->lastf2);
12755 l->lastf2 = NULL;
12756
12757 ast_hangup(l->chan);
12758 ast_hangup(l->pchan);
12759 ast_free(l);
12760 rpt_mutex_lock(&myrpt->lock);
12761 break;
12762 }
12763 }
12764 ast_frfree(f);
12765 rpt_mutex_lock(&myrpt->lock);
12766 break;
12767 }
12768 if (who == l->pchan)
12769 {
12770 rpt_mutex_unlock(&myrpt->lock);
12771 f = ast_read(l->pchan);
12772 if (!f)
12773 {
12774 if (debug) printf("@@@@ rpt:Hung Up\n");
12775 toexit = 1;
12776 rpt_mutex_lock(&myrpt->lock);
12777 break;
12778 }
12779 if (f->frametype == AST_FRAME_VOICE)
12780 {
12781 if (l->chan) ast_write(l->chan,f);
12782 }
12783 if (f->frametype == AST_FRAME_CONTROL)
12784 {
12785 if (f->subclass.integer == AST_CONTROL_HANGUP)
12786 {
12787 if (debug) printf("@@@@ rpt:Hung Up\n");
12788 ast_frfree(f);
12789 toexit = 1;
12790 rpt_mutex_lock(&myrpt->lock);
12791 break;
12792 }
12793 }
12794 ast_frfree(f);
12795 rpt_mutex_lock(&myrpt->lock);
12796 break;
12797 }
12798 l = l->next;
12799 }
12800 rpt_mutex_unlock(&myrpt->lock);
12801 if (toexit) break;
12802 if (who == myrpt->monchannel)
12803 {
12804 f = ast_read(myrpt->monchannel);
12805 if (!f)
12806 {
12807 if (debug) printf("@@@@ rpt:Hung Up\n");
12808 break;
12809 }
12810 if (f->frametype == AST_FRAME_VOICE)
12811 {
12812 if (myrpt->monstream)
12813 ast_writestream(myrpt->monstream,f);
12814 }
12815 if (f->frametype == AST_FRAME_CONTROL)
12816 {
12817 if (f->subclass.integer == AST_CONTROL_HANGUP)
12818 {
12819 if (debug) printf("@@@@ rpt:Hung Up\n");
12820 ast_frfree(f);
12821 break;
12822 }
12823 }
12824 ast_frfree(f);
12825 continue;
12826 }
12827 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12828 {
12829 f = ast_read(myrpt->parrotchannel);
12830 if (!f)
12831 {
12832 if (debug) printf("@@@@ rpt:Hung Up\n");
12833 break;
12834 }
12835 if (!myrpt->p.parrotmode)
12836 {
12837 char myfname[300];
12838
12839 if (myrpt->parrotstream)
12840 {
12841 ast_closestream(myrpt->parrotstream);
12842 myrpt->parrotstream = 0;
12843 }
12844 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12845 strcat(myfname,".wav");
12846 unlink(myfname);
12847 } else if (f->frametype == AST_FRAME_VOICE)
12848 {
12849 if (myrpt->parrotstream)
12850 ast_writestream(myrpt->parrotstream,f);
12851 }
12852 if (f->frametype == AST_FRAME_CONTROL)
12853 {
12854 if (f->subclass.integer == AST_CONTROL_HANGUP)
12855 {
12856 if (debug) printf("@@@@ rpt:Hung Up\n");
12857 ast_frfree(f);
12858 break;
12859 }
12860 }
12861 ast_frfree(f);
12862 continue;
12863 }
12864 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12865 {
12866 f = ast_read(myrpt->voxchannel);
12867 if (!f)
12868 {
12869 if (debug) printf("@@@@ rpt:Hung Up\n");
12870 break;
12871 }
12872 if (f->frametype == AST_FRAME_VOICE)
12873 {
12874 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12875 if (n != myrpt->wasvox)
12876 {
12877 ast_debug(1,"Node %s, vox %d\n",myrpt->name,n);
12878 myrpt->wasvox = n;
12879 myrpt->voxtostate = 0;
12880 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12881 else myrpt->voxtotimer = 0;
12882 }
12883 }
12884 if (f->frametype == AST_FRAME_CONTROL)
12885 {
12886 if (f->subclass.integer == AST_CONTROL_HANGUP)
12887 {
12888 if (debug) printf("@@@@ rpt:Hung Up\n");
12889 ast_frfree(f);
12890 break;
12891 }
12892 }
12893 ast_frfree(f);
12894 continue;
12895 }
12896 if (who == myrpt->txpchannel)
12897 {
12898 f = ast_read(myrpt->txpchannel);
12899 if (!f)
12900 {
12901 if (debug) printf("@@@@ rpt:Hung Up\n");
12902 break;
12903 }
12904 if (f->frametype == AST_FRAME_CONTROL)
12905 {
12906 if (f->subclass.integer == AST_CONTROL_HANGUP)
12907 {
12908 if (debug) printf("@@@@ rpt:Hung Up\n");
12909 ast_frfree(f);
12910 break;
12911 }
12912 }
12913 ast_frfree(f);
12914 continue;
12915 }
12916 }
12917 usleep(100000);
12918 ast_hangup(myrpt->pchannel);
12919 ast_hangup(myrpt->monchannel);
12920 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12921 myrpt->parrotstate = 0;
12922 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12923 ast_hangup(myrpt->txpchannel);
12924 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12925 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12926 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12927 myrpt->lastf1 = NULL;
12928 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12929 myrpt->lastf2 = NULL;
12930 ast_hangup(myrpt->rxchannel);
12931 rpt_mutex_lock(&myrpt->lock);
12932 l = myrpt->links.next;
12933 while(l != &myrpt->links)
12934 {
12935 struct rpt_link *ll = l;
12936
12937 remque((struct qelem *) l);
12938
12939 if (l->chan) ast_hangup(l->chan);
12940 ast_hangup(l->pchan);
12941 l = l->next;
12942 ast_free(ll);
12943 }
12944 if (myrpt->xlink == 1) myrpt->xlink = 2;
12945 rpt_mutex_unlock(&myrpt->lock);
12946 if (debug) printf("@@@@ rpt:Hung up channel\n");
12947 myrpt->rpt_thread = AST_PTHREADT_STOP;
12948 pthread_exit(NULL);
12949 return NULL;
12950 }
12951
12952
12953 static void *rpt_master(void *ignore)
12954 {
12955 int i,n;
12956 pthread_attr_t attr;
12957 struct ast_config *cfg;
12958 char *this,*val;
12959
12960
12961 nodelog.next = nodelog.prev = &nodelog;
12962
12963 this = NULL;
12964 n = 0;
12965 #ifndef OLD_ASTERISK
12966
12967 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12968 usleep(250000);
12969 #endif
12970 #ifdef NEW_ASTERISK
12971 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12972 #else
12973 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12974 #endif
12975 cfg = rpt_vars[n].cfg;
12976 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12977 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12978 pthread_exit(NULL);
12979 }
12980 while((this = ast_category_browse(cfg,this)) != NULL)
12981 {
12982 for(i = 0 ; i < strlen(this) ; i++){
12983 if((this[i] < '0') || (this[i] > '9'))
12984 break;
12985 }
12986 if(i != strlen(this)) continue;
12987 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12988 rpt_vars[n].name = ast_strdup(this);
12989 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12990 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12991 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12992 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12993 rpt_vars[n].remote = 0;
12994 rpt_vars[n].remoterig = "";
12995 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12996 if (val)
12997 {
12998 rpt_vars[n].remoterig = ast_strdup(val);
12999 rpt_vars[n].remote = 1;
13000 }
13001 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
13002 if (val) rpt_vars[n].remoterig = ast_strdup(val);
13003 ast_mutex_init(&rpt_vars[n].lock);
13004 ast_mutex_init(&rpt_vars[n].remlock);
13005 ast_mutex_init(&rpt_vars[n].statpost_lock);
13006 rpt_vars[n].tele.next = &rpt_vars[n].tele;
13007 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
13008 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
13009 rpt_vars[n].tailmessagen = 0;
13010 #ifdef _MDC_DECODE_H_
13011 rpt_vars[n].mdc = mdc_decoder_new(8000);
13012 #endif
13013 n++;
13014 }
13015 nrpts = n;
13016 ast_config_destroy(cfg);
13017
13018
13019 for(i = 0; i < n; i++)
13020 {
13021 load_rpt_vars(i,1);
13022
13023
13024 if (rpt_vars[i].remote)
13025 {
13026 if(retreive_memory(&rpt_vars[i],"init")){
13027 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13028 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13029 else
13030 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13031 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13032
13033 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13034 rpt_vars[i].remmode = REM_MODE_FM;
13035 rpt_vars[i].offset = REM_SIMPLEX;
13036 rpt_vars[i].powerlevel = REM_LOWPWR;
13037 }
13038 continue;
13039 }
13040 else
13041 {
13042 rpt_vars[i].p.memory = rpt_vars[i].name;
13043 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13044 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13045 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13046 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13047 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13048 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13049
13050 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13051 rpt_vars[i].remmode = REM_MODE_FM;
13052 rpt_vars[i].offset = REM_SIMPLEX;
13053 rpt_vars[i].powerlevel = REM_LOWPWR;
13054 }
13055 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13056 }
13057 if (!rpt_vars[i].p.ident)
13058 {
13059 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13060 ast_config_destroy(cfg);
13061 pthread_exit(NULL);
13062 }
13063 pthread_attr_init(&attr);
13064 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13065 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13066 }
13067 usleep(500000);
13068 time(&starttime);
13069 for(;;)
13070 {
13071
13072 for(i = 0; i < n; i++)
13073 {
13074 int rv;
13075 if (rpt_vars[i].remote) continue;
13076 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13077 rv = -1;
13078 else
13079 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13080 if (rv)
13081 {
13082 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13083 {
13084 if(rpt_vars[i].threadrestarts >= 5)
13085 {
13086 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13087 exit(1);
13088 }
13089 else
13090 {
13091 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13092 rpt_vars[i].threadrestarts++;
13093 }
13094 }
13095 else
13096 rpt_vars[i].threadrestarts = 0;
13097
13098 rpt_vars[i].lastthreadrestarttime = time(NULL);
13099 pthread_attr_init(&attr);
13100 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13101 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13102
13103 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13104 }
13105
13106 }
13107 for(;;)
13108 {
13109 struct nodelog *nodep;
13110 char *space,datestr[100],fname[300];
13111 int fd;
13112
13113 ast_mutex_lock(&nodeloglock);
13114 nodep = nodelog.next;
13115 if(nodep == &nodelog)
13116 {
13117 ast_mutex_unlock(&nodeloglock);
13118 break;
13119 }
13120 remque((struct qelem *)nodep);
13121 ast_mutex_unlock(&nodeloglock);
13122 space = strchr(nodep->str,' ');
13123 if (!space)
13124 {
13125 ast_free(nodep);
13126 continue;
13127 }
13128 *space = 0;
13129 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13130 localtime(&nodep->timestamp));
13131 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13132 nodep->str,datestr);
13133 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13134 if (fd == -1)
13135 {
13136 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13137 ast_free(nodep);
13138 continue;
13139 }
13140 if (write(fd,space + 1,strlen(space + 1)) !=
13141 strlen(space + 1))
13142 {
13143 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13144 ast_free(nodep);
13145 continue;
13146 }
13147 close(fd);
13148 ast_free(nodep);
13149 }
13150 sleep(2);
13151 }
13152 ast_config_destroy(cfg);
13153 pthread_exit(NULL);
13154 }
13155
13156 static int rpt_exec(struct ast_channel *chan, const char *data)
13157 {
13158 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13159 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13160 int ismuted,dtmfed,phone_vox = 0;
13161 #ifdef OLD_ASTERISK
13162 struct localuser *u;
13163 #endif
13164 char tmp[256], keyed = 0,keyed1 = 0;
13165 char *options,*stringp,*tele,c,*altp,*memp;
13166 char sx[320],*sy;
13167 struct rpt *myrpt;
13168 struct ast_frame *f,*f1,*f2;
13169 struct ast_channel *who;
13170 struct ast_channel *cs[20];
13171 struct rpt_link *l;
13172 struct dahdi_confinfo ci;
13173 struct dahdi_params par;
13174 int ms,elap,nullfd;
13175 time_t t,last_timeout_warning;
13176 struct dahdi_radio_param z;
13177 struct rpt_tele *telem;
13178 int numlinks;
13179 struct ast_format_cap *cap = NULL;
13180
13181 nullfd = open("/dev/null",O_RDWR);
13182 if (ast_strlen_zero(data)) {
13183 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13184 return -1;
13185 }
13186
13187 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13188 time(&t);
13189
13190 if (t < starttime) t = starttime + START_DELAY;
13191 if ((!starttime) || (t < (starttime + START_DELAY)))
13192 {
13193 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13194 ast_safe_sleep(chan,3000);
13195 return -1;
13196 }
13197
13198 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13199
13200 altp=strstr(tmp, "|*");
13201 if(altp){
13202 altp[0]=0;
13203 altp++;
13204 }
13205
13206 memp=strstr(tmp, "|M");
13207 if(memp){
13208 memp[0]=0;
13209 memp+=2;
13210 }
13211
13212 stringp=tmp;
13213 strsep(&stringp, "|");
13214 options = stringp;
13215
13216 ast_log(LOG_NOTICE,"options=%s \n",options);
13217 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13218 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13219
13220 myrpt = NULL;
13221
13222 for(i = 0; i < nrpts; i++)
13223 {
13224
13225 if (!strcmp(tmp,rpt_vars[i].name))
13226 {
13227 myrpt = &rpt_vars[i];
13228 break;
13229 }
13230 }
13231
13232 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13233
13234 if (myrpt == NULL)
13235 {
13236 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13237 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13238 return (priority_jump(NULL,chan));
13239 }
13240
13241 numlinks=linkcount(myrpt);
13242
13243 if(options && *options == 'q')
13244 {
13245 char buf2[128];
13246
13247 if(myrpt->keyed)
13248 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13249 else
13250 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13251
13252 if(myrpt->txkeyed)
13253 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13254 else
13255 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13256
13257 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13258 pbx_builtin_setvar(chan, buf2);
13259 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13260 pbx_builtin_setvar(chan, buf2);
13261 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13262 pbx_builtin_setvar(chan, buf2);
13263 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13264 pbx_builtin_setvar(chan, buf2);
13265 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13266 pbx_builtin_setvar(chan, buf2);
13267 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13268 pbx_builtin_setvar(chan, buf2);
13269
13270
13271
13272
13273 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13274 pbx_builtin_setvar(chan, buf2);
13275 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13276 pbx_builtin_setvar(chan, buf2);
13277
13278 return priority_jump(myrpt,chan);
13279 }
13280
13281 if(options && *options == 'o')
13282 {
13283 return(channel_revert(myrpt));
13284 }
13285
13286 #if 0
13287 if((altp)&&(*options == 'Z'))
13288 {
13289 rpt_push_alt_macro(myrpt,altp);
13290 return 0;
13291 }
13292 #endif
13293
13294
13295
13296 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13297 {
13298 int val;
13299
13300 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13301
13302 myrpt->bargechan=0;
13303 if(options && strstr(options, "f")>0)
13304 {
13305 myrpt->bargechan=1;
13306 }
13307
13308 if(memp>0)
13309 {
13310 char radiochan;
13311 radiochan=strtod(data,NULL);
13312
13313
13314 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13315 {
13316 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13317 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13318 return (priority_jump(myrpt,chan));
13319 }
13320 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13321 {
13322 channel_steer(myrpt,memp);
13323 }
13324 }
13325 if(altp)rpt_push_alt_macro(myrpt,altp);
13326 phone_mode = 1;
13327 if (*options == 'D') phone_mode = 2;
13328 if (*options == 'S') phone_mode = 3;
13329 ast_set_callerid(chan,"0","app_rpt user","0");
13330 val = 1;
13331 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13332 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13333 }
13334 else
13335 {
13336 #ifdef ALLOW_LOCAL_CHANNELS
13337
13338 if ( (strncmp(ast_channel_name(chan),"IAX2",4)) && (strncmp(ast_channel_name(chan),"Local",5)) ) {
13339 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13340 return -1;
13341 }
13342 #else
13343 if (strncmp(ast_channel_name(chan),"IAX2",4))
13344 {
13345 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13346 return -1;
13347 }
13348 #endif
13349 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13350 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13351 return -1;
13352 }
13353 }
13354 if (options && (*options == 'R'))
13355 {
13356
13357 char *return_context;
13358 int length, m, lot, timeout = 0;
13359 char buffer[256],*template;
13360 char *working, *context, *exten, *priority;
13361 char *s,*orig_s;
13362
13363 rpt_mutex_lock(&myrpt->lock);
13364 m = myrpt->callmode;
13365 rpt_mutex_unlock(&myrpt->lock);
13366
13367 if ((!myrpt->p.nobusyout) && m)
13368 {
13369 if (chan->_state != AST_STATE_UP)
13370 {
13371 ast_indicate(chan,AST_CONTROL_BUSY);
13372 }
13373 while(ast_safe_sleep(chan,10000) != -1);
13374 return -1;
13375 }
13376
13377 if (chan->_state != AST_STATE_UP)
13378 {
13379 ast_answer(chan);
13380 if (!phone_mode) send_newkey(chan);
13381 }
13382
13383 length=strlen(options)+2;
13384 orig_s=ast_malloc(length);
13385 if(!orig_s) {
13386 ast_log(LOG_WARNING, "Out of memory\n");
13387 return -1;
13388 }
13389 s=orig_s;
13390 strncpy(s,options,length);
13391
13392 template=strsep(&s,"|");
13393 if(!template) {
13394 ast_log(LOG_WARNING, "An announce template must be defined\n");
13395 ast_free(orig_s);
13396 return -1;
13397 }
13398
13399 if(s) {
13400 timeout = atoi(strsep(&s, "|"));
13401 timeout *= 1000;
13402 }
13403
13404 return_context = s;
13405
13406 if(return_context != NULL) {
13407
13408
13409 working = return_context;
13410 context = strsep(&working, "|");
13411 exten = strsep(&working, "|");
13412 if(!exten) {
13413
13414 priority = context;
13415 exten = NULL;
13416 context = NULL;
13417 } else {
13418 priority = strsep(&working, "|");
13419 if(!priority) {
13420
13421 priority = exten;
13422 exten = context;
13423 context = NULL;
13424 }
13425 }
13426 if(atoi(priority) < 0) {
13427 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13428 ast_free(orig_s);
13429 return -1;
13430 }
13431
13432 chan->priority = atoi(priority);
13433 #ifdef OLD_ASTERISK
13434 if(exten && strcasecmp(exten, "BYEXTENSION"))
13435 #else
13436 if(exten)
13437 #endif
13438 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13439 if(context)
13440 strncpy(chan->context, context, sizeof(chan->context)-1);
13441 } else {
13442 chan->priority++;
13443 }
13444
13445 ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n",
13446 chan->context, chan->exten, chan->priority,
13447 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
13448 if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
13449 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
13450 ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
13451 }
13452
13453
13454
13455
13456 ast_masq_park_call(chan, NULL, timeout, &lot);
13457
13458 ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13459
13460 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13461
13462 rpt_telemetry(myrpt,REV_PATCH,buffer);
13463
13464 ast_free(orig_s);
13465
13466 return 0;
13467
13468 }
13469
13470 if (!options)
13471 {
13472 struct ast_hostent ahp;
13473 struct hostent *hp;
13474 struct in_addr ia;
13475 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13476
13477
13478 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13479 if (!b)
13480 {
13481 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13482 return -1;
13483 }
13484
13485 memset(hisip,0,sizeof(hisip));
13486 #ifdef ALLOW_LOCAL_CHANNELS
13487
13488 if (strncmp(ast_channel_name(chan),"Local",5)==0) {
13489 strcpy(hisip,"127.0.0.1");
13490 } else {
13491 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13492 }
13493 #else
13494 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13495 #endif
13496
13497 if (!hisip[0])
13498 {
13499 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13500 return -1;
13501 }
13502
13503 b1 = ast_strdupa(b);
13504 ast_shrink_phone_number(b1);
13505 if (!strcmp(myrpt->name,b1))
13506 {
13507 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13508 return -1;
13509 }
13510
13511 if (*b1 < '1')
13512 {
13513 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13514 return -1;
13515 }
13516
13517
13518
13519 val = node_lookup(myrpt,b1);
13520 if (!val)
13521 {
13522 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13523 return -1;
13524 }
13525 strncpy(tmp,val,sizeof(tmp) - 1);
13526 s = tmp;
13527 s1 = strsep(&s,",");
13528 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13529 {
13530 sy = strchr(s1,'/');
13531 *sy = 0;
13532 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13533 s1 = sx;
13534 }
13535 s2 = strsep(&s,",");
13536 if (!s2)
13537 {
13538 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13539 return -1;
13540 }
13541 if (strcmp(s2,"NONE")) {
13542 hp = ast_gethostbyname(s2, &ahp);
13543 if (!hp)
13544 {
13545 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13546 return -1;
13547 }
13548 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13549 #ifdef OLD_ASTERISK
13550 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13551 #else
13552 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13553 #endif
13554 s3 = strchr(hisip,':');
13555 if (s3) *s3 = 0;
13556 if (strcmp(hisip,nodeip))
13557 {
13558 s3 = strchr(s1,'@');
13559 if (s3) s1 = s3 + 1;
13560 s3 = strchr(s1,'/');
13561 if (s3) *s3 = 0;
13562 s3 = strchr(s1,':');
13563 if (s3) *s3 = 0;
13564 hp = ast_gethostbyname(s1, &ahp);
13565 if (!hp)
13566 {
13567 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13568 return -1;
13569 }
13570 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13571 #ifdef OLD_ASTERISK
13572 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13573 #else
13574 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13575 #endif
13576 if (strcmp(hisip,nodeip))
13577 {
13578 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13579 return -1;
13580 }
13581 }
13582 }
13583 }
13584
13585
13586 if (!myrpt->remote)
13587 {
13588 char *b,*b1;
13589 int reconnects = 0;
13590
13591 rpt_mutex_lock(&myrpt->lock);
13592 i = myrpt->xlink;
13593 rpt_mutex_unlock(&myrpt->lock);
13594 if (i)
13595 {
13596 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13597 return -1;
13598 }
13599
13600 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13601 if (!b)
13602 {
13603 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13604 return -1;
13605 }
13606
13607 b1 = ast_strdupa(b);
13608 ast_shrink_phone_number(b1);
13609 if (!strcmp(myrpt->name,b1))
13610 {
13611 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13612 return -1;
13613 }
13614 rpt_mutex_lock(&myrpt->lock);
13615 l = myrpt->links.next;
13616
13617 while(l != &myrpt->links)
13618 {
13619 if (l->name[0] == '0')
13620 {
13621 l = l->next;
13622 continue;
13623 }
13624
13625 if (!strcmp(l->name,b1)) break;
13626 l = l->next;
13627 }
13628
13629 if (l != &myrpt->links)
13630 {
13631 l->killme = 1;
13632 l->retries = l->max_retries + 1;
13633 l->disced = 2;
13634 reconnects = l->reconnects;
13635 reconnects++;
13636 rpt_mutex_unlock(&myrpt->lock);
13637 usleep(500000);
13638 } else
13639 rpt_mutex_unlock(&myrpt->lock);
13640
13641 l = ast_malloc(sizeof(struct rpt_link));
13642 if (!l)
13643 {
13644 ast_log(LOG_WARNING, "Unable to malloc\n");
13645 pthread_exit(NULL);
13646 }
13647
13648 memset((char *)l,0,sizeof(struct rpt_link));
13649 l->mode = 1;
13650 strncpy(l->name,b1,MAXNODESTR - 1);
13651 l->isremote = 0;
13652 l->chan = chan;
13653 l->connected = 1;
13654 l->thisconnected = 1;
13655 l->hasconnected = 1;
13656 l->reconnects = reconnects;
13657 l->phonemode = phone_mode;
13658 l->phonevox = phone_vox;
13659 l->lastf1 = NULL;
13660 l->lastf2 = NULL;
13661 l->dtmfed = 0;
13662 voxinit_link(l,1);
13663 ast_set_read_format_by_id(l->chan,AST_FORMAT_SLINEAR);
13664 ast_set_write_format_by_id(l->chan,AST_FORMAT_SLINEAR);
13665
13666 l->pchan = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
13667 cap = ast_format_cap_destroy(cap);
13668 if (!l->pchan)
13669 {
13670 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13671 pthread_exit(NULL);
13672 }
13673 ast_set_read_format_by_id(l->pchan,AST_FORMAT_SLINEAR);
13674 ast_set_write_format_by_id(l->pchan,AST_FORMAT_SLINEAR);
13675 #ifdef AST_CDR_FLAG_POST_DISABLED
13676 if (l->pchan->cdr)
13677 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13678 #endif
13679
13680 ci.chan = 0;
13681 ci.confno = myrpt->conf;
13682 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13683
13684 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13685 {
13686 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13687 pthread_exit(NULL);
13688 }
13689 rpt_mutex_lock(&myrpt->lock);
13690 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13691 l->max_retries = MAX_RETRIES;
13692
13693 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13694 __kickshort(myrpt);
13695 rpt_mutex_unlock(&myrpt->lock);
13696 if (chan->_state != AST_STATE_UP) {
13697 ast_answer(chan);
13698 if (!phone_mode) send_newkey(chan);
13699 }
13700 if (myrpt->p.archivedir)
13701 {
13702 char str[100];
13703
13704 if (l->phonemode)
13705 sprintf(str,"LINK(P),%s",l->name);
13706 else
13707 sprintf(str,"LINK,%s",l->name);
13708 donodelog(myrpt,str);
13709 }
13710 if (!phone_mode) send_newkey(chan);
13711 return 0;
13712 }
13713
13714 rpt_mutex_lock(&myrpt->lock);
13715
13716 if (myrpt->remoteon)
13717 {
13718 rpt_mutex_unlock(&myrpt->lock);
13719 usleep(500000);
13720 if (myrpt->remoteon)
13721 {
13722 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",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 rpt_mutex_lock(&myrpt->lock);
13730 }
13731 if (myrpt->p.rptnode)
13732 {
13733 char killedit = 0;
13734 time_t now;
13735
13736 time(&now);
13737 for(i = 0; i < nrpts; i++)
13738 {
13739 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13740 {
13741 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13742 rpt_vars[i].keyed ||
13743 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13744 rpt_vars[i].txkeyed ||
13745 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13746 {
13747 rpt_mutex_unlock(&myrpt->lock);
13748 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13749 #ifdef AST_CDR_FLAG_POST_DISABLED
13750 if (chan->cdr)
13751 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13752 #endif
13753 return -1;
13754 }
13755 while(rpt_vars[i].xlink != 3)
13756 {
13757 if (!killedit)
13758 {
13759 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13760 rpt_vars[i].xlink = 1;
13761 killedit = 1;
13762 }
13763 rpt_mutex_unlock(&myrpt->lock);
13764 if (ast_safe_sleep(chan,500) == -1)
13765 {
13766 #ifdef AST_CDR_FLAG_POST_DISABLED
13767 if (chan->cdr)
13768 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13769 #endif
13770 return -1;
13771 }
13772 rpt_mutex_lock(&myrpt->lock);
13773 }
13774 break;
13775 }
13776 }
13777 }
13778
13779 #ifdef HAVE_IOPERM
13780 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13781 (ioperm(myrpt->p.iobase,1,1) == -1))
13782 {
13783 rpt_mutex_unlock(&myrpt->lock);
13784 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13785 return -1;
13786 }
13787 #endif
13788 myrpt->remoteon = 1;
13789 #ifdef OLD_ASTERISK
13790 LOCAL_USER_ADD(u);
13791 #endif
13792 rpt_mutex_unlock(&myrpt->lock);
13793
13794 for(i = 0; i < nrpts; i++)
13795 {
13796 if (&rpt_vars[i] == myrpt)
13797 {
13798 load_rpt_vars(i,0);
13799 break;
13800 }
13801 }
13802 rpt_mutex_lock(&myrpt->lock);
13803 tele = strchr(myrpt->rxchanname,'/');
13804 if (!tele)
13805 {
13806 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13807 rpt_mutex_unlock(&myrpt->lock);
13808 pthread_exit(NULL);
13809 }
13810 *tele++ = 0;
13811 myrpt->rxchannel = ast_request(myrpt->rxchanname, get_slin_cap(cap), NULL, tele, NULL);
13812 cap = ast_format_cap_destroy(cap);
13813 myrpt->dahdirxchannel = NULL;
13814 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13815 myrpt->dahdirxchannel = myrpt->rxchannel;
13816 if (myrpt->rxchannel)
13817 {
13818 ast_set_read_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13819 ast_set_write_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13820 #ifdef AST_CDR_FLAG_POST_DISABLED
13821 if (myrpt->rxchannel->cdr)
13822 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13823 #endif
13824 #ifndef NEW_ASTERISK
13825 myrpt->rxchannel->whentohangup = 0;
13826 #endif
13827 myrpt->rxchannel->appl = "Apprpt";
13828 myrpt->rxchannel->data = "(Link Rx)";
13829 ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
13830 myrpt->rxchanname,tele,ast_channel_name(myrpt->rxchannel));
13831 rpt_mutex_unlock(&myrpt->lock);
13832 ast_call(myrpt->rxchannel,tele,999);
13833 rpt_mutex_lock(&myrpt->lock);
13834 }
13835 else
13836 {
13837 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13838 rpt_mutex_unlock(&myrpt->lock);
13839 pthread_exit(NULL);
13840 }
13841 *--tele = '/';
13842 myrpt->dahditxchannel = NULL;
13843 if (myrpt->txchanname)
13844 {
13845 tele = strchr(myrpt->txchanname,'/');
13846 if (!tele)
13847 {
13848 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13849 rpt_mutex_unlock(&myrpt->lock);
13850 ast_hangup(myrpt->rxchannel);
13851 pthread_exit(NULL);
13852 }
13853 *tele++ = 0;
13854 myrpt->txchannel = ast_request(myrpt->txchanname, get_slin_cap(cap), NULL, tele, NULL);
13855 cap = ast_format_cap_destroy(cap);
13856 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13857 myrpt->dahditxchannel = myrpt->txchannel;
13858 if (myrpt->txchannel)
13859 {
13860 ast_set_read_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR);
13861 ast_set_write_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR);
13862 #ifdef AST_CDR_FLAG_POST_DISABLED
13863 if (myrpt->txchannel->cdr)
13864 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13865 #endif
13866 #ifndef NEW_ASTERISK
13867 myrpt->txchannel->whentohangup = 0;
13868 #endif
13869 myrpt->txchannel->appl = "Apprpt";
13870 myrpt->txchannel->data = "(Link Tx)";
13871 ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
13872 myrpt->txchanname,tele,ast_channel_name(myrpt->txchannel));
13873 rpt_mutex_unlock(&myrpt->lock);
13874 ast_call(myrpt->txchannel,tele,999);
13875 rpt_mutex_lock(&myrpt->lock);
13876 }
13877 else
13878 {
13879 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13880 rpt_mutex_unlock(&myrpt->lock);
13881 ast_hangup(myrpt->rxchannel);
13882 pthread_exit(NULL);
13883 }
13884 *--tele = '/';
13885 }
13886 else
13887 {
13888 myrpt->txchannel = myrpt->rxchannel;
13889 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13890 myrpt->dahditxchannel = myrpt->rxchannel;
13891 }
13892
13893 myrpt->pchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL);
13894 cap = ast_format_cap_destroy(cap);
13895 if (!myrpt->pchannel)
13896 {
13897 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13898 rpt_mutex_unlock(&myrpt->lock);
13899 if (myrpt->txchannel != myrpt->rxchannel)
13900 ast_hangup(myrpt->txchannel);
13901 ast_hangup(myrpt->rxchannel);
13902 pthread_exit(NULL);
13903 }
13904 ast_set_read_format_by_id(myrpt->pchannel,AST_FORMAT_SLINEAR);
13905 ast_set_write_format_by_id(myrpt->pchannel,AST_FORMAT_SLINEAR);
13906 #ifdef AST_CDR_FLAG_POST_DISABLED
13907 if (myrpt->pchannel->cdr)
13908 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13909 #endif
13910 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13911 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13912
13913 ci.chan = 0;
13914 ci.confno = -1;
13915 ci.confmode = DAHDI_CONF_CONFANNMON ;
13916
13917 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13918 {
13919 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13920 rpt_mutex_unlock(&myrpt->lock);
13921 ast_hangup(myrpt->pchannel);
13922 if (myrpt->txchannel != myrpt->rxchannel)
13923 ast_hangup(myrpt->txchannel);
13924 ast_hangup(myrpt->rxchannel);
13925 pthread_exit(NULL);
13926 }
13927
13928 myrpt->conf = myrpt->txconf = ci.confno;
13929
13930 myrpt->iofd = -1;
13931 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13932 {
13933 rpt_mutex_unlock(&myrpt->lock);
13934 ast_hangup(myrpt->pchannel);
13935 if (myrpt->txchannel != myrpt->rxchannel)
13936 ast_hangup(myrpt->txchannel);
13937 ast_hangup(myrpt->rxchannel);
13938 pthread_exit(NULL);
13939 }
13940 iskenwood_pci4 = 0;
13941 memset(&z,0,sizeof(z));
13942 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13943 {
13944 z.radpar = DAHDI_RADPAR_REMMODE;
13945 z.data = DAHDI_RADPAR_REM_NONE;
13946 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13947
13948 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13949 {
13950 z.radpar = DAHDI_RADPAR_UIOMODE;
13951 z.data = 1;
13952 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13953 {
13954 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13955 return -1;
13956 }
13957 z.radpar = DAHDI_RADPAR_UIODATA;
13958 z.data = 3;
13959 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13960 {
13961 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13962 return -1;
13963 }
13964 i = DAHDI_OFFHOOK;
13965 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13966 {
13967 ast_log(LOG_ERROR,"Cannot set hook\n");
13968 return -1;
13969 }
13970 iskenwood_pci4 = 1;
13971 }
13972 }
13973 if (myrpt->txchannel == myrpt->dahditxchannel)
13974 {
13975 i = DAHDI_ONHOOK;
13976 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13977
13978 if ((myrpt->iofd < 1) && (!res) &&
13979 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13980 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13981 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13982 {
13983 z.radpar = DAHDI_RADPAR_UIOMODE;
13984 z.data = 1;
13985 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13986 {
13987 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13988 return -1;
13989 }
13990 z.radpar = DAHDI_RADPAR_UIODATA;
13991 z.data = 3;
13992 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13993 {
13994 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13995 return -1;
13996 }
13997 }
13998 }
13999 myrpt->remoterx = 0;
14000 myrpt->remotetx = 0;
14001 myrpt->retxtimer = 0;
14002 myrpt->rerxtimer = 0;
14003 myrpt->remoteon = 1;
14004 myrpt->dtmfidx = -1;
14005 myrpt->dtmfbuf[0] = 0;
14006 myrpt->dtmf_time_rem = 0;
14007 myrpt->hfscanmode = 0;
14008 myrpt->hfscanstatus = 0;
14009 if (myrpt->p.startupmacro)
14010 {
14011 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
14012 }
14013 time(&myrpt->start_time);
14014 myrpt->last_activity_time = myrpt->start_time;
14015 last_timeout_warning = 0;
14016 myrpt->reload = 0;
14017 myrpt->tele.next = &myrpt->tele;
14018 myrpt->tele.prev = &myrpt->tele;
14019 myrpt->newkey = 0;
14020 rpt_mutex_unlock(&myrpt->lock);
14021 ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
14022 ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
14023 rem_rx = 0;
14024 remkeyed = 0;
14025
14026 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
14027 {
14028 i = 128;
14029 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
14030 }
14031 if (chan->_state != AST_STATE_UP) {
14032 ast_answer(chan);
14033 if (!phone_mode) send_newkey(chan);
14034 }
14035
14036 if (myrpt->rxchannel == myrpt->dahdirxchannel)
14037 {
14038 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
14039 {
14040 if (par.rxisoffhook)
14041 {
14042 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14043 myrpt->remoterx = 1;
14044 remkeyed = 1;
14045 }
14046 }
14047 }
14048 if (myrpt->p.archivedir)
14049 {
14050 char mycmd[100],mydate[100],*b,*b1;
14051 time_t myt;
14052 long blocksleft;
14053
14054
14055 mkdir(myrpt->p.archivedir,0600);
14056 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14057 mkdir(mycmd,0600);
14058 time(&myt);
14059 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14060 localtime(&myt));
14061 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",ast_channel_name(chan),
14062 myrpt->p.archivedir,myrpt->name,mydate);
14063 if (myrpt->p.monminblocks)
14064 {
14065 blocksleft = diskavail(myrpt);
14066 if (myrpt->p.remotetimeout)
14067 {
14068 blocksleft -= (myrpt->p.remotetimeout *
14069 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14070 }
14071 if (blocksleft >= myrpt->p.monminblocks)
14072 ast_cli_command(nullfd,mycmd);
14073 } else ast_cli_command(nullfd,mycmd);
14074
14075 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14076 if (!b)
14077 {
14078 b1 = "0";
14079 } else {
14080 b1 = ast_strdupa(b);
14081 ast_shrink_phone_number(b1);
14082 }
14083 sprintf(mycmd,"CONNECT,%s",b1);
14084 donodelog(myrpt,mycmd);
14085 }
14086 myrpt->loginuser[0] = 0;
14087 myrpt->loginlevel[0] = 0;
14088 myrpt->authtelltimer = 0;
14089 myrpt->authtimer = 0;
14090 authtold = 0;
14091 authreq = 0;
14092 if (myrpt->p.authlevel > 1) authreq = 1;
14093 setrem(myrpt);
14094 n = 0;
14095 dtmfed = 0;
14096 cs[n++] = chan;
14097 cs[n++] = myrpt->rxchannel;
14098 cs[n++] = myrpt->pchannel;
14099 if (myrpt->rxchannel != myrpt->txchannel)
14100 cs[n++] = myrpt->txchannel;
14101 if (!phone_mode) send_newkey(chan);
14102
14103 for(;;)
14104 {
14105 if (ast_check_hangup(chan)) break;
14106 if (ast_check_hangup(myrpt->rxchannel)) break;
14107 notremming = 0;
14108 setting = 0;
14109 reming = 0;
14110 telem = myrpt->tele.next;
14111 while(telem != &myrpt->tele)
14112 {
14113 if (telem->mode == SETREMOTE) setting = 1;
14114 if ((telem->mode == SETREMOTE) ||
14115 (telem->mode == SCAN) ||
14116 (telem->mode == TUNE)) reming = 1;
14117 else notremming = 1;
14118 telem = telem->next;
14119 }
14120 if (myrpt->reload)
14121 {
14122 myrpt->reload = 0;
14123
14124 for(i = 0; i < nrpts; i++)
14125 {
14126 if (&rpt_vars[i] == myrpt)
14127 {
14128 load_rpt_vars(i,0);
14129 break;
14130 }
14131 }
14132 }
14133 time(&t);
14134 if (myrpt->p.remotetimeout)
14135 {
14136 time_t r;
14137
14138 r = (t - myrpt->start_time);
14139 if (r >= myrpt->p.remotetimeout)
14140 {
14141 saynode(myrpt,chan,myrpt->name);
14142 sayfile(chan,"rpt/timeout");
14143 ast_safe_sleep(chan,1000);
14144 break;
14145 }
14146 if ((myrpt->p.remotetimeoutwarning) &&
14147 (r >= (myrpt->p.remotetimeout -
14148 myrpt->p.remotetimeoutwarning)) &&
14149 (r <= (myrpt->p.remotetimeout -
14150 myrpt->p.remotetimeoutwarningfreq)))
14151 {
14152 if (myrpt->p.remotetimeoutwarningfreq)
14153 {
14154 if ((t - last_timeout_warning) >=
14155 myrpt->p.remotetimeoutwarningfreq)
14156 {
14157 time(&last_timeout_warning);
14158 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14159 }
14160 }
14161 else
14162 {
14163 if (!last_timeout_warning)
14164 {
14165 time(&last_timeout_warning);
14166 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14167 }
14168 }
14169 }
14170 }
14171 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14172 {
14173 time_t r;
14174
14175 r = (t - myrpt->last_activity_time);
14176 if (r >= myrpt->p.remoteinacttimeout)
14177 {
14178 saynode(myrpt,chan,myrpt->name);
14179 ast_safe_sleep(chan,1000);
14180 break;
14181 }
14182 if ((myrpt->p.remotetimeoutwarning) &&
14183 (r >= (myrpt->p.remoteinacttimeout -
14184 myrpt->p.remotetimeoutwarning)) &&
14185 (r <= (myrpt->p.remoteinacttimeout -
14186 myrpt->p.remotetimeoutwarningfreq)))
14187 {
14188 if (myrpt->p.remotetimeoutwarningfreq)
14189 {
14190 if ((t - last_timeout_warning) >=
14191 myrpt->p.remotetimeoutwarningfreq)
14192 {
14193 time(&last_timeout_warning);
14194 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14195 }
14196 }
14197 else
14198 {
14199 if (!last_timeout_warning)
14200 {
14201 time(&last_timeout_warning);
14202 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14203 }
14204 }
14205 }
14206 }
14207 ms = MSWAIT;
14208 who = ast_waitfor_n(cs,n,&ms);
14209 if (who == NULL) ms = 0;
14210 elap = MSWAIT - ms;
14211 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14212 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14213 if (!ms) continue;
14214
14215 if (myrpt->dtmf_local_timer)
14216 {
14217 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14218 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14219 }
14220 rpt_mutex_lock(&myrpt->lock);
14221 do_dtmf_local(myrpt,0);
14222 rpt_mutex_unlock(&myrpt->lock);
14223
14224 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14225 rem_totx |= keyed && (!myrpt->tunerequest);
14226 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14227 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14228 rem_totx |= myrpt->tunerequest;
14229
14230 if((debug > 6) && rem_totx) {
14231 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);
14232 }
14233 if (keyed && (!keyed1))
14234 {
14235 keyed1 = 1;
14236 }
14237
14238 if (!keyed && (keyed1))
14239 {
14240 time_t myt;
14241
14242 keyed1 = 0;
14243 time(&myt);
14244
14245 if ((myrpt->p.authlevel) &&
14246 (!myrpt->loginlevel[0]) &&
14247 (myt > (t + 3)))
14248 {
14249 authreq = 1;
14250 authtold = 0;
14251 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14252 }
14253 }
14254
14255 if (rem_rx && (!myrpt->remoterx))
14256 {
14257 myrpt->remoterx = 1;
14258 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14259 }
14260 if ((!rem_rx) && (myrpt->remoterx))
14261 {
14262 myrpt->remoterx = 0;
14263 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14264 }
14265
14266 if (authreq && (!myrpt->loginlevel[0]))
14267 {
14268 if ((!authtold) && ((myrpt->authtelltimer += elap)
14269 >= AUTHTELLTIME))
14270 {
14271 authtold = 1;
14272 rpt_telemetry(myrpt,LOGINREQ,NULL);
14273 }
14274 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14275 {
14276 break;
14277 }
14278 }
14279 if (myrpt->newkey)
14280 {
14281 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14282 {
14283 myrpt->retxtimer = 0;
14284 if ((myrpt->remoterx) && (!myrpt->remotetx))
14285 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14286 else
14287 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14288 }
14289
14290 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14291 {
14292 keyed = 0;
14293 myrpt->rerxtimer = 0;
14294 }
14295 }
14296 if (rem_totx && (!myrpt->remotetx))
14297 {
14298
14299 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14300 {
14301 if(debug > 6)
14302 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14303
14304 myrpt->remotetx = 1;
14305
14306 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14307 {
14308 time(&myrpt->last_activity_time);
14309 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14310 {
14311 z.radpar = DAHDI_RADPAR_UIODATA;
14312 z.data = 1;
14313 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14314 {
14315 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14316 return -1;
14317 }
14318 }
14319 else
14320 {
14321 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14322 }
14323 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14324 }
14325 }
14326 }
14327 if ((!rem_totx) && myrpt->remotetx)
14328 {
14329 myrpt->remotetx = 0;
14330 if(!myrpt->remtxfreqok){
14331 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14332 }
14333 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14334 {
14335 z.radpar = DAHDI_RADPAR_UIODATA;
14336 z.data = 3;
14337 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14338 {
14339 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14340 return -1;
14341 }
14342 }
14343 else
14344 {
14345 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14346 }
14347 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14348 }
14349 if (myrpt->hfscanmode){
14350 myrpt->scantimer -= elap;
14351 if(myrpt->scantimer <= 0){
14352 if (!reming)
14353 {
14354 myrpt->scantimer = REM_SCANTIME;
14355 rpt_telemetry(myrpt,SCAN,0);
14356 } else myrpt->scantimer = 1;
14357 }
14358 }
14359 rpt_mutex_lock(&myrpt->lock);
14360 c = myrpt->macrobuf[0];
14361 if (c && (!myrpt->macrotimer))
14362 {
14363 myrpt->macrotimer = MACROTIME;
14364 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14365 if ((c == 'p') || (c == 'P'))
14366 myrpt->macrotimer = MACROPTIME;
14367 rpt_mutex_unlock(&myrpt->lock);
14368 if (myrpt->p.archivedir)
14369 {
14370 char str[100];
14371 sprintf(str,"DTMF(M),%c",c);
14372 donodelog(myrpt,str);
14373 }
14374 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14375 continue;
14376 } else rpt_mutex_unlock(&myrpt->lock);
14377 if (who == chan)
14378 {
14379 f = ast_read(chan);
14380 if (!f)
14381 {
14382 if (debug) printf("@@@@ link:Hung Up\n");
14383 break;
14384 }
14385 if (f->frametype == AST_FRAME_VOICE)
14386 {
14387 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14388 {
14389 ismuted = 0;
14390 }
14391
14392 ismuted |= (!myrpt->remotetx);
14393 if (dtmfed && phone_mode) ismuted = 1;
14394 dtmfed = 0;
14395 if (ismuted)
14396 {
14397 memset(f->data.ptr,0,f->datalen);
14398 if (myrpt->lastf1)
14399 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14400 if (myrpt->lastf2)
14401 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14402 }
14403 if (f) f2 = ast_frdup(f);
14404 else f2 = NULL;
14405 f1 = myrpt->lastf2;
14406 myrpt->lastf2 = myrpt->lastf1;
14407 myrpt->lastf1 = f2;
14408 if (ismuted)
14409 {
14410 if (myrpt->lastf1)
14411 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14412 if (myrpt->lastf2)
14413 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14414 }
14415 if (f1)
14416 {
14417 if (phone_mode)
14418 ast_write(myrpt->txchannel,f1);
14419 else
14420 ast_write(myrpt->txchannel,f);
14421 ast_frfree(f1);
14422 }
14423 }
14424 #ifndef OLD_ASTERISK
14425 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14426 {
14427 if (myrpt->lastf1)
14428 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14429 if (myrpt->lastf2)
14430 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14431 dtmfed = 1;
14432 }
14433 #endif
14434 if (f->frametype == AST_FRAME_DTMF)
14435 {
14436 if (myrpt->lastf1)
14437 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14438 if (myrpt->lastf2)
14439 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14440 dtmfed = 1;
14441 if (handle_remote_phone_dtmf(myrpt,f->subclass.integer,&keyed,phone_mode) == -1)
14442 {
14443 if (debug) printf("@@@@ rpt:Hung Up\n");
14444 ast_frfree(f);
14445 break;
14446 }
14447 }
14448 if (f->frametype == AST_FRAME_TEXT)
14449 {
14450 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14451 {
14452 if (debug) printf("@@@@ rpt:Hung Up\n");
14453 ast_frfree(f);
14454 break;
14455 }
14456 }
14457 if (f->frametype == AST_FRAME_CONTROL)
14458 {
14459 if (f->subclass.integer == AST_CONTROL_HANGUP)
14460 {
14461 if (debug) printf("@@@@ rpt:Hung Up\n");
14462 ast_frfree(f);
14463 break;
14464 }
14465
14466 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14467 {
14468 if (debug == 7) printf("@@@@ rx key\n");
14469 keyed = 1;
14470 myrpt->rerxtimer = 0;
14471 }
14472
14473 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14474 {
14475 myrpt->rerxtimer = 0;
14476 if (debug == 7) printf("@@@@ rx un-key\n");
14477 keyed = 0;
14478 }
14479 }
14480 ast_frfree(f);
14481 continue;
14482 }
14483 if (who == myrpt->rxchannel)
14484 {
14485 f = ast_read(myrpt->rxchannel);
14486 if (!f)
14487 {
14488 if (debug) printf("@@@@ link:Hung Up\n");
14489 break;
14490 }
14491 if (f->frametype == AST_FRAME_VOICE)
14492 {
14493 int myreming = 0;
14494
14495 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14496 myreming = reming;
14497
14498 if (myreming || (!remkeyed) ||
14499 ((myrpt->remote) && (myrpt->remotetx)) ||
14500 ((myrpt->remmode != REM_MODE_FM) &&
14501 notremming))
14502 memset(f->data.ptr,0,f->datalen);
14503 ast_write(myrpt->pchannel,f);
14504 }
14505 else if (f->frametype == AST_FRAME_CONTROL)
14506 {
14507 if (f->subclass.integer == AST_CONTROL_HANGUP)
14508 {
14509 if (debug) printf("@@@@ rpt:Hung Up\n");
14510 ast_frfree(f);
14511 break;
14512 }
14513
14514 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14515 {
14516 if (debug == 7) printf("@@@@ remote rx key\n");
14517 if (!myrpt->remotetx)
14518 {
14519 remkeyed = 1;
14520 }
14521 }
14522
14523 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14524 {
14525 if (debug == 7) printf("@@@@ remote rx un-key\n");
14526 if (!myrpt->remotetx)
14527 {
14528 remkeyed = 0;
14529 }
14530 }
14531 }
14532 ast_frfree(f);
14533 continue;
14534 }
14535 if (who == myrpt->pchannel)
14536 {
14537 f = ast_read(myrpt->pchannel);
14538 if (!f)
14539 {
14540 if (debug) printf("@@@@ link:Hung Up\n");
14541 break;
14542 }
14543 if (f->frametype == AST_FRAME_VOICE)
14544 {
14545 ast_write(chan,f);
14546 }
14547 if (f->frametype == AST_FRAME_CONTROL)
14548 {
14549 if (f->subclass.integer == AST_CONTROL_HANGUP)
14550 {
14551 if (debug) printf("@@@@ rpt:Hung Up\n");
14552 ast_frfree(f);
14553 break;
14554 }
14555 }
14556 ast_frfree(f);
14557 continue;
14558 }
14559 if ((myrpt->rxchannel != myrpt->txchannel) &&
14560 (who == myrpt->txchannel))
14561 {
14562 f = ast_read(myrpt->txchannel);
14563 if (!f)
14564 {
14565 if (debug) printf("@@@@ link:Hung Up\n");
14566 break;
14567 }
14568 if (f->frametype == AST_FRAME_CONTROL)
14569 {
14570 if (f->subclass.integer == AST_CONTROL_HANGUP)
14571 {
14572 if (debug) printf("@@@@ rpt:Hung Up\n");
14573 ast_frfree(f);
14574 break;
14575 }
14576 }
14577 ast_frfree(f);
14578 continue;
14579 }
14580 }
14581 if (myrpt->p.archivedir)
14582 {
14583 char mycmd[100],*b,*b1;
14584
14585
14586 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14587 if (!b)
14588 {
14589 b1 = "0";
14590 } else {
14591 b1 = ast_strdupa(b);
14592 ast_shrink_phone_number(b1);
14593 }
14594 sprintf(mycmd,"DISCONNECT,%s",b1);
14595 donodelog(myrpt,mycmd);
14596 }
14597
14598 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14599 sprintf(tmp,"mixmonitor stop %s",ast_channel_name(chan));
14600 ast_cli_command(nullfd,tmp);
14601 close(nullfd);
14602 rpt_mutex_lock(&myrpt->lock);
14603 myrpt->hfscanmode = 0;
14604 myrpt->hfscanstatus = 0;
14605 myrpt->remoteon = 0;
14606 rpt_mutex_unlock(&myrpt->lock);
14607 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14608 myrpt->lastf1 = NULL;
14609 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14610 myrpt->lastf2 = NULL;
14611 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14612 {
14613 z.radpar = DAHDI_RADPAR_UIOMODE;
14614 z.data = 3;
14615 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14616 {
14617 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14618 return -1;
14619 }
14620 z.radpar = DAHDI_RADPAR_UIODATA;
14621 z.data = 3;
14622 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14623 {
14624 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14625 return -1;
14626 }
14627 i = DAHDI_OFFHOOK;
14628 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14629 {
14630 ast_log(LOG_ERROR,"Cannot set hook\n");
14631 return -1;
14632 }
14633 }
14634 if (myrpt->iofd) close(myrpt->iofd);
14635 myrpt->iofd = -1;
14636 ast_hangup(myrpt->pchannel);
14637 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14638 ast_hangup(myrpt->rxchannel);
14639 closerem(myrpt);
14640 if (myrpt->p.rptnode)
14641 {
14642 rpt_mutex_lock(&myrpt->lock);
14643 for(i = 0; i < nrpts; i++)
14644 {
14645 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14646 {
14647 rpt_vars[i].xlink = 0;
14648 break;
14649 }
14650 }
14651 rpt_mutex_unlock(&myrpt->lock);
14652 }
14653 #ifdef OLD_ASTERISK
14654 LOCAL_USER_REMOVE(u);
14655 #endif
14656 return res;
14657 }
14658
14659 #ifndef OLD_ASTERISK
14660
14661
14662
14663 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14664 {
14665 int i;
14666 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14667 astman_append(s, "<nodes>\r\n");
14668 for (i=0; i< nrpts; i++)
14669 {
14670 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14671 }
14672 astman_append(s, "</nodes>\r\n");
14673 astman_append(s, "\r\n");
14674 return RESULT_SUCCESS;
14675 }
14676
14677
14678
14679
14680
14681
14682
14683 static void rpt_manager_success(struct mansession *s, const struct message *m)
14684 {
14685 const char *id = astman_get_header(m, "ActionID");
14686 if (!ast_strlen_zero(id))
14687 astman_append(s, "ActionID: %s\r\n", id);
14688 astman_append(s, "Response: Success\r\n");
14689 }
14690
14691
14692
14693
14694
14695 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14696 {
14697 int i,j,numoflinks;
14698 int dailytxtime, dailykerchunks;
14699 time_t now;
14700 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14701 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14702 long long totaltxtime;
14703 struct rpt_link *l;
14704 char *listoflinks[MAX_STAT_LINKS];
14705 char *lastdtmfcommand,*parrot_ena;
14706 char *tot_state, *ider_state, *patch_state;
14707 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14708 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14709 char *transmitterkeyed;
14710 const char *node = astman_get_header(m, "Node");
14711 struct rpt *myrpt;
14712
14713 static char *not_applicable = "N/A";
14714
14715 tot_state = ider_state =
14716 patch_state = reverse_patch_state =
14717 input_signal = not_applicable;
14718 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14719
14720 time(&now);
14721 for(i = 0; i < nrpts; i++)
14722 {
14723 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14724 rpt_manager_success(s,m);
14725
14726 myrpt = &rpt_vars[i];
14727
14728 if(myrpt->remote){
14729 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14730 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14731 char offsetc,powerlevelc;
14732
14733 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14734
14735 rpt_mutex_lock(&myrpt->lock);
14736 if((remoteon = myrpt->remoteon)){
14737 if(!ast_strlen_zero(myrpt->loginuser))
14738 loginuser = ast_strdup(myrpt->loginuser);
14739 if(!ast_strlen_zero(myrpt->loginlevel))
14740 loginlevel = ast_strdup(myrpt->loginlevel);
14741 if(!ast_strlen_zero(myrpt->freq))
14742 freq = ast_strdup(myrpt->freq);
14743 if(!ast_strlen_zero(myrpt->rxpl))
14744 rxpl = ast_strdup(myrpt->rxpl);
14745 if(!ast_strlen_zero(myrpt->txpl))
14746 txpl = ast_strdup(myrpt->txpl);
14747 remmode = myrpt->remmode;
14748 offset = myrpt->offset;
14749 powerlevel = myrpt->powerlevel;
14750 rxplon = myrpt->rxplon;
14751 txplon = myrpt->txplon;
14752 }
14753 rpt_mutex_unlock(&myrpt->lock);
14754 astman_append(s, "IsRemoteBase: YES\r\n");
14755 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14756 if(remoteon){
14757 if(loginuser){
14758 astman_append(s, "LogInUser: %s\r\n", loginuser);
14759 ast_free(loginuser);
14760 }
14761 if(loginlevel){
14762 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14763 ast_free(loginlevel);
14764 }
14765 if(freq){
14766 astman_append(s, "Freq: %s\r\n", freq);
14767 ast_free(freq);
14768 }
14769 reportfmstuff = 0;
14770 switch(remmode){
14771 case REM_MODE_FM:
14772 modestr = "FM";
14773 reportfmstuff = 1;
14774 break;
14775 case REM_MODE_AM:
14776 modestr = "AM";
14777 break;
14778 case REM_MODE_USB:
14779 modestr = "USB";
14780 break;
14781 default:
14782 modestr = "LSB";
14783 break;
14784 }
14785 astman_append(s, "RemMode: %s\r\n", modestr);
14786 if(reportfmstuff){
14787 switch(offset){
14788 case REM_SIMPLEX:
14789 offsetc = 'S';
14790 break;
14791 case REM_MINUS:
14792 offsetc = '-';
14793 break;
14794 default:
14795 offsetc = '+';
14796 break;
14797 }
14798 astman_append(s, "RemOffset: %c\r\n", offsetc);
14799 if(rxplon && rxpl){
14800 astman_append(s, "RxPl: %s\r\n",rxpl);
14801 ast_free(rxpl);
14802 }
14803 if(txplon && txpl){
14804 astman_append(s, "TxPl: %s\r\n",txpl);
14805 ast_free(txpl);
14806 }
14807 }
14808 switch(powerlevel){
14809 case REM_LOWPWR:
14810 powerlevelc = 'L';
14811 break;
14812 case REM_MEDPWR:
14813 powerlevelc = 'M';
14814 break;
14815 default:
14816 powerlevelc = 'H';
14817 break;
14818 }
14819 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14820 }
14821 astman_append(s, "\r\n");
14822 return 0;
14823 }
14824
14825
14826
14827 rpt_mutex_lock(&myrpt->lock);
14828 dailytxtime = myrpt->dailytxtime;
14829 totaltxtime = myrpt->totaltxtime;
14830 dailykeyups = myrpt->dailykeyups;
14831 totalkeyups = myrpt->totalkeyups;
14832 dailykerchunks = myrpt->dailykerchunks;
14833 totalkerchunks = myrpt->totalkerchunks;
14834 dailyexecdcommands = myrpt->dailyexecdcommands;
14835 totalexecdcommands = myrpt->totalexecdcommands;
14836 timeouts = myrpt->timeouts;
14837
14838
14839
14840 reverse_patch_state = "DOWN";
14841 numoflinks = 0;
14842 l = myrpt->links.next;
14843 while(l && (l != &myrpt->links)){
14844 if(numoflinks >= MAX_STAT_LINKS){
14845 ast_log(LOG_NOTICE,
14846 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14847 break;
14848 }
14849 if (l->name[0] == '0'){
14850 reverse_patch_state = "UP";
14851 l = l->next;
14852 continue;
14853 }
14854 listoflinks[numoflinks] = ast_strdup(l->name);
14855 if(listoflinks[numoflinks] == NULL){
14856 break;
14857 }
14858 else{
14859 numoflinks++;
14860 }
14861 l = l->next;
14862 }
14863
14864 if(myrpt->keyed)
14865 input_signal = "YES";
14866 else
14867 input_signal = "NO";
14868
14869 if(myrpt->txkeyed)
14870 transmitterkeyed = "YES";
14871 else
14872 transmitterkeyed = "NO";
14873
14874 if(myrpt->p.parrotmode)
14875 parrot_ena = "ENABLED";
14876 else
14877 parrot_ena = "DISABLED";
14878
14879 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14880 sys_ena = "DISABLED";
14881 else
14882 sys_ena = "ENABLED";
14883
14884 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14885 tot_ena = "DISABLED";
14886 else
14887 tot_ena = "ENABLED";
14888
14889 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14890 link_ena = "DISABLED";
14891 else
14892 link_ena = "ENABLED";
14893
14894 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14895 patch_ena = "DISABLED";
14896 else
14897 patch_ena = "ENABLED";
14898
14899 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14900 sch_ena = "DISABLED";
14901 else
14902 sch_ena = "ENABLED";
14903
14904 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14905 user_funs = "DISABLED";
14906 else
14907 user_funs = "ENABLED";
14908
14909 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14910 tail_type = "ALTERNATE";
14911 else
14912 tail_type = "STANDARD";
14913
14914 if(!myrpt->totimer)
14915 tot_state = "TIMED OUT!";
14916 else if(myrpt->totimer != myrpt->p.totime)
14917 tot_state = "ARMED";
14918 else
14919 tot_state = "RESET";
14920
14921 if(myrpt->tailid)
14922 ider_state = "QUEUED IN TAIL";
14923 else if(myrpt->mustid)
14924 ider_state = "QUEUED FOR CLEANUP";
14925 else
14926 ider_state = "CLEAN";
14927
14928 switch(myrpt->callmode){
14929 case 1:
14930 patch_state = "DIALING";
14931 break;
14932 case 2:
14933 patch_state = "CONNECTING";
14934 break;
14935 case 3:
14936 patch_state = "UP";
14937 break;
14938
14939 case 4:
14940 patch_state = "CALL FAILED";
14941 break;
14942
14943 default:
14944 patch_state = "DOWN";
14945 }
14946
14947 if(strlen(myrpt->exten)){
14948 called_number = ast_strdup(myrpt->exten);
14949 }
14950
14951 if(strlen(myrpt->lastdtmfcommand)){
14952 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14953 }
14954 rpt_mutex_unlock(&myrpt->lock);
14955
14956 astman_append(s, "IsRemoteBase: NO\r\n");
14957 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14958 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14959 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14960 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14961 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14962 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14963 astman_append(s, "TailLength: %s\r\n", tail_type);
14964 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14965 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14966 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14967 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14968 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14969 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14970 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14971 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14972 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14973 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14974 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14975 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14976 hours = dailytxtime/3600000;
14977 dailytxtime %= 3600000;
14978 minutes = dailytxtime/60000;
14979 dailytxtime %= 60000;
14980 seconds = dailytxtime/1000;
14981 dailytxtime %= 1000;
14982
14983 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14984 hours, minutes, seconds, dailytxtime);
14985
14986 hours = (int) totaltxtime/3600000;
14987 totaltxtime %= 3600000;
14988 minutes = (int) totaltxtime/60000;
14989 totaltxtime %= 60000;
14990 seconds = (int) totaltxtime/1000;
14991 totaltxtime %= 1000;
14992
14993 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14994 hours, minutes, seconds, (int) totaltxtime);
14995
14996 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14997 if(!numoflinks){
14998 strcat(str,"<NONE>");
14999 }
15000 else{
15001 for(j = 0 ;j < numoflinks; j++){
15002 sprintf(str+strlen(str), "%s", listoflinks[j]);
15003 if(j < numoflinks - 1)
15004 strcat(str,",");
15005 }
15006 }
15007 astman_append(s,"%s\r\n", str);
15008
15009 astman_append(s, "Autopatch: %s\r\n", patch_ena);
15010 astman_append(s, "AutopatchState: %s\r\n", patch_state);
15011 astman_append(s, "AutopatchCalledNumber: %s\r\n",
15012 (called_number && strlen(called_number)) ? called_number : not_applicable);
15013 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
15014 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
15015 astman_append(s, "UserFunctions: %s\r\n", user_funs);
15016
15017 for(j = 0; j < numoflinks; j++){
15018 ast_free(listoflinks[j]);
15019 }
15020 if(called_number){
15021 ast_free(called_number);
15022 }
15023 if(lastdtmfcommand){
15024 ast_free(lastdtmfcommand);
15025 }
15026 astman_append(s, "\r\n");
15027 return 0;
15028 }
15029 }
15030 astman_send_error(s, m, "RptStatus unknown or missing node");
15031 return -1;
15032 }
15033
15034
15035
15036
15037
15038
15039
15040 static int manager_rpt_status(struct mansession *s, const struct message *m)
15041 {
15042 int i,res,len,idx;
15043 int uptime,hours,minutes;
15044 time_t now;
15045 const char *cmd = astman_get_header(m, "Command");
15046 char *str;
15047 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15048 struct mgrcmdtbl{
15049 const char *cmd;
15050 int index;
15051 };
15052 static struct mgrcmdtbl mct[] = {
15053 {"RptStat",MGRCMD_RPTSTAT},
15054 {"NodeStat",MGRCMD_NODESTAT},
15055 {NULL,0}
15056 };
15057
15058 time(&now);
15059
15060 len = 1024;
15061 if(!(str = ast_malloc(len)))
15062 return -1;
15063
15064
15065 if(ast_strlen_zero(cmd)){
15066 astman_send_error(s, m, "RptStatus missing command");
15067 ast_free(str);
15068 return 0;
15069 }
15070
15071 for(i = 0 ; mct[i].cmd ; i++){
15072 if(!strcmp(mct[i].cmd, cmd))
15073 break;
15074 }
15075
15076 if(!mct[i].cmd){
15077 astman_send_error(s, m, "RptStatus unknown command");
15078 ast_free(str);
15079 return 0;
15080 }
15081 else
15082 idx = mct[i].index;
15083
15084 switch(idx){
15085
15086 case MGRCMD_RPTSTAT:
15087
15088 if((res = snprintf(str, len, "Nodes: ")) > -1)
15089 len -= res;
15090 else{
15091 ast_free(str);
15092 return 0;
15093 }
15094 for(i = 0; i < nrpts; i++){
15095 if(i < nrpts - 1){
15096 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15097 ast_free(str);
15098 return 0;
15099 }
15100 }
15101 else{
15102 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15103 ast_free(str);
15104 return 0;
15105 }
15106 }
15107 len -= res;
15108 }
15109
15110 rpt_manager_success(s,m);
15111
15112 if(!nrpts)
15113 astman_append(s, "<NONE>\r\n");
15114 else
15115 astman_append(s, "%s\r\n", str);
15116
15117 uptime = (int)(now - starttime);
15118 hours = uptime/3600;
15119 uptime %= 3600;
15120 minutes = uptime/60;
15121 uptime %= 60;
15122
15123 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15124 hours, minutes, uptime);
15125
15126 astman_append(s, "\r\n");
15127 break;
15128
15129 case MGRCMD_NODESTAT:
15130 res = rpt_manager_do_stats(s,m,str);
15131 ast_free(str);
15132 return res;
15133
15134 default:
15135 astman_send_error(s, m, "RptStatus invalid command");
15136 break;
15137 }
15138 ast_free(str);
15139 return 0;
15140 }
15141
15142 #endif
15143
15144 #ifdef OLD_ASTERISK
15145 int unload_module()
15146 #else
15147 static int unload_module(void)
15148 #endif
15149 {
15150 int i, res;
15151
15152 #ifdef OLD_ASTERISK
15153 STANDARD_HANGUP_LOCALUSERS;
15154 #endif
15155 for(i = 0; i < nrpts; i++) {
15156 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15157 ast_mutex_destroy(&rpt_vars[i].lock);
15158 ast_mutex_destroy(&rpt_vars[i].remlock);
15159 }
15160 res = ast_unregister_application(app);
15161
15162 #ifdef NEW_ASTERISK
15163 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15164 #else
15165
15166 ast_cli_unregister(&cli_debug);
15167 ast_cli_unregister(&cli_dump);
15168 ast_cli_unregister(&cli_stats);
15169 ast_cli_unregister(&cli_lstats);
15170 ast_cli_unregister(&cli_nodes);
15171 ast_cli_unregister(&cli_local_nodes);
15172 ast_cli_unregister(&cli_reload);
15173 ast_cli_unregister(&cli_restart);
15174 ast_cli_unregister(&cli_fun);
15175 ast_cli_unregister(&cli_fun1);
15176 res |= ast_cli_unregister(&cli_cmd);
15177 #endif
15178 #ifndef OLD_ASTERISK
15179 res |= ast_manager_unregister("RptLocalNodes");
15180 res |= ast_manager_unregister("RptStatus");
15181 #endif
15182 return res;
15183 }
15184
15185 #ifdef OLD_ASTERISK
15186 int load_module()
15187 #else
15188 static int load_module(void)
15189 #endif
15190 {
15191 int res;
15192 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15193
15194 #ifdef NEW_ASTERISK
15195 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15196 res = 0;
15197 #else
15198
15199 ast_cli_register(&cli_debug);
15200 ast_cli_register(&cli_dump);
15201 ast_cli_register(&cli_stats);
15202 ast_cli_register(&cli_lstats);
15203 ast_cli_register(&cli_nodes);
15204 ast_cli_register(&cli_local_nodes);
15205 ast_cli_register(&cli_reload);
15206 ast_cli_register(&cli_restart);
15207 ast_cli_register(&cli_fun);
15208 ast_cli_register(&cli_fun1);
15209 res = ast_cli_register(&cli_cmd);
15210 #endif
15211 #ifndef OLD_ASTERISK
15212 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15213 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15214
15215 #endif
15216 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15217 return res;
15218 }
15219
15220 #ifdef OLD_ASTERISK
15221 char *description()
15222 {
15223 return tdesc;
15224 }
15225 int usecount(void)
15226 {
15227 int res;
15228 STANDARD_USECOUNT(res);
15229 return res;
15230 }
15231
15232 char *key()
15233 {
15234 return ASTERISK_GPL_KEY;
15235 }
15236 #endif
15237
15238 #ifdef OLD_ASTERISK
15239 int reload()
15240 #else
15241 static int reload(void)
15242 #endif
15243 {
15244 int n;
15245
15246 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15247 return(0);
15248 }
15249
15250
15251 #ifndef OLD_ASTERISK
15252
15253 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15254 .load = load_module,
15255 .unload = unload_module,
15256 .reload = reload,
15257 );
15258 #endif
15259