From c29fcd2a8e18fdf9c6bfc6964e18a8a2e4722b41 Mon Sep 17 00:00:00 2001 From: Geoffrey Merck Date: Fri, 24 Dec 2021 15:02:34 +0100 Subject: [PATCH] Add HBRepeaterController (wx free) --- HBRepeaterProtocolHandler.cpp | 288 ++++++++++++++++++++++++++++++++++ HBRepeaterProtocolHandler.h | 72 +++++++++ 2 files changed, 360 insertions(+) create mode 100644 HBRepeaterProtocolHandler.cpp create mode 100644 HBRepeaterProtocolHandler.h diff --git a/HBRepeaterProtocolHandler.cpp b/HBRepeaterProtocolHandler.cpp new file mode 100644 index 0000000..443ad73 --- /dev/null +++ b/HBRepeaterProtocolHandler.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2010-2013 by Jonathan Naylor G4KLX + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "HBRepeaterProtocolHandler.h" +#include "CCITTChecksum.h" +#include "DStarDefines.h" +#include "Utils.h" +#include "Log.h" + +const unsigned int BUFFER_LENGTH = 255U; + +CHBRepeaterProtocolHandler::CHBRepeaterProtocolHandler(const std::string& address, unsigned int port) : +m_socket(address, port), +m_type(RT_NONE), +m_buffer(NULL), +m_length(0U), +m_address(), +m_port(0U) +{ + assert(!address.empty()); + assert(port > 0U); + + m_buffer = new unsigned char[BUFFER_LENGTH]; +} + +CHBRepeaterProtocolHandler::~CHBRepeaterProtocolHandler() +{ + delete[] m_buffer; +} + +bool CHBRepeaterProtocolHandler::open() +{ + return m_socket.open(); +} + +bool CHBRepeaterProtocolHandler::writeHeader(CHeaderData& header) +{ + unsigned char buffer[50U]; + unsigned int length = header.getHBRepeaterData(buffer, 50U, true); + +#if defined(DUMP_TX) + CUtils::dump(wxT("Sending Header"), buffer, length); + return true; +#else + return m_socket.write(buffer, length, header.getYourAddress(), header.getYourPort()); +#endif +} + +bool CHBRepeaterProtocolHandler::writeAMBE(CAMBEData& data) +{ + unsigned char buffer[30U]; + unsigned int length = data.getHBRepeaterData(buffer, 30U); + +#if defined(DUMP_TX) + CUtils::dump(wxT("Sending Data"), buffer, length); + return true; +#else + return m_socket.write(buffer, length, data.getYourAddress(), data.getYourPort()); +#endif +} + +bool CHBRepeaterProtocolHandler::writeDD(CDDData& data) +{ + unsigned char buffer[2000U]; + unsigned int length = data.getHBRepeaterData(buffer, 2000U); + +#if defined(DUMP_TX) + CUtils::dump(wxT("Sending DD Data"), buffer, length); + return true; +#else + return m_socket.write(buffer, length, data.getYourAddress(), data.getYourPort()); +#endif +} + +bool CHBRepeaterProtocolHandler::writeText(CTextData& text) +{ + unsigned char buffer[40U]; + unsigned int length = text.getHBRepeaterData(buffer, 40U); + +#if defined(DUMP_TX) + CUtils::dump(wxT("Sending Text"), buffer, length); + return true; +#else + return m_socket.write(buffer, length, text.getAddress(), text.getPort()); +#endif +} + +bool CHBRepeaterProtocolHandler::writeStatus(CStatusData& status) +{ + unsigned char buffer[30U]; + unsigned int length = status.getHBRepeaterData(buffer, 30U); + +#if defined(DUMP_TX) + CUtils::dump(wxT("Sending Status"), buffer, length); + return true; +#else + return m_socket.write(buffer, length, status.getAddress(), status.getPort()); +#endif +} + +REPEATER_TYPE CHBRepeaterProtocolHandler::read() +{ + bool res = true; + + // Loop until we have no more data from the socket or we have data for the higher layers + while (res) + res = readPackets(); + + return m_type; +} + +bool CHBRepeaterProtocolHandler::readPackets() +{ + m_type = RT_NONE; + + // No more data? + int length = m_socket.read(m_buffer, BUFFER_LENGTH, m_address, m_port); + if (length <= 0) + return false; + + m_length = length; + + // Invalid packet type? + if (m_buffer[0] == 'D' && m_buffer[1] == 'S' && m_buffer[2] == 'R' && m_buffer[3] == 'P') { + // Poll data + if (m_buffer[4] == 0x0AU) { + m_type = RT_POLL; + return false; + } + + // Header data + else if (m_buffer[4] == 0x20U) { + m_type = RT_HEADER; + return false; + } + + // User data + else if (m_buffer[4] == 0x21U) { + m_type = RT_AMBE; + return false; + } + + // DD data + else if (m_buffer[4] == 0x24U) { + m_type = RT_DD; + return false; + } + + // Busy header data + else if (m_buffer[4] == 0x22U) { + m_type = RT_BUSY_HEADER; + return false; + } + + // Busy user data + else if (m_buffer[4] == 0x23U) { + m_type = RT_BUSY_AMBE; + return false; + } + } + + CUtils::dump("Unknown packet from the Repeater", m_buffer, m_length); + + return true; +} + +CPollData* CHBRepeaterProtocolHandler::readPoll() +{ + if (m_type != RT_POLL) + return NULL; + + std::string text = std::string((char*)(m_buffer + 5U)); + + return new CPollData(text, m_address, m_port, m_socket.getPort()); +} + +CHeaderData* CHBRepeaterProtocolHandler::readHeader() +{ + if (m_type != RT_HEADER) + return NULL; + + CHeaderData* header = new CHeaderData; + + bool res = header->setHBRepeaterData(m_buffer, m_length, true, m_address, m_port); + if (!res) { + wxLogError("Invalid checksum from the repeater"); + delete header; + return NULL; + } + + return header; +} + +CAMBEData* CHBRepeaterProtocolHandler::readAMBE() +{ + if (m_type != RT_AMBE) + return NULL; + + CAMBEData* data = new CAMBEData; + + bool res = data->setHBRepeaterData(m_buffer, m_length, m_address, m_port); + if (!res) { + wxLogError("Invalid AMBE data from the repeater"); + delete data; + return NULL; + } + + return data; +} + +CHeaderData* CHBRepeaterProtocolHandler::readBusyHeader() +{ + if (m_type != RT_BUSY_HEADER) + return NULL; + + CHeaderData* header = new CHeaderData; + + bool res = header->setHBRepeaterData(m_buffer, m_length, true, m_address, m_port); + if (!res) { + wxLogError("Invalid checksum from the repeater"); + delete header; + return NULL; + } + + return header; +} + +CAMBEData* CHBRepeaterProtocolHandler::readBusyAMBE() +{ + if (m_type != RT_BUSY_AMBE) + return NULL; + + CAMBEData* data = new CAMBEData; + + bool res = data->setHBRepeaterData(m_buffer, m_length, m_address, m_port); + if (!res) { + wxLogError("Invalid AMBE data from the repeater"); + delete data; + return NULL; + } + + return data; +} + +CHeardData* CHBRepeaterProtocolHandler::readHeard() +{ + return NULL; +} + +CDDData* CHBRepeaterProtocolHandler::readDD() +{ + if (m_type != RT_DD) + return NULL; + + CDDData* data = new CDDData; + + bool res = data->setHBRepeaterData(m_buffer, m_length, m_address, m_port); + if (!res) { + wxLogError("Invalid DD data from the repeater"); + delete data; + return NULL; + } + + return data; +} + +void CHBRepeaterProtocolHandler::close() +{ + m_socket.close(); +} diff --git a/HBRepeaterProtocolHandler.h b/HBRepeaterProtocolHandler.h new file mode 100644 index 0000000..dbe334b --- /dev/null +++ b/HBRepeaterProtocolHandler.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010-2013 by Jonathan Naylor G4KLX + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef HBRepeaterProtocolHandler_H +#define HBRepeaterProtocolHandler_H + +#include +#include + +#include "RepeaterProtocolHandler.h" +#include "UDPReaderWriter.h" +#include "DStarDefines.h" +#include "HeaderData.h" +#include "StatusData.h" +#include "HeardData.h" +#include "AMBEData.h" +#include "TextData.h" +#include "PollData.h" +#include "DDData.h" + +class CHBRepeaterProtocolHandler : public IRepeaterProtocolHandler { +public: + CHBRepeaterProtocolHandler(const std::string& address, unsigned int port); + virtual ~CHBRepeaterProtocolHandler(); + + virtual bool open(); + + virtual bool writeHeader(CHeaderData& header); + virtual bool writeAMBE(CAMBEData& data); + virtual bool writeDD(CDDData& data); + virtual bool writeText(CTextData& text); + virtual bool writeStatus(CStatusData& status); + + virtual REPEATER_TYPE read(); + virtual CPollData* readPoll(); + virtual CHeardData* readHeard(); + virtual CHeaderData* readHeader(); + virtual CAMBEData* readAMBE(); + virtual CDDData* readDD(); + virtual CHeaderData* readBusyHeader(); + virtual CAMBEData* readBusyAMBE(); + + virtual void close(); + +private: + CUDPReaderWriter m_socket; + REPEATER_TYPE m_type; + unsigned char* m_buffer; + unsigned int m_length; + in_addr m_address; + unsigned int m_port; + + bool readPackets(); +}; + +#endif