reworked audio_notify and AudioNotifyThread

lastudp
Tom Early 7 years ago
parent 7715f5dcc6
commit c4d3aacccb

@ -28,15 +28,6 @@ using namespace libconfig;
#define CALL_SIZE 8 #define CALL_SIZE 8
#define MAX_DTMF_BUF 32 #define MAX_DTMF_BUF 32
typedef struct echo_tag {
time_t last_time;
unsigned short streamid;
int fd;
char message[24];
SDSVT header;
char file[FILENAME_MAX + 1];
} SECHO;
typedef struct to_remote_g2_tag { typedef struct to_remote_g2_tag {
unsigned short streamid; unsigned short streamid;
struct sockaddr_in toDst4; struct sockaddr_in toDst4;

@ -164,7 +164,6 @@ void CQnetLink::RptrAckThread(char *arg)
char from_mod = arg[0]; char from_mod = arg[0];
char RADIO_ID[21]; char RADIO_ID[21];
memcpy(RADIO_ID, arg + 1, 21); memcpy(RADIO_ID, arg + 1, 21);
time_t tnow = 0;
unsigned char silence[12] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xf5 }; unsigned char silence[12] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xf5 };
struct sigaction act; struct sigaction act;
@ -180,8 +179,6 @@ void CQnetLink::RptrAckThread(char *arg)
return; return;
} }
time(&tnow);
short int streamid_raw = Random.NewStreamID(); short int streamid_raw = Random.NewStreamID();
sleep(delay_before); sleep(delay_before);
@ -1348,7 +1345,7 @@ void CQnetLink::Process()
} else if (0==memcmp(buf + 10, "NAK", 3) && to_remote_g2[i].from_mod==buf[8]) { } else if (0==memcmp(buf + 10, "NAK", 3) && to_remote_g2[i].from_mod==buf[8]) {
printf("Link module %c to [%s] %c is rejected\n", to_remote_g2[i].from_mod, to_remote_g2[i].to_call, to_remote_g2[i].to_mod); printf("Link module %c to [%s] %c is rejected\n", to_remote_g2[i].from_mod, to_remote_g2[i].to_call, to_remote_g2[i].to_mod);
sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod); sprintf(notify_msg, "%c_failed_link.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod);
audio_notify(notify_msg); audio_notify(notify_msg);
to_remote_g2[i].to_call[0] = '\0'; to_remote_g2[i].to_call[0] = '\0';
@ -2214,7 +2211,7 @@ void CQnetLink::Process()
} else if (buf[4]==70 && buf[5]==65 && buf[6]==73 && buf[7]==76) { } else if (buf[4]==70 && buf[5]==65 && buf[6]==73 && buf[7]==76) {
printf("Login failed to call %s mod %c\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod); printf("Login failed to call %s mod %c\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod);
sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod); sprintf(notify_msg, "%c_failed_link.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod);
audio_notify(notify_msg); audio_notify(notify_msg);
to_remote_g2[i].to_call[0] = '\0'; to_remote_g2[i].to_call[0] = '\0';
@ -2226,7 +2223,7 @@ void CQnetLink::Process()
} else if (buf[4]==66 && buf[5]==85 && buf[6]==83 && buf[7]==89) { } else if (buf[4]==66 && buf[5]==85 && buf[6]==83 && buf[7]==89) {
printf("Busy or unknown status from call %s mod %c\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod); printf("Busy or unknown status from call %s mod %c\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod);
sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod); sprintf(notify_msg, "%c_failed_link.dat_FAILED_TO_LINK", to_remote_g2[i].from_mod);
audio_notify(notify_msg); audio_notify(notify_msg);
to_remote_g2[i].to_call[0] = '\0'; to_remote_g2[i].to_call[0] = '\0';
@ -2818,7 +2815,7 @@ void CQnetLink::Process()
to_remote_g2[i].from_mod, to_remote_g2[i].to_call, to_remote_g2[i].from_mod, to_remote_g2[i].to_call,
to_remote_g2[i].to_mod); to_remote_g2[i].to_mod);
sprintf(notify_msg, "%c_failed_linked.dat_UNLINKED", sprintf(notify_msg, "%c_failed_link.dat_UNLINKED",
to_remote_g2[i].from_mod); to_remote_g2[i].from_mod);
audio_notify(notify_msg); audio_notify(notify_msg);
@ -3360,8 +3357,7 @@ void CQnetLink::audio_notify(char *msg)
if (!announce) if (!announce)
return; return;
short int i = 0; short int i = -1;
static char notify_msg[3][64];
if (*msg == 'A') if (*msg == 'A')
i = 0; i = 0;
@ -3370,202 +3366,161 @@ void CQnetLink::audio_notify(char *msg)
else if (*msg == 'C') else if (*msg == 'C')
i = 2; i = 2;
strcpy(notify_msg[i], msg); if (i < 0) {
fprintf(stderr, "Improper module in msg '%s'\n", msg);
return;
}
SECHO edata;
char *p = strstr(msg, ".dat");
if (NULL == p) {
fprintf(stderr, "Improper AMBE data file in msg '%s'\n", msg);
return;
}
if ('_' == p[4]) {
std::string message(p+5);
message.resize(20, ' ');
strcpy(edata.message, message.c_str());
for (int i=0; i<20; i++) {
if ('_' == edata.message[i])
edata.message[i] = ' ';
}
} else {
strcpy(edata.message, "QnetGateway Message ");
}
p[4] = '\0';
snprintf(edata.file, FILENAME_MAX, "%s/%s", announce_dir.c_str(), msg+2);
memcpy(edata.header.title, "DSVT", 4);
edata.header.config = 0x10U;
edata.header.flaga[0] = edata.header.flaga[1] = edata.header.flaga[2] = 0x0U;
edata.header.id = 0x20;
edata.header.streamid = Random.NewStreamID();
edata.header.ctrl = 0x80U;
edata.header.hdr.flag[0] = edata.header.hdr.flag[1] = edata.header.hdr.flag[2] = 0x0U;
memcpy(edata.header.hdr.rpt1, owner.c_str(), CALL_SIZE);
edata.header.hdr.rpt1[7] = msg[0];
memcpy(edata.header.hdr.rpt2, owner.c_str(), CALL_SIZE);
edata.header.hdr.rpt2[7] = 'G';
memcpy(edata.header.hdr.urcall, "CQCQCQ ", CALL_SIZE);
memcpy(edata.header.hdr.mycall, owner.c_str(), CALL_SIZE);
memcpy(edata.header.hdr.sfx, "RPTR", 4);
calcPFCS(edata.header.title, 56);
try { try {
std::async(std::launch::async, &CQnetLink::AudioNotifyThread, this, notify_msg[i]); std::async(std::launch::async, &CQnetLink::AudioNotifyThread, this, std::ref(edata));
} catch (const std::exception &e) { } catch (const std::exception &e) {
printf ("Failed to start AudioNotifyThread(). Exception: %s\n", e.what()); printf ("Failed to start AudioNotifyThread(). Exception: %s\n", e.what());
} }
return; return;
} }
void CQnetLink::AudioNotifyThread(char *arg) void CQnetLink::AudioNotifyThread(SECHO &edata)
{ {
char notify_msg[64];
strcpy(notify_msg, (char *)arg);
unsigned short rlen = 0;
size_t nread = 0;
bool useTEXT = false;
short int TEXT_idx = 0;
char RADIO_ID[21];
char temp_file[FILENAME_MAX + 1];
FILE *fp = NULL;
char mod;
char *p = NULL;
u_int16_t streamid_raw = 0;
time_t tnow = 0;
struct sigaction act; struct sigaction act;
/* example: A_linked.dat_LINKED_TO_XRF005_A */
/* example: A_unlinked.dat */
/* example: A_failed_linked.dat */
act.sa_handler = sigCatch; act.sa_handler = sigCatch;
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART; act.sa_flags = SA_RESTART;
if (sigaction(SIGTERM, &act, 0) != 0) { if (sigaction(SIGTERM, &act, 0) != 0) {
printf("sigaction-TERM failed, error=%d\n", errno); fprintf(stderr, "sigaction-TERM failed, error=%d\n", errno);
return; return;
} }
if (sigaction(SIGINT, &act, 0) != 0) { if (sigaction(SIGINT, &act, 0) != 0) {
printf("sigaction-INT failed, error=%d\n", errno); fprintf(stderr, "sigaction-INT failed, error=%d\n", errno);
return; return;
} }
memset(RADIO_ID, ' ', 20); char mod = edata.header.hdr.rpt1[7];
RADIO_ID[20] = '\0';
mod = notify_msg[0];
if ((mod != 'A') && (mod != 'B') && (mod != 'C')) { if ((mod != 'A') && (mod != 'B') && (mod != 'C')) {
printf("Invalid module %c in %s\n", mod, notify_msg); fprintf(stderr, "Invalid module %c in %s\n", mod, edata.file);
return; return;
} }
p = strstr(notify_msg, ".dat");
if (!p) {
printf("Incorrect filename in %s\n", notify_msg);
return;
}
if (p[4] == '_') {
useTEXT = true;
memcpy(RADIO_ID, p + 5, (strlen(p + 5) > 20)?20:strlen(p + 5));
for (TEXT_idx = 0; TEXT_idx < 20; TEXT_idx++) {
RADIO_ID[TEXT_idx] = toupper(RADIO_ID[TEXT_idx]);
if (RADIO_ID[TEXT_idx] == '_')
RADIO_ID[TEXT_idx] = ' ';
}
TEXT_idx = 0;
p[4] = '\0';
} else
useTEXT = false;
sleep(delay_before); sleep(delay_before);
memset(temp_file, '\0', sizeof(temp_file)); printf("sending File:[%s], mod:[%c], RADIO_ID=[%s]\n", edata.file, mod, edata.message);
snprintf(temp_file, FILENAME_MAX, "%s/%s", announce_dir.c_str(), notify_msg + 2);
printf("sending File:[%s], mod:[%c], RADIO_ID=[%s]\n", temp_file, mod, RADIO_ID);
fp = fopen(temp_file, "rb"); struct stat sbuf;
if (!fp) { if (stat(edata.file, &sbuf)) {
printf("Failed to open file %s for reading\n", temp_file); fprintf(stderr, "can't stat %s\n", edata.file);
return; return;
} }
/* stupid DVTOOL + 4 byte num_of_records */ if (sbuf.st_size % 9)
unsigned char dstar_buf[10]; printf("Warning %s file size is %ld (not a multiple of 9)!\n", edata.file, sbuf.st_size);
nread = fread(dstar_buf, 10, 1, fp); int ambeblocks = (int)sbuf.st_size / 9;
if (nread != 1) {
printf("Cant read first 10 bytes from %s\n", temp_file);
fclose(fp); FILE *fp = fopen(edata.file, "rb");
return; if (!fp) {
} fprintf(stderr, "Failed to open file %s for reading\n", edata.file);
if (memcmp(dstar_buf, "DVTOOL", 6) != 0) {
printf("DVTOOL keyword not found in %s\n", temp_file);
fclose(fp);
return; return;
} }
time(&tnow); sendto(rptr_sock, edata.header.title, 56, 0, (struct sockaddr *)&toLocalg2, sizeof(struct sockaddr_in));
while (keep_running) { edata.header.config = 0x20U;
/* 2 byte length */
nread = fread(&rlen, 2, 1, fp);
if (nread != 1)
break;
if (rlen == 56) for (int i=0; i<ambeblocks && keep_running; i++) {
streamid_raw = Random.NewStreamID();
else if (rlen == 27)
;
else {
printf("Not 56-byte and not 27-byte in %s\n", temp_file);
break;
}
SDSVT dsvt; int nread = fread(edata.header.vasd.voice, 9, 1, fp);
nread = fread(dsvt.title, rlen, 1, fp);
if (nread == 1) { if (nread == 1) {
if (memcmp(dsvt.title, "DSVT", 4) != 0) { edata.header.ctrl = (unsigned char)(i % 21);
printf("DVST not found in %s\n", temp_file); if (0x0U == edata.header.ctrl) {
const unsigned char sdsync[3] = { 0x55U, 0x2DU, 0x16U };
memcpy(edata.header.vasd.text, sdsync, 3);
} else {
const unsigned char sdsilence[3] = { 0x16U, 0x29U, 0xF5U };
switch (i) {
case 1:
edata.header.vasd.text[0] = '@' ^ 0x70;
edata.header.vasd.text[1] = edata.message[0] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[1] ^ 0x93;
break; break;
} case 2:
edata.header.vasd.text[0] = edata.message[2] ^ 0x70;
if (dsvt.id != 0x20) { edata.header.vasd.text[1] = edata.message[3] ^ 0x4f;
printf("Not Voice type in %s\n", temp_file); edata.header.vasd.text[2] = edata.message[4] ^ 0x93;
break; break;
} case 3:
edata.header.vasd.text[0] = 'A' ^ 0x70;
if (dsvt.config!=0x10 && dsvt.config!=0x20) { edata.header.vasd.text[1] = edata.message[5] ^ 0x4f;
printf("Not a valid record type in %s\n", temp_file); edata.header.vasd.text[2] = edata.message[6] ^ 0x93;
break;
case 4:
edata.header.vasd.text[0] = edata.message[7] ^ 0x70;
edata.header.vasd.text[1] = edata.message[8] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[9] ^ 0x93;
break;
case 5:
edata.header.vasd.text[0] = 'B' ^ 0x70;
edata.header.vasd.text[1] = edata.message[10] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[11] ^ 0x93;
break;
case 6:
edata.header.vasd.text[0] = edata.message[12] ^ 0x70;
edata.header.vasd.text[1] = edata.message[13] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[14] ^ 0x93;
break;
case 7:
edata.header.vasd.text[0] = 'C' ^ 0x70;
edata.header.vasd.text[1] = edata.message[15] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[16] ^ 0x93;
break;
case 8:
edata.header.vasd.text[0] = edata.message[17] ^ 0x70;
edata.header.vasd.text[1] = edata.message[18] ^ 0x4f;
edata.header.vasd.text[2] = edata.message[19] ^ 0x93;
break;
default:
memcpy(edata.header.vasd.text, sdsilence, 3);
break; break;
}
dsvt.streamid = htons(streamid_raw);
if (rlen == 56) {
dsvt.hdr.flag[0] = 0x0;
memcpy(dsvt.hdr.rpt1, owner.c_str(), CALL_SIZE);
dsvt.hdr.rpt1[7] = mod;
memcpy(dsvt.hdr.rpt2, owner.c_str(), CALL_SIZE);
dsvt.hdr.rpt2[7] = 'G';
memcpy(dsvt.hdr.urcall, "CQCQCQ ", 8);
memcpy(dsvt.hdr.mycall, owner.c_str(), CALL_SIZE);
dsvt.hdr.mycall[6] = dsvt.hdr.mycall[7] = ' ';
memcpy(dsvt.hdr.sfx, "RPTR", 4);
calcPFCS(dsvt.title, 56);
} else {
if (useTEXT) {
if ((dsvt.vasd.text[0] != 0x55) || (dsvt.vasd.text[1] != 0x2d) || (dsvt.vasd.text[2] != 0x16)) {
if (TEXT_idx == 0) {
dsvt.vasd.text[0] = '@' ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 2) {
dsvt.vasd.text[0] = RADIO_ID[TEXT_idx++] ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 5) {
dsvt.vasd.text[0] = 'A' ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 7) {
dsvt.vasd.text[0] = RADIO_ID[TEXT_idx++] ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 10) {
dsvt.vasd.text[0] = 'B' ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 12) {
dsvt.vasd.text[0] = RADIO_ID[TEXT_idx++] ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 15) {
dsvt.vasd.text[0] = 'C' ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else if (TEXT_idx == 17) {
dsvt.vasd.text[0] = RADIO_ID[TEXT_idx++] ^ 0x70;
dsvt.vasd.text[1] = RADIO_ID[TEXT_idx++] ^ 0x4f;
dsvt.vasd.text[2] = RADIO_ID[TEXT_idx++] ^ 0x93;
} else {
dsvt.vasd.text[0] = 0x70;
dsvt.vasd.text[1] = 0x4f;
dsvt.vasd.text[2] = 0x93;
}
}
} }
} }
sendto(rptr_sock, dsvt.title, rlen, 0, (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); if (i+1 == ambeblocks)
edata.header.ctrl |= 0x40U;
sendto(rptr_sock, edata.header.title, 27, 0, (struct sockaddr *)&toLocalg2, sizeof(struct sockaddr_in));
} }
std::this_thread::sleep_for(std::chrono::milliseconds(delay_between)); std::this_thread::sleep_for(std::chrono::milliseconds(delay_between));
} }

@ -71,9 +71,9 @@ private:
void print_status_file(); void print_status_file();
void send_heartbeat(); void send_heartbeat();
bool resolve_rmt(char *name, int type, struct sockaddr_in *addr); bool resolve_rmt(char *name, int type, struct sockaddr_in *addr);
void audio_notify(char *notify_msg); void audio_notify(char *msg);
void rptr_ack(short i); void rptr_ack(short i);
void AudioNotifyThread(char *arg); void AudioNotifyThread(SECHO &edata);
void RptrAckThread(char *arg); void RptrAckThread(char *arg);
bool get_value(const Config &cfg, const char *path, int &value, int min, int max, int default_value); bool get_value(const Config &cfg, const char *path, int &value, int min, int max, int default_value);
bool get_value(const Config &cfg, const char *path, double &value, double min, double max, double default_value); bool get_value(const Config &cfg, const char *path, double &value, double min, double max, double default_value);

@ -123,3 +123,12 @@ typedef struct dsrp_tag { // offset size
}; };
} SDSRP; } SDSRP;
#pragma pack(pop) #pragma pack(pop)
typedef struct echo_tag {
time_t last_time;
unsigned short streamid;
int fd;
char message[24];
SDSVT header;
char file[FILENAME_MAX + 1];
} SECHO;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save

Powered by TurnKey Linux.