00001
00002 #define OLDKEY
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 #define MAXDTMF 32
00156 #define MAXMACRO 2048
00157 #define MAXLINKLIST 512
00158 #define LINKLISTTIME 10000
00159 #define LINKLISTSHORTTIME 200
00160 #define MACROTIME 100
00161 #define MACROPTIME 500
00162 #define DTMF_TIMEOUT 3
00163 #define KENWOOD_RETRIES 5
00164
00165 #define AUTHTELLTIME 7000
00166 #define AUTHTXTIME 1000
00167 #define AUTHLOGOUTTIME 25000
00168
00169 #ifdef __RPT_NOTCH
00170 #define MAXFILTERS 10
00171 #endif
00172
00173 #define DISC_TIME 10000
00174 #define MAX_RETRIES 5
00175 #define MAX_RETRIES_PERM 1000000000
00176
00177 #define REDUNDANT_TX_TIME 2000
00178
00179 #define RETRY_TIMER_MS 5000
00180
00181 #define START_DELAY 2
00182
00183 #define MAXPEERSTR 31
00184 #define MAXREMSTR 15
00185
00186 #define DELIMCHR ','
00187 #define QUOTECHR 34
00188
00189 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00190
00191 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00192 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00193 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00194 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00195 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00196
00197 #define NODES "nodes"
00198 #define EXTNODES "extnodes"
00199 #define MEMORY "memory"
00200 #define MACRO "macro"
00201 #define FUNCTIONS "functions"
00202 #define TELEMETRY "telemetry"
00203 #define MORSE "morse"
00204 #define FUNCCHAR '*'
00205 #define ENDCHAR '#'
00206 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00207
00208 #define DEFAULT_IOBASE 0x378
00209
00210 #define DEFAULT_CIV_ADDR 0x58
00211
00212 #define MAXCONNECTTIME 5000
00213
00214 #define MAXNODESTR 300
00215
00216 #define MAXPATCHCONTEXT 100
00217
00218 #define ACTIONSIZE 32
00219
00220 #define TELEPARAMSIZE 256
00221
00222 #define REM_SCANTIME 100
00223
00224 #define DTMF_LOCAL_TIME 250
00225 #define DTMF_LOCAL_STARTTIME 500
00226
00227 #define IC706_PL_MEMORY_OFFSET 50
00228
00229 #define ALLOW_LOCAL_CHANNELS
00230
00231 enum {REM_OFF,REM_MONITOR,REM_TX};
00232
00233 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00234 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
00235 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00236 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00237 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00238 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE,
00239 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX};
00240
00241
00242 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00243
00244 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00245
00246 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00247
00248 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
00249
00250 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY};
00251
00252 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00253
00254 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00255 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00256
00257 #include "asterisk.h"
00258
00259 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 174369 $")
00260
00261 #include <signal.h>
00262 #include <stdio.h>
00263 #include <stdint.h>
00264 #include <unistd.h>
00265 #include <string.h>
00266 #include <stdlib.h>
00267 #include <search.h>
00268 #include <sys/types.h>
00269 #include <sys/stat.h>
00270 #include <errno.h>
00271 #include <dirent.h>
00272 #include <ctype.h>
00273 #include <sys/stat.h>
00274 #include <sys/time.h>
00275 #include <sys/file.h>
00276 #include <sys/ioctl.h>
00277 #ifdef HAVE_SYS_IO_H
00278 #include <sys/io.h>
00279 #endif
00280 #include <sys/vfs.h>
00281 #include <math.h>
00282 #include <netinet/in.h>
00283 #include <arpa/inet.h>
00284 #include <termios.h>
00285
00286 #include "asterisk/utils.h"
00287 #include "asterisk/lock.h"
00288 #include "asterisk/file.h"
00289 #include "asterisk/logger.h"
00290 #include "asterisk/channel.h"
00291 #include "asterisk/callerid.h"
00292 #include "asterisk/pbx.h"
00293 #include "asterisk/module.h"
00294 #include "asterisk/translate.h"
00295 #include "asterisk/features.h"
00296 #include "asterisk/options.h"
00297 #include "asterisk/cli.h"
00298 #include "asterisk/config.h"
00299 #include "asterisk/say.h"
00300 #include "asterisk/localtime.h"
00301 #include "asterisk/cdr.h"
00302 #include "asterisk/options.h"
00303
00304 #include "asterisk/dahdi_compat.h"
00305 #include "asterisk/tonezone_compat.h"
00306
00307
00308 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00309
00310 void ast_playtones_stop(struct ast_channel *chan);
00311
00312 static char *tdesc = "Radio Repeater / Remote Base version 0.73 09/04/2007";
00313
00314 static char *app = "Rpt";
00315
00316 static char *synopsis = "Radio Repeater/Remote Base Control System";
00317
00318 static char *descrip =
00319 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
00320 "\n"
00321 " Not specifying an option puts it in normal endpoint mode (where source\n"
00322 " IP and nodename are verified).\n"
00323 "\n"
00324 " Options are as follows:\n"
00325 "\n"
00326 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00327 " this if you have checked security already (like with an IAX2\n"
00328 " user/password or something).\n"
00329 "\n"
00330 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00331 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00332 " specified by the 'announce-string') is played on radio system.\n"
00333 " Users of radio system can access autopatch, dial specified\n"
00334 " code, and pick up call. Announce-string is list of names of\n"
00335 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00336 " or \"NODE\" to substitute node number.\n"
00337 "\n"
00338 " P - Phone Control mode. This allows a regular phone user to have\n"
00339 " full control and audio access to the radio system. For the\n"
00340 " user to have DTMF control, the 'phone_functions' parameter\n"
00341 " must be specified for the node in 'rpt.conf'. An additional\n"
00342 " function (cop,6) must be listed so that PTT control is available.\n"
00343 "\n"
00344 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00345 " have full control and audio access to the radio system. In this\n"
00346 " mode, the PTT is activated for the entire length of the call.\n"
00347 " For the user to have DTMF control (not generally recomended in\n"
00348 " this mode), the 'dphone_functions' parameter must be specified\n"
00349 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00350 " available to the phone user.\n"
00351 "\n";
00352
00353 static int debug = 0;
00354 static int nrpts = 0;
00355
00356 static char remdtmfstr[] = "0123456789*#ABCD";
00357
00358 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00359
00360 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00361
00362 #define NRPTSTAT 7
00363
00364 struct rpt_chan_stat
00365 {
00366 struct timeval last;
00367 long long total;
00368 unsigned long count;
00369 unsigned long largest;
00370 struct timeval largest_time;
00371 };
00372
00373 char *discstr = "!!DISCONNECT!!";
00374 static char *remote_rig_ft897="ft897";
00375 static char *remote_rig_rbi="rbi";
00376 static char *remote_rig_kenwood="kenwood";
00377 static char *remote_rig_ic706="ic706";
00378
00379 #ifdef OLD_ASTERISK
00380 STANDARD_LOCAL_USER;
00381 LOCAL_USER_DECL;
00382 #endif
00383
00384 #define MSWAIT 200
00385 #define HANGTIME 5000
00386 #define TOTIME 180000
00387 #define IDTIME 300000
00388 #define MAXRPTS 20
00389 #define MAX_STAT_LINKS 32
00390 #define POLITEID 30000
00391 #define FUNCTDELAY 1500
00392
00393 #define MAXXLAT 20
00394 #define MAXXLATTIME 3
00395
00396 #define MAX_SYSSTATES 10
00397
00398 struct rpt_xlat
00399 {
00400 char funccharseq[MAXXLAT];
00401 char endcharseq[MAXXLAT];
00402 char passchars[MAXXLAT];
00403 int funcindex;
00404 int endindex;
00405 time_t lastone;
00406 } ;
00407
00408 static time_t starttime = 0;
00409
00410 static pthread_t rpt_master_thread;
00411
00412 struct rpt;
00413
00414 struct rpt_link
00415 {
00416 struct rpt_link *next;
00417 struct rpt_link *prev;
00418 char mode;
00419 char isremote;
00420 char phonemode;
00421 char name[MAXNODESTR];
00422 char lasttx;
00423 char lastrx;
00424 char lastrx1;
00425 char connected;
00426 char hasconnected;
00427 char perma;
00428 char thisconnected;
00429 char outbound;
00430 char disced;
00431 char killme;
00432 long elaptime;
00433 long disctime;
00434 long retrytimer;
00435 long retxtimer;
00436 long rerxtimer;
00437 int retries;
00438 int max_retries;
00439 int reconnects;
00440 long long connecttime;
00441 struct ast_channel *chan;
00442 struct ast_channel *pchan;
00443 char linklist[MAXLINKLIST];
00444 time_t linklistreceived;
00445 long linklisttimer;
00446 int dtmfed;
00447 int linkunkeytocttimer;
00448 struct ast_frame *lastf1,*lastf2;
00449 struct rpt_chan_stat chan_stat[NRPTSTAT];
00450 } ;
00451
00452 struct rpt_lstat
00453 {
00454 struct rpt_lstat *next;
00455 struct rpt_lstat *prev;
00456 char peer[MAXPEERSTR];
00457 char name[MAXNODESTR];
00458 char mode;
00459 char outbound;
00460 char reconnects;
00461 char thisconnected;
00462 long long connecttime;
00463 struct rpt_chan_stat chan_stat[NRPTSTAT];
00464 } ;
00465
00466 struct rpt_tele
00467 {
00468 struct rpt_tele *next;
00469 struct rpt_tele *prev;
00470 struct rpt *rpt;
00471 struct ast_channel *chan;
00472 int mode;
00473 struct rpt_link mylink;
00474 char param[TELEPARAMSIZE];
00475 intptr_t submode;
00476 pthread_t threadid;
00477 } ;
00478
00479 struct function_table_tag
00480 {
00481 char action[ACTIONSIZE];
00482 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00483 int command_source, struct rpt_link *mylink);
00484 } ;
00485
00486
00487
00488 struct morse_bits
00489 {
00490 int len;
00491 int ddcomb;
00492 } ;
00493
00494 struct telem_defaults
00495 {
00496 char name[20];
00497 char value[80];
00498 } ;
00499
00500
00501 struct sysstate
00502 {
00503 char txdisable;
00504 char totdisable;
00505 char linkfundisable;
00506 char autopatchdisable;
00507 char schedulerdisable;
00508 char userfundisable;
00509 char alternatetail;
00510 };
00511
00512 static struct rpt
00513 {
00514 ast_mutex_t lock;
00515 ast_mutex_t remlock;
00516 struct ast_config *cfg;
00517 char reload;
00518
00519 char *name;
00520 char *rxchanname;
00521 char *txchanname;
00522 char *remote;
00523 struct rpt_chan_stat chan_stat[NRPTSTAT];
00524 unsigned int scram;
00525
00526 struct {
00527 char *ourcontext;
00528 char *ourcallerid;
00529 char *acctcode;
00530 char *ident;
00531 char *tonezone;
00532 char simple;
00533 char *functions;
00534 char *link_functions;
00535 char *phone_functions;
00536 char *dphone_functions;
00537 char *nodes;
00538 char *extnodes;
00539 char *extnodefile;
00540 int hangtime;
00541 int althangtime;
00542 int totime;
00543 int idtime;
00544 int tailmessagetime;
00545 int tailsquashedtime;
00546 int duplex;
00547 int politeid;
00548 char *tailmessages[500];
00549 int tailmessagemax;
00550 char *memory;
00551 char *macro;
00552 char *startupmacro;
00553 int iobase;
00554 char *ioport;
00555 char funcchar;
00556 char endchar;
00557 char nobusyout;
00558 char notelemtx;
00559 char propagate_dtmf;
00560 char propagate_phonedtmf;
00561 char linktolink;
00562 unsigned char civaddr;
00563 struct rpt_xlat inxlat;
00564 struct rpt_xlat outxlat;
00565 char *archivedir;
00566 int authlevel;
00567 char *csstanzaname;
00568 char *skedstanzaname;
00569 char *txlimitsstanzaname;
00570 long monminblocks;
00571 int remoteinacttimeout;
00572 int remotetimeout;
00573 int remotetimeoutwarning;
00574 int remotetimeoutwarningfreq;
00575 int sysstate_cur;
00576 struct sysstate s[MAX_SYSSTATES];
00577 } p;
00578 struct rpt_link links;
00579 int unkeytocttimer;
00580 char keyed;
00581 char exttx;
00582 char localtx;
00583 char remoterx;
00584 char remotetx;
00585 char remoteon;
00586 char remtxfreqok;
00587 char tounkeyed;
00588 char tonotify;
00589 char dtmfbuf[MAXDTMF];
00590 char macrobuf[MAXMACRO];
00591 char rem_dtmfbuf[MAXDTMF];
00592 char lastdtmfcommand[MAXDTMF];
00593 char cmdnode[50];
00594 struct ast_channel *rxchannel,*txchannel, *monchannel;
00595 struct ast_channel *pchannel,*txpchannel, *zaprxchannel, *zaptxchannel;
00596 struct ast_frame *lastf1,*lastf2;
00597 struct rpt_tele tele;
00598 struct timeval lasttv,curtv;
00599 pthread_t rpt_call_thread,rpt_thread;
00600 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00601 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00602 int mustid,tailid;
00603 int tailevent;
00604 int telemrefcount;
00605 int dtmfidx,rem_dtmfidx;
00606 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00607 int totalexecdcommands, dailyexecdcommands;
00608 long retxtimer;
00609 long rerxtimer;
00610 long long totaltxtime;
00611 char mydtmf;
00612 char exten[AST_MAX_EXTENSION];
00613 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00614 char offset;
00615 char powerlevel;
00616 char txplon;
00617 char rxplon;
00618 char remmode;
00619 char tunerequest;
00620 char hfscanmode;
00621 int hfscanstatus;
00622 char hfscanstop;
00623 char lastlinknode[MAXNODESTR];
00624 char savednodes[MAXNODESTR];
00625 int stopgen;
00626 char patchfarenddisconnect;
00627 char patchnoct;
00628 char patchquiet;
00629 char patchcontext[MAXPATCHCONTEXT];
00630 int patchdialtime;
00631 int macro_longest;
00632 int phone_longestfunc;
00633 int dphone_longestfunc;
00634 int link_longestfunc;
00635 int longestfunc;
00636 int longestnode;
00637 int threadrestarts;
00638 int tailmessagen;
00639 time_t disgorgetime;
00640 time_t lastthreadrestarttime;
00641 long macrotimer;
00642 char lastnodewhichkeyedusup[MAXNODESTR];
00643 int dtmf_local_timer;
00644 char dtmf_local_str[100];
00645 struct ast_filestream *monstream;
00646 char loginuser[50];
00647 char loginlevel[10];
00648 long authtelltimer;
00649 long authtimer;
00650 int iofd;
00651 time_t start_time,last_activity_time;
00652 #ifdef __RPT_NOTCH
00653 struct rptfilter
00654 {
00655 char desc[100];
00656 float x0;
00657 float x1;
00658 float x2;
00659 float y0;
00660 float y1;
00661 float y2;
00662 float gain;
00663 float const0;
00664 float const1;
00665 float const2;
00666 } filters[MAXFILTERS];
00667 #endif
00668 #ifdef _MDC_DECODE_H_
00669 mdc_decoder_t *mdc;
00670 unsigned short lastunit;
00671 #endif
00672 } rpt_vars[MAXRPTS];
00673
00674 struct nodelog {
00675 struct nodelog *next;
00676 struct nodelog *prev;
00677 time_t timestamp;
00678 char archivedir[MAXNODESTR];
00679 char str[MAXNODESTR * 2];
00680 } nodelog;
00681
00682 static int service_scan(struct rpt *myrpt);
00683 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00684 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00685 static int simple_command_ft897(struct rpt *myrpt, char command);
00686 static int setrem(struct rpt *myrpt);
00687
00688 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00689
00690 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00691
00692 #ifdef APP_RPT_LOCK_DEBUG
00693
00694 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00695
00696 #define MAXLOCKTHREAD 100
00697
00698 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00699 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00700
00701 struct lockthread
00702 {
00703 pthread_t id;
00704 int lockcount;
00705 int lastlock;
00706 int lastunlock;
00707 } lockthreads[MAXLOCKTHREAD];
00708
00709
00710 struct by_lightning
00711 {
00712 int line;
00713 struct timeval tv;
00714 struct rpt *rpt;
00715 struct lockthread lockthread;
00716 } lock_ring[32];
00717
00718 int lock_ring_index = 0;
00719
00720 AST_MUTEX_DEFINE_STATIC(locklock);
00721
00722 static struct lockthread *get_lockthread(pthread_t id)
00723 {
00724 int i;
00725
00726 for(i = 0; i < MAXLOCKTHREAD; i++)
00727 {
00728 if (lockthreads[i].id == id) return(&lockthreads[i]);
00729 }
00730 return(NULL);
00731 }
00732
00733 static struct lockthread *put_lockthread(pthread_t id)
00734 {
00735 int i;
00736
00737 for(i = 0; i < MAXLOCKTHREAD; i++)
00738 {
00739 if (lockthreads[i].id == id)
00740 return(&lockthreads[i]);
00741 }
00742 for(i = 0; i < MAXLOCKTHREAD; i++)
00743 {
00744 if (!lockthreads[i].id)
00745 {
00746 lockthreads[i].lockcount = 0;
00747 lockthreads[i].lastlock = 0;
00748 lockthreads[i].lastunlock = 0;
00749 lockthreads[i].id = id;
00750 return(&lockthreads[i]);
00751 }
00752 }
00753 return(NULL);
00754 }
00755
00756
00757 static void rpt_mutex_spew(void)
00758 {
00759 struct by_lightning lock_ring_copy[32];
00760 int lock_ring_index_copy;
00761 int i,j;
00762 long long diff;
00763 char a[100];
00764 struct timeval lasttv;
00765
00766 ast_mutex_lock(&locklock);
00767 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00768 lock_ring_index_copy = lock_ring_index;
00769 ast_mutex_unlock(&locklock);
00770
00771 lasttv.tv_sec = lasttv.tv_usec = 0;
00772 for(i = 0 ; i < 32 ; i++)
00773 {
00774 j = (i + lock_ring_index_copy) % 32;
00775 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00776 localtime(&lock_ring_copy[j].tv.tv_sec));
00777 diff = 0;
00778 if(lasttv.tv_sec)
00779 {
00780 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00781 * 1000000;
00782 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00783 }
00784 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00785 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00786 if (!lock_ring_copy[j].tv.tv_sec) continue;
00787 if (lock_ring_copy[j].line < 0)
00788 {
00789 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00790 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);
00791 }
00792 else
00793 {
00794 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00795 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);
00796 }
00797 }
00798 }
00799
00800
00801 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
00802 {
00803 struct lockthread *t;
00804 pthread_t id;
00805
00806 id = pthread_self();
00807 ast_mutex_lock(&locklock);
00808 t = put_lockthread(id);
00809 if (!t)
00810 {
00811 ast_mutex_unlock(&locklock);
00812 return;
00813 }
00814 if (t->lockcount)
00815 {
00816 int lastline = t->lastlock;
00817 ast_mutex_unlock(&locklock);
00818 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);
00819 rpt_mutex_spew();
00820 return;
00821 }
00822 t->lastlock = line;
00823 t->lockcount = 1;
00824 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
00825 lock_ring[lock_ring_index].rpt = myrpt;
00826 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
00827 lock_ring[lock_ring_index++].line = line;
00828 if(lock_ring_index == 32)
00829 lock_ring_index = 0;
00830 ast_mutex_unlock(&locklock);
00831 ast_mutex_lock(lockp);
00832 }
00833
00834
00835 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
00836 {
00837 struct lockthread *t;
00838 pthread_t id;
00839
00840 id = pthread_self();
00841 ast_mutex_lock(&locklock);
00842 t = put_lockthread(id);
00843 if (!t)
00844 {
00845 ast_mutex_unlock(&locklock);
00846 return;
00847 }
00848 if (!t->lockcount)
00849 {
00850 int lastline = t->lastunlock;
00851 ast_mutex_unlock(&locklock);
00852 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);
00853 rpt_mutex_spew();
00854 return;
00855 }
00856 t->lastunlock = line;
00857 t->lockcount = 0;
00858 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
00859 lock_ring[lock_ring_index].rpt = myrpt;
00860 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
00861 lock_ring[lock_ring_index++].line = -line;
00862 if(lock_ring_index == 32)
00863 lock_ring_index = 0;
00864 ast_mutex_unlock(&locklock);
00865 ast_mutex_unlock(lockp);
00866 }
00867
00868 #else
00869
00870 #define rpt_mutex_lock(x) ast_mutex_lock(x)
00871 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
00872
00873 #endif
00874
00875
00876
00877
00878
00879 static int multimode_capable(struct rpt *myrpt)
00880 {
00881 if(!strcmp(myrpt->remote, remote_rig_ft897))
00882 return 1;
00883 if(!strcmp(myrpt->remote, remote_rig_ic706))
00884 return 1;
00885 return 0;
00886 }
00887
00888
00889
00890
00891
00892
00893 static int rpt_do_debug(int fd, int argc, char *argv[]);
00894 static int rpt_do_dump(int fd, int argc, char *argv[]);
00895 static int rpt_do_stats(int fd, int argc, char *argv[]);
00896 static int rpt_do_lstats(int fd, int argc, char *argv[]);
00897 static int rpt_do_nodes(int fd, int argc, char *argv[]);
00898 static int rpt_do_reload(int fd, int argc, char *argv[]);
00899 static int rpt_do_restart(int fd, int argc, char *argv[]);
00900 static int rpt_do_fun(int fd, int argc, char *argv[]);
00901
00902 static char debug_usage[] =
00903 "Usage: rpt debug level {0-7}\n"
00904 " Enables debug messages in app_rpt\n";
00905
00906 static char dump_usage[] =
00907 "Usage: rpt dump <nodename>\n"
00908 " Dumps struct debug info to log\n";
00909
00910 static char dump_stats[] =
00911 "Usage: rpt stats <nodename>\n"
00912 " Dumps node statistics to console\n";
00913
00914 static char dump_lstats[] =
00915 "Usage: rpt lstats <nodename>\n"
00916 " Dumps link statistics to console\n";
00917
00918 static char dump_nodes[] =
00919 "Usage: rpt nodes <nodename>\n"
00920 " Dumps a list of directly and indirectly connected nodes to the console\n";
00921
00922 static char reload_usage[] =
00923 "Usage: rpt reload\n"
00924 " Reloads app_rpt running config parameters\n";
00925
00926 static char restart_usage[] =
00927 "Usage: rpt restart\n"
00928 " Restarts app_rpt\n";
00929
00930 static char fun_usage[] =
00931 "Usage: rpt fun <nodename> <command>\n"
00932 " Send a DTMF function to a node\n";
00933
00934
00935 static struct ast_cli_entry cli_debug =
00936 { { "rpt", "debug", "level" }, rpt_do_debug,
00937 "Enable app_rpt debugging", debug_usage };
00938
00939 static struct ast_cli_entry cli_dump =
00940 { { "rpt", "dump" }, rpt_do_dump,
00941 "Dump app_rpt structs for debugging", dump_usage };
00942
00943 static struct ast_cli_entry cli_stats =
00944 { { "rpt", "stats" }, rpt_do_stats,
00945 "Dump node statistics", dump_stats };
00946
00947 static struct ast_cli_entry cli_nodes =
00948 { { "rpt", "nodes" }, rpt_do_nodes,
00949 "Dump node list", dump_nodes };
00950
00951 static struct ast_cli_entry cli_lstats =
00952 { { "rpt", "lstats" }, rpt_do_lstats,
00953 "Dump link statistics", dump_lstats };
00954
00955 static struct ast_cli_entry cli_reload =
00956 { { "rpt", "reload" }, rpt_do_reload,
00957 "Reload app_rpt config", reload_usage };
00958
00959 static struct ast_cli_entry cli_restart =
00960 { { "rpt", "restart" }, rpt_do_restart,
00961 "Restart app_rpt", restart_usage };
00962
00963 static struct ast_cli_entry cli_fun =
00964 { { "rpt", "fun" }, rpt_do_fun,
00965 "Execute a DTMF function", fun_usage };
00966
00967
00968
00969
00970
00971
00972 static struct telem_defaults tele_defs[] = {
00973 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
00974 {"ct2","|t(660,880,150,3072)"},
00975 {"ct3","|t(440,0,150,3072)"},
00976 {"ct4","|t(550,0,150,3072)"},
00977 {"ct5","|t(660,0,150,3072)"},
00978 {"ct6","|t(880,0,150,3072)"},
00979 {"ct7","|t(660,440,150,3072)"},
00980 {"ct8","|t(700,1100,150,3072)"},
00981 {"remotemon","|t(1600,0,75,2048)"},
00982 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
00983 {"cmdmode","|t(900,904,200,2048)"},
00984 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
00985 } ;
00986
00987
00988
00989
00990
00991 static int setrbi(struct rpt *myrpt);
00992 static int set_ft897(struct rpt *myrpt);
00993 static int set_ic706(struct rpt *myrpt);
00994 static int setkenwood(struct rpt *myrpt);
00995 static int setrbi_check(struct rpt *myrpt);
00996
00997
00998
00999
01000
01001
01002
01003 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01004 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01005 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01006 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01007 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01008 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01009 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01010
01011
01012
01013
01014 static struct function_table_tag function_table[] = {
01015 {"cop", function_cop},
01016 {"autopatchup", function_autopatchup},
01017 {"autopatchdn", function_autopatchdn},
01018 {"ilink", function_ilink},
01019 {"status", function_status},
01020 {"remote", function_remote},
01021 {"macro", function_macro}
01022 } ;
01023
01024 static long diskavail(struct rpt *myrpt)
01025 {
01026 struct statfs statfsbuf;
01027
01028 if (!myrpt->p.archivedir) return(0);
01029 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01030 {
01031 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01032 myrpt->p.archivedir,myrpt->name);
01033 return(-1);
01034 }
01035 return(statfsbuf.f_bavail);
01036 }
01037
01038 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01039 {
01040 struct rpt_link *l;
01041
01042 l = myrpt->links.next;
01043
01044 while(l != &myrpt->links)
01045 {
01046 if (!l->phonemode)
01047 {
01048 l = l->next;
01049 continue;
01050 }
01051
01052 if (mylink && (l == mylink))
01053 {
01054 l = l->next;
01055 continue;
01056 }
01057 if (l->chan) ast_senddigit(l->chan,c);
01058 l = l->next;
01059 }
01060 return;
01061 }
01062
01063
01064 static void donodelog(struct rpt *myrpt,char *str)
01065 {
01066 struct nodelog *nodep;
01067 char datestr[100];
01068
01069 if (!myrpt->p.archivedir) return;
01070 nodep = (struct nodelog *)malloc(sizeof(struct nodelog));
01071 if (nodep == NULL)
01072 {
01073 ast_log(LOG_ERROR,"Cannot get memory for node log");
01074 return;
01075 }
01076 time(&nodep->timestamp);
01077 strncpy(nodep->archivedir,myrpt->p.archivedir,
01078 sizeof(nodep->archivedir) - 1);
01079 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01080 localtime(&nodep->timestamp));
01081 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01082 myrpt->name,datestr,str);
01083 ast_mutex_lock(&nodeloglock);
01084 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01085 ast_mutex_unlock(&nodeloglock);
01086 }
01087
01088
01089 static void do_dtmf_local(struct rpt *myrpt, char c)
01090 {
01091 int i;
01092 char digit;
01093 static const char* dtmf_tones[] = {
01094 "!941+1336/200,!0/200",
01095 "!697+1209/200,!0/200",
01096 "!697+1336/200,!0/200",
01097 "!697+1477/200,!0/200",
01098 "!770+1209/200,!0/200",
01099 "!770+1336/200,!0/200",
01100 "!770+1477/200,!0/200",
01101 "!852+1209/200,!0/200",
01102 "!852+1336/200,!0/200",
01103 "!852+1477/200,!0/200",
01104 "!697+1633/200,!0/200",
01105 "!770+1633/200,!0/200",
01106 "!852+1633/200,!0/200",
01107 "!941+1633/200,!0/200",
01108 "!941+1209/200,!0/200",
01109 "!941+1477/200,!0/200" };
01110
01111
01112 if (c)
01113 {
01114 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01115 if (!myrpt->dtmf_local_timer)
01116 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01117 }
01118
01119 if (myrpt->dtmf_local_timer == 1)
01120 {
01121
01122 if (myrpt->dtmf_local_str[0])
01123 {
01124 digit = myrpt->dtmf_local_str[0];
01125 myrpt->dtmf_local_str[0] = 0;
01126 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01127 {
01128 myrpt->dtmf_local_str[i - 1] =
01129 myrpt->dtmf_local_str[i];
01130 }
01131 myrpt->dtmf_local_str[i - 1] = 0;
01132 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01133 rpt_mutex_unlock(&myrpt->lock);
01134 if (digit >= '0' && digit <='9')
01135 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01136 else if (digit >= 'A' && digit <= 'D')
01137 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01138 else if (digit == '*')
01139 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01140 else if (digit == '#')
01141 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01142 else {
01143
01144 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01145 }
01146 rpt_mutex_lock(&myrpt->lock);
01147 }
01148 else
01149 {
01150 myrpt->dtmf_local_timer = 0;
01151 }
01152 }
01153 }
01154
01155 static int openserial(char *fname)
01156 {
01157 struct termios mode;
01158 int fd;
01159
01160 fd = open(fname,O_RDWR);
01161 if (fd == -1)
01162 {
01163 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01164 return -1;
01165 }
01166 memset(&mode, 0, sizeof(mode));
01167 if (tcgetattr(fd, &mode)) {
01168 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01169 return -1;
01170 }
01171 #ifndef SOLARIS
01172 cfmakeraw(&mode);
01173 #else
01174 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01175 |INLCR|IGNCR|ICRNL|IXON);
01176 mode.c_oflag &= ~OPOST;
01177 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01178 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01179 mode.c_cflag |= CS8;
01180 mode.c_cc[TIME] = 3;
01181 mode.c_cc[MAX] = 1;
01182 #endif
01183
01184 cfsetispeed(&mode, B9600);
01185 cfsetospeed(&mode, B9600);
01186 if (tcsetattr(fd, TCSANOW, &mode))
01187 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01188 return(fd);
01189 }
01190
01191 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01192 {
01193 if (!fromnode)
01194 {
01195 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01196 unit,myrpt->name);
01197 }
01198 else
01199 {
01200 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01201 unit,fromnode,myrpt->name);
01202 }
01203 }
01204
01205 #ifdef _MDC_DECODE_H_
01206
01207 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01208 {
01209 struct rpt_link *l;
01210 struct ast_frame wf;
01211 char str[200];
01212
01213
01214 sprintf(str,"I %s %04X",myrpt->name,unit);
01215
01216 wf.frametype = AST_FRAME_TEXT;
01217 wf.subclass = 0;
01218 wf.offset = 0;
01219 wf.mallocd = 0;
01220 wf.datalen = strlen(str) + 1;
01221 wf.samples = 0;
01222
01223
01224 l = myrpt->links.next;
01225
01226 while(l != &myrpt->links)
01227 {
01228 if (l->name[0] == '0')
01229 {
01230 l = l->next;
01231 continue;
01232 }
01233 wf.data = str;
01234 if (l->chan) ast_write(l->chan,&wf);
01235 l = l->next;
01236 }
01237 return;
01238 }
01239
01240 #endif
01241
01242 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01243 {
01244 time_t now;
01245 int gotone;
01246
01247 time(&now);
01248 gotone = 0;
01249
01250 if ((now - xlat->lastone) > MAXXLATTIME)
01251 {
01252 xlat->funcindex = xlat->endindex = 0;
01253 }
01254 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01255 {
01256 time(&xlat->lastone);
01257 gotone = 1;
01258 if (!xlat->funccharseq[xlat->funcindex])
01259 {
01260 xlat->funcindex = xlat->endindex = 0;
01261 return(myrpt->p.funcchar);
01262 }
01263 } else xlat->funcindex = 0;
01264 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01265 {
01266 time(&xlat->lastone);
01267 gotone = 1;
01268 if (!xlat->endcharseq[xlat->endindex])
01269 {
01270 xlat->funcindex = xlat->endindex = 0;
01271 return(myrpt->p.endchar);
01272 }
01273 } else xlat->endindex = 0;
01274
01275 if (gotone) return(0);
01276
01277 if (!xlat->passchars[0]) return(c);
01278
01279 if (strchr(xlat->passchars,c)) return(c);
01280 return(0);
01281 }
01282
01283
01284
01285
01286
01287 static char *eatwhite(char *s)
01288 {
01289 while((*s == ' ') || (*s == 0x09)){
01290 if(!*s)
01291 break;
01292 s++;
01293 }
01294 return s;
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 static int finddelim(char *str, char *strp[], int limit)
01308 {
01309 int i,l,inquo;
01310
01311 inquo = 0;
01312 i = 0;
01313 strp[i++] = str;
01314 if (!*str)
01315 {
01316 strp[0] = 0;
01317 return(0);
01318 }
01319 for(l = 0; *str && (l < limit) ; str++)
01320 {
01321 if (*str == QUOTECHR)
01322 {
01323 if (inquo)
01324 {
01325 *str = 0;
01326 inquo = 0;
01327 }
01328 else
01329 {
01330 strp[i - 1] = str + 1;
01331 inquo = 1;
01332 }
01333 }
01334 if ((*str == DELIMCHR) && (!inquo))
01335 {
01336 *str = 0;
01337 l++;
01338 strp[i++] = str + 1;
01339 }
01340 }
01341 strp[i] = 0;
01342 return(i);
01343
01344 }
01345
01346
01347 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01348 {
01349 struct rpt_link *l;
01350 char mode;
01351 int i,spos;
01352
01353 buf[0] = 0;
01354
01355 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01356 {
01357
01358 if (l->name[0] == '0') continue;
01359
01360 if (l == mylink) continue;
01361 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01362
01363 mode = 'T';
01364 if (!l->mode) mode = 'R';
01365 if (!l->thisconnected) mode = 'C';
01366 spos = strlen(buf);
01367 if (spos)
01368 {
01369 strcat(buf,",");
01370 spos++;
01371 }
01372
01373 if (l->linklist[0])
01374 {
01375 snprintf(buf + spos,MAXLINKLIST - spos,
01376 "%c%s,%s",mode,l->name,l->linklist);
01377 }
01378 else
01379 {
01380 snprintf(buf + spos,MAXLINKLIST - spos,
01381 "%c%s",mode,l->name);
01382 }
01383
01384 if (mode == 'T') continue;
01385
01386 for(i = spos; buf[i]; i++)
01387 {
01388 if (buf[i] == 'T') buf[i] = mode;
01389 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01390 }
01391 }
01392 return;
01393 }
01394
01395
01396 static void __kickshort(struct rpt *myrpt)
01397 {
01398 struct rpt_link *l;
01399
01400 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01401 {
01402
01403 if (l->name[0] == '0') continue;
01404 l->linklisttimer = LINKLISTSHORTTIME;
01405 }
01406 return;
01407 }
01408
01409 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01410 {
01411
01412 char *val;
01413 int longestnode,j;
01414 struct stat mystat;
01415 static time_t last = 0;
01416 static struct ast_config *ourcfg = NULL;
01417 struct ast_variable *vp;
01418
01419
01420 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01421 if (val) return(val);
01422 ast_mutex_lock(&nodelookuplock);
01423
01424 if (stat(myrpt->p.extnodefile,&mystat) == -1)
01425 {
01426 if (ourcfg) ast_config_destroy(ourcfg);
01427 ourcfg = NULL;
01428 ast_mutex_unlock(&nodelookuplock);
01429 return(NULL);
01430 }
01431
01432 if (mystat.st_mtime > last)
01433 {
01434 if (ourcfg) ast_config_destroy(ourcfg);
01435 ourcfg = ast_config_load(myrpt->p.extnodefile);
01436
01437 if (!ourcfg)
01438 {
01439 ast_mutex_unlock(&nodelookuplock);
01440 return(NULL);
01441 }
01442
01443 last = mystat.st_mtime;
01444
01445
01446 longestnode = 0;
01447 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
01448 while(vp){
01449 j = strlen(vp->name);
01450 if (j > longestnode)
01451 longestnode = j;
01452 vp = vp->next;
01453 }
01454
01455 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
01456 while(vp){
01457 j = strlen(vp->name);
01458 if (j > longestnode)
01459 longestnode = j;
01460 vp = vp->next;
01461 }
01462
01463 myrpt->longestnode = longestnode;
01464 }
01465 val = NULL;
01466 if (ourcfg)
01467 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
01468 ast_mutex_unlock(&nodelookuplock);
01469 return(val);
01470 }
01471
01472
01473
01474
01475
01476
01477 static int matchkeyword(char *string, char **param, char *keywords[])
01478 {
01479 int i,ls;
01480 for( i = 0 ; keywords[i] ; i++){
01481 ls = strlen(keywords[i]);
01482 if(!ls){
01483 *param = NULL;
01484 return 0;
01485 }
01486 if(!strncmp(string, keywords[i], ls)){
01487 if(param)
01488 *param = string + ls;
01489 return i + 1;
01490 }
01491 }
01492 param = NULL;
01493 return 0;
01494 }
01495
01496
01497
01498
01499
01500
01501 static char *skipchars(char *string, char *charlist)
01502 {
01503 int i;
01504 while(*string){
01505 for(i = 0; charlist[i] ; i++){
01506 if(*string == charlist[i]){
01507 string++;
01508 break;
01509 }
01510 }
01511 if(!charlist[i])
01512 return string;
01513 }
01514 return string;
01515 }
01516
01517
01518
01519 static int myatoi(char *str)
01520 {
01521 int ret;
01522
01523 if (str == NULL) return -1;
01524
01525 if (sscanf(str,"%i",&ret) != 1) return -1;
01526 return ret;
01527 }
01528
01529 static int mycompar(const void *a, const void *b)
01530 {
01531 char **x = (char **) a;
01532 char **y = (char **) b;
01533 int xoff,yoff;
01534
01535 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
01536 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
01537 return(strcmp((*x) + xoff,(*y) + yoff));
01538 }
01539
01540 #ifdef __RPT_NOTCH
01541
01542
01543 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
01544 {
01545 int i,j;
01546 struct rptfilter *f;
01547
01548 for(i = 0; i < len; i++)
01549 {
01550 for(j = 0; j < MAXFILTERS; j++)
01551 {
01552 f = &myrpt->filters[j];
01553 if (!*f->desc) continue;
01554 f->x0 = f->x1; f->x1 = f->x2;
01555 f->x2 = ((float)buf[i]) / f->gain;
01556 f->y0 = f->y1; f->y1 = f->y2;
01557 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
01558 + (f->const1 * f->y0) + (f->const2 * f->y1);
01559 buf[i] = (short)f->y2;
01560 }
01561 }
01562 }
01563
01564 #endif
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 static void rpt_localtime( time_t * t, struct tm *lt)
01584 {
01585 #ifdef OLD_ASTERISK
01586 localtime_r(t, lt);
01587 #else
01588 ast_localtime(t, lt, NULL);
01589 #endif
01590 }
01591
01592
01593
01594 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
01595 {
01596 char *var;
01597 int ret;
01598 char include_zero = 0;
01599
01600 if(min < 0){
01601 min = -min;
01602 include_zero = 1;
01603 }
01604
01605 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
01606 if(var){
01607 ret = myatoi(var);
01608 if(include_zero && !ret)
01609 return 0;
01610 if(ret < min)
01611 ret = min;
01612 if(ret > max)
01613 ret = max;
01614 }
01615 else
01616 ret = defl;
01617 return ret;
01618 }
01619
01620
01621 static void load_rpt_vars(int n,int init)
01622 {
01623 char *this,*val;
01624 int i,j,longestnode;
01625 struct ast_variable *vp;
01626 struct ast_config *cfg;
01627 char *strs[100];
01628 char s1[256];
01629 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
01630 "ufena","ufdis","atena","atdis",NULL};
01631
01632 if (option_verbose > 2)
01633 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
01634 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
01635 ast_mutex_lock(&rpt_vars[n].lock);
01636 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
01637 cfg = ast_config_load("rpt.conf");
01638 if (!cfg) {
01639 ast_mutex_unlock(&rpt_vars[n].lock);
01640 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
01641 pthread_exit(NULL);
01642 }
01643 rpt_vars[n].cfg = cfg;
01644 this = rpt_vars[n].name;
01645 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
01646 if (init)
01647 {
01648
01649 memset(&rpt_vars[n].p + sizeof(rpt_vars[0].p), 0, sizeof(rpt_vars[0]) - sizeof(rpt_vars[0].p) - offsetof(typeof(rpt_vars[0]), p));
01650 rpt_vars[n].tele.next = &rpt_vars[n].tele;
01651 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
01652 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
01653 rpt_vars[n].tailmessagen = 0;
01654 }
01655 #ifdef __RPT_NOTCH
01656
01657 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
01658 #endif
01659 val = (char *) ast_variable_retrieve(cfg,this,"context");
01660 if (val) rpt_vars[n].p.ourcontext = val;
01661 else rpt_vars[n].p.ourcontext = this;
01662 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
01663 if (val) rpt_vars[n].p.ourcallerid = val;
01664 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
01665 if (val) rpt_vars[n].p.acctcode = val;
01666 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
01667 if (val) rpt_vars[n].p.ident = val;
01668 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
01669 if (val) rpt_vars[n].p.hangtime = atoi(val);
01670 else rpt_vars[n].p.hangtime = HANGTIME;
01671 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
01672 if (val) rpt_vars[n].p.althangtime = atoi(val);
01673 else rpt_vars[n].p.althangtime = HANGTIME;
01674 val = (char *) ast_variable_retrieve(cfg,this,"totime");
01675 if (val) rpt_vars[n].p.totime = atoi(val);
01676 else rpt_vars[n].p.totime = TOTIME;
01677 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
01678 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
01679 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
01680 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
01681 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
01682 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
01683 if (val) rpt_vars[n].p.tonezone = val;
01684 rpt_vars[n].p.tailmessages[0] = 0;
01685 rpt_vars[n].p.tailmessagemax = 0;
01686 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
01687 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
01688 val = (char *) ast_variable_retrieve(cfg,this,"memory");
01689 if (!val) val = MEMORY;
01690 rpt_vars[n].p.memory = val;
01691 val = (char *) ast_variable_retrieve(cfg,this,"macro");
01692 if (!val) val = MACRO;
01693 rpt_vars[n].p.macro = val;
01694 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
01695 if (val) rpt_vars[n].p.startupmacro = val;
01696 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
01697
01698
01699
01700 if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
01701 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
01702 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
01703 rpt_vars[n].p.ioport = val;
01704 val = (char *) ast_variable_retrieve(cfg,this,"functions");
01705 if (!val)
01706 {
01707 val = FUNCTIONS;
01708 rpt_vars[n].p.simple = 1;
01709 }
01710 rpt_vars[n].p.functions = val;
01711 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
01712 if (val) rpt_vars[n].p.link_functions = val;
01713 else
01714 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
01715 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
01716 if (val) rpt_vars[n].p.phone_functions = val;
01717 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
01718 if (val) rpt_vars[n].p.dphone_functions = val;
01719 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
01720 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
01721 rpt_vars[n].p.funcchar = *val;
01722 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
01723 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
01724 rpt_vars[n].p.endchar = *val;
01725 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
01726 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
01727 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
01728 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
01729 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
01730 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
01731 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
01732 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
01733 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
01734 if (val) rpt_vars[n].p.linktolink = ast_true(val);
01735 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
01736 if (!val) val = NODES;
01737 rpt_vars[n].p.nodes = val;
01738 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
01739 if (!val) val = EXTNODES;
01740 rpt_vars[n].p.extnodes = val;
01741 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
01742 if (!val) val = EXTNODEFILE;
01743 rpt_vars[n].p.extnodefile = val;
01744 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
01745 if (val) rpt_vars[n].p.archivedir = val;
01746 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
01747 if (val) rpt_vars[n].p.authlevel = atoi(val);
01748 else rpt_vars[n].p.authlevel = 0;
01749 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
01750 if (val) rpt_vars[n].p.monminblocks = atol(val);
01751 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
01752 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
01753 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
01754 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
01755 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
01756 if (val) rpt_vars[n].p.civaddr = atoi(val);
01757 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
01758 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
01759 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
01760 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
01761 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
01762 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
01763 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
01764 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
01765 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
01766 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
01767 #ifdef __RPT_NOTCH
01768 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
01769 if (val) {
01770 i = finddelim(val,strs,MAXFILTERS * 2);
01771 i &= ~1;
01772 if (i >= 2) for(j = 0; j < i; j += 2)
01773 {
01774 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
01775 &rpt_vars[n].filters[j >> 1].gain,
01776 &rpt_vars[n].filters[j >> 1].const0,
01777 &rpt_vars[n].filters[j >> 1].const1,
01778 &rpt_vars[n].filters[j >> 1].const2);
01779 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
01780 strs[j],strs[j + 1]);
01781 }
01782
01783 }
01784 #endif
01785 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
01786 if (val) {
01787 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
01788 i = finddelim(val,strs,3);
01789 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
01790 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
01791 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
01792 }
01793 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
01794 if (val) {
01795 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
01796 i = finddelim(val,strs,3);
01797 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
01798 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
01799 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
01800 }
01801
01802 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
01803 rpt_vars[n].p.csstanzaname = val;
01804
01805
01806 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
01807 rpt_vars[n].p.skedstanzaname = val;
01808
01809
01810 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
01811 rpt_vars[n].p.txlimitsstanzaname = val;
01812
01813 longestnode = 0;
01814
01815 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
01816
01817 while(vp){
01818 j = strlen(vp->name);
01819 if (j > longestnode)
01820 longestnode = j;
01821 vp = vp->next;
01822 }
01823
01824 rpt_vars[n].longestnode = longestnode;
01825
01826
01827
01828
01829 rpt_vars[n].longestfunc = 0;
01830 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
01831 while(vp){
01832 j = strlen(vp->name);
01833 if (j > rpt_vars[n].longestfunc)
01834 rpt_vars[n].longestfunc = j;
01835 vp = vp->next;
01836 }
01837
01838
01839
01840 rpt_vars[n].link_longestfunc = 0;
01841 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
01842 while(vp){
01843 j = strlen(vp->name);
01844 if (j > rpt_vars[n].link_longestfunc)
01845 rpt_vars[n].link_longestfunc = j;
01846 vp = vp->next;
01847 }
01848 rpt_vars[n].phone_longestfunc = 0;
01849 if (rpt_vars[n].p.phone_functions)
01850 {
01851 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
01852 while(vp){
01853 j = strlen(vp->name);
01854 if (j > rpt_vars[n].phone_longestfunc)
01855 rpt_vars[n].phone_longestfunc = j;
01856 vp = vp->next;
01857 }
01858 }
01859 rpt_vars[n].dphone_longestfunc = 0;
01860 if (rpt_vars[n].p.dphone_functions)
01861 {
01862 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
01863 while(vp){
01864 j = strlen(vp->name);
01865 if (j > rpt_vars[n].dphone_longestfunc)
01866 rpt_vars[n].dphone_longestfunc = j;
01867 vp = vp->next;
01868 }
01869 }
01870 rpt_vars[n].macro_longest = 1;
01871 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
01872 while(vp){
01873 j = strlen(vp->name);
01874 if (j > rpt_vars[n].macro_longest)
01875 rpt_vars[n].macro_longest = j;
01876 vp = vp->next;
01877 }
01878
01879
01880 if(rpt_vars[n].p.csstanzaname)
01881 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
01882 else
01883 vp = NULL;
01884 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
01885 int k,nukw,statenum;
01886 statenum=atoi(vp->name);
01887 strncpy(s1, vp->value, 255);
01888 s1[255] = 0;
01889 nukw = finddelim(s1,strs,32);
01890
01891 for (k = 0 ; k < nukw ; k++){
01892 for(j = 0 ; cs_keywords[j] != NULL ; j++){
01893 if(!strcmp(strs[k],cs_keywords[j])){
01894 switch(j){
01895 case 0:
01896 rpt_vars[n].p.s[statenum].txdisable = 0;
01897 break;
01898 case 1:
01899 rpt_vars[n].p.s[statenum].txdisable = 1;
01900 break;
01901
01902 case 2:
01903 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
01904 break;
01905
01906 case 3:
01907 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
01908 break;
01909
01910 case 4:
01911 rpt_vars[n].p.s[statenum].linkfundisable = 0;
01912 break;
01913
01914 case 5:
01915 rpt_vars[n].p.s[statenum].linkfundisable = 1;
01916 break;
01917
01918 case 6:
01919 rpt_vars[n].p.s[statenum].totdisable = 0;
01920 break;
01921
01922 case 7:
01923 rpt_vars[n].p.s[statenum].totdisable = 1;
01924 break;
01925
01926 case 8:
01927 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
01928 break;
01929
01930 case 9:
01931 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
01932 break;
01933
01934 case 10:
01935 rpt_vars[n].p.s[statenum].userfundisable = 0;
01936 break;
01937
01938 case 11:
01939 rpt_vars[n].p.s[statenum].userfundisable = 1;
01940 break;
01941
01942 case 12:
01943 rpt_vars[n].p.s[statenum].alternatetail = 1;
01944 break;
01945
01946 case 13:
01947 rpt_vars[n].p.s[statenum].alternatetail = 0;
01948 break;
01949
01950 default:
01951 ast_log(LOG_WARNING,
01952 "Unhandled control state keyword %s", cs_keywords[i]);
01953 break;
01954 }
01955 }
01956 }
01957 }
01958 vp = vp->next;
01959 }
01960 ast_mutex_unlock(&rpt_vars[n].lock);
01961 }
01962
01963
01964
01965
01966
01967 static int rpt_do_debug(int fd, int argc, char *argv[])
01968 {
01969 int newlevel;
01970
01971 if (argc != 4)
01972 return RESULT_SHOWUSAGE;
01973 newlevel = myatoi(argv[3]);
01974 if((newlevel < 0) || (newlevel > 7))
01975 return RESULT_SHOWUSAGE;
01976 if(newlevel)
01977 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
01978 else
01979 ast_cli(fd, "app_rpt Debugging disabled\n");
01980
01981 debug = newlevel;
01982 return RESULT_SUCCESS;
01983 }
01984
01985
01986
01987
01988
01989 static int rpt_do_dump(int fd, int argc, char *argv[])
01990 {
01991 int i;
01992
01993 if (argc != 3)
01994 return RESULT_SHOWUSAGE;
01995
01996 for(i = 0; i < nrpts; i++)
01997 {
01998 if (!strcmp(argv[2],rpt_vars[i].name))
01999 {
02000 rpt_vars[i].disgorgetime = time(NULL) + 10;
02001 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02002 return RESULT_SUCCESS;
02003 }
02004 }
02005 return RESULT_FAILURE;
02006 }
02007
02008
02009
02010
02011
02012 static int rpt_do_stats(int fd, int argc, char *argv[])
02013 {
02014 int i,j;
02015 int dailytxtime, dailykerchunks;
02016 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02017 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02018 long long totaltxtime;
02019 struct rpt_link *l;
02020 char *listoflinks[MAX_STAT_LINKS];
02021 char *lastnodewhichkeyedusup, *lastdtmfcommand;
02022 char *tot_state, *ider_state, *patch_state;
02023 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02024 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02025 struct rpt *myrpt;
02026
02027 static char *not_applicable = "N/A";
02028
02029 if(argc != 3)
02030 return RESULT_SHOWUSAGE;
02031
02032 for(i = 0 ; i < MAX_STAT_LINKS; i++)
02033 listoflinks[i] = NULL;
02034
02035 tot_state = ider_state =
02036 patch_state = reverse_patch_state =
02037 input_signal = called_number =
02038 lastdtmfcommand = not_applicable;
02039
02040 for(i = 0; i < nrpts; i++)
02041 {
02042 if (!strcmp(argv[2],rpt_vars[i].name)){
02043
02044 myrpt = &rpt_vars[i];
02045 rpt_mutex_lock(&myrpt->lock);
02046
02047 dailytxtime = myrpt->dailytxtime;
02048 totaltxtime = myrpt->totaltxtime;
02049 dailykeyups = myrpt->dailykeyups;
02050 totalkeyups = myrpt->totalkeyups;
02051 dailykerchunks = myrpt->dailykerchunks;
02052 totalkerchunks = myrpt->totalkerchunks;
02053 dailyexecdcommands = myrpt->dailyexecdcommands;
02054 totalexecdcommands = myrpt->totalexecdcommands;
02055 timeouts = myrpt->timeouts;
02056
02057
02058 reverse_patch_state = "DOWN";
02059 j = 0;
02060 l = myrpt->links.next;
02061 while(l && (l != &myrpt->links)){
02062 if (l->name[0] == '0'){
02063 reverse_patch_state = "UP";
02064 l = l->next;
02065 continue;
02066 }
02067 listoflinks[j] = ast_strdupa(l->name);
02068 if(listoflinks[j])
02069 j++;
02070 l = l->next;
02071 }
02072
02073 lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);
02074 if((!lastnodewhichkeyedusup) || (!strlen(lastnodewhichkeyedusup)))
02075 lastnodewhichkeyedusup = not_applicable;
02076
02077 if(myrpt->keyed)
02078 input_signal = "YES";
02079 else
02080 input_signal = "NO";
02081
02082 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02083 sys_ena = "DISABLED";
02084 else
02085 sys_ena = "ENABLED";
02086
02087 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02088 tot_ena = "DISABLED";
02089 else
02090 tot_ena = "ENABLED";
02091
02092 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02093 link_ena = "DISABLED";
02094 else
02095 link_ena = "ENABLED";
02096
02097 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02098 patch_ena = "DISABLED";
02099 else
02100 patch_ena = "ENABLED";
02101
02102 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02103 sch_ena = "DISABLED";
02104 else
02105 sch_ena = "ENABLED";
02106
02107 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02108 user_funs = "DISABLED";
02109 else
02110 user_funs = "ENABLED";
02111
02112 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02113 tail_type = "ALTERNATE";
02114 else
02115 tail_type = "STANDARD";
02116
02117 if(!myrpt->totimer)
02118 tot_state = "TIMED OUT!";
02119 else if(myrpt->totimer != myrpt->p.totime)
02120 tot_state = "ARMED";
02121 else
02122 tot_state = "RESET";
02123
02124 if(myrpt->tailid)
02125 ider_state = "QUEUED IN TAIL";
02126 else if(myrpt->mustid)
02127 ider_state = "QUEUED FOR CLEANUP";
02128 else
02129 ider_state = "CLEAN";
02130
02131 switch(myrpt->callmode){
02132 case 1:
02133 patch_state = "DIALING";
02134 break;
02135 case 2:
02136 patch_state = "CONNECTING";
02137 break;
02138 case 3:
02139 patch_state = "UP";
02140 break;
02141
02142 case 4:
02143 patch_state = "CALL FAILED";
02144 break;
02145
02146 default:
02147 patch_state = "DOWN";
02148 }
02149
02150 if(strlen(myrpt->exten)){
02151 called_number = ast_strdupa(myrpt->exten);
02152 if(!called_number)
02153 called_number = not_applicable;
02154 }
02155
02156 if(strlen(myrpt->lastdtmfcommand)){
02157 lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
02158 if(!lastdtmfcommand)
02159 lastdtmfcommand = not_applicable;
02160 }
02161
02162 rpt_mutex_unlock(&myrpt->lock);
02163
02164 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02165 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02166 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02167 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02168 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02169 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02170 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02171 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02172 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02173 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02174 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02175 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02176 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02177 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02178 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02179 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02180 ast_cli(fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
02181 hours = dailytxtime/3600000;
02182 dailytxtime %= 3600000;
02183 minutes = dailytxtime/60000;
02184 dailytxtime %= 60000;
02185 seconds = dailytxtime/1000;
02186 dailytxtime %= 1000;
02187
02188 ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
02189 hours, minutes, seconds, dailytxtime);
02190
02191 hours = (int) totaltxtime/3600000;
02192 totaltxtime %= 3600000;
02193 minutes = (int) totaltxtime/60000;
02194 totaltxtime %= 60000;
02195 seconds = (int) totaltxtime/1000;
02196 totaltxtime %= 1000;
02197
02198 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02199 hours, minutes, seconds, (int) totaltxtime);
02200 ast_cli(fd, "Nodes currently connected to us..................: ");
02201 for(j = 0 ;; j++){
02202 if(!listoflinks[j]){
02203 if(!j){
02204 ast_cli(fd,"<NONE>");
02205 }
02206 break;
02207 }
02208 ast_cli(fd, "%s", listoflinks[j]);
02209 if(j % 4 == 3){
02210 ast_cli(fd, "\n");
02211 ast_cli(fd, " : ");
02212 }
02213 else{
02214 if(listoflinks[j + 1])
02215 ast_cli(fd, ", ");
02216 }
02217 }
02218 ast_cli(fd,"\n");
02219
02220 ast_cli(fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
02221 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02222 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02223 ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
02224 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02225 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02226 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02227 return RESULT_SUCCESS;
02228 }
02229 }
02230 return RESULT_FAILURE;
02231 }
02232
02233
02234
02235
02236
02237 static int rpt_do_lstats(int fd, int argc, char *argv[])
02238 {
02239 int i,j;
02240 char *connstate;
02241 struct rpt *myrpt;
02242 struct rpt_link *l;
02243 struct rpt_lstat *s,*t;
02244 struct rpt_lstat s_head;
02245 if(argc != 3)
02246 return RESULT_SHOWUSAGE;
02247
02248 s = NULL;
02249 s_head.next = &s_head;
02250 s_head.prev = &s_head;
02251
02252 for(i = 0; i < nrpts; i++)
02253 {
02254 if (!strcmp(argv[2],rpt_vars[i].name)){
02255
02256 myrpt = &rpt_vars[i];
02257 rpt_mutex_lock(&myrpt->lock);
02258
02259 j = 0;
02260 l = myrpt->links.next;
02261 while(l && (l != &myrpt->links)){
02262 if (l->name[0] == '0'){
02263 l = l->next;
02264 continue;
02265 }
02266 if((s = (struct rpt_lstat *) malloc(sizeof(struct rpt_lstat))) == NULL){
02267 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02268 rpt_mutex_unlock(&myrpt->lock);
02269 return RESULT_FAILURE;
02270 }
02271 memset(s, 0, sizeof(struct rpt_lstat));
02272 strncpy(s->name, l->name, MAXREMSTR - 1);
02273 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02274 else strcpy(s->peer,"(none)");
02275 s->mode = l->mode;
02276 s->outbound = l->outbound;
02277 s->reconnects = l->reconnects;
02278 s->connecttime = l->connecttime;
02279 s->thisconnected = l->thisconnected;
02280 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02281 insque((struct qelem *) s, (struct qelem *) s_head.next);
02282 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02283 l = l->next;
02284 }
02285 rpt_mutex_unlock(&myrpt->lock);
02286 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02287 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02288
02289 for(s = s_head.next; s != &s_head; s = s->next){
02290 int hours, minutes, seconds;
02291 long long connecttime = s->connecttime;
02292 char conntime[21];
02293 hours = (int) connecttime/3600000;
02294 connecttime %= 3600000;
02295 minutes = (int) connecttime/60000;
02296 connecttime %= 60000;
02297 seconds = (int) connecttime/1000;
02298 connecttime %= 1000;
02299 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02300 hours, minutes, seconds, (int) connecttime);
02301 conntime[20] = 0;
02302 if(s->thisconnected)
02303 connstate = "ESTABLISHED";
02304 else
02305 connstate = "CONNECTING";
02306 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02307 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02308 }
02309
02310 s = s_head.next;
02311 while(s != &s_head){
02312 t = s;
02313 s = s->next;
02314 remque((struct qelem *)t);
02315 free(t);
02316 }
02317 return RESULT_SUCCESS;
02318 }
02319 }
02320 return RESULT_FAILURE;
02321 }
02322
02323
02324
02325
02326
02327 static int rpt_do_nodes(int fd, int argc, char *argv[])
02328 {
02329 int i,j;
02330 char ns;
02331 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02332 struct rpt *myrpt;
02333 if(argc != 3)
02334 return RESULT_SHOWUSAGE;
02335
02336 for(i = 0; i < nrpts; i++)
02337 {
02338 if (!strcmp(argv[2],rpt_vars[i].name)){
02339
02340 myrpt = &rpt_vars[i];
02341 rpt_mutex_lock(&myrpt->lock);
02342 __mklinklist(myrpt,NULL,lbuf);
02343 rpt_mutex_unlock(&myrpt->lock);
02344
02345 ns = finddelim(lbuf,strs,MAXLINKLIST);
02346
02347 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
02348 ast_cli(fd,"\n");
02349 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
02350 for(j = 0 ;; j++){
02351 if(!strs[j]){
02352 if(!j){
02353 ast_cli(fd,"<NONE>");
02354 }
02355 break;
02356 }
02357 ast_cli(fd, "%s", strs[j]);
02358 if(j % 8 == 7){
02359 ast_cli(fd, "\n");
02360 }
02361 else{
02362 if(strs[j + 1])
02363 ast_cli(fd, ", ");
02364 }
02365 }
02366 ast_cli(fd,"\n\n");
02367 return RESULT_SUCCESS;
02368 }
02369 }
02370 return RESULT_FAILURE;
02371 }
02372
02373
02374
02375
02376
02377 static int rpt_do_reload(int fd, int argc, char *argv[])
02378 {
02379 int n;
02380
02381 if (argc > 2) return RESULT_SHOWUSAGE;
02382
02383 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
02384
02385 return RESULT_FAILURE;
02386 }
02387
02388
02389
02390
02391
02392 static int rpt_do_restart(int fd, int argc, char *argv[])
02393 {
02394 int i;
02395
02396 if (argc > 2) return RESULT_SHOWUSAGE;
02397 for(i = 0; i < nrpts; i++)
02398 {
02399 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
02400 }
02401 return RESULT_FAILURE;
02402 }
02403
02404
02405
02406
02407
02408
02409 static int rpt_do_fun(int fd, int argc, char *argv[])
02410 {
02411 int i,busy=0;
02412
02413 if (argc != 4) return RESULT_SHOWUSAGE;
02414
02415 for(i = 0; i < nrpts; i++){
02416 if(!strcmp(argv[2], rpt_vars[i].name)){
02417 struct rpt *myrpt = &rpt_vars[i];
02418 rpt_mutex_lock(&myrpt->lock);
02419 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
02420 rpt_mutex_unlock(&myrpt->lock);
02421 busy=1;
02422 }
02423 if(!busy){
02424 myrpt->macrotimer = MACROTIME;
02425 strncat(myrpt->macrobuf, argv[3], MAXMACRO - strlen(myrpt->macrobuf) - 1);
02426 }
02427 rpt_mutex_unlock(&myrpt->lock);
02428 }
02429 }
02430 if(busy){
02431 ast_cli(fd, "Function decoder busy");
02432 }
02433 return RESULT_FAILURE;
02434 }
02435
02436
02437
02438 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
02439 {
02440 int res;
02441
02442 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
02443 return res;
02444
02445 while(chan->generatordata) {
02446 if (ast_safe_sleep(chan,1)) return -1;
02447 }
02448
02449 return 0;
02450 }
02451
02452 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
02453 {
02454 return play_tone_pair(chan, freq, 0, duration, amplitude);
02455 }
02456
02457 static int play_silence(struct ast_channel *chan, int duration)
02458 {
02459 return play_tone_pair(chan, 0, 0, duration, 0);
02460 }
02461
02462
02463 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
02464 {
02465
02466 static struct morse_bits mbits[] = {
02467 {0, 0},
02468 {0, 0},
02469 {6, 18},
02470 {0, 0},
02471 {7, 72},
02472 {0, 0},
02473 {0, 0},
02474 {6, 30},
02475 {5, 13},
02476 {6, 29},
02477 {0, 0},
02478 {5, 10},
02479 {6, 51},
02480 {6, 33},
02481 {6, 42},
02482 {5, 9},
02483 {5, 31},
02484 {5, 30},
02485 {5, 28},
02486 {5, 24},
02487 {5, 16},
02488 {5, 0},
02489 {5, 1},
02490 {5, 3},
02491 {5, 7},
02492 {5, 15},
02493 {6, 7},
02494 {6, 21},
02495 {0, 0},
02496 {5, 33},
02497 {0, 0},
02498 {6, 12},
02499 {0, 0},
02500 {2, 2},
02501 {4, 1},
02502 {4, 5},
02503 {3, 1},
02504 {1, 0},
02505 {4, 4},
02506 {3, 3},
02507 {4, 0},
02508 {2, 0},
02509 {4, 14},
02510 {3, 5},
02511 {4, 2},
02512 {2, 3},
02513 {2, 1},
02514 {3, 7},
02515 {4, 6},
02516 {4, 11},
02517 {3, 2},
02518 {3, 0},
02519 {1, 1},
02520 {3, 4},
02521 {4, 8},
02522 {3, 6},
02523 {4, 9},
02524 {4, 13},
02525 {4, 3}
02526 };
02527
02528
02529 int dottime;
02530 int dashtime;
02531 int intralettertime;
02532 int interlettertime;
02533 int interwordtime;
02534 int len, ddcomb;
02535 int res;
02536 int c;
02537 int i;
02538 int flags;
02539
02540 res = 0;
02541
02542
02543
02544 dottime = 900/speed;
02545
02546
02547
02548 dashtime = 3 * dottime;
02549 intralettertime = dottime;
02550 interlettertime = dottime * 4 ;
02551 interwordtime = dottime * 7;
02552
02553 for(;(*string) && (!res); string++){
02554
02555 c = *string;
02556
02557
02558
02559 if((c >= 'a') && (c <= 'z'))
02560 c -= 0x20;
02561
02562
02563
02564 if(c > 'Z')
02565 continue;
02566
02567
02568
02569 if(c == ' '){
02570 if(!res)
02571 res = play_silence(chan, interwordtime);
02572 continue;
02573 }
02574
02575
02576
02577 c -= 0x20;
02578
02579
02580
02581 len = mbits[c].len;
02582 ddcomb = mbits[c].ddcomb;
02583
02584
02585
02586 for(; len ; len--){
02587 if(!res)
02588 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
02589 if(!res)
02590 res = play_silence(chan, intralettertime);
02591 ddcomb >>= 1;
02592 }
02593
02594
02595
02596 if(!res)
02597 res = play_silence(chan, interlettertime - intralettertime);
02598 }
02599
02600
02601
02602 if (!res)
02603 res = ast_waitstream(chan, "");
02604 ast_stopstream(chan);
02605
02606
02607
02608
02609
02610 for(i = 0; i < 20 ; i++){
02611 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
02612 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
02613 if(flags & DAHDI_IOMUX_WRITEEMPTY)
02614 break;
02615 if( ast_safe_sleep(chan, 50)){
02616 res = -1;
02617 break;
02618 }
02619 }
02620
02621
02622 return res;
02623 }
02624
02625 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
02626 {
02627 char *stringp;
02628 char *tonesubset;
02629 int f1,f2;
02630 int duration;
02631 int amplitude;
02632 int res;
02633 int i;
02634 int flags;
02635
02636 res = 0;
02637
02638 stringp = ast_strdupa(tonestring);
02639
02640 for(;tonestring;){
02641 tonesubset = strsep(&stringp,")");
02642 if(!tonesubset)
02643 break;
02644 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4)
02645 break;
02646 res = play_tone_pair(chan, f1, f2, duration, amplitude);
02647 if(res)
02648 break;
02649 }
02650 if(!res)
02651 res = play_tone_pair(chan, 0, 0, 100, 0);
02652
02653 if (!res)
02654 res = ast_waitstream(chan, "");
02655 ast_stopstream(chan);
02656
02657
02658
02659
02660
02661 for(i = 0; i < 20 ; i++){
02662 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
02663 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
02664 if(flags & DAHDI_IOMUX_WRITEEMPTY)
02665 break;
02666 if( ast_safe_sleep(chan, 50)){
02667 res = -1;
02668 break;
02669 }
02670 }
02671
02672 return res;
02673
02674 }
02675
02676 static int sayfile(struct ast_channel *mychannel,char *fname)
02677 {
02678 int res;
02679
02680 res = ast_streamfile(mychannel, fname, mychannel->language);
02681 if (!res)
02682 res = ast_waitstream(mychannel, "");
02683 else
02684 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02685 ast_stopstream(mychannel);
02686 return res;
02687 }
02688
02689 static int saycharstr(struct ast_channel *mychannel,char *str)
02690 {
02691 int res;
02692
02693 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
02694 if (!res)
02695 res = ast_waitstream(mychannel, "");
02696 else
02697 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02698 ast_stopstream(mychannel);
02699 return res;
02700 }
02701
02702 static int saynum(struct ast_channel *mychannel, int num)
02703 {
02704 int res;
02705 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
02706 if(!res)
02707 res = ast_waitstream(mychannel, "");
02708 else
02709 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02710 ast_stopstream(mychannel);
02711 return res;
02712 }
02713
02714
02715 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
02716 {
02717 int res;
02718 char c;
02719
02720 static int morsespeed;
02721 static int morsefreq;
02722 static int morseampl;
02723 static int morseidfreq = 0;
02724 static int morseidampl;
02725 static char mcat[] = MORSE;
02726
02727 res = 0;
02728
02729 if(!morseidfreq){
02730 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
02731 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
02732 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
02733 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
02734 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
02735 }
02736
02737
02738
02739 if(entry[0] == '|'){
02740 c = entry[1];
02741 if((c >= 'a')&&(c <= 'z'))
02742 c -= 0x20;
02743
02744 switch(c){
02745 case 'I':
02746 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
02747 break;
02748
02749 case 'M':
02750 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
02751 break;
02752
02753 case 'T':
02754 res = send_tone_telemetry(chan, entry + 2);
02755 break;
02756 default:
02757 res = -1;
02758 }
02759 }
02760 else
02761 res = sayfile(chan, entry);
02762 return res;
02763 }
02764
02765
02766
02767
02768
02769
02770
02771 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
02772 {
02773
02774 int res;
02775 int i;
02776 char *entry;
02777 char *telemetry;
02778 char *telemetry_save;
02779
02780 res = 0;
02781 telemetry_save = NULL;
02782 entry = NULL;
02783
02784
02785 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
02786 if(telemetry ){
02787 telemetry_save = ast_strdupa(telemetry);
02788 if(!telemetry_save){
02789 ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
02790 return res;
02791 }
02792 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
02793 }
02794
02795
02796
02797 if(!entry){
02798
02799 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
02800 if(!strcasecmp(tele_defs[i].name, name))
02801 entry = tele_defs[i].value;
02802 }
02803 }
02804 if(entry){
02805 if(strlen(entry))
02806 telem_any(myrpt,chan, entry);
02807 }
02808 else{
02809 res = -1;
02810 }
02811 return res;
02812 }
02813
02814
02815
02816
02817
02818 static int get_wait_interval(struct rpt *myrpt, int type)
02819 {
02820 int interval;
02821 char *wait_times;
02822 char *wait_times_save;
02823
02824 wait_times_save = NULL;
02825 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
02826
02827 if(wait_times){
02828 wait_times_save = ast_strdupa(wait_times);
02829 if(!wait_times_save){
02830 ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
02831 wait_times = NULL;
02832 }
02833 }
02834
02835 switch(type){
02836 case DLY_TELEM:
02837 if(wait_times)
02838 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
02839 else
02840 interval = 1000;
02841 break;
02842
02843 case DLY_ID:
02844 if(wait_times)
02845 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
02846 else
02847 interval = 500;
02848 break;
02849
02850 case DLY_UNKEY:
02851 if(wait_times)
02852 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",500,5000,1000);
02853 else
02854 interval = 1000;
02855 break;
02856
02857 case DLY_LINKUNKEY:
02858 if(wait_times)
02859 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
02860 else
02861 interval = 1000;
02862 break;
02863
02864 case DLY_CALLTERM:
02865 if(wait_times)
02866 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
02867 else
02868 interval = 1500;
02869 break;
02870
02871 case DLY_COMP:
02872 if(wait_times)
02873 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
02874 else
02875 interval = 200;
02876 break;
02877
02878 default:
02879 return 0;
02880 }
02881 return interval;
02882 }
02883
02884
02885
02886
02887
02888
02889
02890 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
02891 {
02892 int interval;
02893 interval = get_wait_interval(myrpt, type);
02894 if(debug)
02895 ast_log(LOG_NOTICE," Delay interval = %d\n", interval);
02896 if(interval)
02897 ast_safe_sleep(chan,interval);
02898 if(debug)
02899 ast_log(LOG_NOTICE,"Delay complete\n");
02900 return;
02901 }
02902
02903 static int split_freq(char *mhz, char *decimals, char *freq);
02904
02905 static void *rpt_tele_thread(void *this)
02906 {
02907 struct dahdi_confinfo ci;
02908 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
02909 struct rpt_tele *mytele = (struct rpt_tele *)this;
02910 struct rpt_tele *tlist;
02911 struct rpt *myrpt;
02912 struct rpt_link *l,*l1,linkbase;
02913 struct ast_channel *mychannel;
02914 int vmajor, vminor, m;
02915 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
02916 time_t t;
02917 struct tm localtm;
02918 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02919 int i,ns,rbimode;
02920 char mhz[MAXREMSTR];
02921 char decimals[MAXREMSTR];
02922 struct dahdi_params par;
02923
02924
02925
02926 myrpt = mytele->rpt;
02927
02928
02929 rpt_mutex_lock(&myrpt->lock);
02930 nodename = ast_strdupa(myrpt->name);
02931 if (myrpt->p.ident) ident = ast_strdupa(myrpt->p.ident);
02932 else ident = "";
02933 rpt_mutex_unlock(&myrpt->lock);
02934
02935
02936 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02937 if (!mychannel)
02938 {
02939 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02940 rpt_mutex_lock(&myrpt->lock);
02941 remque((struct qelem *)mytele);
02942 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
02943 rpt_mutex_unlock(&myrpt->lock);
02944 free(mytele);
02945 pthread_exit(NULL);
02946 }
02947 #ifdef AST_CDR_FLAG_POST_DISABLED
02948 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
02949 #endif
02950 rpt_mutex_lock(&myrpt->lock);
02951 mytele->chan = mychannel;
02952 rpt_mutex_unlock(&myrpt->lock);
02953
02954 ci.chan = 0;
02955
02956
02957
02958 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
02959 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY)) || (mytele->mode == TIMEOUT) ?
02960 myrpt->txconf : myrpt->conf);
02961 ci.confmode = DAHDI_CONF_CONFANN;
02962
02963 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
02964 {
02965 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02966 rpt_mutex_lock(&myrpt->lock);
02967 remque((struct qelem *)mytele);
02968 rpt_mutex_unlock(&myrpt->lock);
02969 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
02970 free(mytele);
02971 ast_hangup(mychannel);
02972 pthread_exit(NULL);
02973 }
02974 ast_stopstream(mychannel);
02975 switch(mytele->mode)
02976 {
02977 case ID:
02978 case ID1:
02979
02980 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
02981 res = telem_any(myrpt,mychannel, ident);
02982 imdone=1;
02983 break;
02984
02985 case TAILMSG:
02986 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
02987 break;
02988
02989 case IDTALKOVER:
02990 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
02991 if(p)
02992 res = telem_any(myrpt,mychannel, p);
02993 imdone=1;
02994 break;
02995
02996 case PROC:
02997
02998 wait_interval(myrpt, DLY_TELEM, mychannel);
02999 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
03000 if(res < 0){
03001 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
03002 }
03003 break;
03004 case TERM:
03005
03006 wait_interval(myrpt, DLY_CALLTERM, mychannel);
03007 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
03008 if(res < 0){
03009 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
03010 }
03011 break;
03012 case COMPLETE:
03013
03014 wait_interval(myrpt, DLY_TELEM, mychannel);
03015 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03016 break;
03017 case MACRO_NOTFOUND:
03018
03019 wait_interval(myrpt, DLY_TELEM, mychannel);
03020 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
03021 break;
03022 case MACRO_BUSY:
03023
03024 wait_interval(myrpt, DLY_TELEM, mychannel);
03025 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
03026 break;
03027 case UNKEY:
03028 if(myrpt->patchnoct && myrpt->callmode){
03029 imdone = 1;
03030 break;
03031 }
03032
03033
03034
03035
03036
03037 x = get_wait_interval(myrpt, DLY_UNKEY);
03038 rpt_mutex_lock(&myrpt->lock);
03039 myrpt->unkeytocttimer = x;
03040 rpt_mutex_unlock(&myrpt->lock);
03041
03042
03043
03044
03045
03046 tlist = myrpt->tele.next;
03047 unkeys_queued = 0;
03048 if (tlist != &myrpt->tele)
03049 {
03050 rpt_mutex_lock(&myrpt->lock);
03051 while(tlist != &myrpt->tele){
03052 if (tlist->mode == UNKEY) unkeys_queued++;
03053 tlist = tlist->next;
03054 }
03055 rpt_mutex_unlock(&myrpt->lock);
03056 }
03057 if( unkeys_queued > 1){
03058 imdone = 1;
03059 break;
03060 }
03061
03062
03063
03064 while(myrpt->unkeytocttimer)
03065 {
03066 int ctint;
03067 if(myrpt->unkeytocttimer > 100)
03068 ctint = 100;
03069 else
03070 ctint = myrpt->unkeytocttimer;
03071 ast_safe_sleep(mychannel, ctint);
03072 rpt_mutex_lock(&myrpt->lock);
03073 if(myrpt->unkeytocttimer < ctint)
03074 myrpt->unkeytocttimer = 0;
03075 else
03076 myrpt->unkeytocttimer -= ctint;
03077 rpt_mutex_unlock(&myrpt->lock);
03078 }
03079
03080
03081
03082
03083
03084 if(myrpt->keyed){
03085 imdone = 1;
03086 break;
03087 }
03088
03089 rpt_mutex_lock(&myrpt->lock);
03090 myrpt->dailykerchunks++;
03091 myrpt->totalkerchunks++;
03092 rpt_mutex_unlock(&myrpt->lock);
03093
03094 haslink = 0;
03095 hastx = 0;
03096 hasremote = 0;
03097 l = myrpt->links.next;
03098 if (l != &myrpt->links)
03099 {
03100 rpt_mutex_lock(&myrpt->lock);
03101 while(l != &myrpt->links)
03102 {
03103 if (l->name[0] == '0')
03104 {
03105 l = l->next;
03106 continue;
03107 }
03108 haslink = 1;
03109 if (l->mode) {
03110 hastx++;
03111 if (l->isremote) hasremote++;
03112 }
03113 l = l->next;
03114 }
03115 rpt_mutex_unlock(&myrpt->lock);
03116 }
03117 if (haslink)
03118 {
03119
03120 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
03121 if(res)
03122 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
03123
03124
03125
03126 if (myrpt->cmdnode[0])
03127 {
03128 ast_safe_sleep(mychannel,200);
03129 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
03130 if(res)
03131 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
03132 ast_stopstream(mychannel);
03133 }
03134 }
03135 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
03136 ct_copy = ast_strdupa(ct);
03137 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03138 if(res)
03139 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03140 }
03141 if (hasremote && (!myrpt->cmdnode[0]))
03142 {
03143
03144 ci.chan = 0;
03145 ci.confno = myrpt->conf;
03146 ci.confmode = DAHDI_CONF_CONFANN;
03147
03148 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
03149 {
03150 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03151 rpt_mutex_lock(&myrpt->lock);
03152 remque((struct qelem *)mytele);
03153 rpt_mutex_unlock(&myrpt->lock);
03154 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03155 free(mytele);
03156 ast_hangup(mychannel);
03157 pthread_exit(NULL);
03158 }
03159 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
03160 ast_safe_sleep(mychannel,200);
03161 ct_copy = ast_strdupa(ct);
03162 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03163 if(res)
03164 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03165 }
03166 }
03167 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
03168 if (myrpt->lastunit)
03169 {
03170 char mystr[10];
03171
03172 ast_safe_sleep(mychannel,200);
03173
03174 ci.chan = 0;
03175 ci.confno = myrpt->txconf;
03176 ci.confmode = DAHDI_CONF_CONFANN;
03177
03178 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
03179 {
03180 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03181 rpt_mutex_lock(&myrpt->lock);
03182 remque((struct qelem *)mytele);
03183 rpt_mutex_unlock(&myrpt->lock);
03184 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03185 free(mytele);
03186 ast_hangup(mychannel);
03187 pthread_exit(NULL);
03188 }
03189 sprintf(mystr,"%04x",myrpt->lastunit);
03190 myrpt->lastunit = 0;
03191 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
03192 break;
03193 }
03194 #endif
03195 imdone = 1;
03196 break;
03197 case LINKUNKEY:
03198 if(myrpt->patchnoct && myrpt->callmode){
03199 imdone = 1;
03200 break;
03201 }
03202
03203
03204
03205
03206
03207 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
03208 mytele->mylink.linkunkeytocttimer = x;
03209
03210
03211
03212
03213
03214 tlist = myrpt->tele.next;
03215 unkeys_queued = 0;
03216 if (tlist != &myrpt->tele)
03217 {
03218 rpt_mutex_lock(&myrpt->lock);
03219 while(tlist != &myrpt->tele){
03220 if (tlist->mode == LINKUNKEY) unkeys_queued++;
03221 tlist = tlist->next;
03222 }
03223 rpt_mutex_unlock(&myrpt->lock);
03224 }
03225 if( unkeys_queued > 1){
03226 imdone = 1;
03227 break;
03228 }
03229
03230
03231
03232 while(mytele->mylink.linkunkeytocttimer)
03233 {
03234 int ctint;
03235 if(mytele->mylink.linkunkeytocttimer > 100)
03236 ctint = 100;
03237 else
03238 ctint = mytele->mylink.linkunkeytocttimer;
03239 ast_safe_sleep(mychannel, ctint);
03240 rpt_mutex_lock(&myrpt->lock);
03241 if(mytele->mylink.linkunkeytocttimer < ctint)
03242 mytele->mylink.linkunkeytocttimer = 0;
03243 else
03244 mytele->mylink.linkunkeytocttimer -= ctint;
03245 rpt_mutex_unlock(&myrpt->lock);
03246 }
03247
03248 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
03249 ct_copy = ast_strdupa(ct);
03250 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03251 if(res)
03252 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03253 }
03254 imdone = 1;
03255 break;
03256 case REMDISC:
03257
03258 wait_interval(myrpt, DLY_TELEM, mychannel);
03259 l = myrpt->links.next;
03260 haslink = 0;
03261
03262 if (l != &myrpt->links)
03263 {
03264 rpt_mutex_lock(&myrpt->lock);
03265 while(l != &myrpt->links)
03266 {
03267 if (l->name[0] == '0')
03268 {
03269 l = l->next;
03270 continue;
03271 }
03272 if (!strcmp(l->name,mytele->mylink.name))
03273 {
03274 haslink = 1;
03275 break;
03276 }
03277 l = l->next;
03278 }
03279 rpt_mutex_unlock(&myrpt->lock);
03280 }
03281 if (haslink)
03282 {
03283 imdone = 1;
03284 break;
03285 }
03286 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03287 if (!res)
03288 res = ast_waitstream(mychannel, "");
03289 else
03290 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03291 ast_stopstream(mychannel);
03292 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03293 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
03294 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
03295 break;
03296 case REMALREADY:
03297
03298 wait_interval(myrpt, DLY_TELEM, mychannel);
03299 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
03300 break;
03301 case REMNOTFOUND:
03302
03303 wait_interval(myrpt, DLY_TELEM, mychannel);
03304 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
03305 break;
03306 case REMGO:
03307
03308 wait_interval(myrpt, DLY_TELEM, mychannel);
03309 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
03310 break;
03311 case CONNECTED:
03312
03313 wait_interval(myrpt, DLY_TELEM, mychannel);
03314 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03315 if (!res)
03316 res = ast_waitstream(mychannel, "");
03317 else
03318 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03319 ast_stopstream(mychannel);
03320 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03321 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
03322 if (!res)
03323 res = ast_waitstream(mychannel, "");
03324 else
03325 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03326 ast_stopstream(mychannel);
03327 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
03328 if (!res)
03329 res = ast_waitstream(mychannel, "");
03330 else
03331 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03332 ast_stopstream(mychannel);
03333 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03334 if (!res)
03335 res = ast_waitstream(mychannel, "");
03336 else
03337 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03338 ast_stopstream(mychannel);
03339 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03340 imdone = 1;
03341 break;
03342 case CONNFAIL:
03343 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03344 if (!res)
03345 res = ast_waitstream(mychannel, "");
03346 else
03347 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03348 ast_stopstream(mychannel);
03349 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03350 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
03351 break;
03352 case MEMNOTFOUND:
03353
03354 wait_interval(myrpt, DLY_TELEM, mychannel);
03355 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
03356 break;
03357 case SETREMOTE:
03358 ast_mutex_lock(&myrpt->remlock);
03359 res = 0;
03360 if(!strcmp(myrpt->remote, remote_rig_ft897))
03361 {
03362 res = set_ft897(myrpt);
03363 }
03364 if(!strcmp(myrpt->remote, remote_rig_ic706))
03365 {
03366 res = set_ic706(myrpt);
03367 }
03368 #ifdef HAVE_IOPERM
03369 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03370 {
03371 if (ioperm(myrpt->p.iobase,1,1) == -1)
03372 {
03373 rpt_mutex_unlock(&myrpt->lock);
03374 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
03375 res = -1;
03376 }
03377 else res = setrbi(myrpt);
03378 }
03379 #endif
03380 else if(!strcmp(myrpt->remote, remote_rig_kenwood))
03381 {
03382 res = setkenwood(myrpt);
03383 if (ast_safe_sleep(mychannel,200) == -1)
03384 {
03385 ast_mutex_unlock(&myrpt->remlock);
03386 res = -1;
03387 break;
03388 }
03389 i = DAHDI_FLUSH_EVENT;
03390 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
03391 {
03392 ast_mutex_unlock(&myrpt->remlock);
03393 ast_log(LOG_ERROR,"Cant flush events");
03394 res = -1;
03395 break;
03396 }
03397 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
03398 {
03399 ast_mutex_unlock(&myrpt->remlock);
03400 ast_log(LOG_ERROR,"Cant get params");
03401 res = -1;
03402 break;
03403 }
03404 myrpt->remoterx =
03405 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
03406 }
03407 ast_mutex_unlock(&myrpt->remlock);
03408 if (!res)
03409 {
03410 imdone = 1;
03411 break;
03412 }
03413
03414 case INVFREQ:
03415
03416 wait_interval(myrpt, DLY_TELEM, mychannel);
03417 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
03418 break;
03419 case REMMODE:
03420 cp = 0;
03421 wait_interval(myrpt, DLY_TELEM, mychannel);
03422 switch(myrpt->remmode)
03423 {
03424 case REM_MODE_FM:
03425 saycharstr(mychannel,"FM");
03426 break;
03427 case REM_MODE_USB:
03428 saycharstr(mychannel,"USB");
03429 break;
03430 case REM_MODE_LSB:
03431 saycharstr(mychannel,"LSB");
03432 break;
03433 case REM_MODE_AM:
03434 saycharstr(mychannel,"AM");
03435 break;
03436 }
03437 wait_interval(myrpt, DLY_COMP, mychannel);
03438 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03439 break;
03440 case LOGINREQ:
03441 wait_interval(myrpt, DLY_TELEM, mychannel);
03442 sayfile(mychannel,"rpt/login");
03443 saycharstr(mychannel,myrpt->name);
03444 break;
03445 case REMLOGIN:
03446 wait_interval(myrpt, DLY_TELEM, mychannel);
03447 saycharstr(mychannel,myrpt->loginuser);
03448 sayfile(mychannel,"rpt/node");
03449 saycharstr(mychannel,myrpt->name);
03450 wait_interval(myrpt, DLY_COMP, mychannel);
03451 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03452 break;
03453 case REMXXX:
03454 wait_interval(myrpt, DLY_TELEM, mychannel);
03455 res = 0;
03456 switch(mytele->submode)
03457 {
03458 case 100:
03459 sayfile(mychannel, "rpt/rxpl");
03460 sayfile(mychannel, "rpt/off");
03461 break;
03462 case 101:
03463 sayfile(mychannel, "rpt/rxpl");
03464 sayfile(mychannel, "rpt/on");
03465 break;
03466 case 102:
03467 sayfile(mychannel, "rpt/txpl");
03468 sayfile(mychannel, "rpt/off");
03469 break;
03470 case 103:
03471 sayfile(mychannel, "rpt/txpl");
03472 sayfile(mychannel, "rpt/on");
03473 break;
03474 case 104:
03475 sayfile(mychannel, "rpt/lopwr");
03476 break;
03477 case 105:
03478 sayfile(mychannel, "rpt/medpwr");
03479 break;
03480 case 106:
03481 sayfile(mychannel, "rpt/hipwr");
03482 break;
03483 case 113:
03484 sayfile(mychannel,"rpt/down");
03485 sayfile(mychannel, "rpt/slow");
03486 break;
03487 case 114:
03488 sayfile(mychannel,"rpt/down");
03489 sayfile(mychannel, "rpt/quick");
03490 break;
03491 case 115:
03492 sayfile(mychannel,"rpt/down");
03493 sayfile(mychannel, "rpt/fast");
03494 break;
03495 case 116:
03496 sayfile(mychannel,"rpt/up");
03497 sayfile(mychannel, "rpt/slow");
03498 break;
03499 case 117:
03500 sayfile(mychannel,"rpt/up");
03501 sayfile(mychannel, "rpt/quick");
03502 break;
03503 case 118:
03504 sayfile(mychannel,"rpt/up");
03505 sayfile(mychannel, "rpt/fast");
03506 break;
03507 default:
03508 res = -1;
03509 }
03510 wait_interval(myrpt, DLY_COMP, mychannel);
03511 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03512 break;
03513 case SCAN:
03514 ast_mutex_lock(&myrpt->remlock);
03515 if (myrpt->hfscanstop)
03516 {
03517 myrpt->hfscanstatus = 0;
03518 myrpt->hfscanmode = 0;
03519 myrpt->hfscanstop = 0;
03520 mytele->mode = SCANSTAT;
03521 ast_mutex_unlock(&myrpt->remlock);
03522 if (ast_safe_sleep(mychannel,1000) == -1) break;
03523 sayfile(mychannel, "rpt/stop");
03524 imdone = 1;
03525 break;
03526 }
03527 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
03528 i = myrpt->hfscanstatus;
03529 myrpt->hfscanstatus = 0;
03530 if (i) mytele->mode = SCANSTAT;
03531 ast_mutex_unlock(&myrpt->remlock);
03532 if (i < 0) sayfile(mychannel, "rpt/stop");
03533 else if (i > 0) saynum(mychannel,i);
03534 imdone = 1;
03535 break;
03536 case TUNE:
03537 ast_mutex_lock(&myrpt->remlock);
03538 if (!strcmp(myrpt->remote,remote_rig_ic706))
03539 {
03540 set_mode_ic706(myrpt, REM_MODE_AM);
03541 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03542 ast_safe_sleep(mychannel,500);
03543 set_mode_ic706(myrpt, myrpt->remmode);
03544 myrpt->tunerequest = 0;
03545 ast_mutex_unlock(&myrpt->remlock);
03546 imdone = 1;
03547 break;
03548 }
03549 set_mode_ft897(myrpt, REM_MODE_AM);
03550 simple_command_ft897(myrpt, 8);
03551 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03552 simple_command_ft897(myrpt, 0x88);
03553 ast_safe_sleep(mychannel,500);
03554 set_mode_ft897(myrpt, myrpt->remmode);
03555 myrpt->tunerequest = 0;
03556 ast_mutex_unlock(&myrpt->remlock);
03557 imdone = 1;
03558 break;
03559 case REMSHORTSTATUS:
03560 case REMLONGSTATUS:
03561 wait_interval(myrpt, DLY_TELEM, mychannel);
03562 res = sayfile(mychannel,"rpt/node");
03563 if(!res)
03564 res = saycharstr(mychannel, myrpt->name);
03565 if(!res)
03566 res = sayfile(mychannel,"rpt/frequency");
03567 if(!res)
03568 res = split_freq(mhz, decimals, myrpt->freq);
03569 if (!multimode_capable(myrpt)) decimals[3] = 0;
03570 if(!res){
03571 m = atoi(mhz);
03572 if(m < 100)
03573 res = saynum(mychannel, m);
03574 else
03575 res = saycharstr(mychannel, mhz);
03576 }
03577 if(!res)
03578 res = sayfile(mychannel, "letters/dot");
03579 if(!res)
03580 res = saycharstr(mychannel, decimals);
03581
03582 if(res) break;
03583 if(myrpt->remmode == REM_MODE_FM){
03584 switch(myrpt->offset){
03585
03586 case REM_MINUS:
03587 res = sayfile(mychannel,"rpt/minus");
03588 break;
03589
03590 case REM_SIMPLEX:
03591 res = sayfile(mychannel,"rpt/simplex");
03592 break;
03593
03594 case REM_PLUS:
03595 res = sayfile(mychannel,"rpt/plus");
03596 break;
03597
03598 default:
03599 break;
03600 }
03601 }
03602 else{
03603 switch(myrpt->remmode){
03604
03605 case REM_MODE_USB:
03606 res = saycharstr(mychannel, "USB");
03607 break;
03608
03609 case REM_MODE_LSB:
03610 res = saycharstr(mychannel, "LSB");
03611 break;
03612
03613 case REM_MODE_AM:
03614 res = saycharstr(mychannel, "AM");
03615 break;
03616
03617
03618 default:
03619 break;
03620 }
03621 }
03622
03623 if (res == -1) break;
03624
03625 if(mytele->mode == REMSHORTSTATUS){
03626 wait_interval(myrpt, DLY_COMP, mychannel);
03627 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03628 break;
03629 }
03630
03631 if (strcmp(myrpt->remote,remote_rig_ic706))
03632 {
03633 switch(myrpt->powerlevel){
03634
03635 case REM_LOWPWR:
03636 res = sayfile(mychannel,"rpt/lopwr") ;
03637 break;
03638 case REM_MEDPWR:
03639 res = sayfile(mychannel,"rpt/medpwr");
03640 break;
03641 case REM_HIPWR:
03642 res = sayfile(mychannel,"rpt/hipwr");
03643 break;
03644 }
03645 }
03646
03647 rbimode = ((!strncmp(myrpt->remote,remote_rig_rbi,3))
03648 || (!strncmp(myrpt->remote,remote_rig_ic706,3)));
03649 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
03650 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
03651 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
03652 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
03653 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
03654 (sayfile(mychannel,"rpt/frequency") == -1) ||
03655 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
03656 if(myrpt->remmode == REM_MODE_FM){
03657 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
03658 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
03659 (sayfile(mychannel,"rpt/txpl") == -1) ||
03660 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
03661 {
03662 break;
03663 }
03664 }
03665 wait_interval(myrpt, DLY_COMP, mychannel);
03666 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03667 break;
03668 case STATUS:
03669
03670 wait_interval(myrpt, DLY_TELEM, mychannel);
03671 hastx = 0;
03672 linkbase.next = &linkbase;
03673 linkbase.prev = &linkbase;
03674 rpt_mutex_lock(&myrpt->lock);
03675
03676 l = myrpt->links.next;
03677 while(l != &myrpt->links)
03678 {
03679 if (l->name[0] == '0')
03680 {
03681 l = l->next;
03682 continue;
03683 }
03684 l1 = malloc(sizeof(struct rpt_link));
03685 if (!l1)
03686 {
03687 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
03688 remque((struct qelem *)mytele);
03689 rpt_mutex_unlock(&myrpt->lock);
03690 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03691 free(mytele);
03692 ast_hangup(mychannel);
03693 pthread_exit(NULL);
03694 }
03695 memcpy(l1,l,sizeof(struct rpt_link));
03696 l1->next = l1->prev = NULL;
03697 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
03698 l = l->next;
03699 }
03700 rpt_mutex_unlock(&myrpt->lock);
03701 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03702 if (!res)
03703 res = ast_waitstream(mychannel, "");
03704 else
03705 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03706 ast_stopstream(mychannel);
03707 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03708 if (!res)
03709 res = ast_waitstream(mychannel, "");
03710 else
03711 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03712 ast_stopstream(mychannel);
03713 if (myrpt->callmode)
03714 {
03715 hastx = 1;
03716 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03717 if (!res)
03718 res = ast_waitstream(mychannel, "");
03719 else
03720 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03721 ast_stopstream(mychannel);
03722 }
03723 l = linkbase.next;
03724 while(l != &linkbase)
03725 {
03726 char *s;
03727
03728 hastx = 1;
03729 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03730 if (!res)
03731 res = ast_waitstream(mychannel, "");
03732 else
03733 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03734 ast_stopstream(mychannel);
03735 ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
03736 if (!res)
03737 res = ast_waitstream(mychannel, "");
03738 else
03739 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03740 ast_stopstream(mychannel);
03741 s = "rpt/tranceive";
03742 if (!l->mode) s = "rpt/monitor";
03743 if (!l->thisconnected) s = "rpt/connecting";
03744 res = ast_streamfile(mychannel, s, mychannel->language);
03745 if (!res)
03746 res = ast_waitstream(mychannel, "");
03747 else
03748 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03749 ast_stopstream(mychannel);
03750 l = l->next;
03751 }
03752 if (!hastx)
03753 {
03754 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03755 if (!res)
03756 res = ast_waitstream(mychannel, "");
03757 else
03758 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03759 ast_stopstream(mychannel);
03760 }
03761
03762 l = linkbase.next;
03763 while(l != &linkbase)
03764 {
03765 l1 = l;
03766 l = l->next;
03767 remque((struct qelem *)l1);
03768 free(l1);
03769 }
03770 imdone = 1;
03771 break;
03772 case FULLSTATUS:
03773 rpt_mutex_lock(&myrpt->lock);
03774
03775 __mklinklist(myrpt,NULL,lbuf);
03776 rpt_mutex_unlock(&myrpt->lock);
03777
03778 ns = finddelim(lbuf,strs,MAXLINKLIST);
03779
03780 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03781
03782 wait_interval(myrpt, DLY_TELEM, mychannel);
03783 hastx = 0;
03784 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03785 if (!res)
03786 res = ast_waitstream(mychannel, "");
03787 else
03788 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03789 ast_stopstream(mychannel);
03790 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03791 if (!res)
03792 res = ast_waitstream(mychannel, "");
03793 else
03794 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03795 ast_stopstream(mychannel);
03796 if (myrpt->callmode)
03797 {
03798 hastx = 1;
03799 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03800 if (!res)
03801 res = ast_waitstream(mychannel, "");
03802 else
03803 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03804 ast_stopstream(mychannel);
03805 }
03806
03807 for(i = 0; i < ns; i++)
03808 {
03809 char *s,mode = 'T';
03810
03811
03812 if ((*strs[i] < '0') || (*strs[i] > '9'))
03813 {
03814 mode = *strs[i];
03815 strs[i]++;
03816 }
03817
03818 hastx = 1;
03819 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03820 if (!res)
03821 res = ast_waitstream(mychannel, "");
03822 else
03823 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03824 ast_stopstream(mychannel);
03825 ast_say_character_str(mychannel,strs[i],NULL,mychannel->language);
03826 if (!res)
03827 res = ast_waitstream(mychannel, "");
03828 else
03829 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03830 ast_stopstream(mychannel);
03831 s = "rpt/tranceive";
03832 if (mode == 'R') s = "rpt/monitor";
03833 if (mode == 'C') s = "rpt/connecting";
03834 res = ast_streamfile(mychannel, s, mychannel->language);
03835 if (!res)
03836 res = ast_waitstream(mychannel, "");
03837 else
03838 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03839 ast_stopstream(mychannel);
03840 }
03841 if (!hastx)
03842 {
03843 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03844 if (!res)
03845 res = ast_waitstream(mychannel, "");
03846 else
03847 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03848 ast_stopstream(mychannel);
03849 }
03850 imdone = 1;
03851 break;
03852
03853 case LASTNODEKEY:
03854 rpt_mutex_lock(&myrpt->lock);
03855 if(myrpt->lastnodewhichkeyedusup)
03856 p = ast_strdupa(myrpt->lastnodewhichkeyedusup);
03857 else
03858 p = NULL;
03859 rpt_mutex_unlock(&myrpt->lock);
03860 if(!p){
03861 imdone = 1;
03862 break;
03863 }
03864 wait_interval(myrpt, DLY_TELEM, mychannel);
03865 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03866 if (!res)
03867 res = ast_waitstream(mychannel, "");
03868 else
03869 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03870 ast_stopstream(mychannel);
03871 ast_say_character_str(mychannel, p, NULL, mychannel->language);
03872 if (!res)
03873 res = ast_waitstream(mychannel, "");
03874 else
03875 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03876 ast_stopstream(mychannel);
03877 imdone = 1;
03878 break;
03879
03880 case UNAUTHTX:
03881 wait_interval(myrpt, DLY_TELEM, mychannel);
03882 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
03883 if (!res)
03884 res = ast_waitstream(mychannel, "");
03885 else
03886 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03887 ast_stopstream(mychannel);
03888 imdone = 1;
03889 break;
03890
03891
03892 case TIMEOUT:
03893 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03894 if (!res)
03895 res = ast_waitstream(mychannel, "");
03896 else
03897 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03898 ast_stopstream(mychannel);
03899 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03900 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
03901 break;
03902
03903 case TIMEOUT_WARNING:
03904 time(&t);
03905 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03906 if (!res)
03907 res = ast_waitstream(mychannel, "");
03908 else
03909 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03910 ast_stopstream(mychannel);
03911 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03912 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
03913 if (!res)
03914 res = ast_waitstream(mychannel, "");
03915 else
03916 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03917 ast_stopstream(mychannel);
03918 if(!res)
03919 ast_say_number(mychannel, myrpt->p.remotetimeout -
03920 (t - myrpt->last_activity_time),
03921 "", mychannel->language, (char *) NULL);
03922 if (!res)
03923 res = ast_waitstream(mychannel, "");
03924 ast_stopstream(mychannel);
03925 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03926 break;
03927
03928 case ACT_TIMEOUT_WARNING:
03929 time(&t);
03930 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03931 if (!res)
03932 res = ast_waitstream(mychannel, "");
03933 else
03934 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03935 ast_stopstream(mychannel);
03936 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03937 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
03938 if (!res)
03939 res = ast_waitstream(mychannel, "");
03940 else
03941 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03942 ast_stopstream(mychannel);
03943 if(!res)
03944 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
03945 (t - myrpt->last_activity_time),
03946 "", mychannel->language, (char *) NULL);
03947 if (!res)
03948 res = ast_waitstream(mychannel, "");
03949 ast_stopstream(mychannel);
03950 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03951 break;
03952
03953 case STATS_TIME:
03954 wait_interval(myrpt, DLY_TELEM, mychannel);
03955 t = time(NULL);
03956 rpt_localtime(&t, &localtm);
03957
03958 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
03959 p = "rpt/goodmorning";
03960 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
03961 p = "rpt/goodafternoon";
03962 else
03963 p = "rpt/goodevening";
03964 if (sayfile(mychannel,p) == -1)
03965 {
03966 imdone = 1;
03967 break;
03968 }
03969
03970 if (sayfile(mychannel,"rpt/thetimeis") == -1)
03971 {
03972 imdone = 1;
03973 break;
03974 }
03975
03976 res = ast_say_time(mychannel, t, "", mychannel->language);
03977 if (!res)
03978 res = ast_waitstream(mychannel, "");
03979 ast_stopstream(mychannel);
03980 imdone = 1;
03981 break;
03982 case STATS_VERSION:
03983 p = strstr(tdesc, "version");
03984 if(!p)
03985 break;
03986 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
03987 break;
03988 wait_interval(myrpt, DLY_TELEM, mychannel);
03989
03990 if (sayfile(mychannel,"rpt/version") == -1)
03991 {
03992 imdone = 1;
03993 break;
03994 }
03995 if(!res)
03996 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
03997 if (!res)
03998 res = ast_waitstream(mychannel, "");
03999 ast_stopstream(mychannel);
04000 if (saycharstr(mychannel,".") == -1)
04001 {
04002 imdone = 1;
04003 break;
04004 }
04005 if(!res)
04006 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
04007 if (!res){
04008 res = ast_waitstream(mychannel, "");
04009 ast_stopstream(mychannel);
04010 }
04011 else
04012 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04013 imdone = 1;
04014 break;
04015 case ARB_ALPHA:
04016 wait_interval(myrpt, DLY_TELEM, mychannel);
04017 if(mytele->param)
04018 saycharstr(mychannel, mytele->param);
04019 imdone = 1;
04020 break;
04021 case REV_PATCH:
04022 wait_interval(myrpt, DLY_TELEM, mychannel);
04023 if(mytele->param) {
04024
04025
04026 char *tpl_working, *tpl_current;
04027 char *tmp[100], *myparm;
04028 int looptemp=0,i=0, dres = 0;
04029
04030
04031 tpl_working = strdupa(mytele->param);
04032 myparm = strsep(&tpl_working,",");
04033 tpl_current=strsep(&tpl_working, ":");
04034
04035 while(tpl_current && looptemp < sizeof(tmp)) {
04036 tmp[looptemp]=tpl_current;
04037 looptemp++;
04038 tpl_current=strsep(&tpl_working,":");
04039 }
04040
04041 for(i=0; i<looptemp; i++) {
04042 if(!strcmp(tmp[i], "PARKED")) {
04043 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
04044 } else if(!strcmp(tmp[i], "NODE")) {
04045 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
04046 } else {
04047 dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
04048 if(!dres) {
04049 dres = ast_waitstream(mychannel, "");
04050 } else {
04051 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
04052 dres = 0;
04053 }
04054 }
04055 }
04056 }
04057 imdone = 1;
04058 break;
04059 case TEST_TONE:
04060 imdone = 1;
04061 if (myrpt->stopgen) break;
04062 myrpt->stopgen = -1;
04063 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
04064 {
04065 myrpt->stopgen = 0;
04066 break;
04067 }
04068 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
04069 if (ast_safe_sleep(mychannel,1)) break;
04070 imdone = 1;
04071 }
04072 myrpt->stopgen = 0;
04073 break;
04074 default:
04075 break;
04076 }
04077 if (!imdone)
04078 {
04079 if (!res)
04080 res = ast_waitstream(mychannel, "");
04081 else {
04082 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04083 res = 0;
04084 }
04085 }
04086 ast_stopstream(mychannel);
04087 rpt_mutex_lock(&myrpt->lock);
04088 if (mytele->mode == TAILMSG)
04089 {
04090 if (!res)
04091 {
04092 myrpt->tailmessagen++;
04093 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
04094 }
04095 else
04096 {
04097 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
04098 }
04099 }
04100 remque((struct qelem *)mytele);
04101 rpt_mutex_unlock(&myrpt->lock);
04102 free(mytele);
04103 ast_hangup(mychannel);
04104 #ifdef APP_RPT_LOCK_DEBUG
04105 {
04106 struct lockthread *t;
04107
04108 sleep(5);
04109 ast_mutex_lock(&locklock);
04110 t = get_lockthread(pthread_self());
04111 if (t) memset(t,0,sizeof(struct lockthread));
04112 ast_mutex_unlock(&locklock);
04113 }
04114 #endif
04115 pthread_exit(NULL);
04116 }
04117
04118 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
04119 {
04120 struct rpt_tele *tele;
04121 struct rpt_link *mylink = (struct rpt_link *) data;
04122 int res;
04123 pthread_attr_t attr;
04124
04125 tele = malloc(sizeof(struct rpt_tele));
04126 if (!tele)
04127 {
04128 ast_log(LOG_WARNING, "Unable to allocate memory\n");
04129 pthread_exit(NULL);
04130 return;
04131 }
04132
04133 memset((char *)tele,0,sizeof(struct rpt_tele));
04134 tele->rpt = myrpt;
04135 tele->mode = mode;
04136 rpt_mutex_lock(&myrpt->lock);
04137 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
04138 (mode == LINKUNKEY)){
04139 memset(&tele->mylink,0,sizeof(struct rpt_link));
04140 if (mylink){
04141 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
04142 }
04143 }
04144 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
04145 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
04146 tele->param[TELEPARAMSIZE - 1] = 0;
04147 }
04148 if (mode == REMXXX) tele->submode = (intptr_t) data;
04149 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
04150 rpt_mutex_unlock(&myrpt->lock);
04151 pthread_attr_init(&attr);
04152 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04153 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
04154 if(res < 0){
04155 rpt_mutex_lock(&myrpt->lock);
04156 remque((struct qlem *) tele);
04157 rpt_mutex_unlock(&myrpt->lock);
04158 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
04159 }
04160 return;
04161 }
04162
04163 static void *rpt_call(void *this)
04164 {
04165 struct dahdi_confinfo ci;
04166 struct rpt *myrpt = (struct rpt *)this;
04167 int res;
04168 int stopped,congstarted,dialtimer,lastcidx,aborted;
04169 struct ast_channel *mychannel,*genchannel;
04170
04171
04172 myrpt->mydtmf = 0;
04173
04174 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04175 if (!mychannel)
04176 {
04177 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04178 pthread_exit(NULL);
04179 }
04180 #ifdef AST_CDR_FLAG_POST_DISABLED
04181 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04182 #endif
04183 ci.chan = 0;
04184 ci.confno = myrpt->conf;
04185 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
04186 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04187
04188 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04189 {
04190 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04191 ast_hangup(mychannel);
04192 myrpt->callmode = 0;
04193 pthread_exit(NULL);
04194 }
04195
04196 genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04197 if (!genchannel)
04198 {
04199 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04200 ast_hangup(mychannel);
04201 pthread_exit(NULL);
04202 }
04203 #ifdef AST_CDR_FLAG_POST_DISABLED
04204 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04205 #endif
04206 ci.chan = 0;
04207 ci.confno = myrpt->conf;
04208 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
04209 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04210
04211 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04212 {
04213 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04214 ast_hangup(mychannel);
04215 ast_hangup(genchannel);
04216 myrpt->callmode = 0;
04217 pthread_exit(NULL);
04218 }
04219 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
04220 {
04221 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04222 ast_hangup(mychannel);
04223 ast_hangup(genchannel);
04224 myrpt->callmode = 0;
04225 pthread_exit(NULL);
04226 }
04227 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
04228 {
04229 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04230 ast_hangup(mychannel);
04231 ast_hangup(genchannel);
04232 myrpt->callmode = 0;
04233 pthread_exit(NULL);
04234 }
04235
04236 if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
04237 {
04238 ast_log(LOG_WARNING, "Cannot start dialtone\n");
04239 ast_hangup(mychannel);
04240 ast_hangup(genchannel);
04241 myrpt->callmode = 0;
04242 pthread_exit(NULL);
04243 }
04244 stopped = 0;
04245 congstarted = 0;
04246 dialtimer = 0;
04247 lastcidx = 0;
04248 aborted = 0;
04249
04250
04251 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
04252 {
04253
04254 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
04255 dialtimer = 0;
04256 lastcidx = myrpt->cidx;
04257 }
04258
04259 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
04260 rpt_mutex_lock(&myrpt->lock);
04261 aborted = 1;
04262 myrpt->callmode = 0;
04263 rpt_mutex_unlock(&myrpt->lock);
04264 break;
04265 }
04266
04267 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
04268 {
04269 stopped = 1;
04270
04271 tone_zone_play_tone(mychannel->fds[0],-1);
04272 }
04273 if (myrpt->callmode == 4)
04274 {
04275 if(!congstarted){
04276 congstarted = 1;
04277
04278 tone_zone_play_tone(mychannel->fds[0],DAHDI_TONE_CONGESTION);
04279 }
04280 }
04281 res = ast_safe_sleep(mychannel, MSWAIT);
04282 if (res < 0)
04283 {
04284 ast_hangup(mychannel);
04285 ast_hangup(genchannel);
04286 rpt_mutex_lock(&myrpt->lock);
04287 myrpt->callmode = 0;
04288 rpt_mutex_unlock(&myrpt->lock);
04289 pthread_exit(NULL);
04290 }
04291 dialtimer += MSWAIT;
04292 }
04293
04294 tone_zone_play_tone(mychannel->fds[0],-1);
04295
04296 if (!myrpt->callmode)
04297 {
04298 ast_hangup(mychannel);
04299 ast_hangup(genchannel);
04300 rpt_mutex_lock(&myrpt->lock);
04301 myrpt->callmode = 0;
04302 rpt_mutex_unlock(&myrpt->lock);
04303 if((!myrpt->patchquiet) && aborted)
04304 rpt_telemetry(myrpt, TERM, NULL);
04305 pthread_exit(NULL);
04306 }
04307
04308 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
04309 char *name, *loc, *instr;
04310 instr = strdup(myrpt->p.ourcallerid);
04311 if(instr){
04312 ast_callerid_parse(instr, &name, &loc);
04313 if(loc){
04314 if(mychannel->cid.cid_num)
04315 free(mychannel->cid.cid_num);
04316 mychannel->cid.cid_num = strdup(loc);
04317 }
04318 if(name){
04319 if(mychannel->cid.cid_name)
04320 free(mychannel->cid.cid_name);
04321 mychannel->cid.cid_name = strdup(name);
04322 }
04323 free(instr);
04324 }
04325 }
04326
04327 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
04328 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
04329
04330 if (myrpt->p.acctcode)
04331 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
04332 mychannel->priority = 1;
04333 ast_channel_undefer_dtmf(mychannel);
04334 if (ast_pbx_start(mychannel) < 0)
04335 {
04336 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
04337 ast_hangup(mychannel);
04338 ast_hangup(genchannel);
04339 rpt_mutex_lock(&myrpt->lock);
04340 myrpt->callmode = 0;
04341 rpt_mutex_unlock(&myrpt->lock);
04342 pthread_exit(NULL);
04343 }
04344 usleep(10000);
04345 rpt_mutex_lock(&myrpt->lock);
04346 myrpt->callmode = 3;
04347
04348 ci.chan = 0;
04349 ci.confno = myrpt->conf;
04350 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
04351 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
04352
04353 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04354 {
04355 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04356 ast_hangup(mychannel);
04357 ast_hangup(genchannel);
04358 myrpt->callmode = 0;
04359 pthread_exit(NULL);
04360 }
04361 while(myrpt->callmode)
04362 {
04363 if ((!mychannel->pbx) && (myrpt->callmode != 4))
04364 {
04365 if(myrpt->patchfarenddisconnect){
04366 myrpt->callmode = 0;
04367 if(!myrpt->patchquiet){
04368 rpt_mutex_unlock(&myrpt->lock);
04369 rpt_telemetry(myrpt, TERM, NULL);
04370 rpt_mutex_lock(&myrpt->lock);
04371 }
04372 }
04373 else{
04374 myrpt->callmode = 4;
04375 rpt_mutex_unlock(&myrpt->lock);
04376
04377 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
04378 rpt_mutex_lock(&myrpt->lock);
04379 }
04380 }
04381 if (myrpt->mydtmf)
04382 {
04383 struct ast_frame wf = {AST_FRAME_DTMF, } ;
04384 wf.subclass = myrpt->mydtmf;
04385 rpt_mutex_unlock(&myrpt->lock);
04386 ast_queue_frame(mychannel,&wf);
04387 ast_senddigit(genchannel,myrpt->mydtmf);
04388 rpt_mutex_lock(&myrpt->lock);
04389 myrpt->mydtmf = 0;
04390 }
04391 rpt_mutex_unlock(&myrpt->lock);
04392 usleep(MSWAIT * 1000);
04393 rpt_mutex_lock(&myrpt->lock);
04394 }
04395 rpt_mutex_unlock(&myrpt->lock);
04396 tone_zone_play_tone(genchannel->fds[0],-1);
04397 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
04398 ast_hangup(genchannel);
04399 rpt_mutex_lock(&myrpt->lock);
04400 myrpt->callmode = 0;
04401 rpt_mutex_unlock(&myrpt->lock);
04402
04403 ci.chan = 0;
04404 ci.confno = myrpt->conf;
04405 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
04406 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
04407
04408 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04409 {
04410 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04411 }
04412 pthread_exit(NULL);
04413 }
04414
04415 static void send_link_dtmf(struct rpt *myrpt,char c)
04416 {
04417 char str[300];
04418 struct ast_frame wf;
04419 struct rpt_link *l;
04420
04421 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
04422 wf.frametype = AST_FRAME_TEXT;
04423 wf.subclass = 0;
04424 wf.offset = 0;
04425 wf.mallocd = 0;
04426 wf.datalen = strlen(str) + 1;
04427 wf.samples = 0;
04428 l = myrpt->links.next;
04429
04430 while(l != &myrpt->links)
04431 {
04432 if (l->name[0] == '0')
04433 {
04434 l = l->next;
04435 continue;
04436 }
04437
04438 if (!strcmp(l->name,myrpt->cmdnode))
04439 {
04440 wf.data = str;
04441 if (l->chan) ast_write(l->chan,&wf);
04442 return;
04443 }
04444 l = l->next;
04445 }
04446 l = myrpt->links.next;
04447
04448 while(l != &myrpt->links)
04449 {
04450 wf.data = str;
04451 if (l->chan) ast_write(l->chan,&wf);
04452 l = l->next;
04453 }
04454 return;
04455 }
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
04468 {
04469 char *val, *s, *s1, *s2, *tele;
04470 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
04471 char tmp[300], deststr[300] = "",modechange = 0;
04472 struct rpt_link *l;
04473 int reconnects = 0;
04474 int i,n;
04475 struct dahdi_confinfo ci;
04476
04477 val = node_lookup(myrpt,node);
04478 if (!val){
04479 if(strlen(node) >= myrpt->longestnode)
04480 return -1;
04481 return 1;
04482 }
04483 if(debug > 3){
04484 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
04485 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
04486 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
04487 }
04488
04489 strncpy(tmp,val,sizeof(tmp) - 1);
04490 s = tmp;
04491 s1 = strsep(&s,",");
04492 s2 = strsep(&s,",");
04493 rpt_mutex_lock(&myrpt->lock);
04494 l = myrpt->links.next;
04495
04496 while(l != &myrpt->links){
04497 if (l->name[0] == '0')
04498 {
04499 l = l->next;
04500 continue;
04501 }
04502
04503 if (!strcmp(l->name, node))
04504 break;
04505 l = l->next;
04506 }
04507
04508 if (l != &myrpt->links){
04509
04510 if ((l->mode) || (!l->chan)) {
04511 rpt_mutex_unlock(&myrpt->lock);
04512 return 2;
04513 }
04514 reconnects = l->reconnects;
04515 rpt_mutex_unlock(&myrpt->lock);
04516 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
04517 l->retries = l->max_retries + 1;
04518 l->disced = 2;
04519 modechange = 1;
04520 } else
04521 {
04522 __mklinklist(myrpt,NULL,lstr);
04523 rpt_mutex_unlock(&myrpt->lock);
04524 n = finddelim(lstr,strs,MAXLINKLIST);
04525 for(i = 0; i < n; i++)
04526 {
04527 if ((*strs[i] < '0') ||
04528 (*strs[i] > '9')) strs[i]++;
04529 if (!strcmp(strs[i],node))
04530 {
04531 return 2;
04532 }
04533 }
04534 }
04535 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
04536
04537 l = malloc(sizeof(struct rpt_link));
04538 if (!l)
04539 {
04540 ast_log(LOG_WARNING, "Unable to malloc\n");
04541 return -1;
04542 }
04543
04544 memset((char *)l,0,sizeof(struct rpt_link));
04545 l->mode = mode;
04546 l->outbound = 1;
04547 l->thisconnected = 0;
04548 strncpy(l->name, node, MAXNODESTR - 1);
04549 l->isremote = (s && ast_true(s));
04550 if (modechange) l->connected = 1;
04551 l->hasconnected = l->perma = perma;
04552 #ifdef ALLOW_LOCAL_CHANNELS
04553 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
04554 strncpy(deststr, s1, sizeof(deststr));
04555 else
04556 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04557 #else
04558 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04559 #endif
04560 tele = strchr(deststr, '/');
04561 if (!tele){
04562 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
04563 free(l);
04564 return -1;
04565 }
04566 *tele++ = 0;
04567 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04568 if (l->chan){
04569 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04570 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04571 #ifdef AST_CDR_FLAG_POST_DISABLED
04572 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
04573 #endif
04574 l->chan->whentohangup = 0;
04575 l->chan->appl = "Apprpt";
04576 l->chan->data = "(Remote Rx)";
04577 if (debug > 3)
04578 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
04579 deststr, tele, l->chan->name);
04580 if(l->chan->cid.cid_num)
04581 free(l->chan->cid.cid_num);
04582 l->chan->cid.cid_num = strdup(myrpt->name);
04583 ast_call(l->chan,tele,999);
04584 }
04585 else {
04586 if(debug > 3)
04587 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
04588 deststr,tele,l->chan->name);
04589 if (myrpt->p.archivedir)
04590 {
04591 char str[100];
04592 sprintf(str,"LINKFAIL,%s",l->name);
04593 donodelog(myrpt,str);
04594 }
04595 free(l);
04596 return -1;
04597 }
04598
04599 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04600 if (!l->pchan){
04601 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
04602 ast_hangup(l->chan);
04603 free(l);
04604 return -1;
04605 }
04606 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
04607 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
04608 #ifdef AST_CDR_FLAG_POST_DISABLED
04609 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
04610 #endif
04611
04612 ci.chan = 0;
04613 ci.confno = myrpt->conf;
04614 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
04615
04616 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
04617 {
04618 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04619 ast_hangup(l->chan);
04620 ast_hangup(l->pchan);
04621 free(l);
04622 return -1;
04623 }
04624 rpt_mutex_lock(&myrpt->lock);
04625 l->reconnects = reconnects;
04626
04627 l->max_retries = MAX_RETRIES;
04628 if (perma)
04629 l->max_retries = MAX_RETRIES_PERM;
04630 if (l->isremote) l->retries = l->max_retries + 1;
04631 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04632 __kickshort(myrpt);
04633 rpt_mutex_unlock(&myrpt->lock);
04634 return 0;
04635 }
04636
04637
04638
04639
04640
04641
04642
04643 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
04644 {
04645
04646 char *val, *s, *s1, *s2;
04647 char tmp[300];
04648 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
04649 char mode,perma;
04650 struct rpt_link *l;
04651 int i,r;
04652
04653 if(!param)
04654 return DC_ERROR;
04655
04656
04657 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
04658 return DC_ERROR;
04659
04660 strncpy(digitbuf,digits,MAXNODESTR - 1);
04661
04662 if(debug > 6)
04663 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
04664
04665 switch(myatoi(param)){
04666 case 11:
04667 case 1:
04668 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04669 strcpy(digitbuf,myrpt->lastlinknode);
04670 val = node_lookup(myrpt,digitbuf);
04671 if (!val){
04672 if(strlen(digitbuf) >= myrpt->longestnode)
04673 return DC_ERROR;
04674 break;
04675 }
04676 strncpy(tmp,val,sizeof(tmp) - 1);
04677 s = tmp;
04678 s1 = strsep(&s,",");
04679 s2 = strsep(&s,",");
04680 rpt_mutex_lock(&myrpt->lock);
04681 l = myrpt->links.next;
04682
04683 while(l != &myrpt->links){
04684 if (l->name[0] == '0')
04685 {
04686 l = l->next;
04687 continue;
04688 }
04689
04690 if (!strcmp(l->name, digitbuf))
04691 break;
04692 l = l->next;
04693 }
04694 if (l != &myrpt->links){
04695 struct ast_frame wf;
04696
04697
04698 if ((myatoi(param) < 10) &&
04699 (l->max_retries > MAX_RETRIES))
04700 {
04701 rpt_mutex_unlock(&myrpt->lock);
04702 return DC_COMPLETE;
04703 }
04704 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
04705 l->retries = l->max_retries + 1;
04706 l->disced = 1;
04707 rpt_mutex_unlock(&myrpt->lock);
04708 wf.frametype = AST_FRAME_TEXT;
04709 wf.subclass = 0;
04710 wf.offset = 0;
04711 wf.mallocd = 0;
04712 wf.datalen = strlen(discstr) + 1;
04713 wf.samples = 0;
04714 wf.data = discstr;
04715 if (l->chan)
04716 {
04717 ast_write(l->chan,&wf);
04718 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
04719 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04720 }
04721 rpt_telemetry(myrpt, COMPLETE, NULL);
04722 return DC_COMPLETE;
04723 }
04724 rpt_mutex_unlock(&myrpt->lock);
04725 return DC_COMPLETE;
04726 case 2:
04727 case 3:
04728 case 12:
04729 case 13:
04730 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04731 strcpy(digitbuf,myrpt->lastlinknode);
04732
04733 perma = (atoi(param) > 10) ? 1 : 0;
04734 mode = (atoi(param) & 1) ? 1 : 0;
04735 r = connect_link(myrpt, digitbuf, mode, perma);
04736 switch(r){
04737 case 0:
04738 rpt_telemetry(myrpt, COMPLETE, NULL);
04739 return DC_COMPLETE;
04740
04741 case 1:
04742 break;
04743
04744 case 2:
04745 rpt_telemetry(myrpt, REMALREADY, NULL);
04746 return DC_COMPLETE;
04747
04748 default:
04749 rpt_telemetry(myrpt, CONNFAIL, NULL);
04750 return DC_COMPLETE;
04751 }
04752 break;
04753
04754 case 4:
04755
04756
04757 if (((command_source != SOURCE_RPT) &&
04758 (command_source != SOURCE_PHONE) &&
04759 (command_source != SOURCE_DPHONE)) ||
04760 (myrpt->links.next == &myrpt->links))
04761 return DC_COMPLETE;
04762
04763
04764 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
04765
04766 rpt_telemetry(myrpt, REMALREADY, NULL);
04767 return DC_COMPLETE;
04768 }
04769 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04770 strcpy(digitbuf,myrpt->lastlinknode);
04771
04772 val = node_lookup(myrpt,digitbuf);
04773 if (!val){
04774 if(strlen(digitbuf) >= myrpt->longestnode)
04775 return DC_ERROR;
04776 break;
04777
04778 }
04779 rpt_mutex_lock(&myrpt->lock);
04780 strcpy(myrpt->lastlinknode,digitbuf);
04781 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
04782 rpt_mutex_unlock(&myrpt->lock);
04783 rpt_telemetry(myrpt, REMGO, NULL);
04784 return DC_COMPLETE;
04785
04786 case 5:
04787 rpt_telemetry(myrpt, STATUS, NULL);
04788 return DC_COMPLETE;
04789
04790 case 15:
04791 rpt_telemetry(myrpt, FULLSTATUS, NULL);
04792 return DC_COMPLETE;
04793
04794
04795 case 6:
04796 rpt_mutex_lock(&myrpt->lock);
04797 myrpt->savednodes[0] = 0;
04798 l = myrpt->links.next;
04799
04800 while(l != &myrpt->links){
04801 struct ast_frame wf;
04802 if (l->name[0] == '0')
04803 {
04804 l = l->next;
04805 continue;
04806 }
04807
04808 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
04809 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
04810 if(myrpt->savednodes[0])
04811 strcat(myrpt->savednodes, ",");
04812 strcat(myrpt->savednodes, tmp);
04813 }
04814 l->retries = l->max_retries + 1;
04815 l->disced = 2;
04816 rpt_mutex_unlock(&myrpt->lock);
04817
04818
04819 wf.frametype = AST_FRAME_TEXT;
04820 wf.subclass = 0;
04821 wf.offset = 0;
04822 wf.mallocd = 0;
04823 wf.datalen = strlen(discstr) + 1;
04824 wf.samples = 0;
04825 wf.data = discstr;
04826 if (l->chan)
04827 {
04828 ast_write(l->chan,&wf);
04829 ast_safe_sleep(l->chan,250);
04830 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04831 }
04832 rpt_mutex_lock(&myrpt->lock);
04833 l = l->next;
04834 }
04835 rpt_mutex_unlock(&myrpt->lock);
04836 if(debug > 3)
04837 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
04838 rpt_telemetry(myrpt, COMPLETE, NULL);
04839 return DC_COMPLETE;
04840
04841 case 7:
04842 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
04843 break;
04844
04845
04846 #ifdef _MDC_DECODE_H_
04847 case 8:
04848 myrpt->lastunit = 0xd00d;
04849 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
04850 mdc1200_send(myrpt,myrpt->lastunit);
04851 break;
04852 #endif
04853
04854 case 16:
04855 strcpy(tmp, myrpt->savednodes);
04856 finddelim(tmp, strs, MAXLINKLIST);
04857 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
04858 s1 = strs[i];
04859 mode = (s1[0] == 'X') ? 1 : 0;
04860 perma = (s1[1] == 'P') ? 1 : 0;
04861 connect_link(myrpt, s1 + 2, mode, perma);
04862 }
04863 rpt_telemetry(myrpt, COMPLETE, NULL);
04864 break;
04865
04866 case 200:
04867 case 201:
04868 case 202:
04869 case 203:
04870 case 204:
04871 case 205:
04872 case 206:
04873 case 207:
04874 case 208:
04875 case 209:
04876 case 210:
04877 case 211:
04878 case 212:
04879 case 213:
04880 case 214:
04881 case 215:
04882 if (((myrpt->p.propagate_dtmf) &&
04883 (command_source == SOURCE_LNK)) ||
04884 ((myrpt->p.propagate_phonedtmf) &&
04885 ((command_source == SOURCE_PHONE) ||
04886 (command_source == SOURCE_DPHONE))))
04887 do_dtmf_local(myrpt,
04888 remdtmfstr[myatoi(param) - 200]);
04889 default:
04890 return DC_ERROR;
04891
04892 }
04893
04894 return DC_INDETERMINATE;
04895 }
04896
04897
04898
04899
04900
04901 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04902 {
04903 pthread_attr_t attr;
04904 int i, index, paramlength;
04905 char *lparam;
04906 char *value = NULL;
04907 char *paramlist[20];
04908
04909 static char *keywords[] = {
04910 "context",
04911 "dialtime",
04912 "farenddisconnect",
04913 "noct",
04914 "quiet",
04915 NULL
04916 };
04917
04918 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
04919 return DC_ERROR;
04920
04921 if(debug)
04922 printf("@@@@ Autopatch up\n");
04923
04924 if(!myrpt->callmode){
04925
04926 myrpt->patchnoct = 0;
04927 myrpt->patchdialtime = 0;
04928 myrpt->patchfarenddisconnect = 0;
04929 myrpt->patchquiet = 0;
04930 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
04931
04932 if(param){
04933
04934 lparam = ast_strdupa(param);
04935 if(!lparam){
04936 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
04937 return DC_ERROR;
04938 }
04939 paramlength = finddelim(lparam, paramlist, 20);
04940 for(i = 0; i < paramlength; i++){
04941 index = matchkeyword(paramlist[i], &value, keywords);
04942 if(value)
04943 value = skipchars(value, "= ");
04944 switch(index){
04945
04946 case 1:
04947 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
04948 break;
04949
04950 case 2:
04951 myrpt->patchdialtime = atoi(value);
04952 break;
04953
04954 case 3:
04955 myrpt->patchfarenddisconnect = atoi(value);
04956 break;
04957
04958 case 4:
04959 myrpt->patchnoct = atoi(value);
04960 break;
04961
04962 case 5:
04963 myrpt->patchquiet = atoi(value);
04964 break;
04965
04966 default:
04967 break;
04968 }
04969 }
04970 }
04971 }
04972
04973 rpt_mutex_lock(&myrpt->lock);
04974
04975
04976
04977 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
04978 myrpt->mydtmf = myrpt->p.endchar;
04979 }
04980 if (myrpt->callmode){
04981 rpt_mutex_unlock(&myrpt->lock);
04982 return DC_COMPLETE;
04983 }
04984 myrpt->callmode = 1;
04985 myrpt->cidx = 0;
04986 myrpt->exten[myrpt->cidx] = 0;
04987 rpt_mutex_unlock(&myrpt->lock);
04988 pthread_attr_init(&attr);
04989 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04990 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
04991 return DC_COMPLETE;
04992 }
04993
04994
04995
04996
04997
04998 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04999 {
05000 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
05001 return DC_ERROR;
05002
05003 if(debug)
05004 printf("@@@@ Autopatch down\n");
05005
05006 rpt_mutex_lock(&myrpt->lock);
05007
05008 if (!myrpt->callmode){
05009 rpt_mutex_unlock(&myrpt->lock);
05010 return DC_COMPLETE;
05011 }
05012
05013 myrpt->callmode = 0;
05014 rpt_mutex_unlock(&myrpt->lock);
05015 rpt_telemetry(myrpt, TERM, NULL);
05016 return DC_COMPLETE;
05017 }
05018
05019
05020
05021
05022
05023 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
05024 {
05025
05026 if (!param)
05027 return DC_ERROR;
05028
05029 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
05030 return DC_ERROR;
05031
05032 if(debug)
05033 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05034
05035 switch(myatoi(param)){
05036 case 1:
05037 rpt_telemetry(myrpt, ID1, NULL);
05038 return DC_COMPLETE;
05039 case 2:
05040 rpt_telemetry(myrpt, STATS_TIME, NULL);
05041 return DC_COMPLETE;
05042 case 3:
05043 rpt_telemetry(myrpt, STATS_VERSION, NULL);
05044 default:
05045 return DC_ERROR;
05046 }
05047 return DC_INDETERMINATE;
05048 }
05049
05050
05051
05052
05053
05054 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
05055 {
05056
05057 char *val;
05058 int i;
05059 if (myrpt->remote)
05060 return DC_ERROR;
05061
05062 if(debug)
05063 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05064
05065 if(strlen(digitbuf) < 1)
05066 return DC_INDETERMINATE;
05067
05068 for(i = 0 ; i < digitbuf[i] ; i++) {
05069 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
05070 return DC_ERROR;
05071 }
05072
05073 if (*digitbuf == '0') val = myrpt->p.startupmacro;
05074 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
05075
05076 if (!val){
05077 if (strlen(digitbuf) < myrpt->macro_longest)
05078 return DC_INDETERMINATE;
05079 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
05080 return DC_COMPLETE;
05081 }
05082 rpt_mutex_lock(&myrpt->lock);
05083 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
05084 {
05085 rpt_mutex_unlock(&myrpt->lock);
05086 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
05087 return DC_ERROR;
05088 }
05089 myrpt->macrotimer = MACROTIME;
05090 strncat(myrpt->macrobuf, val, MAXMACRO - strlen(myrpt->macrobuf) - 1);
05091 rpt_mutex_unlock(&myrpt->lock);
05092 return DC_COMPLETE;
05093 }
05094
05095
05096
05097
05098
05099 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
05100 {
05101 char string[16];
05102 int res;
05103
05104 if(!param)
05105 return DC_ERROR;
05106
05107 switch(myatoi(param)){
05108 case 1:
05109 res = system("killall -9 asterisk");
05110 return DC_COMPLETE;
05111
05112 case 2:
05113 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
05114 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
05115 return DC_COMPLETE;
05116
05117 case 3:
05118 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
05119 return DC_COMPLETE;
05120
05121 case 4:
05122 if (myrpt->stopgen < 0)
05123 {
05124 myrpt->stopgen = 1;
05125 }
05126 else
05127 {
05128 myrpt->stopgen = 0;
05129 rpt_telemetry(myrpt, TEST_TONE, NULL);
05130 }
05131 return DC_COMPLETE;
05132
05133 case 5:
05134 myrpt->disgorgetime = time(NULL) + 10;
05135 return DC_COMPLETE;
05136
05137 case 6:
05138 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
05139 return DC_DOKEY;
05140
05141
05142 case 7:
05143 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
05144 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
05145 return DC_COMPLETE;
05146
05147 case 8:
05148 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
05149 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
05150 return DC_COMPLETE;
05151
05152 case 9:
05153 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
05154 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
05155 return DC_COMPLETE;
05156
05157 case 10:
05158 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
05159 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
05160 return DC_COMPLETE;
05161
05162 case 11:
05163 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
05164 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
05165 return DC_COMPLETE;
05166
05167 case 12:
05168 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
05169 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
05170 return DC_COMPLETE;
05171
05172 case 13:
05173 string[0] = string[1] = 'S';
05174 string[2] = myrpt->p.sysstate_cur + '0';
05175 string[3] = '\0';
05176 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05177 return DC_COMPLETE;
05178
05179 case 14:
05180 if(strlen(digitbuf) == 0)
05181 break;
05182 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
05183 return DC_ERROR;
05184 myrpt->p.sysstate_cur = digitbuf[0] - '0';
05185 string[0] = string[1] = 'S';
05186 string[2] = myrpt->p.sysstate_cur + '0';
05187 string[3] = '\0';
05188 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05189 return DC_COMPLETE;
05190
05191 case 15:
05192 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
05193 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
05194 return DC_COMPLETE;
05195
05196 case 16:
05197 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
05198 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
05199 return DC_COMPLETE;
05200
05201 case 17:
05202 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
05203 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
05204 return DC_COMPLETE;
05205
05206 case 18:
05207 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
05208 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
05209 return DC_COMPLETE;
05210
05211 case 19:
05212 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
05213 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
05214 return DC_COMPLETE;
05215
05216 case 20:
05217 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
05218 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
05219 return DC_COMPLETE;
05220 }
05221 return DC_INDETERMINATE;
05222 }
05223
05224
05225
05226
05227
05228 static int collect_function_digits(struct rpt *myrpt, char *digits,
05229 int command_source, struct rpt_link *mylink)
05230 {
05231 int i;
05232 char *stringp,*action,*param,*functiondigits;
05233 char function_table_name[30] = "";
05234 char workstring[200];
05235
05236 struct ast_variable *vp;
05237
05238 if(debug)
05239 printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
05240
05241 if (command_source == SOURCE_DPHONE) {
05242 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
05243 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
05244 }
05245 else if (command_source == SOURCE_PHONE) {
05246 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
05247 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
05248 }
05249 else if (command_source == SOURCE_LNK)
05250 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
05251 else
05252 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
05253 vp = ast_variable_browse(myrpt->cfg, function_table_name);
05254 while(vp) {
05255 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
05256 break;
05257 vp = vp->next;
05258 }
05259 if(!vp) {
05260 int n;
05261
05262 n = myrpt->longestfunc;
05263 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
05264 else
05265 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
05266 else
05267 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
05268
05269 if(strlen(digits) >= n)
05270 return DC_ERROR;
05271 else
05272 return DC_INDETERMINATE;
05273 }
05274
05275 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
05276 stringp = workstring;
05277 action = strsep(&stringp, ",");
05278 param = stringp;
05279 if(debug)
05280 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
05281
05282 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
05283 if(!strncasecmp(action, function_table[i].action, strlen(action)))
05284 break;
05285 }
05286 if(debug)
05287 printf("@@@@ table index i = %d\n",i);
05288 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
05289
05290 return DC_ERROR;
05291 }
05292 if(function_table[i].function == NULL){
05293
05294 if(debug)
05295 printf("@@@@ NULL for action: %s\n",action);
05296 return DC_ERROR;
05297 }
05298 functiondigits = digits + strlen(vp->name);
05299 return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
05300 }
05301
05302
05303 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
05304 char *str)
05305 {
05306 char tmp[512],cmd[300] = "",dest[300],src[300],c;
05307 int seq, res;
05308 struct rpt_link *l;
05309 struct ast_frame wf;
05310
05311 wf.frametype = AST_FRAME_TEXT;
05312 wf.subclass = 0;
05313 wf.offset = 0;
05314 wf.mallocd = 0;
05315 wf.datalen = strlen(str) + 1;
05316 wf.samples = 0;
05317
05318 strncpy(tmp,str,sizeof(tmp) - 1);
05319
05320 if (!strcmp(tmp,discstr))
05321 {
05322 mylink->disced = 1;
05323 mylink->retries = mylink->max_retries + 1;
05324 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
05325 return;
05326 }
05327 if (tmp[0] == 'L')
05328 {
05329 rpt_mutex_lock(&myrpt->lock);
05330 strcpy(mylink->linklist,tmp + 2);
05331 time(&mylink->linklistreceived);
05332 rpt_mutex_unlock(&myrpt->lock);
05333 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s recieved node list %s from node %s\n",
05334 myrpt->name,tmp,mylink->name);
05335 return;
05336 }
05337 if (tmp[0] == 'I')
05338 {
05339 if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
05340 {
05341 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
05342 return;
05343 }
05344 mdc1200_notify(myrpt,src,seq);
05345 strcpy(dest,"*");
05346 }
05347 else
05348 {
05349 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
05350 {
05351 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05352 return;
05353 }
05354 if (strcmp(cmd,"D"))
05355 {
05356 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05357 return;
05358 }
05359 }
05360 if (dest[0] == '0')
05361 {
05362 strcpy(dest,myrpt->name);
05363 }
05364
05365
05366 if (strcmp(dest,myrpt->name))
05367 {
05368 l = myrpt->links.next;
05369
05370 while(l != &myrpt->links)
05371 {
05372 if (l->name[0] == '0')
05373 {
05374 l = l->next;
05375 continue;
05376 }
05377
05378 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05379 {
05380 l = l->next;
05381 continue;
05382 }
05383
05384 if (!strcmp(l->name,dest))
05385 {
05386
05387 if (strcmp(l->name,src)) {
05388 wf.data = str;
05389 if (l->chan) ast_write(l->chan,&wf);
05390 }
05391 return;
05392 }
05393 l = l->next;
05394 }
05395 l = myrpt->links.next;
05396
05397 while(l != &myrpt->links)
05398 {
05399 if (l->name[0] == '0')
05400 {
05401 l = l->next;
05402 continue;
05403 }
05404
05405 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05406 {
05407 l = l->next;
05408 continue;
05409 }
05410
05411 if (strcmp(l->name,src)) {
05412 wf.data = str;
05413 if (l->chan) ast_write(l->chan,&wf);
05414 }
05415 l = l->next;
05416 }
05417 return;
05418 }
05419 if (myrpt->p.archivedir)
05420 {
05421 char str[100];
05422
05423 sprintf(str,"DTMF,%s,%c",mylink->name,c);
05424 donodelog(myrpt,str);
05425 }
05426 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
05427 if (!c) return;
05428 rpt_mutex_lock(&myrpt->lock);
05429 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
05430 if (myrpt->callmode == 1)
05431 {
05432 myrpt->exten[myrpt->cidx++] = c;
05433 myrpt->exten[myrpt->cidx] = 0;
05434
05435 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05436 {
05437 myrpt->callmode = 2;
05438 if(!myrpt->patchquiet){
05439 rpt_mutex_unlock(&myrpt->lock);
05440 rpt_telemetry(myrpt,PROC,NULL);
05441 rpt_mutex_lock(&myrpt->lock);
05442 }
05443 }
05444
05445 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05446 {
05447
05448 myrpt->callmode = 4;
05449 }
05450 }
05451 if (c == myrpt->p.funcchar)
05452 {
05453 myrpt->rem_dtmfidx = 0;
05454 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05455 time(&myrpt->rem_dtmf_time);
05456 rpt_mutex_unlock(&myrpt->lock);
05457 return;
05458 }
05459 else if (myrpt->rem_dtmfidx < 0)
05460 {
05461 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05462 {
05463 myrpt->mydtmf = c;
05464 }
05465 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
05466 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
05467 rpt_mutex_unlock(&myrpt->lock);
05468 return;
05469 }
05470 else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05471 {
05472 time(&myrpt->rem_dtmf_time);
05473 if (myrpt->rem_dtmfidx < MAXDTMF)
05474 {
05475 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05476 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05477
05478 rpt_mutex_unlock(&myrpt->lock);
05479 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05480 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
05481 rpt_mutex_lock(&myrpt->lock);
05482
05483 switch(res){
05484
05485 case DC_INDETERMINATE:
05486 break;
05487
05488 case DC_REQ_FLUSH:
05489 myrpt->rem_dtmfidx = 0;
05490 myrpt->rem_dtmfbuf[0] = 0;
05491 break;
05492
05493
05494 case DC_COMPLETE:
05495 case DC_COMPLETEQUIET:
05496 myrpt->totalexecdcommands++;
05497 myrpt->dailyexecdcommands++;
05498 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05499 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05500 myrpt->rem_dtmfbuf[0] = 0;
05501 myrpt->rem_dtmfidx = -1;
05502 myrpt->rem_dtmf_time = 0;
05503 break;
05504
05505 case DC_ERROR:
05506 default:
05507 myrpt->rem_dtmfbuf[0] = 0;
05508 myrpt->rem_dtmfidx = -1;
05509 myrpt->rem_dtmf_time = 0;
05510 break;
05511 }
05512 }
05513
05514 }
05515 rpt_mutex_unlock(&myrpt->lock);
05516 return;
05517 }
05518
05519 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
05520 char c)
05521 {
05522
05523 char cmd[300];
05524 int res;
05525
05526 if (myrpt->p.archivedir)
05527 {
05528 char str[100];
05529
05530 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
05531 donodelog(myrpt,str);
05532 }
05533 rpt_mutex_lock(&myrpt->lock);
05534 if (c == myrpt->p.endchar)
05535 {
05536 if (mylink->lastrx)
05537 {
05538 mylink->lastrx = 0;
05539 rpt_mutex_unlock(&myrpt->lock);
05540 return;
05541 }
05542 myrpt->stopgen = 1;
05543 if (myrpt->cmdnode[0])
05544 {
05545 myrpt->cmdnode[0] = 0;
05546 myrpt->dtmfidx = -1;
05547 myrpt->dtmfbuf[0] = 0;
05548 rpt_mutex_unlock(&myrpt->lock);
05549 rpt_telemetry(myrpt,COMPLETE,NULL);
05550 return;
05551 }
05552 }
05553 if (myrpt->cmdnode[0])
05554 {
05555 rpt_mutex_unlock(&myrpt->lock);
05556 send_link_dtmf(myrpt,c);
05557 return;
05558 }
05559 if (myrpt->callmode == 1)
05560 {
05561 myrpt->exten[myrpt->cidx++] = c;
05562 myrpt->exten[myrpt->cidx] = 0;
05563
05564 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05565 {
05566 myrpt->callmode = 2;
05567 if(!myrpt->patchquiet){
05568 rpt_mutex_unlock(&myrpt->lock);
05569 rpt_telemetry(myrpt,PROC,NULL);
05570 rpt_mutex_lock(&myrpt->lock);
05571 }
05572 }
05573
05574 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05575 {
05576
05577 myrpt->callmode = 4;
05578 }
05579 }
05580 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05581 {
05582 myrpt->mydtmf = c;
05583 }
05584 if (c == myrpt->p.funcchar)
05585 {
05586 myrpt->rem_dtmfidx = 0;
05587 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05588 time(&myrpt->rem_dtmf_time);
05589 rpt_mutex_unlock(&myrpt->lock);
05590 return;
05591 }
05592 else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05593 {
05594 time(&myrpt->rem_dtmf_time);
05595 if (myrpt->rem_dtmfidx < MAXDTMF)
05596 {
05597 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05598 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05599
05600 rpt_mutex_unlock(&myrpt->lock);
05601 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05602 switch(mylink->phonemode)
05603 {
05604 case 1:
05605 res = collect_function_digits(myrpt, cmd,
05606 SOURCE_PHONE, mylink);
05607 break;
05608 case 2:
05609 res = collect_function_digits(myrpt, cmd,
05610 SOURCE_DPHONE,mylink);
05611 break;
05612 default:
05613 res = collect_function_digits(myrpt, cmd,
05614 SOURCE_LNK, mylink);
05615 break;
05616 }
05617
05618 rpt_mutex_lock(&myrpt->lock);
05619
05620 switch(res){
05621
05622 case DC_INDETERMINATE:
05623 break;
05624
05625 case DC_DOKEY:
05626 mylink->lastrx = 1;
05627 break;
05628
05629 case DC_REQ_FLUSH:
05630 myrpt->rem_dtmfidx = 0;
05631 myrpt->rem_dtmfbuf[0] = 0;
05632 break;
05633
05634
05635 case DC_COMPLETE:
05636 case DC_COMPLETEQUIET:
05637 myrpt->totalexecdcommands++;
05638 myrpt->dailyexecdcommands++;
05639 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05640 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05641 myrpt->rem_dtmfbuf[0] = 0;
05642 myrpt->rem_dtmfidx = -1;
05643 myrpt->rem_dtmf_time = 0;
05644 break;
05645
05646 case DC_ERROR:
05647 default:
05648 myrpt->rem_dtmfbuf[0] = 0;
05649 myrpt->rem_dtmfidx = -1;
05650 myrpt->rem_dtmf_time = 0;
05651 break;
05652 }
05653 }
05654
05655 }
05656 rpt_mutex_unlock(&myrpt->lock);
05657 return;
05658 }
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691 static int rbi_mhztoband(char *str)
05692 {
05693 int i;
05694
05695 i = atoi(str) / 10;
05696 switch(i)
05697 {
05698 case 2:
05699 return 10;
05700 case 5:
05701 return 11;
05702 case 14:
05703 return 2;
05704 case 22:
05705 return 3;
05706 case 44:
05707 return 4;
05708 case 124:
05709 return 0;
05710 case 125:
05711 return 1;
05712 case 126:
05713 return 8;
05714 case 127:
05715 return 5;
05716 case 128:
05717 return 6;
05718 case 129:
05719 return 7;
05720 default:
05721 break;
05722 }
05723 return -1;
05724 }
05725
05726
05727 static int rbi_pltocode(char *str)
05728 {
05729 int i;
05730 char *s;
05731
05732 s = strchr(str,'.');
05733 i = 0;
05734 if (s) i = atoi(s + 1);
05735 i += atoi(str) * 10;
05736 switch(i)
05737 {
05738 case 670:
05739 return 0;
05740 case 719:
05741 return 1;
05742 case 744:
05743 return 2;
05744 case 770:
05745 return 3;
05746 case 797:
05747 return 4;
05748 case 825:
05749 return 5;
05750 case 854:
05751 return 6;
05752 case 885:
05753 return 7;
05754 case 915:
05755 return 8;
05756 case 948:
05757 return 9;
05758 case 974:
05759 return 10;
05760 case 1000:
05761 return 11;
05762 case 1035:
05763 return 12;
05764 case 1072:
05765 return 13;
05766 case 1109:
05767 return 14;
05768 case 1148:
05769 return 15;
05770 case 1188:
05771 return 16;
05772 case 1230:
05773 return 17;
05774 case 1273:
05775 return 18;
05776 case 1318:
05777 return 19;
05778 case 1365:
05779 return 20;
05780 case 1413:
05781 return 21;
05782 case 1462:
05783 return 22;
05784 case 1514:
05785 return 23;
05786 case 1567:
05787 return 24;
05788 case 1622:
05789 return 25;
05790 case 1679:
05791 return 26;
05792 case 1738:
05793 return 27;
05794 case 1799:
05795 return 28;
05796 case 1862:
05797 return 29;
05798 case 1928:
05799 return 30;
05800 case 2035:
05801 return 31;
05802 case 2107:
05803 return 32;
05804 case 2181:
05805 return 33;
05806 case 2257:
05807 return 34;
05808 case 2336:
05809 return 35;
05810 case 2418:
05811 return 36;
05812 case 2503:
05813 return 37;
05814 }
05815 return -1;
05816 }
05817
05818
05819
05820
05821
05822 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
05823 {
05824 #ifdef __i386__
05825 int i,j;
05826 unsigned char od,d;
05827 static volatile long long delayvar;
05828
05829 for(i = 0 ; i < 5 ; i++){
05830 od = *data++;
05831 for(j = 0 ; j < 8 ; j++){
05832 d = od & 1;
05833 outb(d,myrpt->p.iobase);
05834
05835 for(delayvar = 1; delayvar < 15000; delayvar++);
05836 od >>= 1;
05837 outb(d | 2,myrpt->p.iobase);
05838
05839 for(delayvar = 1; delayvar < 30000; delayvar++);
05840 outb(d,myrpt->p.iobase);
05841
05842 for(delayvar = 1; delayvar < 10000; delayvar++);
05843 }
05844 }
05845
05846 for(delayvar = 1; delayvar < 50000; delayvar++);
05847 #endif
05848 }
05849
05850 static void rbi_out(struct rpt *myrpt,unsigned char *data)
05851 {
05852 struct dahdi_radio_param r;
05853
05854 memset(&r,0,sizeof(struct dahdi_radio_param));
05855 r.radpar = DAHDI_RADPAR_REMMODE;
05856 r.data = DAHDI_RADPAR_REM_RBI1;
05857
05858 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
05859 {
05860 rbi_out_parallel(myrpt,data);
05861 return;
05862 }
05863 r.radpar = DAHDI_RADPAR_REMCOMMAND;
05864 memcpy(&r.data,data,5);
05865 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
05866 {
05867 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->zaprxchannel->name);
05868 return;
05869 }
05870 }
05871
05872 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
05873 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
05874 {
05875 int i,j,index,oldmode,olddata;
05876 struct dahdi_radio_param prm;
05877 char c;
05878
05879 if(debug){
05880 printf("String output was: ");
05881 for(i = 0; i < txbytes; i++)
05882 printf("%02X ", (unsigned char ) txbuf[i]);
05883 printf("\n");
05884 }
05885 if (myrpt->iofd > 0)
05886 {
05887 if (rxmaxbytes && rxbuf) tcflush(myrpt->iofd,TCIFLUSH);
05888 if (write(myrpt->iofd,txbuf,txbytes) != txbytes) return -1;
05889 if ((!rxmaxbytes) || (rxbuf == NULL)) return(0);
05890 memset(rxbuf,0,rxmaxbytes);
05891 for(i = 0; i < rxmaxbytes; i++)
05892 {
05893 j = read(myrpt->iofd,&c,1);
05894 if (j < 1) return(i);
05895 rxbuf[i] = c;
05896 if (asciiflag & 1)
05897 {
05898 rxbuf[i + 1] = 0;
05899 if (c == '\r') break;
05900 }
05901 }
05902 if(debug){
05903 printf("String returned was: ");
05904 for(j = 0; j < i; j++)
05905 printf("%02X ", (unsigned char ) rxbuf[j]);
05906 printf("\n");
05907 }
05908 return(i);
05909 }
05910
05911
05912 if (myrpt->rxchannel != myrpt->zaprxchannel) return -1;
05913
05914 prm.radpar = DAHDI_RADPAR_UIOMODE;
05915 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
05916 oldmode = prm.data;
05917 prm.radpar = DAHDI_RADPAR_UIODATA;
05918 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
05919 olddata = prm.data;
05920 prm.radpar = DAHDI_RADPAR_REMMODE;
05921 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
05922 else prm.data = DAHDI_RADPAR_REM_SERIAL;
05923 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05924 if (asciiflag & 2)
05925 {
05926 i = DAHDI_ONHOOK;
05927 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
05928 usleep(100000);
05929 }
05930 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
05931 prm.data = rxmaxbytes;
05932 memcpy(prm.buf,txbuf,txbytes);
05933 prm.index = txbytes;
05934 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05935 if (rxbuf)
05936 {
05937 *rxbuf = 0;
05938 memcpy(rxbuf,prm.buf,prm.index);
05939 }
05940 index = prm.index;
05941 prm.radpar = DAHDI_RADPAR_REMMODE;
05942 prm.data = DAHDI_RADPAR_REM_NONE;
05943 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05944 if (asciiflag & 2)
05945 {
05946 i = DAHDI_OFFHOOK;
05947 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
05948 }
05949 prm.radpar = DAHDI_RADPAR_UIOMODE;
05950 prm.data = oldmode;
05951 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05952 prm.radpar = DAHDI_RADPAR_UIODATA;
05953 prm.data = olddata;
05954 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05955 return(index);
05956 }
05957
05958 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
05959 {
05960 unsigned char rxbuf[100];
05961 int i,rv ;
05962
05963 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
05964 if (rv == -1) return(-1);
05965 if (rv != (cmdlen + 6)) return(1);
05966 for(i = 0; i < 6; i++)
05967 if (rxbuf[i] != cmd[i]) return(1);
05968 if (rxbuf[cmdlen] != 0xfe) return(1);
05969 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
05970 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
05971 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
05972 return(0);
05973 }
05974
05975 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
05976 {
05977 int i;
05978
05979 if (debug) printf("Send to kenwood: %s\n",txstr);
05980 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
05981 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
05982 if (i < 0) return -1;
05983 if ((i > 0) && (rxstr[i - 1] == '\r'))
05984 rxstr[i-- - 1] = 0;
05985 if (debug) printf("Got from kenwood: %s\n",rxstr);
05986 return(i);
05987 }
05988
05989
05990 static int kenwood_pltocode(char *str)
05991 {
05992 int i;
05993 char *s;
05994
05995 s = strchr(str,'.');
05996 i = 0;
05997 if (s) i = atoi(s + 1);
05998 i += atoi(str) * 10;
05999 switch(i)
06000 {
06001 case 670:
06002 return 1;
06003 case 719:
06004 return 3;
06005 case 744:
06006 return 4;
06007 case 770:
06008 return 5;
06009 case 797:
06010 return 6;
06011 case 825:
06012 return 7;
06013 case 854:
06014 return 8;
06015 case 885:
06016 return 9;
06017 case 915:
06018 return 10;
06019 case 948:
06020 return 11;
06021 case 974:
06022 return 12;
06023 case 1000:
06024 return 13;
06025 case 1035:
06026 return 14;
06027 case 1072:
06028 return 15;
06029 case 1109:
06030 return 16;
06031 case 1148:
06032 return 17;
06033 case 1188:
06034 return 18;
06035 case 1230:
06036 return 19;
06037 case 1273:
06038 return 20;
06039 case 1318:
06040 return 21;
06041 case 1365:
06042 return 22;
06043 case 1413:
06044 return 23;
06045 case 1462:
06046 return 24;
06047 case 1514:
06048 return 25;
06049 case 1567:
06050 return 26;
06051 case 1622:
06052 return 27;
06053 case 1679:
06054 return 28;
06055 case 1738:
06056 return 29;
06057 case 1799:
06058 return 30;
06059 case 1862:
06060 return 31;
06061 case 1928:
06062 return 32;
06063 case 2035:
06064 return 33;
06065 case 2107:
06066 return 34;
06067 case 2181:
06068 return 35;
06069 case 2257:
06070 return 36;
06071 case 2336:
06072 return 37;
06073 case 2418:
06074 return 38;
06075 case 2503:
06076 return 39;
06077 }
06078 return -1;
06079 }
06080
06081 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
06082 char *cmpstr)
06083 {
06084 int i,j;
06085
06086 for(i = 0;i < KENWOOD_RETRIES;i++)
06087 {
06088 j = sendkenwood(myrpt,txstr,rxstr);
06089 if (j < 0) return(j);
06090 if (j == 0) continue;
06091 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
06092 }
06093 return(-1);
06094 }
06095
06096 static int setkenwood(struct rpt *myrpt)
06097 {
06098 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
06099 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
06100
06101 int offsets[] = {0,2,1};
06102 int powers[] = {2,1,0};
06103
06104 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
06105 split_freq(mhz, decimals, myrpt->freq);
06106 if (atoi(mhz) > 400)
06107 {
06108 band = '6';
06109 band1 = '1';
06110 band2 = '5';
06111 strcpy(offset,"005000000");
06112 }
06113 else
06114 {
06115 band = '2';
06116 band1 = '0';
06117 band2 = '2';
06118 strcpy(offset,"000600000");
06119 }
06120 strcpy(freq,"000000");
06121 strncpy(freq,decimals,strlen(decimals));
06122 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
06123 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
06124 (myrpt->txplon != 0),(myrpt->rxplon != 0),
06125 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
06126 offset);
06127 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
06128 sprintf(txstr,"RBN %c\r",band2);
06129 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
06130 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
06131 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
06132 return 0;
06133 }
06134
06135 static int setrbi(struct rpt *myrpt)
06136 {
06137 char tmp[MAXREMSTR] = "",*s;
06138 unsigned char rbicmd[5];
06139 int band,txoffset = 0,txpower = 0,rxpl;
06140
06141
06142 if (!myrpt->remote) return(0);
06143
06144 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06145 if (setrbi_check(myrpt) == -1) return(-1);
06146 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06147 s = strchr(tmp,'.');
06148
06149
06150 if (s == NULL){
06151 if(debug)
06152 printf("@@@@ Frequency needs a decimal\n");
06153 return -1;
06154 }
06155
06156 *s++ = 0;
06157 if (strlen(tmp) < 2){
06158 if(debug)
06159 printf("@@@@ Bad MHz digits: %s\n", tmp);
06160 return -1;
06161 }
06162
06163 if (strlen(s) < 3){
06164 if(debug)
06165 printf("@@@@ Bad KHz digits: %s\n", s);
06166 return -1;
06167 }
06168
06169 if ((s[2] != '0') && (s[2] != '5')){
06170 if(debug)
06171 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06172 return -1;
06173 }
06174
06175 band = rbi_mhztoband(tmp);
06176 if (band == -1){
06177 if(debug)
06178 printf("@@@@ Bad Band: %s\n", tmp);
06179 return -1;
06180 }
06181
06182 rxpl = rbi_pltocode(myrpt->rxpl);
06183
06184 if (rxpl == -1){
06185 if(debug)
06186 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
06187 return -1;
06188 }
06189
06190
06191 switch(myrpt->offset)
06192 {
06193 case REM_MINUS:
06194 txoffset = 0;
06195 break;
06196 case REM_PLUS:
06197 txoffset = 0x10;
06198 break;
06199 case REM_SIMPLEX:
06200 txoffset = 0x20;
06201 break;
06202 }
06203 switch(myrpt->powerlevel)
06204 {
06205 case REM_LOWPWR:
06206 txpower = 0;
06207 break;
06208 case REM_MEDPWR:
06209 txpower = 0x20;
06210 break;
06211 case REM_HIPWR:
06212 txpower = 0x10;
06213 break;
06214 }
06215 rbicmd[0] = 0;
06216 rbicmd[1] = band | txpower | 0xc0;
06217 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
06218 if (s[2] == '5') rbicmd[2] |= 0x40;
06219 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
06220 rbicmd[4] = rxpl;
06221 if (myrpt->txplon) rbicmd[4] |= 0x40;
06222 if (myrpt->rxplon) rbicmd[4] |= 0x80;
06223 rbi_out(myrpt,rbicmd);
06224 return 0;
06225 }
06226
06227 static int setrbi_check(struct rpt *myrpt)
06228 {
06229 char tmp[MAXREMSTR] = "",*s;
06230 int band,txpl;
06231
06232
06233 if (!myrpt->remote) return(0);
06234
06235 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06236 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06237 s = strchr(tmp,'.');
06238
06239
06240 if (s == NULL){
06241 if(debug)
06242 printf("@@@@ Frequency needs a decimal\n");
06243 return -1;
06244 }
06245
06246 *s++ = 0;
06247 if (strlen(tmp) < 2){
06248 if(debug)
06249 printf("@@@@ Bad MHz digits: %s\n", tmp);
06250 return -1;
06251 }
06252
06253 if (strlen(s) < 3){
06254 if(debug)
06255 printf("@@@@ Bad KHz digits: %s\n", s);
06256 return -1;
06257 }
06258
06259 if ((s[2] != '0') && (s[2] != '5')){
06260 if(debug)
06261 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06262 return -1;
06263 }
06264
06265 band = rbi_mhztoband(tmp);
06266 if (band == -1){
06267 if(debug)
06268 printf("@@@@ Bad Band: %s\n", tmp);
06269 return -1;
06270 }
06271
06272 txpl = rbi_pltocode(myrpt->txpl);
06273
06274 if (txpl == -1){
06275 if(debug)
06276 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
06277 return -1;
06278 }
06279 return 0;
06280 }
06281
06282 static int check_freq_kenwood(int m, int d, int *defmode)
06283 {
06284 int dflmd = REM_MODE_FM;
06285
06286 if (m == 144){
06287 if(d < 10100)
06288 return -1;
06289 }
06290 else if((m >= 145) && (m < 148)){
06291 ;
06292 }
06293 else if((m >= 430) && (m < 450)){
06294 ;
06295 }
06296 else
06297 return -1;
06298
06299 if(defmode)
06300 *defmode = dflmd;
06301
06302
06303 return 0;
06304 }
06305
06306
06307
06308
06309
06310 static int check_freq_rbi(int m, int d, int *defmode)
06311 {
06312 int dflmd = REM_MODE_FM;
06313
06314 if(m == 50){
06315 if(d < 10100)
06316 return -1;
06317 }
06318 else if((m >= 51) && ( m < 54)){
06319 ;
06320 }
06321 else if(m == 144){
06322 if(d < 10100)
06323 return -1;
06324 }
06325 else if((m >= 145) && (m < 148)){
06326 ;
06327 }
06328 else if((m >= 222) && (m < 225)){
06329 ;
06330 }
06331 else if((m >= 430) && (m < 450)){
06332 ;
06333 }
06334 else if((m >= 1240) && (m < 1300)){
06335 ;
06336 }
06337 else
06338 return -1;
06339
06340 if(defmode)
06341 *defmode = dflmd;
06342
06343
06344 return 0;
06345 }
06346
06347
06348
06349
06350
06351 static int decimals2int(char *fraction)
06352 {
06353 int i;
06354 char len = strlen(fraction);
06355 int multiplier = 100000;
06356 int res = 0;
06357
06358 if(!len)
06359 return 0;
06360 for( i = 0 ; i < len ; i++, multiplier /= 10)
06361 res += (fraction[i] - '0') * multiplier;
06362 return res;
06363 }
06364
06365
06366
06367
06368
06369
06370 static int split_freq(char *mhz, char *decimals, char *freq)
06371 {
06372 char freq_copy[MAXREMSTR];
06373 char *decp;
06374
06375 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06376 if(decp){
06377 *decp++ = 0;
06378 strncpy(mhz, freq_copy, MAXREMSTR);
06379 strcpy(decimals, "00000");
06380 strncpy(decimals, decp, strlen(decp));
06381 decimals[5] = 0;
06382 return 0;
06383 }
06384 else
06385 return -1;
06386
06387 }
06388
06389
06390
06391
06392
06393 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
06394 {
06395 char freq_copy[MAXREMSTR];
06396 char *decp;
06397
06398 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06399 if(decp){
06400 *decp++ = 0;
06401 strncpy(hertz, freq_copy, MAXREMSTR);
06402 strncpy(decimal, decp, strlen(decp));
06403 decimal[strlen(decp)] = '\0';
06404 return 0;
06405 }
06406 else
06407 return -1;
06408 }
06409
06410
06411
06412
06413
06414
06415
06416
06417
06418
06419
06420 static int check_freq_ft897(int m, int d, int *defmode)
06421 {
06422 int dflmd = REM_MODE_FM;
06423
06424 if(m == 1){
06425 dflmd = REM_MODE_LSB;
06426 if(d < 80000)
06427 return -1;
06428 }
06429 else if(m == 3){
06430 dflmd = REM_MODE_LSB;
06431 if(d < 50000)
06432 return -1;
06433 }
06434 else if(m == 7){
06435 dflmd = REM_MODE_LSB;
06436 if(d > 30000)
06437 return -1;
06438 }
06439 else if(m == 14){
06440 dflmd = REM_MODE_USB;
06441 if(d > 35000)
06442 return -1;
06443 }
06444 else if(m == 18){
06445 dflmd = REM_MODE_USB;
06446 if((d < 6800) || (d > 16800))
06447 return -1;
06448 }
06449 else if(m == 21){
06450 dflmd = REM_MODE_USB;
06451 if((d < 20000) || (d > 45000))
06452 return -1;
06453 }
06454 else if(m == 24){
06455 dflmd = REM_MODE_USB;
06456 if((d < 89000) || (d > 99000))
06457 return -1;
06458 }
06459 else if(m == 28){
06460 dflmd = REM_MODE_USB;
06461 }
06462 else if(m == 29){
06463 if(d >= 51000)
06464 dflmd = REM_MODE_FM;
06465 else
06466 dflmd = REM_MODE_USB;
06467 if(d > 70000)
06468 return -1;
06469 }
06470 else if(m == 50){
06471 if(d >= 30000)
06472 dflmd = REM_MODE_FM;
06473 else
06474 dflmd = REM_MODE_USB;
06475
06476 }
06477 else if((m >= 51) && ( m < 54)){
06478 dflmd = REM_MODE_FM;
06479 }
06480 else if(m == 144){
06481 if(d >= 30000)
06482 dflmd = REM_MODE_FM;
06483 else
06484 dflmd = REM_MODE_USB;
06485 }
06486 else if((m >= 145) && (m < 148)){
06487 dflmd = REM_MODE_FM;
06488 }
06489 else if((m >= 430) && (m < 450)){
06490 if(m < 438)
06491 dflmd = REM_MODE_USB;
06492 else
06493 dflmd = REM_MODE_FM;
06494 ;
06495 }
06496 else
06497 return -1;
06498
06499 if(defmode)
06500 *defmode = dflmd;
06501
06502 return 0;
06503 }
06504
06505
06506
06507
06508
06509 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
06510 {
06511 unsigned char cmdstr[5];
06512 int fd,m,d;
06513 char mhz[MAXREMSTR];
06514 char decimals[MAXREMSTR];
06515
06516 fd = 0;
06517 if(debug)
06518 printf("New frequency: %s\n",newfreq);
06519
06520 if(split_freq(mhz, decimals, newfreq))
06521 return -1;
06522
06523 m = atoi(mhz);
06524 d = atoi(decimals);
06525
06526
06527
06528 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
06529 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
06530 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
06531 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
06532 cmdstr[4] = 0x01;
06533
06534 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06535
06536 }
06537
06538
06539
06540 static int simple_command_ft897(struct rpt *myrpt, char command)
06541 {
06542 unsigned char cmdstr[5];
06543
06544 memset(cmdstr, 0, 5);
06545
06546 cmdstr[4] = command;
06547
06548 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06549
06550 }
06551
06552
06553
06554 static int set_offset_ft897(struct rpt *myrpt, char offset)
06555 {
06556 unsigned char cmdstr[5];
06557
06558 memset(cmdstr, 0, 5);
06559
06560 switch(offset){
06561 case REM_SIMPLEX:
06562 cmdstr[0] = 0x89;
06563 break;
06564
06565 case REM_MINUS:
06566 cmdstr[0] = 0x09;
06567 break;
06568
06569 case REM_PLUS:
06570 cmdstr[0] = 0x49;
06571 break;
06572
06573 default:
06574 return -1;
06575 }
06576
06577 cmdstr[4] = 0x09;
06578
06579 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06580 }
06581
06582
06583
06584 static int set_mode_ft897(struct rpt *myrpt, char newmode)
06585 {
06586 unsigned char cmdstr[5];
06587
06588 memset(cmdstr, 0, 5);
06589
06590 switch(newmode){
06591 case REM_MODE_FM:
06592 cmdstr[0] = 0x08;
06593 break;
06594
06595 case REM_MODE_USB:
06596 cmdstr[0] = 0x01;
06597 break;
06598
06599 case REM_MODE_LSB:
06600 cmdstr[0] = 0x00;
06601 break;
06602
06603 case REM_MODE_AM:
06604 cmdstr[0] = 0x04;
06605 break;
06606
06607 default:
06608 return -1;
06609 }
06610 cmdstr[4] = 0x07;
06611
06612 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06613 }
06614
06615
06616
06617 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
06618 {
06619 unsigned char cmdstr[5];
06620
06621 memset(cmdstr, 0, 5);
06622
06623 if(rxplon && txplon)
06624 cmdstr[0] = 0x2A;
06625 else if (!rxplon && txplon)
06626 cmdstr[0] = 0x4A;
06627 else if (rxplon && !txplon)
06628 cmdstr[0] = 0x3A;
06629 else
06630 cmdstr[0] = 0x8A;
06631
06632 cmdstr[4] = 0x0A;
06633
06634 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06635 }
06636
06637
06638
06639
06640 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
06641 {
06642 unsigned char cmdstr[5];
06643 char hertz[MAXREMSTR],decimal[MAXREMSTR];
06644 int h,d;
06645
06646 memset(cmdstr, 0, 5);
06647
06648 if(split_ctcss_freq(hertz, decimal, txtone))
06649 return -1;
06650
06651 h = atoi(hertz);
06652 d = atoi(decimal);
06653
06654 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
06655 cmdstr[1] = ((h % 10) << 4) + (d % 10);
06656
06657 if(rxtone){
06658
06659 if(split_ctcss_freq(hertz, decimal, rxtone))
06660 return -1;
06661
06662 h = atoi(hertz);
06663 d = atoi(decimal);
06664
06665 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
06666 cmdstr[3] = ((h % 10) << 4) + (d % 10);
06667 }
06668 cmdstr[4] = 0x0B;
06669
06670 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06671 }
06672
06673
06674
06675 static int set_ft897(struct rpt *myrpt)
06676 {
06677 int res;
06678
06679 if(debug)
06680 printf("@@@@ lock on\n");
06681
06682 res = simple_command_ft897(myrpt, 0x00);
06683
06684 if(debug)
06685 printf("@@@@ ptt off\n");
06686
06687 if(!res)
06688 res = simple_command_ft897(myrpt, 0x88);
06689
06690 if(debug)
06691 printf("Modulation mode\n");
06692
06693 if(!res)
06694 res = set_mode_ft897(myrpt, myrpt->remmode);
06695
06696 if(debug)
06697 printf("Split off\n");
06698
06699 if(!res)
06700 simple_command_ft897(myrpt, 0x82);
06701
06702 if(debug)
06703 printf("Frequency\n");
06704
06705 if(!res)
06706 res = set_freq_ft897(myrpt, myrpt->freq);
06707 if((myrpt->remmode == REM_MODE_FM)){
06708 if(debug)
06709 printf("Offset\n");
06710 if(!res)
06711 res = set_offset_ft897(myrpt, myrpt->offset);
06712 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
06713 if(debug)
06714 printf("CTCSS tone freqs.\n");
06715 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
06716 }
06717 if(!res){
06718 if(debug)
06719 printf("CTCSS mode\n");
06720 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
06721 }
06722 }
06723 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
06724 if(debug)
06725 printf("Clarifier off\n");
06726 simple_command_ft897(myrpt, 0x85);
06727 }
06728 return res;
06729 }
06730
06731 static int closerem_ft897(struct rpt *myrpt)
06732 {
06733 simple_command_ft897(myrpt, 0x88);
06734 return 0;
06735 }
06736
06737
06738
06739
06740
06741
06742
06743 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
06744 {
06745 int m,d;
06746 char mhz[MAXREMSTR], decimals[MAXREMSTR];
06747
06748 if(debug)
06749 printf("Before bump: %s\n", myrpt->freq);
06750
06751 if(split_freq(mhz, decimals, myrpt->freq))
06752 return -1;
06753
06754 m = atoi(mhz);
06755 d = atoi(decimals);
06756
06757 d += (interval / 10);
06758 if(d < 0){
06759 m--;
06760 d += 100000;
06761 }
06762 else if(d >= 100000){
06763 m++;
06764 d -= 100000;
06765 }
06766
06767 if(check_freq_ft897(m, d, NULL)){
06768 if(debug)
06769 printf("Bump freq invalid\n");
06770 return -1;
06771 }
06772
06773 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
06774
06775 if(debug)
06776 printf("After bump: %s\n", myrpt->freq);
06777
06778 return set_freq_ft897(myrpt, myrpt->freq);
06779 }
06780
06781
06782
06783
06784
06785
06786
06787
06788
06789
06790
06791 static int check_freq_ic706(int m, int d, int *defmode)
06792 {
06793 int dflmd = REM_MODE_FM;
06794
06795 if(m == 1){
06796 dflmd = REM_MODE_LSB;
06797 if(d < 80000)
06798 return -1;
06799 }
06800 else if(m == 3){
06801 dflmd = REM_MODE_LSB;
06802 if(d < 50000)
06803 return -1;
06804 }
06805 else if(m == 7){
06806 dflmd = REM_MODE_LSB;
06807 if(d > 30000)
06808 return -1;
06809 }
06810 else if(m == 14){
06811 dflmd = REM_MODE_USB;
06812 if(d > 35000)
06813 return -1;
06814 }
06815 else if(m == 18){
06816 dflmd = REM_MODE_USB;
06817 if((d < 6800) || (d > 16800))
06818 return -1;
06819 }
06820 else if(m == 21){
06821 dflmd = REM_MODE_USB;
06822 if((d < 20000) || (d > 45000))
06823 return -1;
06824 }
06825 else if(m == 24){
06826 dflmd = REM_MODE_USB;
06827 if((d < 89000) || (d > 99000))
06828 return -1;
06829 }
06830 else if(m == 28){
06831 dflmd = REM_MODE_USB;
06832 }
06833 else if(m == 29){
06834 if(d >= 51000)
06835 dflmd = REM_MODE_FM;
06836 else
06837 dflmd = REM_MODE_USB;
06838 if(d > 70000)
06839 return -1;
06840 }
06841 else if(m == 50){
06842 if(d >= 30000)
06843 dflmd = REM_MODE_FM;
06844 else
06845 dflmd = REM_MODE_USB;
06846
06847 }
06848 else if((m >= 51) && ( m < 54)){
06849 dflmd = REM_MODE_FM;
06850 }
06851 else if(m == 144){
06852 if(d >= 30000)
06853 dflmd = REM_MODE_FM;
06854 else
06855 dflmd = REM_MODE_USB;
06856 }
06857 else if((m >= 145) && (m < 148)){
06858 dflmd = REM_MODE_FM;
06859 }
06860 else if((m >= 430) && (m < 450)){
06861 if(m < 438)
06862 dflmd = REM_MODE_USB;
06863 else
06864 dflmd = REM_MODE_FM;
06865 ;
06866 }
06867 else
06868 return -1;
06869
06870 if(defmode)
06871 *defmode = dflmd;
06872
06873 return 0;
06874 }
06875
06876
06877 static int ic706_pltocode(char *str)
06878 {
06879 int i;
06880 char *s;
06881
06882 s = strchr(str,'.');
06883 i = 0;
06884 if (s) i = atoi(s + 1);
06885 i += atoi(str) * 10;
06886 switch(i)
06887 {
06888 case 670:
06889 return 0;
06890 case 693:
06891 return 1;
06892 case 719:
06893 return 2;
06894 case 744:
06895 return 3;
06896 case 770:
06897 return 4;
06898 case 797:
06899 return 5;
06900 case 825:
06901 return 6;
06902 case 854:
06903 return 7;
06904 case 885:
06905 return 8;
06906 case 915:
06907 return 9;
06908 case 948:
06909 return 10;
06910 case 974:
06911 return 11;
06912 case 1000:
06913 return 12;
06914 case 1035:
06915 return 13;
06916 case 1072:
06917 return 14;
06918 case 1109:
06919 return 15;
06920 case 1148:
06921 return 16;
06922 case 1188:
06923 return 17;
06924 case 1230:
06925 return 18;
06926 case 1273:
06927 return 19;
06928 case 1318:
06929 return 20;
06930 case 1365:
06931 return 21;
06932 case 1413:
06933 return 22;
06934 case 1462:
06935 return 23;
06936 case 1514:
06937 return 24;
06938 case 1567:
06939 return 25;
06940 case 1598:
06941 return 26;
06942 case 1622:
06943 return 27;
06944 case 1655:
06945 return 28;
06946 case 1679:
06947 return 29;
06948 case 1713:
06949 return 30;
06950 case 1738:
06951 return 31;
06952 case 1773:
06953 return 32;
06954 case 1799:
06955 return 33;
06956 case 1835:
06957 return 34;
06958 case 1862:
06959 return 35;
06960 case 1899:
06961 return 36;
06962 case 1928:
06963 return 37;
06964 case 1966:
06965 return 38;
06966 case 1995:
06967 return 39;
06968 case 2035:
06969 return 40;
06970 case 2065:
06971 return 41;
06972 case 2107:
06973 return 42;
06974 case 2181:
06975 return 43;
06976 case 2257:
06977 return 44;
06978 case 2291:
06979 return 45;
06980 case 2336:
06981 return 46;
06982 case 2418:
06983 return 47;
06984 case 2503:
06985 return 48;
06986 case 2541:
06987 return 49;
06988 }
06989 return -1;
06990 }
06991
06992
06993
06994 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
06995 {
06996 unsigned char cmdstr[10];
06997
06998 cmdstr[0] = cmdstr[1] = 0xfe;
06999 cmdstr[2] = myrpt->p.civaddr;
07000 cmdstr[3] = 0xe0;
07001 cmdstr[4] = command;
07002 cmdstr[5] = subcommand;
07003 cmdstr[6] = 0xfd;
07004
07005 return(civ_cmd(myrpt,cmdstr,7));
07006 }
07007
07008
07009
07010
07011
07012 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
07013 {
07014 unsigned char cmdstr[20];
07015 char mhz[MAXREMSTR], decimals[MAXREMSTR];
07016 int fd,m,d;
07017
07018 fd = 0;
07019 if(debug)
07020 printf("New frequency: %s\n",newfreq);
07021
07022 if(split_freq(mhz, decimals, newfreq))
07023 return -1;
07024
07025 m = atoi(mhz);
07026 d = atoi(decimals);
07027
07028
07029
07030 cmdstr[0] = cmdstr[1] = 0xfe;
07031 cmdstr[2] = myrpt->p.civaddr;
07032 cmdstr[3] = 0xe0;
07033 cmdstr[4] = 5;
07034 cmdstr[5] = ((d % 10) << 4);
07035 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
07036 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
07037 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
07038 cmdstr[9] = (m / 100);
07039 cmdstr[10] = 0xfd;
07040
07041 return(civ_cmd(myrpt,cmdstr,11));
07042 }
07043
07044
07045
07046 static int set_offset_ic706(struct rpt *myrpt, char offset)
07047 {
07048 unsigned char c;
07049
07050 switch(offset){
07051 case REM_SIMPLEX:
07052 c = 0x10;
07053 break;
07054
07055 case REM_MINUS:
07056 c = 0x11;
07057 break;
07058
07059 case REM_PLUS:
07060 c = 0x12;
07061 break;
07062
07063 default:
07064 return -1;
07065 }
07066
07067 return simple_command_ic706(myrpt,0x0f,c);
07068
07069 }
07070
07071
07072
07073 static int set_mode_ic706(struct rpt *myrpt, char newmode)
07074 {
07075 unsigned char c;
07076
07077 switch(newmode){
07078 case REM_MODE_FM:
07079 c = 5;
07080 break;
07081
07082 case REM_MODE_USB:
07083 c = 1;
07084 break;
07085
07086 case REM_MODE_LSB:
07087 c = 0;
07088 break;
07089
07090 case REM_MODE_AM:
07091 c = 2;
07092 break;
07093
07094 default:
07095 return -1;
07096 }
07097 return simple_command_ic706(myrpt,6,c);
07098 }
07099
07100
07101
07102 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
07103 {
07104 unsigned char cmdstr[10];
07105 int rv;
07106
07107 cmdstr[0] = cmdstr[1] = 0xfe;
07108 cmdstr[2] = myrpt->p.civaddr;
07109 cmdstr[3] = 0xe0;
07110 cmdstr[4] = 0x16;
07111 cmdstr[5] = 0x42;
07112 cmdstr[6] = (txplon != 0);
07113 cmdstr[7] = 0xfd;
07114
07115 rv = civ_cmd(myrpt,cmdstr,8);
07116 if (rv) return(-1);
07117
07118 cmdstr[0] = cmdstr[1] = 0xfe;
07119 cmdstr[2] = myrpt->p.civaddr;
07120 cmdstr[3] = 0xe0;
07121 cmdstr[4] = 0x16;
07122 cmdstr[5] = 0x43;
07123 cmdstr[6] = (rxplon != 0);
07124 cmdstr[7] = 0xfd;
07125
07126 return(civ_cmd(myrpt,cmdstr,8));
07127 }
07128
07129 #if 0
07130
07131
07132 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
07133 {
07134 unsigned char cmdstr[10];
07135 char hertz[MAXREMSTR],decimal[MAXREMSTR];
07136 int h,d,rv;
07137
07138 memset(cmdstr, 0, 5);
07139
07140 if(split_ctcss_freq(hertz, decimal, txtone))
07141 return -1;
07142
07143 h = atoi(hertz);
07144 d = atoi(decimal);
07145
07146 cmdstr[0] = cmdstr[1] = 0xfe;
07147 cmdstr[2] = myrpt->p.civaddr;
07148 cmdstr[3] = 0xe0;
07149 cmdstr[4] = 0x1b;
07150 cmdstr[5] = 0;
07151 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
07152 cmdstr[7] = ((h % 10) << 4) + (d % 10);
07153 cmdstr[8] = 0xfd;
07154
07155 rv = civ_cmd(myrpt,cmdstr,9);
07156 if (rv) return(-1);
07157
07158 if (!rxtone) return(0);
07159
07160 if(split_ctcss_freq(hertz, decimal, rxtone))
07161 return -1;
07162
07163 h = atoi(hertz);
07164 d = atoi(decimal);
07165
07166 cmdstr[0] = cmdstr[1] = 0xfe;
07167 cmdstr[2] = myrpt->p.civaddr;
07168 cmdstr[3] = 0xe0;
07169 cmdstr[4] = 0x1b;
07170 cmdstr[5] = 1;
07171 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
07172 cmdstr[7] = ((h % 10) << 4) + (d % 10);
07173 cmdstr[8] = 0xfd;
07174 return(civ_cmd(myrpt,cmdstr,9));
07175 }
07176 #endif
07177
07178 static int vfo_ic706(struct rpt *myrpt)
07179 {
07180 unsigned char cmdstr[10];
07181
07182 cmdstr[0] = cmdstr[1] = 0xfe;
07183 cmdstr[2] = myrpt->p.civaddr;
07184 cmdstr[3] = 0xe0;
07185 cmdstr[4] = 7;
07186 cmdstr[5] = 0xfd;
07187
07188 return(civ_cmd(myrpt,cmdstr,6));
07189 }
07190
07191 static int mem2vfo_ic706(struct rpt *myrpt)
07192 {
07193 unsigned char cmdstr[10];
07194
07195 cmdstr[0] = cmdstr[1] = 0xfe;
07196 cmdstr[2] = myrpt->p.civaddr;
07197 cmdstr[3] = 0xe0;
07198 cmdstr[4] = 0x0a;
07199 cmdstr[5] = 0xfd;
07200
07201 return(civ_cmd(myrpt,cmdstr,6));
07202 }
07203
07204 static int select_mem_ic706(struct rpt *myrpt, int slot)
07205 {
07206 unsigned char cmdstr[10];
07207
07208 cmdstr[0] = cmdstr[1] = 0xfe;
07209 cmdstr[2] = myrpt->p.civaddr;
07210 cmdstr[3] = 0xe0;
07211 cmdstr[4] = 8;
07212 cmdstr[5] = 0;
07213 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
07214 cmdstr[7] = 0xfd;
07215
07216 return(civ_cmd(myrpt,cmdstr,8));
07217 }
07218
07219 static int set_ic706(struct rpt *myrpt)
07220 {
07221 int res = 0,i;
07222
07223 if(debug)
07224 printf("Set to VFO A\n");
07225
07226 if (!res)
07227 res = simple_command_ic706(myrpt,7,0);
07228
07229
07230 if((myrpt->remmode == REM_MODE_FM))
07231 {
07232 i = ic706_pltocode(myrpt->rxpl);
07233 if (i == -1) return -1;
07234 if(debug)
07235 printf("Select memory number\n");
07236 if (!res)
07237 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
07238 if(debug)
07239 printf("Transfer memory to VFO\n");
07240 if (!res)
07241 res = mem2vfo_ic706(myrpt);
07242 }
07243
07244 if(debug)
07245 printf("Set to VFO\n");
07246
07247 if (!res)
07248 res = vfo_ic706(myrpt);
07249
07250 if(debug)
07251 printf("Modulation mode\n");
07252
07253 if (!res)
07254 res = set_mode_ic706(myrpt, myrpt->remmode);
07255
07256 if(debug)
07257 printf("Split off\n");
07258
07259 if(!res)
07260 simple_command_ic706(myrpt, 0x82,0);
07261
07262 if(debug)
07263 printf("Frequency\n");
07264
07265 if(!res)
07266 res = set_freq_ic706(myrpt, myrpt->freq);
07267 if((myrpt->remmode == REM_MODE_FM)){
07268 if(debug)
07269 printf("Offset\n");
07270 if(!res)
07271 res = set_offset_ic706(myrpt, myrpt->offset);
07272 if(!res){
07273 if(debug)
07274 printf("CTCSS mode\n");
07275 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
07276 }
07277 }
07278 return res;
07279 }
07280
07281
07282
07283
07284
07285
07286
07287 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
07288 {
07289 int m,d;
07290 char mhz[MAXREMSTR], decimals[MAXREMSTR];
07291 unsigned char cmdstr[20];
07292
07293 if(debug)
07294 printf("Before bump: %s\n", myrpt->freq);
07295
07296 if(split_freq(mhz, decimals, myrpt->freq))
07297 return -1;
07298
07299 m = atoi(mhz);
07300 d = atoi(decimals);
07301
07302 d += (interval / 10);
07303 if(d < 0){
07304 m--;
07305 d += 100000;
07306 }
07307 else if(d >= 100000){
07308 m++;
07309 d -= 100000;
07310 }
07311
07312 if(check_freq_ic706(m, d, NULL)){
07313 if(debug)
07314 printf("Bump freq invalid\n");
07315 return -1;
07316 }
07317
07318 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
07319
07320 if(debug)
07321 printf("After bump: %s\n", myrpt->freq);
07322
07323
07324
07325 cmdstr[0] = cmdstr[1] = 0xfe;
07326 cmdstr[2] = myrpt->p.civaddr;
07327 cmdstr[3] = 0xe0;
07328 cmdstr[4] = 0;
07329 cmdstr[5] = ((d % 10) << 4);
07330 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
07331 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
07332 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
07333 cmdstr[9] = (m / 100);
07334 cmdstr[10] = 0xfd;
07335
07336 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
07337 }
07338
07339
07340
07341
07342
07343
07344
07345 static int setrem(struct rpt *myrpt)
07346 {
07347 char str[300];
07348 char *offsets[] = {"MINUS","SIMPLEX","PLUS"};
07349 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
07350 char *modes[] = {"FM","USB","LSB","AM"};
07351 int res = -1;
07352
07353 if (myrpt->p.archivedir)
07354 {
07355 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
07356 modes[(int)myrpt->remmode],
07357 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
07358 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
07359 myrpt->rxplon);
07360 donodelog(myrpt,str);
07361 }
07362 if(!strcmp(myrpt->remote, remote_rig_ft897))
07363 {
07364 rpt_telemetry(myrpt,SETREMOTE,NULL);
07365 res = 0;
07366 }
07367 if(!strcmp(myrpt->remote, remote_rig_ic706))
07368 {
07369 rpt_telemetry(myrpt,SETREMOTE,NULL);
07370 res = 0;
07371 }
07372 else if(!strcmp(myrpt->remote, remote_rig_rbi))
07373 {
07374 res = setrbi_check(myrpt);
07375 if (!res)
07376 {
07377 rpt_telemetry(myrpt,SETREMOTE,NULL);
07378 res = 0;
07379 }
07380 }
07381 else if(!strcmp(myrpt->remote, remote_rig_kenwood)) {
07382 rpt_telemetry(myrpt,SETREMOTE,NULL);
07383 res = 0;
07384 }
07385 else
07386 res = 0;
07387
07388 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
07389
07390 return res;
07391 }
07392
07393 static int closerem(struct rpt *myrpt)
07394 {
07395 if(!strcmp(myrpt->remote, remote_rig_ft897))
07396 return closerem_ft897(myrpt);
07397 else
07398 return 0;
07399 }
07400
07401
07402
07403
07404
07405 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
07406 {
07407 if(!strcmp(myrpt->remote, remote_rig_ft897))
07408 return check_freq_ft897(m, d, defmode);
07409 else if(!strcmp(myrpt->remote, remote_rig_ic706))
07410 return check_freq_ic706(m, d, defmode);
07411 else if(!strcmp(myrpt->remote, remote_rig_rbi))
07412 return check_freq_rbi(m, d, defmode);
07413 else if(!strcmp(myrpt->remote, remote_rig_kenwood))
07414 return check_freq_kenwood(m, d, defmode);
07415 else
07416 return -1;
07417 }
07418
07419
07420
07421
07422
07423 static char check_tx_freq(struct rpt *myrpt)
07424 {
07425 int i;
07426 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
07427 char radio_mhz_char[MAXREMSTR];
07428 char radio_decimals_char[MAXREMSTR];
07429 char limit_mhz_char[MAXREMSTR];
07430 char limit_decimals_char[MAXREMSTR];
07431 char limits[256];
07432 char *limit_ranges[40];
07433 struct ast_variable *limitlist;
07434
07435
07436
07437
07438 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
07439 if(debug > 3){
07440 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in\n");
07441 }
07442 return 1;
07443 }
07444
07445
07446 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
07447
07448 if(!limitlist){
07449 ast_log(LOG_WARNING, "No entries in %s band table stanza\n", myrpt->p.txlimitsstanzaname);
07450 return 0;
07451 }
07452
07453 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
07454 radio_mhz = atoi(radio_mhz_char);
07455 radio_decimals = decimals2int(radio_decimals_char);
07456
07457
07458 if(debug > 3){
07459 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
07460 }
07461
07462
07463
07464 for(;limitlist; limitlist=limitlist->next){
07465 if(!strcmp(limitlist->name, myrpt->loginlevel))
07466 break;
07467 }
07468
07469 if(!limitlist){
07470 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
07471 return 0;
07472 }
07473
07474 if(debug > 3){
07475 ast_log(LOG_NOTICE, "Auth %s = %s\n", limitlist->name, limitlist->value);
07476 }
07477
07478
07479
07480 strncpy(limits, limitlist->value, 256);
07481 limits[255] = 0;
07482 finddelim(limits, limit_ranges, 40);
07483 for(i = 0; i < 40 && limit_ranges[i] ; i++){
07484 char range[40];
07485 char *r,*s;
07486 strncpy(range, limit_ranges[i], 40);
07487 range[39] = 0;
07488 if(debug > 3){
07489 ast_log(LOG_NOTICE, "Checking to see if %s is within limits of %s\n", myrpt->freq, range);
07490 }
07491
07492 r = strchr(range, '-');
07493 if(!r){
07494 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry\n", limitlist->name);
07495 return 0;
07496 }
07497 *r++ = 0;
07498 s = eatwhite(range);
07499 r = eatwhite(r);
07500 split_freq(limit_mhz_char, limit_decimals_char, s);
07501 llimit_mhz = atoi(limit_mhz_char);
07502 llimit_decimals = decimals2int(limit_decimals_char);
07503 split_freq(limit_mhz_char, limit_decimals_char, r);
07504 ulimit_mhz = atoi(limit_mhz_char);
07505 ulimit_decimals = decimals2int(limit_decimals_char);
07506
07507 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
07508 if(radio_mhz == llimit_mhz){
07509 if(radio_decimals >= llimit_decimals){
07510 if(llimit_mhz == ulimit_mhz){
07511 if(radio_decimals <= ulimit_decimals){
07512 return 1;
07513 }
07514 else{
07515 if(debug > 3)
07516 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
07517 return 0;
07518 }
07519 }
07520 else{
07521 return 1;
07522 }
07523 }
07524 else{
07525 if(debug > 3)
07526 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
07527 return 0;
07528 }
07529 }
07530 else if(radio_mhz == ulimit_mhz){
07531 if(radio_decimals <= ulimit_decimals){
07532 return 1;
07533 }
07534 else{
07535 if(debug > 3)
07536 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
07537 return 0;
07538 }
07539 }
07540 else
07541 return 1;
07542 }
07543 }
07544 if(debug > 3)
07545 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 4\n");
07546 return 0;
07547 }
07548
07549
07550
07551
07552
07553
07554 static int multimode_bump_freq(struct rpt *myrpt, int interval)
07555 {
07556 if(!strcmp(myrpt->remote, remote_rig_ft897))
07557 return multimode_bump_freq_ft897(myrpt, interval);
07558 else if(!strcmp(myrpt->remote, remote_rig_ic706))
07559 return multimode_bump_freq_ic706(myrpt, interval);
07560 else
07561 return -1;
07562 }
07563
07564
07565
07566
07567
07568
07569 static void stop_scan(struct rpt *myrpt)
07570 {
07571 myrpt->hfscanstop = 1;
07572 rpt_telemetry(myrpt,SCAN,0);
07573 }
07574
07575
07576
07577
07578
07579
07580 static int service_scan(struct rpt *myrpt)
07581 {
07582 int res, interval;
07583 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
07584
07585 switch(myrpt->hfscanmode){
07586
07587 case HF_SCAN_DOWN_SLOW:
07588 interval = -10;
07589 break;
07590
07591 case HF_SCAN_DOWN_QUICK:
07592 interval = -50;
07593 break;
07594
07595 case HF_SCAN_DOWN_FAST:
07596 interval = -200;
07597 break;
07598
07599 case HF_SCAN_UP_SLOW:
07600 interval = 10;
07601 break;
07602
07603 case HF_SCAN_UP_QUICK:
07604 interval = 50;
07605 break;
07606
07607 case HF_SCAN_UP_FAST:
07608 interval = 200;
07609 break;
07610
07611 default:
07612 myrpt->hfscanmode = 0;
07613 return -1;
07614 }
07615
07616 res = split_freq(mhz, decimals, myrpt->freq);
07617
07618 if(!res){
07619 k100 =decimals[0];
07620 k10 = decimals[1];
07621 res = multimode_bump_freq(myrpt, interval);
07622 }
07623
07624 if(!res)
07625 res = split_freq(mhz, decimals, myrpt->freq);
07626
07627
07628 if(res){
07629 myrpt->hfscanmode = 0;
07630 myrpt->hfscanstatus = -2;
07631 return -1;
07632 }
07633
07634
07635 if(k10 != decimals[1]){
07636 int myhund = (interval < 0) ? k100 : decimals[0];
07637 int myten = (interval < 0) ? k10 : decimals[1];
07638 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
07639 } else myrpt->hfscanstatus = 0;
07640 return res;
07641
07642 }
07643
07644
07645
07646
07647
07648
07649
07650
07651 static int retreive_memory(struct rpt *myrpt, char *memory)
07652 {
07653 char tmp[30], *s, *s1, *val;
07654
07655 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
07656 if (!val){
07657 return -1;
07658 }
07659 strncpy(tmp,val,sizeof(tmp) - 1);
07660 tmp[sizeof(tmp)-1] = 0;
07661
07662 s = strchr(tmp,',');
07663 if (!s)
07664 return 1;
07665 *s++ = 0;
07666 s1 = strchr(s,',');
07667 if (!s1)
07668 return 1;
07669 *s1++ = 0;
07670 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
07671 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
07672 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
07673 myrpt->remmode = REM_MODE_FM;
07674 myrpt->offset = REM_SIMPLEX;
07675 myrpt->powerlevel = REM_MEDPWR;
07676 myrpt->txplon = myrpt->rxplon = 0;
07677 while(*s1){
07678 switch(*s1++){
07679 case 'A':
07680 case 'a':
07681 strcpy(myrpt->rxpl, "100.0");
07682 strcpy(myrpt->txpl, "100.0");
07683 myrpt->remmode = REM_MODE_AM;
07684 break;
07685 case 'B':
07686 case 'b':
07687 strcpy(myrpt->rxpl, "100.0");
07688 strcpy(myrpt->txpl, "100.0");
07689 myrpt->remmode = REM_MODE_LSB;
07690 break;
07691 case 'F':
07692 myrpt->remmode = REM_MODE_FM;
07693 break;
07694 case 'L':
07695 case 'l':
07696 myrpt->powerlevel = REM_LOWPWR;
07697 break;
07698 case 'H':
07699 case 'h':
07700 myrpt->powerlevel = REM_HIPWR;
07701 break;
07702
07703 case 'M':
07704 case 'm':
07705 myrpt->powerlevel = REM_MEDPWR;
07706 break;
07707
07708 case '-':
07709 myrpt->offset = REM_MINUS;
07710 break;
07711
07712 case '+':
07713 myrpt->offset = REM_PLUS;
07714 break;
07715
07716 case 'S':
07717 case 's':
07718 myrpt->offset = REM_SIMPLEX;
07719 break;
07720
07721 case 'T':
07722 case 't':
07723 myrpt->txplon = 1;
07724 break;
07725
07726 case 'R':
07727 case 'r':
07728 myrpt->rxplon = 1;
07729 break;
07730
07731 case 'U':
07732 case 'u':
07733 strcpy(myrpt->rxpl, "100.0");
07734 strcpy(myrpt->txpl, "100.0");
07735 myrpt->remmode = REM_MODE_USB;
07736 break;
07737 default:
07738 return 1;
07739 }
07740 }
07741 return 0;
07742 }
07743
07744
07745
07746
07747
07748
07749
07750 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
07751 {
07752 char *s,*s1,*s2;
07753 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
07754 intptr_t p;
07755 char multimode = 0;
07756 char oc,*cp,*cp1,*cp2;
07757 char tmp[20], freq[20] = "", savestr[20] = "";
07758 char mhz[MAXREMSTR], decimals[MAXREMSTR];
07759
07760 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
07761 return DC_ERROR;
07762
07763 p = myatoi(param);
07764
07765 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
07766 (!myrpt->loginlevel[0])) return DC_ERROR;
07767 multimode = multimode_capable(myrpt);
07768
07769 switch(p){
07770
07771 case 1:
07772 if(strlen(digitbuf) < 2)
07773 break;
07774
07775 for(i = 0 ; i < 2 ; i++){
07776 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07777 return DC_ERROR;
07778 }
07779
07780 r = retreive_memory(myrpt, digitbuf);
07781 if (r < 0){
07782 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
07783 return DC_COMPLETE;
07784 }
07785 if (r > 0){
07786 return DC_ERROR;
07787 }
07788 if (setrem(myrpt) == -1) return DC_ERROR;
07789 return DC_COMPLETE;
07790
07791 case 2:
07792
07793
07794 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07795 if(digitbuf[i] == '*'){
07796 j++;
07797 continue;
07798 }
07799 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07800 goto invalid_freq;
07801 else{
07802 if(j == 0)
07803 l++;
07804 if(j == 1)
07805 k++;
07806 }
07807 }
07808
07809 i = strlen(digitbuf) - 1;
07810 if(multimode){
07811 if((j > 2) || (l > 3) || (k > 6))
07812 goto invalid_freq;
07813 }
07814 else{
07815 if((j > 2) || (l > 4) || (k > 3))
07816 goto invalid_freq;
07817 }
07818
07819
07820
07821 if(j < 2)
07822 break;
07823
07824
07825
07826 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
07827
07828 s = tmp;
07829 s1 = strsep(&s, "*");
07830 s2 = strsep(&s,"*");
07831 ls2 = strlen(s2);
07832
07833 switch(ls2){
07834 case 1:
07835 ht = 0;
07836 k = 100 * atoi(s2);
07837 break;
07838
07839 case 2:
07840 ht = 0;
07841 k = 10 * atoi(s2);
07842 break;
07843
07844 case 3:
07845 if(!multimode){
07846 if((s2[2] != '0')&&(s2[2] != '5'))
07847 goto invalid_freq;
07848 }
07849 ht = 0;
07850 k = atoi(s2);
07851 break;
07852 case 4:
07853 k = atoi(s2)/10;
07854 ht = 10 * (atoi(s2+(ls2-1)));
07855 break;
07856
07857 case 5:
07858 k = atoi(s2)/100;
07859 ht = (atoi(s2+(ls2-2)));
07860 break;
07861
07862 default:
07863 goto invalid_freq;
07864 }
07865
07866
07867
07868 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
07869
07870 if(debug)
07871 printf("New frequency: %s\n", freq);
07872
07873 split_freq(mhz, decimals, freq);
07874 m = atoi(mhz);
07875 d = atoi(decimals);
07876
07877 if(check_freq(myrpt, m, d, &defmode))
07878 goto invalid_freq;
07879
07880
07881 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
07882 break;
07883
07884
07885 offset = REM_SIMPLEX;
07886
07887 if(defmode == REM_MODE_FM){
07888 oc = *s;
07889
07890 if (oc){
07891 switch(oc){
07892 case '1':
07893 offset = REM_MINUS;
07894 break;
07895
07896 case '2':
07897 offset = REM_SIMPLEX;
07898 break;
07899
07900 case '3':
07901 offset = REM_PLUS;
07902 break;
07903
07904 default:
07905 goto invalid_freq;
07906 }
07907 }
07908 }
07909 offsave = myrpt->offset;
07910 modesave = myrpt->remmode;
07911 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
07912 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
07913 myrpt->offset = offset;
07914 myrpt->remmode = defmode;
07915
07916 if (setrem(myrpt) == -1){
07917 myrpt->offset = offsave;
07918 myrpt->remmode = modesave;
07919 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
07920 goto invalid_freq;
07921 }
07922
07923 return DC_COMPLETE;
07924
07925 invalid_freq:
07926 rpt_telemetry(myrpt,INVFREQ,NULL);
07927 return DC_ERROR;
07928
07929 case 3:
07930 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07931 if(digitbuf[i] == '*'){
07932 j++;
07933 continue;
07934 }
07935 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07936 return DC_ERROR;
07937 else{
07938 if(j)
07939 l++;
07940 else
07941 k++;
07942 }
07943 }
07944 if((j > 1) || (k > 3) || (l > 1))
07945 return DC_ERROR;
07946 i = strlen(digitbuf) - 1;
07947 if((j != 1) || (k < 2)|| (l != 1))
07948 break;
07949 if(debug)
07950 printf("PL digits entered %s\n", digitbuf);
07951
07952 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
07953
07954 s = strchr(tmp,'*');
07955 if(s)
07956 *s = '.';
07957 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
07958 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
07959 if(!strcmp(myrpt->remote, remote_rig_rbi))
07960 {
07961 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
07962 }
07963 if (setrem(myrpt) == -1){
07964 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
07965 return DC_ERROR;
07966 }
07967
07968
07969 return DC_COMPLETE;
07970
07971 case 4:
07972
07973 if(!strcmp(myrpt->remote, remote_rig_rbi))
07974 return DC_ERROR;
07975 if(!strcmp(myrpt->remote, remote_rig_ic706))
07976 return DC_ERROR;
07977 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07978 if(digitbuf[i] == '*'){
07979 j++;
07980 continue;
07981 }
07982 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07983 return DC_ERROR;
07984 else{
07985 if(j)
07986 l++;
07987 else
07988 k++;
07989 }
07990 }
07991 if((j > 1) || (k > 3) || (l > 1))
07992 return DC_ERROR;
07993 i = strlen(digitbuf) - 1;
07994 if((j != 1) || (k < 2)|| (l != 1))
07995 break;
07996 if(debug)
07997 printf("PL digits entered %s\n", digitbuf);
07998
07999 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
08000
08001 s = strchr(tmp,'*');
08002 if(s)
08003 *s = '.';
08004 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
08005 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
08006
08007 if (setrem(myrpt) == -1){
08008 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
08009 return DC_ERROR;
08010 }
08011
08012
08013 return DC_COMPLETE;
08014
08015
08016 case 6:
08017 if(strlen(digitbuf) < 1)
08018 break;
08019
08020 if(!multimode)
08021 return DC_ERROR;
08022
08023 switch(*digitbuf){
08024 case '1':
08025 split_freq(mhz, decimals, myrpt->freq);
08026 m=atoi(mhz);
08027 if(m < 29)
08028 return DC_ERROR;
08029 myrpt->remmode = REM_MODE_FM;
08030
08031 rpt_telemetry(myrpt,REMMODE,NULL);
08032 break;
08033
08034 case '2':
08035 myrpt->remmode = REM_MODE_USB;
08036 rpt_telemetry(myrpt,REMMODE,NULL);
08037 break;
08038
08039 case '3':
08040 myrpt->remmode = REM_MODE_LSB;
08041 rpt_telemetry(myrpt,REMMODE,NULL);
08042 break;
08043
08044 case '4':
08045 myrpt->remmode = REM_MODE_AM;
08046 rpt_telemetry(myrpt,REMMODE,NULL);
08047 break;
08048
08049 default:
08050 return DC_ERROR;
08051 }
08052
08053 if(setrem(myrpt))
08054 return DC_ERROR;
08055 return DC_COMPLETEQUIET;
08056 case 99:
08057
08058 if (myrpt->loginlevel[0])
08059 return DC_ERROR;
08060 *myrpt->loginuser = 0;
08061 myrpt->loginlevel[0] = 0;
08062 cp = strdup(param);
08063 cp1 = strchr(cp,',');
08064 ast_mutex_lock(&myrpt->lock);
08065 if (cp1)
08066 {
08067 *cp1 = 0;
08068 cp2 = strchr(cp1 + 1,',');
08069 if (cp2)
08070 {
08071 *cp2 = 0;
08072 strncpy(myrpt->loginlevel,cp2 + 1,
08073 sizeof(myrpt->loginlevel) - 1);
08074 }
08075 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
08076 ast_mutex_unlock(&myrpt->lock);
08077 if (myrpt->p.archivedir)
08078 {
08079 char str[100];
08080
08081 sprintf(str,"LOGIN,%s,%s",
08082 myrpt->loginuser,myrpt->loginlevel);
08083 donodelog(myrpt,str);
08084 }
08085 if (debug)
08086 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
08087 rpt_telemetry(myrpt,REMLOGIN,NULL);
08088 }
08089 free(cp);
08090 return DC_COMPLETEQUIET;
08091 case 100:
08092 myrpt->rxplon = 0;
08093 setrem(myrpt);
08094 rpt_telemetry(myrpt,REMXXX,(void *)p);
08095 return DC_COMPLETEQUIET;
08096 case 101:
08097 myrpt->rxplon = 1;
08098 setrem(myrpt);
08099 rpt_telemetry(myrpt,REMXXX,(void *)p);
08100 return DC_COMPLETEQUIET;
08101 case 102:
08102 myrpt->txplon = 0;
08103 setrem(myrpt);
08104 rpt_telemetry(myrpt,REMXXX,(void *)p);
08105 return DC_COMPLETEQUIET;
08106 case 103:
08107 myrpt->txplon = 1;
08108 setrem(myrpt);
08109 rpt_telemetry(myrpt,REMXXX,(void *)p);
08110 return DC_COMPLETEQUIET;
08111 case 104:
08112 if(!strcmp(myrpt->remote, remote_rig_ic706))
08113 return DC_ERROR;
08114 myrpt->powerlevel = REM_LOWPWR;
08115 setrem(myrpt);
08116 rpt_telemetry(myrpt,REMXXX,(void *)p);
08117 return DC_COMPLETEQUIET;
08118 case 105:
08119 if(!strcmp(myrpt->remote, remote_rig_ic706))
08120 return DC_ERROR;
08121 myrpt->powerlevel = REM_MEDPWR;
08122 setrem(myrpt);
08123 rpt_telemetry(myrpt,REMXXX,(void *)p);
08124 return DC_COMPLETEQUIET;
08125 case 106:
08126 if(!strcmp(myrpt->remote, remote_rig_ic706))
08127 return DC_ERROR;
08128 myrpt->powerlevel = REM_HIPWR;
08129 setrem(myrpt);
08130 rpt_telemetry(myrpt,REMXXX,(void *)p);
08131 return DC_COMPLETEQUIET;
08132 case 107:
08133 multimode_bump_freq(myrpt, -20);
08134 return DC_COMPLETE;
08135 case 108:
08136 multimode_bump_freq(myrpt, -100);
08137 return DC_COMPLETE;
08138 case 109:
08139 multimode_bump_freq(myrpt, -500);
08140 return DC_COMPLETE;
08141 case 110:
08142 multimode_bump_freq(myrpt, 20);
08143 return DC_COMPLETE;
08144 case 111:
08145 multimode_bump_freq(myrpt, 100);
08146 return DC_COMPLETE;
08147 case 112:
08148 multimode_bump_freq(myrpt, 500);
08149 return DC_COMPLETE;
08150 case 113:
08151 myrpt->scantimer = REM_SCANTIME;
08152 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
08153 rpt_telemetry(myrpt,REMXXX,(void *)p);
08154 return DC_COMPLETEQUIET;
08155 case 114:
08156 myrpt->scantimer = REM_SCANTIME;
08157 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
08158 rpt_telemetry(myrpt,REMXXX,(void *)p);
08159 return DC_COMPLETEQUIET;
08160 case 115:
08161 myrpt->scantimer = REM_SCANTIME;
08162 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
08163 rpt_telemetry(myrpt,REMXXX,(void *)p);
08164 return DC_COMPLETEQUIET;
08165 case 116:
08166 myrpt->scantimer = REM_SCANTIME;
08167 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
08168 rpt_telemetry(myrpt,REMXXX,(void *)p);
08169 return DC_COMPLETEQUIET;
08170 case 117:
08171 myrpt->scantimer = REM_SCANTIME;
08172 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
08173 rpt_telemetry(myrpt,REMXXX,(void *)p);
08174 return DC_COMPLETEQUIET;
08175 case 118:
08176 myrpt->scantimer = REM_SCANTIME;
08177 myrpt->hfscanmode = HF_SCAN_UP_FAST;
08178 rpt_telemetry(myrpt,REMXXX,(void *)p);
08179 return DC_COMPLETEQUIET;
08180 case 119:
08181
08182 if((!myrpt->tunerequest) &&
08183 ((!strcmp(myrpt->remote, remote_rig_ft897) ||
08184 !strcmp(myrpt->remote, remote_rig_ic706)) )) {
08185 myrpt->remotetx = 0;
08186 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08187 myrpt->tunerequest = 1;
08188 rpt_telemetry(myrpt,TUNE,NULL);
08189 return DC_COMPLETEQUIET;
08190 }
08191 return DC_ERROR;
08192 case 5:
08193 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
08194 return DC_COMPLETEQUIET;
08195 case 140:
08196 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
08197 return DC_COMPLETEQUIET;
08198 case 200:
08199 case 201:
08200 case 202:
08201 case 203:
08202 case 204:
08203 case 205:
08204 case 206:
08205 case 207:
08206 case 208:
08207 case 209:
08208 case 210:
08209 case 211:
08210 case 212:
08211 case 213:
08212 case 214:
08213 case 215:
08214 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
08215 return DC_COMPLETEQUIET;
08216 default:
08217 break;
08218 }
08219 return DC_INDETERMINATE;
08220 }
08221
08222
08223 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
08224 {
08225 time_t now;
08226 int ret,res = 0,src;
08227
08228 time(&myrpt->last_activity_time);
08229
08230 if(myrpt->hfscanmode){
08231 stop_scan(myrpt);
08232 return 0;
08233 }
08234
08235 time(&now);
08236
08237 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
08238 {
08239 myrpt->dtmfidx = -1;
08240 myrpt->dtmfbuf[0] = 0;
08241 myrpt->dtmf_time_rem = 0;
08242 }
08243
08244 if (myrpt->dtmfidx == -1)
08245 {
08246
08247 if (c != myrpt->p.funcchar)
08248 {
08249 if (!myrpt->p.propagate_dtmf)
08250 {
08251 rpt_mutex_lock(&myrpt->lock);
08252 do_dtmf_local(myrpt,c);
08253 rpt_mutex_unlock(&myrpt->lock);
08254 }
08255 return 0;
08256 }
08257 myrpt->dtmfidx = 0;
08258 myrpt->dtmfbuf[0] = 0;
08259 myrpt->dtmf_time_rem = now;
08260 return 0;
08261 }
08262
08263 if (myrpt->dtmfidx >= MAXDTMF)
08264 {
08265 myrpt->dtmfidx = 0;
08266 myrpt->dtmfbuf[0] = 0;
08267 myrpt->dtmf_time_rem = now;
08268 }
08269 if (c == myrpt->p.funcchar)
08270 {
08271
08272 if ((myrpt->dtmfidx < 1) ||
08273 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
08274 {
08275 myrpt->dtmfidx = 0;
08276 myrpt->dtmfbuf[0] = 0;
08277 myrpt->dtmf_time_rem = now;
08278 return 0;
08279 }
08280 }
08281 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08282 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08283 myrpt->dtmf_time_rem = now;
08284
08285
08286 src = SOURCE_RMT;
08287 if (phonemode > 1) src = SOURCE_DPHONE;
08288 else if (phonemode) src = SOURCE_PHONE;
08289 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
08290
08291 switch(ret){
08292
08293 case DC_INDETERMINATE:
08294 res = 0;
08295 break;
08296
08297 case DC_DOKEY:
08298 if (keyed) *keyed = 1;
08299 res = 0;
08300 break;
08301
08302 case DC_REQ_FLUSH:
08303 myrpt->dtmfidx = 0;
08304 myrpt->dtmfbuf[0] = 0;
08305 res = 0;
08306 break;
08307
08308
08309 case DC_COMPLETE:
08310 res = 1;
08311 case DC_COMPLETEQUIET:
08312 myrpt->totalexecdcommands++;
08313 myrpt->dailyexecdcommands++;
08314 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
08315 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08316 myrpt->dtmfbuf[0] = 0;
08317 myrpt->dtmfidx = -1;
08318 myrpt->dtmf_time_rem = 0;
08319 break;
08320
08321 case DC_ERROR:
08322 default:
08323 myrpt->dtmfbuf[0] = 0;
08324 myrpt->dtmfidx = -1;
08325 myrpt->dtmf_time_rem = 0;
08326 res = 0;
08327 break;
08328 }
08329
08330 return res;
08331 }
08332
08333 static int handle_remote_data(struct rpt *myrpt, char *str)
08334 {
08335 char tmp[300],cmd[300],dest[300],src[300],c;
08336 int seq,res;
08337
08338
08339 strncpy(tmp,str,sizeof(tmp) - 1);
08340 if (!strcmp(tmp,discstr)) return 0;
08341
08342 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
08343 if (tmp[0] == 'I')
08344 {
08345 if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
08346 {
08347 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
08348 return 0;
08349 }
08350 mdc1200_notify(myrpt,src,seq);
08351 return 0;
08352 }
08353 #endif
08354 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
08355 {
08356 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08357 return 0;
08358 }
08359 if (strcmp(cmd,"D"))
08360 {
08361 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08362 return 0;
08363 }
08364
08365 if (strcmp(dest,myrpt->name)) return 0;
08366 if (myrpt->p.archivedir)
08367 {
08368 char str[100];
08369
08370 sprintf(str,"DTMF,%c",c);
08371 donodelog(myrpt,str);
08372 }
08373 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
08374 if (!c) return(0);
08375 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
08376 if (res != 1)
08377 return res;
08378 rpt_telemetry(myrpt,COMPLETE,NULL);
08379 return 0;
08380 }
08381
08382 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
08383 {
08384 int res;
08385
08386
08387 if (keyed && *keyed && (c == myrpt->p.endchar))
08388 {
08389 *keyed = 0;
08390 return DC_INDETERMINATE;
08391 }
08392
08393 if (myrpt->p.archivedir)
08394 {
08395 char str[100];
08396
08397 sprintf(str,"DTMF(P),%c",c);
08398 donodelog(myrpt,str);
08399 }
08400 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
08401 if (res != 1)
08402 return res;
08403 rpt_telemetry(myrpt,COMPLETE,NULL);
08404 return 0;
08405 }
08406
08407 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
08408 {
08409 char *val, *s, *s1, *s2, *tele;
08410 char tmp[300], deststr[300] = "";
08411
08412 val = node_lookup(myrpt,l->name);
08413 if (!val)
08414 {
08415 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
08416 return -1;
08417 }
08418
08419 rpt_mutex_lock(&myrpt->lock);
08420
08421 remque((struct qelem *) l);
08422 rpt_mutex_unlock(&myrpt->lock);
08423 strncpy(tmp,val,sizeof(tmp) - 1);
08424 s = tmp;
08425 s1 = strsep(&s,",");
08426 s2 = strsep(&s,",");
08427 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
08428 tele = strchr(deststr, '/');
08429 if (!tele) {
08430 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
08431 return -1;
08432 }
08433 *tele++ = 0;
08434 l->elaptime = 0;
08435 l->connecttime = 0;
08436 l->thisconnected = 0;
08437 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
08438 if (l->chan){
08439 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
08440 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
08441 l->chan->whentohangup = 0;
08442 l->chan->appl = "Apprpt";
08443 l->chan->data = "(Remote Rx)";
08444 if (option_verbose > 2)
08445 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
08446 deststr, tele, l->chan->name);
08447 if(l->chan->cid.cid_num)
08448 free(l->chan->cid.cid_num);
08449 l->chan->cid.cid_num = strdup(myrpt->name);
08450 ast_call(l->chan,tele,999);
08451
08452 }
08453 else
08454 {
08455 if (option_verbose > 2)
08456 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
08457 deststr,tele,l->chan->name);
08458 return -1;
08459 }
08460 rpt_mutex_lock(&myrpt->lock);
08461
08462 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
08463 rpt_mutex_unlock(&myrpt->lock);
08464 ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
08465 return 0;
08466 }
08467
08468
08469 static void local_dtmf_helper(struct rpt *myrpt,char c)
08470 {
08471 int res;
08472 pthread_attr_t attr;
08473 char cmd[MAXDTMF+1] = "";
08474
08475 if (myrpt->p.archivedir)
08476 {
08477 char str[100];
08478
08479 sprintf(str,"DTMF,MAIN,%c",c);
08480 donodelog(myrpt,str);
08481 }
08482 if (c == myrpt->p.endchar)
08483 {
08484
08485 if (myrpt->p.simple && myrpt->callmode)
08486 {
08487 rpt_mutex_lock(&myrpt->lock);
08488 myrpt->callmode = 0;
08489 rpt_mutex_unlock(&myrpt->lock);
08490 rpt_telemetry(myrpt,TERM,NULL);
08491 return;
08492 }
08493 rpt_mutex_lock(&myrpt->lock);
08494 myrpt->stopgen = 1;
08495 if (myrpt->cmdnode[0])
08496 {
08497 myrpt->cmdnode[0] = 0;
08498 myrpt->dtmfidx = -1;
08499 myrpt->dtmfbuf[0] = 0;
08500 rpt_mutex_unlock(&myrpt->lock);
08501 rpt_telemetry(myrpt,COMPLETE,NULL);
08502 }
08503 else
08504 {
08505 rpt_mutex_unlock(&myrpt->lock);
08506 if (myrpt->p.propagate_phonedtmf)
08507 do_dtmf_phone(myrpt,NULL,c);
08508 }
08509 return;
08510 }
08511 rpt_mutex_lock(&myrpt->lock);
08512 if (myrpt->cmdnode[0])
08513 {
08514 rpt_mutex_unlock(&myrpt->lock);
08515 send_link_dtmf(myrpt,c);
08516 return;
08517 }
08518 if (!myrpt->p.simple)
08519 {
08520 if (c == myrpt->p.funcchar)
08521 {
08522 myrpt->dtmfidx = 0;
08523 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08524 rpt_mutex_unlock(&myrpt->lock);
08525 time(&myrpt->dtmf_time);
08526 return;
08527 }
08528 else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0))
08529 {
08530 time(&myrpt->dtmf_time);
08531
08532 if (myrpt->dtmfidx < MAXDTMF)
08533 {
08534 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08535 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08536
08537 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
08538
08539 rpt_mutex_unlock(&myrpt->lock);
08540 res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
08541 rpt_mutex_lock(&myrpt->lock);
08542 switch(res){
08543 case DC_INDETERMINATE:
08544 break;
08545 case DC_REQ_FLUSH:
08546 myrpt->dtmfidx = 0;
08547 myrpt->dtmfbuf[0] = 0;
08548 break;
08549 case DC_COMPLETE:
08550 case DC_COMPLETEQUIET:
08551 myrpt->totalexecdcommands++;
08552 myrpt->dailyexecdcommands++;
08553 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
08554 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08555 myrpt->dtmfbuf[0] = 0;
08556 myrpt->dtmfidx = -1;
08557 myrpt->dtmf_time = 0;
08558 break;
08559
08560 case DC_ERROR:
08561 default:
08562 myrpt->dtmfbuf[0] = 0;
08563 myrpt->dtmfidx = -1;
08564 myrpt->dtmf_time = 0;
08565 break;
08566 }
08567 if(res != DC_INDETERMINATE) {
08568 rpt_mutex_unlock(&myrpt->lock);
08569 return;
08570 }
08571 }
08572 }
08573 }
08574 else
08575 {
08576 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
08577 {
08578 myrpt->callmode = 1;
08579 myrpt->patchnoct = 0;
08580 myrpt->patchquiet = 0;
08581 myrpt->patchfarenddisconnect = 0;
08582 myrpt->patchdialtime = 0;
08583 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
08584 myrpt->cidx = 0;
08585 myrpt->exten[myrpt->cidx] = 0;
08586 rpt_mutex_unlock(&myrpt->lock);
08587 pthread_attr_init(&attr);
08588 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08589 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
08590 return;
08591 }
08592 }
08593 if (myrpt->callmode == 1)
08594 {
08595 myrpt->exten[myrpt->cidx++] = c;
08596 myrpt->exten[myrpt->cidx] = 0;
08597
08598 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08599 {
08600 myrpt->callmode = 2;
08601 rpt_mutex_unlock(&myrpt->lock);
08602 if(!myrpt->patchquiet)
08603 rpt_telemetry(myrpt,PROC,NULL);
08604 return;
08605 }
08606
08607 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08608 {
08609
08610 myrpt->callmode = 4;
08611 }
08612 rpt_mutex_unlock(&myrpt->lock);
08613 return;
08614 }
08615 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
08616 {
08617 myrpt->mydtmf = c;
08618 }
08619 rpt_mutex_unlock(&myrpt->lock);
08620 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
08621 do_dtmf_phone(myrpt,NULL,c);
08622 return;
08623 }
08624
08625
08626
08627
08628 static void queue_id(struct rpt *myrpt)
08629 {
08630 if(myrpt->p.idtime){
08631 myrpt->mustid = myrpt->tailid = 0;
08632 myrpt->idtimer = myrpt->p.idtime;
08633 rpt_mutex_unlock(&myrpt->lock);
08634 rpt_telemetry(myrpt,ID,NULL);
08635 rpt_mutex_lock(&myrpt->lock);
08636 }
08637 }
08638
08639
08640
08641
08642 static void do_scheduler(struct rpt *myrpt)
08643 {
08644 int i,res;
08645 struct tm tmnow;
08646 struct ast_variable *skedlist;
08647 char *strs[5],*vp,*val,value[100];
08648
08649 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
08650
08651 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
08652 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
08653
08654
08655
08656 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
08657 return;
08658
08659 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
08660
08661
08662
08663 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
08664 myrpt->dailykeyups = 0;
08665 myrpt->dailytxtime = 0;
08666 myrpt->dailykerchunks = 0;
08667 myrpt->dailyexecdcommands = 0;
08668 }
08669
08670 if(tmnow.tm_sec != 0)
08671 return;
08672
08673
08674
08675
08676
08677
08678 if (myrpt->remote)
08679 return;
08680
08681
08682
08683 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
08684 if(debug > 6)
08685 ast_log(LOG_NOTICE, "Scheduler disabled\n");
08686 return;
08687 }
08688
08689 if(!myrpt->p.skedstanzaname){
08690 if(debug > 6)
08691 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
08692 return;
08693 }
08694
08695
08696 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
08697
08698 if(debug > 6){
08699 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
08700 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
08701 }
08702
08703 for(; skedlist; skedlist = skedlist->next){
08704 if(debug > 6)
08705 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
08706 strncpy(value,skedlist->value,99);
08707 value[99] = 0;
08708
08709 for( i = 0, vp = value ; i < 5; i++){
08710 if(!*vp)
08711 break;
08712 while((*vp == ' ') || (*vp == 0x09))
08713 vp++;
08714 strs[i] = vp;
08715 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
08716 vp++;
08717 if(*vp)
08718 *vp++ = 0;
08719 }
08720 if(debug > 6)
08721 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
08722 strs[0], strs[1], strs[2], strs[3], strs[4]);
08723 if(i == 5){
08724 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
08725 continue;
08726 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
08727 continue;
08728 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
08729 continue;
08730 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
08731 continue;
08732 if(atoi(strs[4]) == 7)
08733 strs[4] = "0";
08734 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
08735 continue;
08736 if(debug)
08737 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
08738 if(atoi(skedlist->name) == 0)
08739 return;
08740 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
08741 if (!val){
08742 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
08743 return;
08744 }
08745 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
08746 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
08747 skedlist->name);
08748 return;
08749 }
08750 myrpt->macrotimer = MACROTIME;
08751 strncat(myrpt->macrobuf,val,MAXMACRO - strlen(myrpt->macrobuf) - 1);
08752 }
08753 else{
08754 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
08755 skedlist->name, skedlist->value);
08756 }
08757 }
08758
08759 }
08760
08761
08762 static void *rpt(void *this)
08763 {
08764 struct rpt *myrpt = (struct rpt *)this;
08765 char *tele,*idtalkover,c;
08766 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
08767 int tailmessagequeued,ctqueued,dtmfed;
08768 struct ast_channel *who;
08769 struct dahdi_confinfo ci;
08770 time_t t;
08771 struct rpt_link *l,*m;
08772 struct rpt_tele *telem;
08773 char tmpstr[300],lstr[MAXLINKLIST];
08774
08775
08776 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
08777 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
08778 mkdir(tmpstr,0600);
08779 rpt_mutex_lock(&myrpt->lock);
08780
08781 telem = myrpt->tele.next;
08782 while(telem != &myrpt->tele)
08783 {
08784 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
08785 telem = telem->next;
08786 }
08787 rpt_mutex_unlock(&myrpt->lock);
08788
08789 for(i = 0; i < nrpts; i++)
08790 {
08791 if (&rpt_vars[i] == myrpt)
08792 {
08793 load_rpt_vars(i,0);
08794 break;
08795 }
08796 }
08797 rpt_mutex_lock(&myrpt->lock);
08798 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
08799 tele = strchr(tmpstr,'/');
08800 if (!tele)
08801 {
08802 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
08803 rpt_mutex_unlock(&myrpt->lock);
08804 myrpt->rpt_thread = AST_PTHREADT_STOP;
08805 pthread_exit(NULL);
08806 }
08807 *tele++ = 0;
08808 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08809 myrpt->zaprxchannel = NULL;
08810 if (!strcasecmp(tmpstr,"Zap"))
08811 myrpt->zaprxchannel = myrpt->rxchannel;
08812 if (myrpt->rxchannel)
08813 {
08814 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
08815 {
08816 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08817 rpt_mutex_unlock(&myrpt->lock);
08818 ast_hangup(myrpt->rxchannel);
08819 myrpt->rpt_thread = AST_PTHREADT_STOP;
08820 pthread_exit(NULL);
08821 }
08822 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08823 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08824 #ifdef AST_CDR_FLAG_POST_DISABLED
08825 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08826 #endif
08827 myrpt->rxchannel->whentohangup = 0;
08828 myrpt->rxchannel->appl = "Apprpt";
08829 myrpt->rxchannel->data = "(Repeater Rx)";
08830 if (option_verbose > 2)
08831 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
08832 tmpstr,tele,myrpt->rxchannel->name);
08833 ast_call(myrpt->rxchannel,tele,999);
08834 if (myrpt->rxchannel->_state != AST_STATE_UP)
08835 {
08836 rpt_mutex_unlock(&myrpt->lock);
08837 ast_hangup(myrpt->rxchannel);
08838 myrpt->rpt_thread = AST_PTHREADT_STOP;
08839 pthread_exit(NULL);
08840 }
08841 }
08842 else
08843 {
08844 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08845 rpt_mutex_unlock(&myrpt->lock);
08846 myrpt->rpt_thread = AST_PTHREADT_STOP;
08847 pthread_exit(NULL);
08848 }
08849 myrpt->zaptxchannel = NULL;
08850 if (myrpt->txchanname)
08851 {
08852 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
08853 tele = strchr(tmpstr,'/');
08854 if (!tele)
08855 {
08856 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
08857 rpt_mutex_unlock(&myrpt->lock);
08858 ast_hangup(myrpt->rxchannel);
08859 myrpt->rpt_thread = AST_PTHREADT_STOP;
08860 pthread_exit(NULL);
08861 }
08862 *tele++ = 0;
08863 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08864 if (!strcasecmp(tmpstr,"Zap"))
08865 myrpt->zaptxchannel = myrpt->txchannel;
08866 if (myrpt->txchannel)
08867 {
08868 if (myrpt->txchannel->_state == AST_STATE_BUSY)
08869 {
08870 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08871 rpt_mutex_unlock(&myrpt->lock);
08872 ast_hangup(myrpt->txchannel);
08873 ast_hangup(myrpt->rxchannel);
08874 myrpt->rpt_thread = AST_PTHREADT_STOP;
08875 pthread_exit(NULL);
08876 }
08877 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08878 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08879 #ifdef AST_CDR_FLAG_POST_DISABLED
08880 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08881 #endif
08882 myrpt->txchannel->whentohangup = 0;
08883 myrpt->txchannel->appl = "Apprpt";
08884 myrpt->txchannel->data = "(Repeater Tx)";
08885 if (option_verbose > 2)
08886 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
08887 tmpstr,tele,myrpt->txchannel->name);
08888 ast_call(myrpt->txchannel,tele,999);
08889 if (myrpt->rxchannel->_state != AST_STATE_UP)
08890 {
08891 rpt_mutex_unlock(&myrpt->lock);
08892 ast_hangup(myrpt->rxchannel);
08893 ast_hangup(myrpt->txchannel);
08894 myrpt->rpt_thread = AST_PTHREADT_STOP;
08895 pthread_exit(NULL);
08896 }
08897 }
08898 else
08899 {
08900 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08901 rpt_mutex_unlock(&myrpt->lock);
08902 ast_hangup(myrpt->rxchannel);
08903 myrpt->rpt_thread = AST_PTHREADT_STOP;
08904 pthread_exit(NULL);
08905 }
08906 }
08907 else
08908 {
08909 myrpt->txchannel = myrpt->rxchannel;
08910 }
08911 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
08912 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08913
08914 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08915 if (!myrpt->pchannel)
08916 {
08917 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08918 rpt_mutex_unlock(&myrpt->lock);
08919 if (myrpt->txchannel != myrpt->rxchannel)
08920 ast_hangup(myrpt->txchannel);
08921 ast_hangup(myrpt->rxchannel);
08922 myrpt->rpt_thread = AST_PTHREADT_STOP;
08923 pthread_exit(NULL);
08924 }
08925 #ifdef AST_CDR_FLAG_POST_DISABLED
08926 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08927 #endif
08928 if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
08929 if (!myrpt->zaptxchannel)
08930 {
08931
08932 myrpt->zaptxchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08933 if (!myrpt->zaptxchannel)
08934 {
08935 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08936 rpt_mutex_unlock(&myrpt->lock);
08937 if (myrpt->txchannel != myrpt->rxchannel)
08938 ast_hangup(myrpt->txchannel);
08939 ast_hangup(myrpt->rxchannel);
08940 myrpt->rpt_thread = AST_PTHREADT_STOP;
08941 pthread_exit(NULL);
08942 }
08943 ast_set_read_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
08944 ast_set_write_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
08945 #ifdef AST_CDR_FLAG_POST_DISABLED
08946 ast_set_flag(myrpt->zaptxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08947 #endif
08948 }
08949
08950 myrpt->monchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08951 if (!myrpt->monchannel)
08952 {
08953 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08954 rpt_mutex_unlock(&myrpt->lock);
08955 if (myrpt->txchannel != myrpt->rxchannel)
08956 ast_hangup(myrpt->txchannel);
08957 ast_hangup(myrpt->rxchannel);
08958 myrpt->rpt_thread = AST_PTHREADT_STOP;
08959 pthread_exit(NULL);
08960 }
08961 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08962 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08963 #ifdef AST_CDR_FLAG_POST_DISABLED
08964 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08965 #endif
08966
08967 ci.chan = 0;
08968 ci.confno = -1;
08969 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
08970
08971 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
08972 {
08973 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08974 rpt_mutex_unlock(&myrpt->lock);
08975 ast_hangup(myrpt->pchannel);
08976 ast_hangup(myrpt->monchannel);
08977 if (myrpt->txchannel != myrpt->rxchannel)
08978 ast_hangup(myrpt->txchannel);
08979 ast_hangup(myrpt->rxchannel);
08980 myrpt->rpt_thread = AST_PTHREADT_STOP;
08981 pthread_exit(NULL);
08982 }
08983
08984 myrpt->txconf = ci.confno;
08985
08986 ci.chan = 0;
08987 ci.confno = -1;
08988 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
08989 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
08990
08991 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
08992 {
08993 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08994 rpt_mutex_unlock(&myrpt->lock);
08995 ast_hangup(myrpt->pchannel);
08996 ast_hangup(myrpt->monchannel);
08997 if (myrpt->txchannel != myrpt->rxchannel)
08998 ast_hangup(myrpt->txchannel);
08999 ast_hangup(myrpt->rxchannel);
09000 myrpt->rpt_thread = AST_PTHREADT_STOP;
09001 pthread_exit(NULL);
09002 }
09003
09004 myrpt->conf = ci.confno;
09005
09006 ci.chan = 0;
09007 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
09008 (myrpt->zaptxchannel == myrpt->txchannel))
09009 {
09010
09011 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
09012 {
09013 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
09014 rpt_mutex_unlock(&myrpt->lock);
09015 ast_hangup(myrpt->pchannel);
09016 ast_hangup(myrpt->monchannel);
09017 if (myrpt->txchannel != myrpt->rxchannel)
09018 ast_hangup(myrpt->txchannel);
09019 ast_hangup(myrpt->rxchannel);
09020 myrpt->rpt_thread = AST_PTHREADT_STOP;
09021 pthread_exit(NULL);
09022 }
09023 ci.confmode = DAHDI_CONF_MONITORTX;
09024 }
09025 else
09026 {
09027 ci.confno = myrpt->txconf;
09028 ci.confmode = DAHDI_CONF_CONFANNMON;
09029 }
09030
09031 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
09032 {
09033 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
09034 rpt_mutex_unlock(&myrpt->lock);
09035 ast_hangup(myrpt->pchannel);
09036 ast_hangup(myrpt->monchannel);
09037 if (myrpt->txchannel != myrpt->rxchannel)
09038 ast_hangup(myrpt->txchannel);
09039 ast_hangup(myrpt->rxchannel);
09040 myrpt->rpt_thread = AST_PTHREADT_STOP;
09041 pthread_exit(NULL);
09042 }
09043
09044 myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
09045 if (!myrpt->txpchannel)
09046 {
09047 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
09048 rpt_mutex_unlock(&myrpt->lock);
09049 ast_hangup(myrpt->pchannel);
09050 ast_hangup(myrpt->monchannel);
09051 if (myrpt->txchannel != myrpt->rxchannel)
09052 ast_hangup(myrpt->txchannel);
09053 ast_hangup(myrpt->rxchannel);
09054 myrpt->rpt_thread = AST_PTHREADT_STOP;
09055 pthread_exit(NULL);
09056 }
09057 #ifdef AST_CDR_FLAG_POST_DISABLED
09058 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
09059 #endif
09060
09061 ci.chan = 0;
09062 ci.confno = myrpt->txconf;
09063 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
09064
09065 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
09066 {
09067 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
09068 rpt_mutex_unlock(&myrpt->lock);
09069 ast_hangup(myrpt->txpchannel);
09070 ast_hangup(myrpt->monchannel);
09071 if (myrpt->txchannel != myrpt->rxchannel)
09072 ast_hangup(myrpt->txchannel);
09073 ast_hangup(myrpt->rxchannel);
09074 myrpt->rpt_thread = AST_PTHREADT_STOP;
09075 pthread_exit(NULL);
09076 }
09077
09078
09079
09080 myrpt->links.next = &myrpt->links;
09081 myrpt->links.prev = &myrpt->links;
09082 myrpt->tailtimer = 0;
09083 myrpt->totimer = 0;
09084 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
09085 myrpt->idtimer = myrpt->p.politeid;
09086 myrpt->mustid = myrpt->tailid = 0;
09087 myrpt->callmode = 0;
09088 myrpt->tounkeyed = 0;
09089 myrpt->tonotify = 0;
09090 myrpt->retxtimer = 0;
09091 myrpt->rerxtimer = 0;
09092 myrpt->skedtimer = 0;
09093 myrpt->tailevent = 0;
09094 lasttx = 0;
09095 myrpt->keyed = 0;
09096 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
09097 myrpt->dtmfidx = -1;
09098 myrpt->dtmfbuf[0] = 0;
09099 myrpt->rem_dtmfidx = -1;
09100 myrpt->rem_dtmfbuf[0] = 0;
09101 myrpt->dtmf_time = 0;
09102 myrpt->rem_dtmf_time = 0;
09103 myrpt->disgorgetime = 0;
09104 myrpt->lastnodewhichkeyedusup[0] = '\0';
09105 myrpt->dailytxtime = 0;
09106 myrpt->totaltxtime = 0;
09107 myrpt->dailykeyups = 0;
09108 myrpt->totalkeyups = 0;
09109 myrpt->dailykerchunks = 0;
09110 myrpt->totalkerchunks = 0;
09111 myrpt->dailyexecdcommands = 0;
09112 myrpt->totalexecdcommands = 0;
09113 myrpt->timeouts = 0;
09114 myrpt->exten[0] = '\0';
09115 myrpt->lastdtmfcommand[0] = '\0';
09116 if (myrpt->p.startupmacro)
09117 {
09118 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
09119 }
09120 rpt_mutex_unlock(&myrpt->lock);
09121 val = 1;
09122 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
09123 val = 1;
09124 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
09125 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
09126 dtmfed = 0;
09127 while (ms >= 0)
09128 {
09129 struct ast_frame *f,*f1,*f2;
09130 struct ast_channel *cs[300],*cs1[300];
09131 int totx=0,elap=0,n,x,toexit=0;
09132
09133
09134 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
09135 struct rpt_link *zl;
09136 struct rpt_tele *zt;
09137
09138 myrpt->disgorgetime = 0;
09139 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
09140 ast_log(LOG_NOTICE,"totx = %d\n",totx);
09141 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
09142 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
09143 ast_log(LOG_NOTICE,"elap = %d\n",elap);
09144 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
09145
09146 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
09147 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
09148 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
09149 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
09150 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
09151 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
09152 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
09153 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
09154 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
09155 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
09156
09157 zl = myrpt->links.next;
09158 while(zl != &myrpt->links){
09159 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
09160 ast_log(LOG_NOTICE," link->lasttx %d\n",zl->lasttx);
09161 ast_log(LOG_NOTICE," link->lastrx %d\n",zl->lastrx);
09162 ast_log(LOG_NOTICE," link->connected %d\n",zl->connected);
09163 ast_log(LOG_NOTICE," link->hasconnected %d\n",zl->hasconnected);
09164 ast_log(LOG_NOTICE," link->outbound %d\n",zl->outbound);
09165 ast_log(LOG_NOTICE," link->disced %d\n",zl->disced);
09166 ast_log(LOG_NOTICE," link->killme %d\n",zl->killme);
09167 ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime);
09168 ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer);
09169 ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries);
09170 ast_log(LOG_NOTICE," link->reconnects = %d\n",zl->reconnects);
09171 zl = zl->next;
09172 }
09173
09174 zt = myrpt->tele.next;
09175 if(zt != &myrpt->tele)
09176 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
09177 while(zt != &myrpt->tele){
09178 ast_log(LOG_NOTICE," Telemetry mode: %d\n",zt->mode);
09179 zt = zt->next;
09180 }
09181 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
09182
09183 }
09184
09185
09186 if (myrpt->reload)
09187 {
09188 struct rpt_tele *telem;
09189
09190 rpt_mutex_lock(&myrpt->lock);
09191 telem = myrpt->tele.next;
09192 while(telem != &myrpt->tele)
09193 {
09194 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
09195 telem = telem->next;
09196 }
09197 myrpt->reload = 0;
09198 rpt_mutex_unlock(&myrpt->lock);
09199 usleep(10000);
09200
09201 for(i = 0; i < nrpts; i++)
09202 {
09203 if (&rpt_vars[i] == myrpt)
09204 {
09205 load_rpt_vars(i,0);
09206 break;
09207 }
09208 }
09209 }
09210
09211 rpt_mutex_lock(&myrpt->lock);
09212 if (ast_check_hangup(myrpt->rxchannel)) break;
09213 if (ast_check_hangup(myrpt->txchannel)) break;
09214 if (ast_check_hangup(myrpt->pchannel)) break;
09215 if (ast_check_hangup(myrpt->monchannel)) break;
09216 if (ast_check_hangup(myrpt->txpchannel)) break;
09217 if (myrpt->zaptxchannel && ast_check_hangup(myrpt->zaptxchannel)) break;
09218
09219
09220 myrpt->localtx = myrpt->keyed;
09221
09222 l = myrpt->links.next;
09223 remrx = 0;
09224 while(l != &myrpt->links)
09225 {
09226 if (l->lastrx){
09227 remrx = 1;
09228 if(l->name[0] != '0')
09229 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
09230 }
09231 l = l->next;
09232 }
09233
09234 if(myrpt->p.idtime)
09235 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
09236
09237 totx = myrpt->callmode;
09238
09239 if (myrpt->p.duplex > 1)
09240 {
09241 totx = totx || myrpt->localtx;
09242 }
09243
09244 identqueued = 0;
09245 othertelemqueued = 0;
09246 tailmessagequeued = 0;
09247 ctqueued = 0;
09248 telem = myrpt->tele.next;
09249 while(telem != &myrpt->tele)
09250 {
09251 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
09252 identqueued = 1;
09253 }
09254 else if(telem->mode == TAILMSG)
09255 {
09256 tailmessagequeued = 1;
09257 }
09258 else
09259 {
09260 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
09261 othertelemqueued = 1;
09262 else
09263 ctqueued = 1;
09264 }
09265 telem = telem->next;
09266 }
09267
09268
09269 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
09270
09271 myrpt->exttx = totx;
09272 totx = totx || myrpt->dtmf_local_timer;
09273
09274 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
09275
09276 totx = totx || remrx;
09277
09278 if (myrpt->p.duplex > 0)
09279 totx = totx || identqueued || ctqueued;
09280
09281 if (myrpt->p.duplex > 1)
09282 {
09283 totx = totx || (myrpt->dtmfidx > -1) ||
09284 myrpt->cmdnode[0];
09285 }
09286
09287 if (!totx)
09288 {
09289 myrpt->totimer = myrpt->p.totime;
09290 myrpt->tounkeyed = 0;
09291 myrpt->tonotify = 0;
09292 }
09293 else{
09294 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
09295 myrpt->p.althangtime :
09296 myrpt->p.hangtime;
09297 }
09298
09299 totx = totx && myrpt->totimer;
09300
09301 if ((!myrpt->totimer) && (!myrpt->tonotify))
09302 {
09303 myrpt->tonotify = 1;
09304 myrpt->timeouts++;
09305 rpt_mutex_unlock(&myrpt->lock);
09306 rpt_telemetry(myrpt,TIMEOUT,NULL);
09307 rpt_mutex_lock(&myrpt->lock);
09308 }
09309
09310
09311 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
09312 {
09313 myrpt->tounkeyed = 1;
09314 }
09315 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
09316 {
09317 myrpt->totimer = myrpt->p.totime;
09318 myrpt->tounkeyed = 0;
09319 myrpt->tonotify = 0;
09320 rpt_mutex_unlock(&myrpt->lock);
09321 continue;
09322 }
09323
09324 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
09325 {
09326 myrpt->callmode = 0;
09327 }
09328
09329 if (!myrpt->totimer) myrpt->tailtimer = 0;
09330
09331 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
09332
09333
09334 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
09335 int hasid = 0,hastalkover = 0;
09336
09337 telem = myrpt->tele.next;
09338 while(telem != &myrpt->tele){
09339 if(telem->mode == ID){
09340 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
09341 hasid = 1;
09342 }
09343 if(telem->mode == TAILMSG){
09344 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
09345 }
09346 if (telem->mode == IDTALKOVER) hastalkover = 1;
09347 telem = telem->next;
09348 }
09349 rpt_mutex_unlock(&myrpt->lock);
09350 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
09351 rpt_mutex_lock(&myrpt->lock);
09352 }
09353
09354
09355
09356
09357
09358 if(myrpt->mustid && (!myrpt->idtimer))
09359 queue_id(myrpt);
09360
09361 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
09362 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
09363 {
09364 myrpt->tailid = 1;
09365 }
09366
09367
09368
09369 if(myrpt->tailevent){
09370 myrpt->tailevent = 0;
09371 if(myrpt->tailid){
09372 totx = 1;
09373 queue_id(myrpt);
09374 }
09375 else if ((myrpt->p.tailmessages[0]) &&
09376 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
09377 totx = 1;
09378 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
09379 rpt_mutex_unlock(&myrpt->lock);
09380 rpt_telemetry(myrpt, TAILMSG, NULL);
09381 rpt_mutex_lock(&myrpt->lock);
09382 }
09383 }
09384
09385
09386
09387
09388 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
09389 if (totx && (!lasttx))
09390 {
09391 char mydate[100],myfname[100];
09392 time_t myt;
09393
09394 if (myrpt->monstream) ast_closestream(myrpt->monstream);
09395 if (myrpt->p.archivedir)
09396 {
09397 long blocksleft;
09398
09399 time(&myt);
09400 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
09401 localtime(&myt));
09402 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
09403 myrpt->name,mydate);
09404 myrpt->monstream = ast_writefile(myfname,"wav49",
09405 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
09406 if (myrpt->p.monminblocks)
09407 {
09408 blocksleft = diskavail(myrpt);
09409 if (blocksleft >= myrpt->p.monminblocks)
09410 donodelog(myrpt,"TXKEY,MAIN");
09411 } else donodelog(myrpt,"TXKEY,MAIN");
09412 }
09413 lasttx = 1;
09414 myrpt->dailykeyups++;
09415 myrpt->totalkeyups++;
09416 rpt_mutex_unlock(&myrpt->lock);
09417 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
09418 rpt_mutex_lock(&myrpt->lock);
09419 }
09420 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
09421 if ((!totx) && lasttx)
09422 {
09423 if (myrpt->monstream) ast_closestream(myrpt->monstream);
09424 myrpt->monstream = NULL;
09425
09426 lasttx = 0;
09427 rpt_mutex_unlock(&myrpt->lock);
09428 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
09429 rpt_mutex_lock(&myrpt->lock);
09430 donodelog(myrpt,"TXUNKEY,MAIN");
09431 }
09432 time(&t);
09433
09434 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
09435 {
09436 myrpt->dtmfidx = -1;
09437 myrpt->dtmfbuf[0] = 0;
09438 }
09439
09440 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
09441 {
09442 myrpt->rem_dtmfidx = -1;
09443 myrpt->rem_dtmfbuf[0] = 0;
09444 }
09445
09446
09447
09448 l = myrpt->links.next;
09449 while(l != &myrpt->links)
09450 {
09451 if (l->killme)
09452 {
09453
09454 remque((struct qelem *) l);
09455 if (!strcmp(myrpt->cmdnode,l->name))
09456 myrpt->cmdnode[0] = 0;
09457 rpt_mutex_unlock(&myrpt->lock);
09458
09459 if (l->chan) ast_hangup(l->chan);
09460 ast_hangup(l->pchan);
09461 free(l);
09462 rpt_mutex_lock(&myrpt->lock);
09463
09464 l = myrpt->links.next;
09465 continue;
09466 }
09467 l = l->next;
09468 }
09469 n = 0;
09470 cs[n++] = myrpt->rxchannel;
09471 cs[n++] = myrpt->pchannel;
09472 cs[n++] = myrpt->monchannel;
09473 cs[n++] = myrpt->txpchannel;
09474 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
09475 if (myrpt->zaptxchannel != myrpt->txchannel)
09476 cs[n++] = myrpt->zaptxchannel;
09477 l = myrpt->links.next;
09478 while(l != &myrpt->links)
09479 {
09480 if ((!l->killme) && (!l->disctime) && l->chan)
09481 {
09482 cs[n++] = l->chan;
09483 cs[n++] = l->pchan;
09484 }
09485 l = l->next;
09486 }
09487 rpt_mutex_unlock(&myrpt->lock);
09488 ms = MSWAIT;
09489 for(x = 0; x < n; x++)
09490 {
09491 int s = -(-x - myrpt->scram - 1) % n;
09492 cs1[x] = cs[s];
09493 }
09494 myrpt->scram++;
09495 who = ast_waitfor_n(cs1,n,&ms);
09496 if (who == NULL) ms = 0;
09497 elap = MSWAIT - ms;
09498 rpt_mutex_lock(&myrpt->lock);
09499 l = myrpt->links.next;
09500 while(l != &myrpt->links)
09501 {
09502 if (l->linklisttimer)
09503 {
09504 l->linklisttimer -= elap;
09505 if (l->linklisttimer < 0) l->linklisttimer = 0;
09506 }
09507 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
09508 {
09509 struct ast_frame lf;
09510
09511 memset(&lf,0,sizeof(lf));
09512 lf.frametype = AST_FRAME_TEXT;
09513 lf.subclass = 0;
09514 lf.offset = 0;
09515 lf.mallocd = 0;
09516 lf.samples = 0;
09517 l->linklisttimer = LINKLISTTIME;
09518 strcpy(lstr,"L ");
09519 __mklinklist(myrpt,l,lstr + 2);
09520 if (l->chan)
09521 {
09522 lf.datalen = strlen(lstr) + 1;
09523 lf.data = lstr;
09524 ast_write(l->chan,&lf);
09525 if (debug > 6) ast_log(LOG_NOTICE,
09526 "@@@@ node %s sent node string %s to node %s\n",
09527 myrpt->name,lstr,l->name);
09528 }
09529 }
09530 #ifndef OLDKEY
09531 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
09532 {
09533 l->retxtimer = 0;
09534 if (l->chan && l->phonemode == 0)
09535 {
09536 if (l->lasttx)
09537 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09538 else
09539 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09540 }
09541 }
09542 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
09543 {
09544 if (debug == 7) printf("@@@@ rx un-key\n");
09545 l->lastrx = 0;
09546 l->rerxtimer = 0;
09547 if(myrpt->p.duplex)
09548 rpt_telemetry(myrpt,LINKUNKEY,l);
09549 if (myrpt->p.archivedir)
09550 {
09551 char str[100];
09552
09553 l->lastrx1 = 0;
09554 sprintf(str,"RXUNKEY(T),%s",l->name);
09555 donodelog(myrpt,str);
09556 }
09557 }
09558 #endif
09559 if (l->disctime)
09560 {
09561 l->disctime -= elap;
09562 if (l->disctime <= 0)
09563 l->disctime = 0;
09564 }
09565
09566 if (l->retrytimer)
09567 {
09568 l->retrytimer -= elap;
09569 if (l->retrytimer < 0) l->retrytimer = 0;
09570 }
09571
09572
09573 l->connecttime += elap;
09574
09575
09576 if (l->elaptime < 0)
09577 {
09578 l = l->next;
09579 continue;
09580 }
09581 l->elaptime += elap;
09582
09583 if ((l->elaptime > MAXCONNECTTIME) &&
09584 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
09585 {
09586 l->elaptime = 0;
09587 rpt_mutex_unlock(&myrpt->lock);
09588 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
09589 rpt_mutex_lock(&myrpt->lock);
09590 break;
09591 }
09592 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
09593 (l->retries++ < l->max_retries) && (l->hasconnected))
09594 {
09595 if (l->chan) ast_hangup(l->chan);
09596 l->chan = 0;
09597 rpt_mutex_unlock(&myrpt->lock);
09598 if ((l->name[0] != '0') && (!l->isremote))
09599 {
09600 if (attempt_reconnect(myrpt,l) == -1)
09601 {
09602 l->retrytimer = RETRY_TIMER_MS;
09603 }
09604 }
09605 else
09606 {
09607 l->retrytimer = l->max_retries + 1;
09608 }
09609
09610 rpt_mutex_lock(&myrpt->lock);
09611 break;
09612 }
09613 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
09614 (l->retries >= l->max_retries))
09615 {
09616
09617 remque((struct qelem *) l);
09618 if (!strcmp(myrpt->cmdnode,l->name))
09619 myrpt->cmdnode[0] = 0;
09620 rpt_mutex_unlock(&myrpt->lock);
09621 if (l->name[0] != '0')
09622 {
09623 if (!l->hasconnected)
09624 rpt_telemetry(myrpt,CONNFAIL,l);
09625 else rpt_telemetry(myrpt,REMDISC,l);
09626 }
09627 if (myrpt->p.archivedir)
09628 {
09629 char str[100];
09630
09631 if (!l->hasconnected)
09632 sprintf(str,"LINKFAIL,%s",l->name);
09633 else
09634 sprintf(str,"LINKDISC,%s",l->name);
09635 donodelog(myrpt,str);
09636 }
09637
09638 ast_hangup(l->pchan);
09639 free(l);
09640 rpt_mutex_lock(&myrpt->lock);
09641 break;
09642 }
09643 if ((!l->chan) && (!l->disctime) && (!l->outbound))
09644 {
09645
09646 remque((struct qelem *) l);
09647 if (!strcmp(myrpt->cmdnode,l->name))
09648 myrpt->cmdnode[0] = 0;
09649 rpt_mutex_unlock(&myrpt->lock);
09650 if (l->name[0] != '0')
09651 {
09652 rpt_telemetry(myrpt,REMDISC,l);
09653 }
09654 if (myrpt->p.archivedir)
09655 {
09656 char str[100];
09657
09658 sprintf(str,"LINKDISC,%s",l->name);
09659 donodelog(myrpt,str);
09660 }
09661
09662 ast_hangup(l->pchan);
09663 free(l);
09664 rpt_mutex_lock(&myrpt->lock);
09665 break;
09666 }
09667 l = l->next;
09668 }
09669 if(totx){
09670 myrpt->dailytxtime += elap;
09671 myrpt->totaltxtime += elap;
09672 }
09673 i = myrpt->tailtimer;
09674 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
09675 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
09676 if((i) && (myrpt->tailtimer == 0))
09677 myrpt->tailevent = 1;
09678 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
09679 if (myrpt->totimer < 0) myrpt->totimer = 0;
09680 if (myrpt->idtimer) myrpt->idtimer -= elap;
09681 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
09682 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
09683 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
09684
09685 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
09686 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
09687
09688 if (myrpt->dtmf_local_timer)
09689 {
09690 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
09691 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
09692 }
09693 do_dtmf_local(myrpt,0);
09694
09695 if (myrpt->skedtimer <= 0){
09696 myrpt->skedtimer = 200;
09697 do_scheduler(myrpt);
09698 }
09699 else
09700 myrpt->skedtimer -=elap;
09701 if (!ms)
09702 {
09703 rpt_mutex_unlock(&myrpt->lock);
09704 continue;
09705 }
09706 c = myrpt->macrobuf[0];
09707 time(&t);
09708 if (c && (!myrpt->macrotimer) &&
09709 starttime && (t > (starttime + START_DELAY)))
09710 {
09711 myrpt->macrotimer = MACROTIME;
09712 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
09713 if ((c == 'p') || (c == 'P'))
09714 myrpt->macrotimer = MACROPTIME;
09715 rpt_mutex_unlock(&myrpt->lock);
09716 if (myrpt->p.archivedir)
09717 {
09718 char str[100];
09719
09720 sprintf(str,"DTMF(M),MAIN,%c",c);
09721 donodelog(myrpt,str);
09722 }
09723 local_dtmf_helper(myrpt,c);
09724 } else rpt_mutex_unlock(&myrpt->lock);
09725 if (who == myrpt->rxchannel)
09726 {
09727 int ismuted;
09728
09729 f = ast_read(myrpt->rxchannel);
09730 if (!f)
09731 {
09732 if (debug) printf("@@@@ rpt:Hung Up\n");
09733 break;
09734 }
09735 if (f->frametype == AST_FRAME_VOICE)
09736 {
09737 #ifdef _MDC_DECODE_H_
09738 unsigned char ubuf[2560];
09739 short *sp;
09740 int n;
09741 #endif
09742
09743 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
09744 memset(f->data,0,f->datalen);
09745 }
09746
09747 #ifdef _MDC_DECODE_H_
09748 sp = (short *) f->data;
09749
09750 for(n = 0; n < f->datalen / 2; n++)
09751 {
09752 ubuf[n] = (*sp++ >> 8) + 128;
09753 }
09754 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
09755 if (n == 1)
09756 {
09757 unsigned char op,arg;
09758 unsigned short unitID;
09759
09760 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
09761 if (debug > 2)
09762 {
09763 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
09764 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09765 op & 255,arg & 255,unitID);
09766 }
09767 if ((op == 1) && (arg == 0))
09768 {
09769 myrpt->lastunit = unitID;
09770 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
09771 mdc1200_send(myrpt,myrpt->lastunit);
09772 }
09773 }
09774 if ((debug > 2) && (i == 2))
09775 {
09776 unsigned char op,arg,ex1,ex2,ex3,ex4;
09777 unsigned short unitID;
09778
09779 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
09780 &ex1,&ex2,&ex3,&ex4);
09781 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
09782 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09783 op & 255,arg & 255,unitID);
09784 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
09785 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
09786 }
09787 #endif
09788 #ifdef __RPT_NOTCH
09789
09790 rpt_filter(myrpt,f->data,f->datalen / 2);
09791 #endif
09792 if (ioctl(myrpt->zaprxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
09793 {
09794 ismuted = 0;
09795 }
09796 if (dtmfed) ismuted = 1;
09797 dtmfed = 0;
09798 if (ismuted)
09799 {
09800 memset(f->data,0,f->datalen);
09801 if (myrpt->lastf1)
09802 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09803 if (myrpt->lastf2)
09804 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09805 }
09806 if (f) f2 = ast_frdup(f);
09807 else f2 = NULL;
09808 f1 = myrpt->lastf2;
09809 myrpt->lastf2 = myrpt->lastf1;
09810 myrpt->lastf1 = f2;
09811 if (ismuted)
09812 {
09813 if (myrpt->lastf1)
09814 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09815 if (myrpt->lastf2)
09816 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09817 }
09818 if (f1)
09819 {
09820 ast_write(myrpt->pchannel,f1);
09821 ast_frfree(f1);
09822 }
09823 }
09824 #ifndef OLD_ASTERISK
09825 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
09826 {
09827 if (myrpt->lastf1)
09828 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09829 if (myrpt->lastf2)
09830 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09831 dtmfed = 1;
09832 }
09833 #endif
09834 else if (f->frametype == AST_FRAME_DTMF)
09835 {
09836 c = (char) f->subclass;
09837 ast_frfree(f);
09838 if (myrpt->lastf1)
09839 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09840 if (myrpt->lastf2)
09841 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09842 dtmfed = 1;
09843 if (!myrpt->keyed) continue;
09844 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
09845 if (c) local_dtmf_helper(myrpt,c);
09846 continue;
09847 }
09848 else if (f->frametype == AST_FRAME_CONTROL)
09849 {
09850 if (f->subclass == AST_CONTROL_HANGUP)
09851 {
09852 if (debug) printf("@@@@ rpt:Hung Up\n");
09853 ast_frfree(f);
09854 break;
09855 }
09856
09857 if (f->subclass == AST_CONTROL_RADIO_KEY)
09858 {
09859 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
09860 {
09861 if (debug == 7) printf("@@@@ rx key\n");
09862 myrpt->keyed = 1;
09863 }
09864 if (myrpt->p.archivedir)
09865 {
09866 donodelog(myrpt,"RXKEY,MAIN");
09867 }
09868 }
09869
09870 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
09871 {
09872 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
09873 {
09874 if (debug == 7) printf("@@@@ rx un-key\n");
09875 if(myrpt->p.duplex && myrpt->keyed) {
09876 rpt_telemetry(myrpt,UNKEY,NULL);
09877 }
09878 }
09879 myrpt->keyed = 0;
09880 if (myrpt->p.archivedir)
09881 {
09882 donodelog(myrpt,"RXUNKEY,MAIN");
09883 }
09884 }
09885 }
09886 ast_frfree(f);
09887 continue;
09888 }
09889 if (who == myrpt->pchannel)
09890 {
09891 f = ast_read(myrpt->pchannel);
09892 if (!f)
09893 {
09894 if (debug) printf("@@@@ rpt:Hung Up\n");
09895 break;
09896 }
09897 if (f->frametype == AST_FRAME_VOICE)
09898 {
09899 ast_write(myrpt->txpchannel,f);
09900 }
09901 if (f->frametype == AST_FRAME_CONTROL)
09902 {
09903 if (f->subclass == AST_CONTROL_HANGUP)
09904 {
09905 if (debug) printf("@@@@ rpt:Hung Up\n");
09906 ast_frfree(f);
09907 break;
09908 }
09909 }
09910 ast_frfree(f);
09911 continue;
09912 }
09913 if (who == myrpt->txchannel)
09914 {
09915 f = ast_read(myrpt->txchannel);
09916 if (!f)
09917 {
09918 if (debug) printf("@@@@ rpt:Hung Up\n");
09919 break;
09920 }
09921 if (f->frametype == AST_FRAME_CONTROL)
09922 {
09923 if (f->subclass == AST_CONTROL_HANGUP)
09924 {
09925 if (debug) printf("@@@@ rpt:Hung Up\n");
09926 ast_frfree(f);
09927 break;
09928 }
09929 }
09930 ast_frfree(f);
09931 continue;
09932 }
09933 if (who == myrpt->zaptxchannel)
09934 {
09935 f = ast_read(myrpt->zaptxchannel);
09936 if (!f)
09937 {
09938 if (debug) printf("@@@@ rpt:Hung Up\n");
09939 break;
09940 }
09941 if (f->frametype == AST_FRAME_VOICE)
09942 {
09943 ast_write(myrpt->txchannel,f);
09944 }
09945 if (f->frametype == AST_FRAME_CONTROL)
09946 {
09947 if (f->subclass == AST_CONTROL_HANGUP)
09948 {
09949 if (debug) printf("@@@@ rpt:Hung Up\n");
09950 ast_frfree(f);
09951 break;
09952 }
09953 }
09954 ast_frfree(f);
09955 continue;
09956 }
09957 toexit = 0;
09958 rpt_mutex_lock(&myrpt->lock);
09959 l = myrpt->links.next;
09960 while(l != &myrpt->links)
09961 {
09962 if (l->disctime)
09963 {
09964 l = l->next;
09965 continue;
09966 }
09967 if (who == l->chan)
09968 {
09969 int remnomute;
09970
09971 remrx = 0;
09972
09973 m = myrpt->links.next;
09974 while(m != &myrpt->links)
09975 {
09976
09977 if ((m != l) && (m->lastrx)) remrx = 1;
09978 m = m->next;
09979 }
09980 rpt_mutex_unlock(&myrpt->lock);
09981 remnomute = myrpt->localtx &&
09982 (!(myrpt->cmdnode[0] ||
09983 (myrpt->dtmfidx > -1)));
09984 totx = (((l->isremote) ? (remnomute) :
09985 myrpt->exttx) || remrx) && l->mode;
09986 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
09987 {
09988 if (totx)
09989 {
09990 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09991 }
09992 else
09993 {
09994 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09995 }
09996 if (myrpt->p.archivedir)
09997 {
09998 char str[100];
09999
10000 if (totx)
10001 sprintf(str,"TXKEY,%s",l->name);
10002 else
10003 sprintf(str,"TXUNKEY,%s",l->name);
10004 donodelog(myrpt,str);
10005 }
10006 }
10007 l->lasttx = totx;
10008 f = ast_read(l->chan);
10009 if (!f)
10010 {
10011 rpt_mutex_lock(&myrpt->lock);
10012 __kickshort(myrpt);
10013 rpt_mutex_unlock(&myrpt->lock);
10014 if ((!l->disced) && (!l->outbound))
10015 {
10016 if ((l->name[0] == '0') || l->isremote)
10017 l->disctime = 1;
10018 else
10019 l->disctime = DISC_TIME;
10020 rpt_mutex_lock(&myrpt->lock);
10021 ast_hangup(l->chan);
10022 l->chan = 0;
10023 break;
10024 }
10025
10026 if (l->retrytimer)
10027 {
10028 ast_hangup(l->chan);
10029 l->chan = 0;
10030 rpt_mutex_lock(&myrpt->lock);
10031 break;
10032 }
10033 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
10034 {
10035 rpt_mutex_lock(&myrpt->lock);
10036 if (l->chan) ast_hangup(l->chan);
10037 l->chan = 0;
10038 l->hasconnected = 1;
10039 l->retrytimer = RETRY_TIMER_MS;
10040 l->elaptime = 0;
10041 l->connecttime = 0;
10042 l->thisconnected = 0;
10043 break;
10044 }
10045 rpt_mutex_lock(&myrpt->lock);
10046
10047 remque((struct qelem *) l);
10048 if (!strcmp(myrpt->cmdnode,l->name))
10049 myrpt->cmdnode[0] = 0;
10050 __kickshort(myrpt);
10051 rpt_mutex_unlock(&myrpt->lock);
10052 if (!l->hasconnected)
10053 rpt_telemetry(myrpt,CONNFAIL,l);
10054 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
10055 if (myrpt->p.archivedir)
10056 {
10057 char str[100];
10058
10059 if (!l->hasconnected)
10060 sprintf(str,"LINKFAIL,%s",l->name);
10061 else
10062 sprintf(str,"LINKDISC,%s",l->name);
10063 donodelog(myrpt,str);
10064 }
10065 if (l->lastf1) ast_frfree(l->lastf1);
10066 l->lastf1 = NULL;
10067 if (l->lastf2) ast_frfree(l->lastf2);
10068 l->lastf2 = NULL;
10069
10070 ast_hangup(l->chan);
10071 ast_hangup(l->pchan);
10072 free(l);
10073 rpt_mutex_lock(&myrpt->lock);
10074 break;
10075 }
10076 if (f->frametype == AST_FRAME_VOICE)
10077 {
10078 int ismuted;
10079
10080 if (l->phonemode)
10081 {
10082 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
10083 {
10084 ismuted = 0;
10085 }
10086
10087 ismuted |= (!l->lastrx);
10088 if (l->dtmfed && l->phonemode) ismuted = 1;
10089 l->dtmfed = 0;
10090 if (ismuted)
10091 {
10092 memset(f->data,0,f->datalen);
10093 if (l->lastf1)
10094 memset(l->lastf1->data,0,l->lastf1->datalen);
10095 if (l->lastf2)
10096 memset(l->lastf2->data,0,l->lastf2->datalen);
10097 }
10098 if (f) f2 = ast_frdup(f);
10099 else f2 = NULL;
10100 f1 = l->lastf2;
10101 l->lastf2 = l->lastf1;
10102 l->lastf1 = f2;
10103 if (ismuted)
10104 {
10105 if (l->lastf1)
10106 memset(l->lastf1->data,0,l->lastf1->datalen);
10107 if (l->lastf2)
10108 memset(l->lastf2->data,0,l->lastf2->datalen);
10109 }
10110 if (f1)
10111 {
10112 ast_write(l->pchan,f1);
10113 ast_frfree(f1);
10114 }
10115 }
10116 else
10117 {
10118 if (!l->lastrx)
10119 memset(f->data,0,f->datalen);
10120 ast_write(l->pchan,f);
10121 }
10122 }
10123 #ifndef OLD_ASTERISK
10124 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
10125 {
10126 if (l->lastf1)
10127 memset(l->lastf1->data,0,l->lastf1->datalen);
10128 if (l->lastf2)
10129 memset(l->lastf2->data,0,l->lastf2->datalen);
10130 l->dtmfed = 1;
10131 }
10132 #endif
10133
10134 if (f->frametype == AST_FRAME_TEXT)
10135 {
10136 handle_link_data(myrpt,l,f->data);
10137 }
10138 if (f->frametype == AST_FRAME_DTMF)
10139 {
10140 if (l->lastf1)
10141 memset(l->lastf1->data,0,l->lastf1->datalen);
10142 if (l->lastf2)
10143 memset(l->lastf2->data,0,l->lastf2->datalen);
10144 l->dtmfed = 1;
10145 handle_link_phone_dtmf(myrpt,l,f->subclass);
10146 }
10147 if (f->frametype == AST_FRAME_CONTROL)
10148 {
10149 if (f->subclass == AST_CONTROL_ANSWER)
10150 {
10151 char lconnected = l->connected;
10152
10153 __kickshort(myrpt);
10154 l->connected = 1;
10155 l->hasconnected = 1;
10156 l->thisconnected = 1;
10157 l->elaptime = -1;
10158 if (!l->isremote) l->retries = 0;
10159 if (!lconnected)
10160 {
10161 rpt_telemetry(myrpt,CONNECTED,l);
10162 if (myrpt->p.archivedir)
10163 {
10164 char str[100];
10165
10166 if (l->mode)
10167 sprintf(str,"LINKTRX,%s",l->name);
10168 else
10169 sprintf(str,"LINKMONITOR,%s",l->name);
10170 donodelog(myrpt,str);
10171 }
10172 }
10173 else
10174 l->reconnects++;
10175 }
10176
10177 if (f->subclass == AST_CONTROL_RADIO_KEY)
10178 {
10179 if (debug == 7 ) printf("@@@@ rx key\n");
10180 l->lastrx = 1;
10181 l->rerxtimer = 0;
10182 if (myrpt->p.archivedir && (!l->lastrx1))
10183 {
10184 char str[100];
10185
10186 l->lastrx1 = 1;
10187 sprintf(str,"RXKEY,%s",l->name);
10188 donodelog(myrpt,str);
10189 }
10190 }
10191
10192 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
10193 {
10194 if (debug == 7) printf("@@@@ rx un-key\n");
10195 l->lastrx = 0;
10196 l->rerxtimer = 0;
10197 if(myrpt->p.duplex)
10198 rpt_telemetry(myrpt,LINKUNKEY,l);
10199 if (myrpt->p.archivedir && (l->lastrx1))
10200 {
10201 char str[100];
10202
10203 l->lastrx1 = 0;
10204 sprintf(str,"RXUNKEY,%s",l->name);
10205 donodelog(myrpt,str);
10206 }
10207 }
10208 if (f->subclass == AST_CONTROL_HANGUP)
10209 {
10210 ast_frfree(f);
10211 rpt_mutex_lock(&myrpt->lock);
10212 __kickshort(myrpt);
10213 rpt_mutex_unlock(&myrpt->lock);
10214 if ((!l->outbound) && (!l->disced))
10215 {
10216 if ((l->name[0] == '0') || l->isremote)
10217 l->disctime = 1;
10218 else
10219 l->disctime = DISC_TIME;
10220 rpt_mutex_lock(&myrpt->lock);
10221 ast_hangup(l->chan);
10222 l->chan = 0;
10223 break;
10224 }
10225 if (l->retrytimer)
10226 {
10227 if (l->chan) ast_hangup(l->chan);
10228 l->chan = 0;
10229 rpt_mutex_lock(&myrpt->lock);
10230 break;
10231 }
10232 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
10233 {
10234 rpt_mutex_lock(&myrpt->lock);
10235 if (l->chan) ast_hangup(l->chan);
10236 l->chan = 0;
10237 l->hasconnected = 1;
10238 l->elaptime = 0;
10239 l->retrytimer = RETRY_TIMER_MS;
10240 l->connecttime = 0;
10241 l->thisconnected = 0;
10242 break;
10243 }
10244 rpt_mutex_lock(&myrpt->lock);
10245
10246 remque((struct qelem *) l);
10247 if (!strcmp(myrpt->cmdnode,l->name))
10248 myrpt->cmdnode[0] = 0;
10249 __kickshort(myrpt);
10250 rpt_mutex_unlock(&myrpt->lock);
10251 if (!l->hasconnected)
10252 rpt_telemetry(myrpt,CONNFAIL,l);
10253 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
10254 if (myrpt->p.archivedir)
10255 {
10256 char str[100];
10257
10258 if (!l->hasconnected)
10259 sprintf(str,"LINKFAIL,%s",l->name);
10260 else
10261 sprintf(str,"LINKDISC,%s",l->name);
10262 donodelog(myrpt,str);
10263 }
10264 if (l->lastf1) ast_frfree(l->lastf1);
10265 l->lastf1 = NULL;
10266 if (l->lastf2) ast_frfree(l->lastf2);
10267 l->lastf2 = NULL;
10268
10269 ast_hangup(l->chan);
10270 ast_hangup(l->pchan);
10271 free(l);
10272 rpt_mutex_lock(&myrpt->lock);
10273 break;
10274 }
10275 }
10276 ast_frfree(f);
10277 rpt_mutex_lock(&myrpt->lock);
10278 break;
10279 }
10280 if (who == l->pchan)
10281 {
10282 rpt_mutex_unlock(&myrpt->lock);
10283 f = ast_read(l->pchan);
10284 if (!f)
10285 {
10286 if (debug) printf("@@@@ rpt:Hung Up\n");
10287 toexit = 1;
10288 rpt_mutex_lock(&myrpt->lock);
10289 break;
10290 }
10291 if (f->frametype == AST_FRAME_VOICE)
10292 {
10293 if (l->chan) ast_write(l->chan,f);
10294 }
10295 if (f->frametype == AST_FRAME_CONTROL)
10296 {
10297 if (f->subclass == AST_CONTROL_HANGUP)
10298 {
10299 if (debug) printf("@@@@ rpt:Hung Up\n");
10300 ast_frfree(f);
10301 toexit = 1;
10302 rpt_mutex_lock(&myrpt->lock);
10303 break;
10304 }
10305 }
10306 ast_frfree(f);
10307 rpt_mutex_lock(&myrpt->lock);
10308 break;
10309 }
10310 l = l->next;
10311 }
10312 rpt_mutex_unlock(&myrpt->lock);
10313 if (toexit) break;
10314 if (who == myrpt->monchannel)
10315 {
10316 f = ast_read(myrpt->monchannel);
10317 if (!f)
10318 {
10319 if (debug) printf("@@@@ rpt:Hung Up\n");
10320 break;
10321 }
10322 if (f->frametype == AST_FRAME_VOICE)
10323 {
10324 if (myrpt->monstream)
10325 ast_writestream(myrpt->monstream,f);
10326 }
10327 if (f->frametype == AST_FRAME_CONTROL)
10328 {
10329 if (f->subclass == AST_CONTROL_HANGUP)
10330 {
10331 if (debug) printf("@@@@ rpt:Hung Up\n");
10332 ast_frfree(f);
10333 break;
10334 }
10335 }
10336 ast_frfree(f);
10337 continue;
10338 }
10339 if (who == myrpt->txpchannel)
10340 {
10341 f = ast_read(myrpt->txpchannel);
10342 if (!f)
10343 {
10344 if (debug) printf("@@@@ rpt:Hung Up\n");
10345 break;
10346 }
10347 if (f->frametype == AST_FRAME_CONTROL)
10348 {
10349 if (f->subclass == AST_CONTROL_HANGUP)
10350 {
10351 if (debug) printf("@@@@ rpt:Hung Up\n");
10352 ast_frfree(f);
10353 break;
10354 }
10355 }
10356 ast_frfree(f);
10357 continue;
10358 }
10359 }
10360 usleep(100000);
10361 ast_hangup(myrpt->pchannel);
10362 ast_hangup(myrpt->monchannel);
10363 ast_hangup(myrpt->txpchannel);
10364 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
10365 if (myrpt->zaptxchannel != myrpt->txchannel) ast_hangup(myrpt->zaptxchannel);
10366 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
10367 myrpt->lastf1 = NULL;
10368 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
10369 myrpt->lastf2 = NULL;
10370 ast_hangup(myrpt->rxchannel);
10371 rpt_mutex_lock(&myrpt->lock);
10372 l = myrpt->links.next;
10373 while(l != &myrpt->links)
10374 {
10375 struct rpt_link *ll = l;
10376
10377 remque((struct qelem *) l);
10378
10379 if (l->chan) ast_hangup(l->chan);
10380 ast_hangup(l->pchan);
10381 l = l->next;
10382 free(ll);
10383 }
10384 rpt_mutex_unlock(&myrpt->lock);
10385 if (debug) printf("@@@@ rpt:Hung up channel\n");
10386 myrpt->rpt_thread = AST_PTHREADT_STOP;
10387 pthread_exit(NULL);
10388 return NULL;
10389 }
10390
10391
10392 static void *rpt_master(void *ignore)
10393 {
10394 int i,n;
10395 pthread_attr_t attr;
10396 struct ast_config *cfg;
10397 char *this,*val;
10398
10399
10400 nodelog.next = nodelog.prev = &nodelog;
10401
10402 this = NULL;
10403 n = 0;
10404
10405 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
10406 usleep(250000);
10407 rpt_vars[n].cfg = ast_config_load("rpt.conf");
10408 cfg = rpt_vars[n].cfg;
10409 if (!cfg) {
10410 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
10411 pthread_exit(NULL);
10412 }
10413 while((this = ast_category_browse(cfg,this)) != NULL)
10414 {
10415 for(i = 0 ; i < strlen(this) ; i++){
10416 if((this[i] < '0') || (this[i] > '9'))
10417 break;
10418 }
10419 if(i != strlen(this)) continue;
10420 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
10421 rpt_vars[n].name = strdup(this);
10422 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
10423 if (val) rpt_vars[n].rxchanname = strdup(val);
10424 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
10425 if (val) rpt_vars[n].txchanname = strdup(val);
10426 val = (char *) ast_variable_retrieve(cfg,this,"remote");
10427 if (val) rpt_vars[n].remote = strdup(val);
10428 ast_mutex_init(&rpt_vars[n].lock);
10429 ast_mutex_init(&rpt_vars[n].remlock);
10430 rpt_vars[n].tele.next = &rpt_vars[n].tele;
10431 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
10432 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
10433 rpt_vars[n].tailmessagen = 0;
10434 #ifdef _MDC_DECODE_H_
10435 rpt_vars[n].mdc = mdc_decoder_new(8000);
10436 #endif
10437 n++;
10438 }
10439 nrpts = n;
10440 ast_config_destroy(cfg);
10441
10442
10443 for(i = 0; i < n; i++)
10444 {
10445 load_rpt_vars(i,1);
10446
10447
10448 if (rpt_vars[i].remote)
10449 {
10450 if(retreive_memory(&rpt_vars[i],"init")){
10451 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
10452 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
10453
10454 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
10455 rpt_vars[i].remmode = REM_MODE_FM;
10456 rpt_vars[i].offset = REM_SIMPLEX;
10457 rpt_vars[i].powerlevel = REM_MEDPWR;
10458 }
10459 continue;
10460 }
10461 if (!rpt_vars[i].p.ident)
10462 {
10463 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
10464 ast_config_destroy(cfg);
10465 pthread_exit(NULL);
10466 }
10467 pthread_attr_init(&attr);
10468 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10469 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10470 }
10471 usleep(500000);
10472 time(&starttime);
10473 for(;;)
10474 {
10475
10476 for(i = 0; i < n; i++)
10477 {
10478 int rv;
10479 if (rpt_vars[i].remote) continue;
10480 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
10481 rv = -1;
10482 else
10483 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
10484 if (rv)
10485 {
10486 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
10487 {
10488 if(rpt_vars[i].threadrestarts >= 5)
10489 {
10490 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
10491 exit(1);
10492 }
10493 else
10494 {
10495 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
10496 rpt_vars[i].threadrestarts++;
10497 }
10498 }
10499 else
10500 rpt_vars[i].threadrestarts = 0;
10501
10502 rpt_vars[i].lastthreadrestarttime = time(NULL);
10503 pthread_attr_init(&attr);
10504 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10505 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10506 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
10507 }
10508
10509 }
10510 for(;;)
10511 {
10512 struct nodelog *nodep;
10513 char *space,datestr[100],fname[300];
10514 int fd;
10515
10516 ast_mutex_lock(&nodeloglock);
10517 nodep = nodelog.next;
10518 if(nodep == &nodelog)
10519 {
10520 ast_mutex_unlock(&nodeloglock);
10521 break;
10522 }
10523 remque((struct qelem *)nodep);
10524 ast_mutex_unlock(&nodeloglock);
10525 space = strchr(nodep->str,' ');
10526 if (!space)
10527 {
10528 free(nodep);
10529 continue;
10530 }
10531 *space = 0;
10532 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
10533 localtime(&nodep->timestamp));
10534 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
10535 nodep->str,datestr);
10536 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
10537 if (fd == -1)
10538 {
10539 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
10540 free(nodep);
10541 continue;
10542 }
10543 if (write(fd,space + 1,strlen(space + 1)) !=
10544 strlen(space + 1))
10545 {
10546 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
10547 free(nodep);
10548 continue;
10549 }
10550 close(fd);
10551 free(nodep);
10552 }
10553 sleep(2);
10554 }
10555 ast_config_destroy(cfg);
10556 pthread_exit(NULL);
10557 }
10558
10559 static int rpt_exec(struct ast_channel *chan, void *data)
10560 {
10561 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
10562 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
10563 int ismuted,dtmfed;
10564 #ifdef OLD_ASTERISK
10565 struct localuser *u;
10566 #endif
10567 char tmp[256], keyed = 0,keyed1 = 0;
10568 char *options,*stringp,*tele,c;
10569 struct rpt *myrpt;
10570 struct ast_frame *f,*f1,*f2;
10571 struct ast_channel *who;
10572 struct ast_channel *cs[20];
10573 struct rpt_link *l;
10574 struct dahdi_confinfo ci;
10575 struct dahdi_params par;
10576 int ms,elap,nullfd;
10577 time_t t,last_timeout_warning;
10578 struct dahdi_radio_param z;
10579 struct rpt_tele *telem;
10580
10581 nullfd = open("/dev/null",O_RDWR);
10582 if (ast_strlen_zero(data)) {
10583 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
10584 return -1;
10585 }
10586
10587 strncpy(tmp, (char *)data, sizeof(tmp)-1);
10588 time(&t);
10589
10590 if (t < starttime) t = starttime + START_DELAY;
10591 if ((!starttime) || (t < (starttime + START_DELAY)))
10592 {
10593 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
10594 ast_safe_sleep(chan,3000);
10595 return -1;
10596 }
10597 stringp=tmp;
10598 strsep(&stringp, "|");
10599 options = stringp;
10600 myrpt = NULL;
10601
10602 for(i = 0; i < nrpts; i++)
10603 {
10604
10605 if (!strcmp(tmp,rpt_vars[i].name))
10606 {
10607 myrpt = &rpt_vars[i];
10608 break;
10609 }
10610 }
10611 if (myrpt == NULL)
10612 {
10613 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
10614 return -1;
10615 }
10616
10617 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
10618 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
10619 return -1;
10620 }
10621
10622
10623 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R')))
10624 {
10625 int val;
10626
10627 phone_mode = 1;
10628 if (*options == 'D') phone_mode = 2;
10629 ast_set_callerid(chan,"0","app_rpt user","0");
10630 val = 1;
10631 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
10632 }
10633 else
10634 {
10635 #ifdef ALLOW_LOCAL_CHANNELS
10636
10637 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
10638 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
10639 return -1;
10640 }
10641 #else
10642 if (strncmp(chan->name,"IAX2",4))
10643 {
10644 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
10645 return -1;
10646 }
10647 #endif
10648 }
10649 if (options && (*options == 'R'))
10650 {
10651
10652
10653 char *return_context;
10654 int l, m, lot, timeout = 0;
10655 char tmp[256],*template;
10656 char *working, *context, *exten, *priority;
10657 char *s,*orig_s;
10658
10659
10660 rpt_mutex_lock(&myrpt->lock);
10661 m = myrpt->callmode;
10662 rpt_mutex_unlock(&myrpt->lock);
10663
10664 if ((!myrpt->p.nobusyout) && m)
10665 {
10666 if (chan->_state != AST_STATE_UP)
10667 {
10668 ast_indicate(chan,AST_CONTROL_BUSY);
10669 }
10670 while(ast_safe_sleep(chan,10000) != -1);
10671 return -1;
10672 }
10673
10674 if (chan->_state != AST_STATE_UP)
10675 {
10676 ast_answer(chan);
10677 }
10678
10679 l=strlen(options)+2;
10680 orig_s=malloc(l);
10681 if(!orig_s) {
10682 ast_log(LOG_WARNING, "Out of memory\n");
10683 return -1;
10684 }
10685 s=orig_s;
10686 strncpy(s,options,l);
10687
10688 template=strsep(&s,"|");
10689 if(!template) {
10690 ast_log(LOG_WARNING, "An announce template must be defined\n");
10691 free(orig_s);
10692 return -1;
10693 }
10694
10695 if(s) {
10696 timeout = atoi(strsep(&s, "|"));
10697 timeout *= 1000;
10698 }
10699
10700 return_context = s;
10701
10702 if(return_context != NULL) {
10703
10704
10705 working = return_context;
10706 context = strsep(&working, "|");
10707 exten = strsep(&working, "|");
10708 if(!exten) {
10709
10710 priority = context;
10711 exten = NULL;
10712 context = NULL;
10713 } else {
10714 priority = strsep(&working, "|");
10715 if(!priority) {
10716
10717 priority = exten;
10718 exten = context;
10719 context = NULL;
10720 }
10721 }
10722 if(atoi(priority) < 0) {
10723 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
10724 free(orig_s);
10725 return -1;
10726 }
10727
10728 chan->priority = atoi(priority);
10729 #ifdef OLD_ASTERISK
10730 if(exten && strcasecmp(exten, "BYEXTENSION"))
10731 #else
10732 if(exten)
10733 #endif
10734 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
10735 if(context)
10736 strncpy(chan->context, context, sizeof(chan->context)-1);
10737 } else {
10738 chan->priority++;
10739 }
10740
10741 if(option_verbose > 2) {
10742 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
10743 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
10744 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
10745 }
10746 }
10747
10748
10749
10750
10751 ast_masq_park_call(chan, NULL, timeout, &lot);
10752
10753 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
10754
10755 snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
10756
10757 rpt_telemetry(myrpt,REV_PATCH,tmp);
10758
10759 free(orig_s);
10760
10761 return 0;
10762
10763 }
10764
10765 if (!options)
10766 {
10767 struct ast_hostent ahp;
10768 struct hostent *hp;
10769 struct in_addr ia;
10770 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1;
10771
10772
10773 if (!chan->cid.cid_num)
10774 {
10775 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10776 return -1;
10777 }
10778
10779
10780 memset(hisip,0,sizeof(hisip));
10781 #ifdef ALLOW_LOCAL_CHANNELS
10782
10783 if (strncmp(chan->name,"Local",5)==0) {
10784 strcpy(hisip,"127.0.0.1");
10785 } else {
10786 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
10787 }
10788 #else
10789 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
10790 #endif
10791
10792 if (!hisip[0])
10793 {
10794 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
10795 return -1;
10796 }
10797
10798 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10799 ast_shrink_phone_number(b1);
10800 if (!strcmp(myrpt->name,b1))
10801 {
10802 ast_log(LOG_WARNING, "Trying to link to self!!\n");
10803 return -1;
10804 }
10805
10806 if (*b1 < '1')
10807 {
10808 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
10809 return -1;
10810 }
10811
10812
10813
10814 val = node_lookup(myrpt,b1);
10815 if (!val)
10816 {
10817 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
10818 return -1;
10819 }
10820 strncpy(tmp,val,sizeof(tmp) - 1);
10821 s = tmp;
10822 s1 = strsep(&s,",");
10823 s2 = strsep(&s,",");
10824 if (!s2)
10825 {
10826 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
10827 return -1;
10828 }
10829 if (strcmp(s2,"NONE")) {
10830 hp = ast_gethostbyname(s2, &ahp);
10831 if (!hp)
10832 {
10833 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
10834 return -1;
10835 }
10836 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10837 #ifdef OLD_ASTERISK
10838 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10839 #else
10840 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10841 #endif
10842 if (strcmp(hisip,nodeip))
10843 {
10844 char *s3 = strchr(s1,'@');
10845 if (s3) s1 = s3 + 1;
10846 s3 = strchr(s1,'/');
10847 if (s3) *s3 = 0;
10848 hp = ast_gethostbyname(s1, &ahp);
10849 if (!hp)
10850 {
10851 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
10852 return -1;
10853 }
10854 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10855 #ifdef OLD_ASTERISK
10856 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10857 #else
10858 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10859 #endif
10860 if (strcmp(hisip,nodeip))
10861 {
10862 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
10863 return -1;
10864 }
10865 }
10866 }
10867 }
10868
10869
10870 if (!myrpt->remote)
10871 {
10872
10873 char *b,*b1;
10874 int reconnects = 0;
10875
10876
10877 if (!chan->cid.cid_num)
10878 {
10879 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10880 return -1;
10881 }
10882
10883 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10884 ast_shrink_phone_number(b1);
10885 if (!strcmp(myrpt->name,b1))
10886 {
10887 ast_log(LOG_WARNING, "Trying to link to self!!\n");
10888 return -1;
10889 }
10890 rpt_mutex_lock(&myrpt->lock);
10891 l = myrpt->links.next;
10892
10893 while(l != &myrpt->links)
10894 {
10895 if (l->name[0] == '0')
10896 {
10897 l = l->next;
10898 continue;
10899 }
10900
10901 if (!strcmp(l->name,b1)) break;
10902 l = l->next;
10903 }
10904
10905 if (l != &myrpt->links)
10906 {
10907 l->killme = 1;
10908 l->retries = l->max_retries + 1;
10909 l->disced = 2;
10910 reconnects = l->reconnects;
10911 reconnects++;
10912 rpt_mutex_unlock(&myrpt->lock);
10913 usleep(500000);
10914 } else
10915 rpt_mutex_unlock(&myrpt->lock);
10916
10917 l = malloc(sizeof(struct rpt_link));
10918 if (!l)
10919 {
10920 ast_log(LOG_WARNING, "Unable to malloc\n");
10921 pthread_exit(NULL);
10922 }
10923
10924 memset((char *)l,0,sizeof(struct rpt_link));
10925 l->mode = 1;
10926 strncpy(l->name,b1,MAXNODESTR - 1);
10927 l->isremote = 0;
10928 l->chan = chan;
10929 l->connected = 1;
10930 l->thisconnected = 1;
10931 l->hasconnected = 1;
10932 l->reconnects = reconnects;
10933 l->phonemode = phone_mode;
10934 l->lastf1 = NULL;
10935 l->lastf2 = NULL;
10936 l->dtmfed = 0;
10937 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
10938 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
10939
10940 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
10941 if (!l->pchan)
10942 {
10943 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10944 pthread_exit(NULL);
10945 }
10946 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
10947 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
10948 #ifdef AST_CDR_FLAG_POST_DISABLED
10949 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
10950 #endif
10951
10952 ci.chan = 0;
10953 ci.confno = myrpt->conf;
10954 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
10955
10956 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
10957 {
10958 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10959 pthread_exit(NULL);
10960 }
10961 rpt_mutex_lock(&myrpt->lock);
10962 if (phone_mode > 1) l->lastrx = 1;
10963 l->max_retries = MAX_RETRIES;
10964
10965 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10966 __kickshort(myrpt);
10967 rpt_mutex_unlock(&myrpt->lock);
10968 if (chan->_state != AST_STATE_UP) {
10969 ast_answer(chan);
10970 }
10971 if (myrpt->p.archivedir)
10972 {
10973 char str[100];
10974
10975 if (l->phonemode)
10976 sprintf(str,"LINK(P),%s",l->name);
10977 else
10978 sprintf(str,"LINK,%s",l->name);
10979 donodelog(myrpt,str);
10980 }
10981 return AST_PBX_KEEPALIVE;
10982 }
10983
10984 rpt_mutex_lock(&myrpt->lock);
10985
10986 if (myrpt->remoteon)
10987 {
10988 rpt_mutex_unlock(&myrpt->lock);
10989 usleep(500000);
10990 if (myrpt->remoteon)
10991 {
10992 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
10993 return -1;
10994 }
10995 rpt_mutex_lock(&myrpt->lock);
10996 }
10997 #ifdef HAVE_IOPERM
10998 if ((!strcmp(myrpt->remote, remote_rig_rbi)) &&
10999 (ioperm(myrpt->p.iobase,1,1) == -1))
11000 {
11001 rpt_mutex_unlock(&myrpt->lock);
11002 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
11003 return -1;
11004 }
11005 #endif
11006 myrpt->remoteon = 1;
11007 #ifdef OLD_ASTERISK
11008 LOCAL_USER_ADD(u);
11009 #endif
11010 rpt_mutex_unlock(&myrpt->lock);
11011
11012 for(i = 0; i < nrpts; i++)
11013 {
11014 if (&rpt_vars[i] == myrpt)
11015 {
11016 load_rpt_vars(i,0);
11017 break;
11018 }
11019 }
11020 rpt_mutex_lock(&myrpt->lock);
11021 tele = strchr(myrpt->rxchanname,'/');
11022 if (!tele)
11023 {
11024 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
11025 rpt_mutex_unlock(&myrpt->lock);
11026 pthread_exit(NULL);
11027 }
11028 *tele++ = 0;
11029 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
11030 myrpt->zaprxchannel = NULL;
11031 if (!strcasecmp(myrpt->rxchanname,"Zap"))
11032 myrpt->zaprxchannel = myrpt->rxchannel;
11033 if (myrpt->rxchannel)
11034 {
11035 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
11036 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
11037 #ifdef AST_CDR_FLAG_POST_DISABLED
11038 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11039 #endif
11040 myrpt->rxchannel->whentohangup = 0;
11041 myrpt->rxchannel->appl = "Apprpt";
11042 myrpt->rxchannel->data = "(Link Rx)";
11043 if (option_verbose > 2)
11044 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
11045 myrpt->rxchanname,tele,myrpt->rxchannel->name);
11046 rpt_mutex_unlock(&myrpt->lock);
11047 ast_call(myrpt->rxchannel,tele,999);
11048 rpt_mutex_lock(&myrpt->lock);
11049 }
11050 else
11051 {
11052 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
11053 rpt_mutex_unlock(&myrpt->lock);
11054 pthread_exit(NULL);
11055 }
11056 *--tele = '/';
11057 myrpt->zaptxchannel = NULL;
11058 if (myrpt->txchanname)
11059 {
11060 tele = strchr(myrpt->txchanname,'/');
11061 if (!tele)
11062 {
11063 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
11064 rpt_mutex_unlock(&myrpt->lock);
11065 ast_hangup(myrpt->rxchannel);
11066 pthread_exit(NULL);
11067 }
11068 *tele++ = 0;
11069 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
11070 if (!strcasecmp(myrpt->txchanname,"Zap"))
11071 myrpt->zaptxchannel = myrpt->txchannel;
11072 if (myrpt->txchannel)
11073 {
11074 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
11075 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
11076 #ifdef AST_CDR_FLAG_POST_DISABLED
11077 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11078 #endif
11079 myrpt->txchannel->whentohangup = 0;
11080 myrpt->txchannel->appl = "Apprpt";
11081 myrpt->txchannel->data = "(Link Tx)";
11082 if (option_verbose > 2)
11083 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
11084 myrpt->txchanname,tele,myrpt->txchannel->name);
11085 rpt_mutex_unlock(&myrpt->lock);
11086 ast_call(myrpt->txchannel,tele,999);
11087 rpt_mutex_lock(&myrpt->lock);
11088 }
11089 else
11090 {
11091 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
11092 rpt_mutex_unlock(&myrpt->lock);
11093 ast_hangup(myrpt->rxchannel);
11094 pthread_exit(NULL);
11095 }
11096 *--tele = '/';
11097 }
11098 else
11099 {
11100 myrpt->txchannel = myrpt->rxchannel;
11101 }
11102
11103 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
11104 if (!myrpt->pchannel)
11105 {
11106 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11107 rpt_mutex_unlock(&myrpt->lock);
11108 if (myrpt->txchannel != myrpt->rxchannel)
11109 ast_hangup(myrpt->txchannel);
11110 ast_hangup(myrpt->rxchannel);
11111 pthread_exit(NULL);
11112 }
11113 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
11114 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
11115 #ifdef AST_CDR_FLAG_POST_DISABLED
11116 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11117 #endif
11118 if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
11119 if (!myrpt->zaptxchannel) myrpt->zaptxchannel = myrpt->pchannel;
11120
11121 ci.chan = 0;
11122 ci.confno = -1;
11123 ci.confmode = DAHDI_CONF_CONFANNMON ;
11124
11125 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11126 {
11127 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11128 rpt_mutex_unlock(&myrpt->lock);
11129 ast_hangup(myrpt->pchannel);
11130 if (myrpt->txchannel != myrpt->rxchannel)
11131 ast_hangup(myrpt->txchannel);
11132 ast_hangup(myrpt->rxchannel);
11133 pthread_exit(NULL);
11134 }
11135
11136 myrpt->conf = myrpt->txconf = ci.confno;
11137
11138 myrpt->iofd = -1;
11139 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt->p.ioport)) == -1))
11140 {
11141 rpt_mutex_unlock(&myrpt->lock);
11142 ast_hangup(myrpt->pchannel);
11143 if (myrpt->txchannel != myrpt->rxchannel)
11144 ast_hangup(myrpt->txchannel);
11145 ast_hangup(myrpt->rxchannel);
11146 pthread_exit(NULL);
11147 }
11148 iskenwood_pci4 = 0;
11149 memset(&z,0,sizeof(z));
11150 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->zaptxchannel))
11151 {
11152 z.radpar = DAHDI_RADPAR_REMMODE;
11153 z.data = DAHDI_RADPAR_REM_NONE;
11154 res = ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
11155
11156 if ((!res) && (!strcmp(myrpt->remote,remote_rig_kenwood)))
11157 {
11158 z.radpar = DAHDI_RADPAR_UIOMODE;
11159 z.data = 1;
11160 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11161 {
11162 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11163 return -1;
11164 }
11165 z.radpar = DAHDI_RADPAR_UIODATA;
11166 z.data = 3;
11167 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11168 {
11169 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11170 return -1;
11171 }
11172 i = DAHDI_OFFHOOK;
11173 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i) == -1)
11174 {
11175 ast_log(LOG_ERROR,"Cannot set hook\n");
11176 return -1;
11177 }
11178 iskenwood_pci4 = 1;
11179 }
11180 }
11181 if (myrpt->txchannel == myrpt->zaptxchannel)
11182 {
11183 i = DAHDI_ONHOOK;
11184 ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i);
11185
11186 if ((myrpt->iofd < 1) && (!res) &&
11187 (!strcmp(myrpt->remote,remote_rig_ft897) ||
11188 (!strcmp(myrpt->remote,remote_rig_ic706))))
11189 {
11190 z.radpar = DAHDI_RADPAR_UIOMODE;
11191 z.data = 1;
11192 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11193 {
11194 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11195 return -1;
11196 }
11197 z.radpar = DAHDI_RADPAR_UIODATA;
11198 z.data = 3;
11199 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11200 {
11201 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11202 return -1;
11203 }
11204 }
11205 }
11206 myrpt->remoterx = 0;
11207 myrpt->remotetx = 0;
11208 myrpt->retxtimer = 0;
11209 myrpt->rerxtimer = 0;
11210 myrpt->remoteon = 1;
11211 myrpt->dtmfidx = -1;
11212 myrpt->dtmfbuf[0] = 0;
11213 myrpt->dtmf_time_rem = 0;
11214 myrpt->hfscanmode = 0;
11215 myrpt->hfscanstatus = 0;
11216 if (myrpt->p.startupmacro)
11217 {
11218 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11219 }
11220 time(&myrpt->start_time);
11221 myrpt->last_activity_time = myrpt->start_time;
11222 last_timeout_warning = 0;
11223 myrpt->reload = 0;
11224 myrpt->tele.next = &myrpt->tele;
11225 myrpt->tele.prev = &myrpt->tele;
11226 rpt_mutex_unlock(&myrpt->lock);
11227 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
11228 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
11229 rem_rx = 0;
11230 remkeyed = 0;
11231
11232 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
11233 {
11234 i = 128;
11235 ioctl(myrpt->zaprxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
11236 }
11237 if (chan->_state != AST_STATE_UP) {
11238 ast_answer(chan);
11239 }
11240
11241 if (myrpt->rxchannel == myrpt->zaprxchannel)
11242 {
11243 if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
11244 {
11245 if (par.rxisoffhook)
11246 {
11247 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11248 myrpt->remoterx = 1;
11249 remkeyed = 1;
11250 }
11251 }
11252 }
11253 if (myrpt->p.archivedir)
11254 {
11255 char mycmd[100],mydate[100],*b,*b1;
11256 time_t myt;
11257 long blocksleft;
11258
11259
11260 mkdir(myrpt->p.archivedir,0600);
11261 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
11262 mkdir(mycmd,0600);
11263 time(&myt);
11264 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11265 localtime(&myt));
11266 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
11267 myrpt->p.archivedir,myrpt->name,mydate);
11268 if (myrpt->p.monminblocks)
11269 {
11270 blocksleft = diskavail(myrpt);
11271 if (myrpt->p.remotetimeout)
11272 {
11273 blocksleft -= (myrpt->p.remotetimeout *
11274 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
11275 }
11276 if (blocksleft >= myrpt->p.monminblocks)
11277 ast_cli_command(nullfd,mycmd);
11278 } else ast_cli_command(nullfd,mycmd);
11279
11280 if (!chan->cid.cid_num)
11281 {
11282 b1 = "0";
11283 } else {
11284 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11285 ast_shrink_phone_number(b1);
11286 }
11287 sprintf(mycmd,"CONNECT,%s",b1);
11288 donodelog(myrpt,mycmd);
11289 }
11290 myrpt->loginuser[0] = 0;
11291 myrpt->loginlevel[0] = 0;
11292 myrpt->authtelltimer = 0;
11293 myrpt->authtimer = 0;
11294 authtold = 0;
11295 authreq = 0;
11296 if (myrpt->p.authlevel > 1) authreq = 1;
11297 setrem(myrpt);
11298 n = 0;
11299 dtmfed = 0;
11300 cs[n++] = chan;
11301 cs[n++] = myrpt->rxchannel;
11302 cs[n++] = myrpt->pchannel;
11303 if (myrpt->rxchannel != myrpt->txchannel)
11304 cs[n++] = myrpt->txchannel;
11305
11306 for(;;)
11307 {
11308 if (ast_check_hangup(chan)) break;
11309 if (ast_check_hangup(myrpt->rxchannel)) break;
11310 notremming = 0;
11311 setting = 0;
11312 reming = 0;
11313 telem = myrpt->tele.next;
11314 while(telem != &myrpt->tele)
11315 {
11316 if (telem->mode == SETREMOTE) setting = 1;
11317 if ((telem->mode == SETREMOTE) ||
11318 (telem->mode == SCAN) ||
11319 (telem->mode == TUNE)) reming = 1;
11320 else notremming = 1;
11321 telem = telem->next;
11322 }
11323 if (myrpt->reload)
11324 {
11325 myrpt->reload = 0;
11326
11327 for(i = 0; i < nrpts; i++)
11328 {
11329 if (&rpt_vars[i] == myrpt)
11330 {
11331 load_rpt_vars(i,0);
11332 break;
11333 }
11334 }
11335 }
11336 time(&t);
11337 if (myrpt->p.remotetimeout)
11338 {
11339 time_t r;
11340
11341 r = (t - myrpt->start_time);
11342 if (r >= myrpt->p.remotetimeout)
11343 {
11344 sayfile(chan,"rpt/node");
11345 ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11346 sayfile(chan,"rpt/timeout");
11347 ast_safe_sleep(chan,1000);
11348 break;
11349 }
11350 if ((myrpt->p.remotetimeoutwarning) &&
11351 (r >= (myrpt->p.remotetimeout -
11352 myrpt->p.remotetimeoutwarning)) &&
11353 (r <= (myrpt->p.remotetimeout -
11354 myrpt->p.remotetimeoutwarningfreq)))
11355 {
11356 if (myrpt->p.remotetimeoutwarningfreq)
11357 {
11358 if ((t - last_timeout_warning) >=
11359 myrpt->p.remotetimeoutwarningfreq)
11360 {
11361 time(&last_timeout_warning);
11362 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11363 }
11364 }
11365 else
11366 {
11367 if (!last_timeout_warning)
11368 {
11369 time(&last_timeout_warning);
11370 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11371 }
11372 }
11373 }
11374 }
11375 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
11376 {
11377 time_t r;
11378
11379 r = (t - myrpt->last_activity_time);
11380 if (r >= myrpt->p.remoteinacttimeout)
11381 {
11382 sayfile(chan,"rpt/node");
11383 ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11384 sayfile(chan,"rpt/timeout");
11385 ast_safe_sleep(chan,1000);
11386 break;
11387 }
11388 if ((myrpt->p.remotetimeoutwarning) &&
11389 (r >= (myrpt->p.remoteinacttimeout -
11390 myrpt->p.remotetimeoutwarning)) &&
11391 (r <= (myrpt->p.remoteinacttimeout -
11392 myrpt->p.remotetimeoutwarningfreq)))
11393 {
11394 if (myrpt->p.remotetimeoutwarningfreq)
11395 {
11396 if ((t - last_timeout_warning) >=
11397 myrpt->p.remotetimeoutwarningfreq)
11398 {
11399 time(&last_timeout_warning);
11400 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11401 }
11402 }
11403 else
11404 {
11405 if (!last_timeout_warning)
11406 {
11407 time(&last_timeout_warning);
11408 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11409 }
11410 }
11411 }
11412 }
11413 ms = MSWAIT;
11414 who = ast_waitfor_n(cs,n,&ms);
11415 if (who == NULL) ms = 0;
11416 elap = MSWAIT - ms;
11417 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11418 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11419 if (!ms) continue;
11420
11421 if (myrpt->dtmf_local_timer)
11422 {
11423 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11424 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11425 }
11426 rpt_mutex_lock(&myrpt->lock);
11427 do_dtmf_local(myrpt,0);
11428 rpt_mutex_unlock(&myrpt->lock);
11429 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
11430 rem_totx |= keyed && (!myrpt->tunerequest);
11431 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
11432 if(!strcmp(myrpt->remote, remote_rig_ic706))
11433 rem_totx |= myrpt->tunerequest;
11434 if (keyed && (!keyed1))
11435 {
11436 keyed1 = 1;
11437 }
11438
11439 if (!keyed && (keyed1))
11440 {
11441 time_t myt;
11442
11443 keyed1 = 0;
11444 time(&myt);
11445
11446 if ((myrpt->p.authlevel) &&
11447 (!myrpt->loginlevel[0]) &&
11448 (myt > (t + 3)))
11449 {
11450 authreq = 1;
11451 authtold = 0;
11452 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
11453 }
11454 }
11455
11456
11457 if (rem_rx && (!myrpt->remoterx))
11458 {
11459 myrpt->remoterx = 1;
11460 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11461 }
11462 if ((!rem_rx) && (myrpt->remoterx))
11463 {
11464 myrpt->remoterx = 0;
11465 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11466 }
11467
11468 if (authreq && (!myrpt->loginlevel[0]))
11469 {
11470 if ((!authtold) && ((myrpt->authtelltimer += elap)
11471 >= AUTHTELLTIME))
11472 {
11473 authtold = 1;
11474 rpt_telemetry(myrpt,LOGINREQ,NULL);
11475 }
11476 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
11477 {
11478 break;
11479 }
11480 }
11481 #ifndef OLDKEY
11482 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
11483 {
11484 myrpt->retxtimer = 0;
11485 if ((myrpt->remoterx) && (!myrpt->remotetx))
11486 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11487 else
11488 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11489 }
11490
11491 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
11492 {
11493 keyed = 0;
11494 myrpt->rerxtimer = 0;
11495 }
11496 #endif
11497 if (rem_totx && (!myrpt->remotetx))
11498 {
11499
11500 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
11501 {
11502 myrpt->remotetx = 1;
11503 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
11504 {
11505 time(&myrpt->last_activity_time);
11506 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11507 {
11508 z.radpar = DAHDI_RADPAR_UIODATA;
11509 z.data = 1;
11510 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11511 {
11512 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11513 return -1;
11514 }
11515 }
11516 else
11517 {
11518 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11519 }
11520 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
11521 }
11522 }
11523 }
11524 if ((!rem_totx) && myrpt->remotetx)
11525 {
11526 myrpt->remotetx = 0;
11527 if(!myrpt->remtxfreqok){
11528 rpt_telemetry(myrpt,UNAUTHTX,NULL);
11529 }
11530 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11531 {
11532 z.radpar = DAHDI_RADPAR_UIODATA;
11533 z.data = 3;
11534 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11535 {
11536 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11537 return -1;
11538 }
11539 }
11540 else
11541 {
11542 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11543 }
11544 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
11545 }
11546 if (myrpt->hfscanmode){
11547 myrpt->scantimer -= elap;
11548 if(myrpt->scantimer <= 0){
11549 if (!reming)
11550 {
11551 myrpt->scantimer = REM_SCANTIME;
11552 rpt_telemetry(myrpt,SCAN,0);
11553 } else myrpt->scantimer = 1;
11554 }
11555 }
11556 rpt_mutex_lock(&myrpt->lock);
11557 c = myrpt->macrobuf[0];
11558 if (c && (!myrpt->macrotimer))
11559 {
11560 myrpt->macrotimer = MACROTIME;
11561 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
11562 if ((c == 'p') || (c == 'P'))
11563 myrpt->macrotimer = MACROPTIME;
11564 rpt_mutex_unlock(&myrpt->lock);
11565 if (myrpt->p.archivedir)
11566 {
11567 char str[100];
11568 sprintf(str,"DTMF(M),%c",c);
11569 donodelog(myrpt,str);
11570 }
11571 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
11572 continue;
11573 } else rpt_mutex_unlock(&myrpt->lock);
11574 if (who == chan)
11575 {
11576 f = ast_read(chan);
11577 if (!f)
11578 {
11579 if (debug) printf("@@@@ link:Hung Up\n");
11580 break;
11581 }
11582 if (f->frametype == AST_FRAME_VOICE)
11583 {
11584 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
11585 {
11586 ismuted = 0;
11587 }
11588
11589 ismuted |= (!myrpt->remotetx);
11590 if (dtmfed && phone_mode) ismuted = 1;
11591 dtmfed = 0;
11592 if (ismuted)
11593 {
11594 memset(f->data,0,f->datalen);
11595 if (myrpt->lastf1)
11596 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11597 if (myrpt->lastf2)
11598 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11599 }
11600 if (f) f2 = ast_frdup(f);
11601 else f2 = NULL;
11602 f1 = myrpt->lastf2;
11603 myrpt->lastf2 = myrpt->lastf1;
11604 myrpt->lastf1 = f2;
11605 if (ismuted)
11606 {
11607 if (myrpt->lastf1)
11608 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11609 if (myrpt->lastf2)
11610 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11611 }
11612 if (f1)
11613 {
11614 if (phone_mode)
11615 ast_write(myrpt->txchannel,f1);
11616 else
11617 ast_write(myrpt->txchannel,f);
11618 ast_frfree(f1);
11619 }
11620 }
11621 #ifndef OLD_ASTERISK
11622 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
11623 {
11624 if (myrpt->lastf1)
11625 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11626 if (myrpt->lastf2)
11627 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11628 dtmfed = 1;
11629 }
11630 #endif
11631 if (f->frametype == AST_FRAME_DTMF)
11632 {
11633 if (myrpt->lastf1)
11634 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11635 if (myrpt->lastf2)
11636 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11637 dtmfed = 1;
11638 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
11639 {
11640 if (debug) printf("@@@@ rpt:Hung Up\n");
11641 ast_frfree(f);
11642 break;
11643 }
11644 }
11645 if (f->frametype == AST_FRAME_TEXT)
11646 {
11647 if (handle_remote_data(myrpt,f->data) == -1)
11648 {
11649 if (debug) printf("@@@@ rpt:Hung Up\n");
11650 ast_frfree(f);
11651 break;
11652 }
11653 }
11654 if (f->frametype == AST_FRAME_CONTROL)
11655 {
11656 if (f->subclass == AST_CONTROL_HANGUP)
11657 {
11658 if (debug) printf("@@@@ rpt:Hung Up\n");
11659 ast_frfree(f);
11660 break;
11661 }
11662
11663 if (f->subclass == AST_CONTROL_RADIO_KEY)
11664 {
11665 if (debug == 7) printf("@@@@ rx key\n");
11666 keyed = 1;
11667 myrpt->rerxtimer = 0;
11668 }
11669
11670 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11671 {
11672 myrpt->rerxtimer = 0;
11673 if (debug == 7) printf("@@@@ rx un-key\n");
11674 keyed = 0;
11675 }
11676 }
11677 ast_frfree(f);
11678 continue;
11679 }
11680 if (who == myrpt->rxchannel)
11681 {
11682 f = ast_read(myrpt->rxchannel);
11683 if (!f)
11684 {
11685 if (debug) printf("@@@@ link:Hung Up\n");
11686 break;
11687 }
11688 if (f->frametype == AST_FRAME_VOICE)
11689 {
11690 int myreming = 0;
11691
11692 if(!strcmp(myrpt->remote, remote_rig_kenwood))
11693 myreming = reming;
11694
11695 if (myreming || (!remkeyed) ||
11696 ((myrpt->remote) && (myrpt->remotetx)) ||
11697 ((myrpt->remmode != REM_MODE_FM) &&
11698 notremming))
11699 memset(f->data,0,f->datalen);
11700 ast_write(myrpt->pchannel,f);
11701 }
11702 else if (f->frametype == AST_FRAME_CONTROL)
11703 {
11704 if (f->subclass == AST_CONTROL_HANGUP)
11705 {
11706 if (debug) printf("@@@@ rpt:Hung Up\n");
11707 ast_frfree(f);
11708 break;
11709 }
11710
11711 if (f->subclass == AST_CONTROL_RADIO_KEY)
11712 {
11713 if (debug == 7) printf("@@@@ remote rx key\n");
11714 if (!myrpt->remotetx)
11715 {
11716 remkeyed = 1;
11717 }
11718 }
11719
11720 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11721 {
11722 if (debug == 7) printf("@@@@ remote rx un-key\n");
11723 if (!myrpt->remotetx)
11724 {
11725 remkeyed = 0;
11726 }
11727 }
11728 }
11729 ast_frfree(f);
11730 continue;
11731 }
11732 if (who == myrpt->pchannel)
11733 {
11734 f = ast_read(myrpt->pchannel);
11735 if (!f)
11736 {
11737 if (debug) printf("@@@@ link:Hung Up\n");
11738 break;
11739 }
11740 if (f->frametype == AST_FRAME_VOICE)
11741 {
11742 ast_write(chan,f);
11743 }
11744 if (f->frametype == AST_FRAME_CONTROL)
11745 {
11746 if (f->subclass == AST_CONTROL_HANGUP)
11747 {
11748 if (debug) printf("@@@@ rpt:Hung Up\n");
11749 ast_frfree(f);
11750 break;
11751 }
11752 }
11753 ast_frfree(f);
11754 continue;
11755 }
11756 if ((myrpt->rxchannel != myrpt->txchannel) &&
11757 (who == myrpt->txchannel))
11758 {
11759 f = ast_read(myrpt->txchannel);
11760 if (!f)
11761 {
11762 if (debug) printf("@@@@ link:Hung Up\n");
11763 break;
11764 }
11765 if (f->frametype == AST_FRAME_CONTROL)
11766 {
11767 if (f->subclass == AST_CONTROL_HANGUP)
11768 {
11769 if (debug) printf("@@@@ rpt:Hung Up\n");
11770 ast_frfree(f);
11771 break;
11772 }
11773 }
11774 ast_frfree(f);
11775 continue;
11776 }
11777 }
11778 if (myrpt->p.archivedir)
11779 {
11780 char mycmd[100],*b,*b1;
11781
11782
11783 if (!chan->cid.cid_num)
11784 {
11785 b1 = "0";
11786 } else {
11787 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11788 ast_shrink_phone_number(b1);
11789 }
11790 sprintf(mycmd,"DISCONNECT,%s",b1);
11791 donodelog(myrpt,mycmd);
11792 }
11793
11794 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
11795 sprintf(tmp,"mixmonitor stop %s",chan->name);
11796 ast_cli_command(nullfd,tmp);
11797 close(nullfd);
11798 rpt_mutex_lock(&myrpt->lock);
11799 myrpt->hfscanmode = 0;
11800 myrpt->hfscanstatus = 0;
11801 myrpt->remoteon = 0;
11802 rpt_mutex_unlock(&myrpt->lock);
11803 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
11804 myrpt->lastf1 = NULL;
11805 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
11806 myrpt->lastf2 = NULL;
11807 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11808 {
11809 z.radpar = DAHDI_RADPAR_UIOMODE;
11810 z.data = 3;
11811 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11812 {
11813 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11814 return -1;
11815 }
11816 z.radpar = DAHDI_RADPAR_UIODATA;
11817 z.data = 3;
11818 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11819 {
11820 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11821 return -1;
11822 }
11823 i = DAHDI_OFFHOOK;
11824 if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i) == -1)
11825 {
11826 ast_log(LOG_ERROR,"Cannot set hook\n");
11827 return -1;
11828 }
11829 }
11830 if (myrpt->iofd) close(myrpt->iofd);
11831 myrpt->iofd = -1;
11832 ast_hangup(myrpt->pchannel);
11833 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
11834 ast_hangup(myrpt->rxchannel);
11835 closerem(myrpt);
11836 #ifdef OLD_ASTERISK
11837 LOCAL_USER_REMOVE(u);
11838 #endif
11839 return res;
11840 }
11841
11842 #ifdef OLD_ASTERISK
11843 int unload_module()
11844 #else
11845 static int unload_module(void)
11846 #endif
11847 {
11848 int i;
11849
11850 #ifdef OLD_ASTERISK
11851 STANDARD_HANGUP_LOCALUSERS;
11852 #endif
11853 for(i = 0; i < nrpts; i++) {
11854 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
11855 ast_mutex_destroy(&rpt_vars[i].lock);
11856 ast_mutex_destroy(&rpt_vars[i].remlock);
11857 }
11858 i = ast_unregister_application(app);
11859
11860
11861 ast_cli_unregister(&cli_debug);
11862 ast_cli_unregister(&cli_dump);
11863 ast_cli_unregister(&cli_stats);
11864 ast_cli_unregister(&cli_lstats);
11865 ast_cli_unregister(&cli_nodes);
11866 ast_cli_unregister(&cli_reload);
11867 ast_cli_unregister(&cli_restart);
11868 ast_cli_unregister(&cli_fun);
11869
11870 return i;
11871 }
11872
11873 #ifdef OLD_ASTERISK
11874 int load_module()
11875 #else
11876 static int load_module(void)
11877 #endif
11878 {
11879 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
11880
11881
11882 ast_cli_register(&cli_debug);
11883 ast_cli_register(&cli_dump);
11884 ast_cli_register(&cli_stats);
11885 ast_cli_register(&cli_lstats);
11886 ast_cli_register(&cli_nodes);
11887 ast_cli_register(&cli_reload);
11888 ast_cli_register(&cli_restart);
11889 ast_cli_register(&cli_fun);
11890
11891 return ast_register_application(app, rpt_exec, synopsis, descrip);
11892 }
11893
11894 #ifdef OLD_ASTERISK
11895 char *description()
11896 {
11897 return tdesc;
11898 }
11899 int usecount(void)
11900 {
11901 int res;
11902 STANDARD_USECOUNT(res);
11903 return res;
11904 }
11905
11906 char *key()
11907 {
11908 return ASTERISK_GPL_KEY;
11909 }
11910 #endif
11911
11912 #ifdef OLD_ASTERISK
11913 int reload()
11914 #else
11915 static int reload(void)
11916 #endif
11917 {
11918 int n;
11919
11920 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
11921 return(0);
11922 }
11923
11924 #ifndef OLD_ASTERISK
11925
11926 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
11927 .load = load_module,
11928 .unload = unload_module,
11929 .reload = reload,
11930 );
11931
11932 #endif
11933