astyle -A1 -T -O

pull/14/head
Tom Early 5 years ago
parent ffa9687463
commit 110a70a27a

@ -90,8 +90,10 @@ std::string CCacheManager::findServerUser()
{
std::string suser;
mux.lock();
for (auto it=NameNick.begin(); it!=NameNick.end(); it++) {
if (0 == it->first.compare(0, 2, "s-")) {
for (auto it=NameNick.begin(); it!=NameNick.end(); it++)
{
if (0 == it->first.compare(0, 2, "s-"))
{
suser.assign(it->first);
break;
}
@ -109,14 +111,16 @@ void CCacheManager::updateUser(const std::string &user, const std::string &rptr,
if (! time.empty())
UserTime[user] = time;
if (rptr.empty()) {
if (rptr.empty())
{
mux.unlock();
return;
}
UserRptr[user] = rptr;
if (gate.empty() || addr.empty()) {
if (gate.empty() || addr.empty())
{
mux.unlock();
return;
}
@ -135,7 +139,8 @@ void CCacheManager::updateRptr(const std::string &rptr, const std::string &gate,
mux.lock();
RptrGate[rptr] = gate;
if (addr.empty()) {
if (addr.empty())
{
mux.unlock();
return;
}
@ -149,7 +154,8 @@ void CCacheManager::updateGate(const std::string &G, const std::string &addr)
return;
std::string gate(G);
auto p = gate.find('_');
while (gate.npos != p) {
while (gate.npos != p)
{
gate[p] = ' ';
p = gate.find('_');
}
@ -207,10 +213,12 @@ std::string CCacheManager::findRptrGate(const std::string &rptr)
if (rptr.empty())
return gate;
auto it = RptrGate.find(rptr);
if (it == RptrGate.end()) {
if (it == RptrGate.end())
{
gate.assign(rptr);
gate[7] = 'G';
} else
}
else
gate.assign(it->second);
return gate;
}

@ -22,7 +22,8 @@
#include <mutex>
#include <unordered_map>
class CCacheManager {
class CCacheManager
{
public:
CCacheManager() {}
~CCacheManager() {}

@ -48,7 +48,8 @@ int CDPlusAuthenticator::Process(CQnetDB &db, const bool reflectors, const bool
// return true if everything went okay
{
int result = client.Open(m_address, AF_UNSPEC, "20001");
if (result) {
if (result)
{
fprintf(stderr, "DPlus Authorization failed: %s\n", gai_strerror(result));
return 0;
}
@ -70,7 +71,8 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const
::memcpy(buffer+28, "W7IB2", 5);
::memcpy(buffer+40, "DHS0257", 7);
if (client.Write(buffer, 56U)) {
if (client.Write(buffer, 56U))
{
fprintf(stderr, "ERROR: could not write opening phrase\n");
client.Close();
return 0;
@ -80,21 +82,25 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const
unsigned int rval = 0;
CHostQueue hqueue;
while (ret == 2) {
while (ret == 2)
{
unsigned int len = (buffer[1U] & 0x0FU) * 256U + buffer[0U];
// Ensure that we get exactly len - 2U bytes from the TCP stream
ret = client.ReadExact(buffer + 2U, len - 2U);
if (0 > ret) {
if (0 > ret)
{
fprintf(stderr, "Problem reading line, it returned %d\n", errno);
return rval;
}
if ((buffer[1U] & 0xC0U) != 0xC0U || buffer[2U] != 0x01U) {
if ((buffer[1U] & 0xC0U) != 0xC0U || buffer[2U] != 0x01U)
{
fprintf(stderr, "Invalid packet received from 20001\n");
return rval;
}
for (unsigned int i = 8U; (i + 25U) < len; i += 26U) {
for (unsigned int i = 8U; (i + 25U) < len; i += 26U)
{
std::string address((char *)(buffer + i));
std::string name((char *)(buffer + i + 16U));
@ -106,11 +112,15 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const
bool active = (buffer[i + 25U] & 0x80U) == 0x80U;
// An empty name or IP address or an inactive gateway/reflector is not added
if (address.size()>0U && name.size()>0U && active) {
if (reflectors && 0==name.compare(0, 3, "REF")) {
if (address.size()>0U && name.size()>0U && active)
{
if (reflectors && 0==name.compare(0, 3, "REF"))
{
rval++;
hqueue.Push(CHost(name.c_str(), address.c_str(), 20001));
} else if (repeaters && name.compare(0, 3, "REF")) {
}
else if (repeaters && name.compare(0, 3, "REF"))
{
rval++;
hqueue.Push(CHost(name.c_str(), address.c_str(), 20001));
}

@ -25,7 +25,8 @@
#include "TCPReaderWriterClient.h"
#include "QnetDB.h"
class CDPlusAuthenticator {
class CDPlusAuthenticator
{
public:
CDPlusAuthenticator(const std::string &loginCallsign, const std::string &address);
~CDPlusAuthenticator();

@ -26,7 +26,8 @@
#define MASK12 0xfffff800 /* auxiliary vector for testing */
#define GENPOL 0x00000c75 /* generator polinomial, g(x) */
static const int bit_pos1[] = {
static const int bit_pos1[] =
{
0, 0, 1, 1, 2, 2,
0, 0, 1, 1, 2, 2,
0, 0, 1, 1, 2, 2,
@ -42,7 +43,8 @@ static const int bit_pos1[] = {
0, 0, 1, 1, 2, 2
};
static const int bit_pos2[] = {
static const int bit_pos2[] =
{
23, 11, 23, 11, 23, 11,
22, 10, 22, 10, 22, 10,
21, 9, 21, 9, 21, 9,
@ -66,7 +68,8 @@ CDStarDecode::CDStarDecode(void)
decoding_table[0] = 0;
decoding_table[1] = 1;
temp = 1;
for (i=2; i<= 23; i++) {
for (i=2; i<= 23; i++)
{
temp = temp << 1;
decoding_table[get_syndrome(temp)] = temp;
}
@ -75,7 +78,8 @@ CDStarDecode::CDStarDecode(void)
a[2] = 2;
temp = arr2int(a,2);
decoding_table[get_syndrome(temp)] = temp;
for (i=1; i<253; i++) {
for (i=1; i<253; i++)
{
nextcomb(23,2,a);
temp = arr2int(a,2);
decoding_table[get_syndrome(temp)] = temp;
@ -86,13 +90,15 @@ CDStarDecode::CDStarDecode(void)
a[3] = 3;
temp = arr2int(a,3);
decoding_table[get_syndrome(temp)] = temp;
for (i=1; i<1771; i++) {
for (i=1; i<1771; i++)
{
nextcomb(23,3,a);
temp = arr2int(a,3);
decoding_table[get_syndrome(temp)] = temp;
}
for (i=0; i < 4096; i++) {
for (i=0; i < 4096; i++)
{
int mask = 0x800000;
int j;
int pr;
@ -100,10 +106,12 @@ CDStarDecode::CDStarDecode(void)
prng[i] = 0;
pr = i << 4;
for (j=0; j < 24; j++) {
for (j=0; j < 24; j++)
{
pr = ((173 * pr) + 13849) & 0xFFFF;
if ((pr & 0x8000) != 0) {
if ((pr & 0x8000) != 0)
{
prng[i] |= mask;
}
@ -121,7 +129,8 @@ long CDStarDecode::arr2int(int *a, int r)
int i;
long mul, result = 0, temp;
for (i=1; i<=r; i++) {
for (i=1; i<=r; i++)
{
mul = 1;
temp = a[i]-1;
while (temp--)
@ -164,7 +173,8 @@ long CDStarDecode::get_syndrome(long pattern)
long aux = X22;
if (pattern >= X11)
while (pattern & MASK12) {
while (pattern & MASK12)
{
while (!(aux & pattern))
aux = aux >> 1;
pattern ^= (aux/X11) * GENPOL;
@ -181,22 +191,26 @@ int CDStarDecode::golay2412(int data, int *decoded)
int parity_corr = 0;
int i;
for (i = 0; i < 23; i++) {
for (i = 0; i < 23; i++)
{
int mask = 1 << i;
int bit_rcvd = block & mask;
int bit_corr = corrected_block & mask;
if (bit_corr != 0) {
if (bit_corr != 0)
{
parity_corr ++;
}
if (bit_rcvd != bit_corr) {
if (bit_rcvd != bit_corr)
{
errs ++;
}
}
if ((parity_corr & 0x01) != (data & 0x01)) {
if ((parity_corr & 0x01) != (data & 0x01))
{
errs ++;
}
@ -211,11 +225,13 @@ int CDStarDecode::Decode(const unsigned char *d, int data[3])
int i;
int errs;
for (i=0; i < 3; i++) {
for (i=0; i < 3; i++)
{
bits[i] = 0;
}
for (i=0; i < 72; i++) {
for (i=0; i < 72; i++)
{
bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0;
}

@ -20,7 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
class CDStarDecode {
class CDStarDecode
{
public:
CDStarDecode();
~CDStarDecode() {}

@ -41,8 +41,10 @@ bool CDVAPDongle::Initialize(const char *serialno, const int frequency, const in
bool ok = false;
char device[128];
do {
for (int i = 0; i < 32; i++) {
do
{
for (int i = 0; i < 32; i++)
{
sprintf(device, "/dev/ttyUSB%d", i);
if (access(device, R_OK | W_OK) != 0)
@ -52,7 +54,8 @@ bool CDVAPDongle::Initialize(const char *serialno, const int frequency, const in
if (!ok)
continue;
if (flock(serfd, LOCK_EX | LOCK_NB) != 0) {
if (flock(serfd, LOCK_EX | LOCK_NB) != 0)
{
close(serfd);
serfd = -1;
ok = false;
@ -62,7 +65,8 @@ bool CDVAPDongle::Initialize(const char *serialno, const int frequency, const in
printf("Device %s now locked for exclusive use\n", device);
ok = get_ser(device, serialno);
if (!ok) {
if (!ok)
{
close(serfd);
serfd = -1;
continue;
@ -109,10 +113,13 @@ bool CDVAPDongle::Initialize(const char *serialno, const int frequency, const in
if (!ok)
break;
} while (false);
}
while (false);
if (!ok) {
if (serfd != -1) {
if (!ok)
{
if (serfd != -1)
{
Stop();
close(serfd);
serfd = -1;
@ -132,7 +139,8 @@ REPLY_TYPE CDVAPDongle::GetReply(SDVAP_REGISTER &dr)
if (rc != 2)
return RT_ERR;
switch (dr.header) {
switch (dr.header)
{
case 0x5u:
case 0x6u:
case 0x7u:
@ -154,7 +162,8 @@ REPLY_TYPE CDVAPDongle::GetReply(SDVAP_REGISTER &dr)
}
// read the rest of the register
uint16_t len = dr.header & 0x1fff;
while (off < len) {
while (off < len)
{
uint8_t *ptr = (uint8_t *)&dr;
rc = read_from_dvp(ptr + off, len - off);
if (rc < 0)
@ -163,9 +172,11 @@ REPLY_TYPE CDVAPDongle::GetReply(SDVAP_REGISTER &dr)
off += rc;
}
// okay, now we'll parse the register and return its type
switch (dr.header) {
switch (dr.header)
{
case 0x5u:
switch (dr.param.control) {
switch (dr.param.control)
{
case 0x18u:
if (dr.param.byte)
return RT_START;
@ -184,7 +195,8 @@ REPLY_TYPE CDVAPDongle::GetReply(SDVAP_REGISTER &dr)
}
break;
case 0x6u:
switch (dr.param.control) {
switch (dr.param.control)
{
case 0x138u:
return RT_PWR;
case 0x400u:
@ -244,22 +256,28 @@ bool CDVAPDongle::syncit()
dvapreg.header = 0x2007u;
dvapreg.param.control = 0x90u;
while (memcmp(data, &dvapreg, 4) != 0) {
while (memcmp(data, &dvapreg, 4) != 0)
{
FD_ZERO(&fds);
FD_SET(serfd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 1000;
int n = select(serfd + 1, &fds, NULL, NULL, &tv);
if (n <= 0) {
if (n <= 0)
{
cnt ++;
if (cnt > 100) {
if (cnt > 100)
{
printf("syncit() uncessful...stopping\n");
return true;
}
} else {
}
else
{
unsigned char c;
n = read_from_dvp(&c, 1);
if (n > 0) {
if (n > 0)
{
data[0] = data[1];
data[1] = data[2];
data[2] = data[3];
@ -284,23 +302,28 @@ bool CDVAPDongle::get_ser(const char *dvp, const char *dvap_serial_number)
dvapreg.param.control = 0x2u;
int rc = write_to_dvp(&dvapreg, 4);
if (rc != 4) {
if (rc != 4)
{
printf("Failed to send request to get dvap serial#\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to receive dvap serial#\n");
return false;
}
} while (reply != RT_SER);
}
while (reply != RT_SER);
if (0 == strcmp(dvapreg.param.sstr, dvap_serial_number)) {
if (0 == strcmp(dvapreg.param.sstr, dvap_serial_number))
{
printf("Using %s: %s, because serial number matches your configuration file\n", dvp, dvap_serial_number);
return true;
}
@ -316,23 +339,28 @@ bool CDVAPDongle::get_name()
dvapreg.param.control = 0x1u;
int rc = write_to_dvp(&dvapreg, 4);
if (rc != 4) {
if (rc != 4)
{
printf("Failed to send request to get dvap name\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to receive dvap name\n");
return false;
}
} while (reply != RT_NAME);
}
while (reply != RT_NAME);
if (0x10u!=dvapreg.header || 0x1u!=dvapreg.param.control || strncmp(dvapreg.param.sstr, "DVAP Dongle", 11)) {
if (0x10u!=dvapreg.header || 0x1u!=dvapreg.param.control || strncmp(dvapreg.param.sstr, "DVAP Dongle", 11))
{
printf("Failed to receive dvap name, got %s\n", dvapreg.param.sstr);
return false;
}
@ -350,21 +378,25 @@ bool CDVAPDongle::get_fw()
dvapreg.param.ustr[0] = 0x1u;
int rc = write_to_dvp(&dvapreg, 5);
if (rc != 5) {
if (rc != 5)
{
printf("Failed to send request to get dvap fw\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to receive dvap fw\n");
return false;
}
} while (reply != RT_FW);
}
while (reply != RT_FW);
unsigned int ver = dvapreg.param.ustr[1] + 256 * dvapreg.param.ustr[2];
printf("dvap fw ver: %u.%u\n", ver / 100, ver % 100);
@ -381,22 +413,26 @@ bool CDVAPDongle::set_modu()
dvapreg.param.ustr[0] = 0x1u;
int rc = write_to_dvp(&dvapreg, 5);
if (rc != 5) {
if (rc != 5)
{
printf("Failed to send request to set dvap modulation\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap modulation\n");
return false;
}
} while (reply != RT_MODU);
}
while (reply != RT_MODU);
return true;
}
@ -410,22 +446,26 @@ bool CDVAPDongle::set_mode()
dvapreg.param.ustr[0] = 0x0u;
int rc = write_to_dvp(&dvapreg, 5);
if (rc != 5) {
if (rc != 5)
{
printf("Failed to send request to set dvap mode\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap mode\n");
return false;
}
} while (reply != RT_MODE);
}
while (reply != RT_MODE);
return true;
}
@ -437,32 +477,39 @@ bool CDVAPDongle::set_sql(int squelch)
dvapreg.header = 0x5u;
dvapreg.param.control = 0x80u;
if (squelch < -128) {
if (squelch < -128)
{
printf("Squelch setting of %d too small, resetting...\n", squelch);
squelch = -128;
} else if (squelch > -45) {
}
else if (squelch > -45)
{
printf("Squelch setting of %d too large, resetting...\n", squelch);
squelch = -45;
}
dvapreg.param.byte = (int8_t)squelch;
int rc = write_to_dvp(&dvapreg, 5);
if (rc != 5) {
if (rc != 5)
{
printf("Failed to send request to set dvap sql\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap sql\n");
return false;
}
} while (reply != RT_SQL);
}
while (reply != RT_SQL);
printf("DVAP squelch is %d dB\n", (int)dvapreg.param.byte);
return true;
}
@ -474,32 +521,39 @@ bool CDVAPDongle::set_pwr(int power)
dvapreg.header = 0x6u;
dvapreg.param.control = 0x138u;
if (power < -12) {
if (power < -12)
{
printf("Power setting of %d is too low, resetting...\n", power);
power = -12;
} else if (power > 10) {
}
else if (power > 10)
{
printf("Power setting of %d is too high, resetting...\n", power);
power = 10;
}
dvapreg.param.word = (int16_t)power;
int rc = write_to_dvp(&dvapreg, 6);
if (rc != 6) {
if (rc != 6)
{
printf("Failed to send request to set dvap pwr\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap pwr\n");
return false;
}
} while (reply != RT_PWR);
}
while (reply != RT_PWR);
printf("DVAP power is %d dB\n", (int)dvapreg.param.word);
return true;
}
@ -511,32 +565,39 @@ bool CDVAPDongle::set_off(int offset)
dvapreg.header = 0x6u;
dvapreg.param.control = 0x400u;
if (offset < -2000) {
if (offset < -2000)
{
printf("Offset of %d is too low, resetting...\n", offset);
offset = -2000;
} else if (offset > 2000) {
}
else if (offset > 2000)
{
printf("Offset of %d is too high, resetting...\n", offset);
offset = 2000;
}
dvapreg.param.word = (int16_t)offset;
int rc = write_to_dvp(&dvapreg, 6);
if (rc != 6) {
if (rc != 6)
{
printf("Failed to send request to set dvap offset\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap offset\n");
return false;
}
} while (reply != RT_OFF);
}
while (reply != RT_OFF);
printf("DVAP offset is %d Hz\n", (int)dvapreg.param.word);
return true;
}
@ -551,29 +612,36 @@ bool CDVAPDongle::set_freq(int frequency)
dvapreg.param.control = 0x230u;
int rc = write_to_dvp(&dvapreg, 4);
if (rc != 4) {
if (rc != 4)
{
printf("Failed to send request for frequency limits\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests for dvap frequency limits\n");
return false;
}
} while (reply != RT_FREQ_LIMIT);
}
while (reply != RT_FREQ_LIMIT);
printf("DVAP Frequency limits are from %d to %d Hz\n", dvapreg.param.twod[0], dvapreg.param.twod[1]);
// okay, now we know the frequency limits, get on with the show...
if (frequency < dvapreg.param.twod[0]) {
if (frequency < dvapreg.param.twod[0])
{
printf("Frequency of %d is too small, resetting...\n", frequency);
frequency = dvapreg.param.twod[0];
} else if (frequency > dvapreg.param.twod[1]) {
}
else if (frequency > dvapreg.param.twod[1])
{
printf("Frequency of %d is too large, resetting...\n", frequency);
frequency = dvapreg.param.twod[1];
}
@ -584,22 +652,26 @@ bool CDVAPDongle::set_freq(int frequency)
dvapreg.param.dword = frequency;
rc = write_to_dvp(&dvapreg, 8);
if (rc != 8) {
if (rc != 8)
{
printf("Failed to send request to set dvap frequency\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to set dvap frequency\n");
return false;
}
} while (reply != RT_FREQ);
}
while (reply != RT_FREQ);
printf("DVAP frequency is %d Hz\n", dvapreg.param.dword);
return true;
}
@ -614,22 +686,26 @@ bool CDVAPDongle::start_dvap()
dvapreg.param.byte = 0x1;
int rc = write_to_dvp(&dvapreg, 5);
if (rc != 5) {
if (rc != 5)
{
printf("Failed to send request to start the dvap dongle\n");
return false;
}
do {
do
{
usleep(5000);
reply = GetReply(dvapreg);
cnt ++;
if (cnt >= MAX_REPL_CNT) {
if (cnt >= MAX_REPL_CNT)
{
printf("Reached max number of requests to start the dvap dongle\n");
return false;
}
} while (reply != RT_START);
}
while (reply != RT_START);
return true;
}
@ -649,9 +725,11 @@ int CDVAPDongle::write_to_dvp(const void *buffer, const unsigned int len)
return 0;
uint8_t *buf = (uint8_t *)buffer;
while (ptr < len) {
while (ptr < len)
{
ssize_t n = write(serfd, buf + ptr, len - ptr);
if (n < 0) {
if (n < 0)
{
printf("Error %d writing to dvap, message=%s\n", errno, strerror(errno));
return -1;
}
@ -675,25 +753,30 @@ int CDVAPDongle::read_from_dvp(void *buffer, unsigned int len)
if (len == 0)
return 0;
while (off < len) {
while (off < len)
{
FD_ZERO(&fds);
FD_SET(serfd, &fds);
if (off == 0) {
if (off == 0)
{
tv.tv_sec = 0;
tv.tv_usec = 0;
n = select(serfd + 1, &fds, NULL, NULL, &tv);
if (n == 0)
return 0; // nothing to read from the dvap
} else
}
else
n = select(serfd + 1, &fds, NULL, NULL, NULL);
if (n < 0) {
if (n < 0)
{
printf("select error=%d on dvap\n", errno);
return -1;
}
if (n > 0) {
if (n > 0)
{
temp_len = read(serfd, buf + off, len - off);
if (temp_len > 0)
off += temp_len;
@ -708,19 +791,22 @@ bool CDVAPDongle::OpenSerial(char *device)
static termios t;
serfd = open(device, O_RDWR | O_NOCTTY | O_NDELAY, 0);
if (serfd < 0) {
if (serfd < 0)
{
printf("Failed to open device [%s], error=%d, message=%s\n", device, errno, strerror(errno));
return false;
}
if (isatty(serfd) == 0) {
if (isatty(serfd) == 0)
{
printf("Device %s is not a tty device\n", device);
close(serfd);
serfd = -1;
return false;
}
if (tcgetattr(serfd, &t) < 0) {
if (tcgetattr(serfd, &t) < 0)
{
printf("tcgetattr failed for %s, error=%d, message-%s\n", device, errno, strerror(errno));
close(serfd);
serfd = -1;
@ -738,7 +824,8 @@ bool CDVAPDongle::OpenSerial(char *device)
cfsetospeed(&t, B230400);
cfsetispeed(&t, B230400);
if (tcsetattr(serfd, TCSANOW, &t) < 0) {
if (tcsetattr(serfd, TCSANOW, &t) < 0)
{
printf("tcsetattr failed for %s, error=%dm message=%s\n", device, errno, strerror(errno));
close(serfd);
serfd = -1;

@ -19,7 +19,8 @@
#include <stdint.h>
enum REPLY_TYPE {
enum REPLY_TYPE
{
RT_TIMEOUT,
RT_ERR,
RT_UNKNOWN,
@ -44,13 +45,17 @@ enum REPLY_TYPE {
};
#pragma pack(push,1)
using SDVAP_REGISTER = struct dvp_register_tag {
using SDVAP_REGISTER = struct dvp_register_tag
{
uint16_t header;
union {
union
{
uint8_t nul;
struct {
struct
{
uint16_t control;
union {
union
{
int8_t byte;
int16_t word;
int32_t dword;
@ -59,12 +64,15 @@ using SDVAP_REGISTER = struct dvp_register_tag {
uint8_t ustr[12];
};
} param;
struct {
struct
{
uint16_t streamid;
uint8_t framepos;
uint8_t seq;
union {
struct {
union
{
struct
{
unsigned char flag[3];
unsigned char rpt2[8];
unsigned char rpt1[8];
@ -73,7 +81,8 @@ using SDVAP_REGISTER = struct dvp_register_tag {
unsigned char sfx[4];
unsigned char pfcs[2];
} hdr;
struct {
struct
{
unsigned char voice;
unsigned char sdata;
} vad;

@ -21,7 +21,8 @@
#include <queue>
#include <string>
class CHost {
class CHost
{
public:
CHost() {}

@ -42,7 +42,8 @@ void CKRBase::SetState(bool state)
void CKRBase::SigHandler(int sig)
{
switch (sig) {
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:

@ -38,13 +38,15 @@ bool CLocation::Parse(const char *instr)
if (s.size() < 20)
return false;
if (! std::regex_search(s.c_str(), cm, gps, std::regex_constants::match_default)) {
if (! std::regex_search(s.c_str(), cm, gps, std::regex_constants::match_default))
{
//std::cerr << "Unsuccessful gps parse of '" << s << "'" << std::endl;
return false;
}
auto size = cm.size();
if (size != 7) {
if (size != 7)
{
std::cerr << "Bad CRC Match for " << s << ":";
for (unsigned i=0; i<size; i++)
std::cerr << " [" << cm[i] << "]";
@ -53,13 +55,15 @@ bool CLocation::Parse(const char *instr)
}
double deg = stod(cm[1]);
if (90.0 < deg) {
if (90.0 < deg)
{
std::cout << "Latitude degree " << deg << " is out of range" << std::endl;
return false;
}
double min = stod(cm[2]);
if (60.0 < min) {
if (60.0 < min)
{
std::cout << "Latitude minutes " << min << " is out of range" << std::endl;
return false;
}
@ -69,13 +73,15 @@ bool CLocation::Parse(const char *instr)
latitude = 0.0 - latitude;
deg = stod(cm[4]);
if (180.0 < deg) {
if (180.0 < deg)
{
std::cout << "Longitude degree " << deg << " is out of range" << std::endl;
return false;
}
min = stod(cm[5]);
if (60.0 < min) {
if (60.0 < min)
{
std::cout << "Longitude minutes " << min << " is out of range" << std::endl;
return false;
}
@ -103,7 +109,8 @@ const char *CLocation::APRS(std::string &call, const char *station)
call.resize(8, ' ');
last = call.at(7);
auto pos = call.find(' ');
if (call.npos != pos) {
if (call.npos != pos)
{
call.resize(pos+1);
}
double latmin, lonmin;

@ -43,20 +43,25 @@ char *CQnetConfigure::Trim(char *s)
bool CQnetConfigure::ReadConfigFile(const char *configfile, std::map<std::string, std::string> &amap)
{
FILE *fp = fopen(configfile, "r");
if (fp) {
if (fp)
{
char line[2048];
while (fgets(line, 2048, fp)) {
while (fgets(line, 2048, fp))
{
char *key = strtok(line, "=");
key = Trim(key);
if (strlen(key) && '#' != *key) {
if (strlen(key) && '#' != *key)
{
char *val = strtok(NULL, "\r\n");
char *val2 = Trim(val);
if ('\'' == val2[0]) {
if ('\'' == val2[0])
{
if ('\'' == val2[1])
val[0] = '\0';
else
val = strtok(val2, "'");
} else
}
else
val = strtok(val2, "# \t");
amap[key] = val;
}
@ -95,7 +100,8 @@ bool CQnetConfigure::GetDefaultBool(const std::string &path, const std::string &
dvalue = false;
else if ('1'==value.at(0) || 't'==value.at(0) || 'T'==value.at(0))
dvalue = true;
else {
else
{
fprintf(stderr, "%s=%s doesn't seem to be a boolean!\n", path.c_str(), value.c_str());
return true;
}
@ -123,28 +129,38 @@ bool CQnetConfigure::GetDefaultInt(const std::string &path, const std::string &m
bool CQnetConfigure::GetDefaultString(const std::string &path, const std::string &mod, std::string &dvalue)
{
std::string search, search_again;
if (mod.empty()) {
if (mod.empty())
{
search = path + "_d"; // there is no mod, so this is a simple search
} else {
}
else
{
search_again = mod; // we're looking from a module value. We may have to look for non-generic module parameters
if (0==path.compare(0, 7, "module_") && ('a'==path.at(7) || 'b'==path.at(7) || 'c'==path.at(7)) && '_'==path.at(8)) {
if (0==path.compare(0, 7, "module_") && ('a'==path.at(7) || 'b'==path.at(7) || 'c'==path.at(7)) && '_'==path.at(8))
{
// path begins with module_{a|b|c}_
if (0==mod.compare("dvrptr") || 0==mod.compare("dvap") || 0==mod.compare("mmdvmhost") || 0==mod.compare("mmdvmmodem") || 0==mod.compare("itap") || 0==mod.compare("thumbdv")) {
if (0==mod.compare("dvrptr") || 0==mod.compare("dvap") || 0==mod.compare("mmdvmhost") || 0==mod.compare("mmdvmmodem") || 0==mod.compare("itap") || 0==mod.compare("thumbdv"))
{
// and the module is recognized
search = path;
search.replace(7, 1, 1, 'x');
search_again += path.substr(8); // now the search_again path might look like dvap_frequency, for example.
} else {
}
else
{
fprintf(stderr, "Unrecognized module type = '%s'\n", mod.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "%s looks like an ilformed request from module '%s'\n", path.c_str(), mod.c_str());
return true;
}
}
auto it = defaults.find(search);
if (defaults.end() == it) {
if (defaults.end() == it)
{
it = defaults.find(search_again);
if (defaults.end() == it)
return true;
@ -156,20 +172,25 @@ bool CQnetConfigure::GetDefaultString(const std::string &path, const std::string
bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, bool &value)
{
auto it = cfg.find(path);
if (cfg.end() == it) {
if (cfg.end() == it)
{
bool dvalue;
if (GetDefaultBool(path, mod, dvalue)) {
if (GetDefaultBool(path, mod, dvalue))
{
fprintf(stderr, "%s not found in either the cfg file or the defaults file!\n", path.c_str());
return true;
}
value = dvalue; // found a value in the defaults
} else { // found a value in the cfg file
}
else // found a value in the cfg file
{
char c = it->second.at(0);
if ('0'==c || 'f'==c || 'F'==c)
value = false;
else if ('1'==c || 't'==c || 'T'==c)
value = true;
else {
else
{
fprintf(stderr, "%s=%s doesn't seem to define a boolean\n", path.c_str(), it->second.c_str());
return true;
}
@ -181,20 +202,26 @@ bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, b
bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, double &value, const double min, const double max)
{
auto it = cfg.find(path);
if (cfg.end() == it) {
if (cfg.end() == it)
{
double dvalue;
if (GetDefaultDouble(path, mod, dvalue)) {
if (GetDefaultDouble(path, mod, dvalue))
{
fprintf(stderr, "%s not found in either the cfg file or the defaults file!\n", path.c_str());
return true;
}
if (dvalue < min || dvalue > max) {
if (dvalue < min || dvalue > max)
{
fprintf(stderr, "Default value %s=%g is out of acceptable range\n", path.c_str(), value);
return true;
}
value = dvalue;
} else {
}
else
{
value = std::stod(it->second);
if (value < min || value > max) {
if (value < min || value > max)
{
fprintf(stderr, "%s=%g is out of acceptable range\n", path.c_str(), value);
return true;
}
@ -206,20 +233,26 @@ bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, d
bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, int &value, const int min, const int max)
{
auto it = cfg.find(path);
if (cfg.end() == it) {
if (cfg.end() == it)
{
int dvalue;
if (GetDefaultInt(path, mod, dvalue)) {
if (GetDefaultInt(path, mod, dvalue))
{
fprintf(stderr, "%s not found in either the cfg file or the defaults file\n", path.c_str());
return true;
}
if (dvalue < min || dvalue > max) {
if (dvalue < min || dvalue > max)
{
fprintf(stderr, "Default value %s=%d is out of acceptable range\n", path.c_str(), value);
return true;
}
value = dvalue;
} else {
}
else
{
value = std::stoi(it->second);
if (value < min || value > max) {
if (value < min || value > max)
{
fprintf(stderr, "%s=%s is out of acceptable range\n", path.c_str(), it->second.c_str());
return true;
}
@ -231,22 +264,28 @@ bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, i
bool CQnetConfigure::GetValue(const std::string &path, const std::string &mod, std::string &value, int min, int max)
{
auto it = cfg.find(path);
if (cfg.end() == it) {
if (cfg.end() == it)
{
std::string dvalue;
if (GetDefaultString(path, mod, dvalue)) {
if (GetDefaultString(path, mod, dvalue))
{
fprintf(stderr, "%s not found in either the cfg file or the defaults file\n", path.c_str());
return true;
}
int l = dvalue.length();
if (min-1>=l || l>max) {
if (min-1>=l || l>max)
{
printf("Default value %s='%s' is wrong size\n", path.c_str(), value.c_str());
return true;
}
value.assign(dvalue);
} else {
}
else
{
value.assign(it->second);
int l = value.length();
if (l<min || l>max) {
if (l<min || l>max)
{
printf("%s='%s' is wrong size\n", path.c_str(), value.c_str());
return true;
}

@ -21,7 +21,8 @@
#include <string>
#include <map>
class CQnetConfigure {
class CQnetConfigure
{
public:
CQnetConfigure();
virtual ~CQnetConfigure();

@ -23,7 +23,8 @@
bool CQnetDB::Open(const char *name)
{
if (sqlite3_open_v2(name, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL)) {
if (sqlite3_open_v2(name, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL))
{
fprintf(stderr, "CQnetDB::Open: can't open %s\n", name);
return true;
}
@ -47,7 +48,8 @@ bool CQnetDB::Init()
"lasttime INT NOT NULL"
") WITHOUT ROWID;");
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::Init [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -61,7 +63,8 @@ bool CQnetDB::Init()
"linked_time INT NOT NULL"
") WITHOUT ROWID;");
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::Init [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -73,7 +76,8 @@ bool CQnetDB::Init()
"port INT NOT NULL"
") WITHOUT ROWID;");
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::Init [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -81,7 +85,8 @@ bool CQnetDB::Init()
return false;
}
static int countcallback(void *count, int /*argc*/, char **argv, char **/*azColName*/) {
static int countcallback(void *count, int /*argc*/, char **argv, char **/*azColName*/)
{
auto c = (int *)count;
*c = atoi(argv[0]);
return 0;
@ -98,13 +103,15 @@ bool CQnetDB::UpdateLH(const char *callsign, const char *sfx, const char module,
int count = 0;
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), countcallback, &count, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), countcallback, &count, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateLH [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
}
if (count) {
if (count)
{
sql.assign("UPDATE LHEARD SET (sfx,module,reflector,lasttime) = ('");
sql.append(sfx);
sql.append("','");
@ -115,7 +122,9 @@ bool CQnetDB::UpdateLH(const char *callsign, const char *sfx, const char module,
sql.append("strftime('%s','now')) WHERE callsign='");
sql.append(callsign);
sql.append("';");
} else {
}
else
{
sql.assign("INSERT INTO LHEARD (callsign,sfx,module,reflector,lasttime) VALUES ('");
sql.append(callsign);
sql.append("','");
@ -128,7 +137,8 @@ bool CQnetDB::UpdateLH(const char *callsign, const char *sfx, const char module,
sql.append("strftime('%s','now'));");
}
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateLH [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -153,7 +163,8 @@ bool CQnetDB::UpdatePosition(const char *callsign, const char *maidenhead, doubl
sql.append("';");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdatePosition [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -174,7 +185,8 @@ bool CQnetDB::UpdateMessage(const char *callsign, const char *message)
sql.append("';");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateMessage [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -200,7 +212,8 @@ bool CQnetDB::UpdateLS(const char *address, const char from_mod, const char *to_
sql.append(");");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateLS [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -224,7 +237,8 @@ bool CQnetDB::UpdateGW(const char *name, const char *address, unsigned short por
sql.append(");");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateGW [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -239,18 +253,21 @@ bool CQnetDB::UpdateGW(CHostQueue &hqueue)
return false;
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateGW BEGIN TRANSATION error: %s\n", eMsg);
sqlite3_free(eMsg);
return true;
}
while (! hqueue.Empty()) {
while (! hqueue.Empty())
{
auto h = hqueue.Pop();
UpdateGW(h.name.c_str(), h.addr.c_str(), h.port);
}
if (SQLITE_OK != sqlite3_exec(db, "COMMIT TRANSACTION;", NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, "COMMIT TRANSACTION;", NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::UpdateGW COMMIT TRANSACTION error: %s\n", eMsg);
sqlite3_free(eMsg);
return true;
@ -267,7 +284,8 @@ bool CQnetDB::DeleteLS(const char *address)
sql.append("';");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::DeleteLS [%s] error: %s\n", sql.c_str(), eMsg);
sqlite3_free(eMsg);
return true;
@ -286,15 +304,18 @@ bool CQnetDB::FindLS(const char mod, std::list<CLink> &linklist)
sqlite3_stmt *stmt;
int rval = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
if (SQLITE_OK != rval) {
if (SQLITE_OK != rval)
{
fprintf(stderr, "CQnetDB::FindLS [%s] error\n", sql.c_str());
return true;
}
while (SQLITE_ROW == sqlite3_step(stmt)) {
while (SQLITE_ROW == sqlite3_step(stmt))
{
std::string cs((const char *)sqlite3_column_text(stmt, 1));
std::string mod((const char *)sqlite3_column_text(stmt, 2));
if (mod.at(0) != 'p') {
if (mod.at(0) != 'p')
{
cs.resize(7, ' ');
cs.append(mod);
}
@ -318,17 +339,21 @@ bool CQnetDB::FindGW(const char *name, std::string &address, unsigned short &por
sqlite3_stmt *stmt;
int rval = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
if (SQLITE_OK != rval) {
if (SQLITE_OK != rval)
{
fprintf(stderr, "CQnetDB::FindGW error: %d\n", rval);
return true;
}
if (SQLITE_ROW == sqlite3_step(stmt)) {
if (SQLITE_ROW == sqlite3_step(stmt))
{
address.assign((const char *)sqlite3_column_text(stmt, 0));
port = (unsigned short)(sqlite3_column_int(stmt, 1));
sqlite3_finalize(stmt);
return false;
} else {
}
else
{
sqlite3_finalize(stmt);
return true;
}
@ -347,15 +372,19 @@ bool CQnetDB::FindGW(const char *name)
sqlite3_stmt *stmt;
int rval = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
if (SQLITE_OK != rval) {
if (SQLITE_OK != rval)
{
fprintf(stderr, "CQnetDB::FindGW error: %d\n", rval);
return true;
}
if (SQLITE_ROW == sqlite3_step(stmt)) {
if (SQLITE_ROW == sqlite3_step(stmt))
{
sqlite3_finalize(stmt);
return true;
} else {
}
else
{
sqlite3_finalize(stmt);
return false;
}
@ -368,7 +397,8 @@ void CQnetDB::ClearLH()
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM LHEARD;", NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM LHEARD;", NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::ClearLH error: %s\n", eMsg);
sqlite3_free(eMsg);
}
@ -381,7 +411,8 @@ void CQnetDB::ClearLS()
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM LINKSTATUS;", NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM LINKSTATUS;", NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::ClearLS error: %s\n", eMsg);
sqlite3_free(eMsg);
}
@ -394,7 +425,8 @@ void CQnetDB::ClearGW()
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM GATEWAYS;", NULL, 0, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM GATEWAYS;", NULL, 0, &eMsg))
{
fprintf(stderr, "CQnetDB::ClearGW error: %s\n", eMsg);
sqlite3_free(eMsg);
}
@ -412,7 +444,8 @@ int CQnetDB::Count(const char *table)
int count = 0;
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), countcallback, &count, &eMsg)) {
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), countcallback, &count, &eMsg))
{
fprintf(stderr, "CQnetDB::Count error: %s\n", eMsg);
sqlite3_free(eMsg);
}

@ -24,7 +24,8 @@
#include "HostQueue.h"
class CLink {
class CLink
{
public:
CLink(const std::string &call, const unsigned char *addr, time_t ltime) : callsign(call), address((const char *)addr), linked_time(ltime) {}
@ -49,7 +50,8 @@ public:
time_t linked_time;
};
class CQnetDB {
class CQnetDB
{
public:
CQnetDB() : db(NULL) {}
~CQnetDB() { if (db) sqlite3_close(db); }

@ -62,7 +62,8 @@ void CQnetDVAP::calcPFCS(unsigned char *packet, unsigned char *pfcs)
{
unsigned short crc_dstar_ffff = 0xffff;
unsigned short tmp, short_c;
unsigned short crc_tabccitt[256] = {
unsigned short crc_tabccitt[256] =
{
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
@ -81,7 +82,8 @@ void CQnetDVAP::calcPFCS(unsigned char *packet, unsigned char *pfcs)
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
};
for (int i = 0; i < 39 ; i++) {
for (int i = 0; i < 39 ; i++)
{
short_c = 0x00ff & (unsigned short)packet[i];
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
@ -107,12 +109,15 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
const std::string estr; // an empty string
std::string type;
std::string dvap_path("module_");
if (0 > assigned_module) {
if (0 > assigned_module)
{
// we need to find the lone dvap module
for (int i=0; i<3; i++) {
for (int i=0; i<3; i++)
{
std::string test(dvap_path);
test.append(1, 'a'+i);
if (cfg.KeyExists(test)) {
if (cfg.KeyExists(test))
{
cfg.GetValue(test, estr, type, 1, 16);
if (type.compare("dvap"))
continue; // this ain't it!
@ -121,27 +126,35 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
break;
}
}
if (0 > assigned_module) {
if (0 > assigned_module)
{
fprintf(stderr, "Error: no 'dvap' module found\n!");
return true;
}
} else {
}
else
{
// make sure dvap module is defined
dvap_path.append(1, 'a' + assigned_module);
if (cfg.KeyExists(dvap_path)) {
if (cfg.KeyExists(dvap_path))
{
cfg.GetValue(dvap_path, estr, type, 1, 16);
if (type.compare("dvap")) {
if (type.compare("dvap"))
{
fprintf(stderr, "%s = %s is not 'dvap' type!\n", dvap_path.c_str(), type.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
return true;
}
}
RPTR_MOD = 'A' + assigned_module;
cfg.GetValue("gateway_tomodem"+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
if (cfg.KeyExists(dvap_path+"_callsign")) {
if (cfg.KeyExists(dvap_path+"_callsign"))
{
if (cfg.GetValue(dvap_path+"_callsign", type, RPTR, 3, 6))
return true;
}
@ -150,11 +163,13 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
if (RPTR.empty())
RPTR.assign(OWNER);
for (unsigned long i=0; i<RPTR.length(); i++) {
for (unsigned long i=0; i<RPTR.length(); i++)
{
if (islower(RPTR.at(i)))
RPTR.at(i) = toupper(RPTR.at(i));
}
for (unsigned long i=0; i<OWNER.length(); i++) {
for (unsigned long i=0; i<OWNER.length(); i++)
{
if (islower(OWNER.at(i)))
OWNER.at(i) = toupper(OWNER.at(i));
}
@ -209,7 +224,8 @@ void CQnetDVAP::ReadFromGateway()
bool written_to_q = false;
unsigned char ctrl_in = 0x80;
while (keep_running) {
while (keep_running)
{
written_to_q = false;
len = 0;
tv.tv_sec = 0;
@ -219,15 +235,19 @@ void CQnetDVAP::ReadFromGateway()
FD_SET (fd, &readfd);
select(fd + 1, &readfd, NULL, NULL, &tv);
if (FD_ISSET(fd, &readfd)) {
if (FD_ISSET(fd, &readfd))
{
len = ToGate.Read(dsvt.title, 56);
if (len == 56) {
if (busy20000) {
if (len == 56)
{
if (busy20000)
{
FD_CLR (fd, &readfd);
continue;
}
if ('G' == dsvt.hdr.rpt1[7]) {
if ('G' == dsvt.hdr.rpt1[7])
{
unsigned char tmp[8];
memcpy(tmp, dsvt.hdr.rpt1, 8);
memcpy(dsvt.hdr.rpt1, dsvt.hdr.rpt2, 8);
@ -235,19 +255,22 @@ void CQnetDVAP::ReadFromGateway()
}
/* check the module and gateway */
if (dsvt.hdr.rpt1[7] != RPTR_MOD) {
if (dsvt.hdr.rpt1[7] != RPTR_MOD)
{
FD_CLR(fd, &readfd);
break;
}
memcpy(dsvt.hdr.rpt2, OWNER.c_str(), 7);
dsvt.hdr.rpt2[7] = 'G';
if (RPTR.compare(OWNER)) {
if (RPTR.compare(OWNER))
{
// restriction mode
memcpy(dsvt.hdr.rpt1, RPTR.c_str(), 7);
memcpy(dsvt.hdr.rpt2, RPTR.c_str(), 7);
if (memcmp(dsvt.hdr.mycall, OWNER.c_str(), 7) == 0) {
if (memcmp(dsvt.hdr.mycall, OWNER.c_str(), 7) == 0)
{
/* this is an ACK back */
memcpy(dsvt.hdr.mycall, RPTR.c_str(), 7);
}
@ -258,12 +281,14 @@ void CQnetDVAP::ReadFromGateway()
(dsvt.hdr.flag[0] != 0x08) &&
(dsvt.hdr.flag[0] != 0x20) &&
(dsvt.hdr.flag[0] != 0x28) &&
(dsvt.hdr.flag[0] != 0x40)) {
(dsvt.hdr.flag[0] != 0x40))
{
FD_CLR(fd, &readfd);
break;
}
if (memcmp(dsvt.title, "DSVT", 4) || dsvt.id!=0x20 || dsvt.config!=0x10) {
if (memcmp(dsvt.title, "DSVT", 4) || dsvt.id!=0x20 || dsvt.config!=0x10)
{
FD_CLR(fd, &readfd);
break;
}
@ -278,7 +303,8 @@ void CQnetDVAP::ReadFromGateway()
/* save the streamid that is winning */
streamid = dsvt.streamid;
if (dsvt.hdr.flag[0] != 0x01) {
if (dsvt.hdr.flag[0] != 0x01)
{
if (dsvt.hdr.flag[0] == 0x00)
dsvt.hdr.flag[0] = 0x40;
@ -316,22 +342,33 @@ void CQnetDVAP::ReadFromGateway()
inactive = 0;
seq_no = 0;
} else if (len == 27) {
if (busy20000) {
if (dsvt.streamid == streamid) {
if (dsvt.ctrl == ctrl_in) {
}
else if (len == 27)
{
if (busy20000)
{
if (dsvt.streamid == streamid)
{
if (dsvt.ctrl == ctrl_in)
{
/* do not update written_to_q, ctrl_in */
; // printf("dup\n");
} else {
}
else
{
ctrl_in = dsvt.ctrl;
written_to_q = true;
if (seq_no == 0) {
if (seq_no == 0)
{
dsvt.vasd.text[0] = 0x55;
dsvt.vasd.text[1] = 0x2d;
dsvt.vasd.text[2] = 0x16;
} else {
if ((dsvt.vasd.text[0] == 0x55) && (dsvt.vasd.text[1] == 0x2d) && (dsvt.vasd.text[2] == 0x16)) {
}
else
{
if ((dsvt.vasd.text[0] == 0x55) && (dsvt.vasd.text[1] == 0x2d) && (dsvt.vasd.text[2] == 0x16))
{
dsvt.vasd.text[0] = 0x70;
dsvt.vasd.text[1] = 0x4f;
dsvt.vasd.text[2] = 0x93;
@ -361,7 +398,8 @@ void CQnetDVAP::ReadFromGateway()
if (seq_no == 21)
seq_no = 0;
if ((dsvt.ctrl & 0x40) != 0) {
if ((dsvt.ctrl & 0x40) != 0)
{
if (LOG_QSO)
printf("End G2: streamid=%04x\n", ntohs(dsvt.streamid));
@ -376,12 +414,17 @@ void CQnetDVAP::ReadFromGateway()
}
}
}
} else { // busy20000 is false
}
else // busy20000 is false
{
FD_CLR (fd, &readfd);
break;
}
} else { // len is not 56 or 27
if (!busy20000) {
}
else // len is not 56 or 27
{
if (!busy20000)
{
FD_CLR (fd, &readfd);
break;
}
@ -391,9 +434,12 @@ void CQnetDVAP::ReadFromGateway()
// If we received a dup or select() timed out or streamids dont match,
// then written_to_q is false
if (!written_to_q) { // we could also end up here if we are busy and we received a non-standard packet size
if (busy20000) {
if (++inactive >= inactiveMax) {
if (!written_to_q) // we could also end up here if we are busy and we received a non-standard packet size
{
if (busy20000)
{
if (++inactive >= inactiveMax)
{
if (LOG_QSO)
printf("G2 Timeout...\n");
@ -404,15 +450,21 @@ void CQnetDVAP::ReadFromGateway()
busy20000 = false;
break;
} else { // inactive too long
if (space == 127) {
}
else // inactive too long
{
if (space == 127)
{
if (LOG_DEBUG)
fprintf(stderr, "sending silent frame where: len=%d, inactive=%d\n", len, inactive);
if (seq_no == 0) {
if (seq_no == 0)
{
silence[9] = 0x55;
silence[10] = 0x2d;
silence[11] = 0x16;
} else {
}
else
{
silence[9] = 0x70;
silence[10] = 0x4f;
silence[11] = 0x93;
@ -435,7 +487,8 @@ void CQnetDVAP::ReadFromGateway()
seq_no = 0;
}
}
} else // busy20000 is false
}
else // busy20000 is false
break;
}
}
@ -481,11 +534,13 @@ void CQnetDVAP::RptrAckThread(SDVAP_ACK_ARG *parg)
// SYNC
dr.header = 0xc012u;
dr.frame.streamid = sid;
for (int i=0; i<10; i++) {
for (int i=0; i<10; i++)
{
while ((space < 1) && keep_running)
usleep(5);
dr.frame.framepos = dr.frame.seq = i;
switch (i) {
switch (i)
{
case 0:
silence[9] = 0x55;
silence[10] = 0x2d;
@ -568,32 +623,43 @@ void CQnetDVAP::ReadDVAPThread()
int num_dv_frames = 0;
int num_bit_errors = 0;
while (keep_running) {
while (keep_running)
{
// local RF user went away ?
if (dvap_busy) {
if (dvap_busy)
{
if (last_RF_time.time() > TIMING_TIMEOUT_LOCAL_RPTR)
dvap_busy = false;
}
// read from the dvap and process
reply = dongle.GetReply(dr);
if (reply == RT_ERR) {
if (reply == RT_ERR)
{
printf("Detected ERROR event from DVAP dongle, stopping...n");
break;
} else if (reply == RT_STOP) {
}
else if (reply == RT_STOP)
{
printf("Detected STOP event from DVAP dongle, stopping...\n");
break;
} else if (reply == RT_START) {
}
else if (reply == RT_START)
{
printf("Detected START event from DVAP dongle\n");
// else if (reply == RT_PTT) {
// ptt = (dvp_buf[4] == 0x01);
// printf("Detected PTT=%s\n", ptt?"on":"off");
} else if (reply == RT_STS) {
}
else if (reply == RT_STS)
{
space = (unsigned int)dr.param.sstr[2];
if (status_cntr < 3000)
status_cntr += 20;
} else if (reply == RT_HDR) {
}
else if (reply == RT_HDR)
{
num_dv_frames = 0;
num_bit_errors = 0;
@ -603,7 +669,8 @@ void CQnetDVAP::ReadDVAPThread()
ok = true;
/* Accept valid flags only */
if (ok) {
if (ok)
{
if ((dr.frame.hdr.flag[0] != 0x00) && (dr.frame.hdr.flag[0] != 0x08) && // net
(dr.frame.hdr.flag[0] != 0x20) && (dr.frame.hdr.flag[0] != 0x28) && // flags
@ -642,21 +709,28 @@ void CQnetDVAP::ReadDVAPThread()
that means that mycall, rpt1, rpt2 must be equal to RPTR
otherwise we drop the rf data
*/
if (RPTR.compare(OWNER)) {
if (memcmp(dsvt.hdr.mycall, RPTR.c_str(), CALL_SIZE) != 0) {
if (RPTR.compare(OWNER))
{
if (memcmp(dsvt.hdr.mycall, RPTR.c_str(), CALL_SIZE) != 0)
{
printf("mycall=[%.8s], not equal to %s\n", dsvt.hdr.mycall, RPTR.c_str());
ok = false;
}
} else if (memcmp(dsvt.hdr.mycall, " ", 8) == 0) {
}
else if (memcmp(dsvt.hdr.mycall, " ", 8) == 0)
{
printf("Invalid value for mycall=[%.8s]\n", dsvt.hdr.mycall);
ok = false;
}
if (ok) {
for (i = 0; i < 8; i++) {
if (ok)
{
for (i = 0; i < 8; i++)
{
if (!isupper(dsvt.hdr.mycall[i]) &&
!isdigit(dsvt.hdr.mycall[i]) &&
(dsvt.hdr.mycall[i] != ' ')) {
(dsvt.hdr.mycall[i] != ' '))
{
memset(dsvt.hdr.mycall, ' ', 8);
ok = false;
printf("Invalid value for MYCALL\n");
@ -664,20 +738,24 @@ void CQnetDVAP::ReadDVAPThread()
}
}
for (i = 0; i < 4; i++) {
for (i = 0; i < 4; i++)
{
if (!isupper(dsvt.hdr.sfx[i]) &&
!isdigit(dsvt.hdr.sfx[i]) &&
(dsvt.hdr.sfx[i] != ' ')) {
(dsvt.hdr.sfx[i] != ' '))
{
memset(dsvt.hdr.sfx, ' ', 4);
break;
}
}
for (i = 0; i < 8; i++) {
for (i = 0; i < 8; i++)
{
if (!isupper(dsvt.hdr.urcall[i]) &&
!isdigit(dsvt.hdr.urcall[i]) &&
(dsvt.hdr.urcall[i] != ' ') &&
(dsvt.hdr.urcall[i] != '/')) {
(dsvt.hdr.urcall[i] != '/'))
{
memcpy(dsvt.hdr.urcall, "CQCQCQ ", 8);
break;
}
@ -724,9 +802,12 @@ void CQnetDVAP::ReadDVAPThread()
memcpy(mycall, dr.frame.hdr.mycall, 8);
}
} else if (reply == RT_DAT) {
}
else if (reply == RT_DAT)
{
/* have we already received a header ? */
if (dvap_busy) {
if (dvap_busy)
{
the_end = ((dr.frame.framepos & 0x40) == 0x40);
dsvt.config = 0x20U;
@ -738,7 +819,8 @@ void CQnetDVAP::ReadDVAPThread()
int ber_data[3];
int ber_errs = decode.Decode(dsvt.vasd.voice, ber_data);
if (ber_data[0] != 0xf85) {
if (ber_data[0] != 0xf85)
{
num_bit_errors += ber_errs;
num_dv_frames++;
}
@ -748,7 +830,8 @@ void CQnetDVAP::ReadDVAPThread()
// local RF user still talking, update timer
last_RF_time.start();
if (the_end) {
if (the_end)
{
// local RF user stopped talking
dvap_busy = false;
SDVAP_ACK_ARG dvap_ack_arg;
@ -756,11 +839,15 @@ void CQnetDVAP::ReadDVAPThread()
if (LOG_QSO)
printf("End of dvap audio, ber=%.02f\n", dvap_ack_arg.ber);
if (MODULE_ACKNOWLEDGE && !busy20000) {
if (MODULE_ACKNOWLEDGE && !busy20000)
{
memcpy(dvap_ack_arg.mycall, mycall, 8);
try {
try
{
std::async(std::launch::async, &CQnetDVAP::RptrAckThread, this, &dvap_ack_arg);
} catch (const std::exception &e) {
}
catch (const std::exception &e)
{
printf("Failed to start RptrAckThread(). Exception: %s\n", e.what());
}
}
@ -787,16 +874,19 @@ bool CQnetDVAP::Init(const char *file, const int amod)
{
assigned_module = amod;
if (ReadConfig(file)) {
if (ReadConfig(file))
{
printf("Failed to process config file %s\n", file);
return true;
}
if (RPTR.length() != 8) {
if (RPTR.length() != 8)
{
printf("Bad RPTR value, length must be exactly 8 bytes\n");
return true;
}
if ((RPTR_MOD != 'A') && (RPTR_MOD != 'B') && (RPTR_MOD != 'C')) {
if ((RPTR_MOD != 'A') && (RPTR_MOD != 'B') && (RPTR_MOD != 'C'))
{
printf("Bad RPTR_MOD value, must be one of A or B or C\n");
return true;
}
@ -818,7 +908,8 @@ bool CQnetDVAP::Init(const char *file, const int amod)
if (!dongle.Initialize(MODULE_SERIAL_NUMBER.c_str(), MODULE_FREQUENCY, MODULE_OFFSET, MODULE_POWER, MODULE_SQUELCH))
return true;
if (ToGate.Open(togate.c_str(), this)) {
if (ToGate.Open(togate.c_str(), this))
{
dongle.Stop();
close(serfd);
return true;
@ -831,25 +922,33 @@ void CQnetDVAP::Run()
{
CTimer ackpoint;
std::future<void> readthread;
try {
try
{
readthread = std::async(std::launch::async, &CQnetDVAP::ReadDVAPThread, this);
} catch (const std::exception &e) {
}
catch (const std::exception &e)
{
printf("Unable to start ReadDVAPThread(). Exception: %s\n", e.what());
keep_running = false;
}
printf("Started ReadDVAPThread()\n");
int cnt = 0;
while (keep_running) {
if (ackpoint.time() > 2.5) {
while (keep_running)
{
if (ackpoint.time() > 2.5)
{
int rc = dongle.KeepAlive();
if (rc < 0) {
if (rc < 0)
{
cnt ++;
if (cnt > 5) {
if (cnt > 5)
{
printf("Could not send KEEPALIVE signal to dvap 5 times...exiting\n");
keep_running = false;
}
} else
}
else
cnt = 0;
ackpoint.start();
}
@ -867,12 +966,14 @@ int main(int argc, char *argv[])
setvbuf(stdout, NULL, _IOLBF, 0);
printf("dvap_rptr VERSION %s\n", DVAP_VERSION);
if (argc != 2) {
if (argc != 2)
{
fprintf(stderr, "Usage: %s dvap_rptr.cfg\n", argv[0]);
return EXIT_FAILURE;
}
if ('-' == argv[1][0]) {
if ('-' == argv[1][0])
{
printf("\nQnetDVAP Version #%s Copyright (C) 2018-2020 by Thomas A. Early N7TAE\n", DVAP_VERSION);
printf("QnetDVAP comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
@ -880,14 +981,16 @@ int main(int argc, char *argv[])
}
const char *qn = strstr(argv[0], "qndvap");
if (NULL == qn) {
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qndvap' in %s!\n", argv[0]);
return EXIT_FAILURE;
}
qn += 6;
int mod;
switch (*qn) {
switch (*qn)
{
case NULL:
mod = -1;
break;

@ -20,7 +20,8 @@
#include "KRBase.h"
using SDVAP_ACK_ARG = struct davp_ack_arg_tag {
using SDVAP_ACK_ARG = struct davp_ack_arg_tag
{
char mycall[8];
float ber;
};

@ -45,7 +45,8 @@
#define BAUD B115200
#define IP_SIZE 15
static const uint32_t ENCODING_TABLE_24128[] = {
static const uint32_t ENCODING_TABLE_24128[] =
{
0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU,
0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U,
0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU,
@ -471,8 +472,10 @@ static const uint32_t ENCODING_TABLE_24128[] = {
uint32_t CQnetDVRPTR::get_syndrome_23127(uint32_t pattern)
{
uint32_t aux = GORLAY_X22;
if (pattern >= GORLAY_X11) {
while (pattern & GORLAY_MASK12) {
if (pattern >= GORLAY_X11)
{
while (pattern & GORLAY_MASK12)
{
while ((aux & pattern)==0) aux >>= 1;
pattern ^= (aux / GORLAY_X11) * GORLAY_GENPOL;
}
@ -482,7 +485,8 @@ uint32_t CQnetDVRPTR::get_syndrome_23127(uint32_t pattern)
unsigned int CQnetDVRPTR::gorlay_decode23127(unsigned int code)
{
const uint32_t DECODING_TABLE_23127[] = {
const uint32_t DECODING_TABLE_23127[] =
{
0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U,
0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U,
0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U,
@ -706,7 +710,8 @@ unsigned int CQnetDVRPTR::gorlay_decode24128(unsigned int code)
return gorlay_decode23127(code >> 1);
}
const uint32_t PRNG_TABLE[] = {
const uint32_t PRNG_TABLE[] =
{
0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU,
0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U,
0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU,
@ -1124,7 +1129,8 @@ void CQnetDVRPTR::ambefec_deinterleave(tambevoicefec result, const tambevoicefec
uint32_t bitpos, bytcnt;
memset(result, 0, sizeof(tambevoicefec)); // init result
bitpos = 0;
for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) {
for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++)
{
char voice_dsr = voice[bytcnt];
if (voice_dsr & 0x80) result[bitpos>>3] |= (0x80 >> (bitpos&7));
interleaveambe12(bitpos);
@ -1149,7 +1155,8 @@ void CQnetDVRPTR::ambefec_interleave(tambevoicefec result, const tambevoicefec r
{
uint32_t bitpos, bytcnt;
bitpos = 0;
for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) {
for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++)
{
char voice_dsr = (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7)))?0x80:0x00;
interleaveambe12(bitpos);
if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x40;
@ -1191,14 +1198,16 @@ void CQnetDVRPTR::ambefec_regenerate(tambevoicefec voice)
const unsigned char silence[12] = { 0x9e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 };
void CQnetDVRPTR::CleanCall(std::string &callsign) {
void CQnetDVRPTR::CleanCall(std::string &callsign)
{
for (auto it=callsign.begin(); it!=callsign.end(); it++)
if (islower(*it))
*it = toupper(*it);
callsign.resize(CALL_SIZE, ' ');
}
const unsigned short crc_tabccitt[256] = {
const unsigned short crc_tabccitt[256] =
{
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
@ -1223,7 +1232,8 @@ void CQnetDVRPTR::calcPFCS(unsigned char *packet) //Netzwerk CRC
unsigned short tmp, short_c;
int i;
for (i = 17; i < 56 ; i++) {
for (i = 17; i < 56 ; i++)
{
short_c = 0x00ff & (unsigned short)packet[i];
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
@ -1249,12 +1259,15 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
const std::string estr; // an empty string
std::string type;
std::string path("module_");
if (0 > assigned_module) {
if (0 > assigned_module)
{
// we need to find the lone dvrptr module
for (int i=0; i<3; i++) {
for (int i=0; i<3; i++)
{
std::string test(path);
test.append(1, 'a'+i);
if (cfg.KeyExists(test)) {
if (cfg.KeyExists(test))
{
cfg.GetValue(test, estr, type, 1, 16);
if (type.compare("dvrptr"))
continue; // this ain't it!
@ -1263,20 +1276,27 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
break;
}
}
if (0 > assigned_module) {
if (0 > assigned_module)
{
fprintf(stderr, "Error: no 'dvrptr' module found\n!");
return true;
}
} else {
}
else
{
// make sure dvrptr module is defined
path.append(1, 'a' + assigned_module);
if (cfg.KeyExists(path)) {
if (cfg.KeyExists(path))
{
cfg.GetValue(path, estr, type, 1, 16);
if (type.compare("dvrptr")) {
if (type.compare("dvrptr"))
{
fprintf(stderr, "%s = %s is not 'dvrptr' type!\n", path.c_str(), type.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
return true;
}
@ -1291,12 +1311,15 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
CleanCall(call);
strncpy(DVCALL, call.c_str(), CALL_SIZE+1);
if (cfg.KeyExists(path+"_callsign")) {
if (cfg.KeyExists(path+"_callsign"))
{
if (cfg.GetValue(path+"_callsign", type, call, 3, 6))
return true;
CleanCall(call);
strncpy(RPTR, call.c_str(), CALL_SIZE+1);
} else {
}
else
{
strncpy(RPTR, DVCALL, CALL_SIZE+1);
}
@ -1345,16 +1368,20 @@ char *CQnetDVRPTR::cleanstr(char *Text)
static char cbuf[250];
memset(cbuf, 0U, 250U);
for (unsigned int x=0; x < strlen(Text); x++) {
if ((Text[x] > 0x1F) && (Text[x] < 0x7F)) {
if (Text[x] == '\'') {
for (unsigned int x=0; x < strlen(Text); x++)
{
if ((Text[x] > 0x1F) && (Text[x] < 0x7F))
{
if (Text[x] == '\'')
{
strcat(cbuf, "\\");
}
strncat(cbuf, &Text[x], 1);
}
}
for (unsigned int x=0; x < strlen(cbuf); x++) {
for (unsigned int x=0; x < strlen(cbuf); x++)
{
if (!isdigit(cbuf[x]) && !isupper(cbuf[x]) && (cbuf[x] != '/'))
cbuf[x] = ' ';
}
@ -1368,7 +1395,8 @@ int CQnetDVRPTR::open_port(char *dvrptr_device)
struct termios terminal;
fd_ser = open(dvrptr_device, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
if (fd_ser < 0) {
if (fd_ser < 0)
{
printf("Can not open the serial port %s, error=%d(%s)\n",
dvrptr_device, errno, strerror(errno));
return -1;
@ -1399,10 +1427,12 @@ int CQnetDVRPTR::read_port(int *fd_ser,unsigned char* buffera)
tva.tv_usec = 50;
select(*fd_ser + 1,&rfds,NULL,NULL,&tva);
if (FD_ISSET(*fd_ser, &rfds)) {
if (FD_ISSET(*fd_ser, &rfds))
{
a = read(*fd_ser,buffera,200);
return a;
} else
}
else
return 0;
}
@ -1440,7 +1470,8 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
memcpy(Send_Modem_Header + 35, DVCALL_and_MOD, 8);
memcpy(Send_Modem_Header + 43, "RPTR", 4);
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0) {
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0)
{
memcpy(Send_Modem_Header + 11, RPTR, 7);
memcpy(Send_Modem_Header + 19, RPTR, 7);
@ -1456,9 +1487,11 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
write(fd_ser, start_Header, sizeof (start_Header));
write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header));
for (i = 0; i < 16; i++) {
for (i = 0; i < 16; i++)
{
usleep(DELAY_BETWEEN);
if (i == 0) {
if (i == 0)
{
writevoice[0] =0xD0;
writevoice[1] =0x13;
writevoice[2] =0x00;
@ -1482,7 +1515,8 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
write(fd_ser, writevoice, sizeof (writevoice));
}
if ((i < 9) && ( i > 0 )) {
if ((i < 9) && ( i > 0 ))
{
writevoice[0] =0xD0;
writevoice[1] =0x13;
writevoice[2] =0x00;
@ -1493,35 +1527,50 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
writevoice[7] =0x00;
memcpy(writevoice + 8, silence, 9);
if (i == 1) {
if (i == 1)
{
writevoice[17] = '@' ^ 0x70;
writevoice[18] = RADIO_ID[0] ^ 0x4f;
writevoice[19] = RADIO_ID[1] ^ 0x93;
} else if (i == 2) {
}
else if (i == 2)
{
writevoice[17] = RADIO_ID[2] ^ 0x70;
writevoice[18] = RADIO_ID[3] ^ 0x4f;
writevoice[19] = RADIO_ID[4] ^ 0x93;
} else if (i == 3) {
}
else if (i == 3)
{
writevoice[17] = 'A' ^ 0x70;
writevoice[18] = RADIO_ID[5] ^ 0x4f;
writevoice[19] = RADIO_ID[6] ^ 0x93;
} else if (i == 4) {
}
else if (i == 4)
{
writevoice[17] = RADIO_ID[7] ^ 0x70;
writevoice[18] = RADIO_ID[8] ^ 0x4f;
writevoice[19] = RADIO_ID[9] ^ 0x93;
} else if (i == 5) {
}
else if (i == 5)
{
writevoice[17] = 'B' ^ 0x70;
writevoice[18] = RADIO_ID[10] ^ 0x4f;
writevoice[19] = RADIO_ID[11] ^ 0x93;
} else if (i == 6) {
}
else if (i == 6)
{
writevoice[17] = RADIO_ID[12] ^ 0x70;
writevoice[18] = RADIO_ID[13] ^ 0x4f;
writevoice[19] = RADIO_ID[14] ^ 0x93;
} else if (i == 7) {
}
else if (i == 7)
{
writevoice[17] = 'C' ^ 0x70;
writevoice[18] = RADIO_ID[15] ^ 0x4f;
writevoice[19] = RADIO_ID[16] ^ 0x93;
} else if (i == 8) {
}
else if (i == 8)
{
writevoice[17] = RADIO_ID[17] ^ 0x70;
writevoice[18] = RADIO_ID[18] ^ 0x4f;
writevoice[19] = RADIO_ID[19] ^ 0x93;
@ -1538,7 +1587,8 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
write(fd_ser, writevoice, sizeof (writevoice));
}
if (i == 9) {
if (i == 9)
{
writevoice[0] =0xD0;
writevoice[1] =0x13;
writevoice[2] =0x00;
@ -1563,7 +1613,8 @@ void CQnetDVRPTR::send_ack(char *a_call, float ber)
write(fd_ser, writevoice, sizeof (writevoice));
}
if (i == 15) {
if (i == 15)
{
write(fd_ser, ptt_off, sizeof(ptt_off));
seq_no1 ++;
if (seq_no1 == 250)
@ -1586,7 +1637,8 @@ void CQnetDVRPTR::readFrom20000()
bool written_to_q = false;
int fd = ToGate.GetFD();
while (keep_running) {
while (keep_running)
{
written_to_q = false;
tv.tv_sec = 0;
@ -1594,23 +1646,28 @@ void CQnetDVRPTR::readFrom20000()
FD_ZERO (&readfd);
FD_SET (fd, &readfd);
select(fd + 1, &readfd, NULL, NULL, &tv);
if (FD_ISSET(fd, &readfd)) {
if (FD_ISSET(fd, &readfd))
{
len = ToGate.Read(recv_buf.title, 56);
if (len == 56) {
if (busy20000) {
if (len == 56)
{
if (busy20000)
{
FD_CLR (fd, &readfd);
continue;
}
/* check the module and gateway */
if (recv_buf.hdr.rpt1[7] != DVRPTR_MOD) {
if (recv_buf.hdr.rpt1[7] != DVRPTR_MOD)
{
fprintf(stderr, "rpt1=%.8s != %c, ignoring\n", recv_buf.hdr.rpt1, DVRPTR_MOD);
FD_CLR (fd, &readfd);
break;
}
memcpy(recv_buf.hdr.rpt2, DVCALL_and_G, 8);
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0) {
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0)
{
memcpy(recv_buf.hdr.rpt1, RPTR, 7);
memcpy(recv_buf.hdr.rpt2, RPTR, 7);
@ -1627,12 +1684,14 @@ void CQnetDVRPTR::readFrom20000()
(recv_buf.hdr.flag[0] != 0x08) &&
(recv_buf.hdr.flag[0] != 0x20) &&
(recv_buf.hdr.flag[0] != 0x28) &&
(recv_buf.hdr.flag[0] != 0x40)) {
(recv_buf.hdr.flag[0] != 0x40))
{
FD_CLR (fd, &readfd);
break;
}
if ((memcmp(recv_buf.title, "DSVT", 4) != 0) || (recv_buf.id != 0x20)) {
if ((memcmp(recv_buf.title, "DSVT", 4) != 0) || (recv_buf.id != 0x20))
{
FD_CLR (fd, &readfd);
break;
}
@ -1653,7 +1712,8 @@ void CQnetDVRPTR::readFrom20000()
Send_Modem_Header[6] =0x00;
Send_Modem_Header[7] =0x00;
if (recv_buf.hdr.flag[0] != 0x1U) {
if (recv_buf.hdr.flag[0] != 0x1U)
{
if (recv_buf.hdr.flag[0] == 0x0U)
recv_buf.hdr.flag[0] = 0x40U;
else if (recv_buf.hdr.flag[0] == 0x8U)
@ -1692,9 +1752,12 @@ void CQnetDVRPTR::readFrom20000()
write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header));
inactive = 0;
seq_no = 0;
} else if (len == 27) {
}
else if (len == 27)
{
seq_no = recv_buf.ctrl & 0x1f;
if ((seq_no < 3) && (old_seq_no > 17)) {
if ((seq_no < 3) && (old_seq_no > 17))
{
block ++;
if (block >= 12)
block = 0;
@ -1702,12 +1765,17 @@ void CQnetDVRPTR::readFrom20000()
old_seq_no = seq_no;
seq_no = block * 21 + seq_no;
if (busy20000) {
if (recv_buf.streamid == streamid) {
if ((recv_buf.ctrl <= ctrl_in) && (ctrl_in != 0x80)) {
if (busy20000)
{
if (recv_buf.streamid == streamid)
{
if ((recv_buf.ctrl <= ctrl_in) && (ctrl_in != 0x80))
{
/* do not update written_to_q, ctrl_in */
; // printf("dup\n");
} else {
}
else
{
ctrl_in = recv_buf.ctrl;
if (ctrl_in == 0x14)
ctrl_in = 0x80;
@ -1733,7 +1801,8 @@ void CQnetDVRPTR::readFrom20000()
write(fd_ser, writevoice, sizeof (writevoice));
inactive = 1;
if ((recv_buf.ctrl & 0x40) != 0) {
if ((recv_buf.ctrl & 0x40) != 0)
{
printf("End G2: streamid=%04x\n",ntohs(recv_buf.streamid));
ptt_off[4] = Send_Modem_Header[4];
@ -1748,12 +1817,17 @@ void CQnetDVRPTR::readFrom20000()
}
}
}
} else {
}
else
{
FD_CLR (fd, &readfd);
break;
}
} else {
if (!busy20000) {
}
else
{
if (!busy20000)
{
FD_CLR (fd, &readfd);
break;
}
@ -1765,9 +1839,12 @@ void CQnetDVRPTR::readFrom20000()
If we received a dup or select() timed out or streamids dont match,
then written_to_q is false
*/
if (!written_to_q) { /* nothing was written to the adapter */
if (busy20000) {
if (++inactive == inactiveMax) {
if (!written_to_q) /* nothing was written to the adapter */
{
if (busy20000)
{
if (++inactive == inactiveMax)
{
printf("G2 Timeout...\n");
ptt_off[4] = Send_Modem_Header[4];
write(fd_ser, ptt_off, 8);
@ -1778,7 +1855,8 @@ void CQnetDVRPTR::readFrom20000()
inactive = 0;
break;
}
} else
}
else
break;
}
}
@ -1792,7 +1870,8 @@ bool CQnetDVRPTR::check_serial()
bool match = false;
unsigned char puffer[200];
for (int i = 0; i < 32; i++) {
for (int i = 0; i < 32; i++)
{
sprintf(dvrptr_device, "/dev/ttyACM%d", i);
if (access(dvrptr_device, R_OK | W_OK) != 0)
continue;
@ -1804,14 +1883,16 @@ bool CQnetDVRPTR::check_serial()
if (RX_Inverse == true)
Modem_Init2[6]=0x01;
if (TX_Inverse == true) {
if (TX_Inverse == true)
{
if (Modem_Init2[6]==0x01)
Modem_Init2[6]=0x03;
else
Modem_Init2[6]=0x02;
}
if (flock(fd_ser, LOCK_EX | LOCK_NB) != 0) {
if (flock(fd_ser, LOCK_EX | LOCK_NB) != 0)
{
close(fd_ser);
fd_ser = -1;
printf("Device %s is already locked/used by other dvrptr repeater\n", dvrptr_device);
@ -1820,20 +1901,25 @@ bool CQnetDVRPTR::check_serial()
printf("Device %s now locked for exclusive use\n", dvrptr_device);
int loop_count = 0;
while (true) {
if (InitCount == 4 ) {
while (true)
{
if (InitCount == 4 )
{
write(fd_ser, Modem_SERIAL, sizeof (Modem_SERIAL));
InitCount = 0;
}
if (InitCount == 3 ) {
if (InitCount == 3 )
{
write(fd_ser, Modem_Init0, sizeof (Modem_Init0));
InitCount = 4;
}
if (InitCount == 2 ) {
if (InitCount == 2 )
{
write(fd_ser, Modem_Init1, sizeof (Modem_Init1));
InitCount = 3;
}
if (InitCount == 1 ) {
if (InitCount == 1 )
{
write(fd_ser, Modem_Init2, sizeof (Modem_Init2));
InitCount = 2;
}
@ -1857,12 +1943,14 @@ bool CQnetDVRPTR::check_serial()
if ((puffer[0] == 0xD0) &&
(puffer[1] == 0x05) &&
(puffer[2] == 0x00) &&
(puffer[3] == 0x92)) {
(puffer[3] == 0x92))
{
puffer[1] = 0x00;
char temp_dvrptr_serial[16];
sprintf(temp_dvrptr_serial, "%02X.%02X.%02X.%02X", puffer[4], puffer[5], puffer[6], puffer[7]);
printf("Device %s has serial=[%s]\n", dvrptr_device, temp_dvrptr_serial);
if (strcmp(temp_dvrptr_serial, DVRPTR_SERIAL.c_str()) == 0) {
if (strcmp(temp_dvrptr_serial, DVRPTR_SERIAL.c_str()) == 0)
{
printf("Device %s serial number matches DVRPTR_SERIAL in dvrptr.cfg\n", dvrptr_device);
match = true;
}
@ -1870,13 +1958,15 @@ bool CQnetDVRPTR::check_serial()
}
loop_count ++;
if (loop_count > 50) {
if (loop_count > 50)
{
printf("Waited 5 seconds to receive serial number from device %s, ...aborting\n", dvrptr_device);
break;
}
}
if (match) {
if (match)
{
printf("Found a match after %d loops\n", loop_count);
break;
}
@ -1895,12 +1985,14 @@ int main(int argc, const char **argv)
setvbuf(stdout, NULL, _IOLBF, 0);
printf("dvrptr VERSION %s\n", DVRPTR_VERSION);
if (argc != 2) {
if (argc != 2)
{
fprintf(stderr, "Usage: %s <config_file>\n", argv[0]);
return 1;
}
if ('-' == argv[1][0]) {
if ('-' == argv[1][0])
{
printf("\nQnetDVRPTR Version #%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", DVRPTR_VERSION);
printf("QnetDVRPTR comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
@ -1908,14 +2000,16 @@ int main(int argc, const char **argv)
}
const char *qn = strstr(argv[0], "qndvrptr");
if (NULL == qn) {
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qndvrptr' in %s!\n", argv[0]);
return 1;
}
qn += 8;
int mod;
switch (*qn) {
switch (*qn)
{
case NULL:
mod = -1;
break;
@ -1944,21 +2038,25 @@ int main(int argc, const char **argv)
bool CQnetDVRPTR::Init(const char *file, int mod)
{
assigned_module = mod;
if (ReadConfig(file)) {
if (ReadConfig(file))
{
fprintf(stderr, "Failed to process config file %s\n", file);
return true;
}
if (!check_serial()) {
if (!check_serial())
{
fprintf(stderr, "Cant find any FREE ACMx device that matches\n");
return true;
}
if (strlen(DVCALL) != 8) {
if (strlen(DVCALL) != 8)
{
fprintf(stderr, "Bad DVCALL value, length must be exactly 8 bytes\n");
return true;
}
if ((DVRPTR_MOD != 'A') && (DVRPTR_MOD != 'B') && (DVRPTR_MOD != 'C')) {
if ((DVRPTR_MOD != 'A') && (DVRPTR_MOD != 'B') && (DVRPTR_MOD != 'C'))
{
fprintf(stderr, "Bad DVCALL_MOD value, must be one of A or B or C\n");
return true;
}
@ -1979,11 +2077,13 @@ bool CQnetDVRPTR::Init(const char *file, int mod)
if (ToGate.Open(togate.c_str(), this))
return true;
if (RX_Inverse == true) {
if (RX_Inverse == true)
{
Modem_Init2[6]=0x01;
}
if (TX_Inverse == true) {
if (TX_Inverse == true)
{
if (Modem_Init2[6]==0x01)
Modem_Init2[6]=0x03;
else
@ -2000,16 +2100,19 @@ void CQnetDVRPTR::Run()
time_t time_rqst = tNow;
time_t last_RF_time = tNow;
while (keep_running) {
while (keep_running)
{
time(&tNow);
if ((tNow - time_rqst) > 2) {
if ((tNow - time_rqst) > 2)
{
if (rqst_count < (RQST_COUNT - 2))
write(fd_ser, Modem_SERIAL, sizeof(Modem_SERIAL));
time_rqst = tNow;
rqst_count --;
if (rqst_count < 0) {
if (rqst_count < 0)
{
printf("Modem is not responding... shuttting down\n");
close(fd_ser);
break;
@ -2017,19 +2120,23 @@ void CQnetDVRPTR::Run()
}
// init Modem
if (InitCount == 4 ) {
if (InitCount == 4 )
{
write(fd_ser, Modem_STATUS, sizeof (Modem_STATUS));
InitCount = 0;
}
if (InitCount == 3 ) {
if (InitCount == 3 )
{
write(fd_ser, Modem_Init0, sizeof (Modem_Init0));
InitCount = 4;
}
if (InitCount == 2 ) {
if (InitCount == 2 )
{
write(fd_ser, Modem_Init1, sizeof (Modem_Init1));
InitCount = 3;
}
if (InitCount == 1 ) {
if (InitCount == 1 )
{
write(fd_ser, Modem_Init2, sizeof (Modem_Init2));
InitCount = 2;
}
@ -2040,8 +2147,10 @@ void CQnetDVRPTR::Run()
int seq_no = 0;
bool ok = false;
if (bytes2 > 0) {
switch (bytes2) {
if (bytes2 > 0)
{
switch (bytes2)
{
case 52:
num_dv_frames = 0;
@ -2080,18 +2189,22 @@ void CQnetDVRPTR::Run()
(puffer[8] != 0x40) &&
(puffer[8] != 0x48) &&
(puffer[8] != 0x60) &&
(puffer[8] != 0x68)) {
(puffer[8] != 0x68))
{
// printf("flags look BAD\n");
ok = false;
}
if ((puffer[9] != 0x00) || (puffer[10] != 0x00)) {
if ((puffer[9] != 0x00) || (puffer[10] != 0x00))
{
// printf("flags look BAD\n");
ok = false;
}
if (ok) {
if ((puffer[5] & 0x80) == 0x80) {
if (ok)
{
if ((puffer[5] & 0x80) == 0x80)
{
printf("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n",
puffer[8], puffer[9], puffer[10], myCall, myCall2, myUR, myRPT1, myRPT2);
printf("CRC checksum is BAD, will NOT process this QSO\n");
@ -2099,7 +2212,8 @@ void CQnetDVRPTR::Run()
}
}
if (ok) {
if (ok)
{
time(&last_RF_time);
printf("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n",
@ -2111,16 +2225,19 @@ void CQnetDVRPTR::Run()
in this case, set rpt1 and rpt2 to our values,
because the remote standalone repeater does not have a gateway.
*/
if (memcmp(myRPT1, myRPT2, 7) == 0) {
if (memcmp(myRPT1, myRPT2, 7) == 0)
{
if ((memcmp(myRPT1, DVCALL, 7) != 0) &&
(memcmp(myRPT1, RPTR, 7) != 0)) {
(memcmp(myRPT1, RPTR, 7) != 0))
{
memcpy(myRPT1, DVCALL_and_MOD, 8);
memcpy(myRPT2, DVCALL_and_G, 8);
}
}
}
if (ok) {
if (ok)
{
/* RPT1 must always be the repeater + module */
memcpy(myRPT1, DVCALL_and_MOD, 8);
@ -2130,17 +2247,20 @@ void CQnetDVRPTR::Run()
(myRPT2[7] == 'C') ||
(myRPT2[7] == 'G'))
memcpy(myRPT2, DVCALL, 7);
else {
else
{
printf("myRPT2=%.8s not A, B, C or G, blanking it\n", myRPT2);
memset(myRPT2, ' ', 8);
}
if ((memcmp(myUR, "CQCQCQ", 6) != 0) && (myRPT2[0] != ' ')) {
if ((memcmp(myUR, "CQCQCQ", 6) != 0) && (myRPT2[0] != ' '))
{
memcpy(myRPT2, DVCALL_and_G, 8);
}
/* 8th in rpt1, rpt2 must be diff */
if (myRPT2[7] == myRPT1[7]) {
if (myRPT2[7] == myRPT1[7])
{
memset(myRPT2, ' ', 8);
printf("%.8s==%.8s, blanking myRPT2\n", myRPT2, myRPT1);
}
@ -2152,22 +2272,29 @@ void CQnetDVRPTR::Run()
that means that mycall, rpt1, rpt2 must be equal to RPTR
otherwise we drop the rf data
*/
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0) {
if (memcmp(myCall, RPTR, CALL_SIZE) != 0) {
if (memcmp(RPTR, DVCALL, CALL_SIZE) != 0)
{
if (memcmp(myCall, RPTR, CALL_SIZE) != 0)
{
printf("mycall=[%.8s], not equal to %s\n", myCall, RPTR);
ok = false;
}
} else if (memcmp(myCall, " ", 8) == 0) {
}
else if (memcmp(myCall, " ", 8) == 0)
{
printf("Invalid value for mycall=[%.8s]\n", myCall);
ok = false;
}
}
if (ok) {
for (int i = 0; i < 8; i++) {
if (ok)
{
for (int i = 0; i < 8; i++)
{
if (!isupper(myCall[i]) &&
!isdigit(myCall[i]) &&
(myCall[i] != ' ')) {
(myCall[i] != ' '))
{
memset(myCall, ' ', 8);
ok = false;
printf("Invalid value for MYCALL\n");
@ -2175,20 +2302,24 @@ void CQnetDVRPTR::Run()
}
}
for (int i = 0; i < 4; i++) {
for (int i = 0; i < 4; i++)
{
if (!isupper(myCall2[i]) &&
!isdigit(myCall2[i]) &&
(myCall2[i] != ' ')) {
(myCall2[i] != ' '))
{
memset(myCall2, ' ', 4);
break;
}
}
for (int i = 0; i < 8; i++) {
for (int i = 0; i < 8; i++)
{
if (!isupper(myUR[i]) &&
!isdigit(myUR[i]) &&
(myUR[i] != ' ') &&
(myUR[i] != '/')) {
(myUR[i] != '/'))
{
memcpy(myUR, "CQCQCQ ", 8);
break;
}
@ -2199,11 +2330,15 @@ void CQnetDVRPTR::Run()
memcpy(myUR, "CQCQCQ ", 8);
}
if (ok) {
if ((memcmp(myUR, ENABLE_RF, 8) == 0) && (ENABLE_RF[0] != ' ')) {
if (ok)
{
if ((memcmp(myUR, ENABLE_RF, 8) == 0) && (ENABLE_RF[0] != ' '))
{
IS_ENABLED = true;
memcpy(myUR, "CQCQCQ ", 8);
} else if ((memcmp(myUR, DISABLE_RF, 8) == 0) && (DISABLE_RF[0] != ' ')) {
}
else if ((memcmp(myUR, DISABLE_RF, 8) == 0) && (DISABLE_RF[0] != ' '))
{
IS_ENABLED = false;
memcpy(myUR, "CQCQCQ ", 8);
}
@ -2249,8 +2384,10 @@ void CQnetDVRPTR::Run()
memcpy(Send_Network_Header.hdr.sfx, myCall2, 4);
calcPFCS(Send_Network_Header.title);
if (ok) {
if (IS_ENABLED) {
if (ok)
{
if (IS_ENABLED)
{
ToGate.Write(Send_Network_Header.title, 56);
}
}
@ -2259,7 +2396,8 @@ void CQnetDVRPTR::Run()
bytes2 = 0;
if (DUPLEX && !busy20000) {
if (DUPLEX && !busy20000)
{
Send_Modem_Header[0] =0xd0;
Send_Modem_Header[1] =0x2f;
Send_Modem_Header[2] =0x00;
@ -2279,8 +2417,10 @@ void CQnetDVRPTR::Run()
ptt_off[4] = seq_no1;
start_Header[4]=seq_no1;
if (ok) {
if (IS_ENABLED) {
if (ok)
{
if (IS_ENABLED)
{
write(fd_ser, start_Header, sizeof (start_Header));
write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header));
}
@ -2310,7 +2450,8 @@ void CQnetDVRPTR::Run()
Send_Network_Audio.ctrl = seq_no;
memcpy(Send_Network_Audio.vasd.voice, puffer + 8, 12);
if (IS_ENABLED) {
if (IS_ENABLED)
{
ToGate.Write(Send_Network_Audio.title, 27);
ber_errs = decode.Decode(Send_Network_Audio.vasd.voice, ber_data);
num_bit_errors += ber_errs;
@ -2321,7 +2462,8 @@ void CQnetDVRPTR::Run()
if (seq_no == 21)
seq_no = 0;
if (DUPLEX && !busy20000) {
if (DUPLEX && !busy20000)
{
writevoice1[0] =0xD0;
writevoice1[1] =0x13;
writevoice1[2] =0x00;
@ -2344,7 +2486,8 @@ void CQnetDVRPTR::Run()
if ((puffer[17] == 0x55) &&
(puffer[18] == 0x55) &&
(puffer[19] == 0x55)) {
(puffer[19] == 0x55))
{
ptt_off[4] = writevoice1[4];
write(fd_ser, ptt_off, 8);
}
@ -2365,7 +2508,8 @@ void CQnetDVRPTR::Run()
}
}
if ((puffer[0] == 0xD0) && (puffer[1] == 0x17) && (puffer[2] == 0x00) && (puffer[3] == 0x91)) {
if ((puffer[0] == 0xD0) && (puffer[1] == 0x17) && (puffer[2] == 0x00) && (puffer[3] == 0x91))
{
rqst_count = RQST_COUNT;
printf("DVRPTR Hardware ver: %.20s\n",puffer+6 );
@ -2385,7 +2529,8 @@ void CQnetDVRPTR::Run()
puffer[1] = 0x00;
}
if ((puffer[0] == 0xD0) && ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && (puffer[2] == 0x00) && (puffer[3] == 0x90)) {
if ((puffer[0] == 0xD0) && ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && (puffer[2] == 0x00) && (puffer[3] == 0x90))
{
rqst_count = RQST_COUNT;
printf("\n------- STATUS READ FROM MODEM ---------\n");
@ -2401,7 +2546,8 @@ void CQnetDVRPTR::Run()
}
/* serial */
if ((puffer[0] == 0xD0) && (puffer[1] == 0x05) && (puffer[2] == 0x00) && (puffer[3] == 0x92)) {
if ((puffer[0] == 0xD0) && (puffer[1] == 0x05) && (puffer[2] == 0x00) && (puffer[3] == 0x92))
{
rqst_count = RQST_COUNT;
puffer[1] = 0x00;
}
@ -2412,16 +2558,19 @@ void CQnetDVRPTR::Run()
time(&tNow);
/* If an RF user TXed and disappeared after that */
if ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) {
if ((last_RF_time > 0) && ((tNow - last_RF_time) > 1))
{
printf("End RF(Timeout), ber=%.02f\n",
(num_dv_frames == 0) ? 0.0 : 100.0 * ((float)num_bit_errors / (float)(num_dv_frames * 24.0)) );
ptt_off[4] = Send_Modem_Header[4];
write(fd_ser, ptt_off, 8);
}
if ( ((puffer[0] == 0xD0) && (puffer[1] == 0x03) && (puffer[2] == 0x00) && (puffer[3] == 0x1A)) || ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) ) {
if ( ((puffer[0] == 0xD0) && (puffer[1] == 0x03) && (puffer[2] == 0x00) && (puffer[3] == 0x1A)) || ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) )
{
puffer[0] = 0x00;
if (last_RF_time > 0) {
if (last_RF_time > 0)
{
const unsigned char silence[12] = { 0x9EU,0x8DU,0x32U,0x88U,0x26U,0x1AU,0x3FU,0x61U,0xE8U,0x70U,0x4FU,0x93U };
const unsigned char silsync[12] = { 0x9EU,0x8DU,0x32U,0x88U,0x26U,0x1AU,0x3FU,0x61U,0xE8U,0x55U,0x2DU,0x16U };
memcpy(Send_Network_Audio.title, "DSVT", 4);
@ -2434,8 +2583,10 @@ void CQnetDVRPTR::Run()
Send_Network_Audio.ctrl = seq_no | 0x40U;
memcpy(Send_Network_Audio.vasd.voice, seq_no ? silsync : silence, 12U);
if (ok) {
if (IS_ENABLED) {
if (ok)
{
if (IS_ENABLED)
{
ToGate.Write(Send_Network_Audio.title, 27);
}
}

File diff suppressed because it is too large Load Diff

@ -35,20 +35,23 @@
#define CALL_SIZE 8
#define MAX_DTMF_BUF 32
using STOREMOTEG2 = struct to_remote_g2_tag {
using STOREMOTEG2 = struct to_remote_g2_tag
{
unsigned short streamid;
CSockAddress toDstar;
time_t last_time;
};
using STOREPEATER = struct torepeater_tag {
using STOREPEATER = struct torepeater_tag
{
// help with header re-generation
SDSVT saved_hdr; // repeater format
time_t last_time;
unsigned char sequence;
};
using SBANDTXT = struct band_txt_tag {
using SBANDTXT = struct band_txt_tag
{
unsigned short streamID;
unsigned char flags[3];
std::string mycall, sfx, urcall, rpt1, rpt2, txt, dest_rptr;
@ -76,7 +79,8 @@ using SBANDTXT = struct band_txt_tag {
}
};
using SSD = struct sd_tag {
using SSD = struct sd_tag
{
unsigned char header[41];
unsigned char message[21];
unsigned char gps[256];

@ -70,19 +70,22 @@ bool CQnetITAP::Initialize(const char *cfgfile)
int CQnetITAP::OpenITAP()
{
int fd = open(ITAP_DEVICE.c_str(), O_RDWR | O_NOCTTY | O_NDELAY, 0);
if (fd < 0) {
if (fd < 0)
{
printf("Failed to open device [%s], error=%d, message=%s\n", ITAP_DEVICE.c_str(), errno, strerror(errno));
return -1;
}
if (isatty(fd) == 0) {
if (isatty(fd) == 0)
{
printf("Device %s is not a tty device\n", ITAP_DEVICE.c_str());
close(fd);
return -1;
}
static termios t;
if (tcgetattr(fd, &t) < 0) {
if (tcgetattr(fd, &t) < 0)
{
printf("tcgetattr failed for %s, error=%d, message-%s\n", ITAP_DEVICE.c_str(), errno, strerror(errno));
close(fd);
return -1;
@ -99,7 +102,8 @@ int CQnetITAP::OpenITAP()
cfsetospeed(&t, B38400);
cfsetispeed(&t, B38400);
if (tcsetattr(fd, TCSANOW, &t) < 0) {
if (tcsetattr(fd, TCSANOW, &t) < 0)
{
printf("tcsetattr failed for %s, error=%dm message=%s\n", ITAP_DEVICE.c_str(), errno, strerror(errno));
close(fd);
return -1;
@ -111,13 +115,15 @@ int CQnetITAP::OpenITAP()
void CQnetITAP::DumpSerialPacket(const char *title, const unsigned char *buf)
{
printf("%s: ", title);
if (buf[0] > 41) {
if (buf[0] > 41)
{
printf("UNKNOWN: length=%u", (unsigned)buf[0]);
return;
}
SITAP itap;
memcpy(&itap, buf, buf[0]);
switch (itap.type) {
switch (itap.type)
{
case 0x03U: //pong
printf("Pong\n");
break;
@ -150,7 +156,8 @@ REPLY_TYPE CQnetITAP::GetITAPData(unsigned char *buf)
// Get the buffer size or nothing at all
int ret = read(serfd, buf, 1U);
if (ret < 0) {
if (ret < 0)
{
printf("Error when reading first byte from the Icom radio %d: %s", errno, strerror(errno));
return RT_ERROR;
}
@ -163,17 +170,20 @@ REPLY_TYPE CQnetITAP::GetITAPData(unsigned char *buf)
unsigned int length = buf[0U];
if (length >= 100U) {
if (length >= 100U)
{
printf("Invalid data received from the Icom radio, length=%d\n", length);
return RT_ERROR;
}
unsigned int offset = 1U;
while (offset < length) {
while (offset < length)
{
ret = read(serfd, buf + offset, length - offset);
if (ret<0 && errno!=EAGAIN) {
if (ret<0 && errno!=EAGAIN)
{
printf("Error when reading buffer from the Icom radio %d: %s\n", errno, strerror(errno));
return RT_ERROR;
}
@ -182,7 +192,8 @@ REPLY_TYPE CQnetITAP::GetITAPData(unsigned char *buf)
offset += ret;
}
switch (buf[1U]) {
switch (buf[1U])
{
case 0x03U:
return RT_PONG;
case 0x10U:
@ -220,7 +231,8 @@ void CQnetITAP::Run(const char *cfgfile)
double pingtime = 0.001;
const double ackwait = AP_MODE ? 0.4 : 0.06;
while (keep_running) {
while (keep_running)
{
fd_set readfds;
FD_ZERO(&readfds);
@ -235,24 +247,30 @@ void CQnetITAP::Run(const char *cfgfile)
// don't care about writefds and exceptfds:
// and we'll wait for 5 ms
int ret = select(maxfs+1, &readfds, NULL, NULL, &tv);
if (ret < 0) {
if (ret < 0)
{
printf("ERROR: Run: select returned err=%d, %s\n", errno, strerror(errno));
break;
}
// check for a dead or disconnected radio
if (10.0 < lastdataTimer.time()) {
if (10.0 < lastdataTimer.time())
{
printf("no activity from radio for 10 sec. Exiting...\n");
break;
}
if (pingTimer.time() >= pingtime) {
if (poll_counter < 18 ) {
if (pingTimer.time() >= pingtime)
{
if (poll_counter < 18 )
{
const unsigned char poll[2] = { 0xffu, 0xffu };
SendTo(poll);
if (poll_counter == 17)
pingtime = 1.0;
} else {
}
else
{
const unsigned char ping[2] = { 0x02u, 0x02u };
SendTo(ping);
}
@ -262,8 +280,10 @@ void CQnetITAP::Run(const char *cfgfile)
unsigned char buf[100];
if (keep_running && FD_ISSET(serfd, &readfds)) { // there is something to read!
switch (GetITAPData(buf)) {
if (keep_running && FD_ISSET(serfd, &readfds)) // there is something to read!
{
switch (GetITAPData(buf))
{
case RT_ERROR:
keep_running = false;
break;
@ -287,30 +307,39 @@ void CQnetITAP::Run(const char *cfgfile)
lastdataTimer.start();
break;
case RT_PONG:
if (! is_alive) {
if (LOG_DEBUG) {
if (! is_alive)
{
if (LOG_DEBUG)
{
auto count = queue.size();
if (count)
printf("%u packets in queue. Icom radio is connected.", (unsigned int)count);
} else
}
else
printf("Icom Radio is connected.\n");
is_alive = true;
}
lastdataTimer.start();
break;
case RT_HEADER_ACK:
if (acknowledged) {
if (acknowledged)
{
fprintf(stderr, "ERROR: Header already acknowledged!\n");
} else {
}
else
{
if (0x0U == buf[2])
acknowledged = true;
}
lastdataTimer.start();
break;
case RT_DATA_ACK:
if (acknowledged) {
if (acknowledged)
{
fprintf(stderr, "ERROR: voice frame %d already acknowledged!\n", (int)buf[2]);
} else {
}
else
{
if (0x0U == buf[3])
acknowledged = true;
}
@ -326,15 +355,18 @@ void CQnetITAP::Run(const char *cfgfile)
FD_CLR(serfd, &readfds);
}
if (keep_running && FD_ISSET(ug2m, &readfds)) {
if (keep_running && FD_ISSET(ug2m, &readfds))
{
ssize_t len = ToGate.Read(buf, 100);
if (len < 0) {
if (len < 0)
{
printf("ERROR: Run: recvfrom(gsock) returned error %d, %s\n", errno, strerror(errno));
break;
}
if (0 == memcmp(buf, "DSVT", 4)) {
if (0 == memcmp(buf, "DSVT", 4))
{
//printf("read %d bytes from QnetGateway\n", (int)len);
if (ProcessGateway(len, buf))
break;
@ -343,10 +375,14 @@ void CQnetITAP::Run(const char *cfgfile)
}
// send queued frames
if (keep_running) {
if (acknowledged) {
if (is_alive) {
if (! queue.empty()) {
if (keep_running)
{
if (acknowledged)
{
if (is_alive)
{
if (! queue.empty())
{
CFrame frame = queue.front();
queue.pop();
SendTo(frame.data());
@ -354,8 +390,11 @@ void CQnetITAP::Run(const char *cfgfile)
acknowledged = false;
}
}
} else { // we are waiting on an acknowledgement
if (ackTimer.time() >= ackwait) {
}
else // we are waiting on an acknowledgement
{
if (ackTimer.time() >= ackwait)
{
fprintf(stderr, "Icom failure suspected, restarting...\n");
close(serfd);
poll_counter = 0;
@ -365,9 +404,12 @@ void CQnetITAP::Run(const char *cfgfile)
lastdataTimer.start();
pingTimer.start();
serfd = OpenITAP();
if (serfd < 0) {
if (serfd < 0)
{
keep_running = false;
} else {
}
else
{
while (! queue.empty())
queue.pop();
}
@ -386,10 +428,13 @@ int CQnetITAP::SendTo(const unsigned char *buf)
unsigned int ptr = 0;
unsigned int length = (0xffu == buf[0]) ? 2 : buf[0];
while (ptr < length) {
while (ptr < length)
{
n = write(serfd, buf + ptr, length - ptr);
if (n < 0) {
if (EAGAIN != errno) {
if (n < 0)
{
if (EAGAIN != errno)
{
printf("Error %d writing to dvap, message=%s\n", errno, strerror(errno));
return -1;
}
@ -398,11 +443,14 @@ int CQnetITAP::SendTo(const unsigned char *buf)
}
n = 0; // send an ending 0xffu
while (0 == n) {
while (0 == n)
{
const unsigned char push = 0xffu;
n = write(serfd, &push, 1);
if (n < 0) {
if (EAGAIN != errno) {
if (n < 0)
{
if (EAGAIN != errno)
{
printf("Error %d writing to dvap, message=%s\n", errno, strerror(errno));
return -1;
}
@ -415,20 +463,25 @@ int CQnetITAP::SendTo(const unsigned char *buf)
bool CQnetITAP::ProcessGateway(const int len, const unsigned char *raw)
{
static unsigned char counter = 0;
if (27==len || 56==len) { //here is dstar data
if (27==len || 56==len) //here is dstar data
{
SDSVT dsvt;
memcpy(dsvt.title, raw, len); // transfer raw data to SDSVT struct
SITAP itap; // destination
if (56 == len) { // write a Header packet
if (56 == len) // write a Header packet
{
counter = 0;
itap.length = 41U;
itap.type = 0x20;
memcpy(itap.header.flag, dsvt.hdr.flag, 3);
if (RPTR_MOD == dsvt.hdr.rpt2[7]) {
if (RPTR_MOD == dsvt.hdr.rpt2[7])
{
memcpy(itap.header.r1, dsvt.hdr.rpt2, 8);
memcpy(itap.header.r2, dsvt.hdr.rpt1, 8);
} else {
}
else
{
memcpy(itap.header.r1, dsvt.hdr.rpt1, 8);
memcpy(itap.header.r2, dsvt.hdr.rpt2, 8);
}
@ -437,7 +490,9 @@ bool CQnetITAP::ProcessGateway(const int len, const unsigned char *raw)
memcpy(itap.header.nm, dsvt.hdr.sfx, 4);
if (LOG_QSO)
printf("Queued ITAP to %s ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", ITAP_DEVICE.c_str(), itap.header.ur, itap.header.r1, itap.header.r2, itap.header.my, itap.header.nm);
} else { // write an AMBE packet
}
else // write an AMBE packet
{
itap.length = 16U;
itap.type = 0x22U;
itap.voice.counter = counter++;
@ -450,7 +505,8 @@ bool CQnetITAP::ProcessGateway(const int len, const unsigned char *raw)
}
queue.push(CFrame(&itap.length));
} else
}
else
printf("DEBUG: ProcessGateway: unusual packet size read len=%d\n", len);
return false;
}
@ -477,19 +533,22 @@ bool CQnetITAP::ProcessITAP(const unsigned char *buf)
dsvt.flagb[2] = ('B'==RPTR_MOD) ? 0x1 : (('C'==RPTR_MOD) ? 0x2 : 0x3);
dsvt.streamid = htons(stream_id);
if (41 == len) { // header
if (41 == len) // header
{
dsvt.ctrl = 0x80;
memcpy(dsvt.hdr.flag, itap.header.flag, 3);
////////////////// Terminal or Access /////////////////////////
if (0 == memcmp(itap.header.r1, "DIRECT", 6)) {
if (0 == memcmp(itap.header.r1, "DIRECT", 6))
{
// Terminal Mode!
memcpy(dsvt.hdr.rpt1, RPTR.c_str(), 7); // build r1
dsvt.hdr.rpt1[7] = RPTR_MOD; // with module
memcpy(dsvt.hdr.rpt2, RPTR.c_str(), 7); // build r2
dsvt.hdr.rpt2[7] = 'G'; // with gateway
if (' '==itap.header.ur[2] && ' '!=itap.header.ur[0]) {
if (' '==itap.header.ur[2] && ' '!=itap.header.ur[0])
{
// it's a command because it has as space in the 3rd position, we have to right-justify it!
// Terminal Mode left justifies short commands.
memset(dsvt.hdr.urcall, ' ', 8); // first file ur with spaces
@ -497,9 +556,12 @@ bool CQnetITAP::ProcessITAP(const unsigned char *buf)
dsvt.hdr.urcall[7] = itap.header.ur[0]; // one char command, like "E" or "I"
else
memcpy(dsvt.hdr.urcall+6, itap.header.ur, 2); // two char command, like "HX" or "S0"
} else
}
else
memcpy(dsvt.hdr.urcall, itap.header.ur, 8); // ur is at least 3 chars
} else {
}
else
{
// Access Point Mode
memcpy(dsvt.hdr.rpt1, itap.header.r1, 8);
memcpy(dsvt.hdr.rpt2, itap.header.r2, 8);
@ -510,16 +572,20 @@ bool CQnetITAP::ProcessITAP(const unsigned char *buf)
memcpy(dsvt.hdr.mycall, itap.header.my, 8);
memcpy(dsvt.hdr.sfx, itap.header.nm, 4);
calcPFCS(dsvt.hdr.flag, dsvt.hdr.pfcs);
if (ToGate.Write(dsvt.title, 56)) {
if (ToGate.Write(dsvt.title, 56))
{
printf("ERROR: ProcessITAP: Could not write gateway header packet\n");
return true;
}
if (LOG_QSO)
printf("Sent DSVT to gateway, streamid=%04x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", ntohs(dsvt.streamid), dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2, dsvt.hdr.mycall, dsvt.hdr.sfx);
} else if (16 == len) { // ambe
}
else if (16 == len) // ambe
{
dsvt.ctrl = itap.voice.sequence;
memcpy(dsvt.vasd.voice, itap.voice.ambe, 12);
if (ToGate.Write(dsvt.title, 27)) {
if (ToGate.Write(dsvt.title, 27))
{
printf("ERROR: ProcessMMDVM: Could not write gateway voice packet\n");
return true;
}
@ -542,12 +608,15 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
const std::string estr; // an empty string
std::string type;
std::string itap_path("module_");
if (0 > assigned_module) {
if (0 > assigned_module)
{
// we need to find the lone itap module
for (int i=0; i<3; i++) {
for (int i=0; i<3; i++)
{
std::string test(itap_path);
test.append(1, 'a'+i);
if (cfg.KeyExists(test)) {
if (cfg.KeyExists(test))
{
cfg.GetValue(test, estr, type, 1, 16);
if (type.compare("itap"))
continue; // this ain't it!
@ -556,20 +625,27 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
break;
}
}
if (0 > assigned_module) {
if (0 > assigned_module)
{
fprintf(stderr, "Error: no 'itap' module found\n!");
return true;
}
} else {
}
else
{
// make sure itap module is defined
itap_path.append(1, 'a' + assigned_module);
if (cfg.KeyExists(itap_path)) {
if (cfg.KeyExists(itap_path))
{
cfg.GetValue(itap_path, estr, type, 1, 16);
if (type.compare("itap")) {
if (type.compare("itap"))
{
fprintf(stderr, "%s = %s is not 'itap' type!\n", itap_path.c_str(), type.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
return true;
}
@ -580,22 +656,30 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
cfg.GetValue(itap_path+"_ap_mode", type, AP_MODE);
itap_path.append("_callsign");
if (cfg.KeyExists(itap_path)) {
if (cfg.KeyExists(itap_path))
{
if (cfg.GetValue(itap_path, type, RPTR, 3, 6))
return true;
} else {
}
else
{
itap_path.assign("ircddb_login");
if (cfg.KeyExists(itap_path)) {
if (cfg.KeyExists(itap_path))
{
if (cfg.GetValue(itap_path, estr, RPTR, 3, 6))
return true;
}
}
int l = RPTR.length();
if (l<3 || l>6) {
if (l<3 || l>6)
{
printf("Call '%s' is invalid length!\n", RPTR.c_str());
return true;
} else {
for (int i=0; i<l; i++) {
}
else
{
for (int i=0; i<l; i++)
{
if (islower(RPTR[i]))
RPTR[i] = toupper(RPTR[i]);
}
@ -612,7 +696,8 @@ void CQnetITAP::calcPFCS(const unsigned char *packet, unsigned char *pfcs)
{
unsigned short crc_dstar_ffff = 0xffff;
unsigned short tmp, short_c;
unsigned short crc_tabccitt[256] = {
unsigned short crc_tabccitt[256] =
{
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
@ -631,7 +716,8 @@ void CQnetITAP::calcPFCS(const unsigned char *packet, unsigned char *pfcs)
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
};
for (int i = 0; i < 39 ; i++) {
for (int i = 0; i < 39 ; i++)
{
short_c = 0x00ff & (unsigned short)packet[i];
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
@ -648,12 +734,14 @@ void CQnetITAP::calcPFCS(const unsigned char *packet, unsigned char *pfcs)
int main(int argc, const char **argv)
{
setbuf(stdout, NULL);
if (2 != argc) {
if (2 != argc)
{
fprintf(stderr, "usage: %s path_to_config_file\n", argv[0]);
return 1;
}
if ('-' == argv[1][0]) {
if ('-' == argv[1][0])
{
printf("\nQnetITAP Version #%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", ITAP_VERSION);
printf("QnetITAP comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
@ -661,14 +749,16 @@ int main(int argc, const char **argv)
}
const char *qn = strstr(argv[0], "qnitap");
if (NULL == qn) {
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qnitap' in %s!\n", argv[0]);
return 1;
}
qn += 6;
int assigned_module;
switch (*qn) {
switch (*qn)
{
case NULL:
assigned_module = -1;
break;

@ -31,7 +31,8 @@
#define CALL_SIZE 8
#define IP_SIZE 15
enum REPLY_TYPE {
enum REPLY_TYPE
{
RT_TIMEOUT,
RT_ERROR,
RT_UNKNOWN,
@ -44,7 +45,8 @@ enum REPLY_TYPE {
// Icom Terminal and Access Point Mode data structure
#pragma pack(push, 1)
using SITAP = struct itap_tag {
using SITAP = struct itap_tag
{
unsigned char length;
// 41 for header
// 16 for voice
@ -58,8 +60,10 @@ using SITAP = struct itap_tag {
// 0x21U header acknowledgment
// 0x22U data to icom
// 0x23U data acknowledgment
union {
struct {
union
{
struct
{
unsigned char flag[3];
unsigned char r2[8];
unsigned char r1[8];
@ -67,7 +71,8 @@ using SITAP = struct itap_tag {
unsigned char my[8];
unsigned char nm[4];
} header;
struct {
struct
{
unsigned char counter; // ordinal counter is reset with each header
unsigned char sequence; // is modulo 21
unsigned char ambe[9];
@ -80,11 +85,13 @@ using SITAP = struct itap_tag {
class CFrame
{
public:
CFrame(const unsigned char *buf) {
CFrame(const unsigned char *buf)
{
memcpy(&frame.length, buf, buf[0]);
}
CFrame(const CFrame &from) {
CFrame(const CFrame &from)
{
memcpy(&frame.length, from.data(), from.size());
}

File diff suppressed because it is too large Load Diff

@ -43,12 +43,14 @@
#define TIMEOUT 50
#define LH_MAX_SIZE 39
using SREFDSVT = struct refdsvt_tag {
using SREFDSVT = struct refdsvt_tag
{
unsigned char head[2];
SDSVT dsvt;
};
using STOREMOTE = struct to_remote_g2_tag {
using STOREMOTE = struct to_remote_g2_tag
{
char cs[CALL_SIZE + 1];
CSockAddress addr;
char from_mod, to_mod;
@ -60,7 +62,8 @@ using STOREMOTE = struct to_remote_g2_tag {
// This is the data payload in the map: inbound_list
// This is for inbound dongles
using SINBOUND = struct inbound_tag {
using SINBOUND = struct inbound_tag
{
char call[CALL_SIZE + 1]; // the callsign of the remote
CSockAddress addr; // IP and port of remote
short countdown; // if countdown expires, the connection is terminated
@ -68,13 +71,15 @@ using SINBOUND = struct inbound_tag {
char client; // dvap, dvdongle
};
using STRACING = struct tracing_tag {
using STRACING = struct tracing_tag
{
unsigned short streamid;
time_t last_time; // last time RF user talked
};
class CQnetLink : CKRBase {
class CQnetLink : CKRBase
{
public:
// functions
CQnetLink();
@ -129,7 +134,8 @@ private:
STOREMOTE to_remote_g2[3];
// broadcast for data arriving from xrf to local rptr
struct brd_from_xrf_tag {
struct brd_from_xrf_tag
{
unsigned short xrf_streamid; // streamid from xrf
unsigned short rptr_streamid[2]; // generated streamid to rptr(s)
} brd_from_xrf;
@ -137,7 +143,8 @@ private:
short brd_from_xrf_idx;
// broadcast for data arriving from local rptr to xrf
struct brd_from_rptr_tag {
struct brd_from_rptr_tag
{
unsigned short from_rptr_streamid;
unsigned short to_rptr_streamid[2];
} brd_from_rptr;
@ -172,7 +179,8 @@ private:
// END: TEXT crap
// this is used for the "dashboard and qso_details" to avoid processing multiple headers
struct old_sid_tag {
struct old_sid_tag
{
unsigned short sid;
} old_sid[3];
@ -184,29 +192,35 @@ private:
const unsigned char endbytes[6] = { 0x55U, 0x55U, 0x55U, 0x55U, 0xC8U, 0x7AU };
time_t tnow;
unsigned char dcs_seq[3] = { 0x00, 0x00, 0x00 };
struct {
struct
{
char mycall[9];
char sfx[5];
unsigned int dcs_rptr_seq;
} rptr_2_dcs[3] = {
} rptr_2_dcs[3] =
{
{" ", " ", 0},
{" ", " ", 0},
{" ", " ", 0}
};
struct {
struct
{
char mycall[9];
char sfx[5];
unsigned int dcs_rptr_seq;
} ref_2_dcs[3] = {
} ref_2_dcs[3] =
{
{" ", " ", 0},
{" ", " ", 0},
{" ", " ", 0}
};
struct {
struct
{
char mycall[9];
char sfx[5];
unsigned int dcs_rptr_seq;
} xrf_2_dcs[3] = {
} xrf_2_dcs[3] =
{
{" ", " ", 0},
{" ", " ", 0},
{" ", " ", 0}

@ -84,7 +84,8 @@ bool CQnetModem::GetBufferSize()
{
std::this_thread::sleep_for(std::chrono::seconds(2));
for (int i=0; i<6; i++) {
for (int i=0; i<6; i++)
{
SMODEM frame;
frame.start = FRAME_START;
@ -94,10 +95,12 @@ bool CQnetModem::GetBufferSize()
if (3 != SendToModem(&frame.start))
return true;
for (int count = 0; count < MAX_RESPONSES; count++) {
for (int count = 0; count < MAX_RESPONSES; count++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
EModemResponse resp = GetModemData(&frame.start, sizeof(SVERSION));
if (resp == EModemResponse::status) {
if (resp == EModemResponse::status)
{
dstarSpace = frame.status.dsrsize;
printf("D-Star buffer will hold %u voice frames\n", dstarSpace);
return false;
@ -114,7 +117,8 @@ bool CQnetModem::GetVersion()
{
std::this_thread::sleep_for(std::chrono::seconds(2));
for (int i=0; i<6; i++) {
for (int i=0; i<6; i++)
{
SVERSION frame;
frame.start = FRAME_START;
@ -124,10 +128,12 @@ bool CQnetModem::GetVersion()
if (3 != SendToModem(&frame.start))
return true;
for (int count = 0; count < MAX_RESPONSES; count++) {
for (int count = 0; count < MAX_RESPONSES; count++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
EModemResponse resp = GetModemData(&frame.start, sizeof(SVERSION));
if (resp == EModemResponse::version && frame.length > 14U) {
if (resp == EModemResponse::version && frame.length > 14U)
{
frame.version[frame.length-4U] = '\0'; // just to make sure!
if (0 == memcmp(frame.version, "MMDVM ", 6U))
hardwareType = EHardwareType::mmdvm;
@ -145,7 +151,8 @@ bool CQnetModem::GetVersion()
hardwareType = EHardwareType::nano_dv;
else if (0 == memcmp(frame.version, "MMDVM_HS-", 9U))
hardwareType = EHardwareType::mmdvm_hs;
else {
else
{
hardwareType = EHardwareType::unknown;
}
@ -170,7 +177,8 @@ bool CQnetModem::SetFrequency()
if (hardwareType == EHardwareType::dvmega)
frame.length = 12U;
else {
else
{
frame.frequency.level = 255U;
frame.frequency.ps = __builtin_bswap32(htonl(pocsagFrequency));
@ -188,10 +196,12 @@ bool CQnetModem::SetFrequency()
int count = 0;
bool got_ack = false;
while (! got_ack) {
while (! got_ack)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
switch (GetModemData(&frame.start, sizeof(SMODEM))) {
switch (GetModemData(&frame.start, sizeof(SMODEM)))
{
case EModemResponse::ack:
got_ack = true;
break;
@ -199,7 +209,8 @@ bool CQnetModem::SetFrequency()
fprintf(stderr, "SET_FREQ failed, returned NACK reason %u\n", frame.nack.reason);
return true;
default:
if (++count >= MAX_RESPONSES) {
if (++count >= MAX_RESPONSES)
{
fprintf(stderr, "The MMDVM is not responding to the SET_FREQ command!\n");
return true;
}
@ -271,10 +282,12 @@ bool CQnetModem::SetConfiguration()
int count = 0;
bool got_ack = false;
while (! got_ack) {
while (! got_ack)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
switch (GetModemData(&frame.start, sizeof(SMODEM))) {
switch (GetModemData(&frame.start, sizeof(SMODEM)))
{
case EModemResponse::ack:
got_ack = true;
break;
@ -282,7 +295,8 @@ bool CQnetModem::SetConfiguration()
fprintf(stderr, "SET_CONFIG failed, returned NACK reason %u\n", frame.nack.reason);
return true;
default:
if (++count >= MAX_RESPONSES) {
if (++count >= MAX_RESPONSES)
{
fprintf(stderr, "The MMDVM is not responding to the SET_CONFIG command!\n");
return true;
}
@ -296,19 +310,22 @@ bool CQnetModem::SetConfiguration()
int CQnetModem::OpenModem()
{
int fd = open(MODEM_DEVICE.c_str(), O_RDWR | O_NOCTTY | O_SYNC, 0);
if (fd < 0) {
if (fd < 0)
{
printf("Failed to open device [%s], error=%d, message=%s\n", MODEM_DEVICE.c_str(), errno, strerror(errno));
return -1;
}
if (isatty(fd) == 0) {
if (isatty(fd) == 0)
{
printf("Device %s is not a tty device\n", MODEM_DEVICE.c_str());
close(fd);
return -1;
}
static termios t;
if (tcgetattr(fd, &t) < 0) {
if (tcgetattr(fd, &t) < 0)
{
printf("tcgetattr failed for %s, error=%d, message-%s\n", MODEM_DEVICE.c_str(), errno, strerror(errno));
close(fd);
return -1;
@ -325,7 +342,8 @@ int CQnetModem::OpenModem()
cfsetospeed(&t, B115200);
cfsetispeed(&t, B115200);
if (tcsetattr(fd, TCSANOW, &t) < 0) {
if (tcsetattr(fd, TCSANOW, &t) < 0)
{
printf("tcsetattr failed for %s, error=%dm message=%s\n", MODEM_DEVICE.c_str(), errno, strerror(errno));
close(fd);
return -1;
@ -336,28 +354,36 @@ int CQnetModem::OpenModem()
EModemResponse CQnetModem::GetModemData(unsigned char *buf, unsigned int size)
{
if (size < 4U) {
if (size < 4U)
{
fprintf(stderr, "Buffer size, %u is too small\n", size);
return EModemResponse::error;
}
// Get the start byte
int ret = read(serfd, buf, 1U);
if (ret < 0) {
if (ret < 0)
{
fprintf(stderr, "Error when reading frame start byte: %s\n", strerror(errno));
return EModemResponse::error;
} else if (ret == 0) {
}
else if (ret == 0)
{
printf("READ START RETURNED A ZERO!\n");
return EModemResponse::timeout;
} else if (buf[0] != FRAME_START)
}
else if (buf[0] != FRAME_START)
return EModemResponse::timeout;
//get the length byte
ret = read(serfd, buf+1, 1U);
if (ret < 0) {
if (ret < 0)
{
fprintf(stderr, "Error when reading frame length: %s\n", strerror(errno));
return EModemResponse::error;
} else if (ret == 0) {
}
else if (ret == 0)
{
printf("READ LENGTH RETURNED A ZERO!\n");
return(EModemResponse::timeout);
}
@ -366,44 +392,58 @@ EModemResponse CQnetModem::GetModemData(unsigned char *buf, unsigned int size)
// get the type byte
ret = read(serfd, buf+2, 1U);
if (ret < 0) {
if (ret < 0)
{
fprintf(stderr, "Error when reading frame type: %s\n", strerror(errno));
return EModemResponse::error;
} else if (ret == 0) {
}
else if (ret == 0)
{
printf("READ TYPE RETURNED A ZERO!\n");
return(EModemResponse::timeout);
}
// get the data
unsigned int length = buf[1];
unsigned int offset = 3;
while (offset < length) {
while (offset < length)
{
ret = read(serfd, buf + offset, length - offset);
if (ret < 0) {
if (ret < 0)
{
printf("Error when reading data: %s\n", strerror(errno));
return EModemResponse::error;
}
if (ret == 0) {
if (ret == 0)
{
printf("READ DATA RETURNED A ZERO!\n");
return(EModemResponse::timeout);
} else
}
else
offset += ret;
}
while (junk_count) {
while (junk_count)
{
unsigned char junk[8];
ret = read(serfd, junk, (junk_count > 8U) ? 8U : junk_count);
if (ret < 0) {
if (ret < 0)
{
printf("Error when reading junk: %s\n", strerror(errno));
return EModemResponse::error;
} else if (ret == 0) {
}
else if (ret == 0)
{
printf("READ junk RETURNED A ZERO!\n");
return(EModemResponse::timeout);
} else {
}
else
{
junk_count -= (unsigned int)ret;
}
}
switch (buf[2]) {
switch (buf[2])
{
case TYPE_ACK:
return EModemResponse::ack;
case TYPE_NACK:
@ -438,7 +478,8 @@ void CQnetModem::Run(const char *cfgfile)
CTimer statusTimer;
CTimer deadTimer;
while (keep_running) {
while (keep_running)
{
SMODEM frame;
frame.start = FRAME_START;
@ -454,20 +495,24 @@ void CQnetModem::Run(const char *cfgfile)
// don't care about writefds and exceptfds:
int ret = select(maxfs+1, &readfds, NULL, NULL, &tv);
if (ret < 0) {
if (ret < 0)
{
printf("ERROR: Run: select returned err=%d, %s\n", errno, strerror(errno));
break;
}
// check for a dead or disconnected radio
if (10.0 < deadTimer.time()) {
if (10.0 < deadTimer.time())
{
printf("no activity from radio for 10 sec. Exiting...\n");
keep_running = false;
}
if (keep_running && FD_ISSET(serfd, &readfds)) {
if (keep_running && FD_ISSET(serfd, &readfds))
{
deadTimer.start();
switch (GetModemData(&frame.start, sizeof(SMODEM))) {
switch (GetModemData(&frame.start, sizeof(SMODEM)))
{
case EModemResponse::data:
case EModemResponse::header:
case EModemResponse::eot:
@ -492,17 +537,22 @@ void CQnetModem::Run(const char *cfgfile)
FD_CLR(serfd, &readfds);
}
if (keep_running && FD_ISSET(ug2m, &readfds)) {
if (keep_running && FD_ISSET(ug2m, &readfds))
{
SDSVT dsvt;
ssize_t len = ToGate.Read(dsvt.title, sizeof(SDSVT));
if (len <= 0) {
if (len <= 0)
{
break;
}
if (0 == memcmp(dsvt.title, "DSVT", 4) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U) && (len==56 || len==27)) {
if (0 == memcmp(dsvt.title, "DSVT", 4) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U) && (len==56 || len==27))
{
ProcessGateway(dsvt);
} else {
}
else
{
fprintf(stderr, "Unexpected data, returned %d bytes from the gateway: %02x", int(len), *dsvt.title);
for (ssize_t i=1; i<len; i++)
fprintf(stderr, " %02x", *(dsvt.title + int(i)));
@ -512,7 +562,8 @@ void CQnetModem::Run(const char *cfgfile)
FD_CLR(ug2m, &readfds);
}
if (keep_running) {
if (keep_running)
{
//if (g2_is_active && PacketWait.time() > packet_wait) {
// // g2 has timed out
// frame.length = 3U;
@ -520,17 +571,20 @@ void CQnetModem::Run(const char *cfgfile)
// queue.push(CFrame(&frame.start));
// g2_is_active = false;
//}
if (! queue.empty()) {
if (! queue.empty())
{
// send queued D-Star frames to modem
CFrame cframe = queue.front();
const unsigned char type = cframe.type();
if ((type==TYPE_HEADER && dstarSpace>3U) || ((type==TYPE_DATA || type==TYPE_EOT || type==TYPE_LOST) && dstarSpace>0U)) {
if ((type==TYPE_HEADER && dstarSpace>3U) || ((type==TYPE_DATA || type==TYPE_EOT || type==TYPE_LOST) && dstarSpace>0U))
{
SendToModem(cframe.data());
queue.pop();
dstarSpace -= (type==TYPE_HEADER) ? 4U : 1U;
}
}
if (statusTimer.time() > 0.25) {
if (statusTimer.time() > 0.25)
{
// request a status update every 250 milliseconds
frame.length = 3U;
frame.type = TYPE_STATUS;
@ -550,10 +604,13 @@ int CQnetModem::SendToModem(const unsigned char *buf)
size_t sent = 0;
ssize_t length = buf[1];
while ((ssize_t)sent < length) {
while ((ssize_t)sent < length)
{
n = write(serfd, buf + sent, length - sent);
if (n < 0) {
if (EAGAIN != errno) {
if (n < 0)
{
if (EAGAIN != errno)
{
printf("Error %d writing to dvap, message=%s\n", errno, strerror(errno));
return -1;
}
@ -569,7 +626,8 @@ void CQnetModem::ProcessGateway(const SDSVT &dsvt)
static std::string superframe;
SMODEM frame; // destination
frame.start = FRAME_START;
if (0x10U == dsvt.config) { // write a Header packet
if (0x10U == dsvt.config) // write a Header packet
{
superframe.clear();
frame.length = 44U;
frame.type = TYPE_HEADER;
@ -584,29 +642,39 @@ void CQnetModem::ProcessGateway(const SDSVT &dsvt)
PacketWait.start();
if (LOG_QSO)
printf("Queued to %s flags=%02x:%02x:%02x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", MODEM_DEVICE.c_str(), frame.header.flag[0], frame.header.flag[1], frame.header.flag[2], frame.header.ur, frame.header.r2, frame.header.r1, frame.header.my, frame.header.nm);
} else { // write a voice data packet
}
else // write a voice data packet
{
//const unsigned char sdsync[3] = { 0x55U, 0x2DU, 0x16U };
if (dsvt.ctrl & 0x40U) {
if (dsvt.ctrl & 0x40U)
{
if (LOG_DEBUG && superframe.size())
printf("Final order: %s\n", superframe.c_str());
frame.length = 3U;
frame.type = TYPE_EOT;
if (LOG_QSO)
printf("Queued modem end of transmission\n");
} else {
}
else
{
frame.length = 15U;
frame.type = TYPE_DATA;
memcpy(frame.voice.ambe, dsvt.vasd.voice, 12);
if (LOG_DEBUG) {
if (LOG_DEBUG)
{
const unsigned int ctrl = dsvt.ctrl & 0x3FU;
if (VoicePacketIsSync(dsvt.vasd.text)) {
if (superframe.size() > 65) {
if (VoicePacketIsSync(dsvt.vasd.text))
{
if (superframe.size() > 65)
{
printf("Frame order: %s\n", superframe.c_str());
superframe.clear();
}
const char *ch = "#abcdefghijklmnopqrstuvwxyz";
superframe.append(1, (ctrl<27U) ? ch[ctrl] : '%');
} else {
}
else
{
const char *ch = "!ABCDEFGHIJKLMNOPQRSTUVWXYZ";
superframe.append(1, (ctrl<27U) ? ch[ctrl] : '*');
}
@ -638,7 +706,8 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
dsvt.flagb[2] = ('B'==RPTR_MOD) ? 0x1U : (('C'==RPTR_MOD) ? 0x2U : 0x3U);
dsvt.streamid = htons(stream_id);
if (frame.type == TYPE_HEADER) { // header
if (frame.type == TYPE_HEADER) // header
{
nextctrl = 21U;
in_stream = first_voice_packet = true;
dsvt.config = 0x10U;
@ -653,20 +722,26 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
memcpy(dsvt.hdr.mycall, frame.header.my, 8);
memcpy(dsvt.hdr.sfx, frame.header.nm, 4);
memcpy(dsvt.hdr.pfcs, frame.header.pfcs, 2);
if (ToGate.Write(dsvt.title, 56)) {
if (ToGate.Write(dsvt.title, 56))
{
printf("ERROR: ProcessModem: Could not write gateway header packet\n");
return true;
}
if (LOG_QSO)
printf("Sent DSVT to gateway, streamid=%04x flags=%02x:%02x:%02x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", ntohs(dsvt.streamid), dsvt.hdr.flag[0], dsvt.hdr.flag[1], dsvt.hdr.flag[2], dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2, dsvt.hdr.mycall, dsvt.hdr.sfx);
} else if (in_stream && (frame.type==TYPE_DATA || frame.type==TYPE_EOT || frame.type==TYPE_LOST)) { // ambe
}
else if (in_stream && (frame.type==TYPE_DATA || frame.type==TYPE_EOT || frame.type==TYPE_LOST)) // ambe
{
const unsigned char sync[12] = { 0x9EU,0x8DU,0x32U,0x88U,0x26U,0x1AU,0x3FU,0x61U,0xE8U,0x55U,0x2DU,0x16U };
const unsigned char silence[12] = { 0x9EU,0x8DU,0x32U,0x88U,0x26U,0x1AU,0x3FU,0x61U,0xE8U,0x70U,0x4FU,0x93U };
dsvt.config = 0x20U;
if (frame.type == TYPE_DATA) {
if (frame.type == TYPE_DATA)
{
if (first_voice_packet) { // make sure the first voice packet is a sync frame
if (! VoicePacketIsSync(frame.voice.text)) { // create a quite sync voice packet
if (first_voice_packet) // make sure the first voice packet is a sync frame
{
if (! VoicePacketIsSync(frame.voice.text)) // create a quite sync voice packet
{
if (LOG_DEBUG)
printf("Warning: Inserting missing frame sync after header\n");
dsvt.ctrl = 0U;
@ -677,18 +752,21 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
first_voice_packet = false;
}
if (VoicePacketIsSync(frame.voice.text)) {
if (VoicePacketIsSync(frame.voice.text))
{
if (nextctrl < 21U)
fprintf(stderr, "Warning: The last superframe had %u frames, inserting missing frame(s)\n", nextctrl);
memcpy(dsvt.vasd.voice, silence, 12U);
while (nextctrl < 21U) {
while (nextctrl < 21U)
{
dsvt.ctrl = nextctrl++;
ToGate.Write(dsvt.title, 27);
}
nextctrl = 0x0U;
}
if (nextctrl > 20U) {
if (nextctrl > 20U)
{
fprintf(stderr, "Warning: nextctrl=%u, inserting missing sync frame\n", nextctrl);
dsvt.ctrl = 0U;
memcpy(dsvt.vasd.voice, sync, 12U);
@ -697,16 +775,22 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
}
memcpy(dsvt.vasd.voice, frame.voice.ambe, 12);
} else {
}
else
{
if (frame.type == TYPE_LOST)
printf("Got a TYPE_LOST packet.\n");
if (0U == nextctrl) {
if (0U == nextctrl)
{
memcpy(dsvt.vasd.voice, sync, 12);
} else {
}
else
{
memcpy(dsvt.vasd.voice, silence, 12);
}
nextctrl |= 0x40U;
if (LOG_QSO) {
if (LOG_QSO)
{
if (frame.type == TYPE_EOT)
printf("Sent DSVT end of streamid=%04x\n", ntohs(dsvt.streamid));
else
@ -715,13 +799,17 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
in_stream = false;
}
dsvt.ctrl = nextctrl++;
if (ToGate.Write(dsvt.title, 27)) {
if (ToGate.Write(dsvt.title, 27))
{
printf("ERROR: ProcessModem: Could not write gateway voice packet\n");
return true;
}
} else {
if (in_stream) {
}
else
{
if (in_stream)
{
fprintf(stderr, "Warning! Unexpected frame: %02x", frame.start);
for (unsigned int i=1U; i<frame.length; i++)
fprintf(stderr, ":%02x", *(&frame.start + i));
@ -743,12 +831,15 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
const std::string estr; // an empty string
std::string type;
std::string modem_path("module_");
if (0 > assigned_module) {
if (0 > assigned_module)
{
// we need to find the lone mmdvmmodem module
for (int i=0; i<3; i++) {
for (int i=0; i<3; i++)
{
std::string test(modem_path);
test.append(1, 'a'+i);
if (cfg.KeyExists(test)) {
if (cfg.KeyExists(test))
{
cfg.GetValue(test, estr, type, 1, 16);
if (type.compare("mmdvmmodem"))
continue; // this ain't it!
@ -757,20 +848,27 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
break;
}
}
if (0 > assigned_module) {
if (0 > assigned_module)
{
fprintf(stderr, "Error: no 'mmdvmmodem' module found\n!");
return true;
}
} else {
}
else
{
// make sure mmdvmmodem module is defined
modem_path.append(1, 'a' + assigned_module);
if (cfg.KeyExists(modem_path)) {
if (cfg.KeyExists(modem_path))
{
cfg.GetValue(modem_path, estr, type, 1, 16);
if (type.compare("mmdvmmodem")) {
if (type.compare("mmdvmmodem"))
{
fprintf(stderr, "%s = %s is not 'mmdvmmodem' type!\n", modem_path.c_str(), type.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
return true;
}
@ -798,22 +896,30 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
packet_wait = 1.0E-3 * double(PACKET_WAIT);
modem_path.append("_callsign");
if (cfg.KeyExists(modem_path)) {
if (cfg.KeyExists(modem_path))
{
if (cfg.GetValue(modem_path, type, RPTR, 3, 6))
return true;
} else {
}
else
{
modem_path.assign("ircddb_login");
if (cfg.KeyExists(modem_path)) {
if (cfg.KeyExists(modem_path))
{
if (cfg.GetValue(modem_path, estr, RPTR, 3, 6))
return true;
}
}
int l = RPTR.length();
if (l<3 || l>6) {
if (l<3 || l>6)
{
printf("Call '%s' is invalid length!\n", RPTR.c_str());
return true;
} else {
for (int i=0; i<l; i++) {
}
else
{
for (int i=0; i<l; i++)
{
if (islower(RPTR[i]))
RPTR[i] = toupper(RPTR[i]);
}
@ -829,12 +935,14 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
int main(int argc, const char **argv)
{
setbuf(stdout, NULL);
if (2 != argc) {
if (2 != argc)
{
fprintf(stderr, "usage: %s path_to_config_file\n", argv[0]);
return 1;
}
if ('-' == argv[1][0]) {
if ('-' == argv[1][0])
{
printf("\nQnetModem Version %s Copyright (C) 2019 by Thomas A. Early N7TAE\n", MODEM_VERSION);
printf("QnetModem comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\n");
@ -843,14 +951,16 @@ int main(int argc, const char **argv)
}
const char *qn = strstr(argv[0], "qnmodem");
if (NULL == qn) {
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qnmodem' in %s!\n", argv[0]);
return 1;
}
qn += 7;
int assigned_module;
switch (*qn) {
switch (*qn)
{
case NULL:
assigned_module = -1;
break;

@ -32,7 +32,8 @@
#define CALL_SIZE 8
#define IP_SIZE 15
enum class EModemResponse {
enum class EModemResponse
{
ack,
nack,
timeout,
@ -45,7 +46,8 @@ enum class EModemResponse {
version
};
enum class EHardwareType {
enum class EHardwareType
{
mmdvm,
dvmega,
zumspot,
@ -59,7 +61,8 @@ enum class EHardwareType {
// Icom Terminal and Access Point Mode data structure
#pragma pack(push, 1)
using SVERSION = struct version_tag {
using SVERSION = struct version_tag
{
unsigned char start;
unsigned char length;
unsigned char type;
@ -67,7 +70,8 @@ using SVERSION = struct version_tag {
unsigned char version[251];
};
using SMODEM = struct mmodem_tag {
using SMODEM = struct mmodem_tag
{
unsigned char start; // always 0xEOU
unsigned char length; // 3 - 255
unsigned char type;
@ -82,10 +86,12 @@ using SMODEM = struct mmodem_tag {
// 0x11U data
// 0x12U transmission lost
// 0x13U transmission end
union {
union
{
unsigned char ack; // the type being acknowledged
unsigned char mode; // 0 idle, 1 dstar, 2 dmr, 3 ysf, 99 calibration
struct {
struct
{
unsigned char ack; // the type being acknowledged
unsigned char reason; // reason for the NAK
// 1 - invalid command
@ -99,7 +105,8 @@ using SMODEM = struct mmodem_tag {
// unsigned char protocol_version;
// unsigned char version[250];
//} version;
struct {
struct
{
unsigned char modes; // 0x1U dstar | 0x2 dmr | 0x4 system fusion
unsigned char status; // 0 idle, 1 dstar, 2 dmr, 3 system fusion, 99 calibration
unsigned char flags; // 0x1 Tx on, 0x2 adc overflow
@ -108,7 +115,8 @@ using SMODEM = struct mmodem_tag {
unsigned char dm2size; // dmr timeslot 2 buffersize
unsigned char ysfsize; // ysf buffersize
} status;
struct {
struct
{
unsigned char flags; // 0x1 rx 0x2 tx 0x4 ptt 0x8 ysf lodev 0x10 debug 0x80 not duplex
unsigned char mode; // 0x1 dstar 0x2 drm 0x4 ysf 0x8 p25 0x10 nxdx 0x20 pocsag
unsigned char tx_delay; // tx delay in 10 millisecond increments
@ -128,14 +136,16 @@ using SMODEM = struct mmodem_tag {
unsigned char ysf_tx_hang;
unsigned char pocsag_tx;
} config;
struct {
struct
{
unsigned char zero; // should be zero;
uint32_t rx; // receive frequency
uint32_t tx; // transmitter frequency
unsigned char level; // rf level for pocsag?
uint32_t ps; // pocsag frequency, default 433000000U
} frequency;
struct {
struct
{
unsigned char flag[3];
unsigned char r2[8];
unsigned char r1[8];
@ -144,7 +154,8 @@ using SMODEM = struct mmodem_tag {
unsigned char nm[4];
unsigned char pfcs[2];
} header;
struct {
struct
{
unsigned char ambe[9];
unsigned char text[3];
} voice;
@ -155,15 +166,18 @@ using SMODEM = struct mmodem_tag {
class CFrame
{
public:
CFrame(const unsigned char *buf) {
CFrame(const unsigned char *buf)
{
memcpy(&frame.start, buf, buf[1]);
}
CFrame(const CFrame &from) {
CFrame(const CFrame &from)
{
memcpy(&frame.start, from.data(), from.size());
}
CFrame &operator=(const CFrame &from) {
CFrame &operator=(const CFrame &from)
{
memcpy(&frame.start, from.data(), from.size());
return *this;
}

@ -59,13 +59,15 @@ bool CQnetRelay::Initialize(const char *cfgfile)
int CQnetRelay::OpenSocket(const std::string &address, unsigned short port)
{
if (! port) {
if (! port)
{
printf("ERROR: OpenSocket: non-zero port must be specified.\n");
return -1;
}
int fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
if (fd < 0)
{
printf("Cannot create the UDP socket, err: %d, %s\n", errno, strerror(errno));
return -1;
}
@ -76,9 +78,11 @@ int CQnetRelay::OpenSocket(const std::string &address, unsigned short port)
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (! address.empty()) {
if (! address.empty())
{
addr.sin_addr.s_addr = ::inet_addr(address.c_str());
if (addr.sin_addr.s_addr == INADDR_NONE) {
if (addr.sin_addr.s_addr == INADDR_NONE)
{
printf("The local address is invalid - %s\n", address.c_str());
close(fd);
return -1;
@ -86,13 +90,15 @@ int CQnetRelay::OpenSocket(const std::string &address, unsigned short port)
}
int reuse = 1;
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1)
{
printf("Cannot set the UDP socket %s:%u option, err: %d, %s\n", address.c_str(), port, errno, strerror(errno));
close(fd);
return -1;
}
if (::bind(fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
if (::bind(fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
{
printf("Cannot bind the UDP socket %s:%u address, err: %d, %s\n", address.c_str(), port, errno, strerror(errno));
close(fd);
return -1;
@ -119,7 +125,8 @@ bool CQnetRelay::Run(const char *cfgfile)
keep_running = true;
while (keep_running) {
while (keep_running)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(msock, &readfds);
@ -129,7 +136,8 @@ bool CQnetRelay::Run(const char *cfgfile)
// don't care about writefds and exceptfds:
// and we'll wait as long as needed
int ret = ::select(maxfs+1, &readfds, NULL, NULL, NULL);
if (ret < 0) {
if (ret < 0)
{
printf("ERROR: Run: select returned err=%d, %s\n", errno, strerror(errno));
break;
}
@ -143,10 +151,12 @@ bool CQnetRelay::Run(const char *cfgfile)
socklen_t size = sizeof(sockaddr);
ssize_t len;
if (FD_ISSET(msock, &readfds)) {
if (FD_ISSET(msock, &readfds))
{
len = ::recvfrom(msock, buf, 100, 0, (sockaddr *)&addr, &size);
if (len < 0) {
if (len < 0)
{
fprintf(stderr, "ERROR: Run: recvfrom(mmdvmhost) return error %d: %s\n", errno, strerror(errno));
break;
}
@ -156,29 +166,37 @@ bool CQnetRelay::Run(const char *cfgfile)
}
if (FD_ISSET(fd, &readfds)) {
if (FD_ISSET(fd, &readfds))
{
len = ToGate.Read(buf, 100);
if (len < 0) {
if (len < 0)
{
fprintf(stderr, "ERROR: Run: ToGate.Read() returned error %d: %s\n", errno, strerror(errno));
break;
}
}
if (len == 0) {
if (len == 0)
{
fprintf(stderr, "DEBUG: Run: read zero bytes from %u\n", ntohs(addr.sin_port));
continue;
}
if (0 == memcmp(buf, "DSRP", 4)) {
if (0 == memcmp(buf, "DSRP", 4))
{
//printf("read %d bytes from MMDVMHost\n", (int)len);
if (ProcessMMDVM(len, buf))
break;
} else if (0 == ::memcmp(buf, "DSVT", 4)) {
}
else if (0 == ::memcmp(buf, "DSVT", 4))
{
//printf("read %d bytes from MMDVMHost\n", (int)len);
if (ProcessGateway(len, buf))
break;
} else {
}
else
{
char title[5];
for (int i=0; i<4; i++)
title[i] = (buf[i]>=0x20u && buf[i]<0x7fu) ? buf[i] : '.';
@ -210,7 +228,8 @@ int CQnetRelay::SendTo(const int fd, const unsigned char *buf, const int size, c
bool CQnetRelay::ProcessGateway(const int len, const unsigned char *raw)
{
if (27==len || 56==len) { //here is dstar data
if (27==len || 56==len) //here is dstar data
{
SDSVT dsvt;
::memcpy(dsvt.title, raw, len); // transfer raw data to SDSVT struct
@ -219,7 +238,8 @@ bool CQnetRelay::ProcessGateway(const int len, const unsigned char *raw)
::memcpy(dsrp.title, "DSRP", 4);
dsrp.voice.id = dsvt.streamid; // voice or header is the same position
dsrp.voice.seq = dsvt.ctrl; // ditto
if (27 == len) { // write an AMBE packet
if (27 == len) // write an AMBE packet
{
dsrp.tag = 0x21U;
if (log_qso && (dsrp.voice.seq & 0x40))
printf("Sent DSRP end of streamid=%04x\n", ntohs(dsrp.voice.id));
@ -228,13 +248,17 @@ bool CQnetRelay::ProcessGateway(const int len, const unsigned char *raw)
dsrp.voice.err = 0; // NOT SURE WHERE TO GET THIS FROM THE INPUT buf
memcpy(dsrp.voice.ambe, dsvt.vasd.voice, 12);
int ret = SendTo(msock, dsrp.title, 21, MMDVM_IP, MMDVM_IN_PORT);
if (ret != 21) {
if (ret != 21)
{
printf("ERROR: ProcessGateway: Could not write AMBE mmdvmhost packet\n");
return true;
}
} else { // write a Header packet
}
else // write a Header packet
{
dsrp.tag = 0x20U;
if (dsrp.header.seq) {
if (dsrp.header.seq)
{
// printf("DEBUG: ProcessGateway: unexpected pkt.header.seq %d, resetting to 0\n", pkt.header.seq);
dsrp.header.seq = 0;
}
@ -247,7 +271,8 @@ bool CQnetRelay::ProcessGateway(const int len, const unsigned char *raw)
memcpy(dsrp.header.nm, dsvt.hdr.sfx, 4);
memcpy(dsrp.header.pfcs, dsvt.hdr.pfcs, 2);
int ret = SendTo(msock, dsrp.title, 49, MMDVM_IP, MMDVM_IN_PORT);
if (ret != 49) {
if (ret != 49)
{
printf("ERROR: ProcessGateway: Could not write Header mmdvmhost packet\n");
return true;
}
@ -255,7 +280,8 @@ bool CQnetRelay::ProcessGateway(const int len, const unsigned char *raw)
printf("Sent DSRP to %u, streamid=%04x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", MMDVM_IN_PORT, ntohs(dsrp.header.id), dsrp.header.ur, dsrp.header.r2, dsrp.header.r1, dsrp.header.my, dsrp.header.nm);
}
} else
}
else
printf("DEBUG: ProcessGateway: unusual packet size read len=%d\n", len);
return false;
}
@ -267,13 +293,17 @@ bool CQnetRelay::ProcessMMDVM(const int len, const unsigned char *raw)
if (len < 65)
::memcpy(dsrp.title, raw, len); // transfer raw data to SDSRP struct
if (49==len || 21==len) {
if (49==len || 21==len)
{
// grab the stream id if this is a header
if (49 == len) {
if (49 == len)
{
if (dsrp.header.id == id)
return false;
id = dsrp.header.id;
} else {
}
else
{
if (dsrp.voice.id != id)
return false;
}
@ -289,7 +319,8 @@ bool CQnetRelay::ProcessMMDVM(const int len, const unsigned char *raw)
dsvt.flagb[2] = ('B'==RPTR_MOD) ? 0x1U : (('C'==RPTR_MOD) ? 0x2U : 0x3U);
dsvt.streamid = id;
if (49 == len) { // header
if (49 == len) // header
{
dsvt.ctrl = 0x80;
//memcpy(dsvt.hdr.flag, dsrp.header.flag, 41);
memcpy(dsvt.hdr.flag, dsrp.header.flag, 3);
@ -299,17 +330,21 @@ bool CQnetRelay::ProcessMMDVM(const int len, const unsigned char *raw)
memcpy(dsvt.hdr.mycall, dsrp.header.my, 8);
memcpy(dsvt.hdr.sfx, dsrp.header.nm, 4);
memcpy(dsvt.hdr.pfcs, dsrp.header.pfcs, 2);
if (ToGate.Write(dsvt.title, 56)) {
if (ToGate.Write(dsvt.title, 56))
{
printf("ERROR: ProcessMMDVM: Could not write gateway header packet\n");
return true;
}
if (log_qso)
printf("Sent DSVT streamid=%04x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", ntohs(dsvt.streamid), dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2, dsvt.hdr.mycall, dsvt.hdr.sfx);
} else if (21 == len) { // ambe
}
else if (21 == len) // ambe
{
dsvt.ctrl = dsrp.header.seq;
memcpy(dsvt.vasd.voice, dsrp.voice.ambe, 12);
if (ToGate.Write(dsvt.title, 27)) {
if (ToGate.Write(dsvt.title, 27))
{
printf("ERROR: ProcessMMDVM: Could not write gateway voice packet\n");
return true;
}
@ -317,9 +352,12 @@ bool CQnetRelay::ProcessMMDVM(const int len, const unsigned char *raw)
if (log_qso && dsvt.ctrl&0x40)
printf("Sent DSVT end of streamid=%04x\n", ntohs(dsvt.streamid));
}
} else if (len < 65 && dsrp.tag == 0xAU) {
}
else if (len < 65 && dsrp.tag == 0xAU)
{
// printf("MMDVM Poll: '%s'\n", (char *)mpkt.poll_msg);
} else
}
else
printf("DEBUG: ProcessMMDVM: unusual packet len=%d\n", len);
return false;
}
@ -336,12 +374,15 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
std::string mmdvm_path("module_");
std::string type;
if (0 > assigned_module) {
if (0 > assigned_module)
{
// we need to find the lone mmdvmhost module
for (int i=0; i<3; i++) {
for (int i=0; i<3; i++)
{
std::string test(mmdvm_path);
test.append(1, 'a'+i);
if (cfg.KeyExists(test)) {
if (cfg.KeyExists(test))
{
cfg.GetValue(test, estr, type, 1, 16);
if (type.compare("mmdvmhost"))
continue; // this ain't it!
@ -350,20 +391,27 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
break;
}
}
if (0 > assigned_module) {
if (0 > assigned_module)
{
fprintf(stderr, "Error: no 'mmdvmhost' module found\n!");
return true;
}
} else {
}
else
{
// make sure mmdvmhost module is defined
mmdvm_path.append(1, 'a' + assigned_module);
if (cfg.KeyExists(mmdvm_path)) {
if (cfg.KeyExists(mmdvm_path))
{
cfg.GetValue(mmdvm_path, estr, type, 1, 16);
if (type.compare("mmdvmhost")) {
if (type.compare("mmdvmhost"))
{
fprintf(stderr, "%s = %s is not 'mmdvmhost' type!\n", mmdvm_path.c_str(), type.c_str());
return true;
}
} else {
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
return true;
}
@ -386,12 +434,14 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
int main(int argc, const char **argv)
{
setbuf(stdout, NULL);
if (2 != argc) {
if (2 != argc)
{
fprintf(stderr, "usage: %s path_to_config_file\n", argv[0]);
return 1;
}
if ('-' == argv[1][0]) {
if ('-' == argv[1][0])
{
printf("\nQnetRelay Version #%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", RELAY_VERSION);
printf("QnetRelay comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n\n");
@ -399,13 +449,15 @@ int main(int argc, const char **argv)
}
const char *qn = strstr(argv[0], "qnrelay");
if (NULL == qn) {
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qnrelay' in %s!\n", argv[0]);
return 1;
}
qn += 7;
int module;
switch (*qn) {
switch (*qn)
{
case NULL:
module = -1;
break;

@ -54,7 +54,8 @@ static int PLAY_WAIT, PLAY_DELAY;
static unsigned char silence[9] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8 };
static unsigned short crc_tabccitt[256] = {
static unsigned short crc_tabccitt[256] =
{
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
@ -82,15 +83,18 @@ static bool ReadCfgFile()
std::string path = "module_";
path.append(1, 'a'+module);
if (! cfg.KeyExists(path)) {
if (! cfg.KeyExists(path))
{
fprintf(stderr, "%s not defined!\n", path.c_str());
return true;
}
cfg.GetValue(path, estr, type, 1, 16);
cfg.GetValue(path+"_callsign", type, REPEATER, 0, 6);
if (REPEATER.length() < 4) {
if (cfg.GetValue("ircddb_login", estr, REPEATER, 3, 6)) {
if (REPEATER.length() < 4)
{
if (cfg.GetValue("ircddb_login", estr, REPEATER, 3, 6))
{
fprintf(stderr, "no Callsign for the repeater was found!\n");
return true;
}
@ -108,7 +112,8 @@ static void calcPFCS(unsigned char rawbytes[56])
unsigned short tmp, short_c;
short int i;
for (i = 15; i < 54 ; i++) {
for (i = 15; i < 54 ; i++)
{
short_c = 0x00ff & (unsigned short)rawbytes[i];
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
@ -130,7 +135,8 @@ static void ToUpper(std::string &str)
int main(int argc, char *argv[])
{
if (argc != 4) {
if (argc != 4)
{
fprintf(stderr, "Usage: %s <module> <mycall> <yourcall>\n", argv[0]);
fprintf(stderr, "Example: %s c n7tae xrf757al\n", argv[0]);
fprintf(stderr, "Where...\n");
@ -140,7 +146,8 @@ int main(int argc, char *argv[])
return 0;
}
switch (argv[1][0]) {
switch (argv[1][0])
{
case '0':
case 'a':
case 'A':
@ -169,13 +176,15 @@ int main(int argc, char *argv[])
if (ReadCfgFile())
return 1;
if (REPEATER.size() > 6) {
if (REPEATER.size() > 6)
{
printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", REPEATER.c_str());
return 1;
}
ToUpper(REPEATER);
if (strlen(argv[2]) > 8) {
if (strlen(argv[2]) > 8)
{
printf("MYCALL can not be more than 8 characters, %s is invalid\n", argv[2]);
return 1;
}
@ -183,7 +192,8 @@ int main(int argc, char *argv[])
ToUpper(mycall);
if (strlen(argv[3]) > 8) {
if (strlen(argv[3]) > 8)
{
printf("YOURCALL can not be more than 8 characters, %s is invalid\n", argv[3]);
return 1;
}
@ -191,7 +201,8 @@ int main(int argc, char *argv[])
ToUpper(yourcall);
// replace underscores with spaces
auto pos = yourcall.find_first_of('_');
while (yourcall.npos != pos) {
while (yourcall.npos != pos)
{
yourcall[pos] = ' ';
pos = yourcall.find_first_of('_');
}
@ -244,7 +255,8 @@ int main(int argc, char *argv[])
calcPFCS(pkt.title);
// send the header
if (56 != ToGateway.Write(pkt.title, 56)) {
if (56 != ToGateway.Write(pkt.title, 56))
{
printf("%s: ERROR: Couldn't send header!\n", argv[0]);
return 1;
}
@ -253,11 +265,13 @@ int main(int argc, char *argv[])
pkt.config = 0x20U;
memcpy(pkt.vasd.voice, silence, 9);
for (int i=0; i<10; i++) {
for (int i=0; i<10; i++)
{
/* start sending silence + text */
pkt.ctrl = i;
switch (i) {
switch (i)
{
case 0: // sync voice frame
pkt.vasd.text[0] = 0x55;
pkt.vasd.text[1] = 0x2d;
@ -311,7 +325,8 @@ int main(int argc, char *argv[])
break;
}
if (27 != ToGateway.Write(pkt.title, 27)) {
if (27 != ToGateway.Write(pkt.title, 27))
{
printf("%s: ERROR: could not send voice packet %d\n", argv[0], i);
return 1;
}

@ -19,25 +19,31 @@
// for communicating with the g2 gateway on the internal port
#pragma pack(push, 1) // used internally by Icom stacks
using SDSTR = struct dstr_tag {
using SDSTR = struct dstr_tag
{
unsigned char pkt_id[4]; // 0 "DSTR"
unsigned short counter; // 4
unsigned char flag[3]; // 6 { 0x73, 0x12, 0x00 }
unsigned char remaining; // 9 the number of bytes left in the packet
union {
struct {
union
{
struct
{
unsigned char mycall[8]; // 10
unsigned char rpt[8]; // 18
} spkt; // total 26
struct {
struct
{
unsigned char icm_id; // 10
unsigned char dst_rptr_id; // 11
unsigned char snd_rptr_id; // 12
unsigned char snd_term_id; // 13
unsigned short streamid; // 14
unsigned char ctrl; // 16 sequence number hdr=0, voice%21, end|=0x40
union {
struct {
union
{
struct
{
unsigned char flag[3]; // 17
unsigned char r2[8]; // 20
unsigned char r1[8]; // 28
@ -46,12 +52,15 @@ using SDSTR = struct dstr_tag {
unsigned char nm[4]; // 52
unsigned char pfcs[2]; // 56
} hdr; // total 58
union {
struct {
union
{
struct
{
unsigned char voice[9]; // 17
unsigned char text[3]; // 26
} vasd; // total 29
struct {
struct
{
unsigned char UNKNOWN[3]; // 17 not sure what this is, but g2_ doesn't seem to need it
unsigned char voice[9]; // 20
unsigned char text[3]; // 29
@ -65,7 +74,8 @@ using SDSTR = struct dstr_tag {
// for the g2 external port and between QnetGateway programs
#pragma pack(push, 1)
using SDSVT = struct dsvt_tag {
using SDSVT = struct dsvt_tag
{
unsigned char title[4]; // 0 "DSVT"
unsigned char config; // 4 0x10 is hdr 0x20 is vasd
unsigned char flaga[3]; // 5 zeros
@ -73,8 +83,10 @@ using SDSVT = struct dsvt_tag {
unsigned char flagb[3]; // 9 0x0 0x1 (A:0x3 B:0x1 C:0x2)
unsigned short streamid;// 12
unsigned char ctrl; // 14 hdr: 0x80 vsad: framecounter (mod 21)
union {
struct { // index
union
{
struct // index
{
unsigned char flag[3]; // 15
unsigned char rpt1[8]; // 18
unsigned char rpt2[8]; // 26
@ -83,11 +95,13 @@ using SDSVT = struct dsvt_tag {
unsigned char sfx[4]; // 50
unsigned char pfcs[2]; // 54
} hdr; // total 56
struct {
struct
{
unsigned char voice[9]; // 15
unsigned char text[3]; // 24
} vasd; // voice and slow data total 27
struct {
struct
{
unsigned char voice[9]; // 15
unsigned char end[6]; // 24
} vend; // voice and end seq total 32 (for DPlus)
@ -97,14 +111,17 @@ using SDSVT = struct dsvt_tag {
// for mmdvm
#pragma pack(push, 1)
using SDSRP = struct dsrp_tag { // offset size
using SDSRP = struct dsrp_tag // offset size
{
unsigned char title[4]; // "DSRP" 0
unsigned char tag; // Poll : 0xA 4
// Header : busy ? 0x22 : 0x20
// Voice : busy ? 0x23 : 0x21
union {
union
{
unsigned char poll_msg[59]; // space for text 5 variable, max is 64, including trailing null
struct {
struct
{
unsigned short id; // random id number 5
unsigned char seq; // 0x0 7
unsigned char flag[3]; // 0x80 Dstar Data 8
@ -117,7 +134,8 @@ using SDSRP = struct dsrp_tag { // offset size
unsigned char nm[4]; // Name 43
unsigned char pfcs[2]; // checksum 47 49
} header;
struct {
struct
{
unsigned short id; // random id number 5
unsigned char seq; // sequence from 0 to 0x14 7
// if end then sequence |= 0x40
@ -129,7 +147,8 @@ using SDSRP = struct dsrp_tag { // offset size
#pragma pack(pop)
#pragma pack(push, 1)
using SLINKFAMILY = struct link_family_tag {
using SLINKFAMILY = struct link_family_tag
{
char title[4];
int family[3];
};

@ -37,13 +37,16 @@ bool read_config(const char *cfgFile)
if (cfg.Initialize(cfgFile))
return true;
for (int m=0; m<3; m++) {
for (int m=0; m<3; m++)
{
std::string path("module_");
path.append(std::to_string(m));
std::string type;
if (cfg.KeyExists(path)) {
if (cfg.KeyExists(path))
{
cfg.GetValue(path, "", type, 1, 16);
if (strcasecmp(type.c_str(), "dvap") && strcasecmp(type.c_str(), "dvrptr") && strcasecmp(type.c_str(), "mmdvm") && strcasecmp(type.c_str(), "itap")) {
if (strcasecmp(type.c_str(), "dvap") && strcasecmp(type.c_str(), "dvrptr") && strcasecmp(type.c_str(), "mmdvm") && strcasecmp(type.c_str(), "itap"))
{
printf("module type '%s' is invalid\n", type.c_str());
return true;
}
@ -69,7 +72,8 @@ int main(int argc, char *argv[])
{
char RADIO_ID[21];
if (argc != 4) {
if (argc != 4)
{
printf("Usage: %s <module> <datFile> <txtMsg>\n", argv[0]);
printf("Where...\n");
printf(" <module> is one of your modules: A, B or C\n");
@ -87,7 +91,8 @@ int main(int argc, char *argv[])
if (islower(module))
module = toupper(module);
if ((module != 'A') && (module != 'B') && (module != 'C')) {
if ((module != 'A') && (module != 'B') && (module != 'C'))
{
printf("module must be one of A B C\n");
return 1;
}
@ -96,7 +101,8 @@ int main(int argc, char *argv[])
snprintf(pathname, FILENAME_MAX, "%s/%s", announce_dir.c_str(), argv[2]);
FILE *fp = fopen(pathname, "rb");
if (!fp) {
if (!fp)
{
printf("Failed to find file %s for reading\n", pathname);
return 1;
}
@ -112,10 +118,13 @@ int main(int argc, char *argv[])
RADIO_ID[i] = '_';
fp = fopen(qnvoice_file.c_str(), "w");
if (fp) {
if (fp)
{
fprintf(fp, "%c_%s_%s\n", module, argv[2], RADIO_ID);
fclose(fp);
} else {
}
else
{
printf("Failed to open %s for writing", qnvoice_file.c_str());
return 1;
}

@ -17,7 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
using SECHO = struct echo_tag {
using SECHO = struct echo_tag
{
bool is_linked;
time_t last_time;
unsigned short streamid;

@ -44,33 +44,41 @@ public:
{
Clear();
addr.ss_family = family;
if (AF_INET == family) {
if (AF_INET == family)
{
auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_port = htons(port);
if (address) {
if (address)
{
if (0 == strncasecmp(address, "loc", 3))
inet_pton(AF_INET, "127.0.0.1", &(addr4->sin_addr));
else if (0 == strncasecmp(address, "any", 3))
inet_pton(AF_INET, "0.0.0.0", &(addr4->sin_addr));
else if (address) {
else if (address)
{
if (1 > inet_pton(AF_INET, address, &(addr4->sin_addr)))
std::cerr << "Address Initialization Error: '" << address << "' is not a valdid IPV4 address!" << std::endl;
}
}
} else if (AF_INET6 == family) {
}
else if (AF_INET6 == family)
{
auto addr6 = (struct sockaddr_in6 *)&addr;
addr6->sin6_port = htons(port);
if (address) {
if (address)
{
if (0 == strncasecmp(address, "loc", 3))
inet_pton(AF_INET6, "::1", &(addr6->sin6_addr));
else if (0 == strncasecmp(address, "any", 3))
inet_pton(AF_INET6, "::", &(addr6->sin6_addr));
else if (address) {
else if (address)
{
if (1 > inet_pton(AF_INET6, address, &(addr6->sin6_addr)))
std::cerr << "Address Initialization Error: '" << address << "' is not a valid IPV6 address!" << std::endl;
}
}
} else
}
else
std::cerr << "Error: Wrong address family type:" << family << " for [" << (address ? address : "NULL") << "]:" << port << std::endl;
}
@ -89,11 +97,14 @@ public:
{
if (addr.ss_family != rhs.addr.ss_family)
return false;
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto l = (struct sockaddr_in *)&addr;
auto r = (struct sockaddr_in *)&rhs.addr;
return (l->sin_addr.s_addr == r->sin_addr.s_addr);
} else if (AF_INET6 == addr.ss_family) {
}
else if (AF_INET6 == addr.ss_family)
{
auto l = (struct sockaddr_in6 *)&addr;
auto r = (struct sockaddr_in6 *)&rhs.addr;
return (0 == memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
@ -105,11 +116,14 @@ public:
{
if (addr.ss_family != rhs.addr.ss_family)
return true;
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto l = (struct sockaddr_in *)&addr;
auto r = (struct sockaddr_in *)&rhs.addr;
return (l->sin_addr.s_addr != r->sin_addr.s_addr);
} else if (AF_INET6 == addr.ss_family) {
}
else if (AF_INET6 == addr.ss_family)
{
auto l = (struct sockaddr_in6 *)&addr;
auto r = (struct sockaddr_in6 *)&rhs.addr;
return (0 != memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
@ -119,12 +133,16 @@ public:
bool AddressIsZero() const
{
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr;
return (addr4->sin_addr.s_addr == 0U);
} else {
}
else
{
auto addr6 = (struct sockaddr_in6 *)&addr;
for (unsigned int i=0; i<16; i++) {
for (unsigned int i=0; i<16; i++)
{
if (addr6->sin6_addr.s6_addr[i])
return false;
}
@ -134,11 +152,14 @@ public:
void ClearAddress()
{
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_addr.s_addr = 0U;
strcpy(straddr, "0.0.0.0");
} else {
}
else
{
auto addr6 = (struct sockaddr_in6 *)&addr;
memset(&(addr6->sin6_addr.s6_addr), 0, 16);
strcpy(straddr, "::");
@ -149,13 +170,18 @@ public:
{
if (straddr[0])
return straddr;
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr;
inet_ntop(AF_INET, &(addr4->sin_addr), straddr, INET6_ADDRSTRLEN);
} else if (AF_INET6 == addr.ss_family) {
}
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr;
inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, INET6_ADDRSTRLEN);
} else {
}
else
{
std::cerr << "Unknown socket family: " << addr.ss_family << std::endl;
}
return straddr;
@ -168,22 +194,29 @@ public:
unsigned short GetPort() const
{
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr;
return ntohs(addr4->sin_port);
} else if (AF_INET6 == addr.ss_family) {
}
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr;
return ntohs(addr6->sin6_port);
} else
}
else
return 0;
}
void SetPort(const uint16_t newport)
{
if (AF_INET == addr.ss_family) {
if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_port = htons(newport);
} else if (AF_INET6 == addr.ss_family) {
}
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr;
addr6->sin6_port = htons(newport);
}

@ -51,17 +51,20 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
bool CTCPReaderWriterClient::Open()
{
if (m_fd != -1) {
if (m_fd != -1)
{
fprintf(stderr, "ERROR: port for '%s' is already open!\n", m_address.c_str());
return true;
}
if (0 == m_address.size() || 0 == m_port.size() || 0 == std::stoul(m_port)) {
if (0 == m_address.size() || 0 == m_port.size() || 0 == std::stoul(m_port))
{
fprintf(stderr, "ERROR: '[%s]:%s' is malformed!\n", m_address.c_str(), m_port.c_str());
return true;
}
if (AF_INET!=m_family && AF_INET6!=m_family && AF_UNSPEC!=m_family) {
if (AF_INET!=m_family && AF_INET6!=m_family && AF_UNSPEC!=m_family)
{
fprintf(stderr, "ERROR: family must be AF_INET, AF_INET6 or AF_UNSPEC\n");
return true;
}
@ -76,37 +79,47 @@ bool CTCPReaderWriterClient::Open()
struct addrinfo *res;
int s = EAI_AGAIN;
int count = 0;
while (EAI_AGAIN==s and count++<20) {
while (EAI_AGAIN==s and count++<20)
{
// connecting to a server, so we can wait until it's ready
s = getaddrinfo(m_address.c_str(), m_port.c_str(), &hints, &res);
if (s && s != EAI_AGAIN) {
if (s && s != EAI_AGAIN)
{
fprintf(stderr, "ERROR: getaddrinfo of %s: %s\n", m_address.c_str(), gai_strerror(s));
return true;
}
std::this_thread::sleep_for(std::chrono::seconds(3));
}
if (EAI_AGAIN == s) {
if (EAI_AGAIN == s)
{
fprintf(stderr, "ERROR getaddrinfo of %s failed 20 times\n", m_address.c_str());
return true;
}
struct addrinfo *rp;
for (rp = res; rp != NULL; rp = rp->ai_next) {
for (rp = res; rp != NULL; rp = rp->ai_next)
{
m_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (m_fd == -1)
continue;
if (connect(m_fd, rp->ai_addr, rp->ai_addrlen)) {
if (connect(m_fd, rp->ai_addr, rp->ai_addrlen))
{
Close();
continue;
} else {
}
else
{
char buf[INET6_ADDRSTRLEN];
void *addr;
if (AF_INET == rp->ai_family) {
if (AF_INET == rp->ai_family)
{
struct sockaddr_in *addr4 = (struct sockaddr_in *)rp->ai_addr;
addr = &(addr4->sin_addr);
} else {
}
else
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
addr = &(addr6->sin6_addr);
}
@ -117,7 +130,8 @@ bool CTCPReaderWriterClient::Open()
}
freeaddrinfo(res);
if (rp == NULL) {
if (rp == NULL)
{
fprintf(stderr, "Could not connect to any system returned by %s\n", m_address.c_str());
m_fd = -1;
return true;
@ -130,13 +144,15 @@ int CTCPReaderWriterClient::ReadExact(unsigned char *buf, const unsigned int len
{
unsigned int offset = 0U;
do {
do
{
int n = Read(buf + offset, length - offset);
if (n < 0)
return n;
offset += n;
} while ((length - offset) > 0U);
}
while ((length - offset) > 0U);
return length;
}
@ -148,7 +164,8 @@ int CTCPReaderWriterClient::Read(unsigned char* buffer, const unsigned int lengt
assert(m_fd != -1);
ssize_t len = recv(m_fd, buffer, length, 0);
if (len <= 0) {
if (len <= 0)
{
if (len < 0)
fprintf(stderr, "Error returned from recv, err=%d\n", errno);
return -1;
@ -167,11 +184,13 @@ int CTCPReaderWriterClient::ReadLine(std::string& line)
do
{
resultCode = Read(&c, 1);
if(resultCode == 1) {
if(resultCode == 1)
{
line += c;
len++;
}
} while(c != '\n' && resultCode == 1);
}
while(c != '\n' && resultCode == 1);
return resultCode <= 0 ? resultCode : len;
}
@ -183,7 +202,8 @@ bool CTCPReaderWriterClient::Write(const unsigned char *buffer, const unsigned i
assert(m_fd != -1);
ssize_t ret = send(m_fd, (char *)buffer, length, 0);
if (ret != ssize_t(length)) {
if (ret != ssize_t(length))
{
if (ret < 0)
fprintf(stderr, "Error returned from send, err=%s\n", strerror(errno));
else
@ -202,7 +222,8 @@ bool CTCPReaderWriterClient::WriteLine(const std::string& line)
size_t len = lineCopy.size();
bool result = true;
for(size_t i = 0; i < len && result; i++){
for(size_t i = 0; i < len && result; i++)
{
unsigned char c = lineCopy.at(i);
result = Write(&c, 1);
}
@ -212,7 +233,8 @@ bool CTCPReaderWriterClient::WriteLine(const std::string& line)
void CTCPReaderWriterClient::Close()
{
if (m_fd != -1) {
if (m_fd != -1)
{
close(m_fd);
m_fd = -1;
}

@ -33,7 +33,8 @@
#include <thread>
#include <chrono>
class CTCPReaderWriterClient {
class CTCPReaderWriterClient
{
public:
CTCPReaderWriterClient(const std::string &address, int family, const std::string &port);
CTCPReaderWriterClient();

@ -26,10 +26,12 @@ class CTimer
public:
CTimer() { start(); }
~CTimer() {}
void start() {
void start()
{
starttime = std::chrono::steady_clock::now();
}
double time() {
double time()
{
std::chrono::duration<double> elapsed(std::chrono::steady_clock::now() - starttime);
return elapsed.count();
}

@ -49,12 +49,14 @@ bool CUDPSocket::Open(const CSockAddress &addr)
{
// create socket
m_fd = socket(addr.GetFamily(), SOCK_DGRAM, 0);
if (0 > m_fd) {
if (0 > m_fd)
{
std::cerr << "Cannot create socket on " << addr << ", " << strerror(errno) << std::endl;
return true;
}
if (0 > fcntl(m_fd, F_SETFL, O_NONBLOCK)) {
if (0 > fcntl(m_fd, F_SETFL, O_NONBLOCK))
{
std::cerr << "cannot set socket " << addr << " to non-blocking: " << strerror(errno) << std::endl;
close(m_fd);
m_fd = -1;
@ -62,7 +64,8 @@ bool CUDPSocket::Open(const CSockAddress &addr)
}
const int reuse = 1;
if (0 > setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))) {
if (0 > setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)))
{
std::cerr << "Cannot set the UDP socket option on " << m_addr << ", err: " << strerror(errno) << std::endl;
close(m_fd);
m_fd = -1;
@ -72,7 +75,8 @@ bool CUDPSocket::Open(const CSockAddress &addr)
// initialize sockaddr struct
m_addr = addr;
if (0 != bind(m_fd, m_addr.GetCPointer(), m_addr.GetSize())) {
if (0 != bind(m_fd, m_addr.GetCPointer(), m_addr.GetSize()))
{
std::cerr << "bind failed on " << m_addr << ", " << strerror(errno) << std::endl;
close(m_fd);
m_fd = -1;
@ -84,7 +88,8 @@ bool CUDPSocket::Open(const CSockAddress &addr)
void CUDPSocket::Close(void)
{
if ( m_fd >= 0 ) {
if ( m_fd >= 0 )
{
close(m_fd);
m_fd = -1;
}

@ -39,7 +39,8 @@ CUnixDgramReader::~CUnixDgramReader()
bool CUnixDgramReader::Open(const char *path) // returns true on failure
{
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
if (fd < 0)
{
fprintf(stderr, "CUnixDgramReader::Open: socket() failed: %s\n", strerror(errno));
return true;
}
@ -51,7 +52,8 @@ bool CUnixDgramReader::Open(const char *path) // returns true on failure
strncpy(addr.sun_path+1, path, sizeof(addr.sun_path)-2);
int rval = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (rval < 0) {
if (rval < 0)
{
fprintf(stderr, "CUnixDgramReader::Open: bind() failed: %s\n", strerror(errno));
close(fd);
fd = -1;
@ -98,13 +100,15 @@ ssize_t CUnixDgramWriter::Write(const void *buf, size_t size)
{
// open the socket
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
if (fd < 0)
{
fprintf(stderr, "Failed to open socket %s : %s\n", addr.sun_path+1, strerror(errno));
return -1;
}
// connect to the receiver
int rval = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if (rval < 0) {
if (rval < 0)
{
fprintf(stderr, "Failed to connect to socket %s : %s\n", addr.sun_path+1, strerror(errno));
close(fd);
return -1;
@ -112,7 +116,8 @@ ssize_t CUnixDgramWriter::Write(const void *buf, size_t size)
ssize_t written = 0;
int count = 0;
while (written <= 0) {
while (written <= 0)
{
written = write(fd, buf, size);
if (written == (ssize_t)size)
break;
@ -120,11 +125,13 @@ ssize_t CUnixDgramWriter::Write(const void *buf, size_t size)
fprintf(stderr, "ERROR: faied to write to %s : %s\n", addr.sun_path+1, strerror(errno));
else if (written == 0)
fprintf(stderr, "Warning: zero bytes written to %s\n", addr.sun_path+1);
else if (written != (ssize_t)size) {
else if (written != (ssize_t)size)
{
fprintf(stderr, "ERROR: only %d of %d bytes written to %s\n", (int)written, (int)size, addr.sun_path+1);
break;
}
if (++count >= 100) {
if (++count >= 100)
{
fprintf(stderr, "ERROR: Write failed after %d attempts\n", count-1);
break;
}

@ -33,10 +33,14 @@ ssize_t CUnixPacket::Read(void *buffer, const ssize_t size)
if (0 > m_fd)
return -1;
ssize_t len = read(m_fd, buffer, size);
if (len < 1) {
if (-1 == len) {
if (len < 1)
{
if (-1 == len)
{
std::cerr << "Read error on '" << m_name << "': " << strerror(errno) << std::endl;
} else if (0 == len) {
}
else if (0 == len)
{
std::cerr << "Read error on '" << m_name << "': EOF" << std::endl;
}
if (Restart())
@ -52,10 +56,14 @@ bool CUnixPacket::Write(const void *buffer, const ssize_t size)
if (0 > m_fd)
return true;
ssize_t written = write(m_fd, buffer, size);
if (written != size) {
if (-1 == written) {
if (written != size)
{
if (-1 == written)
{
std::cerr << "Write error on '" << m_name << "': " << strerror(errno) << std::endl;
} else {
}
else
{
std::cout << "Write error on '" << m_name << "': Only wrote " << written << " of " << size << " bytes" << std::endl;
}
return Restart();
@ -86,7 +94,8 @@ CUnixPacketServer::~CUnixPacketServer()
bool CUnixPacketServer::Open(const char *name, CKRBase *host)
{
m_server = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (m_server < 0) {
if (m_server < 0)
{
std::cerr << "Cannot open '" << name << "' socket: " << strerror(errno) << std::endl;
return true;
}
@ -95,20 +104,23 @@ bool CUnixPacketServer::Open(const char *name, CKRBase *host)
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path+1, name, strlen(name));
if (-1 == bind(m_server, (struct sockaddr *)&addr, sizeof(addr))) {
if (-1 == bind(m_server, (struct sockaddr *)&addr, sizeof(addr)))
{
std::cerr << "Cannot bind '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
if (-1 == listen(m_server, 1)) {
if (-1 == listen(m_server, 1))
{
std::cerr << "Cannot listen on '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
m_fd = accept(m_server, nullptr, 0);
if (m_fd < 0) {
if (m_fd < 0)
{
std::cerr << "Cannot accept on '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
@ -121,11 +133,13 @@ bool CUnixPacketServer::Open(const char *name, CKRBase *host)
void CUnixPacketServer::Close()
{
if (m_server >= 0) {
if (m_server >= 0)
{
close(m_server);
m_server = -1;
}
if (m_fd >= 0) {
if (m_fd >= 0)
{
close(m_fd);
m_fd = -1;
}
@ -139,7 +153,8 @@ CUnixPacketClient::~CUnixPacketClient()
bool CUnixPacketClient::Open(const char *name, CKRBase *host)
{
m_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (m_fd < 0) {
if (m_fd < 0)
{
std::cerr << "Cannot open unix client socket " << name << std::endl;
return true;
}
@ -150,20 +165,26 @@ bool CUnixPacketClient::Open(const char *name, CKRBase *host)
memcpy(addr.sun_path+1, name, strlen(name));
int rval = -1;
int tries = 0;
while (rval < 0) {
while (rval < 0)
{
rval = connect(m_fd, (struct sockaddr *)&addr, sizeof(addr));
if (rval < 0) {
if (ECONNREFUSED == errno) {
if (rval < 0)
{
if (ECONNREFUSED == errno)
{
if (0 == tries++ % 20)
std::cout << "Waiting for " << name << " server to start..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
} else {
}
else
{
std::cerr << "Cannot connect '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
}
if (! m_host->IsRunning()) {
if (! m_host->IsRunning())
{
Close();
return true;
}
@ -176,7 +197,8 @@ bool CUnixPacketClient::Open(const char *name, CKRBase *host)
void CUnixPacketClient::Close()
{
if (m_fd >= 0) {
if (m_fd >= 0)
{
close(m_fd);
m_fd = -1;
}

@ -22,7 +22,8 @@
#include "KRBase.h"
class CUnixPacket {
class CUnixPacket
{
public:
CUnixPacket();
virtual bool Open(const char *name, CKRBase *host) = 0;
@ -37,7 +38,8 @@ protected:
char m_name[108];
};
class CUnixPacketServer : public CUnixPacket {
class CUnixPacketServer : public CUnixPacket
{
public:
CUnixPacketServer();
~CUnixPacketServer();
@ -47,7 +49,8 @@ protected:
int m_server;
};
class CUnixPacketClient : public CUnixPacket {
class CUnixPacketClient : public CUnixPacket
{
public:
~CUnixPacketClient();
bool Open(const char *name, CKRBase *host);

@ -3,39 +3,47 @@
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
static inline void ltrim(std::string &s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch)
{
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
static inline void rtrim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch)
{
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
static inline void trim(std::string &s)
{
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
static inline std::string ltrim_copy(std::string s)
{
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
static inline std::string rtrim_copy(std::string s)
{
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
static inline std::string trim_copy(std::string s)
{
trim(s);
return s;
}

@ -32,7 +32,8 @@
// This is called when header comes in from repeater
void CAPRS::SelectBand(short int rptr_idx, unsigned short streamID)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("ERROR in aprs_select_band, invalid mod %d\n", rptr_idx);
return;
}
@ -58,14 +59,17 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
short int rptr_idx = -1;
for (short int i = 0; i < 3; i++) {
if (streamID == aprs_streamID[i].streamID) {
for (short int i = 0; i < 3; i++)
{
if (streamID == aprs_streamID[i].streamID)
{
rptr_idx = i;
break;
}
}
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("ERROR in aprs_process_text: rptr_idx %d is invalid\n", rptr_idx);
return;
}
@ -73,7 +77,8 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
if ((seq & 0x40) == 0x40)
return;
if ((seq & 0x1f) == 0x00) {
if ((seq & 0x1f) == 0x00)
{
SyncIt(rptr_idx);
return;
}
@ -93,7 +98,8 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
return;
char *p = strchr((char*)aprs_data, ':');
if (!p) {
if (!p)
{
Reset(rptr_idx);
return;
}
@ -111,7 +117,8 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
sprintf(aprs_buf, "%s,qAR,%s:%s\r\n", hdr, m_rptr->mod[rptr_idx].call.c_str(), aud);
// printf("GPS-A=%s", aprs_buf);
int rc = aprs_sock.Write((unsigned char *)aprs_buf, strlen(aprs_buf));
if (rc == -1) {
if (rc == -1)
{
if ((errno == EPIPE) ||
(errno == ECONNRESET) ||
(errno == ETIMEDOUT) ||
@ -122,10 +129,12 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
(errno == ENETDOWN) ||
(errno == ENETUNREACH) ||
(errno == EHOSTDOWN) ||
(errno == ENOTCONN)) {
(errno == ENOTCONN))
{
printf("CAPRS::ProcessText(): APRS_HOST closed connection, error=%d\n",errno);
aprs_sock.Close();
} else /* if it is WOULDBLOCK, we will not go into a loop here */
}
else /* if it is WOULDBLOCK, we will not go into a loop here */
printf("CAPRS::ProcessText(): send error=%d\n", errno);
}
@ -137,7 +146,8 @@ void CAPRS::ProcessText(unsigned short streamID, unsigned char seq, unsigned cha
void CAPRS::Init()
{
/* Initialize the statistics on the APRS packets */
for (short int rptr_idx = 0; rptr_idx < 3; rptr_idx++) {
for (short int rptr_idx = 0; rptr_idx < 3; rptr_idx++)
{
aprs_pack[rptr_idx].al = al_none;
aprs_pack[rptr_idx].data[0] = '\0';
aprs_pack[rptr_idx].len = 0;
@ -146,7 +156,8 @@ void CAPRS::Init()
aprs_pack[rptr_idx].is_sent = false;
}
for (short int i = 0; i < 3; i++) {
for (short int i = 0; i < 3; i++)
{
aprs_streamID[i].streamID = 0;
aprs_streamID[i].last_time = 0;
}
@ -157,7 +168,8 @@ void CAPRS::Init()
bool CAPRS::WriteData(short int rptr_idx, unsigned char *data)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::WriteData: rptr_idx %d is invalid\n", rptr_idx);
return false;
}
@ -165,7 +177,8 @@ bool CAPRS::WriteData(short int rptr_idx, unsigned char *data)
if (aprs_pack[rptr_idx].is_sent)
return false;
switch (aprs_pack[rptr_idx].sl) {
switch (aprs_pack[rptr_idx].sl)
{
case sl_first:
aprs_pack[rptr_idx].buf[0] = data[0] ^ 0x70;
aprs_pack[rptr_idx].buf[1] = data[1] ^ 0x4f;
@ -190,7 +203,8 @@ bool CAPRS::WriteData(short int rptr_idx, unsigned char *data)
void CAPRS::SyncIt(short int rptr_idx)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::SyncIt(): rptr_idx %d is invalid\n", rptr_idx);
return;
}
@ -201,7 +215,8 @@ void CAPRS::SyncIt(short int rptr_idx)
void CAPRS::Reset(short int rptr_idx)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::Reset(): rptr_idx %d is invalid\n", rptr_idx);
return;
}
@ -216,7 +231,8 @@ void CAPRS::Reset(short int rptr_idx)
unsigned int CAPRS::GetData(short int rptr_idx, unsigned char *data, unsigned int len)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::GetData: rptr_idx %d is invalid\n", rptr_idx);
return 0;
}
@ -239,7 +255,8 @@ void CAPRS::Open(const std::string OWNER)
{
char snd_buf[512];
char rcv_buf[512];
while (aprs_sock.Open(m_rptr->aprs.ip, AF_UNSPEC, std::to_string(m_rptr->aprs.port))) {
while (aprs_sock.Open(m_rptr->aprs.ip, AF_UNSPEC, std::to_string(m_rptr->aprs.port)))
{
fprintf(stderr, "Failed to open %s, retry in 10 seconds...\n", m_rptr->aprs.ip.c_str());
std::this_thread::sleep_for(std::chrono::seconds(10));
}
@ -249,24 +266,32 @@ void CAPRS::Open(const std::string OWNER)
sprintf(snd_buf, "user %s pass %d vers QnetGateway-9 ", OWNER.c_str(), m_rptr->aprs_hash);
/* add the user's filter */
if (m_rptr->aprs_filter.length()) {
if (m_rptr->aprs_filter.length())
{
strcat(snd_buf, "filter ");
strcat(snd_buf, m_rptr->aprs_filter.c_str());
}
//printf("APRS Login command:[%s]\n", snd_buf);
strcat(snd_buf, "\r\n");
while (true) {
while (true)
{
int rc = aprs_sock.Write((unsigned char *)snd_buf, strlen(snd_buf));
if (rc < 0) {
if (errno == EWOULDBLOCK) {
if (rc < 0)
{
if (errno == EWOULDBLOCK)
{
aprs_sock.Read((unsigned char *)rcv_buf, sizeof(rcv_buf));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
}
else
{
printf("APRS Login command failed, error=%d\n", errno);
break;
}
} else {
}
else
{
// printf("APRS Login command sent\n");
break;
}
@ -278,78 +303,109 @@ void CAPRS::Open(const std::string OWNER)
bool CAPRS::AddData(short int rptr_idx, unsigned char *data)
{
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::AddData(): rptr_idx %d is invalid\n", rptr_idx);
return false;
}
for (unsigned int i = 0; i < 5; i++) {
for (unsigned int i = 0; i < 5; i++)
{
unsigned char c = data[i];
if ((aprs_pack[rptr_idx].al == al_none) && (c == '$')) {
if ((aprs_pack[rptr_idx].al == al_none) && (c == '$'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_$1;
} else if ((aprs_pack[rptr_idx].al == al_$1) && (c == '$')) {
}
else if ((aprs_pack[rptr_idx].al == al_$1) && (c == '$'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_$2;
} else if ((aprs_pack[rptr_idx].al == al_$2) && (c == 'C')) {
}
else if ((aprs_pack[rptr_idx].al == al_$2) && (c == 'C'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_c1;
} else if ((aprs_pack[rptr_idx].al == al_c1) && (c == 'R')) {
}
else if ((aprs_pack[rptr_idx].al == al_c1) && (c == 'R'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_r1;
} else if ((aprs_pack[rptr_idx].al == al_r1) && (c == 'C')) {
}
else if ((aprs_pack[rptr_idx].al == al_r1) && (c == 'C'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_c2;
} else if (aprs_pack[rptr_idx].al == al_c2) {
}
else if (aprs_pack[rptr_idx].al == al_c2)
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_csum1;
} else if (aprs_pack[rptr_idx].al == al_csum1) {
}
else if (aprs_pack[rptr_idx].al == al_csum1)
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_csum2;
} else if (aprs_pack[rptr_idx].al == al_csum2) {
}
else if (aprs_pack[rptr_idx].al == al_csum2)
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_csum3;
} else if (aprs_pack[rptr_idx].al == al_csum3) {
}
else if (aprs_pack[rptr_idx].al == al_csum3)
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_csum4;
} else if ((aprs_pack[rptr_idx].al == al_csum4) && (c == ',')) {
}
else if ((aprs_pack[rptr_idx].al == al_csum4) && (c == ','))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
aprs_pack[rptr_idx].al = al_data;
} else if ((aprs_pack[rptr_idx].al == al_data) && (c != '\r')) {
}
else if ((aprs_pack[rptr_idx].al == al_data) && (c != '\r'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
if (aprs_pack[rptr_idx].len >= 300) {
if (aprs_pack[rptr_idx].len >= 300)
{
printf("ERROR in aprs_add_data: Expected END of APRS data\n");
aprs_pack[rptr_idx].len = 0;
aprs_pack[rptr_idx].al = al_none;
}
} else if ((aprs_pack[rptr_idx].al == al_data) && (c == '\r')) {
}
else if ((aprs_pack[rptr_idx].al == al_data) && (c == '\r'))
{
aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c;
aprs_pack[rptr_idx].len++;
bool ok = CheckData(rptr_idx);
if (ok) {
if (ok)
{
aprs_pack[rptr_idx].al = al_end;
return true;
} else {
}
else
{
printf("BAD checksum in APRS data\n");
aprs_pack[rptr_idx].al = al_none;
aprs_pack[rptr_idx].len = 0;
}
} else {
}
else
{
aprs_pack[rptr_idx].al = al_none;
aprs_pack[rptr_idx].len = 0;
}
@ -362,7 +418,8 @@ bool CAPRS::CheckData(short int rptr_idx)
unsigned int my_sum;
char buf[5];
if ((rptr_idx < 0) || (rptr_idx > 2)) {
if ((rptr_idx < 0) || (rptr_idx > 2))
{
printf("CAPRS::CheckData(): rptr_idx %d is invalid\n", rptr_idx);
return false;
}
@ -383,10 +440,12 @@ unsigned int CAPRS::CalcCRC(unsigned char* buf, unsigned int len)
if (len <= 0)
return 0;
for (unsigned int j = 0; j < len; j++) {
for (unsigned int j = 0; j < len; j++)
{
unsigned int c = buf[j];
for (unsigned int i = 0; i < 8; i++) {
for (unsigned int i = 0; i < 8; i++)
{
bool xor_val = (((my_crc ^ c) & 0x01) == 0x01);
my_crc >>= 1;

@ -30,12 +30,14 @@ enum aprs_level { al_none, al_$1, al_$2, al_c1, al_r1, al_c2, al_csum1, al_csum2
enum slow_level { sl_first, sl_second };
using SPORTIP = struct portip_tag {
using SPORTIP = struct portip_tag
{
std::string ip;
int port;
};
using SMOD = struct aprs_module {
using SMOD = struct aprs_module
{
std::string call; /* KJ4NHF-B */
bool defined;
std::string band; /* 23cm ... */
@ -43,7 +45,8 @@ using SMOD = struct aprs_module {
std::string desc1, desc2, url, package_version;
};
using SRPTR = struct aprs_info {
using SRPTR = struct aprs_info
{
SPORTIP aprs;
std::string aprs_filter;
int aprs_hash;
@ -53,7 +56,8 @@ using SRPTR = struct aprs_info {
SMOD mod[3];
};
class CAPRS {
class CAPRS
{
public:
// functions
CAPRS(SRPTR *prptr);
@ -68,7 +72,8 @@ public:
private:
// data
struct {
struct
{
aprs_level al;
unsigned char data[300];
unsigned int len;
@ -77,7 +82,8 @@ private:
bool is_sent;
} aprs_pack[3];
// lock down a stream per band
struct {
struct
{
unsigned short streamID;
time_t last_time;
} aprs_streamID[3];

@ -53,23 +53,29 @@ void IRCClient::Entry()
int timer = 0;
socklen_t optlen;
while (true) {
while (true)
{
if (timer > 0) {
if (timer > 0)
{
timer--;
}
switch (state) {
switch (state)
{
case 0:
if (terminateThread) {
if (terminateThread)
{
printf("IRCClient::Entry: thread terminated at state=%d\n", state);
return;
}
if (timer == 0) {
if (timer == 0)
{
timer = 30;
if (! ircSock.Open(host_name, AF_UNSPEC, std::to_string(port))) {
if (! ircSock.Open(host_name, AF_UNSPEC, std::to_string(port)))
{
state = 4;
timer = 0;
}
@ -93,19 +99,26 @@ void IRCClient::Entry()
case 5:
if (terminateThread) {
if (terminateThread)
{
state = 6;
} else {
}
else
{
if (recvQ->isEOF()) {
if (recvQ->isEOF())
{
timer = 0;
state = 6;
} else if (proto.processQueues(recvQ, sendQ) == false) {
}
else if (proto.processQueues(recvQ, sendQ) == false)
{
timer = 0;
state = 6;
}
while ((state == 5) && sendQ->messageAvailable()) {
while ((state == 5) && sendQ->messageAvailable())
{
IRCMessage * m = sendQ->getMessage();
std::string out;
@ -116,14 +129,18 @@ void IRCClient::Entry()
safeStringCopy(buf, out.c_str(), sizeof buf);
int len = strlen(buf);
if (buf[len - 1] == 10) { // is there a NL char at the end?
if (ircSock.Write((unsigned char *)buf, len)) {
if (buf[len - 1] == 10) // is there a NL char at the end?
{
if (ircSock.Write((unsigned char *)buf, len))
{
printf("IRCClient::Entry: short write\n");
timer = 0;
state = 6;
}
} else {
}
else
{
printf("IRCClient::Entry: no NL at end, len=%d\n", len);
timer = 0;
@ -135,8 +152,10 @@ void IRCClient::Entry()
}
break;
case 6: {
if (app != NULL) {
case 6:
{
if (app != NULL)
{
app->setSendQ(NULL);
app->userListReset();
}
@ -151,7 +170,8 @@ void IRCClient::Entry()
ircSock.Close();
if (terminateThread) { // request to end the thread
if (terminateThread) // request to end the thread
{
printf("IRCClient::Entry: thread terminated at state=%d\n", state);
return;
}

@ -59,27 +59,32 @@ void CIRCDDB::kickWatchdog(const std::string &wdInfo)
// Send heard data, a false return implies a network error
bool CIRCDDB::sendHeard(const std::string &myCall, const std::string &myCallExt, const std::string &yourCall, const std::string &rpt1, const std::string &rpt2, unsigned char flag1, unsigned char flag2, unsigned char flag3)
{
if (myCall.size() != 8) {
if (myCall.size() != 8)
{
printf("CIRCDDB::sendHeard:myCall: len != 8\n");
return false;
}
if (myCallExt.size() != 4) {
if (myCallExt.size() != 4)
{
printf("CIRCDDB::sendHeard:myCallExt: len != 4\n");
return false;
}
if (yourCall.size() != 8) {
if (yourCall.size() != 8)
{
printf("CIRCDDB::sendHeard:yourCall: len != 8\n");
return false;
}
if (rpt1.size() != 8) {
if (rpt1.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt1: len != 8\n");
return false;
}
if (rpt2.size() != 8) {
if (rpt2.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt2: len != 8\n");
return false;
}
@ -90,27 +95,32 @@ bool CIRCDDB::sendHeard(const std::string &myCall, const std::string &myCallExt,
// Send heard data, a false return implies a network error
bool CIRCDDB::sendHeardWithTXMsg(const std::string &myCall, const std::string &myCallExt, const std::string &yourCall, const std::string &rpt1, const std::string &rpt2, unsigned char flag1, unsigned char flag2, unsigned char flag3, const std::string &network_destination, const std::string &tx_message)
{
if (myCall.size() != 8) {
if (myCall.size() != 8)
{
printf("CIRCDDB::sendHeard:myCall: len != 8\n");
return false;
}
if (myCallExt.size() != 4) {
if (myCallExt.size() != 4)
{
printf("CIRCDDB::sendHeard:myCallExt: len != 4\n");
return false;
}
if (yourCall.size() != 8) {
if (yourCall.size() != 8)
{
printf("CIRCDDB::sendHeard:yourCall: len != 8\n");
return false;
}
if (rpt1.size() != 8) {
if (rpt1.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt1: len != 8\n");
return false;
}
if (rpt2.size() != 8) {
if (rpt2.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt2: len != 8\n");
return false;
}
@ -120,20 +130,26 @@ bool CIRCDDB::sendHeardWithTXMsg(const std::string &myCall, const std::string &m
if (dest.size() == 0)
dest = " ";
if (dest.size() != 8) {
if (dest.size() != 8)
{
printf("CIRCDDB::sendHeard:network_destination: len != 8\n");
return false;
}
std::string msg;
if (tx_message.length() == 20) {
for (unsigned int i=0; i < tx_message.size(); i++) {
if (tx_message.length() == 20)
{
for (unsigned int i=0; i < tx_message.size(); i++)
{
char ch = tx_message.at(i);
if (ch>32 && ch<127) {
if (ch>32 && ch<127)
{
msg.push_back(ch);
} else {
}
else
{
msg.push_back('_');
}
}
@ -145,42 +161,50 @@ bool CIRCDDB::sendHeardWithTXMsg(const std::string &myCall, const std::string &m
bool CIRCDDB::sendHeardWithTXStats(const std::string &myCall, const std::string &myCallExt, const std::string &yourCall, const std::string &rpt1, const std::string &rpt2, unsigned char flag1,
unsigned char flag2, unsigned char flag3, int num_dv_frames, int num_dv_silent_frames, int num_bit_errors)
{
if (num_dv_frames<= 0 || num_dv_frames>65535) {
if (num_dv_frames<= 0 || num_dv_frames>65535)
{
printf("CIRCDDB::sendHeard:num_dv_frames not in range 1-65535\n");
return false;
}
if (num_dv_silent_frames > num_dv_frames) {
if (num_dv_silent_frames > num_dv_frames)
{
printf("CIRCDDB::sendHeard:num_dv_silent_frames > num_dv_frames\n");
return false;
}
if (num_bit_errors > 4*num_dv_frames) { // max 4 bit errors per frame
if (num_bit_errors > 4*num_dv_frames) // max 4 bit errors per frame
{
printf("CIRCDDB::sendHeard:num_bit_errors > (4*num_dv_frames)\n");
return false;
}
if (myCall.size() != 8) {
if (myCall.size() != 8)
{
printf("CIRCDDB::sendHeard:myCall: len != 8\n");
return false;
}
if (myCallExt.size() != 4) {
if (myCallExt.size() != 4)
{
printf("CIRCDDB::sendHeard:myCallExt: len != 4\n");
return false;
}
if (yourCall.size() != 8) {
if (yourCall.size() != 8)
{
printf("CIRCDDB::sendHeard:yourCall: len != 8\n");
return false;
}
if (rpt1.size() != 8) {
if (rpt1.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt1: len != 8\n");
return false;
}
if (rpt2.size() != 8) {
if (rpt2.size() != 8)
{
printf("CIRCDDB::sendHeard:rpt2: len != 8\n");
return false;
}
@ -189,17 +213,23 @@ bool CIRCDDB::sendHeardWithTXStats(const std::string &myCall, const std::string
snprintf(buf, 16, "%04x", num_dv_frames);
std::string stats = buf;
if (num_dv_silent_frames >= 0) {
if (num_dv_silent_frames >= 0)
{
snprintf(buf, 16, "%02x", num_dv_silent_frames * 100 / num_dv_frames);
stats.append(buf);
if (num_bit_errors >= 0) {
if (num_bit_errors >= 0)
{
snprintf(buf,16, "%02x", num_bit_errors * 125 / (num_dv_frames * 3));
stats.append(buf);
} else {
}
else
{
stats.append("__");
}
} else {
}
else
{
stats.append("____");
}
@ -211,7 +241,8 @@ bool CIRCDDB::sendHeardWithTXStats(const std::string &myCall, const std::string
// Send query for a user, a false return implies a network error
bool CIRCDDB::findUser(const std::string &userCallsign)
{
if (userCallsign.size() != 8) {
if (userCallsign.size() != 8)
{
printf("CIRCDDB::findUser: len != 8\n");
return false;
}
@ -232,24 +263,28 @@ bool CIRCDDB::receivePing(std::string &repeaterCallsign)
{
IRCDDB_RESPONSE_TYPE rt = app->getReplyMessageType();
if (rt != IDRT_PING) {
if (rt != IDRT_PING)
{
printf("CIRCDDB::receivePing: unexpected response type\n");
return false;
}
IRCMessage *m = app->getReplyMessage();
if (NULL == m) {
if (NULL == m)
{
printf("CIRCDDB::receivePing: no message\n");
return false;
}
if (m->getCommand().compare("IDRT_PING")) {
if (m->getCommand().compare("IDRT_PING"))
{
printf("CIRCDDB::receivePing: wrong messsage type\n");
return false;
}
if (1 != m->getParamCount()) {
if (1 != m->getParamCount())
{
printf("CIRCDDB::receivePing: unexpected number of message parameters\n");
return false;
}

@ -4,12 +4,14 @@
#include "../CacheManager.h"
enum IRCDDB_RESPONSE_TYPE {
enum IRCDDB_RESPONSE_TYPE
{
IDRT_NONE,
IDRT_PING
};
enum DSTAR_PROTOCOL {
enum DSTAR_PROTOCOL
{
DP_UNKNOWN,
DP_DEXTRA,
DP_DPLUS

@ -30,7 +30,8 @@ IRCDDBApp::IRCDDBApp(const std::string &u_chan, CCacheManager *cache) : numberOf
IRCDDBApp::~IRCDDBApp()
{
if (sendQ != NULL) {
if (sendQ != NULL)
{
delete sendQ;
}
}
@ -98,7 +99,8 @@ void IRCDDBApp::rptrQTH(const std::string &rptrcall, double latitude, double lon
void IRCDDBApp::rptrQRG(const std::string &rptrcall, double txFrequency, double duplexShift, double range, double agl)
{
if (std::regex_match(rptrcall, modulePattern)) {
if (std::regex_match(rptrcall, modulePattern))
{
std::string c = rptrcall;
ReplaceChar(c, ' ', '_');
@ -119,7 +121,8 @@ void IRCDDBApp::rptrQRG(const std::string &rptrcall, double txFrequency, double
void IRCDDBApp::kickWatchdog(const std::string &s)
{
if (s.length() > 0) {
if (s.length() > 0)
{
std::regex nonValid("[^[:graph:]]+");
std::smatch sm;
@ -141,13 +144,15 @@ int IRCDDBApp::getConnectionState()
IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType()
{
IRCMessage * m = replyQ.peekFirst();
if (m == NULL) {
if (m == NULL)
{
return IDRT_NONE;
}
std::string msgType = m->getCommand();
if (msgType == std::string("IDRT_PING")) {
if (msgType == std::string("IDRT_PING"))
{
return IDRT_PING;
}
@ -181,7 +186,8 @@ void IRCDDBApp::stopWork()
void IRCDDBApp::userJoin(const std::string &nick, const std::string &name, const std::string &addr)
{
if (0 == nick.compare(0, 2, "u-")) {
if (0 == nick.compare(0, 2, "u-"))
{
return;
}
std::string gate(name);
@ -194,7 +200,8 @@ void IRCDDBApp::userJoin(const std::string &nick, const std::string &name, const
void IRCDDBApp::userLeave(const std::string &nick)
{
if (0 == nick.compare(0, 2, "s-")) {
if (0 == nick.compare(0, 2, "s-"))
{
currentServer.clear();
state = 2;
timer = 200;
@ -203,7 +210,8 @@ void IRCDDBApp::userLeave(const std::string &nick)
}
std::string name(nick);
name.pop_back();
if ('-' == name.back()) {
if ('-' == name.back())
{
name.pop_back();
cache->eraseName(name);
ToUpper(name);
@ -252,7 +260,8 @@ void IRCDDBApp::sendPing(const std::string &to, const std::string &from)
auto nick = cache->findNameNick(name);
if (! nick.empty()) {
if (! nick.empty())
{
std::string rptr(from);
ReplaceChar(rptr, ' ', '_');
IRCMessage *m = new IRCMessage(nick, "IDRT_PING");
@ -292,7 +301,8 @@ bool IRCDDBApp::sendHeard(const std::string &myCall, const std::string &myCallEx
std::string srv = currentServer;
IRCMessageQueue *q = getSendQ();
if ((srv.length() > 0) && (state >= 6) && (q != NULL)) {
if ((srv.length() > 0) && (state >= 6) && (q != NULL))
{
std::string cmd("UPDATE ");
cmd.append(getCurrentTime());
@ -303,7 +313,8 @@ bool IRCDDBApp::sendHeard(const std::string &myCall, const std::string &myCallEx
cmd.append(" ");
cmd.append(r1);
cmd.append(" ");
if (!statsMsg) {
if (!statsMsg)
{
cmd.append("0 ");
}
cmd.append(r2);
@ -318,14 +329,18 @@ bool IRCDDBApp::sendHeard(const std::string &myCall, const std::string &myCallEx
cmd.append(" ");
cmd.append(myext);
if (statsMsg) {
if (statsMsg)
{
cmd.append(" # ");
cmd.append(tx_stats);
} else {
}
else
{
cmd.append(" 00 ");
cmd.append(dest);
if (tx_msg.length() == 20) {
if (tx_msg.length() == 20)
{
cmd.append(" ");
cmd.append(tx_msg);
}
@ -336,7 +351,8 @@ bool IRCDDBApp::sendHeard(const std::string &myCall, const std::string &myCallEx
q->putMessage(m);
return true;
} else
}
else
return false;
}
@ -345,7 +361,8 @@ bool IRCDDBApp::findUser(const std::string &usrCall)
std::string srv = currentServer;
IRCMessageQueue *q = getSendQ();
if ((srv.length() > 0) && (state >= 6) && (q != NULL)) {
if ((srv.length() > 0) && (state >= 6) && (q != NULL))
{
std::string usr = usrCall;
ReplaceChar(usr, ' ', '_');
@ -360,7 +377,8 @@ bool IRCDDBApp::findUser(const std::string &usrCall)
void IRCDDBApp::msgChannel(IRCMessage *m)
{
if (0==m->getPrefixNick().compare(0, 2, "s-") && (m->numParams >= 2)) { // server msg
if (0==m->getPrefixNick().compare(0, 2, "s-") && (m->numParams >= 2)) // server msg
{
doUpdate(m->params[1]);
}
}
@ -378,10 +396,12 @@ void IRCDDBApp::doNotFound(std::string &msg, std::string &retval)
tkz.erase(tkz.begin());
if (std::regex_match(tk, tablePattern)) {
if (std::regex_match(tk, tablePattern))
{
long tableID = std::stol(tk);
if ((tableID < 0) || (tableID >= numberOfTables)) {
if ((tableID < 0) || (tableID >= numberOfTables))
{
printf("invalid table ID %ld", tableID);
return;
}
@ -393,7 +413,8 @@ void IRCDDBApp::doNotFound(std::string &msg, std::string &retval)
tk.erase(tk.begin());
}
if (tableID == 0) {
if (tableID == 0)
{
if (! std::regex_match(tk, dbPattern))
return; // no valid key
@ -413,9 +434,11 @@ void IRCDDBApp::doUpdate(std::string &msg)
std::string tk = tkz.front();
tkz.erase(tkz.begin());
if (std::regex_match(tk, tablePattern)) {
if (std::regex_match(tk, tablePattern))
{
tableID = stol(tk);
if ((tableID < 0) || (tableID >= numberOfTables)) {
if ((tableID < 0) || (tableID >= numberOfTables))
{
printf("invalid table ID %d", tableID);
return;
}
@ -427,7 +450,8 @@ void IRCDDBApp::doUpdate(std::string &msg)
tkz.erase(tkz.begin());
}
if (std::regex_match(tk, datePattern)) {
if (std::regex_match(tk, datePattern))
{
if (0 == tkz.size())
return; // nothing after date string
@ -440,7 +464,8 @@ void IRCDDBApp::doUpdate(std::string &msg)
std::string tstr(std::string(tk + " " + timeToken)); // used to update user time
auto rtime = parseTime(tstr); // used to update maxTime for sendlist
if ((tableID == 0) || (tableID == 1)) {
if ((tableID == 0) || (tableID == 1))
{
if (0 == tkz.size())
return; // nothing after time string
@ -461,9 +486,11 @@ void IRCDDBApp::doUpdate(std::string &msg)
//printf("TABLE %d %s %s\n", tableID, key.c_str(), value.c_str());
if (tableID == 1) {
if (tableID == 1)
{
if (initReady && key.compare(0,6, value, 0, 6)) {
if (initReady && key.compare(0,6, value, 0, 6))
{
std::string rptr(key);
std::string gate(value);
@ -474,7 +501,9 @@ void IRCDDBApp::doUpdate(std::string &msg)
if (rtime > maxTime)
maxTime = rtime;
}
} else if ((tableID == 0) && initReady) {
}
else if ((tableID == 0) && initReady)
{
std::string user(key);
std::string rptr(value);
@ -490,15 +519,23 @@ void IRCDDBApp::doUpdate(std::string &msg)
std::string IRCDDBApp::getTableIDString(int tableID, bool spaceBeforeNumber)
{
if (tableID == 0) {
if (tableID == 0)
{
return std::string("");
} else if ((tableID > 0) && (tableID < numberOfTables)) {
if (spaceBeforeNumber) {
}
else if ((tableID > 0) && (tableID < numberOfTables))
{
if (spaceBeforeNumber)
{
return std::string(" ") + std::to_string(tableID);
} else {
}
else
{
return std::to_string(tableID) + std::string(" ");
}
} else {
}
else
{
return std::string(" TABLE_ID_OUT_OF_RANGE ");
}
}
@ -506,7 +543,8 @@ std::string IRCDDBApp::getTableIDString(int tableID, bool spaceBeforeNumber)
void IRCDDBApp::msgQuery(IRCMessage *m)
{
if (0 == strcmp(m->getPrefixNick().substr(0,2).c_str(), "s-") && (m->numParams >= 2)) { // server msg
if (0 == strcmp(m->getPrefixNick().substr(0,2).c_str(), "s-") && (m->numParams >= 2)) // server msg
{
std::string msg = m->params[1];
std::vector<std::string> tkz = stringTokenizer(msg);
@ -516,27 +554,38 @@ void IRCDDBApp::msgQuery(IRCMessage *m)
std::string cmd = tkz.front();
tkz.erase(tkz.begin());
if (cmd == std::string("UPDATE")) {
if (cmd == std::string("UPDATE"))
{
std::string restOfLine;
while (tkz.size()) {
while (tkz.size())
{
restOfLine += tkz.front();
tkz.erase(tkz.begin());
if (tkz.size())
restOfLine += " ";
}
doUpdate(restOfLine);
} else if (cmd == std::string("LIST_END")) {
if (state == 5) { // if in sendlist processing state
}
else if (cmd == std::string("LIST_END"))
{
if (state == 5) // if in sendlist processing state
{
state = 3; // get next table
}
} else if (cmd == std::string("LIST_MORE")) {
if (state == 5) { // if in sendlist processing state
}
else if (cmd == std::string("LIST_MORE"))
{
if (state == 5) // if in sendlist processing state
{
state = 4; // send next SENDLIST
}
} else if (cmd == std::string("NOT_FOUND")) {
}
else if (cmd == std::string("NOT_FOUND"))
{
std::string callsign;
std::string restOfLine;
while (tkz.size()) {
while (tkz.size())
{
restOfLine += tkz.front();
tkz.erase(tkz.begin());
if (tkz.size())
@ -544,7 +593,8 @@ void IRCDDBApp::msgQuery(IRCMessage *m)
}
doNotFound(restOfLine, callsign);
if (callsign.length() > 0) {
if (callsign.length() > 0)
{
ReplaceChar(callsign, '_', ' ');
IRCMessage *m2 = new IRCMessage("IDRT_USER");
@ -571,7 +621,8 @@ IRCMessageQueue *IRCDDBApp::getSendQ()
std::string IRCDDBApp::getLastEntryTime(int tableID)
{
if (tableID == 1) {
if (tableID == 1)
{
struct tm *ptm = gmtime(&maxTime);
char tstr[80];
strftime(tstr, 80, "%Y-%m-%d %H:%M:%S", ptm);
@ -586,16 +637,20 @@ void IRCDDBApp::Entry()
{
int sendlistTableID = 0;
while (!terminateThread) {
while (!terminateThread)
{
if (timer > 0) {
if (timer > 0)
{
timer--;
}
switch(state) {
switch(state)
{
case 0: // wait for network to start
if (getSendQ() != NULL) {
if (getSendQ() != NULL)
{
state = 1;
}
break;
@ -608,21 +663,28 @@ void IRCDDBApp::Entry()
case 2: // choose server
printf("IRCDDBApp: state=2 choose new 's-'-user\n");
if (getSendQ() == NULL) {
if (getSendQ() == NULL)
{
state = 10;
} else {
if (findServerUser()) {
}
else
{
if (findServerUser())
{
sendlistTableID = numberOfTables;
state = 3; // next: send "SENDLIST"
} else if (timer == 0) {
}
else if (timer == 0)
{
state = 10;
IRCMessage *m = new IRCMessage("QUIT");
m->addParam("no op user with 's-' found.");
IRCMessageQueue * q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
}
@ -630,13 +692,19 @@ void IRCDDBApp::Entry()
break;
case 3:
if (getSendQ() == NULL) {
if (getSendQ() == NULL)
{
state = 10; // disconnect DB
} else {
}
else
{
sendlistTableID --;
if (sendlistTableID < 0) {
if (sendlistTableID < 0)
{
state = 6; // end of sendlist
} else {
}
else
{
printf("IRCDDBApp: state=3 tableID=%d\n", sendlistTableID);
state = 4; // send "SENDLIST"
timer = 900; // 15 minutes max for update
@ -645,10 +713,14 @@ void IRCDDBApp::Entry()
break;
case 4:
if (getSendQ() == NULL) {
if (getSendQ() == NULL)
{
state = 10; // disconnect DB
} else {
if (1 == sendlistTableID) {
}
else
{
if (1 == sendlistTableID)
{
IRCMessage *m = new IRCMessage(currentServer, std::string("SENDLIST") + getTableIDString(sendlistTableID, true)
+ std::string(" ") + getLastEntryTime(sendlistTableID));
@ -657,22 +729,27 @@ void IRCDDBApp::Entry()
q->putMessage(m);
state = 5; // wait for answers
} else
}
else
state = 3; // don't send SENDLIST for this table (tableID 0), go to next table
}
break;
case 5: // sendlist processing
if (getSendQ() == NULL) {
if (getSendQ() == NULL)
{
state = 10; // disconnect DB
} else if (timer == 0) {
}
else if (timer == 0)
{
state = 10; // disconnect DB
IRCMessage *m = new IRCMessage("QUIT");
m->addParam("timeout SENDLIST");
IRCMessageQueue *q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
@ -680,9 +757,12 @@ void IRCDDBApp::Entry()
break;
case 6:
if (getSendQ() == NULL) {
if (getSendQ() == NULL)
{
state = 10; // disconnect DB
} else {
}
else
{
printf("IRCDDBApp: state=6 initialization completed\n");
infoTimer = 2;
@ -697,48 +777,58 @@ void IRCDDBApp::Entry()
if (getSendQ() == NULL)
state = 10; // disconnect DB
if (infoTimer > 0) {
if (infoTimer > 0)
{
infoTimer--;
if (infoTimer == 0) {
if (infoTimer == 0)
{
moduleMapMutex.lock();
for (auto itl = locationMap.begin(); itl != locationMap.end(); itl++) {
for (auto itl = locationMap.begin(); itl != locationMap.end(); itl++)
{
std::string value = itl->second;
IRCMessage *m = new IRCMessage(currentServer, std::string("IRCDDB RPTRQTH: ") + value);
IRCMessageQueue * q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
}
for (auto itu = urlMap.begin(); itu != urlMap.end(); itu++) {
for (auto itu = urlMap.begin(); itu != urlMap.end(); itu++)
{
std::string value = itu->second;
IRCMessage * m = new IRCMessage(currentServer, std::string("IRCDDB RPTRURL: ") + value);
IRCMessageQueue * q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
}
for(auto itm = moduleMap.begin(); itm != moduleMap.end(); itm++) {
for(auto itm = moduleMap.begin(); itm != moduleMap.end(); itm++)
{
std::string value = itm->second;
IRCMessage * m = new IRCMessage(currentServer, std::string("IRCDDB RPTRQRG: ") + value);
IRCMessageQueue *q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
}
for(auto its = swMap.begin(); its != swMap.end(); its++) {
for(auto its = swMap.begin(); its != swMap.end(); its++)
{
std::string value = its->second;
IRCMessage * m = new IRCMessage(currentServer, std::string("IRCDDB RPTRSW: ") + value);
IRCMessageQueue *q = getSendQ();
if (q != NULL) {
if (q != NULL)
{
q->putMessage(m);
}
}
@ -747,9 +837,11 @@ void IRCDDBApp::Entry()
}
}
if (wdTimer > 0) {
if (wdTimer > 0)
{
wdTimer--;
if (wdTimer <= 0) {
if (wdTimer <= 0)
{
wdTimer = 900; // 15 minutes
IRCMessage *m = new IRCMessage(currentServer, std::string("IRCDDB WATCHDOG: ") +

@ -56,16 +56,19 @@ void IRCMessage::parsePrefix()
{
unsigned int i;
for (i=0; i < 3; i++) {
for (i=0; i < 3; i++)
{
prefixComponents.push_back("");
}
int state = 0;
for (i=0; i < prefix.length(); i++) {
for (i=0; i < prefix.length(); i++)
{
char c = prefix.at(i);
switch (c) {
switch (c)
{
case '!':
state = 1; // next is name
break;
@ -85,7 +88,8 @@ void IRCMessage::parsePrefix()
std::string &IRCMessage::getPrefixNick()
{
if (!prefixParsed) {
if (!prefixParsed)
{
parsePrefix();
}
@ -94,7 +98,8 @@ std::string &IRCMessage::getPrefixNick()
std::string &IRCMessage::getPrefixName()
{
if (!prefixParsed) {
if (!prefixParsed)
{
parsePrefix();
}
@ -103,7 +108,8 @@ std::string &IRCMessage::getPrefixName()
std::string &IRCMessage::getPrefixHost()
{
if (!prefixParsed) {
if (!prefixParsed)
{
parsePrefix();
}
@ -114,16 +120,21 @@ void IRCMessage::composeMessage(std::string &output)
{
std::string o;
if (prefix.length() > 0) {
if (prefix.length() > 0)
{
o = std::string(":") + prefix + ' ';
}
o += command;
for (int i=0; i < numParams; i++) {
if (i == (numParams - 1)) {
for (int i=0; i < numParams; i++)
{
if (i == (numParams - 1))
{
o += (std::string(" :") + params[i]);
} else {
}
else
{
o += (std::string(" ") + params[i]);
}
}

@ -31,7 +31,8 @@ IRCMessageQueue::IRCMessageQueue()
IRCMessageQueue::~IRCMessageQueue()
{
accessMutex.lock();
while (! m_queue.empty()) {
while (! m_queue.empty())
{
delete m_queue.front();
m_queue.pop();
}

@ -20,7 +20,8 @@ void IRCProtocol::Init(IRCDDBApp *app, const std::string &callsign, const std::s
this->versionInfo = "CIRCDDB:";
this->versionInfo.append(CIRCDDB_VERSION);
if (versionInfo.length() > 0) {
if (versionInfo.length() > 0)
{
this->versionInfo.append(" ");
this->versionInfo.append(versionInfo);
}
@ -28,7 +29,8 @@ void IRCProtocol::Init(IRCDDBApp *app, const std::string &callsign, const std::s
int hyphenPos = callsign.find('-');
if (hyphenPos < 0) {
if (hyphenPos < 0)
{
std::string n;
n = callsign + "-1";
@ -39,7 +41,9 @@ void IRCProtocol::Init(IRCDDBApp *app, const std::string &callsign, const std::s
nicks.push_back(n);
n = callsign + "-4";
nicks.push_back(n);
} else {
}
else
{
nicks.push_back(callsign);
}
@ -66,13 +70,16 @@ void IRCProtocol::chooseNewNick()
void IRCProtocol::setNetworkReady(bool b)
{
if (b == true) {
if (b == true)
{
if (state != 0)
printf("IRCProtocol::setNetworkReady: unexpected state");
state = 1;
chooseNewNick();
} else {
}
else
{
state = 0;
}
}
@ -80,16 +87,19 @@ void IRCProtocol::setNetworkReady(bool b)
bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
{
if (timer > 0) {
if (timer > 0)
{
timer--;
}
while (recvQ->messageAvailable()) {
while (recvQ->messageAvailable())
{
IRCMessage *m = recvQ->getMessage();
#if defined(DEBUG_IRC)
std::string d = std::string("R [") + m->prefix + std::string("] [") + m->command + std::string("]");
for (int i=0; i < m->numParams; i++) {
for (int i=0; i < m->numParams; i++)
{
d.append(std::string(" [") + m->params[i] + std::string("]") );
}
// d.Replace(std::string("%"), std::string("%%"), true);
@ -97,96 +107,146 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
printf("%s\n", d.c_str());
#endif
if (0 == m->command.compare("004")) {
if (state == 4) {
if (m->params.size() > 1) {
if (0 == m->command.compare("004"))
{
if (state == 4)
{
if (m->params.size() > 1)
{
std::regex serverNamePattern("^grp[1-9]s[1-9].ircDDB$");
if (std::regex_match(m->params[1], serverNamePattern)) {
if (std::regex_match(m->params[1], serverNamePattern))
{
app->setBestServer(std::string("s-") + m->params[1].substr(0,6));
}
}
state = 5; // next: JOIN
app->setCurrentNick(currentNick);
}
} else if (0 == m->command.compare("PING")) {
}
else if (0 == m->command.compare("PING"))
{
IRCMessage *m2 = new IRCMessage();
m2->command = "PONG";
if (m->params.size() > 0) {
if (m->params.size() > 0)
{
m2->numParams = 1;
m2->params.push_back( m->params[0] );
}
sendQ -> putMessage(m2);
} else if (0 == m->command.compare("JOIN")) {
if ((m->numParams >= 1) && 0==m->params[0].compare(channel)) {
if (0==m->getPrefixNick().compare(currentNick) && (state == 6)) {
if (debugChannel.length() > 0) {
}
else if (0 == m->command.compare("JOIN"))
{
if ((m->numParams >= 1) && 0==m->params[0].compare(channel))
{
if (0==m->getPrefixNick().compare(currentNick) && (state == 6))
{
if (debugChannel.length() > 0)
{
state = 7; // next: join debug_channel
} else {
}
else
{
state = 10; // next: WHO *
}
} else if (app != NULL) {
}
else if (app != NULL)
{
app->userJoin( m->getPrefixNick(), m->getPrefixName(), m->getPrefixHost());
}
}
if ((m->numParams >= 1) && 0==m->params[0].compare(debugChannel)) {
if (0==m->getPrefixNick().compare(currentNick) && (state == 8)) {
if ((m->numParams >= 1) && 0==m->params[0].compare(debugChannel))
{
if (0==m->getPrefixNick().compare(currentNick) && (state == 8))
{
state = 10; // next: WHO *
}
}
} else if (0 == m->command.compare("PONG")) {
if (state == 12) {
}
else if (0 == m->command.compare("PONG"))
{
if (state == 12)
{
timer = pingTimer;
state = 11;
}
} else if (0 == m->command.compare("PART")) {
if ((m->numParams >= 1) && 0==m->params[0].compare(channel)) {
if (app != NULL) {
}
else if (0 == m->command.compare("PART"))
{
if ((m->numParams >= 1) && 0==m->params[0].compare(channel))
{
if (app != NULL)
{
app->userLeave( m->getPrefixNick() );
}
}
} else if (0 == m->command.compare("KICK")) {
if ((m->numParams >= 2) && 0==m->params[0].compare(channel)) {
if (0 == m->params[1].compare(currentNick)) {
}
else if (0 == m->command.compare("KICK"))
{
if ((m->numParams >= 2) && 0==m->params[0].compare(channel))
{
if (0 == m->params[1].compare(currentNick))
{
// i was kicked!!
delete m;
return false;
} else if (app != NULL) {
}
else if (app != NULL)
{
app->userLeave( m->params[1] );
}
}
} else if (0 == m->command.compare("QUIT")) {
if (app != NULL) {
}
else if (0 == m->command.compare("QUIT"))
{
if (app != NULL)
{
app->userLeave( m->getPrefixNick() );
}
} else if (0 == m->command.compare("PRIVMSG")) {
if (app) {
}
else if (0 == m->command.compare("PRIVMSG"))
{
if (app)
{
// std::string out;
// m->composeMessage(out);
// out.pop_back(); out.pop_back();
if (2 == m->numParams) {
if (0 == m->params[0].compare(channel)) {
if (2 == m->numParams)
{
if (0 == m->params[0].compare(channel))
{
app->msgChannel(m);
} else if (0 == m->params[0].compare(currentNick)) {
if (0 == m->params[1].find("IDRT_PING")) {
}
else if (0 == m->params[0].compare(currentNick))
{
if (0 == m->params[1].find("IDRT_PING"))
{
std::string from = m->params[1].substr(10);
IRCMessage *rm = new IRCMessage("IDRT_PING");
rm->addParam(from);
app->putReplyMessage(rm);
} else
}
else
app->msgQuery(m);
}
}
}
} else if (0 == m->command.compare("352")) { // WHO list
if ((m->numParams >= 7) && 0==m->params[0].compare(currentNick) && 0==m->params[1].compare(channel)) {
if (app != NULL) {
}
else if (0 == m->command.compare("352")) // WHO list
{
if ((m->numParams >= 7) && 0==m->params[0].compare(currentNick) && 0==m->params[1].compare(channel))
{
if (app != NULL)
{
app->userJoin(m->params[5], m->params[2], m->params[3]);
}
}
} else if (0 == m->command.compare("433")) { // nick collision
if (state == 2) {
}
else if (0 == m->command.compare("433")) // nick collision
{
if (state == 2)
{
state = 3; // nick collision, choose new nick
timer = 10; // wait 5 seconds..
}
@ -197,7 +257,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
IRCMessage * m;
switch (state) {
switch (state)
{
case 1:
m = new IRCMessage();
m->command = "PASS";
@ -216,7 +277,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 2:
if (timer == 0) {
if (timer == 0)
{
m = new IRCMessage();
m->command = "USER";
m->numParams = 4;
@ -232,7 +294,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 3:
if (timer == 0) {
if (timer == 0)
{
chooseNewNick();
m = new IRCMessage();
m->command = "NICK";
@ -246,7 +309,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 4:
if (timer == 0) {
if (timer == 0)
{
// no login message received -> disconnect
return false;
}
@ -264,14 +328,16 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 6:
if (timer == 0) {
if (timer == 0)
{
// no join message received -> disconnect
return false;
}
break;
case 7:
if (debugChannel.length() == 0) {
if (debugChannel.length() == 0)
{
return false; // this state cannot be processed if there is no debug_channel
}
@ -286,7 +352,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 8:
if (timer == 0) {
if (timer == 0)
{
// no join message received -> disconnect
return false;
}
@ -303,13 +370,15 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
timer = pingTimer;
state = 11; // wait for timer and then send ping
if (app != NULL) {
if (app != NULL)
{
app->setSendQ(sendQ); // this switches the application on
}
break;
case 11:
if (timer == 0) {
if (timer == 0)
{
m = new IRCMessage();
m->command = "PING";
m->numParams = 1;
@ -322,7 +391,8 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ)
break;
case 12:
if (timer == 0) {
if (timer == 0)
{
// no pong message received -> disconnect
return false;
}

@ -47,25 +47,34 @@ int IRCReceiver::doRead(CTCPReaderWriterClient *ircSock, char *buf, int buf_size
res = select(fd+1, &rdset, NULL, &errset, &tv);
if ( res < 0 ) {
if ( res < 0 )
{
printf("IRCReceiver::doread: select() error.\n");
return -1;
} else if ( res > 0 ) {
if (FD_ISSET(fd, &errset)) {
}
else if ( res > 0 )
{
if (FD_ISSET(fd, &errset))
{
printf("IRCReceiver::doRead: FD_ISSET error\n");
return -1;
}
if (FD_ISSET(fd, &rdset)) {
if (FD_ISSET(fd, &rdset))
{
res = ircSock->Read((unsigned char *)buf, buf_size);
if (res < 0) {
if (res < 0)
{
printf("IRCReceiver::doRead: recv error\n");
return -1;
} else if (res == 0) {
}
else if (res == 0)
{
printf("IRCReceiver::doRead: EOF read==0\n");
return -1;
} else
}
else
return res;
}
@ -81,67 +90,93 @@ void IRCReceiver::Entry()
int i;
int state = 0;
while (!terminateThread) {
while (!terminateThread)
{
char buf[200];
int r = doRead(ircSock, buf, sizeof buf);
if (r < 0) {
if (r < 0)
{
recvQ->signalEOF();
delete m; // delete unfinished IRCMessage
break;
}
for (i=0; i<r; i++) {
for (i=0; i<r; i++)
{
char b = buf[i];
if (b > 0) {
if (b == '\n') {
if (b > 0)
{
if (b == '\n')
{
recvQ->putMessage(m);
m = new IRCMessage();
state = 0;
} else if (b == '\r') {
}
else if (b == '\r')
{
// do nothing
} else switch (state) {
}
else switch (state)
{
case 0:
if (b == ':') {
if (b == ':')
{
state = 1; // prefix
} else if (b == ' ') {
}
else if (b == ' ')
{
// do nothing
} else {
}
else
{
m->command.push_back(b);
state = 2; // command
}
break;
case 1:
if (b == ' ') {
if (b == ' ')
{
state = 2; // command is next
} else {
}
else
{
m->prefix.push_back(b);
}
break;
case 2:
if (b == ' ') {
if (b == ' ')
{
state = 3; // params
m->numParams = 1;
m->params.push_back("");
} else {
}
else
{
m->command.push_back(b);
}
break;
case 3:
if (b == ' ') {
if (b == ' ')
{
m->numParams++;
if (m->numParams >= 15) {
if (m->numParams >= 15)
{
state = 5; // ignore the rest
}
m->params.push_back("");
} else if ((b == ':') && (m->params[m->numParams - 1].length() == 0)) {
}
else if ((b == ':') && (m->params[m->numParams - 1].length() == 0))
{
state = 4; // rest of line is this param
} else {
}
else
{
m->params[m->numParams - 1].push_back(b);
}
break;

@ -39,7 +39,8 @@ void safeStringCopy (char *dest, const char *src, unsigned int buf_size)
{
unsigned int i = 0;
while (i<(buf_size - 1) && src[i] != 0) {
while (i<(buf_size - 1) && src[i] != 0)
{
dest[i] = src[i];
i++;
}
@ -64,7 +65,8 @@ char *getCurrentTime(void)
void ToUpper(std::string &str)
{
for (auto it=str.begin(); it!=str.end(); it++) {
for (auto it=str.begin(); it!=str.end(); it++)
{
if (islower(*it))
*it = toupper(*it);
}
@ -72,7 +74,8 @@ void ToUpper(std::string &str)
void ToLower(std::string &str)
{
for (auto it=str.begin(); it!=str.end(); it++) {
for (auto it=str.begin(); it!=str.end(); it++)
{
if (isupper(*it))
*it = tolower(*it);
}
@ -81,7 +84,8 @@ void ToLower(std::string &str)
void ReplaceChar(std::string &str, char from, char to)
{
for (auto it=str.begin(); it!=str.end(); it++) {
for (auto it=str.begin(); it!=str.end(); it++)
{
if (from == *it)
*it = to;
}

Loading…
Cancel
Save

Powered by TurnKey Linux.