00001 #define NEW_ASTERISK
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 #ifdef OLD_ASTERISK
00171 #define ast_free free
00172 #define ast_malloc malloc
00173 #define ast_strdup strdup
00174 #endif
00175
00176
00177 #define MAXDTMF 32
00178 #define MAXMACRO 2048
00179 #define MAXLINKLIST 512
00180 #define LINKLISTTIME 10000
00181 #define LINKLISTSHORTTIME 200
00182 #define LINKPOSTTIME 30000
00183 #define LINKPOSTSHORTTIME 200
00184 #define KEYPOSTTIME 30000
00185 #define KEYPOSTSHORTTIME 200
00186 #define MACROTIME 100
00187 #define MACROPTIME 500
00188 #define DTMF_TIMEOUT 3
00189 #define KENWOOD_RETRIES 5
00190 #define TOPKEYN 32
00191 #define TOPKEYWAIT 3
00192 #define TOPKEYMAXSTR 30
00193
00194 #define AUTHTELLTIME 7000
00195 #define AUTHTXTIME 1000
00196 #define AUTHLOGOUTTIME 25000
00197
00198 #ifdef __RPT_NOTCH
00199 #define MAXFILTERS 10
00200 #endif
00201
00202 #define DISC_TIME 10000
00203 #define MAX_RETRIES 5
00204 #define MAX_RETRIES_PERM 1000000000
00205
00206 #define REDUNDANT_TX_TIME 2000
00207
00208 #define RETRY_TIMER_MS 5000
00209
00210 #define PATCH_DIALPLAN_TIMEOUT 1500
00211
00212 #ifdef OLD_ASTERISK
00213 #define START_DELAY 10
00214 #else
00215 #define START_DELAY 2
00216 #endif
00217
00218 #define RPT_LOCKOUT_SECS 10
00219
00220 #define MAXPEERSTR 31
00221 #define MAXREMSTR 15
00222
00223 #define DELIMCHR ','
00224 #define QUOTECHR 34
00225
00226 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00227
00228 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00229 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00230 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00232 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00233
00234 #define NODES "nodes"
00235 #define EXTNODES "extnodes"
00236 #define MEMORY "memory"
00237 #define MACRO "macro"
00238 #define FUNCTIONS "functions"
00239 #define TELEMETRY "telemetry"
00240 #define MORSE "morse"
00241 #define TONEMACRO "tonemacro"
00242 #define FUNCCHAR '*'
00243 #define ENDCHAR '#'
00244 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00245 #define NODENAMES "rpt/nodenames"
00246 #define PARROTFILE "/tmp/parrot_%s_%u"
00247
00248 #define PARROTTIME 1000
00249
00250 #define DEFAULT_IOBASE 0x378
00251
00252 #define DEFAULT_CIV_ADDR 0x58
00253
00254 #define MAXCONNECTTIME 5000
00255
00256 #define MAXNODESTR 300
00257
00258 #define MAXNODELEN 16
00259
00260 #define MAXIDENTLEN 32
00261
00262 #define MAXPATCHCONTEXT 100
00263
00264 #define ACTIONSIZE 32
00265
00266 #define TELEPARAMSIZE 256
00267
00268 #define REM_SCANTIME 100
00269
00270 #define DTMF_LOCAL_TIME 250
00271 #define DTMF_LOCAL_STARTTIME 500
00272
00273 #define IC706_PL_MEMORY_OFFSET 50
00274
00275 #define VOX_ON_DEBOUNCE_COUNT 3
00276 #define VOX_OFF_DEBOUNCE_COUNT 20
00277 #define VOX_MAX_THRESHOLD 10000.0
00278 #define VOX_MIN_THRESHOLD 3000.0
00279 #define VOX_TIMEOUT_MS 5000
00280 #define VOX_RECOVER_MS 500
00281 #define SIMPLEX_PATCH_DELAY 25
00282 #define SIMPLEX_PHONE_DELAY 25
00283
00284 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00285
00286 #define ALLOW_LOCAL_CHANNELS
00287
00288 enum {REM_OFF,REM_MONITOR,REM_TX};
00289
00290 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00291 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00292 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00293 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00294 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00295 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00296 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00297 STATS_TIME_LOCAL};
00298
00299
00300 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00301
00302 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00303
00304 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00305
00306 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00307
00308 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00309
00310 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00311
00312 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00313 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00314
00315 #include "asterisk.h"
00316
00317 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211580 $")
00318
00319 #include <signal.h>
00320 #include <stdio.h>
00321 #include <stdint.h>
00322 #include <unistd.h>
00323 #include <string.h>
00324 #include <stdlib.h>
00325 #include <search.h>
00326 #include <sys/types.h>
00327 #include <sys/stat.h>
00328 #include <errno.h>
00329 #include <dirent.h>
00330 #include <ctype.h>
00331 #include <sys/stat.h>
00332 #include <sys/time.h>
00333 #include <sys/file.h>
00334 #include <sys/ioctl.h>
00335 #ifdef HAVE_SYS_IO_H
00336 #include <sys/io.h>
00337 #endif
00338 #include <sys/vfs.h>
00339 #include <math.h>
00340 #include <dahdi/user.h>
00341 #include <dahdi/tonezone.h>
00342 #include <netinet/in.h>
00343 #include <arpa/inet.h>
00344
00345 #include "asterisk/utils.h"
00346 #include "asterisk/lock.h"
00347 #include "asterisk/file.h"
00348 #include "asterisk/logger.h"
00349 #include "asterisk/channel.h"
00350 #include "asterisk/callerid.h"
00351 #include "asterisk/pbx.h"
00352 #include "asterisk/module.h"
00353 #include "asterisk/translate.h"
00354 #include "asterisk/features.h"
00355 #include "asterisk/options.h"
00356 #include "asterisk/cli.h"
00357 #include "asterisk/config.h"
00358 #include "asterisk/say.h"
00359 #include "asterisk/localtime.h"
00360 #include "asterisk/cdr.h"
00361 #include "asterisk/options.h"
00362 #include "asterisk/manager.h"
00363 #include "asterisk/app.h"
00364
00365 #include <termios.h>
00366
00367 #ifdef NEW_ASTERISK
00368 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00369 #endif
00370
00371
00372
00373 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00374
00375 void ast_playtones_stop(struct ast_channel *chan);
00376
00377 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00378
00379 static char *app = "Rpt";
00380
00381 static char *synopsis = "Radio Repeater/Remote Base Control System";
00382
00383 static char *descrip =
00384 " Rpt(nodename[|options][|M][|*]): \n"
00385 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00386 "\n"
00387 " Not specifying an option puts it in normal endpoint mode (where source\n"
00388 " IP and nodename are verified).\n"
00389 "\n"
00390 " Options are as follows:\n"
00391 "\n"
00392 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00393 " this if you have checked security already (like with an IAX2\n"
00394 " user/password or something).\n"
00395 "\n"
00396 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00397 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00398 " specified by the 'announce-string') is played on radio system.\n"
00399 " Users of radio system can access autopatch, dial specified\n"
00400 " code, and pick up call. Announce-string is list of names of\n"
00401 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00402 " or \"NODE\" to substitute node number.\n"
00403 "\n"
00404 " P - Phone Control mode. This allows a regular phone user to have\n"
00405 " full control and audio access to the radio system. For the\n"
00406 " user to have DTMF control, the 'phone_functions' parameter\n"
00407 " must be specified for the node in 'rpt.conf'. An additional\n"
00408 " function (cop,6) must be listed so that PTT control is available.\n"
00409 "\n"
00410 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00411 " have full control and audio access to the radio system. In this\n"
00412 " mode, the PTT is activated for the entire length of the call.\n"
00413 " For the user to have DTMF control (not generally recomended in\n"
00414 " this mode), the 'dphone_functions' parameter must be specified\n"
00415 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00416 " available to the phone user.\n"
00417 "\n"
00418 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00419 " audio-only access to the radio system. In this mode, the\n"
00420 " transmitter is toggled on and off when the phone user presses the\n"
00421 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00422 " will turn off if the endchar (#) key is pressed. When a user first\n"
00423 " calls in, the transmitter will be off, and the user can listen for\n"
00424 " radio traffic. When the user wants to transmit, they press the *\n"
00425 " key, start talking, then press the * key again or the # key to turn\n"
00426 " the transmitter off. No other functions can be executed by the\n"
00427 " user on the phone when this mode is selected. Note: If your\n"
00428 " radio system is full-duplex, we recommend using either P or D\n"
00429 " modes as they provide more flexibility.\n"
00430 "\n"
00431 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00432 "\n"
00433 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00434 "\n"
00435 " * - Alt Macro to execute (e.g. *7 for status)\n"
00436 "\n";
00437 ;
00438
00439 static int debug = 0;
00440 static int nrpts = 0;
00441
00442 static char remdtmfstr[] = "0123456789*#ABCD";
00443
00444 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00445
00446 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00447
00448 #define NRPTSTAT 7
00449
00450 struct rpt_chan_stat
00451 {
00452 struct timeval last;
00453 long long total;
00454 unsigned long count;
00455 unsigned long largest;
00456 struct timeval largest_time;
00457 };
00458
00459 char *discstr = "!!DISCONNECT!!";
00460 char *newkeystr = "!NEWKEY!";
00461 static char *remote_rig_ft897="ft897";
00462 static char *remote_rig_rbi="rbi";
00463 static char *remote_rig_kenwood="kenwood";
00464 static char *remote_rig_tm271="tm271";
00465 static char *remote_rig_ic706="ic706";
00466 static char *remote_rig_rtx150="rtx150";
00467 static char *remote_rig_rtx450="rtx450";
00468 static char *remote_rig_ppp16="ppp16";
00469
00470 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00471 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00472
00473 #ifdef OLD_ASTERISK
00474 STANDARD_LOCAL_USER;
00475 LOCAL_USER_DECL;
00476 #endif
00477
00478 #define MSWAIT 200
00479 #define HANGTIME 5000
00480 #define TOTIME 180000
00481 #define IDTIME 300000
00482 #define MAXRPTS 20
00483 #define MAX_STAT_LINKS 32
00484 #define POLITEID 30000
00485 #define FUNCTDELAY 1500
00486
00487 #define MAXXLAT 20
00488 #define MAXXLATTIME 3
00489
00490 #define MAX_SYSSTATES 10
00491
00492 struct vox {
00493 float speech_energy;
00494 float noise_energy;
00495 int enacount;
00496 char voxena;
00497 char lastvox;
00498 int offdebcnt;
00499 int ondebcnt;
00500 } ;
00501
00502 #define mymax(x,y) ((x > y) ? x : y)
00503 #define mymin(x,y) ((x < y) ? x : y)
00504
00505 struct rpt_topkey
00506 {
00507 char node[TOPKEYMAXSTR];
00508 int timesince;
00509 int keyed;
00510 } ;
00511
00512 struct rpt_xlat
00513 {
00514 char funccharseq[MAXXLAT];
00515 char endcharseq[MAXXLAT];
00516 char passchars[MAXXLAT];
00517 int funcindex;
00518 int endindex;
00519 time_t lastone;
00520 } ;
00521
00522 static time_t starttime = 0;
00523
00524 static pthread_t rpt_master_thread;
00525
00526 struct rpt;
00527
00528 struct rpt_link
00529 {
00530 struct rpt_link *next;
00531 struct rpt_link *prev;
00532 char mode;
00533 char isremote;
00534 char phonemode;
00535 char phonevox;
00536 char name[MAXNODESTR];
00537 char lasttx;
00538 char lasttx1;
00539 char lastrx;
00540 char lastrealrx;
00541 char lastrx1;
00542 char connected;
00543 char hasconnected;
00544 char perma;
00545 char thisconnected;
00546 char outbound;
00547 char disced;
00548 char killme;
00549 long elaptime;
00550 long disctime;
00551 long retrytimer;
00552 long retxtimer;
00553 long rerxtimer;
00554 int retries;
00555 int max_retries;
00556 int reconnects;
00557 long long connecttime;
00558 struct ast_channel *chan;
00559 struct ast_channel *pchan;
00560 char linklist[MAXLINKLIST];
00561 time_t linklistreceived;
00562 long linklisttimer;
00563 int dtmfed;
00564 int linkunkeytocttimer;
00565 struct timeval lastlinktv;
00566 struct ast_frame *lastf1,*lastf2;
00567 struct rpt_chan_stat chan_stat[NRPTSTAT];
00568 struct vox vox;
00569 char wasvox;
00570 int voxtotimer;
00571 char voxtostate;
00572 char newkey;
00573 #ifdef OLD_ASTERISK
00574 AST_LIST_HEAD(, ast_frame) rxq;
00575 #else
00576 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00577 #endif
00578 } ;
00579
00580 struct rpt_lstat
00581 {
00582 struct rpt_lstat *next;
00583 struct rpt_lstat *prev;
00584 char peer[MAXPEERSTR];
00585 char name[MAXNODESTR];
00586 char mode;
00587 char outbound;
00588 char reconnects;
00589 char thisconnected;
00590 long long connecttime;
00591 struct rpt_chan_stat chan_stat[NRPTSTAT];
00592 } ;
00593
00594 struct rpt_tele
00595 {
00596 struct rpt_tele *next;
00597 struct rpt_tele *prev;
00598 struct rpt *rpt;
00599 struct ast_channel *chan;
00600 int mode;
00601 struct rpt_link mylink;
00602 char param[TELEPARAMSIZE];
00603 intptr_t submode;
00604 uintptr_t parrot;
00605 pthread_t threadid;
00606 } ;
00607
00608 struct function_table_tag
00609 {
00610 char action[ACTIONSIZE];
00611 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00612 int command_source, struct rpt_link *mylink);
00613 } ;
00614
00615
00616
00617 struct morse_bits
00618 {
00619 int len;
00620 int ddcomb;
00621 } ;
00622
00623 struct telem_defaults
00624 {
00625 char name[20];
00626 char value[80];
00627 } ;
00628
00629
00630 struct sysstate
00631 {
00632 char txdisable;
00633 char totdisable;
00634 char linkfundisable;
00635 char autopatchdisable;
00636 char schedulerdisable;
00637 char userfundisable;
00638 char alternatetail;
00639 };
00640
00641
00642 #define CMD_DEPTH 1
00643 #define CMD_STATE_IDLE 0
00644 #define CMD_STATE_BUSY 1
00645 #define CMD_STATE_READY 2
00646 #define CMD_STATE_EXECUTING 3
00647
00648 struct rpt_cmd_struct
00649 {
00650 int state;
00651 int functionNumber;
00652 char param[MAXDTMF];
00653 char digits[MAXDTMF];
00654 int command_source;
00655 };
00656
00657 static struct rpt
00658 {
00659 ast_mutex_t lock;
00660 ast_mutex_t remlock;
00661 ast_mutex_t statpost_lock;
00662 struct ast_config *cfg;
00663 char reload;
00664 char xlink;
00665 unsigned int statpost_seqno;
00666
00667 char *name;
00668 char *rxchanname;
00669 char *txchanname;
00670 char remote;
00671 char *remoterig;
00672 struct rpt_chan_stat chan_stat[NRPTSTAT];
00673 unsigned int scram;
00674
00675 struct {
00676 char *ourcontext;
00677 char *ourcallerid;
00678 char *acctcode;
00679 char *ident;
00680 char *tonezone;
00681 char simple;
00682 char *functions;
00683 char *link_functions;
00684 char *phone_functions;
00685 char *dphone_functions;
00686 char *alt_functions;
00687 char *nodes;
00688 char *extnodes;
00689 char *extnodefile;
00690 int hangtime;
00691 int althangtime;
00692 int totime;
00693 int idtime;
00694 int tailmessagetime;
00695 int tailsquashedtime;
00696 int duplex;
00697 int politeid;
00698 char *tailmessages[500];
00699 int tailmessagemax;
00700 char *memory;
00701 char *macro;
00702 char *tonemacro;
00703 char *startupmacro;
00704 int iobase;
00705 char *ioport;
00706 char funcchar;
00707 char endchar;
00708 char nobusyout;
00709 char notelemtx;
00710 char propagate_dtmf;
00711 char propagate_phonedtmf;
00712 char linktolink;
00713 unsigned char civaddr;
00714 struct rpt_xlat inxlat;
00715 struct rpt_xlat outxlat;
00716 char *archivedir;
00717 int authlevel;
00718 char *csstanzaname;
00719 char *skedstanzaname;
00720 char *txlimitsstanzaname;
00721 long monminblocks;
00722 int remoteinacttimeout;
00723 int remotetimeout;
00724 int remotetimeoutwarning;
00725 int remotetimeoutwarningfreq;
00726 int sysstate_cur;
00727 struct sysstate s[MAX_SYSSTATES];
00728 char parrotmode;
00729 int parrottime;
00730 char *rptnode;
00731 char remote_mars;
00732 int voxtimeout_ms;
00733 int voxrecover_ms;
00734 int simplexpatchdelay;
00735 int simplexphonedelay;
00736 char *statpost_program;
00737 char *statpost_url;
00738 } p;
00739 struct rpt_link links;
00740 int unkeytocttimer;
00741 time_t lastkeyedtime;
00742 time_t lasttxkeyedtime;
00743 char keyed;
00744 char txkeyed;
00745 char exttx;
00746 char localtx;
00747 char remoterx;
00748 char remotetx;
00749 char remoteon;
00750 char remtxfreqok;
00751 char tounkeyed;
00752 char tonotify;
00753 char dtmfbuf[MAXDTMF];
00754 char macrobuf[MAXMACRO];
00755 char rem_dtmfbuf[MAXDTMF];
00756 char lastdtmfcommand[MAXDTMF];
00757 char cmdnode[50];
00758 char nowchan;
00759 char waschan;
00760 char bargechan;
00761 char macropatch;
00762 char parrotstate;
00763 int parrottimer;
00764 unsigned int parrotcnt;
00765 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00766 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00767 struct ast_channel *voxchannel;
00768 struct ast_frame *lastf1,*lastf2;
00769 struct rpt_tele tele;
00770 struct timeval lasttv,curtv;
00771 pthread_t rpt_call_thread,rpt_thread;
00772 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00773 int calldigittimer;
00774 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00775 int mustid,tailid;
00776 int tailevent;
00777 int telemrefcount;
00778 int dtmfidx,rem_dtmfidx;
00779 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00780 int totalexecdcommands, dailyexecdcommands;
00781 long retxtimer;
00782 long rerxtimer;
00783 long long totaltxtime;
00784 char mydtmf;
00785 char exten[AST_MAX_EXTENSION];
00786 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00787 char offset;
00788 char powerlevel;
00789 char txplon;
00790 char rxplon;
00791 char remmode;
00792 char tunerequest;
00793 char hfscanmode;
00794 int hfscanstatus;
00795 char hfscanstop;
00796 char lastlinknode[MAXNODESTR];
00797 char savednodes[MAXNODESTR];
00798 int stopgen;
00799 char patchfarenddisconnect;
00800 char patchnoct;
00801 char patchquiet;
00802 char patchcontext[MAXPATCHCONTEXT];
00803 int patchdialtime;
00804 int macro_longest;
00805 int phone_longestfunc;
00806 int alt_longestfunc;
00807 int dphone_longestfunc;
00808 int link_longestfunc;
00809 int longestfunc;
00810 int longestnode;
00811 int threadrestarts;
00812 int tailmessagen;
00813 time_t disgorgetime;
00814 time_t lastthreadrestarttime;
00815 long macrotimer;
00816 char lastnodewhichkeyedusup[MAXNODESTR];
00817 int dtmf_local_timer;
00818 char dtmf_local_str[100];
00819 struct ast_filestream *monstream,*parrotstream;
00820 char loginuser[50];
00821 char loginlevel[10];
00822 long authtelltimer;
00823 long authtimer;
00824 int iofd;
00825 time_t start_time,last_activity_time;
00826 char lasttone[32];
00827 struct rpt_tele *active_telem;
00828 struct rpt_topkey topkey[TOPKEYN];
00829 int topkeystate;
00830 time_t topkeytime;
00831 int topkeylong;
00832 struct vox vox;
00833 char wasvox;
00834 int voxtotimer;
00835 char voxtostate;
00836 int linkposttimer;
00837 int keyposttimer;
00838 char newkey;
00839 char inpadtest;
00840 #ifdef OLD_ASTERISK
00841 AST_LIST_HEAD(, ast_frame) txq;
00842 #else
00843 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00844 #endif
00845 char txrealkeyed;
00846 #ifdef __RPT_NOTCH
00847 struct rptfilter
00848 {
00849 char desc[100];
00850 float x0;
00851 float x1;
00852 float x2;
00853 float y0;
00854 float y1;
00855 float y2;
00856 float gain;
00857 float const0;
00858 float const1;
00859 float const2;
00860 } filters[MAXFILTERS];
00861 #endif
00862 #ifdef _MDC_DECODE_H_
00863 mdc_decoder_t *mdc;
00864 unsigned short lastunit;
00865 #endif
00866 struct rpt_cmd_struct cmdAction;
00867 } rpt_vars[MAXRPTS];
00868
00869 struct nodelog {
00870 struct nodelog *next;
00871 struct nodelog *prev;
00872 time_t timestamp;
00873 char archivedir[MAXNODESTR];
00874 char str[MAXNODESTR * 2];
00875 } nodelog;
00876
00877 static int service_scan(struct rpt *myrpt);
00878 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00879 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00880 static int simple_command_ft897(struct rpt *myrpt, char command);
00881 static int setrem(struct rpt *myrpt);
00882 static int setrtx_check(struct rpt *myrpt);
00883 static int channel_revert(struct rpt *myrpt);
00884 static int channel_steer(struct rpt *myrpt, char *data);
00885
00886 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00887
00888 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00889
00890 #ifdef APP_RPT_LOCK_DEBUG
00891
00892 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00893
00894 #define MAXLOCKTHREAD 100
00895
00896 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00897 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00898
00899 struct lockthread
00900 {
00901 pthread_t id;
00902 int lockcount;
00903 int lastlock;
00904 int lastunlock;
00905 } lockthreads[MAXLOCKTHREAD];
00906
00907
00908 struct by_lightning
00909 {
00910 int line;
00911 struct timeval tv;
00912 struct rpt *rpt;
00913 struct lockthread lockthread;
00914 } lock_ring[32];
00915
00916 int lock_ring_index = 0;
00917
00918 AST_MUTEX_DEFINE_STATIC(locklock);
00919
00920 static struct lockthread *get_lockthread(pthread_t id)
00921 {
00922 int i;
00923
00924 for(i = 0; i < MAXLOCKTHREAD; i++)
00925 {
00926 if (lockthreads[i].id == id) return(&lockthreads[i]);
00927 }
00928 return(NULL);
00929 }
00930
00931 static struct lockthread *put_lockthread(pthread_t id)
00932 {
00933 int i;
00934
00935 for(i = 0; i < MAXLOCKTHREAD; i++)
00936 {
00937 if (lockthreads[i].id == id)
00938 return(&lockthreads[i]);
00939 }
00940 for(i = 0; i < MAXLOCKTHREAD; i++)
00941 {
00942 if (!lockthreads[i].id)
00943 {
00944 lockthreads[i].lockcount = 0;
00945 lockthreads[i].lastlock = 0;
00946 lockthreads[i].lastunlock = 0;
00947 lockthreads[i].id = id;
00948 return(&lockthreads[i]);
00949 }
00950 }
00951 return(NULL);
00952 }
00953
00954
00955 static void rpt_mutex_spew(void)
00956 {
00957 struct by_lightning lock_ring_copy[32];
00958 int lock_ring_index_copy;
00959 int i,j;
00960 long long diff;
00961 char a[100];
00962 struct timeval lasttv;
00963
00964 ast_mutex_lock(&locklock);
00965 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00966 lock_ring_index_copy = lock_ring_index;
00967 ast_mutex_unlock(&locklock);
00968
00969 lasttv.tv_sec = lasttv.tv_usec = 0;
00970 for(i = 0 ; i < 32 ; i++)
00971 {
00972 j = (i + lock_ring_index_copy) % 32;
00973 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00974 localtime(&lock_ring_copy[j].tv.tv_sec));
00975 diff = 0;
00976 if(lasttv.tv_sec)
00977 {
00978 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00979 * 1000000;
00980 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00981 }
00982 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00983 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00984 if (!lock_ring_copy[j].tv.tv_sec) continue;
00985 if (lock_ring_copy[j].line < 0)
00986 {
00987 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00988 i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00989 }
00990 else
00991 {
00992 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00993 i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00994 }
00995 }
00996 }
00997
00998
00999 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01000 {
01001 struct lockthread *t;
01002 pthread_t id;
01003
01004 id = pthread_self();
01005 ast_mutex_lock(&locklock);
01006 t = put_lockthread(id);
01007 if (!t)
01008 {
01009 ast_mutex_unlock(&locklock);
01010 return;
01011 }
01012 if (t->lockcount)
01013 {
01014 int lastline = t->lastlock;
01015 ast_mutex_unlock(&locklock);
01016 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01017 rpt_mutex_spew();
01018 return;
01019 }
01020 t->lastlock = line;
01021 t->lockcount = 1;
01022 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01023 lock_ring[lock_ring_index].rpt = myrpt;
01024 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01025 lock_ring[lock_ring_index++].line = line;
01026 if(lock_ring_index == 32)
01027 lock_ring_index = 0;
01028 ast_mutex_unlock(&locklock);
01029 ast_mutex_lock(lockp);
01030 }
01031
01032
01033 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01034 {
01035 struct lockthread *t;
01036 pthread_t id;
01037
01038 id = pthread_self();
01039 ast_mutex_lock(&locklock);
01040 t = put_lockthread(id);
01041 if (!t)
01042 {
01043 ast_mutex_unlock(&locklock);
01044 return;
01045 }
01046 if (!t->lockcount)
01047 {
01048 int lastline = t->lastunlock;
01049 ast_mutex_unlock(&locklock);
01050 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01051 rpt_mutex_spew();
01052 return;
01053 }
01054 t->lastunlock = line;
01055 t->lockcount = 0;
01056 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01057 lock_ring[lock_ring_index].rpt = myrpt;
01058 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01059 lock_ring[lock_ring_index++].line = -line;
01060 if(lock_ring_index == 32)
01061 lock_ring_index = 0;
01062 ast_mutex_unlock(&locklock);
01063 ast_mutex_unlock(lockp);
01064 }
01065
01066 #else
01067
01068 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01069 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01070
01071 #endif
01072
01073
01074
01075
01076
01077 static int multimode_capable(struct rpt *myrpt)
01078 {
01079 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01080 return 1;
01081 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01082 return 1;
01083 return 0;
01084 }
01085
01086 static void voxinit_rpt(struct rpt *myrpt,char enable)
01087 {
01088
01089 myrpt->vox.speech_energy = 0.0;
01090 myrpt->vox.noise_energy = 0.0;
01091 myrpt->vox.enacount = 0;
01092 myrpt->vox.voxena = 0;
01093 if (!enable) myrpt->vox.voxena = -1;
01094 myrpt->vox.lastvox = 0;
01095 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01096 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01097 myrpt->wasvox = 0;
01098 myrpt->voxtotimer = 0;
01099 myrpt->voxtostate = 0;
01100 }
01101
01102 static void voxinit_link(struct rpt_link *mylink,char enable)
01103 {
01104
01105 mylink->vox.speech_energy = 0.0;
01106 mylink->vox.noise_energy = 0.0;
01107 mylink->vox.enacount = 0;
01108 mylink->vox.voxena = 0;
01109 if (!enable) mylink->vox.voxena = -1;
01110 mylink->vox.lastvox = 0;
01111 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01112 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01113 mylink->wasvox = 0;
01114 mylink->voxtotimer = 0;
01115 mylink->voxtostate = 0;
01116 }
01117
01118 static int dovox(struct vox *v,short *buf,int bs)
01119 {
01120
01121 int i;
01122 float esquare = 0.0;
01123 float energy = 0.0;
01124 float threshold = 0.0;
01125
01126 if (v->voxena < 0) return(v->lastvox);
01127 for(i = 0; i < bs; i++)
01128 {
01129 esquare += (float) buf[i] * (float) buf[i];
01130 }
01131 energy = sqrt(esquare);
01132
01133 if (energy >= v->speech_energy)
01134 v->speech_energy += (energy - v->speech_energy) / 4;
01135 else
01136 v->speech_energy += (energy - v->speech_energy) / 64;
01137
01138 if (energy >= v->noise_energy)
01139 v->noise_energy += (energy - v->noise_energy) / 64;
01140 else
01141 v->noise_energy += (energy - v->noise_energy) / 4;
01142
01143 if (v->voxena) threshold = v->speech_energy / 8;
01144 else
01145 {
01146 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01147 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01148 }
01149 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01150 if (energy > threshold)
01151 {
01152 if (v->voxena) v->noise_energy *= 0.75;
01153 v->voxena = 1;
01154 } else v->voxena = 0;
01155 if (v->lastvox != v->voxena)
01156 {
01157 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01158 {
01159 v->lastvox = v->voxena;
01160 v->enacount = 0;
01161 }
01162 } else v->enacount = 0;
01163 return(v->lastvox);
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static int rpt_do_debug(int fd, int argc, char *argv[]);
01175 static int rpt_do_dump(int fd, int argc, char *argv[]);
01176 static int rpt_do_stats(int fd, int argc, char *argv[]);
01177 static int rpt_do_lstats(int fd, int argc, char *argv[]);
01178 static int rpt_do_nodes(int fd, int argc, char *argv[]);
01179 static int rpt_do_local_nodes(int fd, int argc, char *argv[]);
01180 static int rpt_do_reload(int fd, int argc, char *argv[]);
01181 static int rpt_do_restart(int fd, int argc, char *argv[]);
01182 static int rpt_do_fun(int fd, int argc, char *argv[]);
01183 static int rpt_do_fun1(int fd, int argc, char *argv[]);
01184 static int rpt_do_cmd(int fd, int argc, char *argv[]);
01185
01186 static char debug_usage[] =
01187 "Usage: rpt debug level {0-7}\n"
01188 " Enables debug messages in app_rpt\n";
01189
01190 static char dump_usage[] =
01191 "Usage: rpt dump <nodename>\n"
01192 " Dumps struct debug info to log\n";
01193
01194 static char dump_stats[] =
01195 "Usage: rpt stats <nodename>\n"
01196 " Dumps node statistics to console\n";
01197
01198 static char dump_lstats[] =
01199 "Usage: rpt lstats <nodename>\n"
01200 " Dumps link statistics to console\n";
01201
01202 static char dump_nodes[] =
01203 "Usage: rpt nodes <nodename>\n"
01204 " Dumps a list of directly and indirectly connected nodes to the console\n";
01205
01206 static char usage_local_nodes[] =
01207 "Usage: rpt localnodes\n"
01208 " Dumps a list of the locally configured node numbers to the console.\n";
01209
01210 static char reload_usage[] =
01211 "Usage: rpt reload\n"
01212 " Reloads app_rpt running config parameters\n";
01213
01214 static char restart_usage[] =
01215 "Usage: rpt restart\n"
01216 " Restarts app_rpt\n";
01217
01218 static char fun_usage[] =
01219 "Usage: rpt fun <nodename> <command>\n"
01220 " Send a DTMF function to a node\n";
01221
01222 static char cmd_usage[] =
01223 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01224 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01225
01226 #ifndef NEW_ASTERISK
01227
01228 static struct ast_cli_entry cli_debug =
01229 { { "rpt", "debug", "level" }, rpt_do_debug,
01230 "Enable app_rpt debugging", debug_usage };
01231
01232 static struct ast_cli_entry cli_dump =
01233 { { "rpt", "dump" }, rpt_do_dump,
01234 "Dump app_rpt structs for debugging", dump_usage };
01235
01236 static struct ast_cli_entry cli_stats =
01237 { { "rpt", "stats" }, rpt_do_stats,
01238 "Dump node statistics", dump_stats };
01239
01240 static struct ast_cli_entry cli_nodes =
01241 { { "rpt", "nodes" }, rpt_do_nodes,
01242 "Dump node list", dump_nodes };
01243
01244 static struct ast_cli_entry cli_local_nodes =
01245 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01246 "Dump list of local node numbers", usage_local_nodes };
01247
01248 static struct ast_cli_entry cli_lstats =
01249 { { "rpt", "lstats" }, rpt_do_lstats,
01250 "Dump link statistics", dump_lstats };
01251
01252 static struct ast_cli_entry cli_reload =
01253 { { "rpt", "reload" }, rpt_do_reload,
01254 "Reload app_rpt config", reload_usage };
01255
01256 static struct ast_cli_entry cli_restart =
01257 { { "rpt", "restart" }, rpt_do_restart,
01258 "Restart app_rpt", restart_usage };
01259
01260 static struct ast_cli_entry cli_fun =
01261 { { "rpt", "fun" }, rpt_do_fun,
01262 "Execute a DTMF function", fun_usage };
01263
01264 static struct ast_cli_entry cli_fun1 =
01265 { { "rpt", "fun1" }, rpt_do_fun1,
01266 "Execute a DTMF function", fun_usage };
01267
01268 static struct ast_cli_entry cli_cmd =
01269 { { "rpt", "cmd" }, rpt_do_cmd,
01270 "Execute a DTMF function", cmd_usage };
01271
01272 #endif
01273
01274
01275
01276
01277
01278
01279 static struct telem_defaults tele_defs[] = {
01280 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01281 {"ct2","|t(660,880,150,3072)"},
01282 {"ct3","|t(440,0,150,3072)"},
01283 {"ct4","|t(550,0,150,3072)"},
01284 {"ct5","|t(660,0,150,3072)"},
01285 {"ct6","|t(880,0,150,3072)"},
01286 {"ct7","|t(660,440,150,3072)"},
01287 {"ct8","|t(700,1100,150,3072)"},
01288 {"remotemon","|t(1600,0,75,2048)"},
01289 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01290 {"cmdmode","|t(900,904,200,2048)"},
01291 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01292 } ;
01293
01294
01295
01296
01297
01298 static int setrbi(struct rpt *myrpt);
01299 static int set_ft897(struct rpt *myrpt);
01300 static int set_ic706(struct rpt *myrpt);
01301 static int setkenwood(struct rpt *myrpt);
01302 static int set_tm271(struct rpt *myrpt);
01303 static int setrbi_check(struct rpt *myrpt);
01304
01305
01306
01307
01308
01309
01310
01311 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01312 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01319
01320
01321
01322
01323 static struct function_table_tag function_table[] = {
01324 {"cop", function_cop},
01325 {"autopatchup", function_autopatchup},
01326 {"autopatchdn", function_autopatchdn},
01327 {"ilink", function_ilink},
01328 {"status", function_status},
01329 {"remote", function_remote},
01330 {"macro", function_macro},
01331 {"playback", function_playback}
01332 } ;
01333
01334 static long diskavail(struct rpt *myrpt)
01335 {
01336 struct statfs statfsbuf;
01337
01338 if (!myrpt->p.archivedir) return(0);
01339 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01340 {
01341 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01342 myrpt->p.archivedir,myrpt->name);
01343 return(-1);
01344 }
01345 return(statfsbuf.f_bavail);
01346 }
01347
01348 static void flush_telem(struct rpt *myrpt)
01349 {
01350 struct rpt_tele *telem;
01351 if(debug > 2)
01352 ast_log(LOG_NOTICE, "flush_telem()!!");
01353 rpt_mutex_lock(&myrpt->lock);
01354 telem = myrpt->tele.next;
01355 while(telem != &myrpt->tele)
01356 {
01357 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01358 telem = telem->next;
01359 }
01360 rpt_mutex_unlock(&myrpt->lock);
01361 }
01362
01363
01364
01365 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01366 {
01367 int res=0;
01368
01369
01370 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01371 res = 0;
01372 } else {
01373 res = -1;
01374 }
01375 return res;
01376 }
01377
01378
01379 static int linkcount(struct rpt *myrpt)
01380 {
01381 struct rpt_link *l;
01382 char *reverse_patch_state;
01383 int numoflinks;
01384
01385 reverse_patch_state = "DOWN";
01386 numoflinks = 0;
01387 l = myrpt->links.next;
01388 while(l && (l != &myrpt->links)){
01389 if(numoflinks >= MAX_STAT_LINKS){
01390 ast_log(LOG_WARNING,
01391 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01392 break;
01393 }
01394
01395
01396
01397
01398
01399 numoflinks++;
01400
01401 l = l->next;
01402 }
01403 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01404 return numoflinks;
01405 }
01406
01407
01408
01409
01410
01411
01412 static int retreive_memory(struct rpt *myrpt, char *memory)
01413 {
01414 char tmp[30], *s, *s1, *val;
01415
01416 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01417
01418 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01419 if (!val){
01420 return -1;
01421 }
01422 strncpy(tmp,val,sizeof(tmp) - 1);
01423 tmp[sizeof(tmp)-1] = 0;
01424
01425 s = strchr(tmp,',');
01426 if (!s)
01427 return 1;
01428 *s++ = 0;
01429 s1 = strchr(s,',');
01430 if (!s1)
01431 return 1;
01432 *s1++ = 0;
01433 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01434 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01435 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01436 myrpt->remmode = REM_MODE_FM;
01437 myrpt->offset = REM_SIMPLEX;
01438 myrpt->powerlevel = REM_MEDPWR;
01439 myrpt->txplon = myrpt->rxplon = 0;
01440 while(*s1){
01441 switch(*s1++){
01442 case 'A':
01443 case 'a':
01444 strcpy(myrpt->rxpl, "100.0");
01445 strcpy(myrpt->txpl, "100.0");
01446 myrpt->remmode = REM_MODE_AM;
01447 break;
01448 case 'B':
01449 case 'b':
01450 strcpy(myrpt->rxpl, "100.0");
01451 strcpy(myrpt->txpl, "100.0");
01452 myrpt->remmode = REM_MODE_LSB;
01453 break;
01454 case 'F':
01455 myrpt->remmode = REM_MODE_FM;
01456 break;
01457 case 'L':
01458 case 'l':
01459 myrpt->powerlevel = REM_LOWPWR;
01460 break;
01461 case 'H':
01462 case 'h':
01463 myrpt->powerlevel = REM_HIPWR;
01464 break;
01465
01466 case 'M':
01467 case 'm':
01468 myrpt->powerlevel = REM_MEDPWR;
01469 break;
01470
01471 case '-':
01472 myrpt->offset = REM_MINUS;
01473 break;
01474
01475 case '+':
01476 myrpt->offset = REM_PLUS;
01477 break;
01478
01479 case 'S':
01480 case 's':
01481 myrpt->offset = REM_SIMPLEX;
01482 break;
01483
01484 case 'T':
01485 case 't':
01486 myrpt->txplon = 1;
01487 break;
01488
01489 case 'R':
01490 case 'r':
01491 myrpt->rxplon = 1;
01492 break;
01493
01494 case 'U':
01495 case 'u':
01496 strcpy(myrpt->rxpl, "100.0");
01497 strcpy(myrpt->txpl, "100.0");
01498 myrpt->remmode = REM_MODE_USB;
01499 break;
01500 default:
01501 return 1;
01502 }
01503 }
01504 return 0;
01505 }
01506
01507
01508
01509 static void birdbath(struct rpt *myrpt)
01510 {
01511 struct rpt_tele *telem;
01512 if(debug > 2)
01513 ast_log(LOG_NOTICE, "birdbath!!");
01514 rpt_mutex_lock(&myrpt->lock);
01515 telem = myrpt->tele.next;
01516 while(telem != &myrpt->tele)
01517 {
01518 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01519 telem = telem->next;
01520 }
01521 rpt_mutex_unlock(&myrpt->lock);
01522 }
01523
01524 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01525 {
01526 struct rpt_link *l;
01527
01528 l = myrpt->links.next;
01529
01530 while(l != &myrpt->links)
01531 {
01532 if (!l->phonemode)
01533 {
01534 l = l->next;
01535 continue;
01536 }
01537
01538 if (mylink && (l == mylink))
01539 {
01540 l = l->next;
01541 continue;
01542 }
01543 #ifdef NEW_ASTERISK
01544 if (l->chan) ast_senddigit(l->chan,c,0);
01545 #else
01546 if (l->chan) ast_senddigit(l->chan,c);
01547 #endif
01548 l = l->next;
01549 }
01550 return;
01551 }
01552
01553
01554 static void donodelog(struct rpt *myrpt,char *str)
01555 {
01556 struct nodelog *nodep;
01557 char datestr[100];
01558
01559 if (!myrpt->p.archivedir) return;
01560 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01561 if (nodep == NULL)
01562 {
01563 ast_log(LOG_ERROR,"Cannot get memory for node log");
01564 return;
01565 }
01566 time(&nodep->timestamp);
01567 strncpy(nodep->archivedir,myrpt->p.archivedir,
01568 sizeof(nodep->archivedir) - 1);
01569 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01570 localtime(&nodep->timestamp));
01571 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01572 myrpt->name,datestr,str);
01573 ast_mutex_lock(&nodeloglock);
01574 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01575 ast_mutex_unlock(&nodeloglock);
01576 }
01577
01578
01579 static void do_dtmf_local(struct rpt *myrpt, char c)
01580 {
01581 int i;
01582 char digit;
01583 static const char* dtmf_tones[] = {
01584 "!941+1336/200,!0/200",
01585 "!697+1209/200,!0/200",
01586 "!697+1336/200,!0/200",
01587 "!697+1477/200,!0/200",
01588 "!770+1209/200,!0/200",
01589 "!770+1336/200,!0/200",
01590 "!770+1477/200,!0/200",
01591 "!852+1209/200,!0/200",
01592 "!852+1336/200,!0/200",
01593 "!852+1477/200,!0/200",
01594 "!697+1633/200,!0/200",
01595 "!770+1633/200,!0/200",
01596 "!852+1633/200,!0/200",
01597 "!941+1633/200,!0/200",
01598 "!941+1209/200,!0/200",
01599 "!941+1477/200,!0/200" };
01600
01601
01602 if (c)
01603 {
01604 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01605 if (!myrpt->dtmf_local_timer)
01606 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01607 }
01608
01609 if (myrpt->dtmf_local_timer == 1)
01610 {
01611 if(debug > 6)
01612 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01613
01614
01615 if (myrpt->dtmf_local_str[0])
01616 {
01617 digit = myrpt->dtmf_local_str[0];
01618 myrpt->dtmf_local_str[0] = 0;
01619 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01620 {
01621 myrpt->dtmf_local_str[i - 1] =
01622 myrpt->dtmf_local_str[i];
01623 }
01624 myrpt->dtmf_local_str[i - 1] = 0;
01625 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01626 rpt_mutex_unlock(&myrpt->lock);
01627 if (digit >= '0' && digit <='9')
01628 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01629 else if (digit >= 'A' && digit <= 'D')
01630 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01631 else if (digit == '*')
01632 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01633 else if (digit == '#')
01634 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01635 else {
01636
01637 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01638 }
01639 rpt_mutex_lock(&myrpt->lock);
01640 }
01641 else
01642 {
01643 myrpt->dtmf_local_timer = 0;
01644 }
01645 }
01646 }
01647
01648 static int setdtr(int fd, int enable)
01649 {
01650 struct termios mode;
01651
01652 if (fd < 0) return -1;
01653 if (tcgetattr(fd, &mode)) {
01654 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01655 return -1;
01656 }
01657 if (enable)
01658 {
01659 cfsetspeed(&mode, B9600);
01660 }
01661 else
01662 {
01663 cfsetspeed(&mode, B0);
01664 usleep(100000);
01665 }
01666 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01667 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01668 return -1;
01669 }
01670 if (enable) usleep(100000);
01671 return 0;
01672 }
01673
01674 static int openserial(struct rpt *myrpt,char *fname)
01675 {
01676 struct termios mode;
01677 int fd;
01678
01679 fd = open(fname,O_RDWR);
01680 if (fd == -1)
01681 {
01682 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01683 return -1;
01684 }
01685 memset(&mode, 0, sizeof(mode));
01686 if (tcgetattr(fd, &mode)) {
01687 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01688 return -1;
01689 }
01690 #ifndef SOLARIS
01691 cfmakeraw(&mode);
01692 #else
01693 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01694 |INLCR|IGNCR|ICRNL|IXON);
01695 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01696 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01697 mode.c_cflag |= CS8;
01698 mode.c_cc[VTIME] = 3;
01699 mode.c_cc[VMIN] = 1;
01700 #endif
01701
01702 cfsetispeed(&mode, B9600);
01703 cfsetospeed(&mode, B9600);
01704 if (tcsetattr(fd, TCSANOW, &mode))
01705 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01706 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01707 usleep(100000);
01708 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01709 return(fd);
01710 }
01711
01712 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01713 {
01714 if (!fromnode)
01715 {
01716 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01717 unit,myrpt->name);
01718 }
01719 else
01720 {
01721 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01722 unit,fromnode,myrpt->name);
01723 }
01724 }
01725
01726 #ifdef _MDC_DECODE_H_
01727
01728 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01729 {
01730 struct rpt_link *l;
01731 struct ast_frame wf;
01732 char str[200];
01733
01734
01735 sprintf(str,"I %s %04X",myrpt->name,unit);
01736
01737 wf.frametype = AST_FRAME_TEXT;
01738 wf.subclass = 0;
01739 wf.offset = 0;
01740 wf.mallocd = 0;
01741 wf.datalen = strlen(str) + 1;
01742 wf.samples = 0;
01743
01744
01745 l = myrpt->links.next;
01746
01747 while(l != &myrpt->links)
01748 {
01749 if (l->name[0] == '0')
01750 {
01751 l = l->next;
01752 continue;
01753 }
01754 wf.data = str;
01755 if (l->chan) ast_write(l->chan,&wf);
01756 l = l->next;
01757 }
01758 return;
01759 }
01760
01761 #endif
01762
01763 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01764 {
01765 time_t now;
01766 int gotone;
01767
01768 time(&now);
01769 gotone = 0;
01770
01771 if ((now - xlat->lastone) > MAXXLATTIME)
01772 {
01773 xlat->funcindex = xlat->endindex = 0;
01774 }
01775 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01776 {
01777 time(&xlat->lastone);
01778 gotone = 1;
01779 if (!xlat->funccharseq[xlat->funcindex])
01780 {
01781 xlat->funcindex = xlat->endindex = 0;
01782 return(myrpt->p.funcchar);
01783 }
01784 } else xlat->funcindex = 0;
01785 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01786 {
01787 time(&xlat->lastone);
01788 gotone = 1;
01789 if (!xlat->endcharseq[xlat->endindex])
01790 {
01791 xlat->funcindex = xlat->endindex = 0;
01792 return(myrpt->p.endchar);
01793 }
01794 } else xlat->endindex = 0;
01795
01796 if (gotone) return(0);
01797
01798 if (!xlat->passchars[0]) return(c);
01799
01800 if (strchr(xlat->passchars,c)) return(c);
01801 return(0);
01802 }
01803
01804
01805
01806
01807
01808 static char *eatwhite(char *s)
01809 {
01810 while((*s == ' ') || (*s == 0x09)){
01811 if(!*s)
01812 break;
01813 s++;
01814 }
01815 return s;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static int finddelim(char *str, char *strp[], int limit)
01829 {
01830 int i,l,inquo;
01831
01832 inquo = 0;
01833 i = 0;
01834 strp[i++] = str;
01835 if (!*str)
01836 {
01837 strp[0] = 0;
01838 return(0);
01839 }
01840 for(l = 0; *str && (l < limit) ; str++)
01841 {
01842 if (*str == QUOTECHR)
01843 {
01844 if (inquo)
01845 {
01846 *str = 0;
01847 inquo = 0;
01848 }
01849 else
01850 {
01851 strp[i - 1] = str + 1;
01852 inquo = 1;
01853 }
01854 }
01855 if ((*str == DELIMCHR) && (!inquo))
01856 {
01857 *str = 0;
01858 l++;
01859 strp[i++] = str + 1;
01860 }
01861 }
01862 strp[i] = 0;
01863 return(i);
01864
01865 }
01866
01867
01868
01869 static int send_usb_txt(struct rpt *myrpt, char *txt)
01870 {
01871 struct ast_frame wf;
01872
01873 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01874 wf.frametype = AST_FRAME_TEXT;
01875 wf.subclass = 0;
01876 wf.offset = 0;
01877 wf.mallocd = 0;
01878 wf.datalen = strlen(txt) + 1;
01879 wf.data.ptr = txt;
01880 wf.samples = 0;
01881 ast_write(myrpt->txchannel,&wf);
01882 return 0;
01883 }
01884
01885 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01886 {
01887 struct rpt_link *l;
01888 char mode;
01889 int i,spos;
01890
01891 buf[0] = 0;
01892 if (myrpt->remote) return;
01893
01894 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01895 {
01896
01897 if (l->name[0] == '0') continue;
01898
01899 if (l == mylink) continue;
01900 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01901
01902 mode = 'T';
01903 if (!l->mode) mode = 'R';
01904 if (!l->thisconnected) mode = 'C';
01905 spos = strlen(buf);
01906 if (spos)
01907 {
01908 strcat(buf,",");
01909 spos++;
01910 }
01911
01912 if (l->linklist[0])
01913 {
01914 snprintf(buf + spos,MAXLINKLIST - spos,
01915 "%c%s,%s",mode,l->name,l->linklist);
01916 }
01917 else
01918 {
01919 snprintf(buf + spos,MAXLINKLIST - spos,
01920 "%c%s",mode,l->name);
01921 }
01922
01923 if (mode == 'T') continue;
01924
01925 for(i = spos; buf[i]; i++)
01926 {
01927 if (buf[i] == 'T') buf[i] = mode;
01928 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01929 }
01930 }
01931 return;
01932 }
01933
01934
01935 static void __kickshort(struct rpt *myrpt)
01936 {
01937 struct rpt_link *l;
01938
01939 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01940 {
01941
01942 if (l->name[0] == '0') continue;
01943 l->linklisttimer = LINKLISTSHORTTIME;
01944 }
01945 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01946 return;
01947 }
01948
01949 static void statpost(struct rpt *myrpt,char *pairs)
01950 {
01951 char *str,*astr;
01952 char *astrs[100];
01953 int n,pid;
01954 time_t now;
01955 unsigned int seq;
01956
01957 if (!myrpt->p.statpost_url) return;
01958 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01959 astr = ast_strdup(myrpt->p.statpost_program);
01960 if ((!str) || (!astr)) return;
01961 n = finddelim(astr,astrs,100);
01962 if (n < 1) return;
01963 ast_mutex_lock(&myrpt->statpost_lock);
01964 seq = ++myrpt->statpost_seqno;
01965 ast_mutex_unlock(&myrpt->statpost_lock);
01966 astrs[n++] = str;
01967 astrs[n] = NULL;
01968 time(&now);
01969 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01970 myrpt->name,(unsigned int) now,seq);
01971 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01972 if (!(pid = ast_safe_fork(0)))
01973 {
01974 execv(astrs[0],astrs);
01975 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01976 perror("asterisk");
01977 exit(0);
01978 }
01979 ast_free(astr);
01980 ast_free(str);
01981 return;
01982 }
01983
01984 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01985 {
01986
01987 char *val;
01988 int longestnode,j;
01989 struct stat mystat;
01990 static time_t last = 0;
01991 static struct ast_config *ourcfg = NULL;
01992 struct ast_variable *vp;
01993
01994
01995 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01996 if (val) return(val);
01997 ast_mutex_lock(&nodelookuplock);
01998
01999 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02000 {
02001 if (ourcfg) ast_config_destroy(ourcfg);
02002 ourcfg = NULL;
02003 ast_mutex_unlock(&nodelookuplock);
02004 return(NULL);
02005 }
02006
02007 if (mystat.st_mtime > last)
02008 {
02009 if (ourcfg) ast_config_destroy(ourcfg);
02010 #ifdef NEW_ASTERISK
02011 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02012 #else
02013 ourcfg = ast_config_load(myrpt->p.extnodefile);
02014 #endif
02015
02016 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02017 {
02018 ast_mutex_unlock(&nodelookuplock);
02019 return(NULL);
02020 }
02021
02022 last = mystat.st_mtime;
02023
02024
02025 longestnode = 0;
02026 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02027 while(vp){
02028 j = strlen(vp->name);
02029 if (j > longestnode)
02030 longestnode = j;
02031 vp = vp->next;
02032 }
02033
02034 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02035 while(vp){
02036 j = strlen(vp->name);
02037 if (j > longestnode)
02038 longestnode = j;
02039 vp = vp->next;
02040 }
02041
02042 myrpt->longestnode = longestnode;
02043 }
02044 val = NULL;
02045 if (ourcfg)
02046 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02047 ast_mutex_unlock(&nodelookuplock);
02048 return(val);
02049 }
02050
02051
02052
02053
02054
02055
02056 static int matchkeyword(char *string, char **param, char *keywords[])
02057 {
02058 int i,ls;
02059 for( i = 0 ; keywords[i] ; i++){
02060 ls = strlen(keywords[i]);
02061 if(!ls){
02062 *param = NULL;
02063 return 0;
02064 }
02065 if(!strncmp(string, keywords[i], ls)){
02066 if(param)
02067 *param = string + ls;
02068 return i + 1;
02069 }
02070 }
02071 *param = NULL;
02072 return 0;
02073 }
02074
02075
02076
02077
02078
02079
02080 static char *skipchars(char *string, char *charlist)
02081 {
02082 int i;
02083 while(*string){
02084 for(i = 0; charlist[i] ; i++){
02085 if(*string == charlist[i]){
02086 string++;
02087 break;
02088 }
02089 }
02090 if(!charlist[i])
02091 return string;
02092 }
02093 return string;
02094 }
02095
02096
02097
02098 static int myatoi(char *str)
02099 {
02100 int ret;
02101
02102 if (str == NULL) return -1;
02103
02104 if (sscanf(str, "%30i", &ret) != 1) {
02105 return -1;
02106 }
02107
02108 return ret;
02109 }
02110
02111 static int mycompar(const void *a, const void *b)
02112 {
02113 char **x = (char **) a;
02114 char **y = (char **) b;
02115 int xoff,yoff;
02116
02117 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02118 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02119 return(strcmp((*x) + xoff,(*y) + yoff));
02120 }
02121
02122 static int topcompar(const void *a, const void *b)
02123 {
02124 struct rpt_topkey *x = (struct rpt_topkey *) a;
02125 struct rpt_topkey *y = (struct rpt_topkey *) b;
02126
02127 return(x->timesince - y->timesince);
02128 }
02129
02130 #ifdef __RPT_NOTCH
02131
02132
02133 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02134 {
02135 int i,j;
02136 struct rptfilter *f;
02137
02138 for(i = 0; i < len; i++)
02139 {
02140 for(j = 0; j < MAXFILTERS; j++)
02141 {
02142 f = &myrpt->filters[j];
02143 if (!*f->desc) continue;
02144 f->x0 = f->x1; f->x1 = f->x2;
02145 f->x2 = ((float)buf[i]) / f->gain;
02146 f->y0 = f->y1; f->y1 = f->y2;
02147 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02148 + (f->const1 * f->y0) + (f->const2 * f->y1);
02149 buf[i] = (short)f->y2;
02150 }
02151 }
02152 }
02153
02154 #endif
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173 #ifdef NEW_ASTERISK
02174 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02175 {
02176 struct timeval when;
02177
02178 when.tv_sec = *t;
02179 when.tv_usec = 0;
02180 ast_localtime(&when, lt, NULL);
02181 }
02182
02183 #else
02184 static void rpt_localtime( time_t * t, struct tm *lt)
02185 {
02186 #ifdef OLD_ASTERISK
02187 localtime_r(t, lt);
02188 #else
02189 ast_localtime(t, lt, NULL);
02190 #endif
02191 }
02192 #endif
02193
02194
02195
02196
02197 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02198 {
02199 char *var;
02200 int ret;
02201 char include_zero = 0;
02202
02203 if(min < 0){
02204 min = -min;
02205 include_zero = 1;
02206 }
02207
02208 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02209 if(var){
02210 ret = myatoi(var);
02211 if(include_zero && !ret)
02212 return 0;
02213 if(ret < min)
02214 ret = min;
02215 if(ret > max)
02216 ret = max;
02217 }
02218 else
02219 ret = defl;
02220 return ret;
02221 }
02222
02223
02224 static void load_rpt_vars(int n,int init)
02225 {
02226 char *this,*val;
02227 int i,j,longestnode;
02228 struct ast_variable *vp;
02229 struct ast_config *cfg;
02230 char *strs[100];
02231 char s1[256];
02232 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02233 "ufena","ufdis","atena","atdis",NULL};
02234
02235 if (option_verbose > 2)
02236 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02237 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02238 ast_mutex_lock(&rpt_vars[n].lock);
02239 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02240 #ifdef NEW_ASTERISK
02241 cfg = ast_config_load("rpt.conf",config_flags);
02242 #else
02243 cfg = ast_config_load("rpt.conf");
02244 #endif
02245 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02246 ast_mutex_unlock(&rpt_vars[n].lock);
02247 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02248 pthread_exit(NULL);
02249 }
02250 rpt_vars[n].cfg = cfg;
02251 this = rpt_vars[n].name;
02252 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02253 if (init)
02254 {
02255 char *cp;
02256 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02257
02258 cp = (char *) &rpt_vars[n].p;
02259 memset(cp + sizeof(rpt_vars[n].p),0,
02260 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02261 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02262 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02263 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02264 rpt_vars[n].tailmessagen = 0;
02265 }
02266 #ifdef __RPT_NOTCH
02267
02268 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02269 #endif
02270 val = (char *) ast_variable_retrieve(cfg,this,"context");
02271 if (val) rpt_vars[n].p.ourcontext = val;
02272 else rpt_vars[n].p.ourcontext = this;
02273 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02274 if (val) rpt_vars[n].p.ourcallerid = val;
02275 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02276 if (val) rpt_vars[n].p.acctcode = val;
02277 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02278 if (val) rpt_vars[n].p.ident = val;
02279 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02280 if (val) rpt_vars[n].p.hangtime = atoi(val);
02281 else rpt_vars[n].p.hangtime = HANGTIME;
02282 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02283 if (val) rpt_vars[n].p.althangtime = atoi(val);
02284 else rpt_vars[n].p.althangtime = HANGTIME;
02285 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02286 if (val) rpt_vars[n].p.totime = atoi(val);
02287 else rpt_vars[n].p.totime = TOTIME;
02288 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02289 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02290 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02291 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02292 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02293 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02294 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02295 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02296 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02297 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02298 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02299 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02300 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02301 if (val) rpt_vars[n].p.statpost_program = val;
02302 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02303 rpt_vars[n].p.statpost_url =
02304 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02305 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02306 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02307 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02308 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02309 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02310 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02311 if (val) rpt_vars[n].p.tonezone = val;
02312 rpt_vars[n].p.tailmessages[0] = 0;
02313 rpt_vars[n].p.tailmessagemax = 0;
02314 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02315 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02316 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02317 if (!val) val = MEMORY;
02318 rpt_vars[n].p.memory = val;
02319 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02320 if (!val) val = MACRO;
02321 rpt_vars[n].p.macro = val;
02322 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02323 if (!val) val = TONEMACRO;
02324 rpt_vars[n].p.tonemacro = val;
02325 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02326 if (val) rpt_vars[n].p.startupmacro = val;
02327 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02328
02329
02330
02331 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02332 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02333 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02334 rpt_vars[n].p.ioport = val;
02335 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02336 if (!val)
02337 {
02338 val = FUNCTIONS;
02339 rpt_vars[n].p.simple = 1;
02340 }
02341 rpt_vars[n].p.functions = val;
02342 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02343 if (val) rpt_vars[n].p.link_functions = val;
02344 else
02345 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02346 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02347 if (val) rpt_vars[n].p.phone_functions = val;
02348 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02349 if (val) rpt_vars[n].p.dphone_functions = val;
02350 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02351 if (val) rpt_vars[n].p.alt_functions = val;
02352 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02353 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02354 rpt_vars[n].p.funcchar = *val;
02355 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02356 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02357 rpt_vars[n].p.endchar = *val;
02358 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02359 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02360 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02361 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02362 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02363 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02364 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02365 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02366 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02367 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02368 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02369 if (!val) val = NODES;
02370 rpt_vars[n].p.nodes = val;
02371 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02372 if (!val) val = EXTNODES;
02373 rpt_vars[n].p.extnodes = val;
02374 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02375 if (!val) val = EXTNODEFILE;
02376 rpt_vars[n].p.extnodefile = val;
02377 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02378 if (val) rpt_vars[n].p.archivedir = val;
02379 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02380 if (val) rpt_vars[n].p.authlevel = atoi(val);
02381 else rpt_vars[n].p.authlevel = 0;
02382 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02383 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02384 else rpt_vars[n].p.parrotmode = 0;
02385 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02386 if (val) rpt_vars[n].p.parrottime = atoi(val);
02387 else rpt_vars[n].p.parrottime = PARROTTIME;
02388 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02389 rpt_vars[n].p.rptnode = val;
02390 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02391 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02392 else rpt_vars[n].p.remote_mars = 0;
02393 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02394 if (val) rpt_vars[n].p.monminblocks = atol(val);
02395 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02396 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02397 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02398 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02399 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02400 if (val) rpt_vars[n].p.civaddr = atoi(val);
02401 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02402 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02403 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02404 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02405 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02406 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02407 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02408 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02409 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02410 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02411 #ifdef __RPT_NOTCH
02412 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02413 if (val) {
02414 i = finddelim(val,strs,MAXFILTERS * 2);
02415 i &= ~1;
02416 if (i >= 2) for(j = 0; j < i; j += 2)
02417 {
02418 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02419 &rpt_vars[n].filters[j >> 1].gain,
02420 &rpt_vars[n].filters[j >> 1].const0,
02421 &rpt_vars[n].filters[j >> 1].const1,
02422 &rpt_vars[n].filters[j >> 1].const2);
02423 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02424 strs[j],strs[j + 1]);
02425 }
02426
02427 }
02428 #endif
02429 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02430 if (val) {
02431 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02432 i = finddelim(val,strs,3);
02433 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02434 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02435 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02436 }
02437 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02438 if (val) {
02439 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02440 i = finddelim(val,strs,3);
02441 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02442 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02443 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02444 }
02445
02446 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02447 rpt_vars[n].p.csstanzaname = val;
02448
02449
02450 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02451 rpt_vars[n].p.skedstanzaname = val;
02452
02453
02454 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02455 rpt_vars[n].p.txlimitsstanzaname = val;
02456
02457 longestnode = 0;
02458
02459 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02460
02461 while(vp){
02462 j = strlen(vp->name);
02463 if (j > longestnode)
02464 longestnode = j;
02465 vp = vp->next;
02466 }
02467
02468 rpt_vars[n].longestnode = longestnode;
02469
02470
02471
02472
02473 rpt_vars[n].longestfunc = 0;
02474 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02475 while(vp){
02476 j = strlen(vp->name);
02477 if (j > rpt_vars[n].longestfunc)
02478 rpt_vars[n].longestfunc = j;
02479 vp = vp->next;
02480 }
02481
02482
02483
02484 rpt_vars[n].link_longestfunc = 0;
02485 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02486 while(vp){
02487 j = strlen(vp->name);
02488 if (j > rpt_vars[n].link_longestfunc)
02489 rpt_vars[n].link_longestfunc = j;
02490 vp = vp->next;
02491 }
02492 rpt_vars[n].phone_longestfunc = 0;
02493 if (rpt_vars[n].p.phone_functions)
02494 {
02495 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02496 while(vp){
02497 j = strlen(vp->name);
02498 if (j > rpt_vars[n].phone_longestfunc)
02499 rpt_vars[n].phone_longestfunc = j;
02500 vp = vp->next;
02501 }
02502 }
02503 rpt_vars[n].dphone_longestfunc = 0;
02504 if (rpt_vars[n].p.dphone_functions)
02505 {
02506 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02507 while(vp){
02508 j = strlen(vp->name);
02509 if (j > rpt_vars[n].dphone_longestfunc)
02510 rpt_vars[n].dphone_longestfunc = j;
02511 vp = vp->next;
02512 }
02513 }
02514 rpt_vars[n].alt_longestfunc = 0;
02515 if (rpt_vars[n].p.alt_functions)
02516 {
02517 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02518 while(vp){
02519 j = strlen(vp->name);
02520 if (j > rpt_vars[n].alt_longestfunc)
02521 rpt_vars[n].alt_longestfunc = j;
02522 vp = vp->next;
02523 }
02524 }
02525 rpt_vars[n].macro_longest = 1;
02526 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02527 while(vp){
02528 j = strlen(vp->name);
02529 if (j > rpt_vars[n].macro_longest)
02530 rpt_vars[n].macro_longest = j;
02531 vp = vp->next;
02532 }
02533
02534
02535 if(rpt_vars[n].p.csstanzaname)
02536 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02537 else
02538 vp = NULL;
02539 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02540 int k,nukw,statenum;
02541 statenum=atoi(vp->name);
02542 strncpy(s1, vp->value, 255);
02543 s1[255] = 0;
02544 nukw = finddelim(s1,strs,32);
02545
02546 for (k = 0 ; k < nukw ; k++){
02547 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02548 if(!strcmp(strs[k],cs_keywords[j])){
02549 switch(j){
02550 case 0:
02551 rpt_vars[n].p.s[statenum].txdisable = 0;
02552 break;
02553 case 1:
02554 rpt_vars[n].p.s[statenum].txdisable = 1;
02555 break;
02556
02557 case 2:
02558 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02559 break;
02560
02561 case 3:
02562 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02563 break;
02564
02565 case 4:
02566 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02567 break;
02568
02569 case 5:
02570 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02571 break;
02572
02573 case 6:
02574 rpt_vars[n].p.s[statenum].totdisable = 0;
02575 break;
02576
02577 case 7:
02578 rpt_vars[n].p.s[statenum].totdisable = 1;
02579 break;
02580
02581 case 8:
02582 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02583 break;
02584
02585 case 9:
02586 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02587 break;
02588
02589 case 10:
02590 rpt_vars[n].p.s[statenum].userfundisable = 0;
02591 break;
02592
02593 case 11:
02594 rpt_vars[n].p.s[statenum].userfundisable = 1;
02595 break;
02596
02597 case 12:
02598 rpt_vars[n].p.s[statenum].alternatetail = 1;
02599 break;
02600
02601 case 13:
02602 rpt_vars[n].p.s[statenum].alternatetail = 0;
02603 break;
02604
02605 default:
02606 ast_log(LOG_WARNING,
02607 "Unhandled control state keyword %s", cs_keywords[i]);
02608 break;
02609 }
02610 }
02611 }
02612 }
02613 vp = vp->next;
02614 }
02615 ast_mutex_unlock(&rpt_vars[n].lock);
02616 }
02617
02618
02619
02620
02621
02622 static int rpt_do_debug(int fd, int argc, char *argv[])
02623 {
02624 int newlevel;
02625
02626 if (argc != 4)
02627 return RESULT_SHOWUSAGE;
02628 newlevel = myatoi(argv[3]);
02629 if((newlevel < 0) || (newlevel > 7))
02630 return RESULT_SHOWUSAGE;
02631 if(newlevel)
02632 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02633 else
02634 ast_cli(fd, "app_rpt Debugging disabled\n");
02635
02636 debug = newlevel;
02637 return RESULT_SUCCESS;
02638 }
02639
02640
02641
02642
02643
02644 static int rpt_do_dump(int fd, int argc, char *argv[])
02645 {
02646 int i;
02647
02648 if (argc != 3)
02649 return RESULT_SHOWUSAGE;
02650
02651 for(i = 0; i < nrpts; i++)
02652 {
02653 if (!strcmp(argv[2],rpt_vars[i].name))
02654 {
02655 rpt_vars[i].disgorgetime = time(NULL) + 10;
02656 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02657 return RESULT_SUCCESS;
02658 }
02659 }
02660 return RESULT_FAILURE;
02661 }
02662
02663
02664
02665
02666
02667 static int rpt_do_stats(int fd, int argc, char *argv[])
02668 {
02669 int i,j,numoflinks;
02670 int dailytxtime, dailykerchunks;
02671 time_t now;
02672 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02673 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02674 int uptime;
02675 long long totaltxtime;
02676 struct rpt_link *l;
02677 char *listoflinks[MAX_STAT_LINKS];
02678 char *lastdtmfcommand,*parrot_ena;
02679 char *tot_state, *ider_state, *patch_state;
02680 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02681 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02682 struct rpt *myrpt;
02683
02684 static char *not_applicable = "N/A";
02685
02686 if(argc != 3)
02687 return RESULT_SHOWUSAGE;
02688
02689 tot_state = ider_state =
02690 patch_state = reverse_patch_state =
02691 input_signal = not_applicable;
02692 called_number = lastdtmfcommand = NULL;
02693
02694 time(&now);
02695 for(i = 0; i < nrpts; i++)
02696 {
02697 if (!strcmp(argv[2],rpt_vars[i].name)){
02698
02699 myrpt = &rpt_vars[i];
02700 rpt_mutex_lock(&myrpt->lock);
02701 uptime = (int)(now - starttime);
02702 dailytxtime = myrpt->dailytxtime;
02703 totaltxtime = myrpt->totaltxtime;
02704 dailykeyups = myrpt->dailykeyups;
02705 totalkeyups = myrpt->totalkeyups;
02706 dailykerchunks = myrpt->dailykerchunks;
02707 totalkerchunks = myrpt->totalkerchunks;
02708 dailyexecdcommands = myrpt->dailyexecdcommands;
02709 totalexecdcommands = myrpt->totalexecdcommands;
02710 timeouts = myrpt->timeouts;
02711
02712
02713 reverse_patch_state = "DOWN";
02714 numoflinks = 0;
02715 l = myrpt->links.next;
02716 while(l && (l != &myrpt->links)){
02717 if(numoflinks >= MAX_STAT_LINKS){
02718 ast_log(LOG_NOTICE,
02719 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02720 break;
02721 }
02722 if (l->name[0] == '0'){
02723 reverse_patch_state = "UP";
02724 l = l->next;
02725 continue;
02726 }
02727 listoflinks[numoflinks] = ast_strdup(l->name);
02728 if(listoflinks[numoflinks] == NULL){
02729 break;
02730 }
02731 else{
02732 numoflinks++;
02733 }
02734 l = l->next;
02735 }
02736
02737 if(myrpt->keyed)
02738 input_signal = "YES";
02739 else
02740 input_signal = "NO";
02741
02742 if(myrpt->p.parrotmode)
02743 parrot_ena = "ENABLED";
02744 else
02745 parrot_ena = "DISABLED";
02746
02747 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02748 sys_ena = "DISABLED";
02749 else
02750 sys_ena = "ENABLED";
02751
02752 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02753 tot_ena = "DISABLED";
02754 else
02755 tot_ena = "ENABLED";
02756
02757 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02758 link_ena = "DISABLED";
02759 else
02760 link_ena = "ENABLED";
02761
02762 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02763 patch_ena = "DISABLED";
02764 else
02765 patch_ena = "ENABLED";
02766
02767 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02768 sch_ena = "DISABLED";
02769 else
02770 sch_ena = "ENABLED";
02771
02772 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02773 user_funs = "DISABLED";
02774 else
02775 user_funs = "ENABLED";
02776
02777 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02778 tail_type = "ALTERNATE";
02779 else
02780 tail_type = "STANDARD";
02781
02782 if(!myrpt->totimer)
02783 tot_state = "TIMED OUT!";
02784 else if(myrpt->totimer != myrpt->p.totime)
02785 tot_state = "ARMED";
02786 else
02787 tot_state = "RESET";
02788
02789 if(myrpt->tailid)
02790 ider_state = "QUEUED IN TAIL";
02791 else if(myrpt->mustid)
02792 ider_state = "QUEUED FOR CLEANUP";
02793 else
02794 ider_state = "CLEAN";
02795
02796 switch(myrpt->callmode){
02797 case 1:
02798 patch_state = "DIALING";
02799 break;
02800 case 2:
02801 patch_state = "CONNECTING";
02802 break;
02803 case 3:
02804 patch_state = "UP";
02805 break;
02806
02807 case 4:
02808 patch_state = "CALL FAILED";
02809 break;
02810
02811 default:
02812 patch_state = "DOWN";
02813 }
02814
02815 if(strlen(myrpt->exten)){
02816 called_number = ast_strdup(myrpt->exten);
02817 }
02818
02819 if(strlen(myrpt->lastdtmfcommand)){
02820 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02821 }
02822 rpt_mutex_unlock(&myrpt->lock);
02823
02824 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02825 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02826 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02827 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02828 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02829 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02830 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02831 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02832 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02833 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02834 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02835 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02836 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02837 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02838 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02839 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02840 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02841 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02842 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02843 hours = dailytxtime/3600000;
02844 dailytxtime %= 3600000;
02845 minutes = dailytxtime/60000;
02846 dailytxtime %= 60000;
02847 seconds = dailytxtime/1000;
02848 dailytxtime %= 1000;
02849
02850 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02851 hours, minutes, seconds, dailytxtime);
02852
02853 hours = (int) totaltxtime/3600000;
02854 totaltxtime %= 3600000;
02855 minutes = (int) totaltxtime/60000;
02856 totaltxtime %= 60000;
02857 seconds = (int) totaltxtime/1000;
02858 totaltxtime %= 1000;
02859
02860 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02861 hours, minutes, seconds, (int) totaltxtime);
02862
02863 hours = uptime/3600;
02864 uptime %= 3600;
02865 minutes = uptime/60;
02866 uptime %= 60;
02867
02868 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02869 hours, minutes, uptime);
02870
02871 ast_cli(fd, "Nodes currently connected to us..................: ");
02872 if(!numoflinks){
02873 ast_cli(fd,"<NONE>");
02874 }
02875 else{
02876 for(j = 0 ;j < numoflinks; j++){
02877 ast_cli(fd, "%s", listoflinks[j]);
02878 if(j % 4 == 3){
02879 ast_cli(fd, "\n");
02880 ast_cli(fd, " : ");
02881 }
02882 else{
02883 if((numoflinks - 1) - j > 0)
02884 ast_cli(fd, ", ");
02885 }
02886 }
02887 }
02888 ast_cli(fd,"\n");
02889
02890 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02891 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02892 ast_cli(fd, "Autopatch called number..........................: %s\n",
02893 (called_number && strlen(called_number)) ? called_number : not_applicable);
02894 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02895 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02896 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02897
02898 for(j = 0; j < numoflinks; j++){
02899 ast_free(listoflinks[j]);
02900 }
02901 if(called_number){
02902 ast_free(called_number);
02903 }
02904 if(lastdtmfcommand){
02905 ast_free(lastdtmfcommand);
02906 }
02907 return RESULT_SUCCESS;
02908 }
02909 }
02910 return RESULT_FAILURE;
02911 }
02912
02913
02914
02915
02916
02917 static int rpt_do_lstats(int fd, int argc, char *argv[])
02918 {
02919 int i,j;
02920 char *connstate;
02921 struct rpt *myrpt;
02922 struct rpt_link *l;
02923 struct rpt_lstat *s,*t;
02924 struct rpt_lstat s_head;
02925 if(argc != 3)
02926 return RESULT_SHOWUSAGE;
02927
02928 s = NULL;
02929 s_head.next = &s_head;
02930 s_head.prev = &s_head;
02931
02932 for(i = 0; i < nrpts; i++)
02933 {
02934 if (!strcmp(argv[2],rpt_vars[i].name)){
02935
02936 myrpt = &rpt_vars[i];
02937 rpt_mutex_lock(&myrpt->lock);
02938
02939 j = 0;
02940 l = myrpt->links.next;
02941 while(l && (l != &myrpt->links)){
02942 if (l->name[0] == '0'){
02943 l = l->next;
02944 continue;
02945 }
02946 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02947 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02948 rpt_mutex_unlock(&myrpt->lock);
02949 return RESULT_FAILURE;
02950 }
02951 memset(s, 0, sizeof(struct rpt_lstat));
02952 strncpy(s->name, l->name, MAXREMSTR - 1);
02953 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02954 else strcpy(s->peer,"(none)");
02955 s->mode = l->mode;
02956 s->outbound = l->outbound;
02957 s->reconnects = l->reconnects;
02958 s->connecttime = l->connecttime;
02959 s->thisconnected = l->thisconnected;
02960 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02961 insque((struct qelem *) s, (struct qelem *) s_head.next);
02962 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02963 l = l->next;
02964 }
02965 rpt_mutex_unlock(&myrpt->lock);
02966 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02967 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02968
02969 for(s = s_head.next; s != &s_head; s = s->next){
02970 int hours, minutes, seconds;
02971 long long connecttime = s->connecttime;
02972 char conntime[21];
02973 hours = (int) connecttime/3600000;
02974 connecttime %= 3600000;
02975 minutes = (int) connecttime/60000;
02976 connecttime %= 60000;
02977 seconds = (int) connecttime/1000;
02978 connecttime %= 1000;
02979 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02980 hours, minutes, seconds, (int) connecttime);
02981 conntime[20] = 0;
02982 if(s->thisconnected)
02983 connstate = "ESTABLISHED";
02984 else
02985 connstate = "CONNECTING";
02986 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02987 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02988 }
02989
02990 s = s_head.next;
02991 while(s != &s_head){
02992 t = s;
02993 s = s->next;
02994 remque((struct qelem *)t);
02995 ast_free(t);
02996 }
02997 return RESULT_SUCCESS;
02998 }
02999 }
03000 return RESULT_FAILURE;
03001 }
03002
03003
03004
03005
03006
03007 static int rpt_do_nodes(int fd, int argc, char *argv[])
03008 {
03009 int i,j;
03010 char ns;
03011 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03012 struct rpt *myrpt;
03013 if(argc != 3)
03014 return RESULT_SHOWUSAGE;
03015
03016 for(i = 0; i < nrpts; i++)
03017 {
03018 if (!strcmp(argv[2],rpt_vars[i].name)){
03019
03020 myrpt = &rpt_vars[i];
03021 rpt_mutex_lock(&myrpt->lock);
03022 __mklinklist(myrpt,NULL,lbuf);
03023 rpt_mutex_unlock(&myrpt->lock);
03024
03025 ns = finddelim(lbuf,strs,MAXLINKLIST);
03026
03027 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03028 ast_cli(fd,"\n");
03029 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03030 for(j = 0 ;; j++){
03031 if(!strs[j]){
03032 if(!j){
03033 ast_cli(fd,"<NONE>");
03034 }
03035 break;
03036 }
03037 ast_cli(fd, "%s", strs[j]);
03038 if(j % 8 == 7){
03039 ast_cli(fd, "\n");
03040 }
03041 else{
03042 if(strs[j + 1])
03043 ast_cli(fd, ", ");
03044 }
03045 }
03046 ast_cli(fd,"\n\n");
03047 return RESULT_SUCCESS;
03048 }
03049 }
03050 return RESULT_FAILURE;
03051 }
03052
03053
03054
03055
03056
03057 static int rpt_do_local_nodes(int fd, int argc, char *argv[])
03058 {
03059
03060 int i;
03061 ast_cli(fd, "\nNode\n----\n");
03062 for (i=0; i< nrpts; i++)
03063 {
03064 ast_cli(fd, "%s\n", rpt_vars[i].name);
03065 }
03066 ast_cli(fd,"\n");
03067 return RESULT_SUCCESS;
03068 }
03069
03070
03071
03072
03073
03074
03075 static int rpt_do_reload(int fd, int argc, char *argv[])
03076 {
03077 int n;
03078
03079 if (argc > 2) return RESULT_SHOWUSAGE;
03080
03081 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03082
03083 return RESULT_FAILURE;
03084 }
03085
03086
03087
03088
03089
03090 static int rpt_do_restart(int fd, int argc, char *argv[])
03091 {
03092 int i;
03093
03094 if (argc > 2) return RESULT_SHOWUSAGE;
03095 for(i = 0; i < nrpts; i++)
03096 {
03097 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03098 }
03099 return RESULT_FAILURE;
03100 }
03101
03102
03103
03104
03105
03106
03107 static int rpt_do_fun(int fd, int argc, char *argv[])
03108 {
03109 int i,busy=0;
03110
03111 if (argc != 4) return RESULT_SHOWUSAGE;
03112
03113 for(i = 0; i < nrpts; i++){
03114 if(!strcmp(argv[2], rpt_vars[i].name)){
03115 struct rpt *myrpt = &rpt_vars[i];
03116 rpt_mutex_lock(&myrpt->lock);
03117 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03118 rpt_mutex_unlock(&myrpt->lock);
03119 busy=1;
03120 }
03121 if(!busy){
03122 myrpt->macrotimer = MACROTIME;
03123 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03124 }
03125 rpt_mutex_unlock(&myrpt->lock);
03126 }
03127 }
03128 if(busy){
03129 ast_cli(fd, "Function decoder busy");
03130 }
03131 return RESULT_FAILURE;
03132 }
03133
03134
03135
03136
03137
03138
03139
03140
03141 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03142 {
03143 int busy=0;
03144
03145 rpt_mutex_lock(&myrpt->lock);
03146 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03147 rpt_mutex_unlock(&myrpt->lock);
03148 busy=1;
03149 }
03150 if(!busy){
03151 int x;
03152 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03153 myrpt->macrotimer = MACROTIME;
03154 for(x = 0; *(sptr + x); x++)
03155 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03156 *(sptr + x) = 0;
03157 }
03158 rpt_mutex_unlock(&myrpt->lock);
03159
03160 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03161
03162 return busy;
03163 }
03164
03165
03166
03167 static int rpt_do_fun1(int fd, int argc, char *argv[])
03168 {
03169 int i;
03170
03171 if (argc != 4) return RESULT_SHOWUSAGE;
03172
03173 for(i = 0; i < nrpts; i++){
03174 if(!strcmp(argv[2], rpt_vars[i].name)){
03175 struct rpt *myrpt = &rpt_vars[i];
03176 rpt_push_alt_macro(myrpt,argv[3]);
03177 }
03178 }
03179 return RESULT_FAILURE;
03180 }
03181
03182
03183
03184
03185 static int rpt_do_cmd(int fd, int argc, char *argv[])
03186 {
03187 int i, l;
03188 int busy=0;
03189 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03190
03191 int thisRpt = -1;
03192 int thisAction = -1;
03193 struct rpt *myrpt = NULL;
03194 if (argc != 6) return RESULT_SHOWUSAGE;
03195
03196 for(i = 0; i < nrpts; i++)
03197 {
03198 if(!strcmp(argv[2], rpt_vars[i].name))
03199 {
03200 thisRpt = i;
03201 myrpt = &rpt_vars[i];
03202 break;
03203 }
03204 }
03205
03206 if (thisRpt < 0)
03207 {
03208 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03209 return RESULT_FAILURE;
03210 }
03211
03212
03213 l = strlen(argv[3]);
03214 for(i = 0 ; i < maxActions; i++)
03215 {
03216 if(!strncasecmp(argv[3], function_table[i].action, l))
03217 {
03218 thisAction = i;
03219 break;
03220 }
03221 }
03222
03223 if (thisAction < 0)
03224 {
03225 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03226 return RESULT_FAILURE;
03227 }
03228
03229
03230
03231 rpt_mutex_lock(&myrpt->lock);
03232
03233 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03234 {
03235 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03236 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03237 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03238 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03239 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03240 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03241 }
03242 else
03243 {
03244 busy = 1;
03245 }
03246 rpt_mutex_unlock(&myrpt->lock);
03247
03248 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03249 }
03250
03251 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03252 {
03253 int res;
03254
03255 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03256 return res;
03257
03258 while(chan->generatordata) {
03259 if (ast_safe_sleep(chan,1)) return -1;
03260 }
03261
03262 return 0;
03263 }
03264
03265 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03266 {
03267 return play_tone_pair(chan, freq, 0, duration, amplitude);
03268 }
03269
03270 static int play_silence(struct ast_channel *chan, int duration)
03271 {
03272 return play_tone_pair(chan, 0, 0, duration, 0);
03273 }
03274
03275 #ifdef NEW_ASTERISK
03276
03277 static char *res2cli(int r)
03278
03279 {
03280 switch (r)
03281 {
03282 case RESULT_SUCCESS:
03283 return(CLI_SUCCESS);
03284 case RESULT_SHOWUSAGE:
03285 return(CLI_SHOWUSAGE);
03286 default:
03287 return(CLI_FAILURE);
03288 }
03289 }
03290
03291 static char *handle_cli_debug(struct ast_cli_entry *e,
03292 int cmd, struct ast_cli_args *a)
03293 {
03294 switch (cmd) {
03295 case CLI_INIT:
03296 e->command = "rpt debug level";
03297 e->usage = debug_usage;
03298 return NULL;
03299 case CLI_GENERATE:
03300 return NULL;
03301 }
03302 return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
03303 }
03304
03305 static char *handle_cli_dump(struct ast_cli_entry *e,
03306 int cmd, struct ast_cli_args *a)
03307 {
03308 switch (cmd) {
03309 case CLI_INIT:
03310 e->command = "rpt dump level";
03311 e->usage = dump_usage;
03312 return NULL;
03313 case CLI_GENERATE:
03314 return NULL;
03315 }
03316 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03317 }
03318
03319
03320 static char *handle_cli_stats(struct ast_cli_entry *e,
03321 int cmd, struct ast_cli_args *a)
03322 {
03323 switch (cmd) {
03324 case CLI_INIT:
03325 e->command = "rpt stats";
03326 e->usage = dump_stats;
03327 return NULL;
03328 case CLI_GENERATE:
03329 return NULL;
03330 }
03331 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03332 }
03333
03334 static char *handle_cli_nodes(struct ast_cli_entry *e,
03335 int cmd, struct ast_cli_args *a)
03336 {
03337 switch (cmd) {
03338 case CLI_INIT:
03339 e->command = "rpt nodes";
03340 e->usage = dump_nodes;
03341 return NULL;
03342 case CLI_GENERATE:
03343 return NULL;
03344 }
03345 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03346 }
03347
03348 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03349 int cmd, struct ast_cli_args *a)
03350 {
03351 switch (cmd) {
03352 case CLI_INIT:
03353 e->command = "rpt localnodes";
03354 e->usage = usage_local_nodes;
03355 return NULL;
03356 case CLI_GENERATE:
03357 return NULL;
03358 }
03359 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03360 }
03361
03362 static char *handle_cli_lstats(struct ast_cli_entry *e,
03363 int cmd, struct ast_cli_args *a)
03364 {
03365 switch (cmd) {
03366 case CLI_INIT:
03367 e->command = "rpt lstats";
03368 e->usage = dump_lstats;
03369 return NULL;
03370 case CLI_GENERATE:
03371 return NULL;
03372 }
03373 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03374 }
03375
03376 static char *handle_cli_reload(struct ast_cli_entry *e,
03377 int cmd, struct ast_cli_args *a)
03378 {
03379 switch (cmd) {
03380 case CLI_INIT:
03381 e->command = "rpt reload";
03382 e->usage = reload_usage;
03383 return NULL;
03384 case CLI_GENERATE:
03385 return NULL;
03386 }
03387 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03388 }
03389
03390 static char *handle_cli_restart(struct ast_cli_entry *e,
03391 int cmd, struct ast_cli_args *a)
03392 {
03393 switch (cmd) {
03394 case CLI_INIT:
03395 e->command = "rpt restart";
03396 e->usage = restart_usage;
03397 return NULL;
03398 case CLI_GENERATE:
03399 return NULL;
03400 }
03401 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03402 }
03403
03404 static char *handle_cli_fun(struct ast_cli_entry *e,
03405 int cmd, struct ast_cli_args *a)
03406 {
03407 switch (cmd) {
03408 case CLI_INIT:
03409 e->command = "rpt fun";
03410 e->usage = fun_usage;
03411 return NULL;
03412 case CLI_GENERATE:
03413 return NULL;
03414 }
03415 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03416 }
03417
03418 static char *handle_cli_fun1(struct ast_cli_entry *e,
03419 int cmd, struct ast_cli_args *a)
03420 {
03421 switch (cmd) {
03422 case CLI_INIT:
03423 e->command = "rpt fun1";
03424 e->usage = fun_usage;
03425 return NULL;
03426 case CLI_GENERATE:
03427 return NULL;
03428 }
03429 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03430 }
03431
03432 static char *handle_cli_cmd(struct ast_cli_entry *e,
03433 int cmd, struct ast_cli_args *a)
03434 {
03435 switch (cmd) {
03436 case CLI_INIT:
03437 e->command = "rpt cmd";
03438 e->usage = cmd_usage;
03439 return NULL;
03440 case CLI_GENERATE:
03441 return NULL;
03442 }
03443 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03444 }
03445
03446 static struct ast_cli_entry rpt_cli[] = {
03447 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03448 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03449 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03450 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03451 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03452 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03453 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03454 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03455 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03456 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03457 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03458 };
03459
03460 #endif
03461
03462 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03463 {
03464
03465 static struct morse_bits mbits[] = {
03466 {0, 0},
03467 {0, 0},
03468 {6, 18},
03469 {0, 0},
03470 {7, 72},
03471 {0, 0},
03472 {0, 0},
03473 {6, 30},
03474 {5, 13},
03475 {6, 29},
03476 {0, 0},
03477 {5, 10},
03478 {6, 51},
03479 {6, 33},
03480 {6, 42},
03481 {5, 9},
03482 {5, 31},
03483 {5, 30},
03484 {5, 28},
03485 {5, 24},
03486 {5, 16},
03487 {5, 0},
03488 {5, 1},
03489 {5, 3},
03490 {5, 7},
03491 {5, 15},
03492 {6, 7},
03493 {6, 21},
03494 {0, 0},
03495 {5, 33},
03496 {0, 0},
03497 {6, 12},
03498 {0, 0},
03499 {2, 2},
03500 {4, 1},
03501 {4, 5},
03502 {3, 1},
03503 {1, 0},
03504 {4, 4},
03505 {3, 3},
03506 {4, 0},
03507 {2, 0},
03508 {4, 14},
03509 {3, 5},
03510 {4, 2},
03511 {2, 3},
03512 {2, 1},
03513 {3, 7},
03514 {4, 6},
03515 {4, 11},
03516 {3, 2},
03517 {3, 0},
03518 {1, 1},
03519 {3, 4},
03520 {4, 8},
03521 {3, 6},
03522 {4, 9},
03523 {4, 13},
03524 {4, 3}
03525 };
03526
03527
03528 int dottime;
03529 int dashtime;
03530 int intralettertime;
03531 int interlettertime;
03532 int interwordtime;
03533 int len, ddcomb;
03534 int res;
03535 int c;
03536 int i;
03537 int flags;
03538
03539 res = 0;
03540
03541
03542
03543 dottime = 900/speed;
03544
03545
03546
03547 dashtime = 3 * dottime;
03548 intralettertime = dottime;
03549 interlettertime = dottime * 4 ;
03550 interwordtime = dottime * 7;
03551
03552 for(;(*string) && (!res); string++){
03553
03554 c = *string;
03555
03556
03557
03558 if((c >= 'a') && (c <= 'z'))
03559 c -= 0x20;
03560
03561
03562
03563 if(c > 'Z')
03564 continue;
03565
03566
03567
03568 if(c == ' '){
03569 if(!res)
03570 res = play_silence(chan, interwordtime);
03571 continue;
03572 }
03573
03574
03575
03576 c -= 0x20;
03577
03578
03579
03580 len = mbits[c].len;
03581 ddcomb = mbits[c].ddcomb;
03582
03583
03584
03585 for(; len ; len--){
03586 if(!res)
03587 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03588 if(!res)
03589 res = play_silence(chan, intralettertime);
03590 ddcomb >>= 1;
03591 }
03592
03593
03594
03595 if(!res)
03596 res = play_silence(chan, interlettertime - intralettertime);
03597 }
03598
03599
03600
03601 if (!res)
03602 res = ast_waitstream(chan, "");
03603 ast_stopstream(chan);
03604
03605
03606
03607
03608
03609 for(i = 0; i < 20 ; i++){
03610 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03611 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03612 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03613 break;
03614 if( ast_safe_sleep(chan, 50)){
03615 res = -1;
03616 break;
03617 }
03618 }
03619
03620
03621 return res;
03622 }
03623
03624 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03625 {
03626 char *p,*stringp;
03627 char *tonesubset;
03628 int f1,f2;
03629 int duration;
03630 int amplitude;
03631 int res;
03632 int i;
03633 int flags;
03634
03635 res = 0;
03636
03637 if(!tonestring)
03638 return res;
03639
03640 p = stringp = ast_strdup(tonestring);
03641
03642 for(;tonestring;){
03643 tonesubset = strsep(&stringp,")");
03644 if(!tonesubset)
03645 break;
03646 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03647 break;
03648 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03649 if(res)
03650 break;
03651 }
03652 if(p)
03653 ast_free(p);
03654 if(!res)
03655 res = play_tone_pair(chan, 0, 0, 100, 0);
03656
03657 if (!res)
03658 res = ast_waitstream(chan, "");
03659
03660 ast_stopstream(chan);
03661
03662
03663
03664
03665
03666 for(i = 0; i < 20 ; i++){
03667 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03668 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03669 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03670 break;
03671 if( ast_safe_sleep(chan, 50)){
03672 res = -1;
03673 break;
03674 }
03675 }
03676
03677 return res;
03678
03679 }
03680
03681 static int sayfile(struct ast_channel *mychannel,char *fname)
03682 {
03683 int res;
03684
03685 res = ast_streamfile(mychannel, fname, mychannel->language);
03686 if (!res)
03687 res = ast_waitstream(mychannel, "");
03688 else
03689 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03690 ast_stopstream(mychannel);
03691 return res;
03692 }
03693
03694 static int saycharstr(struct ast_channel *mychannel,char *str)
03695 {
03696 int res;
03697
03698 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03699 if (!res)
03700 res = ast_waitstream(mychannel, "");
03701 else
03702 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03703 ast_stopstream(mychannel);
03704 return res;
03705 }
03706
03707 static int saynum(struct ast_channel *mychannel, int num)
03708 {
03709 int res;
03710 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03711 if(!res)
03712 res = ast_waitstream(mychannel, "");
03713 else
03714 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03715 ast_stopstream(mychannel);
03716 return res;
03717 }
03718
03719
03720
03721
03722 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03723 {
03724 int res;
03725 char *val,fname[300];
03726
03727 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03728 if (!val) val = NODENAMES;
03729 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03730 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03731 return(sayfile(mychannel,fname));
03732 res = sayfile(mychannel,"rpt/node");
03733 if (!res)
03734 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03735 return res;
03736 }
03737
03738 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03739 {
03740 int res;
03741 char c;
03742
03743 static int morsespeed;
03744 static int morsefreq;
03745 static int morseampl;
03746 static int morseidfreq = 0;
03747 static int morseidampl;
03748 static char mcat[] = MORSE;
03749
03750 res = 0;
03751
03752 if(!morseidfreq){
03753 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03754 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03755 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03756 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03757 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03758 }
03759
03760
03761
03762 if(entry[0] == '|'){
03763 c = entry[1];
03764 if((c >= 'a')&&(c <= 'z'))
03765 c -= 0x20;
03766
03767 switch(c){
03768 case 'I':
03769 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03770 break;
03771
03772 case 'M':
03773 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03774 break;
03775
03776 case 'T':
03777 res = send_tone_telemetry(chan, entry + 2);
03778 break;
03779 default:
03780 res = -1;
03781 }
03782 }
03783 else
03784 res = sayfile(chan, entry);
03785 return res;
03786 }
03787
03788
03789
03790
03791
03792
03793
03794 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03795 {
03796
03797 int res;
03798 int i;
03799 char *entry;
03800 char *telemetry;
03801 char *telemetry_save;
03802
03803 res = 0;
03804 telemetry_save = NULL;
03805 entry = NULL;
03806
03807
03808 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03809 if(telemetry ){
03810 telemetry_save = ast_strdup(telemetry);
03811 if(!telemetry_save){
03812 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03813 return res;
03814 }
03815 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03816 }
03817
03818
03819
03820 if(!entry){
03821
03822 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03823 if(!strcasecmp(tele_defs[i].name, name))
03824 entry = tele_defs[i].value;
03825 }
03826 }
03827 if(entry){
03828 if(strlen(entry))
03829 if (chan) telem_any(myrpt,chan, entry);
03830 }
03831 else{
03832 res = -1;
03833 }
03834 if(telemetry_save)
03835 ast_free(telemetry_save);
03836 return res;
03837 }
03838
03839
03840
03841
03842
03843 static int get_wait_interval(struct rpt *myrpt, int type)
03844 {
03845 int interval;
03846 char *wait_times;
03847 char *wait_times_save;
03848
03849 wait_times_save = NULL;
03850 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03851
03852 if(wait_times){
03853 wait_times_save = ast_strdup(wait_times);
03854 if(!wait_times_save)
03855 return 0;
03856
03857 }
03858
03859 switch(type){
03860 case DLY_TELEM:
03861 if(wait_times)
03862 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03863 else
03864 interval = 1000;
03865 break;
03866
03867 case DLY_ID:
03868 if(wait_times)
03869 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03870 else
03871 interval = 500;
03872 break;
03873
03874 case DLY_UNKEY:
03875 if(wait_times)
03876 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03877 else
03878 interval = 1000;
03879 break;
03880
03881 case DLY_LINKUNKEY:
03882 if(wait_times)
03883 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03884 else
03885 interval = 1000;
03886 break;
03887
03888 case DLY_CALLTERM:
03889 if(wait_times)
03890 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03891 else
03892 interval = 1500;
03893 break;
03894
03895 case DLY_COMP:
03896 if(wait_times)
03897 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03898 else
03899 interval = 200;
03900 break;
03901
03902 case DLY_PARROT:
03903 if(wait_times)
03904 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03905 else
03906 interval = 200;
03907 break;
03908
03909 default:
03910 interval = 0;
03911 break;
03912 }
03913 if(wait_times_save)
03914 ast_free(wait_times_save);
03915 return interval;
03916 }
03917
03918
03919
03920
03921
03922 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03923 {
03924 int interval;
03925 interval = get_wait_interval(myrpt, type);
03926 if(debug)
03927 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03928 if(interval)
03929 ast_safe_sleep(chan,interval);
03930 if(debug)
03931 ast_log(LOG_NOTICE,"Delay complete\n");
03932 return;
03933 }
03934
03935 static int split_freq(char *mhz, char *decimals, char *freq);
03936
03937 static void *rpt_tele_thread(void *this)
03938 {
03939 struct dahdi_confinfo ci;
03940 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03941 struct rpt_tele *mytele = (struct rpt_tele *)this;
03942 struct rpt_tele *tlist;
03943 struct rpt *myrpt;
03944 struct rpt_link *l,*l1,linkbase;
03945 struct ast_channel *mychannel;
03946 int vmajor, vminor, m;
03947 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03948 time_t t;
03949 #ifdef NEW_ASTERISK
03950 struct ast_tm localtm;
03951 #else
03952 struct tm localtm;
03953 #endif
03954 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03955 int i,ns,rbimode;
03956 char mhz[MAXREMSTR];
03957 char decimals[MAXREMSTR];
03958 char mystr[200];
03959 struct dahdi_params par;
03960
03961
03962
03963 myrpt = mytele->rpt;
03964
03965
03966 rpt_mutex_lock(&myrpt->lock);
03967 nodename = ast_strdup(myrpt->name);
03968 if(!nodename)
03969 {
03970 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03971 rpt_mutex_lock(&myrpt->lock);
03972 remque((struct qelem *)mytele);
03973 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03974 rpt_mutex_unlock(&myrpt->lock);
03975 ast_free(mytele);
03976 pthread_exit(NULL);
03977 }
03978
03979 if (myrpt->p.ident){
03980 ident = ast_strdup(myrpt->p.ident);
03981 if(!ident)
03982 {
03983 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03984 rpt_mutex_lock(&myrpt->lock);
03985 remque((struct qelem *)mytele);
03986 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03987 __LINE__, mytele->mode);
03988 rpt_mutex_unlock(&myrpt->lock);
03989 ast_free(nodename);
03990 ast_free(mytele);
03991 pthread_exit(NULL);
03992 }
03993 }
03994 else
03995 {
03996 ident = "";
03997 }
03998 rpt_mutex_unlock(&myrpt->lock);
03999
04000
04001
04002
04003 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
04004 if (!mychannel)
04005 {
04006 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04007 rpt_mutex_lock(&myrpt->lock);
04008 remque((struct qelem *)mytele);
04009 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04010 rpt_mutex_unlock(&myrpt->lock);
04011 ast_free(nodename);
04012 ast_free(ident);
04013 ast_free(mytele);
04014 pthread_exit(NULL);
04015 }
04016 #ifdef AST_CDR_FLAG_POST_DISABLED
04017 if (mychannel->cdr)
04018 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04019 #endif
04020 rpt_mutex_lock(&myrpt->lock);
04021 mytele->chan = mychannel;
04022 rpt_mutex_unlock(&myrpt->lock);
04023
04024 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04025 (mytele->mode != LINKUNKEY))
04026 {
04027 rpt_mutex_lock(&myrpt->lock);
04028 if (!myrpt->active_telem)
04029 {
04030 myrpt->active_telem = mytele;
04031 rpt_mutex_unlock(&myrpt->lock);
04032 break;
04033 }
04034 rpt_mutex_unlock(&myrpt->lock);
04035 usleep(100000);
04036 }
04037
04038
04039 ci.chan = 0;
04040
04041
04042
04043 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04044 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04045 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04046 myrpt->txconf : myrpt->conf);
04047 ci.confmode = DAHDI_CONF_CONFANN;
04048
04049 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04050 {
04051 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04052 rpt_mutex_lock(&myrpt->lock);
04053 myrpt->active_telem = NULL;
04054 remque((struct qelem *)mytele);
04055 rpt_mutex_unlock(&myrpt->lock);
04056 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04057 ast_free(nodename);
04058 ast_free(ident);
04059 ast_free(mytele);
04060 ast_hangup(mychannel);
04061 pthread_exit(NULL);
04062 }
04063 ast_stopstream(mychannel);
04064 switch(mytele->mode)
04065 {
04066 case ID:
04067 case ID1:
04068
04069 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04070 res = telem_any(myrpt,mychannel, ident);
04071 imdone=1;
04072 break;
04073
04074 case TAILMSG:
04075 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04076 break;
04077
04078 case IDTALKOVER:
04079 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04080 if(p)
04081 res = telem_any(myrpt,mychannel, p);
04082 imdone=1;
04083 break;
04084
04085 case PROC:
04086
04087 wait_interval(myrpt, DLY_TELEM, mychannel);
04088 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04089 if(res < 0){
04090 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04091 }
04092 break;
04093 case TERM:
04094
04095 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04096 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04097 if(res < 0){
04098 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04099 }
04100 break;
04101 case COMPLETE:
04102
04103 wait_interval(myrpt, DLY_TELEM, mychannel);
04104 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04105 break;
04106 case MACRO_NOTFOUND:
04107
04108 wait_interval(myrpt, DLY_TELEM, mychannel);
04109 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04110 break;
04111 case MACRO_BUSY:
04112
04113 wait_interval(myrpt, DLY_TELEM, mychannel);
04114 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04115 break;
04116 case UNKEY:
04117 if(myrpt->patchnoct && myrpt->callmode){
04118 imdone = 1;
04119 break;
04120 }
04121
04122
04123
04124
04125
04126 x = get_wait_interval(myrpt, DLY_UNKEY);
04127 rpt_mutex_lock(&myrpt->lock);
04128 myrpt->unkeytocttimer = x;
04129 rpt_mutex_unlock(&myrpt->lock);
04130
04131
04132
04133
04134
04135 tlist = myrpt->tele.next;
04136 unkeys_queued = 0;
04137 if (tlist != &myrpt->tele)
04138 {
04139 rpt_mutex_lock(&myrpt->lock);
04140 while(tlist != &myrpt->tele){
04141 if (tlist->mode == UNKEY) unkeys_queued++;
04142 tlist = tlist->next;
04143 }
04144 rpt_mutex_unlock(&myrpt->lock);
04145 }
04146 if( unkeys_queued > 1){
04147 imdone = 1;
04148 break;
04149 }
04150
04151
04152
04153 while(myrpt->unkeytocttimer)
04154 {
04155 int ctint;
04156 if(myrpt->unkeytocttimer > 100)
04157 ctint = 100;
04158 else
04159 ctint = myrpt->unkeytocttimer;
04160 ast_safe_sleep(mychannel, ctint);
04161 rpt_mutex_lock(&myrpt->lock);
04162 if(myrpt->unkeytocttimer < ctint)
04163 myrpt->unkeytocttimer = 0;
04164 else
04165 myrpt->unkeytocttimer -= ctint;
04166 rpt_mutex_unlock(&myrpt->lock);
04167 }
04168
04169
04170
04171
04172
04173 if(myrpt->keyed){
04174 imdone = 1;
04175 break;
04176 }
04177
04178 rpt_mutex_lock(&myrpt->lock);
04179 myrpt->dailykerchunks++;
04180 myrpt->totalkerchunks++;
04181 rpt_mutex_unlock(&myrpt->lock);
04182
04183 haslink = 0;
04184 hastx = 0;
04185 hasremote = 0;
04186 l = myrpt->links.next;
04187 if (l != &myrpt->links)
04188 {
04189 rpt_mutex_lock(&myrpt->lock);
04190 while(l != &myrpt->links)
04191 {
04192 if (l->name[0] == '0')
04193 {
04194 l = l->next;
04195 continue;
04196 }
04197 haslink = 1;
04198 if (l->mode) {
04199 hastx++;
04200 if (l->isremote) hasremote++;
04201 }
04202 l = l->next;
04203 }
04204 rpt_mutex_unlock(&myrpt->lock);
04205 }
04206 if (haslink)
04207 {
04208
04209 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04210 if(res)
04211 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04212
04213
04214
04215 if (myrpt->cmdnode[0])
04216 {
04217 ast_safe_sleep(mychannel,200);
04218 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04219 if(res)
04220 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04221 ast_stopstream(mychannel);
04222 }
04223 }
04224 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04225 ct_copy = ast_strdup(ct);
04226 if(ct_copy)
04227 {
04228 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04229 ast_free(ct_copy);
04230 }
04231 else
04232 res = -1;
04233 if(res)
04234 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04235 }
04236 if (hasremote && (!myrpt->cmdnode[0]))
04237 {
04238
04239 ci.chan = 0;
04240 ci.confno = myrpt->conf;
04241 ci.confmode = DAHDI_CONF_CONFANN;
04242
04243 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04244 {
04245 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04246 rpt_mutex_lock(&myrpt->lock);
04247 myrpt->active_telem = NULL;
04248 remque((struct qelem *)mytele);
04249 rpt_mutex_unlock(&myrpt->lock);
04250 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04251 ast_free(nodename);
04252 ast_free(ident);
04253 ast_free(mytele);
04254 ast_hangup(mychannel);
04255 pthread_exit(NULL);
04256 }
04257 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04258 ast_safe_sleep(mychannel,200);
04259 ct_copy = ast_strdup(ct);
04260 if(ct_copy)
04261 {
04262 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04263 ast_free(ct_copy);
04264 }
04265 else
04266 res = -1;
04267
04268 if(res)
04269 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04270 }
04271 }
04272 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04273 if (myrpt->lastunit)
04274 {
04275 char mystr[10];
04276
04277 ast_safe_sleep(mychannel,200);
04278
04279 ci.chan = 0;
04280 ci.confno = myrpt->txconf;
04281 ci.confmode = DAHDI_CONF_CONFANN;
04282
04283 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04284 {
04285 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04286 rpt_mutex_lock(&myrpt->lock);
04287 myrpt->active_telem = NULL;
04288 remque((struct qelem *)mytele);
04289 rpt_mutex_unlock(&myrpt->lock);
04290 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04291 ast_free(nodename);
04292 ast_free(ident);
04293 ast_free(mytele);
04294 ast_hangup(mychannel);
04295 pthread_exit(NULL);
04296 }
04297 sprintf(mystr,"%04x",myrpt->lastunit);
04298 myrpt->lastunit = 0;
04299 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04300 break;
04301 }
04302 #endif
04303 imdone = 1;
04304 break;
04305 case LINKUNKEY:
04306 if(myrpt->patchnoct && myrpt->callmode){
04307 imdone = 1;
04308 break;
04309 }
04310
04311
04312
04313
04314
04315 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04316 mytele->mylink.linkunkeytocttimer = x;
04317
04318
04319
04320
04321
04322 tlist = myrpt->tele.next;
04323 unkeys_queued = 0;
04324 if (tlist != &myrpt->tele)
04325 {
04326 rpt_mutex_lock(&myrpt->lock);
04327 while(tlist != &myrpt->tele){
04328 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04329 tlist = tlist->next;
04330 }
04331 rpt_mutex_unlock(&myrpt->lock);
04332 }
04333 if( unkeys_queued > 1){
04334 imdone = 1;
04335 break;
04336 }
04337
04338
04339
04340 while(mytele->mylink.linkunkeytocttimer)
04341 {
04342 int ctint;
04343 if(mytele->mylink.linkunkeytocttimer > 100)
04344 ctint = 100;
04345 else
04346 ctint = mytele->mylink.linkunkeytocttimer;
04347 ast_safe_sleep(mychannel, ctint);
04348 rpt_mutex_lock(&myrpt->lock);
04349 if(mytele->mylink.linkunkeytocttimer < ctint)
04350 mytele->mylink.linkunkeytocttimer = 0;
04351 else
04352 mytele->mylink.linkunkeytocttimer -= ctint;
04353 rpt_mutex_unlock(&myrpt->lock);
04354 }
04355
04356 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04357 ct_copy = ast_strdup(ct);
04358 if(ct_copy){
04359 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04360 ast_free(ct_copy);
04361 }
04362 else
04363 res = -1;
04364 if(res)
04365 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04366 }
04367 imdone = 1;
04368 break;
04369 case REMDISC:
04370
04371 wait_interval(myrpt, DLY_TELEM, mychannel);
04372 l = myrpt->links.next;
04373 haslink = 0;
04374
04375 if (l != &myrpt->links)
04376 {
04377 rpt_mutex_lock(&myrpt->lock);
04378 while(l != &myrpt->links)
04379 {
04380 if (l->name[0] == '0')
04381 {
04382 l = l->next;
04383 continue;
04384 }
04385 if (!strcmp(l->name,mytele->mylink.name))
04386 {
04387 haslink = 1;
04388 break;
04389 }
04390 l = l->next;
04391 }
04392 rpt_mutex_unlock(&myrpt->lock);
04393 }
04394 if (haslink)
04395 {
04396 imdone = 1;
04397 break;
04398 }
04399 res = saynode(myrpt,mychannel,mytele->mylink.name);
04400 if (!res)
04401 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04402 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04403 break;
04404 case REMALREADY:
04405
04406 wait_interval(myrpt, DLY_TELEM, mychannel);
04407 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04408 break;
04409 case REMNOTFOUND:
04410
04411 wait_interval(myrpt, DLY_TELEM, mychannel);
04412 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04413 break;
04414 case REMGO:
04415
04416 wait_interval(myrpt, DLY_TELEM, mychannel);
04417 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04418 break;
04419 case CONNECTED:
04420
04421 wait_interval(myrpt, DLY_TELEM, mychannel);
04422 res = saynode(myrpt,mychannel,mytele->mylink.name);
04423 if (!res)
04424 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04425 if (!res)
04426 res = ast_waitstream(mychannel, "");
04427 else
04428 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04429 ast_stopstream(mychannel);
04430 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04431 if (!res)
04432 res = ast_waitstream(mychannel, "");
04433 else
04434 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04435 ast_stopstream(mychannel);
04436 res = saynode(myrpt,mychannel,myrpt->name);
04437 imdone = 1;
04438 break;
04439 case CONNFAIL:
04440 res = saynode(myrpt,mychannel,mytele->mylink.name);
04441 if (!res)
04442 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04443 break;
04444 case MEMNOTFOUND:
04445
04446 wait_interval(myrpt, DLY_TELEM, mychannel);
04447 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04448 break;
04449 case PLAYBACK:
04450
04451 wait_interval(myrpt, DLY_TELEM, mychannel);
04452 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04453 break;
04454 case TOPKEY:
04455
04456 wait_interval(myrpt, DLY_TELEM, mychannel);
04457 for(i = 0; i < TOPKEYN; i++)
04458 {
04459 if (!myrpt->topkey[i].node[0]) continue;
04460 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04461 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04462 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04463 "rpt/keyedfor" : "rpt/unkeyedfor");
04464 if (!res) res = saynum(mychannel,
04465 myrpt->topkey[i].timesince);
04466 if (!res) res = sayfile(mychannel,"rpt/seconds");
04467 if (!myrpt->topkeylong) break;
04468 }
04469 imdone = 1;
04470 break;
04471 case SETREMOTE:
04472 ast_mutex_lock(&myrpt->remlock);
04473 res = 0;
04474 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04475 {
04476 res = set_ft897(myrpt);
04477 }
04478 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04479 {
04480 res = set_tm271(myrpt);
04481 }
04482 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04483 {
04484 res = set_ic706(myrpt);
04485 }
04486 #ifdef HAVE_IOPERM
04487 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04488 {
04489 if (ioperm(myrpt->p.iobase,1,1) == -1)
04490 {
04491 rpt_mutex_unlock(&myrpt->lock);
04492 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04493 res = -1;
04494 }
04495 else res = setrbi(myrpt);
04496 }
04497 #endif
04498 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04499 {
04500 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04501 res = setkenwood(myrpt);
04502 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04503 if (ast_safe_sleep(mychannel,200) == -1)
04504 {
04505 ast_mutex_unlock(&myrpt->remlock);
04506 res = -1;
04507 break;
04508 }
04509 if (myrpt->iofd < 0)
04510 {
04511 i = DAHDI_FLUSH_EVENT;
04512 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04513 {
04514 ast_mutex_unlock(&myrpt->remlock);
04515 ast_log(LOG_ERROR,"Cant flush events");
04516 res = -1;
04517 break;
04518 }
04519 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04520 {
04521 ast_mutex_unlock(&myrpt->remlock);
04522 ast_log(LOG_ERROR,"Cant get params");
04523 res = -1;
04524 break;
04525 }
04526 myrpt->remoterx =
04527 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04528 }
04529 }
04530
04531 ast_mutex_unlock(&myrpt->remlock);
04532 if (!res)
04533 {
04534 imdone = 1;
04535 break;
04536 }
04537
04538 case INVFREQ:
04539
04540 wait_interval(myrpt, DLY_TELEM, mychannel);
04541 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04542 break;
04543 case REMMODE:
04544 cp = 0;
04545 wait_interval(myrpt, DLY_TELEM, mychannel);
04546 switch(myrpt->remmode)
04547 {
04548 case REM_MODE_FM:
04549 saycharstr(mychannel,"FM");
04550 break;
04551 case REM_MODE_USB:
04552 saycharstr(mychannel,"USB");
04553 break;
04554 case REM_MODE_LSB:
04555 saycharstr(mychannel,"LSB");
04556 break;
04557 case REM_MODE_AM:
04558 saycharstr(mychannel,"AM");
04559 break;
04560 }
04561 wait_interval(myrpt, DLY_COMP, mychannel);
04562 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04563 break;
04564 case LOGINREQ:
04565 wait_interval(myrpt, DLY_TELEM, mychannel);
04566 sayfile(mychannel,"rpt/login");
04567 saycharstr(mychannel,myrpt->name);
04568 break;
04569 case REMLOGIN:
04570 wait_interval(myrpt, DLY_TELEM, mychannel);
04571 saycharstr(mychannel,myrpt->loginuser);
04572 saynode(myrpt,mychannel,myrpt->name);
04573 wait_interval(myrpt, DLY_COMP, mychannel);
04574 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04575 break;
04576 case REMXXX:
04577 wait_interval(myrpt, DLY_TELEM, mychannel);
04578 res = 0;
04579 switch(mytele->submode)
04580 {
04581 case 100:
04582 sayfile(mychannel, "rpt/rxpl");
04583 sayfile(mychannel, "rpt/off");
04584 break;
04585 case 101:
04586 sayfile(mychannel, "rpt/rxpl");
04587 sayfile(mychannel, "rpt/on");
04588 break;
04589 case 102:
04590 sayfile(mychannel, "rpt/txpl");
04591 sayfile(mychannel, "rpt/off");
04592 break;
04593 case 103:
04594 sayfile(mychannel, "rpt/txpl");
04595 sayfile(mychannel, "rpt/on");
04596 break;
04597 case 104:
04598 sayfile(mychannel, "rpt/lopwr");
04599 break;
04600 case 105:
04601 sayfile(mychannel, "rpt/medpwr");
04602 break;
04603 case 106:
04604 sayfile(mychannel, "rpt/hipwr");
04605 break;
04606 case 113:
04607 sayfile(mychannel,"rpt/down");
04608 sayfile(mychannel, "rpt/slow");
04609 break;
04610 case 114:
04611 sayfile(mychannel,"rpt/down");
04612 sayfile(mychannel, "rpt/quick");
04613 break;
04614 case 115:
04615 sayfile(mychannel,"rpt/down");
04616 sayfile(mychannel, "rpt/fast");
04617 break;
04618 case 116:
04619 sayfile(mychannel,"rpt/up");
04620 sayfile(mychannel, "rpt/slow");
04621 break;
04622 case 117:
04623 sayfile(mychannel,"rpt/up");
04624 sayfile(mychannel, "rpt/quick");
04625 break;
04626 case 118:
04627 sayfile(mychannel,"rpt/up");
04628 sayfile(mychannel, "rpt/fast");
04629 break;
04630 default:
04631 res = -1;
04632 }
04633 wait_interval(myrpt, DLY_COMP, mychannel);
04634 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04635 break;
04636 case SCAN:
04637 ast_mutex_lock(&myrpt->remlock);
04638 if (myrpt->hfscanstop)
04639 {
04640 myrpt->hfscanstatus = 0;
04641 myrpt->hfscanmode = 0;
04642 myrpt->hfscanstop = 0;
04643 mytele->mode = SCANSTAT;
04644 ast_mutex_unlock(&myrpt->remlock);
04645 if (ast_safe_sleep(mychannel,1000) == -1) break;
04646 sayfile(mychannel, "rpt/stop");
04647 imdone = 1;
04648 break;
04649 }
04650 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04651 i = myrpt->hfscanstatus;
04652 myrpt->hfscanstatus = 0;
04653 if (i) mytele->mode = SCANSTAT;
04654 ast_mutex_unlock(&myrpt->remlock);
04655 if (i < 0) sayfile(mychannel, "rpt/stop");
04656 else if (i > 0) saynum(mychannel,i);
04657 imdone = 1;
04658 break;
04659 case TUNE:
04660 ast_mutex_lock(&myrpt->remlock);
04661 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04662 {
04663 set_mode_ic706(myrpt, REM_MODE_AM);
04664 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04665 ast_safe_sleep(mychannel,500);
04666 set_mode_ic706(myrpt, myrpt->remmode);
04667 myrpt->tunerequest = 0;
04668 ast_mutex_unlock(&myrpt->remlock);
04669 imdone = 1;
04670 break;
04671 }
04672 set_mode_ft897(myrpt, REM_MODE_AM);
04673 simple_command_ft897(myrpt, 8);
04674 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04675 simple_command_ft897(myrpt, 0x88);
04676 ast_safe_sleep(mychannel,500);
04677 set_mode_ft897(myrpt, myrpt->remmode);
04678 myrpt->tunerequest = 0;
04679 ast_mutex_unlock(&myrpt->remlock);
04680 imdone = 1;
04681 break;
04682 case REMSHORTSTATUS:
04683 case REMLONGSTATUS:
04684 wait_interval(myrpt, DLY_TELEM, mychannel);
04685 res = saynode(myrpt,mychannel,myrpt->name);
04686 if(!res)
04687 res = sayfile(mychannel,"rpt/frequency");
04688 if(!res)
04689 res = split_freq(mhz, decimals, myrpt->freq);
04690 if (!multimode_capable(myrpt)) decimals[3] = 0;
04691 if(!res){
04692 m = atoi(mhz);
04693 if(m < 100)
04694 res = saynum(mychannel, m);
04695 else
04696 res = saycharstr(mychannel, mhz);
04697 }
04698 if(!res)
04699 res = sayfile(mychannel, "letters/dot");
04700 if(!res)
04701 res = saycharstr(mychannel, decimals);
04702
04703 if(res) break;
04704 if(myrpt->remmode == REM_MODE_FM){
04705 switch(myrpt->offset){
04706
04707 case REM_MINUS:
04708 res = sayfile(mychannel,"rpt/minus");
04709 break;
04710
04711 case REM_SIMPLEX:
04712 res = sayfile(mychannel,"rpt/simplex");
04713 break;
04714
04715 case REM_PLUS:
04716 res = sayfile(mychannel,"rpt/plus");
04717 break;
04718
04719 default:
04720 break;
04721 }
04722 }
04723 else{
04724 switch(myrpt->remmode){
04725
04726 case REM_MODE_USB:
04727 res = saycharstr(mychannel, "USB");
04728 break;
04729
04730 case REM_MODE_LSB:
04731 res = saycharstr(mychannel, "LSB");
04732 break;
04733
04734 case REM_MODE_AM:
04735 res = saycharstr(mychannel, "AM");
04736 break;
04737
04738
04739 default:
04740 break;
04741 }
04742 }
04743
04744 if (res == -1) break;
04745
04746 if(mytele->mode == REMSHORTSTATUS){
04747 wait_interval(myrpt, DLY_COMP, mychannel);
04748 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04749 break;
04750 }
04751
04752 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04753 {
04754 switch(myrpt->powerlevel){
04755
04756 case REM_LOWPWR:
04757 res = sayfile(mychannel,"rpt/lopwr") ;
04758 break;
04759 case REM_MEDPWR:
04760 res = sayfile(mychannel,"rpt/medpwr");
04761 break;
04762 case REM_HIPWR:
04763 res = sayfile(mychannel,"rpt/hipwr");
04764 break;
04765 }
04766 }
04767
04768 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04769 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04770 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04771 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04772 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04773 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04774 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04775 (sayfile(mychannel,"rpt/frequency") == -1) ||
04776 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04777 if(myrpt->remmode == REM_MODE_FM){
04778 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04779 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04780 (sayfile(mychannel,"rpt/txpl") == -1) ||
04781 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04782 {
04783 break;
04784 }
04785 }
04786 wait_interval(myrpt, DLY_COMP, mychannel);
04787 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04788 break;
04789 case STATUS:
04790
04791 wait_interval(myrpt, DLY_TELEM, mychannel);
04792 hastx = 0;
04793 linkbase.next = &linkbase;
04794 linkbase.prev = &linkbase;
04795 rpt_mutex_lock(&myrpt->lock);
04796
04797 l = myrpt->links.next;
04798 while(l != &myrpt->links)
04799 {
04800 if (l->name[0] == '0')
04801 {
04802 l = l->next;
04803 continue;
04804 }
04805 l1 = ast_malloc(sizeof(struct rpt_link));
04806 if (!l1)
04807 {
04808 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04809 remque((struct qelem *)mytele);
04810 myrpt->active_telem = NULL;
04811 rpt_mutex_unlock(&myrpt->lock);
04812 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04813 ast_free(nodename);
04814 ast_free(ident);
04815 ast_free(mytele);
04816 ast_hangup(mychannel);
04817 pthread_exit(NULL);
04818 }
04819 memcpy(l1,l,sizeof(struct rpt_link));
04820 l1->next = l1->prev = NULL;
04821 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04822 l = l->next;
04823 }
04824 rpt_mutex_unlock(&myrpt->lock);
04825 res = saynode(myrpt,mychannel,myrpt->name);
04826 if (myrpt->callmode)
04827 {
04828 hastx = 1;
04829 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04830 if (!res)
04831 res = ast_waitstream(mychannel, "");
04832 else
04833 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04834 ast_stopstream(mychannel);
04835 }
04836 l = linkbase.next;
04837 while(l != &linkbase)
04838 {
04839 char *s;
04840
04841 hastx = 1;
04842 res = saynode(myrpt,mychannel,l->name);
04843 s = "rpt/tranceive";
04844 if (!l->mode) s = "rpt/monitor";
04845 if (!l->thisconnected) s = "rpt/connecting";
04846 res = ast_streamfile(mychannel, s, mychannel->language);
04847 if (!res)
04848 res = ast_waitstream(mychannel, "");
04849 else
04850 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04851 ast_stopstream(mychannel);
04852 l = l->next;
04853 }
04854 if (!hastx)
04855 {
04856 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04857 if (!res)
04858 res = ast_waitstream(mychannel, "");
04859 else
04860 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04861 ast_stopstream(mychannel);
04862 }
04863
04864 l = linkbase.next;
04865 while(l != &linkbase)
04866 {
04867 l1 = l;
04868 l = l->next;
04869 remque((struct qelem *)l1);
04870 ast_free(l1);
04871 }
04872 imdone = 1;
04873 break;
04874 case FULLSTATUS:
04875 rpt_mutex_lock(&myrpt->lock);
04876
04877 __mklinklist(myrpt,NULL,lbuf);
04878 rpt_mutex_unlock(&myrpt->lock);
04879
04880 ns = finddelim(lbuf,strs,MAXLINKLIST);
04881
04882 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04883
04884 wait_interval(myrpt, DLY_TELEM, mychannel);
04885 hastx = 0;
04886 res = saynode(myrpt,mychannel,myrpt->name);
04887 if (myrpt->callmode)
04888 {
04889 hastx = 1;
04890 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04891 if (!res)
04892 res = ast_waitstream(mychannel, "");
04893 else
04894 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04895 ast_stopstream(mychannel);
04896 }
04897
04898 for(i = 0; i < ns; i++)
04899 {
04900 char *s,mode = 'T';
04901
04902
04903 if ((*strs[i] < '0') || (*strs[i] > '9'))
04904 {
04905 mode = *strs[i];
04906 strs[i]++;
04907 }
04908
04909 hastx = 1;
04910 res = saynode(myrpt,mychannel,strs[i]);
04911 s = "rpt/tranceive";
04912 if (mode == 'R') s = "rpt/monitor";
04913 if (mode == 'C') s = "rpt/connecting";
04914 res = ast_streamfile(mychannel, s, mychannel->language);
04915 if (!res)
04916 res = ast_waitstream(mychannel, "");
04917 else
04918 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04919 ast_stopstream(mychannel);
04920 }
04921 if (!hastx)
04922 {
04923 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04924 if (!res)
04925 res = ast_waitstream(mychannel, "");
04926 else
04927 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04928 ast_stopstream(mychannel);
04929 }
04930 imdone = 1;
04931 break;
04932
04933 case LASTNODEKEY:
04934 rpt_mutex_lock(&myrpt->lock);
04935 if(myrpt->lastnodewhichkeyedusup){
04936 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04937 if(!p){
04938 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04939 imdone = 1;
04940 break;
04941 }
04942 }
04943 else
04944 p = NULL;
04945 rpt_mutex_unlock(&myrpt->lock);
04946 if(!p){
04947 imdone = 1;
04948 break;
04949 }
04950 wait_interval(myrpt, DLY_TELEM, mychannel);
04951 res = saynode(myrpt,mychannel,p);
04952 ast_free(p);
04953 imdone = 1;
04954 break;
04955
04956 case UNAUTHTX:
04957 wait_interval(myrpt, DLY_TELEM, mychannel);
04958 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04959 if (!res)
04960 res = ast_waitstream(mychannel, "");
04961 else
04962 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04963 ast_stopstream(mychannel);
04964 imdone = 1;
04965 break;
04966
04967 case PARROT:
04968
04969 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04970 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04971 {
04972 imdone = 1;
04973 myrpt->parrotstate = 0;
04974 break;
04975 }
04976 wait_interval(myrpt, DLY_PARROT, mychannel);
04977 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04978 res = ast_streamfile(mychannel, mystr, mychannel->language);
04979 if (!res)
04980 res = ast_waitstream(mychannel, "");
04981 else
04982 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04983 ast_stopstream(mychannel);
04984 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04985 strcat(mystr,".wav");
04986 unlink(mystr);
04987 imdone = 1;
04988 myrpt->parrotstate = 0;
04989 break;
04990
04991 case TIMEOUT:
04992 res = saynode(myrpt,mychannel,myrpt->name);
04993 if (!res)
04994 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
04995 break;
04996
04997 case TIMEOUT_WARNING:
04998 time(&t);
04999 res = saynode(myrpt,mychannel,myrpt->name);
05000 if (!res)
05001 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05002 if (!res)
05003 res = ast_waitstream(mychannel, "");
05004 else
05005 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05006 ast_stopstream(mychannel);
05007 if(!res)
05008 ast_say_number(mychannel, myrpt->p.remotetimeout -
05009 (t - myrpt->last_activity_time),
05010 "", mychannel->language, (char *) NULL);
05011 if (!res)
05012 res = ast_waitstream(mychannel, "");
05013 ast_stopstream(mychannel);
05014 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05015 break;
05016
05017 case ACT_TIMEOUT_WARNING:
05018 time(&t);
05019 res = saynode(myrpt,mychannel,myrpt->name);
05020 if (!res)
05021 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05022 if (!res)
05023 res = ast_waitstream(mychannel, "");
05024 else
05025 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05026 ast_stopstream(mychannel);
05027 if(!res)
05028 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05029 (t - myrpt->last_activity_time),
05030 "", mychannel->language, (char *) NULL);
05031 if (!res)
05032 res = ast_waitstream(mychannel, "");
05033 ast_stopstream(mychannel);
05034 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05035 break;
05036
05037 case STATS_TIME:
05038 case STATS_TIME_LOCAL:
05039 wait_interval(myrpt, DLY_TELEM, mychannel);
05040 t = time(NULL);
05041 rpt_localtime(&t, &localtm);
05042
05043 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05044 p = "rpt/goodmorning";
05045 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05046 p = "rpt/goodafternoon";
05047 else
05048 p = "rpt/goodevening";
05049 if (sayfile(mychannel,p) == -1)
05050 {
05051 imdone = 1;
05052 break;
05053 }
05054
05055 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05056 {
05057 imdone = 1;
05058 break;
05059 }
05060
05061 res = ast_say_time(mychannel, t, "", mychannel->language);
05062 if (!res)
05063 res = ast_waitstream(mychannel, "");
05064 ast_stopstream(mychannel);
05065 imdone = 1;
05066 break;
05067 case STATS_VERSION:
05068 p = strstr(tdesc, "version");
05069 if(!p)
05070 break;
05071 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05072 break;
05073 wait_interval(myrpt, DLY_TELEM, mychannel);
05074
05075 if (sayfile(mychannel,"rpt/version") == -1)
05076 {
05077 imdone = 1;
05078 break;
05079 }
05080 if(!res)
05081 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05082 if (!res)
05083 res = ast_waitstream(mychannel, "");
05084 ast_stopstream(mychannel);
05085 if (saycharstr(mychannel,".") == -1)
05086 {
05087 imdone = 1;
05088 break;
05089 }
05090 if(!res)
05091 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05092 if (!res){
05093 res = ast_waitstream(mychannel, "");
05094 ast_stopstream(mychannel);
05095 }
05096 else
05097 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05098 imdone = 1;
05099 break;
05100 case ARB_ALPHA:
05101 wait_interval(myrpt, DLY_TELEM, mychannel);
05102 if(mytele->param)
05103 saycharstr(mychannel, mytele->param);
05104 imdone = 1;
05105 break;
05106 case REV_PATCH:
05107 wait_interval(myrpt, DLY_TELEM, mychannel);
05108 if(mytele->param) {
05109
05110
05111 char *tpl_working, *tpl_current;
05112 char *tmp[100], *myparm;
05113 int looptemp=0,idx=0, dres = 0;
05114
05115
05116 tpl_working = ast_strdup(mytele->param);
05117 myparm = strsep(&tpl_working,",");
05118 tpl_current=strsep(&tpl_working, ":");
05119
05120 while(tpl_current && looptemp < sizeof(tmp)) {
05121 tmp[looptemp]=tpl_current;
05122 looptemp++;
05123 tpl_current=strsep(&tpl_working,":");
05124 }
05125
05126 for(idx=0; idx<looptemp; idx++) {
05127 if(!strcmp(tmp[idx], "PARKED")) {
05128 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05129 } else if(!strcmp(tmp[idx], "NODE")) {
05130 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05131 } else {
05132 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05133 if(!dres) {
05134 dres = ast_waitstream(mychannel, "");
05135 } else {
05136 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05137 dres = 0;
05138 }
05139 }
05140 }
05141 ast_free(tpl_working);
05142 }
05143 imdone = 1;
05144 break;
05145 case TEST_TONE:
05146 imdone = 1;
05147 if (myrpt->stopgen) break;
05148 myrpt->stopgen = -1;
05149 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05150 {
05151 myrpt->stopgen = 0;
05152 break;
05153 }
05154 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05155 if (ast_safe_sleep(mychannel,1)) break;
05156 imdone = 1;
05157 }
05158 myrpt->stopgen = 0;
05159 break;
05160 default:
05161 break;
05162 }
05163 if (!imdone)
05164 {
05165 if (!res)
05166 res = ast_waitstream(mychannel, "");
05167 else {
05168 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05169 res = 0;
05170 }
05171 }
05172 ast_stopstream(mychannel);
05173 rpt_mutex_lock(&myrpt->lock);
05174 if (mytele->mode == TAILMSG)
05175 {
05176 if (!res)
05177 {
05178 myrpt->tailmessagen++;
05179 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05180 }
05181 else
05182 {
05183 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05184 }
05185 }
05186 remque((struct qelem *)mytele);
05187 myrpt->active_telem = NULL;
05188 rpt_mutex_unlock(&myrpt->lock);
05189 ast_free(nodename);
05190 ast_free(ident);
05191 ast_free(mytele);
05192 ast_hangup(mychannel);
05193 #ifdef APP_RPT_LOCK_DEBUG
05194 {
05195 struct lockthread *t;
05196
05197 sleep(5);
05198 ast_mutex_lock(&locklock);
05199 t = get_lockthread(pthread_self());
05200 if (t) memset(t,0,sizeof(struct lockthread));
05201 ast_mutex_unlock(&locklock);
05202 }
05203 #endif
05204 pthread_exit(NULL);
05205 }
05206
05207 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05208 {
05209 struct rpt_tele *tele;
05210 struct rpt_link *mylink = NULL;
05211 int res;
05212 pthread_attr_t attr;
05213 char *v1, *v2;
05214
05215 if(debug > 6)
05216 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05217
05218 switch(mode)
05219 {
05220 case UNKEY:
05221
05222
05223 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05224 "unlinkedct");
05225 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05226 "remotect");
05227 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05228 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05229 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05230 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05231 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05232 break;
05233 case LINKUNKEY:
05234 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05235 return;
05236 break;
05237 default:
05238 break;
05239 }
05240 tele = ast_malloc(sizeof(struct rpt_tele));
05241 if (!tele)
05242 {
05243 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05244 pthread_exit(NULL);
05245 return;
05246 }
05247
05248 memset((char *)tele,0,sizeof(struct rpt_tele));
05249 tele->rpt = myrpt;
05250 tele->mode = mode;
05251 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05252 else mylink = (struct rpt_link *) data;
05253 rpt_mutex_lock(&myrpt->lock);
05254 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05255 (mode == LINKUNKEY)){
05256 memset(&tele->mylink,0,sizeof(struct rpt_link));
05257 if (mylink){
05258 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05259 }
05260 }
05261 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05262 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05263 tele->param[TELEPARAMSIZE - 1] = 0;
05264 }
05265 if (mode == REMXXX) tele->submode = (intptr_t) data;
05266 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05267 rpt_mutex_unlock(&myrpt->lock);
05268 pthread_attr_init(&attr);
05269 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05270 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05271 if(res < 0){
05272 rpt_mutex_lock(&myrpt->lock);
05273 remque((struct qlem *) tele);
05274 rpt_mutex_unlock(&myrpt->lock);
05275 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05276 }
05277 return;
05278 }
05279
05280 static void *rpt_call(void *this)
05281 {
05282 struct dahdi_confinfo ci;
05283 struct rpt *myrpt = (struct rpt *)this;
05284 int res;
05285 int stopped,congstarted,dialtimer,lastcidx,aborted;
05286 struct ast_channel *mychannel,*genchannel;
05287
05288 myrpt->mydtmf = 0;
05289
05290 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05291 if (!mychannel)
05292 {
05293 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05294 pthread_exit(NULL);
05295 }
05296 #ifdef AST_CDR_FLAG_POST_DISABLED
05297 if (mychannel->cdr)
05298 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05299 #endif
05300 ci.chan = 0;
05301 ci.confno = myrpt->conf;
05302 #if 0
05303 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05304 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05305 #endif
05306 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05307
05308 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05309 {
05310 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05311 ast_hangup(mychannel);
05312 myrpt->callmode = 0;
05313 pthread_exit(NULL);
05314 }
05315
05316 genchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05317 if (!genchannel)
05318 {
05319 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05320 ast_hangup(mychannel);
05321 pthread_exit(NULL);
05322 }
05323 #ifdef AST_CDR_FLAG_POST_DISABLED
05324 if (genchannel->cdr)
05325 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05326 #endif
05327 ci.chan = 0;
05328 ci.confno = myrpt->conf;
05329 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05330 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05331
05332 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05333 {
05334 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05335 ast_hangup(mychannel);
05336 ast_hangup(genchannel);
05337 myrpt->callmode = 0;
05338 pthread_exit(NULL);
05339 }
05340 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05341 {
05342 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05343 ast_hangup(mychannel);
05344 ast_hangup(genchannel);
05345 myrpt->callmode = 0;
05346 pthread_exit(NULL);
05347 }
05348 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05349 {
05350 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05351 ast_hangup(mychannel);
05352 ast_hangup(genchannel);
05353 myrpt->callmode = 0;
05354 pthread_exit(NULL);
05355 }
05356
05357 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05358 {
05359 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05360 ast_hangup(mychannel);
05361 ast_hangup(genchannel);
05362 myrpt->callmode = 0;
05363 pthread_exit(NULL);
05364 }
05365 stopped = 0;
05366 congstarted = 0;
05367 dialtimer = 0;
05368 lastcidx = 0;
05369 myrpt->calldigittimer = 0;
05370 aborted = 0;
05371
05372 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05373 {
05374 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05375 dialtimer = 0;
05376 lastcidx = myrpt->cidx;
05377 }
05378
05379 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05380 if(debug)
05381 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05382 rpt_mutex_lock(&myrpt->lock);
05383 aborted = 1;
05384 myrpt->callmode = 0;
05385 rpt_mutex_unlock(&myrpt->lock);
05386 break;
05387 }
05388
05389 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05390 {
05391 stopped = 1;
05392
05393 tone_zone_play_tone(genchannel->fds[0],-1);
05394 }
05395 if (myrpt->callmode == 1)
05396 {
05397 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05398 {
05399 myrpt->callmode = 2;
05400 break;
05401 }
05402
05403 if (myrpt->calldigittimer)
05404 myrpt->calldigittimer += MSWAIT;
05405 }
05406 if (myrpt->callmode == 4)
05407 {
05408 if(!congstarted){
05409 congstarted = 1;
05410
05411 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05412 }
05413 }
05414 res = ast_safe_sleep(mychannel, MSWAIT);
05415 if (res < 0)
05416 {
05417 if(debug)
05418 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05419 ast_hangup(mychannel);
05420 ast_hangup(genchannel);
05421 rpt_mutex_lock(&myrpt->lock);
05422 myrpt->callmode = 0;
05423 rpt_mutex_unlock(&myrpt->lock);
05424 pthread_exit(NULL);
05425 }
05426 dialtimer += MSWAIT;
05427 }
05428
05429 tone_zone_play_tone(genchannel->fds[0],-1);
05430
05431 if (!myrpt->callmode)
05432 {
05433 if(debug)
05434 ast_log(LOG_NOTICE, "callmode==0\n");
05435 ast_hangup(mychannel);
05436 ast_hangup(genchannel);
05437 rpt_mutex_lock(&myrpt->lock);
05438 myrpt->callmode = 0;
05439 myrpt->macropatch=0;
05440 channel_revert(myrpt);
05441 rpt_mutex_unlock(&myrpt->lock);
05442 if((!myrpt->patchquiet) && aborted)
05443 rpt_telemetry(myrpt, TERM, NULL);
05444 pthread_exit(NULL);
05445 }
05446
05447 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05448 char *name, *loc, *instr;
05449 instr = ast_strdup(myrpt->p.ourcallerid);
05450 if(instr){
05451 ast_callerid_parse(instr, &name, &loc);
05452 if(loc){
05453 if(mychannel->cid.cid_num)
05454 ast_free(mychannel->cid.cid_num);
05455 mychannel->cid.cid_num = ast_strdup(loc);
05456 }
05457 if(name){
05458 if(mychannel->cid.cid_name)
05459 ast_free(mychannel->cid.cid_name);
05460 mychannel->cid.cid_name = ast_strdup(name);
05461 }
05462 ast_free(instr);
05463 }
05464 }
05465
05466 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05467 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05468
05469 if (myrpt->p.acctcode)
05470 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05471 mychannel->priority = 1;
05472 ast_channel_undefer_dtmf(mychannel);
05473 if (ast_pbx_start(mychannel) < 0)
05474 {
05475 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05476 ast_hangup(mychannel);
05477 ast_hangup(genchannel);
05478 rpt_mutex_lock(&myrpt->lock);
05479 myrpt->callmode = 0;
05480 rpt_mutex_unlock(&myrpt->lock);
05481 pthread_exit(NULL);
05482 }
05483 usleep(10000);
05484 rpt_mutex_lock(&myrpt->lock);
05485 myrpt->callmode = 3;
05486
05487 ci.chan = 0;
05488 ci.confno = myrpt->conf;
05489 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05490 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05491
05492 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05493 {
05494 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05495 ast_hangup(mychannel);
05496 ast_hangup(genchannel);
05497 myrpt->callmode = 0;
05498 pthread_exit(NULL);
05499 }
05500
05501 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05502 {
05503 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05504 ast_hangup(mychannel);
05505 myrpt->callmode = 0;
05506 pthread_exit(NULL);
05507 }
05508 ci.chan = 0;
05509 ci.confno = res;
05510 ci.confmode = DAHDI_CONF_MONITOR;
05511
05512 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05513 {
05514 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05515 ast_hangup(mychannel);
05516 myrpt->callmode = 0;
05517 pthread_exit(NULL);
05518 }
05519 while(myrpt->callmode)
05520 {
05521 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05522 {
05523
05524 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05525 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05526 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05527 myrpt->callmode = 0;
05528 myrpt->macropatch=0;
05529 if(!myrpt->patchquiet){
05530 rpt_mutex_unlock(&myrpt->lock);
05531 rpt_telemetry(myrpt, TERM, NULL);
05532 rpt_mutex_lock(&myrpt->lock);
05533 }
05534 }
05535 else{
05536 myrpt->callmode = 4;
05537 rpt_mutex_unlock(&myrpt->lock);
05538
05539 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05540 rpt_mutex_lock(&myrpt->lock);
05541 }
05542 }
05543 if (myrpt->mydtmf)
05544 {
05545 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05546 wf.subclass = myrpt->mydtmf;
05547 rpt_mutex_unlock(&myrpt->lock);
05548 ast_queue_frame(mychannel,&wf);
05549 #ifdef NEW_ASTERISK
05550 ast_senddigit(genchannel,myrpt->mydtmf,0);
05551 #else
05552 ast_senddigit(genchannel,myrpt->mydtmf);
05553 #endif
05554 rpt_mutex_lock(&myrpt->lock);
05555 myrpt->mydtmf = 0;
05556 }
05557 rpt_mutex_unlock(&myrpt->lock);
05558 usleep(MSWAIT * 1000);
05559 rpt_mutex_lock(&myrpt->lock);
05560 }
05561 if(debug)
05562 ast_log(LOG_NOTICE, "exit channel loop\n");
05563 rpt_mutex_unlock(&myrpt->lock);
05564 tone_zone_play_tone(genchannel->fds[0],-1);
05565 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05566 ast_hangup(genchannel);
05567 rpt_mutex_lock(&myrpt->lock);
05568 myrpt->callmode = 0;
05569 myrpt->macropatch=0;
05570 channel_revert(myrpt);
05571 rpt_mutex_unlock(&myrpt->lock);
05572
05573 ci.chan = 0;
05574 ci.confno = myrpt->conf;
05575 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05576 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05577
05578 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05579 {
05580 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05581 }
05582 pthread_exit(NULL);
05583 }
05584
05585 static void send_link_dtmf(struct rpt *myrpt,char c)
05586 {
05587 char str[300];
05588 struct ast_frame wf;
05589 struct rpt_link *l;
05590
05591 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05592 wf.frametype = AST_FRAME_TEXT;
05593 wf.subclass = 0;
05594 wf.offset = 0;
05595 wf.mallocd = 0;
05596 wf.datalen = strlen(str) + 1;
05597 wf.samples = 0;
05598 l = myrpt->links.next;
05599
05600 while(l != &myrpt->links)
05601 {
05602 if (l->name[0] == '0')
05603 {
05604 l = l->next;
05605 continue;
05606 }
05607
05608 if (!strcmp(l->name,myrpt->cmdnode))
05609 {
05610 wf.data.ptr = str;
05611 if (l->chan) ast_write(l->chan,&wf);
05612 return;
05613 }
05614 l = l->next;
05615 }
05616 l = myrpt->links.next;
05617
05618 while(l != &myrpt->links)
05619 {
05620 wf.data.ptr = str;
05621 if (l->chan) ast_write(l->chan,&wf);
05622 l = l->next;
05623 }
05624 return;
05625 }
05626
05627 static void send_link_keyquery(struct rpt *myrpt)
05628 {
05629 char str[300];
05630 struct ast_frame wf;
05631 struct rpt_link *l;
05632
05633 rpt_mutex_lock(&myrpt->lock);
05634 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05635 myrpt->topkeystate = 1;
05636 time(&myrpt->topkeytime);
05637 rpt_mutex_unlock(&myrpt->lock);
05638 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05639 wf.frametype = AST_FRAME_TEXT;
05640 wf.subclass = 0;
05641 wf.offset = 0;
05642 wf.mallocd = 0;
05643 wf.datalen = strlen(str) + 1;
05644 wf.samples = 0;
05645 l = myrpt->links.next;
05646
05647 while(l != &myrpt->links)
05648 {
05649 wf.data.ptr = str;
05650 if (l->chan) ast_write(l->chan,&wf);
05651 l = l->next;
05652 }
05653 return;
05654 }
05655
05656
05657
05658 static void send_newkey(struct ast_channel *chan)
05659 {
05660
05661
05662 ast_sendtext(chan,newkeystr);
05663 return;
05664 }
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05679 {
05680 char *val, *s, *s1, *s2, *tele;
05681 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05682 char tmp[300], deststr[300] = "",modechange = 0;
05683 char sx[320],*sy;
05684 struct rpt_link *l;
05685 int reconnects = 0;
05686 int i,n;
05687 struct dahdi_confinfo ci;
05688
05689 val = node_lookup(myrpt,node);
05690 if (!val){
05691 if(strlen(node) >= myrpt->longestnode)
05692 return -1;
05693 return 1;
05694 }
05695
05696 if(!strcmp(myrpt->name,node))
05697 return -2;
05698
05699 if(debug > 3){
05700 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05701 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05702 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05703 }
05704
05705 strncpy(tmp,val,sizeof(tmp) - 1);
05706 s = tmp;
05707 s1 = strsep(&s,",");
05708 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05709 {
05710 sy = strchr(s1,'/');
05711 *sy = 0;
05712 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05713 s1 = sx;
05714 }
05715 s2 = strsep(&s,",");
05716 rpt_mutex_lock(&myrpt->lock);
05717 l = myrpt->links.next;
05718
05719 while(l != &myrpt->links){
05720 if (l->name[0] == '0')
05721 {
05722 l = l->next;
05723 continue;
05724 }
05725
05726 if (!strcmp(l->name, node))
05727 break;
05728 l = l->next;
05729 }
05730
05731 if (l != &myrpt->links){
05732
05733 if ((l->mode) || (!l->chan)) {
05734 rpt_mutex_unlock(&myrpt->lock);
05735 return 2;
05736 }
05737 reconnects = l->reconnects;
05738 rpt_mutex_unlock(&myrpt->lock);
05739 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05740 l->retries = l->max_retries + 1;
05741 l->disced = 2;
05742 modechange = 1;
05743 } else
05744 {
05745 __mklinklist(myrpt,NULL,lstr);
05746 rpt_mutex_unlock(&myrpt->lock);
05747 n = finddelim(lstr,strs,MAXLINKLIST);
05748 for(i = 0; i < n; i++)
05749 {
05750 if ((*strs[i] < '0') ||
05751 (*strs[i] > '9')) strs[i]++;
05752 if (!strcmp(strs[i],node))
05753 {
05754 return 2;
05755 }
05756 }
05757 }
05758 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05759
05760 l = ast_malloc(sizeof(struct rpt_link));
05761 if (!l)
05762 {
05763 ast_log(LOG_WARNING, "Unable to malloc\n");
05764 return -1;
05765 }
05766
05767 memset((char *)l,0,sizeof(struct rpt_link));
05768 l->mode = mode;
05769 l->outbound = 1;
05770 l->thisconnected = 0;
05771 voxinit_link(l,1);
05772 strncpy(l->name, node, MAXNODESTR - 1);
05773 l->isremote = (s && ast_true(s));
05774 if (modechange) l->connected = 1;
05775 l->hasconnected = l->perma = perma;
05776 #ifdef ALLOW_LOCAL_CHANNELS
05777 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05778 strncpy(deststr, s1, sizeof(deststr));
05779 else
05780 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05781 #else
05782 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05783 #endif
05784 tele = strchr(deststr, '/');
05785 if (!tele){
05786 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05787 ast_free(l);
05788 return -1;
05789 }
05790 *tele++ = 0;
05791 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
05792 if (l->chan){
05793 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05794 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05795 #ifdef AST_CDR_FLAG_POST_DISABLED
05796 if (l->chan->cdr)
05797 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05798 #endif
05799 #ifndef NEW_ASTERISK
05800 l->chan->whentohangup = 0;
05801 #endif
05802 l->chan->appl = "Apprpt";
05803 l->chan->data = "(Remote Rx)";
05804 if (debug > 3)
05805 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05806 deststr, tele, l->chan->name);
05807 if(l->chan->cid.cid_num)
05808 ast_free(l->chan->cid.cid_num);
05809 l->chan->cid.cid_num = ast_strdup(myrpt->name);
05810 ast_call(l->chan,tele,999);
05811 }
05812 else {
05813 if(debug > 3)
05814 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05815 deststr,tele,l->chan->name);
05816 if (myrpt->p.archivedir)
05817 {
05818 char str[100];
05819 sprintf(str,"LINKFAIL,%s",l->name);
05820 donodelog(myrpt,str);
05821 }
05822 ast_free(l);
05823 return -1;
05824 }
05825
05826 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05827 if (!l->pchan){
05828 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05829 ast_hangup(l->chan);
05830 ast_free(l);
05831 return -1;
05832 }
05833 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05834 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05835 #ifdef AST_CDR_FLAG_POST_DISABLED
05836 if (l->pchan->cdr)
05837 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05838 #endif
05839
05840 ci.chan = 0;
05841 ci.confno = myrpt->conf;
05842 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05843
05844 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05845 {
05846 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05847 ast_hangup(l->chan);
05848 ast_hangup(l->pchan);
05849 ast_free(l);
05850 return -1;
05851 }
05852 rpt_mutex_lock(&myrpt->lock);
05853 l->reconnects = reconnects;
05854
05855 l->max_retries = MAX_RETRIES;
05856 if (perma)
05857 l->max_retries = MAX_RETRIES_PERM;
05858 if (l->isremote) l->retries = l->max_retries + 1;
05859 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05860 __kickshort(myrpt);
05861 rpt_mutex_unlock(&myrpt->lock);
05862 if (!l->phonemode) send_newkey(l->chan);
05863 return 0;
05864 }
05865
05866
05867
05868
05869
05870
05871
05872 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05873 {
05874
05875 char *val, *s, *s1, *s2;
05876 char tmp[300];
05877 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05878 char mode,perma;
05879 char sx[320],*sy;
05880 struct rpt_link *l;
05881 int i,r;
05882
05883 if(!param)
05884 return DC_ERROR;
05885
05886
05887 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05888 return DC_ERROR;
05889
05890 strncpy(digitbuf,digits,MAXNODESTR - 1);
05891
05892 if(debug > 6)
05893 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05894
05895 switch(myatoi(param)){
05896 case 11:
05897 case 1:
05898 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05899 strcpy(digitbuf,myrpt->lastlinknode);
05900 val = node_lookup(myrpt,digitbuf);
05901 if (!val){
05902 if(strlen(digitbuf) >= myrpt->longestnode)
05903 return DC_ERROR;
05904 break;
05905 }
05906 strncpy(tmp,val,sizeof(tmp) - 1);
05907 s = tmp;
05908 s1 = strsep(&s,",");
05909 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05910 {
05911 sy = strchr(s1,'/');
05912 *sy = 0;
05913 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05914 s1 = sx;
05915 }
05916 s2 = strsep(&s,",");
05917 rpt_mutex_lock(&myrpt->lock);
05918 l = myrpt->links.next;
05919
05920 while(l != &myrpt->links){
05921 if (l->name[0] == '0')
05922 {
05923 l = l->next;
05924 continue;
05925 }
05926
05927 if (!strcmp(l->name, digitbuf))
05928 break;
05929 l = l->next;
05930 }
05931 if (l != &myrpt->links){
05932 struct ast_frame wf;
05933
05934
05935 if ((myatoi(param) < 10) &&
05936 (l->max_retries > MAX_RETRIES))
05937 {
05938 rpt_mutex_unlock(&myrpt->lock);
05939 return DC_COMPLETE;
05940 }
05941 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05942 l->retries = l->max_retries + 1;
05943 l->disced = 1;
05944 rpt_mutex_unlock(&myrpt->lock);
05945 wf.frametype = AST_FRAME_TEXT;
05946 wf.subclass = 0;
05947 wf.offset = 0;
05948 wf.mallocd = 0;
05949 wf.datalen = strlen(discstr) + 1;
05950 wf.samples = 0;
05951 wf.data.ptr = discstr;
05952 if (l->chan)
05953 {
05954 ast_write(l->chan,&wf);
05955 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05956 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05957 }
05958 rpt_telemetry(myrpt, COMPLETE, NULL);
05959 return DC_COMPLETE;
05960 }
05961 rpt_mutex_unlock(&myrpt->lock);
05962 return DC_COMPLETE;
05963 case 2:
05964 case 3:
05965 case 12:
05966 case 13:
05967 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05968 strcpy(digitbuf,myrpt->lastlinknode);
05969
05970 perma = (atoi(param) > 10) ? 1 : 0;
05971 mode = (atoi(param) & 1) ? 1 : 0;
05972 r = connect_link(myrpt, digitbuf, mode, perma);
05973 switch(r){
05974 case -2:
05975 return DC_COMPLETE;
05976
05977 case 0:
05978 rpt_telemetry(myrpt, COMPLETE, NULL);
05979 return DC_COMPLETE;
05980
05981 case 1:
05982 break;
05983
05984 case 2:
05985 rpt_telemetry(myrpt, REMALREADY, NULL);
05986 return DC_COMPLETE;
05987
05988 default:
05989 rpt_telemetry(myrpt, CONNFAIL, NULL);
05990 return DC_COMPLETE;
05991 }
05992 break;
05993
05994 case 4:
05995
05996
05997 if (((command_source != SOURCE_RPT) &&
05998 (command_source != SOURCE_PHONE) &&
05999 (command_source != SOURCE_ALT) &&
06000 (command_source != SOURCE_DPHONE)) ||
06001 (myrpt->links.next == &myrpt->links))
06002 return DC_COMPLETE;
06003
06004
06005 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06006
06007 rpt_telemetry(myrpt, REMALREADY, NULL);
06008 return DC_COMPLETE;
06009 }
06010 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06011 strcpy(digitbuf,myrpt->lastlinknode);
06012
06013 val = node_lookup(myrpt,digitbuf);
06014 if (!val){
06015 if(strlen(digitbuf) >= myrpt->longestnode)
06016 return DC_ERROR;
06017 break;
06018
06019 }
06020 rpt_mutex_lock(&myrpt->lock);
06021 strcpy(myrpt->lastlinknode,digitbuf);
06022 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06023 rpt_mutex_unlock(&myrpt->lock);
06024 rpt_telemetry(myrpt, REMGO, NULL);
06025 return DC_COMPLETE;
06026
06027 case 5:
06028 rpt_telemetry(myrpt, STATUS, NULL);
06029 return DC_COMPLETE;
06030
06031 case 15:
06032 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06033 return DC_COMPLETE;
06034
06035
06036 case 6:
06037 rpt_mutex_lock(&myrpt->lock);
06038 myrpt->savednodes[0] = 0;
06039 l = myrpt->links.next;
06040
06041 while(l != &myrpt->links){
06042 struct ast_frame wf;
06043 if (l->name[0] == '0')
06044 {
06045 l = l->next;
06046 continue;
06047 }
06048
06049 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06050 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06051 if(myrpt->savednodes[0])
06052 strcat(myrpt->savednodes, ",");
06053 strcat(myrpt->savednodes, tmp);
06054 }
06055 l->retries = l->max_retries + 1;
06056 l->disced = 2;
06057 rpt_mutex_unlock(&myrpt->lock);
06058
06059
06060 wf.frametype = AST_FRAME_TEXT;
06061 wf.subclass = 0;
06062 wf.offset = 0;
06063 wf.mallocd = 0;
06064 wf.datalen = strlen(discstr) + 1;
06065 wf.samples = 0;
06066 wf.data.ptr = discstr;
06067 if (l->chan)
06068 {
06069 ast_write(l->chan,&wf);
06070 ast_safe_sleep(l->chan,250);
06071 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06072 }
06073 rpt_mutex_lock(&myrpt->lock);
06074 l = l->next;
06075 }
06076 rpt_mutex_unlock(&myrpt->lock);
06077 if(debug > 3)
06078 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06079 rpt_telemetry(myrpt, COMPLETE, NULL);
06080 return DC_COMPLETE;
06081
06082 case 7:
06083 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06084 break;
06085
06086
06087 #ifdef _MDC_DECODE_H_
06088 case 8:
06089 myrpt->lastunit = 0xd00d;
06090 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06091 mdc1200_send(myrpt,myrpt->lastunit);
06092 break;
06093 #endif
06094
06095 case 16:
06096 strcpy(tmp, myrpt->savednodes);
06097 finddelim(tmp, strs, MAXLINKLIST);
06098 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06099 s1 = strs[i];
06100 mode = (s1[0] == 'X') ? 1 : 0;
06101 perma = (s1[1] == 'P') ? 1 : 0;
06102 connect_link(myrpt, s1 + 2, mode, perma);
06103 }
06104 rpt_telemetry(myrpt, COMPLETE, NULL);
06105 break;
06106
06107 case 200:
06108 case 201:
06109 case 202:
06110 case 203:
06111 case 204:
06112 case 205:
06113 case 206:
06114 case 207:
06115 case 208:
06116 case 209:
06117 case 210:
06118 case 211:
06119 case 212:
06120 case 213:
06121 case 214:
06122 case 215:
06123 if (((myrpt->p.propagate_dtmf) &&
06124 (command_source == SOURCE_LNK)) ||
06125 ((myrpt->p.propagate_phonedtmf) &&
06126 ((command_source == SOURCE_PHONE) ||
06127 (command_source == SOURCE_ALT) ||
06128 (command_source == SOURCE_DPHONE))))
06129 do_dtmf_local(myrpt,
06130 remdtmfstr[myatoi(param) - 200]);
06131 default:
06132 return DC_ERROR;
06133
06134 }
06135
06136 return DC_INDETERMINATE;
06137 }
06138
06139
06140
06141
06142
06143 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06144 {
06145 pthread_attr_t attr;
06146 int i, idx, paramlength;
06147 char *lparam;
06148 char *value = NULL;
06149 char *paramlist[20];
06150
06151 static char *keywords[] = {
06152 "context",
06153 "dialtime",
06154 "farenddisconnect",
06155 "noct",
06156 "quiet",
06157 NULL
06158 };
06159
06160 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06161 return DC_ERROR;
06162
06163 if(debug)
06164 printf("@@@@ Autopatch up\n");
06165
06166 if(!myrpt->callmode){
06167
06168 myrpt->patchnoct = 0;
06169 myrpt->patchdialtime = 0;
06170 myrpt->patchfarenddisconnect = 0;
06171 myrpt->patchquiet = 0;
06172 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06173
06174 if(param){
06175
06176 lparam = ast_strdup(param);
06177 if(!lparam){
06178 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06179 return DC_ERROR;
06180 }
06181 paramlength = finddelim(lparam, paramlist, 20);
06182 for(i = 0; i < paramlength; i++){
06183 idx = matchkeyword(paramlist[i], &value, keywords);
06184 if(value)
06185 value = skipchars(value, "= ");
06186 switch(idx){
06187
06188 case 1:
06189 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06190 break;
06191
06192 case 2:
06193 myrpt->patchdialtime = atoi(value);
06194 break;
06195
06196 case 3:
06197 myrpt->patchfarenddisconnect = atoi(value);
06198 break;
06199
06200 case 4:
06201 myrpt->patchnoct = atoi(value);
06202 break;
06203
06204 case 5:
06205 myrpt->patchquiet = atoi(value);
06206 break;
06207
06208 default:
06209 break;
06210 }
06211 }
06212 ast_free(lparam);
06213 }
06214 }
06215
06216 rpt_mutex_lock(&myrpt->lock);
06217
06218
06219
06220 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06221 myrpt->mydtmf = myrpt->p.endchar;
06222 }
06223 if (myrpt->callmode){
06224 rpt_mutex_unlock(&myrpt->lock);
06225 return DC_COMPLETE;
06226 }
06227 myrpt->callmode = 1;
06228 myrpt->cidx = 0;
06229 myrpt->exten[myrpt->cidx] = 0;
06230 rpt_mutex_unlock(&myrpt->lock);
06231 pthread_attr_init(&attr);
06232 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06233 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06234 return DC_COMPLETE;
06235 }
06236
06237
06238
06239
06240
06241 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06242 {
06243 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06244 return DC_ERROR;
06245
06246 if(debug)
06247 printf("@@@@ Autopatch down\n");
06248
06249 rpt_mutex_lock(&myrpt->lock);
06250
06251 myrpt->macropatch=0;
06252
06253 if (!myrpt->callmode){
06254 rpt_mutex_unlock(&myrpt->lock);
06255 return DC_COMPLETE;
06256 }
06257
06258 myrpt->callmode = 0;
06259 channel_revert(myrpt);
06260 rpt_mutex_unlock(&myrpt->lock);
06261 rpt_telemetry(myrpt, TERM, NULL);
06262 return DC_COMPLETE;
06263 }
06264
06265
06266
06267
06268
06269 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06270 {
06271
06272 if (!param)
06273 return DC_ERROR;
06274
06275 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06276 return DC_ERROR;
06277
06278 if(debug)
06279 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06280
06281 switch(myatoi(param)){
06282 case 1:
06283 rpt_telemetry(myrpt, ID1, NULL);
06284 return DC_COMPLETE;
06285 case 2:
06286 rpt_telemetry(myrpt, STATS_TIME, NULL);
06287 return DC_COMPLETE;
06288 case 3:
06289 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06290 return DC_COMPLETE;
06291 case 11:
06292 rpt_telemetry(myrpt, ID , NULL);
06293 return DC_COMPLETE;
06294 case 12:
06295 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06296 return DC_COMPLETE;
06297 default:
06298 return DC_ERROR;
06299 }
06300 return DC_INDETERMINATE;
06301 }
06302
06303
06304
06305 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06306 {
06307 char *val;
06308 int i;
06309 if (myrpt->remote)
06310 return DC_ERROR;
06311
06312 if(debug)
06313 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06314
06315 if(strlen(digitbuf) < 1)
06316 return DC_INDETERMINATE;
06317
06318 for(i = 0 ; i < digitbuf[i] ; i++) {
06319 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06320 return DC_ERROR;
06321 }
06322
06323 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06324 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06325
06326 if (!val){
06327 if (strlen(digitbuf) < myrpt->macro_longest)
06328 return DC_INDETERMINATE;
06329 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06330 return DC_COMPLETE;
06331 }
06332 rpt_mutex_lock(&myrpt->lock);
06333 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06334 {
06335 rpt_mutex_unlock(&myrpt->lock);
06336 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06337 return DC_ERROR;
06338 }
06339 myrpt->macrotimer = MACROTIME;
06340 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06341 rpt_mutex_unlock(&myrpt->lock);
06342 return DC_COMPLETE;
06343 }
06344
06345
06346
06347
06348
06349 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06350 {
06351
06352 if (myrpt->remote)
06353 return DC_ERROR;
06354
06355 if(debug)
06356 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06357
06358 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06359 return DC_ERROR;
06360
06361 rpt_telemetry(myrpt,PLAYBACK,param);
06362 return DC_COMPLETE;
06363 }
06364
06365
06366
06367
06368
06369 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06370 {
06371 char string[16];
06372 int res;
06373
06374 int i, r;
06375
06376 if(!param)
06377 return DC_ERROR;
06378
06379 switch(myatoi(param)){
06380 case 1:
06381 res = system("killall -9 asterisk");
06382 return DC_COMPLETE;
06383
06384 case 2:
06385 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06386 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06387 return DC_COMPLETE;
06388
06389 case 3:
06390 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06391 return DC_COMPLETE;
06392
06393 case 4:
06394 if (myrpt->stopgen < 0)
06395 {
06396 myrpt->stopgen = 1;
06397 }
06398 else
06399 {
06400 myrpt->stopgen = 0;
06401 rpt_telemetry(myrpt, TEST_TONE, NULL);
06402 }
06403 return DC_COMPLETE;
06404
06405 case 5:
06406 myrpt->disgorgetime = time(NULL) + 10;
06407 return DC_COMPLETE;
06408
06409 case 6:
06410 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06411 return DC_DOKEY;
06412
06413
06414 case 7:
06415 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06416 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06417 return DC_COMPLETE;
06418
06419 case 8:
06420 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06421 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06422 return DC_COMPLETE;
06423
06424 case 9:
06425 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06426 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06427 return DC_COMPLETE;
06428
06429 case 10:
06430 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06431 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06432 return DC_COMPLETE;
06433
06434 case 11:
06435 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06436 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06437 return DC_COMPLETE;
06438
06439 case 12:
06440 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06441 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06442 return DC_COMPLETE;
06443
06444 case 13:
06445 string[0] = string[1] = 'S';
06446 string[2] = myrpt->p.sysstate_cur + '0';
06447 string[3] = '\0';
06448 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06449 return DC_COMPLETE;
06450
06451 case 14:
06452 if(strlen(digitbuf) == 0)
06453 break;
06454 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06455 return DC_ERROR;
06456 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06457 string[0] = string[1] = 'S';
06458 string[2] = myrpt->p.sysstate_cur + '0';
06459 string[3] = '\0';
06460 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06461 return DC_COMPLETE;
06462
06463 case 15:
06464 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06465 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06466 return DC_COMPLETE;
06467
06468 case 16:
06469 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06470 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06471 return DC_COMPLETE;
06472
06473 case 17:
06474 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06475 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06476 return DC_COMPLETE;
06477
06478 case 18:
06479 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06480 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06481 return DC_COMPLETE;
06482
06483 case 19:
06484 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06485 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06486 return DC_COMPLETE;
06487
06488 case 20:
06489 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06490 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06491 return DC_COMPLETE;
06492
06493 case 21:
06494 birdbath(myrpt);
06495 if (myrpt->p.parrotmode < 2)
06496 {
06497 myrpt->p.parrotmode = 0;
06498 rpt_telemetry(myrpt,COMPLETE,NULL);
06499 return DC_COMPLETE;
06500 }
06501 break;
06502
06503 case 22:
06504 birdbath(myrpt);
06505 if (myrpt->p.parrotmode < 2)
06506 {
06507 myrpt->p.parrotmode = 1;
06508 rpt_telemetry(myrpt,COMPLETE,NULL);
06509 return DC_COMPLETE;
06510 }
06511 break;
06512 case 23:
06513 birdbath(myrpt);
06514 rpt_telemetry(myrpt,COMPLETE,NULL);
06515 return DC_COMPLETE;
06516 case 24:
06517 flush_telem(myrpt);
06518 rpt_telemetry(myrpt,COMPLETE,NULL);
06519 return DC_COMPLETE;
06520 case 25:
06521 send_link_keyquery(myrpt);
06522 myrpt->topkeylong = 0;
06523 rpt_telemetry(myrpt,COMPLETE,NULL);
06524 return DC_COMPLETE;
06525 case 26:
06526 send_link_keyquery(myrpt);
06527 myrpt->topkeylong = 1;
06528 rpt_telemetry(myrpt,COMPLETE,NULL);
06529 return DC_COMPLETE;
06530
06531 case 30:
06532
06533 if(strlen(digitbuf) < 2)
06534 break;
06535
06536 for(i = 0 ; i < 2 ; i++){
06537 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06538 return DC_ERROR;
06539 }
06540
06541 r = retreive_memory(myrpt, digitbuf);
06542 if (r < 0){
06543 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06544 return DC_COMPLETE;
06545 }
06546 if (r > 0){
06547 return DC_ERROR;
06548 }
06549 if (setrem(myrpt) == -1) return DC_ERROR;
06550 return DC_COMPLETE;
06551
06552 case 31:
06553
06554
06555 if(strlen(digitbuf) < 2)
06556 break;
06557
06558 for(i = 0 ; i < 2 ; i++){
06559 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06560 return DC_ERROR;
06561 }
06562 channel_steer(myrpt,digitbuf);
06563 return DC_COMPLETE;
06564
06565 case 32:
06566 i = strlen(digitbuf);
06567 if(!i){
06568 if(debug > 3)
06569 ast_log(LOG_NOTICE,"Padtest entered");
06570 myrpt->inpadtest = 1;
06571 }
06572 else{
06573 if(debug > 3)
06574 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06575 if(digitbuf[i-1] != myrpt->p.endchar)
06576 break;
06577 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06578 myrpt->inpadtest = 0;
06579 if(debug > 3)
06580 ast_log(LOG_NOTICE,"Padtest exited");
06581 return DC_COMPLETE;
06582 }
06583 }
06584 return DC_INDETERMINATE;
06585 }
06586
06587
06588
06589 static int collect_function_digits(struct rpt *myrpt, char *digits,
06590 int command_source, struct rpt_link *mylink)
06591 {
06592 int i,rv;
06593 char *stringp,*action,*param,*functiondigits;
06594 char function_table_name[30] = "";
06595 char workstring[200];
06596
06597 struct ast_variable *vp;
06598
06599 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06600
06601
06602
06603
06604 if (command_source == SOURCE_DPHONE) {
06605 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06606 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06607 }
06608 else if (command_source == SOURCE_ALT) {
06609 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06610 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06611 }
06612 else if (command_source == SOURCE_PHONE) {
06613 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06614 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06615 }
06616 else if (command_source == SOURCE_LNK)
06617 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06618 else
06619 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06620
06621 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06622 while(vp) {
06623 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06624 break;
06625 vp = vp->next;
06626 }
06627
06628 if(!vp) {
06629 int n;
06630
06631 n = myrpt->longestfunc;
06632 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06633 else
06634 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06635 else
06636 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06637 else
06638 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06639
06640 if(strlen(digits) >= n)
06641 return DC_ERROR;
06642 else
06643 return DC_INDETERMINATE;
06644 }
06645
06646 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06647 stringp = workstring;
06648 action = strsep(&stringp, ",");
06649 param = stringp;
06650 if(debug)
06651 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06652
06653 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06654 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06655 break;
06656 }
06657 if(debug)
06658 printf("@@@@ table index i = %d\n",i);
06659 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06660
06661 return DC_ERROR;
06662 }
06663 if(function_table[i].function == NULL){
06664
06665 if(debug)
06666 printf("@@@@ NULL for action: %s\n",action);
06667 return DC_ERROR;
06668 }
06669 functiondigits = digits + strlen(vp->name);
06670 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06671 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06672 return(rv);
06673 }
06674
06675
06676 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06677 char *str)
06678 {
06679
06680
06681 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06682 int i,seq, res, ts;
06683 struct rpt_link *l;
06684 struct ast_frame wf;
06685
06686 wf.frametype = AST_FRAME_TEXT;
06687 wf.subclass = 0;
06688 wf.offset = 0;
06689 wf.mallocd = 0;
06690 wf.datalen = strlen(str) + 1;
06691 wf.samples = 0;
06692
06693 strncpy(tmp,str,sizeof(tmp) - 1);
06694
06695 if (!strcmp(tmp,discstr))
06696 {
06697 mylink->disced = 1;
06698 mylink->retries = mylink->max_retries + 1;
06699 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06700 return;
06701 }
06702 if (!strcmp(tmp,newkeystr))
06703 {
06704 mylink->newkey = 1;
06705 return;
06706 }
06707 if (tmp[0] == 'L')
06708 {
06709 rpt_mutex_lock(&myrpt->lock);
06710 strcpy(mylink->linklist,tmp + 2);
06711 time(&mylink->linklistreceived);
06712 rpt_mutex_unlock(&myrpt->lock);
06713 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06714 myrpt->name,tmp,mylink->name);
06715 return;
06716 }
06717 if (tmp[0] == 'K')
06718 {
06719 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06720 {
06721 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06722 return;
06723 }
06724 if (dest[0] == '0')
06725 {
06726 strcpy(dest,myrpt->name);
06727 }
06728
06729 if (strcmp(dest,myrpt->name))
06730 {
06731 l = myrpt->links.next;
06732
06733 while(l != &myrpt->links)
06734 {
06735 if (l->name[0] == '0')
06736 {
06737 l = l->next;
06738 continue;
06739 }
06740
06741 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06742 {
06743 l = l->next;
06744 continue;
06745 }
06746
06747 if (!strcmp(l->name,dest))
06748 {
06749
06750 if (strcmp(l->name,src)) {
06751 wf.data.ptr = str;
06752 if (l->chan) ast_write(l->chan,&wf);
06753 }
06754 return;
06755 }
06756 l = l->next;
06757 }
06758 }
06759
06760 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06761 {
06762 l = myrpt->links.next;
06763
06764 while(l != &myrpt->links)
06765 {
06766 if (l->name[0] == '0')
06767 {
06768 l = l->next;
06769 continue;
06770 }
06771
06772 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06773 {
06774 l = l->next;
06775 continue;
06776 }
06777
06778 if (strcmp(l->name,src)) {
06779 wf.data.ptr = str;
06780 if (l->chan) ast_write(l->chan,&wf);
06781 }
06782 l = l->next;
06783 }
06784 }
06785
06786 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06787 if (cmd[1] == '?')
06788 {
06789 time_t now;
06790 int n = 0;
06791
06792 time(&now);
06793 if (myrpt->lastkeyedtime)
06794 {
06795 n = (int)(now - myrpt->lastkeyedtime);
06796 }
06797 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06798 wf.data.ptr = tmp1;
06799 wf.datalen = strlen(tmp1) + 1;
06800 if (mylink->chan) ast_write(mylink->chan,&wf);
06801 return;
06802 }
06803 if (myrpt->topkeystate != 1) return;
06804 rpt_mutex_lock(&myrpt->lock);
06805 for(i = 0; i < TOPKEYN; i++)
06806 {
06807 if (!strcmp(myrpt->topkey[i].node,src)) break;
06808 }
06809 if (i >= TOPKEYN)
06810 {
06811 for(i = 0; i < TOPKEYN; i++)
06812 {
06813 if (!myrpt->topkey[i].node[0]) break;
06814 }
06815 }
06816 if (i < TOPKEYN)
06817 {
06818 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06819 myrpt->topkey[i].timesince = ts;
06820 myrpt->topkey[i].keyed = seq;
06821 }
06822 rpt_mutex_unlock(&myrpt->lock);
06823 return;
06824 }
06825 if (tmp[0] == 'I')
06826 {
06827
06828
06829 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06830 {
06831 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06832 return;
06833 }
06834 mdc1200_notify(myrpt,src,seq);
06835 strcpy(dest,"*");
06836 }
06837 else
06838 {
06839
06840
06841 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06842 {
06843 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06844 return;
06845 }
06846 if (strcmp(cmd,"D"))
06847 {
06848 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06849 return;
06850 }
06851 }
06852 if (dest[0] == '0')
06853 {
06854 strcpy(dest,myrpt->name);
06855 }
06856
06857
06858 if (strcmp(dest,myrpt->name))
06859 {
06860 l = myrpt->links.next;
06861
06862 while(l != &myrpt->links)
06863 {
06864 if (l->name[0] == '0')
06865 {
06866 l = l->next;
06867 continue;
06868 }
06869
06870 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06871 {
06872 l = l->next;
06873 continue;
06874 }
06875
06876 if (!strcmp(l->name,dest))
06877 {
06878
06879 if (strcmp(l->name,src)) {
06880 wf.data.ptr = str;
06881 if (l->chan) ast_write(l->chan,&wf);
06882 }
06883 return;
06884 }
06885 l = l->next;
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,src)) {
06904 wf.data.ptr = str;
06905 if (l->chan) ast_write(l->chan,&wf);
06906 }
06907 l = l->next;
06908 }
06909 return;
06910 }
06911 if (myrpt->p.archivedir)
06912 {
06913 char dtmfstr[100];
06914
06915 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06916 donodelog(myrpt,dtmfstr);
06917 }
06918 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06919 if (!c) return;
06920 rpt_mutex_lock(&myrpt->lock);
06921 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06922 if (myrpt->callmode == 1)
06923 {
06924 myrpt->exten[myrpt->cidx++] = c;
06925 myrpt->exten[myrpt->cidx] = 0;
06926
06927 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06928 {
06929
06930 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06931 myrpt->exten,1,NULL))
06932 {
06933 myrpt->callmode = 2;
06934 if(!myrpt->patchquiet)
06935 {
06936 rpt_mutex_unlock(&myrpt->lock);
06937 rpt_telemetry(myrpt,PROC,NULL);
06938 rpt_mutex_lock(&myrpt->lock);
06939 }
06940 }
06941 else
06942 {
06943 myrpt->calldigittimer = 1;
06944 }
06945 }
06946
06947 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06948 {
06949
06950 myrpt->callmode = 4;
06951 }
06952 }
06953 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06954 {
06955 myrpt->rem_dtmfidx = 0;
06956 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06957 time(&myrpt->rem_dtmf_time);
06958 rpt_mutex_unlock(&myrpt->lock);
06959 return;
06960 }
06961 else if (myrpt->rem_dtmfidx < 0)
06962 {
06963 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06964 {
06965 myrpt->mydtmf = c;
06966 }
06967 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06968 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06969 rpt_mutex_unlock(&myrpt->lock);
06970 return;
06971 }
06972 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06973 {
06974 time(&myrpt->rem_dtmf_time);
06975 if (myrpt->rem_dtmfidx < MAXDTMF)
06976 {
06977 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06978 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06979
06980 rpt_mutex_unlock(&myrpt->lock);
06981 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06982 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06983 rpt_mutex_lock(&myrpt->lock);
06984
06985 switch(res){
06986
06987 case DC_INDETERMINATE:
06988 break;
06989
06990 case DC_REQ_FLUSH:
06991 myrpt->rem_dtmfidx = 0;
06992 myrpt->rem_dtmfbuf[0] = 0;
06993 break;
06994
06995
06996 case DC_COMPLETE:
06997 case DC_COMPLETEQUIET:
06998 myrpt->totalexecdcommands++;
06999 myrpt->dailyexecdcommands++;
07000 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07001 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07002 myrpt->rem_dtmfbuf[0] = 0;
07003 myrpt->rem_dtmfidx = -1;
07004 myrpt->rem_dtmf_time = 0;
07005 break;
07006
07007 case DC_ERROR:
07008 default:
07009 myrpt->rem_dtmfbuf[0] = 0;
07010 myrpt->rem_dtmfidx = -1;
07011 myrpt->rem_dtmf_time = 0;
07012 break;
07013 }
07014 }
07015
07016 }
07017 rpt_mutex_unlock(&myrpt->lock);
07018 return;
07019 }
07020
07021 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07022 char c)
07023 {
07024
07025 char cmd[300];
07026 int res;
07027
07028 if (myrpt->p.archivedir)
07029 {
07030 char str[100];
07031
07032 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07033 donodelog(myrpt,str);
07034 }
07035 rpt_mutex_lock(&myrpt->lock);
07036
07037 if (mylink->phonemode == 3)
07038 {
07039 if(c == myrpt->p.endchar)
07040 {
07041 mylink->lastrealrx = 0;
07042 rpt_mutex_unlock(&myrpt->lock);
07043 return;
07044 }
07045
07046 if(c == myrpt->p.funcchar)
07047 {
07048 mylink->lastrealrx = !mylink->lastrealrx;
07049 rpt_mutex_unlock(&myrpt->lock);
07050 return;
07051 }
07052 }
07053 else
07054 {
07055 if (c == myrpt->p.endchar)
07056 {
07057 if (mylink->lastrx)
07058 {
07059 mylink->lastrealrx = 0;
07060 rpt_mutex_unlock(&myrpt->lock);
07061 return;
07062 }
07063 myrpt->stopgen = 1;
07064 if (myrpt->cmdnode[0])
07065 {
07066 myrpt->cmdnode[0] = 0;
07067 myrpt->dtmfidx = -1;
07068 myrpt->dtmfbuf[0] = 0;
07069 rpt_mutex_unlock(&myrpt->lock);
07070 rpt_telemetry(myrpt,COMPLETE,NULL);
07071 return;
07072 }
07073 }
07074 }
07075 if (myrpt->cmdnode[0])
07076 {
07077 rpt_mutex_unlock(&myrpt->lock);
07078 send_link_dtmf(myrpt,c);
07079 return;
07080 }
07081 if (myrpt->callmode == 1)
07082 {
07083 myrpt->exten[myrpt->cidx++] = c;
07084 myrpt->exten[myrpt->cidx] = 0;
07085
07086 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07087 {
07088
07089 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07090 myrpt->exten,1,NULL))
07091 {
07092 myrpt->callmode = 2;
07093 if(!myrpt->patchquiet)
07094 {
07095 rpt_mutex_unlock(&myrpt->lock);
07096 rpt_telemetry(myrpt,PROC,NULL);
07097 rpt_mutex_lock(&myrpt->lock);
07098 }
07099 }
07100 else
07101 {
07102 myrpt->calldigittimer = 1;
07103 }
07104 }
07105
07106 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07107 {
07108
07109 myrpt->callmode = 4;
07110 }
07111 }
07112 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07113 {
07114 myrpt->mydtmf = c;
07115 }
07116 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07117 {
07118 myrpt->rem_dtmfidx = 0;
07119 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07120 time(&myrpt->rem_dtmf_time);
07121 rpt_mutex_unlock(&myrpt->lock);
07122 return;
07123 }
07124 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07125 {
07126 time(&myrpt->rem_dtmf_time);
07127 if (myrpt->rem_dtmfidx < MAXDTMF)
07128 {
07129 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07130 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07131
07132 rpt_mutex_unlock(&myrpt->lock);
07133 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07134 switch(mylink->phonemode)
07135 {
07136 case 1:
07137 res = collect_function_digits(myrpt, cmd,
07138 SOURCE_PHONE, mylink);
07139 break;
07140 case 2:
07141 res = collect_function_digits(myrpt, cmd,
07142 SOURCE_DPHONE,mylink);
07143 break;
07144 case 4:
07145 res = collect_function_digits(myrpt, cmd,
07146 SOURCE_ALT,mylink);
07147 break;
07148 default:
07149 res = collect_function_digits(myrpt, cmd,
07150 SOURCE_LNK, mylink);
07151 break;
07152 }
07153
07154 rpt_mutex_lock(&myrpt->lock);
07155
07156 switch(res){
07157
07158 case DC_INDETERMINATE:
07159 break;
07160
07161 case DC_DOKEY:
07162 mylink->lastrealrx = 1;
07163 break;
07164
07165 case DC_REQ_FLUSH:
07166 myrpt->rem_dtmfidx = 0;
07167 myrpt->rem_dtmfbuf[0] = 0;
07168 break;
07169
07170
07171 case DC_COMPLETE:
07172 case DC_COMPLETEQUIET:
07173 myrpt->totalexecdcommands++;
07174 myrpt->dailyexecdcommands++;
07175 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07176 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07177 myrpt->rem_dtmfbuf[0] = 0;
07178 myrpt->rem_dtmfidx = -1;
07179 myrpt->rem_dtmf_time = 0;
07180 break;
07181
07182 case DC_ERROR:
07183 default:
07184 myrpt->rem_dtmfbuf[0] = 0;
07185 myrpt->rem_dtmfidx = -1;
07186 myrpt->rem_dtmf_time = 0;
07187 break;
07188 }
07189 }
07190
07191 }
07192 rpt_mutex_unlock(&myrpt->lock);
07193 return;
07194 }
07195
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226
07227 static int rbi_mhztoband(char *str)
07228 {
07229 int i;
07230
07231 i = atoi(str) / 10;
07232 switch(i)
07233 {
07234 case 2:
07235 return 10;
07236 case 5:
07237 return 11;
07238 case 14:
07239 return 2;
07240 case 22:
07241 return 3;
07242 case 44:
07243 return 4;
07244 case 124:
07245 return 0;
07246 case 125:
07247 return 1;
07248 case 126:
07249 return 8;
07250 case 127:
07251 return 5;
07252 case 128:
07253 return 6;
07254 case 129:
07255 return 7;
07256 default:
07257 break;
07258 }
07259 return -1;
07260 }
07261
07262
07263 static int rbi_pltocode(char *str)
07264 {
07265 int i;
07266 char *s;
07267
07268 s = strchr(str,'.');
07269 i = 0;
07270 if (s) i = atoi(s + 1);
07271 i += atoi(str) * 10;
07272 switch(i)
07273 {
07274 case 670:
07275 return 0;
07276 case 719:
07277 return 1;
07278 case 744:
07279 return 2;
07280 case 770:
07281 return 3;
07282 case 797:
07283 return 4;
07284 case 825:
07285 return 5;
07286 case 854:
07287 return 6;
07288 case 885:
07289 return 7;
07290 case 915:
07291 return 8;
07292 case 948:
07293 return 9;
07294 case 974:
07295 return 10;
07296 case 1000:
07297 return 11;
07298 case 1035:
07299 return 12;
07300 case 1072:
07301 return 13;
07302 case 1109:
07303 return 14;
07304 case 1148:
07305 return 15;
07306 case 1188:
07307 return 16;
07308 case 1230:
07309 return 17;
07310 case 1273:
07311 return 18;
07312 case 1318:
07313 return 19;
07314 case 1365:
07315 return 20;
07316 case 1413:
07317 return 21;
07318 case 1462:
07319 return 22;
07320 case 1514:
07321 return 23;
07322 case 1567:
07323 return 24;
07324 case 1622:
07325 return 25;
07326 case 1679:
07327 return 26;
07328 case 1738:
07329 return 27;
07330 case 1799:
07331 return 28;
07332 case 1862:
07333 return 29;
07334 case 1928:
07335 return 30;
07336 case 2035:
07337 return 31;
07338 case 2107:
07339 return 32;
07340 case 2181:
07341 return 33;
07342 case 2257:
07343 return 34;
07344 case 2336:
07345 return 35;
07346 case 2418:
07347 return 36;
07348 case 2503:
07349 return 37;
07350 }
07351 return -1;
07352 }
07353
07354
07355
07356
07357
07358 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07359 {
07360 #ifdef __i386__
07361 int i,j;
07362 unsigned char od,d;
07363 static volatile long long delayvar;
07364
07365 for(i = 0 ; i < 5 ; i++){
07366 od = *data++;
07367 for(j = 0 ; j < 8 ; j++){
07368 d = od & 1;
07369 outb(d,myrpt->p.iobase);
07370
07371 for(delayvar = 1; delayvar < 15000; delayvar++);
07372 od >>= 1;
07373 outb(d | 2,myrpt->p.iobase);
07374
07375 for(delayvar = 1; delayvar < 30000; delayvar++);
07376 outb(d,myrpt->p.iobase);
07377
07378 for(delayvar = 1; delayvar < 10000; delayvar++);
07379 }
07380 }
07381
07382 for(delayvar = 1; delayvar < 50000; delayvar++);
07383