Merge branch 'SimpleDMR' into AX25_FM
This commit is contained in:
commit
98b1e6478b
|
@ -34,8 +34,8 @@ const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
|
||||||
|
|
||||||
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
|
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
|
||||||
m_addressStr(address),
|
m_addressStr(address),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_port(port),
|
m_port(port),
|
||||||
m_id(NULL),
|
m_id(NULL),
|
||||||
m_duplex(duplex),
|
m_duplex(duplex),
|
||||||
|
@ -62,7 +62,8 @@ m_pingTimer(1000U, 10U)
|
||||||
assert(port > 0U);
|
assert(port > 0U);
|
||||||
assert(id > 1000U);
|
assert(id > 1000U);
|
||||||
|
|
||||||
CUDPSocket::lookup(m_addressStr, m_port, m_address, m_addrlen);
|
if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
|
|
||||||
m_buffer = new unsigned char[BUFFER_LENGTH];
|
m_buffer = new unsigned char[BUFFER_LENGTH];
|
||||||
m_id = new uint8_t[4U];
|
m_id = new uint8_t[4U];
|
||||||
|
@ -100,12 +101,14 @@ void CDMRNetwork::setConfig(const std::string & callsign, unsigned int rxFrequen
|
||||||
|
|
||||||
bool CDMRNetwork::open()
|
bool CDMRNetwork::open()
|
||||||
{
|
{
|
||||||
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the DMR Gateway");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LogMessage("DMR, Opening DMR Network");
|
LogMessage("DMR, Opening DMR Network");
|
||||||
|
|
||||||
if (CUDPSocket::isnone(m_address))
|
bool ret = m_socket.open(m_addr);
|
||||||
CUDPSocket::lookup(m_addressStr, m_port, m_address, m_addrlen);
|
|
||||||
|
|
||||||
bool ret = m_socket.open();
|
|
||||||
if (ret)
|
if (ret)
|
||||||
m_pingTimer.start();
|
m_pingTimer.start();
|
||||||
|
|
||||||
|
@ -297,26 +300,25 @@ void CDMRNetwork::clock(unsigned int ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CUDPSocket::match(m_address, address)) {
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
LogMessage("DMR, packet received from an invalid source");
|
LogMessage("DMR, packet received from an invalid source");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Network Received", m_buffer, length);
|
CUtils::dump(1U, "Network Received", m_buffer, length);
|
||||||
|
|
||||||
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
|
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
|
||||||
unsigned char len = length;
|
if (m_enabled) {
|
||||||
m_rxData.addData(&len, 1U);
|
unsigned char len = length;
|
||||||
m_rxData.addData(m_buffer, len);
|
m_rxData.addData(&len, 1U);
|
||||||
|
m_rxData.addData(m_buffer, len);
|
||||||
|
}
|
||||||
} else if (::memcmp(m_buffer, "DMRP", 4U) == 0) {
|
} else if (::memcmp(m_buffer, "DMRP", 4U) == 0) {
|
||||||
;
|
;
|
||||||
} else if (::memcmp(m_buffer, "DMRB", 4U) == 0) {
|
} else if (::memcmp(m_buffer, "DMRB", 4U) == 0) {
|
||||||
|
@ -427,7 +429,7 @@ bool CDMRNetwork::write(const unsigned char* data, unsigned int length)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Network Transmitted", data, length);
|
CUtils::dump(1U, "Network Transmitted", data, length);
|
||||||
|
|
||||||
bool ret = m_socket.write(data, length, m_address, m_addrlen);
|
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
LogError("DMR, socket error when writing to the DMR Gateway");
|
LogError("DMR, socket error when writing to the DMR Gateway");
|
||||||
return false;
|
return false;
|
||||||
|
|
46
DMRNetwork.h
46
DMRNetwork.h
|
@ -56,30 +56,30 @@ public:
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_addressStr;
|
std::string m_addressStr;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
unsigned int m_port;
|
unsigned int m_port;
|
||||||
uint8_t* m_id;
|
uint8_t* m_id;
|
||||||
bool m_duplex;
|
bool m_duplex;
|
||||||
const char* m_version;
|
const char* m_version;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
bool m_slot1;
|
bool m_slot1;
|
||||||
bool m_slot2;
|
bool m_slot2;
|
||||||
HW_TYPE m_hwType;
|
HW_TYPE m_hwType;
|
||||||
unsigned char* m_buffer;
|
unsigned char* m_buffer;
|
||||||
uint32_t* m_streamId;
|
uint32_t* m_streamId;
|
||||||
CRingBuffer<unsigned char> m_rxData;
|
CRingBuffer<unsigned char> m_rxData;
|
||||||
bool m_beacon;
|
bool m_beacon;
|
||||||
std::mt19937 m_random;
|
std::mt19937 m_random;
|
||||||
std::string m_callsign;
|
std::string m_callsign;
|
||||||
unsigned int m_rxFrequency;
|
unsigned int m_rxFrequency;
|
||||||
unsigned int m_txFrequency;
|
unsigned int m_txFrequency;
|
||||||
unsigned int m_power;
|
unsigned int m_power;
|
||||||
unsigned int m_colorCode;
|
unsigned int m_colorCode;
|
||||||
CTimer m_pingTimer;
|
CTimer m_pingTimer;
|
||||||
|
|
||||||
bool writeConfig();
|
bool writeConfig();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016,2019 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2019,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,8 +32,8 @@ const unsigned int BUFFER_LENGTH = 100U;
|
||||||
|
|
||||||
CDStarNetwork::CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug) :
|
CDStarNetwork::CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug) :
|
||||||
m_socket(localPort),
|
m_socket(localPort),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_duplex(duplex),
|
m_duplex(duplex),
|
||||||
m_version(version),
|
m_version(version),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
|
@ -47,7 +47,8 @@ m_linkStatus(LS_NONE),
|
||||||
m_linkReflector(NULL),
|
m_linkReflector(NULL),
|
||||||
m_random()
|
m_random()
|
||||||
{
|
{
|
||||||
CUDPSocket::lookup(gatewayAddress, gatewayPort, m_address, m_addrlen);
|
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
|
|
||||||
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
|
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
|
||||||
|
|
||||||
|
@ -63,14 +64,16 @@ CDStarNetwork::~CDStarNetwork()
|
||||||
|
|
||||||
bool CDStarNetwork::open()
|
bool CDStarNetwork::open()
|
||||||
{
|
{
|
||||||
LogMessage("Opening D-Star network connection");
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the ircDDB Gateway");
|
||||||
if (CUDPSocket::isnone(m_address))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage("Opening D-Star network connection");
|
||||||
|
|
||||||
m_pollTimer.start();
|
m_pollTimer.start();
|
||||||
|
|
||||||
return m_socket.open(m_address.ss_family);
|
return m_socket.open(m_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length, bool busy)
|
bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length, bool busy)
|
||||||
|
@ -103,7 +106,7 @@ bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length
|
||||||
CUtils::dump(1U, "D-Star Network Header Sent", buffer, 49U);
|
CUtils::dump(1U, "D-Star Network Header Sent", buffer, 49U);
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 2U; i++) {
|
for (unsigned int i = 0U; i < 2U; i++) {
|
||||||
bool ret = m_socket.write(buffer, 49U, m_address, m_addrlen);
|
bool ret = m_socket.write(buffer, 49U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +149,7 @@ bool CDStarNetwork::writeData(const unsigned char* data, unsigned int length, un
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "D-Star Network Data Sent", buffer, length + 9U);
|
CUtils::dump(1U, "D-Star Network Data Sent", buffer, length + 9U);
|
||||||
|
|
||||||
return m_socket.write(buffer, length + 9U, m_address, m_addrlen);
|
return m_socket.write(buffer, length + 9U, m_addr, m_addrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDStarNetwork::writePoll(const char* text)
|
bool CDStarNetwork::writePoll(const char* text)
|
||||||
|
@ -170,7 +173,7 @@ bool CDStarNetwork::writePoll(const char* text)
|
||||||
// if (m_debug)
|
// if (m_debug)
|
||||||
// CUtils::dump(1U, "D-Star Network Poll Sent", buffer, 6U + length);
|
// CUtils::dump(1U, "D-Star Network Poll Sent", buffer, 6U + length);
|
||||||
|
|
||||||
return m_socket.write(buffer, 6U + length, m_address, m_addrlen);
|
return m_socket.write(buffer, 6U + length, m_addr, m_addrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarNetwork::clock(unsigned int ms)
|
void CDStarNetwork::clock(unsigned int ms)
|
||||||
|
@ -196,11 +199,16 @@ void CDStarNetwork::clock(unsigned int ms)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match(m_address, address))
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
|
LogMessage("D-Star, packet received from an invalid source");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Invalid packet type?
|
// Invalid packet type?
|
||||||
if (::memcmp(buffer, "DSRP", 4U) != 0)
|
if (::memcmp(buffer, "DSRP", 4U) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -51,21 +51,21 @@ public:
|
||||||
void clock(unsigned int ms);
|
void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
bool m_duplex;
|
bool m_duplex;
|
||||||
const char* m_version;
|
const char* m_version;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
uint16_t m_outId;
|
uint16_t m_outId;
|
||||||
uint8_t m_outSeq;
|
uint8_t m_outSeq;
|
||||||
uint16_t m_inId;
|
uint16_t m_inId;
|
||||||
CRingBuffer<unsigned char> m_buffer;
|
CRingBuffer<unsigned char> m_buffer;
|
||||||
CTimer m_pollTimer;
|
CTimer m_pollTimer;
|
||||||
LINK_STATUS m_linkStatus;
|
LINK_STATUS m_linkStatus;
|
||||||
unsigned char* m_linkReflector;
|
unsigned char* m_linkReflector;
|
||||||
std::mt19937 m_random;
|
std::mt19937 m_random;
|
||||||
|
|
||||||
bool writePoll(const char* text);
|
bool writePoll(const char* text);
|
||||||
};
|
};
|
||||||
|
|
|
@ -359,10 +359,13 @@ int CMMDVMHost::run()
|
||||||
LogInfo(" Local Port: %u", localPort);
|
LogInfo(" Local Port: %u", localPort);
|
||||||
LogInfo(" Send Frame Type: %u", sendFrameType);
|
LogInfo(" Send Frame Type: %u", sendFrameType);
|
||||||
|
|
||||||
CUDPSocket::lookup(remoteAddress, remotePort, transparentAddress, transparentAddrLen);
|
if (CUDPSocket::lookup(remoteAddress, remotePort, transparentAddress, transparentAddrLen) != 0) {
|
||||||
|
LogError("Unable to resolve the address of the Transparent Data source");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
transparentSocket = new CUDPSocket(localPort);
|
transparentSocket = new CUDPSocket(localPort);
|
||||||
ret = transparentSocket->open(transparentAddress.ss_family);
|
ret = transparentSocket->open(transparentAddress);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
LogWarning("Could not open the Transparent data socket, disabling");
|
LogWarning("Could not open the Transparent data socket, disabling");
|
||||||
delete transparentSocket;
|
delete transparentSocket;
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
CC = cc
|
CC = cc
|
||||||
CXX = c++
|
CXX = c++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H
|
||||||
LIBS = -lpthread -lutil -lsamplerate
|
LIBS = -lpthread
|
||||||
LDFLAGS = -g
|
LDFLAGS = -g
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DRASPBERRY_PI -I/usr/local/include
|
||||||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lutil -lsamplerate
|
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||||
LDFLAGS = -g -L/usr/local/lib
|
LDFLAGS = -g -L/usr/local/lib
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
|
||||||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lutil -lsamplerate
|
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||||
LDFLAGS = -g -L/usr/local/lib
|
LDFLAGS = -g -L/usr/local/lib
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/usr/local/include
|
||||||
|
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||||
LDFLAGS = -g -L/usr/local/lib
|
LDFLAGS = -g -L/usr/local/lib
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DOLED -I/usr/local/include
|
||||||
LIBS = -lArduiPi_OLED -lwiringPi -lpthread -lutil -lsamplerate
|
LIBS = -lArduiPi_OLED -lwiringPi -lpthread
|
||||||
LDFLAGS = -g -L/usr/local/lib
|
LDFLAGS = -g -L/usr/local/lib
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
|
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
|
||||||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lutil -lsamplerate
|
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||||
LDFLAGS = -g -L/usr/local/lib
|
LDFLAGS = -g -L/usr/local/lib
|
||||||
|
|
||||||
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
OBJECTS = AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o \
|
||||||
|
|
|
@ -30,8 +30,8 @@ const unsigned int BUFFER_LENGTH = 200U;
|
||||||
|
|
||||||
CNXDNIcomNetwork::CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
CNXDNIcomNetwork::CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
||||||
m_socket(localAddress, localPort),
|
m_socket(localAddress, localPort),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
m_buffer(1000U, "NXDN Network")
|
m_buffer(1000U, "NXDN Network")
|
||||||
|
@ -39,7 +39,8 @@ m_buffer(1000U, "NXDN Network")
|
||||||
assert(gatewayPort > 0U);
|
assert(gatewayPort > 0U);
|
||||||
assert(!gatewayAddress.empty());
|
assert(!gatewayAddress.empty());
|
||||||
|
|
||||||
CUDPSocket::lookup(gatewayAddress, gatewayPort, m_address, m_addrlen);
|
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
CNXDNIcomNetwork::~CNXDNIcomNetwork()
|
CNXDNIcomNetwork::~CNXDNIcomNetwork()
|
||||||
|
@ -48,12 +49,14 @@ CNXDNIcomNetwork::~CNXDNIcomNetwork()
|
||||||
|
|
||||||
bool CNXDNIcomNetwork::open()
|
bool CNXDNIcomNetwork::open()
|
||||||
{
|
{
|
||||||
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the NXDN Gateway");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LogMessage("Opening NXDN network connection");
|
LogMessage("Opening NXDN network connection");
|
||||||
|
|
||||||
if (CUDPSocket::isnone(m_address))
|
return m_socket.open(m_addr);
|
||||||
return false;
|
|
||||||
|
|
||||||
return m_socket.open();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNIcomNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type)
|
bool CNXDNIcomNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type)
|
||||||
|
@ -100,7 +103,7 @@ bool CNXDNIcomNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYP
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U);
|
CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U);
|
||||||
|
|
||||||
return m_socket.write(buffer, 102U, m_address, m_addrlen);
|
return m_socket.write(buffer, 102U, m_addr, m_addrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNXDNIcomNetwork::clock(unsigned int ms)
|
void CNXDNIcomNetwork::clock(unsigned int ms)
|
||||||
|
@ -108,11 +111,19 @@ void CNXDNIcomNetwork::clock(unsigned int ms)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match(m_address, address))
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
|
LogMessage("NXDN, packet received from an invalid source");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_debug)
|
||||||
|
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
|
||||||
|
|
||||||
// Invalid packet type?
|
// Invalid packet type?
|
||||||
if (::memcmp(buffer, "ICOM", 4U) != 0)
|
if (::memcmp(buffer, "ICOM", 4U) != 0)
|
||||||
return;
|
return;
|
||||||
|
@ -123,9 +134,6 @@ void CNXDNIcomNetwork::clock(unsigned int ms)
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_debug)
|
|
||||||
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
|
|
||||||
|
|
||||||
m_buffer.addData(buffer + 40U, 33U);
|
m_buffer.addData(buffer + 40U, 33U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,26 +33,26 @@ public:
|
||||||
CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||||
virtual ~CNXDNIcomNetwork();
|
virtual ~CNXDNIcomNetwork();
|
||||||
|
|
||||||
virtual bool open();
|
virtual bool open();
|
||||||
|
|
||||||
virtual void enable(bool enabled);
|
virtual void enable(bool enabled);
|
||||||
|
|
||||||
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||||
|
|
||||||
virtual bool read(unsigned char* data);
|
virtual bool read(unsigned char* data);
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
virtual void clock(unsigned int ms);
|
virtual void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
CRingBuffer<unsigned char> m_buffer;
|
CRingBuffer<unsigned char> m_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,10 @@ const unsigned int BUFFER_LENGTH = 200U;
|
||||||
CNXDNKenwoodNetwork::CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) :
|
CNXDNKenwoodNetwork::CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) :
|
||||||
m_rtpSocket(localAddress, localPort + 0U),
|
m_rtpSocket(localAddress, localPort + 0U),
|
||||||
m_rtcpSocket(localAddress, localPort + 1U),
|
m_rtcpSocket(localAddress, localPort + 1U),
|
||||||
m_rtcpaddress(),
|
m_rtcpAddr(),
|
||||||
m_rtpaddress(),
|
m_rtpAddr(),
|
||||||
m_addrlen(),
|
m_rtcpAddrLen(0U),
|
||||||
|
m_rtpAddrLen(0U),
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
m_headerSeen(false),
|
m_headerSeen(false),
|
||||||
m_seen1(false),
|
m_seen1(false),
|
||||||
|
@ -65,8 +66,11 @@ m_random()
|
||||||
|
|
||||||
m_sacch = new unsigned char[10U];
|
m_sacch = new unsigned char[10U];
|
||||||
|
|
||||||
CUDPSocket::lookup(gwyAddress, gwyPort + 1, m_rtcpaddress, m_addrlen);
|
if (CUDPSocket::lookup(gwyAddress, gwyPort + 1U, m_rtcpAddr, m_rtcpAddrLen) != 0)
|
||||||
CUDPSocket::lookup(gwyAddress, gwyPort, m_rtpaddress, m_addrlen);
|
m_rtcpAddrLen = 0U;
|
||||||
|
|
||||||
|
if (CUDPSocket::lookup(gwyAddress, gwyPort + 0U, m_rtpAddr, m_rtpAddrLen) != 0)
|
||||||
|
m_rtpAddrLen = 0U;
|
||||||
|
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 mt(rd());
|
std::mt19937 mt(rd());
|
||||||
|
@ -80,16 +84,17 @@ CNXDNKenwoodNetwork::~CNXDNKenwoodNetwork()
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::open()
|
bool CNXDNKenwoodNetwork::open()
|
||||||
{
|
{
|
||||||
|
if (m_rtcpAddrLen == 0U || m_rtpAddrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the NXDN Gateway");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LogMessage("Opening Kenwood connection");
|
LogMessage("Opening Kenwood connection");
|
||||||
|
|
||||||
if (CUDPSocket::isnone(m_rtpaddress) ||
|
if (!m_rtcpSocket.open(m_rtcpAddr))
|
||||||
CUDPSocket::isnone(m_rtcpaddress))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_rtcpSocket.open())
|
if (!m_rtpSocket.open(m_rtpAddr)) {
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!m_rtpSocket.open()) {
|
|
||||||
m_rtcpSocket.close();
|
m_rtcpSocket.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -365,7 +370,7 @@ bool CNXDNKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 47U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 47U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data)
|
bool CNXDNKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data)
|
||||||
|
@ -411,7 +416,7 @@ bool CNXDNKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 47U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 47U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data)
|
bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data)
|
||||||
|
@ -457,7 +462,7 @@ bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 59U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 59U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 59U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 59U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTPDataHeader(const unsigned char* data)
|
bool CNXDNKenwoodNetwork::writeRTPDataHeader(const unsigned char* data)
|
||||||
|
@ -499,7 +504,7 @@ bool CNXDNKenwoodNetwork::writeRTPDataHeader(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 42U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 42U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTPDataTrailer(const unsigned char* data)
|
bool CNXDNKenwoodNetwork::writeRTPDataTrailer(const unsigned char* data)
|
||||||
|
@ -541,7 +546,7 @@ bool CNXDNKenwoodNetwork::writeRTPDataTrailer(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 42U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 42U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTPDataData(const unsigned char* data)
|
bool CNXDNKenwoodNetwork::writeRTPDataData(const unsigned char* data)
|
||||||
|
@ -583,7 +588,7 @@ bool CNXDNKenwoodNetwork::writeRTPDataData(const unsigned char* data)
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U);
|
||||||
|
|
||||||
return m_rtpSocket.write(buffer, 42U, m_rtpaddress, m_addrlen);
|
return m_rtpSocket.write(buffer, 42U, m_rtpAddr, m_rtpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTCPStart()
|
bool CNXDNKenwoodNetwork::writeRTCPStart()
|
||||||
|
@ -643,7 +648,7 @@ bool CNXDNKenwoodNetwork::writeRTCPStart()
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U);
|
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U);
|
||||||
|
|
||||||
return m_rtcpSocket.write(buffer, 28U, m_rtcpaddress, m_addrlen);
|
return m_rtcpSocket.write(buffer, 28U, m_rtcpAddr, m_rtcpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTCPPing()
|
bool CNXDNKenwoodNetwork::writeRTCPPing()
|
||||||
|
@ -685,7 +690,7 @@ bool CNXDNKenwoodNetwork::writeRTCPPing()
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U);
|
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U);
|
||||||
|
|
||||||
return m_rtcpSocket.write(buffer, 28U, m_rtcpaddress, m_addrlen);
|
return m_rtcpSocket.write(buffer, 28U, m_rtcpAddr, m_rtcpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst)
|
bool CNXDNKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst)
|
||||||
|
@ -728,7 +733,7 @@ bool CNXDNKenwoodNetwork::writeRTCPHang()
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 20U);
|
CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 20U);
|
||||||
|
|
||||||
return m_rtcpSocket.write(buffer, 20U, m_rtcpaddress, m_addrlen);
|
return m_rtcpSocket.write(buffer, 20U, m_rtcpAddr, m_rtcpAddrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNXDNKenwoodNetwork::read(unsigned char* data)
|
bool CNXDNKenwoodNetwork::read(unsigned char* data)
|
||||||
|
@ -764,11 +769,16 @@ unsigned int CNXDNKenwoodNetwork::readRTP(unsigned char* data)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_rtpSocket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_rtpSocket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match_addr(m_rtpaddress, address))
|
if (length <= 0)
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_rtpAddr, address, IMT_ADDRESS_ONLY)) {
|
||||||
|
LogMessage("NXDN, RTP packet received from an invalid source");
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
|
@ -789,9 +799,14 @@ unsigned int CNXDNKenwoodNetwork::readRTCP(unsigned char* data)
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrlen;
|
||||||
int length = m_rtcpSocket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_rtcpSocket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
||||||
if (length <= 0 || !CUDPSocket::match_addr(m_rtcpaddress, address))
|
if (length <= 0)
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_rtpAddr, address, IMT_ADDRESS_ONLY)) {
|
||||||
|
LogMessage("NXDN, RTCP packet received from an invalid source");
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
|
|
|
@ -34,66 +34,67 @@ public:
|
||||||
|
|
||||||
virtual bool open();
|
virtual bool open();
|
||||||
|
|
||||||
virtual void enable(bool enabled);
|
virtual void enable(bool enabled);
|
||||||
|
|
||||||
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||||
|
|
||||||
virtual bool read(unsigned char* data);
|
virtual bool read(unsigned char* data);
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
virtual void clock(unsigned int ms);
|
virtual void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_rtpSocket;
|
CUDPSocket m_rtpSocket;
|
||||||
CUDPSocket m_rtcpSocket;
|
CUDPSocket m_rtcpSocket;
|
||||||
sockaddr_storage m_rtcpaddress;
|
sockaddr_storage m_rtcpAddr;
|
||||||
sockaddr_storage m_rtpaddress;
|
sockaddr_storage m_rtpAddr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_rtcpAddrLen;
|
||||||
bool m_enabled;
|
unsigned int m_rtpAddrLen;
|
||||||
bool m_headerSeen;
|
bool m_enabled;
|
||||||
bool m_seen1;
|
bool m_headerSeen;
|
||||||
bool m_seen2;
|
bool m_seen1;
|
||||||
bool m_seen3;
|
bool m_seen2;
|
||||||
bool m_seen4;
|
bool m_seen3;
|
||||||
unsigned char* m_sacch;
|
bool m_seen4;
|
||||||
uint8_t m_sessionId;
|
unsigned char* m_sacch;
|
||||||
uint16_t m_seqNo;
|
uint8_t m_sessionId;
|
||||||
unsigned int m_ssrc;
|
uint16_t m_seqNo;
|
||||||
bool m_debug;
|
unsigned int m_ssrc;
|
||||||
uint32_t m_startSecs;
|
bool m_debug;
|
||||||
uint32_t m_startUSecs;
|
uint32_t m_startSecs;
|
||||||
CTimer m_rtcpTimer;
|
uint32_t m_startUSecs;
|
||||||
CTimer m_hangTimer;
|
CTimer m_rtcpTimer;
|
||||||
unsigned char m_hangType;
|
CTimer m_hangTimer;
|
||||||
unsigned short m_hangSrc;
|
unsigned char m_hangType;
|
||||||
unsigned short m_hangDst;
|
unsigned short m_hangSrc;
|
||||||
std::mt19937 m_random;
|
unsigned short m_hangDst;
|
||||||
|
std::mt19937 m_random;
|
||||||
|
|
||||||
bool processIcomVoiceHeader(const unsigned char* data);
|
bool processIcomVoiceHeader(const unsigned char* data);
|
||||||
bool processIcomVoiceData(const unsigned char* data);
|
bool processIcomVoiceData(const unsigned char* data);
|
||||||
bool processIcomDataHeader(const unsigned char* data);
|
bool processIcomDataHeader(const unsigned char* data);
|
||||||
bool processIcomDataData(const unsigned char* data);
|
bool processIcomDataData(const unsigned char* data);
|
||||||
bool processIcomDataTrailer(const unsigned char* data);
|
bool processIcomDataTrailer(const unsigned char* data);
|
||||||
bool processKenwoodVoiceHeader(unsigned char* data);
|
bool processKenwoodVoiceHeader(unsigned char* data);
|
||||||
bool processKenwoodVoiceData(unsigned char* data);
|
bool processKenwoodVoiceData(unsigned char* data);
|
||||||
bool processKenwoodVoiceLateEntry(unsigned char* data);
|
bool processKenwoodVoiceLateEntry(unsigned char* data);
|
||||||
bool processKenwoodData(unsigned char* data);
|
bool processKenwoodData(unsigned char* data);
|
||||||
bool writeRTPVoiceHeader(const unsigned char* data);
|
bool writeRTPVoiceHeader(const unsigned char* data);
|
||||||
bool writeRTPVoiceData(const unsigned char* data);
|
bool writeRTPVoiceData(const unsigned char* data);
|
||||||
bool writeRTPVoiceTrailer(const unsigned char* data);
|
bool writeRTPVoiceTrailer(const unsigned char* data);
|
||||||
bool writeRTPDataHeader(const unsigned char* data);
|
bool writeRTPDataHeader(const unsigned char* data);
|
||||||
bool writeRTPDataData(const unsigned char* data);
|
bool writeRTPDataData(const unsigned char* data);
|
||||||
bool writeRTPDataTrailer(const unsigned char* data);
|
bool writeRTPDataTrailer(const unsigned char* data);
|
||||||
bool writeRTCPStart();
|
bool writeRTCPStart();
|
||||||
bool writeRTCPPing();
|
bool writeRTCPPing();
|
||||||
bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst);
|
bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst);
|
||||||
bool writeRTCPHang();
|
bool writeRTCPHang();
|
||||||
unsigned int readRTP(unsigned char* data);
|
unsigned int readRTP(unsigned char* data);
|
||||||
unsigned int readRTCP(unsigned char* data);
|
unsigned int readRTCP(unsigned char* data);
|
||||||
unsigned long getTimeStamp() const;
|
unsigned long getTimeStamp() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016,2019 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2019,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -89,14 +89,15 @@ const unsigned int BUFFER_LENGTH = 100U;
|
||||||
|
|
||||||
CP25Network::CP25Network(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool debug) :
|
CP25Network::CP25Network(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool debug) :
|
||||||
m_socket(localPort),
|
m_socket(localPort),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
m_buffer(1000U, "P25 Network"),
|
m_buffer(1000U, "P25 Network"),
|
||||||
m_audio()
|
m_audio()
|
||||||
{
|
{
|
||||||
CUDPSocket::lookup(gatewayAddress, gatewayPort, m_address, m_addrlen);
|
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
CP25Network::~CP25Network()
|
CP25Network::~CP25Network()
|
||||||
|
@ -105,12 +106,14 @@ CP25Network::~CP25Network()
|
||||||
|
|
||||||
bool CP25Network::open()
|
bool CP25Network::open()
|
||||||
{
|
{
|
||||||
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the P25 Gateway");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LogMessage("Opening P25 network connection");
|
LogMessage("Opening P25 network connection");
|
||||||
|
|
||||||
if (CUDPSocket::isnone(m_address))
|
return m_socket.open(m_addr);
|
||||||
return false;
|
|
||||||
|
|
||||||
return m_socket.open(m_address.ss_family);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control, const CP25LowSpeedData& lsd, bool end)
|
bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control, const CP25LowSpeedData& lsd, bool end)
|
||||||
|
@ -126,7 +129,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 22U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 22U);
|
||||||
|
|
||||||
bool ret = m_socket.write(buffer, 22U, m_address, m_addrlen);
|
bool ret = m_socket.write(buffer, 22U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -137,7 +140,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 14U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 14U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 14U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 14U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -150,7 +153,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -165,7 +168,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -180,7 +183,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -191,7 +194,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -202,7 +205,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -213,7 +216,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -226,7 +229,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 16U);
|
CUtils::dump(1U, "P25 Network LDU1 Sent", buffer, 16U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 16U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 16U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -234,7 +237,7 @@ bool CP25Network::writeLDU1(const unsigned char* ldu1, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network END Sent", REC80, 17U);
|
CUtils::dump(1U, "P25 Network END Sent", REC80, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(REC80, 17U, m_address, m_addrlen);
|
ret = m_socket.write(REC80, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +258,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 22U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 22U);
|
||||||
|
|
||||||
bool ret = m_socket.write(buffer, 22U, m_address, m_addrlen);
|
bool ret = m_socket.write(buffer, 22U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -266,7 +269,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 14U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 14U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 14U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 14U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -283,7 +286,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -297,7 +300,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -311,7 +314,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -326,7 +329,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -337,7 +340,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -348,7 +351,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 17U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -361,7 +364,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 16U);
|
CUtils::dump(1U, "P25 Network LDU2 Sent", buffer, 16U);
|
||||||
|
|
||||||
ret = m_socket.write(buffer, 16U, m_address, m_addrlen);
|
ret = m_socket.write(buffer, 16U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -369,7 +372,7 @@ bool CP25Network::writeLDU2(const unsigned char* ldu2, const CP25Data& control,
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "P25 Network END Sent", REC80, 17U);
|
CUtils::dump(1U, "P25 Network END Sent", REC80, 17U);
|
||||||
|
|
||||||
ret = m_socket.write(REC80, 17U, m_address, m_addrlen);
|
ret = m_socket.write(REC80, 17U, m_addr, m_addrLen);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -382,11 +385,16 @@ void CP25Network::clock(unsigned int ms)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match(m_address, address))
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
|
LogMessage("P25, packet received from an invalid source");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
14
P25Network.h
14
P25Network.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -48,13 +48,13 @@ public:
|
||||||
void clock(unsigned int ms);
|
void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
CRingBuffer<unsigned char> m_buffer;
|
CRingBuffer<unsigned char> m_buffer;
|
||||||
CP25Audio m_audio;
|
CP25Audio m_audio;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2018,2019 by Jonathan Naylor G4KLX
|
* Copyright (C) 2018,2019,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -30,13 +30,14 @@ const unsigned int BUFFER_LENGTH = 200U;
|
||||||
|
|
||||||
CPOCSAGNetwork::CPOCSAGNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
CPOCSAGNetwork::CPOCSAGNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
||||||
m_socket(myAddress, myPort),
|
m_socket(myAddress, myPort),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
m_buffer(1000U, "POCSAG Network")
|
m_buffer(1000U, "POCSAG Network")
|
||||||
{
|
{
|
||||||
CUDPSocket::lookup(gatewayAddress, gatewayPort, m_address, m_addrlen);
|
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPOCSAGNetwork::~CPOCSAGNetwork()
|
CPOCSAGNetwork::~CPOCSAGNetwork()
|
||||||
|
@ -45,10 +46,12 @@ CPOCSAGNetwork::~CPOCSAGNetwork()
|
||||||
|
|
||||||
bool CPOCSAGNetwork::open()
|
bool CPOCSAGNetwork::open()
|
||||||
{
|
{
|
||||||
LogMessage("Opening POCSAG network connection");
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the DAPNET Gateway");
|
||||||
if (CUDPSocket::isnone(m_address))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage("Opening POCSAG network connection");
|
||||||
|
|
||||||
return m_socket.open();
|
return m_socket.open();
|
||||||
}
|
}
|
||||||
|
@ -58,11 +61,19 @@ void CPOCSAGNetwork::clock(unsigned int ms)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match(m_address, address))
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
|
LogMessage("POCSAG, packet received from an invalid source");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_debug)
|
||||||
|
CUtils::dump(1U, "POCSAG Network Data Received", buffer, length);
|
||||||
|
|
||||||
// Invalid packet type?
|
// Invalid packet type?
|
||||||
if (::memcmp(buffer, "POCSAG", 6U) != 0)
|
if (::memcmp(buffer, "POCSAG", 6U) != 0)
|
||||||
return;
|
return;
|
||||||
|
@ -70,9 +81,6 @@ void CPOCSAGNetwork::clock(unsigned int ms)
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_debug)
|
|
||||||
CUtils::dump(1U, "POCSAG Network Data Received", buffer, length);
|
|
||||||
|
|
||||||
unsigned char len = length - 6U;
|
unsigned char len = length - 6U;
|
||||||
m_buffer.addData(&len, 1U);
|
m_buffer.addData(&len, 1U);
|
||||||
m_buffer.addData(buffer + 6U, length - 6U);
|
m_buffer.addData(buffer + 6U, length - 6U);
|
||||||
|
@ -112,7 +120,7 @@ void CPOCSAGNetwork::enable(bool enabled)
|
||||||
|
|
||||||
unsigned char c = enabled ? 0x00U : 0xFFU;
|
unsigned char c = enabled ? 0x00U : 0xFFU;
|
||||||
|
|
||||||
m_socket.write(&c, 1U, m_address, m_addrlen);
|
m_socket.write(&c, 1U, m_addr, m_addrLen);
|
||||||
|
|
||||||
m_enabled = enabled;
|
m_enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
* Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -45,11 +45,11 @@ public:
|
||||||
void clock(unsigned int ms);
|
void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
CRingBuffer<unsigned char> m_buffer;
|
CRingBuffer<unsigned char> m_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Jonathan Naylor G4KLX
|
* Copyright (C) 2019,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -61,17 +61,20 @@ CRemoteCommand::~CRemoteCommand()
|
||||||
|
|
||||||
int CRemoteCommand::send(const std::string& command)
|
int CRemoteCommand::send(const std::string& command)
|
||||||
{
|
{
|
||||||
sockaddr_storage address;
|
sockaddr_storage addr;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
CUDPSocket::lookup("127.0.0.1", m_port, address, addrlen);
|
if (CUDPSocket::lookup("127.0.0.1", m_port, addr, addrLen) != 0) {
|
||||||
|
LogError("Unable to resolve the address of the host");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
CUDPSocket socket(0U);
|
CUDPSocket socket(0U);
|
||||||
|
|
||||||
bool ret = socket.open(address.ss_family);
|
bool ret = socket.open(addr);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ret = socket.write((unsigned char*)command.c_str(), command.length(), address, addrlen);
|
ret = socket.write((unsigned char*)command.c_str(), command.length(), addr, addrLen);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
socket.close();
|
socket.close();
|
||||||
return 1;
|
return 1;
|
||||||
|
|
262
UDPSocket.cpp
262
UDPSocket.cpp
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "UDPSocket.h"
|
#include "UDPSocket.h"
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -26,11 +25,17 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LOG_H)
|
||||||
|
#include "Log.h"
|
||||||
|
#else
|
||||||
|
#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||||
|
#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||||
m_address(address),
|
m_address_save(address),
|
||||||
m_port(port),
|
m_port_save(port),
|
||||||
m_fd(-1)
|
m_counter(0U)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
WSAData data;
|
WSAData data;
|
||||||
|
@ -38,12 +43,18 @@ m_fd(-1)
|
||||||
if (wsaRet != 0)
|
if (wsaRet != 0)
|
||||||
LogError("Error from WSAStartup");
|
LogError("Error from WSAStartup");
|
||||||
#endif
|
#endif
|
||||||
|
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||||
|
m_address[i] = "";
|
||||||
|
m_port[i] = 0U;
|
||||||
|
m_af[i] = 0U;
|
||||||
|
m_fd[i] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||||
m_address(),
|
m_address_save(),
|
||||||
m_port(port),
|
m_port_save(port),
|
||||||
m_fd(-1)
|
m_counter(0U)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
WSAData data;
|
WSAData data;
|
||||||
|
@ -51,6 +62,12 @@ m_fd(-1)
|
||||||
if (wsaRet != 0)
|
if (wsaRet != 0)
|
||||||
LogError("Error from WSAStartup");
|
LogError("Error from WSAStartup");
|
||||||
#endif
|
#endif
|
||||||
|
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||||
|
m_address[i] = "";
|
||||||
|
m_port[i] = 0U;
|
||||||
|
m_af[i] = 0U;
|
||||||
|
m_fd[i] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CUDPSocket::~CUDPSocket()
|
CUDPSocket::~CUDPSocket()
|
||||||
|
@ -60,28 +77,26 @@ CUDPSocket::~CUDPSocket()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage &addr, unsigned int &address_length)
|
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
|
||||||
::memset(&hints, 0, sizeof(hints));
|
::memset(&hints, 0, sizeof(hints));
|
||||||
|
|
||||||
return lookup(hostname, port, addr, address_length, hints);
|
return lookup(hostname, port, addr, address_length, hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage &addr, unsigned int &address_length, struct addrinfo &hints)
|
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
std::string portstr = std::to_string(port);
|
std::string portstr = std::to_string(port);
|
||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
|
|
||||||
/* port is always digits, no needs to lookup service */
|
/* port is always digits, no needs to lookup service */
|
||||||
hints.ai_flags |= AI_NUMERICSERV;
|
hints.ai_flags |= AI_NUMERICSERV;
|
||||||
|
|
||||||
err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||||
if (err) {
|
if (err != 0) {
|
||||||
sockaddr_in *paddr = (sockaddr_in *)&addr;
|
sockaddr_in* paddr = (sockaddr_in*)&addr;
|
||||||
::memset(paddr, 0, address_length = sizeof(sockaddr_in));
|
::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in));
|
||||||
paddr->sin_family = AF_INET;
|
paddr->sin_family = AF_INET;
|
||||||
paddr->sin_port = htons(port);
|
paddr->sin_port = htons(port);
|
||||||
paddr->sin_addr.s_addr = htonl(INADDR_NONE);
|
paddr->sin_addr.s_addr = htonl(INADDR_NONE);
|
||||||
|
@ -92,86 +107,86 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
||||||
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUDPSocket::match(const sockaddr_storage &addr1, const sockaddr_storage &addr2)
|
bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type)
|
||||||
{
|
{
|
||||||
if (addr1.ss_family != addr2.ss_family)
|
if (addr1.ss_family != addr2.ss_family)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (addr1.ss_family) {
|
if (type == IMT_ADDRESS_AND_PORT) {
|
||||||
case AF_INET:
|
switch (addr1.ss_family) {
|
||||||
struct sockaddr_in *in_1, *in_2;
|
case AF_INET:
|
||||||
in_1 = (struct sockaddr_in *)&addr1;
|
struct sockaddr_in *in_1, *in_2;
|
||||||
in_2 = (struct sockaddr_in *)&addr2;
|
in_1 = (struct sockaddr_in*)&addr1;
|
||||||
return ( (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) &&
|
in_2 = (struct sockaddr_in*)&addr2;
|
||||||
(in_1->sin_port == in_2->sin_port) );
|
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
struct sockaddr_in6 *in6_1, *in6_2;
|
struct sockaddr_in6 *in6_1, *in6_2;
|
||||||
in6_1 = (struct sockaddr_in6 *)&addr1;
|
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||||
in6_2 = (struct sockaddr_in6 *)&addr2;
|
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||||
return ( IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) &&
|
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||||
(in6_1->sin6_port == in6_2->sin6_port) );
|
default:
|
||||||
default:
|
return false;
|
||||||
|
}
|
||||||
|
} else if (type == IMT_ADDRESS_ONLY) {
|
||||||
|
switch (addr1.ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
struct sockaddr_in *in_1, *in_2;
|
||||||
|
in_1 = (struct sockaddr_in*)&addr1;
|
||||||
|
in_2 = (struct sockaddr_in*)&addr2;
|
||||||
|
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||||
|
case AF_INET6:
|
||||||
|
struct sockaddr_in6 *in6_1, *in6_2;
|
||||||
|
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||||
|
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||||
|
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUDPSocket::match_addr(const sockaddr_storage &addr1, const sockaddr_storage &addr2)
|
bool CUDPSocket::isNone(const sockaddr_storage& addr)
|
||||||
{
|
|
||||||
if (addr1.ss_family != addr2.ss_family)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (addr1.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
struct sockaddr_in *in_1, *in_2;
|
|
||||||
in_1 = (struct sockaddr_in *)&addr1;
|
|
||||||
in_2 = (struct sockaddr_in *)&addr2;
|
|
||||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr);
|
|
||||||
case AF_INET6:
|
|
||||||
struct sockaddr_in6 *in6_1, *in6_2;
|
|
||||||
in6_1 = (struct sockaddr_in6 *)&addr1;
|
|
||||||
in6_2 = (struct sockaddr_in6 *)&addr2;
|
|
||||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CUDPSocket::isnone(const sockaddr_storage &addr)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in *in = (struct sockaddr_in *)&addr;
|
struct sockaddr_in *in = (struct sockaddr_in *)&addr;
|
||||||
|
|
||||||
return ( (addr.ss_family == AF_INET) &&
|
return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE)));
|
||||||
(in->sin_addr.s_addr == htonl(INADDR_NONE)) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUDPSocket::open()
|
bool CUDPSocket::open(const sockaddr_storage& address)
|
||||||
{
|
{
|
||||||
return open(AF_UNSPEC);
|
return open(address.ss_family);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUDPSocket::open(const unsigned int af)
|
bool CUDPSocket::open(unsigned int af)
|
||||||
|
{
|
||||||
|
return open(0, af, m_address_save, m_port_save);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
sockaddr_storage addr;
|
sockaddr_storage addr;
|
||||||
unsigned int addrlen;
|
unsigned int addrlen;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
|
||||||
::memset(&hints, 0, sizeof(hints));
|
::memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
hints.ai_family = af;
|
hints.ai_family = af;
|
||||||
|
|
||||||
/* to determine protocol family, call lookup() first. */
|
/* to determine protocol family, call lookup() first. */
|
||||||
err = lookup(m_address, m_port, addr, addrlen, hints);
|
int err = lookup(address, port, addr, addrlen, hints);
|
||||||
if (err) {
|
if (err != 0) {
|
||||||
LogError("The local address is invalid - %s", m_address.c_str());
|
LogError("The local address is invalid - %s", address.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
||||||
if (m_fd < 0) {
|
if (fd < 0) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||||
#else
|
#else
|
||||||
|
@ -180,9 +195,14 @@ bool CUDPSocket::open(const unsigned int af)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_port > 0U) {
|
m_address[index] = address;
|
||||||
|
m_port[index] = port;
|
||||||
|
m_af[index] = addr.ss_family;
|
||||||
|
m_fd[index] = fd;
|
||||||
|
|
||||||
|
if (port > 0U) {
|
||||||
int reuse = 1;
|
int reuse = 1;
|
||||||
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
|
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError());
|
LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError());
|
||||||
#else
|
#else
|
||||||
|
@ -191,7 +211,7 @@ bool CUDPSocket::open(const unsigned int af)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -1) {
|
if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
LogError("Cannot bind the UDP address, err: %lu", ::GetLastError());
|
LogError("Cannot bind the UDP address, err: %lu", ::GetLastError());
|
||||||
#else
|
#else
|
||||||
|
@ -199,6 +219,8 @@ bool CUDPSocket::open(const unsigned int af)
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogInfo("Opening UDP port on %u", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -210,30 +232,43 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
||||||
assert(length > 0U);
|
assert(length > 0U);
|
||||||
|
|
||||||
// Check that the readfrom() won't block
|
// Check that the readfrom() won't block
|
||||||
fd_set readFds;
|
int i, n;
|
||||||
FD_ZERO(&readFds);
|
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
|
||||||
FD_SET((unsigned int)m_fd, &readFds);
|
if (m_fd[i] >= 0) {
|
||||||
#else
|
pfd[n].fd = m_fd[i];
|
||||||
FD_SET(m_fd, &readFds);
|
pfd[n].events = POLLIN;
|
||||||
#endif
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no socket descriptor to receive
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Return immediately
|
// Return immediately
|
||||||
timeval tv;
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
tv.tv_sec = 0L;
|
int ret = WSAPoll(pfd, n, 0);
|
||||||
tv.tv_usec = 0L;
|
#else
|
||||||
|
int ret = ::poll(pfd, n, 0);
|
||||||
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
LogError("Error returned from UDP select, err: %lu", ::GetLastError());
|
LogError("Error returned from UDP poll, err: %lu", ::GetLastError());
|
||||||
#else
|
#else
|
||||||
LogError("Error returned from UDP select, err: %d", errno);
|
LogError("Error returned from UDP poll, err: %d", errno);
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
int index;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
// round robin
|
||||||
|
index = (i + m_counter) % n;
|
||||||
|
if (pfd[index].revents & POLLIN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == n)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
@ -243,9 +278,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||||
#else
|
#else
|
||||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||||
#endif
|
#endif
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
@ -256,6 +291,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_counter++;
|
||||||
address_length = size;
|
address_length = size;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -265,36 +301,52 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s
|
||||||
assert(buffer != NULL);
|
assert(buffer != NULL);
|
||||||
assert(length > 0U);
|
assert(length > 0U);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||||
|
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
|
||||||
|
continue;
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||||
#else
|
#else
|
||||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0) {
|
|
||||||
|
if (ret < 0) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||||
#else
|
#else
|
||||||
LogError("Error returned from sendto, err: %d", errno);
|
LogError("Error returned from sendto, err: %d", errno);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
} else {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
if (ret == int(length))
|
||||||
|
result = true;
|
||||||
|
#else
|
||||||
|
if (ret == ssize_t(length))
|
||||||
|
result = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
return result;
|
||||||
if (ret != int(length))
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
if (ret != ssize_t(length))
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUDPSocket::close()
|
void CUDPSocket::close()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
for (int i = 0; i < UDP_SOCKET_MAX; i++)
|
||||||
::closesocket(m_fd);
|
close(m_fd[i]);
|
||||||
#else
|
}
|
||||||
::close(m_fd);
|
|
||||||
#endif
|
void CUDPSocket::close(const unsigned int index)
|
||||||
|
{
|
||||||
|
if (m_fd[index] >= 0) {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
::closesocket(m_fd[index]);
|
||||||
|
#else
|
||||||
|
::close(m_fd[index]);
|
||||||
|
#endif
|
||||||
|
m_fd[index] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
38
UDPSocket.h
38
UDPSocket.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -35,30 +36,45 @@
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(UDP_SOCKET_MAX)
|
||||||
|
#define UDP_SOCKET_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum IPMATCHTYPE {
|
||||||
|
IMT_ADDRESS_AND_PORT,
|
||||||
|
IMT_ADDRESS_ONLY
|
||||||
|
};
|
||||||
|
|
||||||
class CUDPSocket {
|
class CUDPSocket {
|
||||||
public:
|
public:
|
||||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||||
CUDPSocket(unsigned int port = 0U);
|
CUDPSocket(unsigned int port = 0U);
|
||||||
~CUDPSocket();
|
~CUDPSocket();
|
||||||
|
|
||||||
bool open();
|
bool open(unsigned int af = AF_UNSPEC);
|
||||||
bool open(const unsigned int af);
|
bool open(const sockaddr_storage& address);
|
||||||
|
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
|
||||||
|
|
||||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
||||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
void close(const unsigned int index);
|
||||||
|
|
||||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length);
|
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length);
|
||||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length, struct addrinfo &hints);
|
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints);
|
||||||
static bool match(const sockaddr_storage &addr1, const sockaddr_storage &addr2);
|
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
|
||||||
static bool match_addr(const sockaddr_storage &addr1, const sockaddr_storage &addr2);
|
|
||||||
static bool isnone(const sockaddr_storage &addr);
|
static bool isNone(const sockaddr_storage& addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_address;
|
std::string m_address_save;
|
||||||
unsigned short m_port;
|
unsigned short m_port_save;
|
||||||
int m_fd;
|
std::string m_address[UDP_SOCKET_MAX];
|
||||||
|
unsigned short m_port[UDP_SOCKET_MAX];
|
||||||
|
unsigned int m_af[UDP_SOCKET_MAX];
|
||||||
|
int m_fd[UDP_SOCKET_MAX];
|
||||||
|
unsigned int m_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,6 @@
|
||||||
#if !defined(VERSION_H)
|
#if !defined(VERSION_H)
|
||||||
#define VERSION_H
|
#define VERSION_H
|
||||||
|
|
||||||
const char* VERSION = "20200830";
|
const char* VERSION = "20200906";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016,2019 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2019,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -30,8 +30,8 @@ const unsigned int BUFFER_LENGTH = 200U;
|
||||||
|
|
||||||
CYSFNetwork::CYSFNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, const std::string& callsign, bool debug) :
|
CYSFNetwork::CYSFNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, const std::string& callsign, bool debug) :
|
||||||
m_socket(myAddress, myPort),
|
m_socket(myAddress, myPort),
|
||||||
m_address(),
|
m_addr(),
|
||||||
m_addrlen(),
|
m_addrLen(0U),
|
||||||
m_callsign(),
|
m_callsign(),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
|
@ -42,7 +42,8 @@ m_tag(NULL)
|
||||||
m_callsign = callsign;
|
m_callsign = callsign;
|
||||||
m_callsign.resize(YSF_CALLSIGN_LENGTH, ' ');
|
m_callsign.resize(YSF_CALLSIGN_LENGTH, ' ');
|
||||||
|
|
||||||
CUDPSocket::lookup(gatewayAddress, gatewayPort, m_address, m_addrlen);
|
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
|
||||||
|
m_addrLen = 0U;
|
||||||
|
|
||||||
m_tag = new unsigned char[YSF_CALLSIGN_LENGTH];
|
m_tag = new unsigned char[YSF_CALLSIGN_LENGTH];
|
||||||
::memset(m_tag, ' ', YSF_CALLSIGN_LENGTH);
|
::memset(m_tag, ' ', YSF_CALLSIGN_LENGTH);
|
||||||
|
@ -55,14 +56,16 @@ CYSFNetwork::~CYSFNetwork()
|
||||||
|
|
||||||
bool CYSFNetwork::open()
|
bool CYSFNetwork::open()
|
||||||
{
|
{
|
||||||
LogMessage("Opening YSF network connection");
|
if (m_addrLen == 0U) {
|
||||||
|
LogError("Unable to resolve the address of the YSF Gateway");
|
||||||
if (CUDPSocket::isnone(m_address))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage("Opening YSF network connection");
|
||||||
|
|
||||||
m_pollTimer.start();
|
m_pollTimer.start();
|
||||||
|
|
||||||
return m_socket.open();
|
return m_socket.open(m_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CYSFNetwork::write(const unsigned char* src, const unsigned char* dest, const unsigned char* data, unsigned int count, bool end)
|
bool CYSFNetwork::write(const unsigned char* src, const unsigned char* dest, const unsigned char* data, unsigned int count, bool end)
|
||||||
|
@ -97,7 +100,7 @@ bool CYSFNetwork::write(const unsigned char* src, const unsigned char* dest, con
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "YSF Network Data Sent", buffer, 155U);
|
CUtils::dump(1U, "YSF Network Data Sent", buffer, 155U);
|
||||||
|
|
||||||
return m_socket.write(buffer, 155U, m_address, m_addrlen);
|
return m_socket.write(buffer, 155U, m_addr, m_addrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CYSFNetwork::writePoll()
|
bool CYSFNetwork::writePoll()
|
||||||
|
@ -115,7 +118,7 @@ bool CYSFNetwork::writePoll()
|
||||||
if (m_debug)
|
if (m_debug)
|
||||||
CUtils::dump(1U, "YSF Network Poll Sent", buffer, 14U);
|
CUtils::dump(1U, "YSF Network Poll Sent", buffer, 14U);
|
||||||
|
|
||||||
return m_socket.write(buffer, 14U, m_address, m_addrlen);
|
return m_socket.write(buffer, 14U, m_addr, m_addrLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CYSFNetwork::clock(unsigned int ms)
|
void CYSFNetwork::clock(unsigned int ms)
|
||||||
|
@ -129,11 +132,16 @@ void CYSFNetwork::clock(unsigned int ms)
|
||||||
unsigned char buffer[BUFFER_LENGTH];
|
unsigned char buffer[BUFFER_LENGTH];
|
||||||
|
|
||||||
sockaddr_storage address;
|
sockaddr_storage address;
|
||||||
unsigned int addrlen;
|
unsigned int addrLen;
|
||||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrlen);
|
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
|
||||||
if (length <= 0 || !CUDPSocket::match(m_address, address))
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CUDPSocket::match(m_addr, address)) {
|
||||||
|
LogMessage("YSF, packet received from an invalid source");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore incoming polls
|
// Ignore incoming polls
|
||||||
if (::memcmp(buffer, "YSFP", 4U) == 0)
|
if (::memcmp(buffer, "YSFP", 4U) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
18
YSFNetwork.h
18
YSFNetwork.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2014,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2014,2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -47,15 +47,15 @@ public:
|
||||||
void clock(unsigned int ms);
|
void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CUDPSocket m_socket;
|
CUDPSocket m_socket;
|
||||||
sockaddr_storage m_address;
|
sockaddr_storage m_addr;
|
||||||
unsigned int m_addrlen;
|
unsigned int m_addrLen;
|
||||||
std::string m_callsign;
|
std::string m_callsign;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
CRingBuffer<unsigned char> m_buffer;
|
CRingBuffer<unsigned char> m_buffer;
|
||||||
CTimer m_pollTimer;
|
CTimer m_pollTimer;
|
||||||
unsigned char* m_tag;
|
unsigned char* m_tag;
|
||||||
|
|
||||||
bool writePoll();
|
bool writePoll();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue