new echo and voicemail

lastudp
Tom Early 7 years ago
parent fd6a42cd76
commit 0023fc9f91

@ -56,7 +56,6 @@
#include "IRCDDB.h"
#include "IRCutils.h"
#include "versions.h"
#include "QnetTypeDefs.h"
#include "QnetGateway.h"
@ -676,8 +675,7 @@ void CQnetGateway::ProcessTimeouts()
if (recd[i].last_time != 0) {
time(&t_now);
if ((t_now - recd[i].last_time) > echotest_rec_timeout) {
printf("Inactivity on echotest recording mod %d, removing stream id=%04x\n",
i, recd[i].streamid);
printf("Inactivity on echotest recording mod %d, removing stream id=%04x\n", i, recd[i].streamid);
recd[i].streamid = 0;
recd[i].last_time = 0;
@ -687,7 +685,7 @@ void CQnetGateway::ProcessTimeouts()
/* START: echotest thread setup */
try {
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, recd[i].file);
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, std::ref(recd[i]));
} catch (const std::exception &e) {
printf("Failed to start echotest thread. Exception: %s\n", e.what());
// when the echotest thread runs, it deletes the file,
@ -702,8 +700,7 @@ void CQnetGateway::ProcessTimeouts()
if (vm[i].last_time != 0) {
time(&t_now);
if ((t_now - vm[i].last_time) > voicemail_rec_timeout) {
printf("Inactivity on voicemail recording mod %d, removing stream id=%04x\n",
i, vm[i].streamid);
printf("Inactivity on voicemail recording mod %d, removing stream id=%04x\n", i, vm[i].streamid);
vm[i].streamid = 0;
vm[i].last_time = 0;
@ -1334,8 +1331,6 @@ void CQnetGateway::Process()
char ip[IP_SIZE + 1];
char tempfile[FILENAME_MAX + 1];
long num_recs = 0L;
short int rec_len = 56;
SDSVT g2buf;
@ -1690,8 +1685,9 @@ void CQnetGateway::Process()
if (i>=0 && i<3) {
/* voicemail file is closed */
if ((vm[i].fd == -1) && (vm[i].file[0] != '\0')) {
snprintf(vm[i].message, 21, "VOICEMAIL ON MOD %c ", 'A'+i);
try {
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, vm[i].file);
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, std::ref(vm[i]));
} catch (const std::exception &e) {
printf("Failed to start voicemail playback. Exception: %s\n", e.what());
}
@ -1737,11 +1733,7 @@ void CQnetGateway::Process()
calcPFCS(recbuf.title, 56);
rec_len = 56;
(void)write(vm[i].fd, "DVTOOL", 6);
(void)write(vm[i].fd, &num_recs, 4);
(void)write(vm[i].fd, &rec_len, 2);
(void)write(vm[i].fd, &recbuf, rec_len);
memcpy(vm[i].header.title, recbuf.title, 56);
}
}
}
@ -1762,7 +1754,7 @@ void CQnetGateway::Process()
else {
strcpy(recd[i].file, tempfile);
printf("Recording mod %c for echotest into file:[%s]\n", rptrbuf.vpkt.hdr.r1[7], recd[i].file);
snprintf(recd[i].message, 21, "ECHO ON MODULE %c ", 'A' + i);
time(&recd[i].last_time);
recd[i].streamid = rptrbuf.vpkt.streamid;
@ -1784,11 +1776,7 @@ void CQnetGateway::Process()
calcPFCS(recbuf.title, 56);
rec_len = 56;
(void)write(recd[i].fd, "DVTOOL", 6);
(void)write(recd[i].fd, &num_recs, 4);
(void)write(recd[i].fd, &rec_len, 2);
(void)write(recd[i].fd, &recbuf, rec_len);
memcpy(recd[i].header.title, recbuf.title, 56);
}
}
}
@ -1974,22 +1962,24 @@ void CQnetGateway::Process()
else if (recd[i].fd>=0 && recd[i].streamid==rptrbuf.vpkt.streamid) { // Is the data to be recorded for echotest
time(&recd[i].last_time);
memcpy(recbuf.title, "DSVT", 4);
recbuf.config = 0x20;
recbuf.id = rptrbuf.vpkt.icm_id;
recbuf.flaga[0] = recbuf.flaga[1] = recbuf.flaga[20] = 0;
recbuf.flagb[0] = rptrbuf.vpkt.dst_rptr_id;
recbuf.flagb[1] = rptrbuf.vpkt.snd_rptr_id;
recbuf.flagb[2] = rptrbuf.vpkt.snd_term_id;
memcpy(&recbuf.streamid, &rptrbuf.vpkt.streamid, 3);
//memcpy(recbuf.title, "DSVT", 4);
//recbuf.config = 0x20;
//recbuf.id = rptrbuf.vpkt.icm_id;
//recbuf.flaga[0] = recbuf.flaga[1] = recbuf.flaga[20] = 0;
//recbuf.flagb[0] = rptrbuf.vpkt.dst_rptr_id;
//recbuf.flagb[1] = rptrbuf.vpkt.snd_rptr_id;
//recbuf.flagb[2] = rptrbuf.vpkt.snd_term_id;
//memcpy(&recbuf.streamid, &rptrbuf.vpkt.streamid, 3);
if (recvlen == 29)
memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd.voice, 12);
//memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd.voice, 12);
(void)write(recd[i].fd, rptrbuf.vpkt.vasd.voice, 9);
else
memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd1.voice, 12);
//memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd1.voice, 12);
(void)write(recd[i].fd, rptrbuf.vpkt.vasd1.voice, 9);
rec_len = 27;
(void)write(recd[i].fd, &rec_len, 2);
(void)write(recd[i].fd, &recbuf, rec_len);
//rec_len = 27;
//(void)write(recd[i].fd, &rec_len, 2);
//(void)write(recd[i].fd, &recbuf, rec_len);
if ((rptrbuf.vpkt.ctrl & 0x40) != 0) {
recd[i].streamid = 0;
@ -2000,7 +1990,7 @@ void CQnetGateway::Process()
/* we are in echotest mode, so play it back */
try {
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, recd[i].file);
std::async(std::launch::async, &CQnetGateway::PlayFileThread, this, std::ref(recd[i]));
} catch (const std::exception &e) {
printf("failed to start PlayFileThread. Exception: %s\n", e.what());
// When the echotest thread runs, it deletes the file,
@ -2013,22 +2003,24 @@ void CQnetGateway::Process()
else if ((vm[i].fd >= 0) && (vm[i].streamid==rptrbuf.vpkt.streamid)) { // Is the data to be recorded for voicemail
time(&vm[i].last_time);
memcpy(recbuf.title, "DSVT", 4);
recbuf.config = 0x20;
recbuf.flaga[0] = recbuf.flaga[1] = recbuf.flaga[2] = 0;
recbuf.id = rptrbuf.vpkt.icm_id;
recbuf.flagb[0] = rptrbuf.vpkt.dst_rptr_id;
recbuf.flagb[1] = rptrbuf.vpkt.snd_rptr_id;
recbuf.flagb[2] = rptrbuf.vpkt.snd_term_id;
memcpy(&recbuf.streamid, &rptrbuf.vpkt.streamid, 3);
//memcpy(recbuf.title, "DSVT", 4);
//recbuf.config = 0x20;
//recbuf.flaga[0] = recbuf.flaga[1] = recbuf.flaga[2] = 0;
//recbuf.id = rptrbuf.vpkt.icm_id;
//recbuf.flagb[0] = rptrbuf.vpkt.dst_rptr_id;
//recbuf.flagb[1] = rptrbuf.vpkt.snd_rptr_id;
//recbuf.flagb[2] = rptrbuf.vpkt.snd_term_id;
//memcpy(&recbuf.streamid, &rptrbuf.vpkt.streamid, 3);
if (recvlen == 29)
memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd.voice, 12);
//memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd.voice, 12);
(void)write(vm[i].fd, rptrbuf.vpkt.vasd.voice, 9);
else
memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd1.voice, 12);
//memcpy(recbuf.vasd.voice, rptrbuf.vpkt.vasd1.voice, 12);
(void)write(vm[i].fd, rptrbuf.vpkt.vasd1.voice, 9);
rec_len = 27;
(void)write(vm[i].fd, &rec_len, 2);
(void)write(vm[i].fd, &recbuf, rec_len);
//rec_len = 27;
//(void)write(vm[i].fd, &rec_len, 2);
//(void)write(vm[i].fd, &recbuf, rec_len);
if ((rptrbuf.vpkt.ctrl & 0x40) != 0) {
vm[i].streamid = 0;
@ -2295,10 +2287,11 @@ void CQnetGateway::APRSBeaconThread()
return;
}
void CQnetGateway::PlayFileThread(char *file)
void CQnetGateway::PlayFileThread(SECHO &edata)
{
SDSTR dstr;
SDSVT dsvt;
const unsigned char sdsilence[3] = { 0x16U, 0x29U, 0xF5U };
const unsigned char sdsync[3] = { 0x55U, 0x2DU, 0x16U };
struct sigaction act;
act.sa_handler = sigCatch;
@ -2317,65 +2310,33 @@ void CQnetGateway::PlayFileThread(char *file)
return;
}
printf("File to playback:[%s]\n", file);
printf("File to playback:[%s]\n", edata.file);
FILE *fp = fopen(file, "rb");
if (!fp) {
printf("Failed to open file %s\n", file);
struct stat sbuf;
if (stat(edata.file, &sbuf)) {
fprintf(stderr, "Can't stat %s\n", edata.file);
return;
}
size_t nread = fread(dstr.pkt_id, 10, 1, fp);
if (nread != 1) {
printf("Cant read first 10 bytes in %s\n", file);
fclose(fp);
return;
}
if (sbuf.st_size % 9)
printf("Warning %s file size is %ld (not a multiple of 9)!\n", edata.file, sbuf.st_size);
int ambeblocks = (int)sbuf.st_size / 9;
if (memcmp(dstr.pkt_id, "DVTOOL", 6) != 0) {
printf("DVTOOL keyword not found in %s\n", file);
fclose(fp);
FILE *fp = fopen(edata.file, "rb");
if (!fp) {
fprintf(stderr, "Failed to open file %s\n", edata.file);
return;
}
sleep(play_wait);
while (keep_running) {
unsigned short rlen;
nread = fread(&rlen, 2, 1, fp);
if (nread != 1)
break;
if ((rlen != 56) && (rlen != 27)) {
printf("Expected 56 bytes or 27 bytes, found %d\n", rlen);
break;
}
nread = fread(dsvt.title, rlen, 1, fp);
if (nread == 1) {
if (memcmp(dsvt.title, "DSVT", 4) != 0) {
printf("DVST keyword not found in %s\n", file);
break;
}
if (dsvt.id != 0x20) {
printf("Not Voice type in %s\n", file);
break;
}
if ((dsvt.config != 0x10) && (dsvt.config != 0x20)) {
printf("Not a valid record type in %s\n",file);
break;
}
int i;
if (rlen == 56) {
/* which module is this recording for? */
i = dsvt.hdr.rpt1[7] - 'A';
int i = edata.header.hdr.rpt1[7] - 'A';
if (i<0 || i>2) {
printf("found a bad module destination for this file!\n");
fclose(fp);
fprintf(stderr, "unknown module suffix '%s'\n", edata.header.hdr.rpt1);
return;
}
sleep(play_wait);
// reformat the header and send it
memcpy(dstr.pkt_id, "DSTR", 4);
dstr.counter = htons(is_icom ? G2_COUNTER_OUT++ : toRptr[i].G2_COUNTER++);
dstr.flag[0] = 0x73;
@ -2383,42 +2344,93 @@ void CQnetGateway::PlayFileThread(char *file)
dstr.flag[2] = 0x00;
dstr.remaining = 0x30;
dstr.vpkt.icm_id = 0x20;
//memcpy(&dstr.vpkt.dst_rptr_id, dsvt.flagb, 47);
dstr.vpkt.dst_rptr_id = dsvt.flagb[0];
dstr.vpkt.snd_rptr_id = dsvt.flagb[1];
dstr.vpkt.snd_term_id = dsvt.flagb[2];
dstr.vpkt.streamid = dsvt.streamid;
dstr.vpkt.ctrl = dsvt.ctrl;
memcpy(dstr.vpkt.hdr.flag, dsvt.hdr.flag, 3);
if (is_icom) {
memcpy(dstr.vpkt.hdr.r1, dsvt.hdr.rpt2, 8);
memcpy(dstr.vpkt.hdr.r2, dsvt.hdr.rpt1, 8);
dstr.vpkt.dst_rptr_id = edata.header.flagb[0];
dstr.vpkt.snd_rptr_id = edata.header.flagb[1];
dstr.vpkt.snd_term_id = edata.header.flagb[2];
dstr.vpkt.streamid = edata.header.streamid;
dstr.vpkt.ctrl = 0x80u;
memcpy(dstr.vpkt.hdr.flag, edata.header.hdr.flag, 3);
memcpy(dstr.vpkt.hdr.r1, edata.header.hdr.rpt1, 8);
memcpy(dstr.vpkt.hdr.r2, edata.header.hdr.rpt2, 8);
memcpy(dstr.vpkt.hdr.ur, "CQCQCQ ", 8);
memcpy(dstr.vpkt.hdr.my, edata.header.hdr.mycall, 8);
memcpy(dstr.vpkt.hdr.nm, edata.header.hdr.sfx, 4);
calcPFCS(dstr.pkt_id, 58);
sendto(srv_sock, dstr.pkt_id, 58, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in));
dstr.remaining = 0x13U;
for (i=0; i<ambeblocks; i++) {
int nread = fread(dstr.vpkt.vasd.voice, 9, 1, fp);
if (nread == 1) {
dstr.counter = htons(is_icom ? G2_COUNTER_OUT++ : toRptr[i].G2_COUNTER++);
dstr.vpkt.ctrl = (unsigned char)(i % 21);
if (0x0U == dstr.vpkt.ctrl) {
memcpy(dstr.vpkt.vasd.text, sdsync, 3);
} else {
memcpy(dstr.vpkt.hdr.r1, dsvt.hdr.rpt1, 8);
memcpy(dstr.vpkt.hdr.r2, dsvt.hdr.rpt2, 8);
switch (i) {
case 1:
dstr.vpkt.vasd.text[0] = '@' ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[0] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[1] ^ 0x93;
break;
case 2:
dstr.vpkt.vasd.text[0] = edata.message[2] ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[3] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[4] ^ 0x93;
break;
case 3:
dstr.vpkt.vasd.text[0] = 'A' ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[5] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[6] ^ 0x93;
break;
case 4:
dstr.vpkt.vasd.text[0] = edata.message[7] ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[8] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[9] ^ 0x93;
break;
case 5:
dstr.vpkt.vasd.text[0] = 'B' ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[10] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[11] ^ 0x93;
break;
case 6:
dstr.vpkt.vasd.text[0] = edata.message[12] ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[13] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[14] ^ 0x93;
break;
case 7:
dstr.vpkt.vasd.text[0] = 'C' ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[15] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[16] ^ 0x93;
break;
case 8:
dstr.vpkt.vasd.text[0] = edata.message[17] ^ 0x70;
dstr.vpkt.vasd.text[1] = edata.message[18] ^ 0x4f;
dstr.vpkt.vasd.text[2] = edata.message[19] ^ 0x93;
break;
default:
memcpy(dstr.vpkt.vasd.text, sdsilence, 3);
break;
}
memcpy(dstr.vpkt.hdr.ur, dsvt.hdr.urcall, 8);
memcpy(dstr.vpkt.hdr.my, dsvt.hdr.mycall, 8);
memcpy(dstr.vpkt.hdr.nm, dsvt.hdr.sfx, 4);
memcpy(dstr.vpkt.hdr.pfcs, dsvt.hdr.pfcs, 2);
/* We did not change anything */
// calcPFCS(rptr_buf, 58);
} else {
dstr.counter = htons(is_icom ? G2_COUNTER_OUT++ : toRptr[i].G2_COUNTER++);
dstr.remaining = 0x13;
memcpy(&dstr.vpkt.dst_rptr_id, dsvt.flagb, 18);
}
if (i+1 == ambeblocks)
dstr.vpkt.ctrl |= 0x40U;
sendto(srv_sock, dstr.pkt_id, rlen+2, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in));
sendto(srv_sock, dstr.pkt_id, 29, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in));
std::this_thread::sleep_for(std::chrono::milliseconds(play_delay));
}
}
fclose(fp);
if (!strstr(file, "voicemail.dat"))
unlink(file);
printf("Finished playing\n");
// if it's an echo file, delete it!
if (strstr(edata.file, "echotest.dat")) {
unlink(edata.file);
edata.file[0] = edata.message[0] = '\0';
}
return;
}
@ -2739,8 +2751,7 @@ void CQnetGateway::gps_send(short int rptr_idx)
return;
}
if (memcmp(band_txt[rptr_idx].gpid, band_txt[rptr_idx].lh_mycall, CALL_SIZE) != 0) {
printf("MYCALL [%s] does not match first 8 characters of GPS ID [%.8s]\n",
band_txt[rptr_idx].lh_mycall, band_txt[rptr_idx].gpid);
printf("MYCALL [%s] does not match first 8 characters of GPS ID [%.8s]\n", band_txt[rptr_idx].lh_mycall, band_txt[rptr_idx].gpid);
band_txt[rptr_idx].gprmc[0] = '\0';
band_txt[rptr_idx].gpid[0] = '\0';
return;

@ -17,6 +17,7 @@
*/
#include <libconfig.h++>
#include "QnetTypeDefs.h"
#include "aprs.h"
@ -31,6 +32,8 @@ typedef struct echo_tag {
time_t last_time;
unsigned short streamid;
int fd;
char message[24];
SDSVT header;
char file[FILENAME_MAX + 1];
} SECHO;
@ -154,7 +157,7 @@ private:
void GetIRCDataThread();
int get_yrcall_rptr_from_cache(char *call, char *arearp_cs, char *zonerp_cs, char *mod, char *ip, char RoU);
bool get_yrcall_rptr(char *call, char *arearp_cs, char *zonerp_cs, char *mod, char *ip, char RoU);
void PlayFileThread(char *file);
void PlayFileThread(SECHO &edata);
void compute_aprs_hash();
void APRSBeaconThread();
void ProcessTimeouts();

Loading…
Cancel
Save

Powered by TurnKey Linux.