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