From 263a969b1aedb0800305c509d0102d7816780260 Mon Sep 17 00:00:00 2001 From: Alex Robenko Date: Thu, 15 Feb 2024 09:16:56 +1000 Subject: [PATCH] Added "UDP/IP Proxy Socket". --- CMakeLists.txt | 1 + plugin/udp_socket/CMakeLists.txt | 57 +-- plugin/udp_socket/generic/CMakeLists.txt | 55 +++ .../UdpGenericSocket.cpp} | 35 +- .../UdpGenericSocket.h} | 6 +- .../UdpGenericSocketConfigWidget.cpp} | 24 +- .../UdpGenericSocketConfigWidget.h} | 18 +- .../UdpGenericSocketConfigWidget.ui} | 4 +- .../UdpGenericSocketPlugin.cpp} | 20 +- .../UdpGenericSocketPlugin.h} | 10 +- .../udp_socket/{ => generic}/udp_socket.json | 0 plugin/udp_socket/proxy/CMakeLists.txt | 55 +++ plugin/udp_socket/proxy/UdpProxySocket.cpp | 335 ++++++++++++++++++ plugin/udp_socket/proxy/UdpProxySocket.h | 107 ++++++ .../proxy/UdpProxySocketConfigWidget.cpp | 86 +++++ .../proxy/UdpProxySocketConfigWidget.h | 59 +++ .../proxy/UdpProxySocketConfigWidget.ui | 118 ++++++ .../udp_socket/proxy/UdpProxySocketPlugin.cpp | 113 ++++++ .../udp_socket/proxy/UdpProxySocketPlugin.h | 59 +++ plugin/udp_socket/proxy/udp_proxy_socket.json | 7 + 20 files changed, 1056 insertions(+), 113 deletions(-) create mode 100644 plugin/udp_socket/generic/CMakeLists.txt rename plugin/udp_socket/{UdpSocket.cpp => generic/UdpGenericSocket.cpp} (88%) rename plugin/udp_socket/{UdpSocket.h => generic/UdpGenericSocket.h} (94%) rename plugin/udp_socket/{UdpSocketConfigWidget.cpp => generic/UdpGenericSocketConfigWidget.cpp} (71%) rename plugin/udp_socket/{UdpSocketConfigWidget.h => generic/UdpGenericSocketConfigWidget.h} (75%) rename plugin/udp_socket/{UdpSocketConfigWidget.ui => generic/UdpGenericSocketConfigWidget.ui} (97%) rename plugin/udp_socket/{UdpSocketPlugin.cpp => generic/UdpGenericSocketPlugin.cpp} (84%) rename plugin/udp_socket/{UdpSocketPlugin.h => generic/UdpGenericSocketPlugin.h} (85%) rename plugin/udp_socket/{ => generic}/udp_socket.json (100%) create mode 100644 plugin/udp_socket/proxy/CMakeLists.txt create mode 100644 plugin/udp_socket/proxy/UdpProxySocket.cpp create mode 100644 plugin/udp_socket/proxy/UdpProxySocket.h create mode 100644 plugin/udp_socket/proxy/UdpProxySocketConfigWidget.cpp create mode 100644 plugin/udp_socket/proxy/UdpProxySocketConfigWidget.h create mode 100644 plugin/udp_socket/proxy/UdpProxySocketConfigWidget.ui create mode 100644 plugin/udp_socket/proxy/UdpProxySocketPlugin.cpp create mode 100644 plugin/udp_socket/proxy/UdpProxySocketPlugin.h create mode 100644 plugin/udp_socket/proxy/udp_proxy_socket.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bad151..98f6815 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ option (CC_TOOLS_QT_BUILD_PLUGIN_TCP_CLIENT_SOCKET "Build TCP client socket plug option (CC_TOOLS_QT_BUILD_PLUGIN_TCP_PROXY_SOCKET "Build TCP proxy socket plugin." ${CC_TOOLS_QT_BUILD_PLUGINS}) option (CC_TOOLS_QT_BUILD_PLUGIN_TCP_SERVER_SOCKET "Build TCP server socket plugin." ${CC_TOOLS_QT_BUILD_PLUGINS}) option (CC_TOOLS_QT_BUILD_PLUGIN_UDP_SOCKET "Build UDP socket plugin." ${CC_TOOLS_QT_BUILD_PLUGINS}) +option (CC_TOOLS_QT_BUILD_PLUGIN_UDP_PROXY_SOCKET "Build UDP proxy socket plugin." ${CC_TOOLS_QT_BUILD_PLUGINS}) option (CC_TOOLS_QT_BUILD_PLUGIN_RAW_DATA_PROTOCOL "Build raw data protocol plugin." ${CC_TOOLS_QT_BUILD_PLUGINS}) option (CC_TOOLS_QT_BUILD_PLUGIN_DEMO_PROTOCOL "Build demo protocol plugin." OFF) diff --git a/plugin/udp_socket/CMakeLists.txt b/plugin/udp_socket/CMakeLists.txt index 9210a97..8a6b954 100644 --- a/plugin/udp_socket/CMakeLists.txt +++ b/plugin/udp_socket/CMakeLists.txt @@ -1,55 +1,2 @@ -if (NOT CC_TOOLS_QT_BUILD_PLUGIN_UDP_SOCKET) - return() -endif () - -###################################################################### - -function (plugin_udp_client_socket) - set (name "cc_tools_plugin_udp_client_socket") - - if (NOT TARGET Qt::Network) - message(WARNING "Can NOT build ${name} due to missing Qt::Network library") - return() - endif () - - set (meta_file "${CMAKE_CURRENT_SOURCE_DIR}/udp_socket.json") - set (stamp_file "${CMAKE_CURRENT_BINARY_DIR}/refresh_stamp.txt") - - set (refresh_plugin_header TRUE) - if ((NOT EXISTS ${stamp_file}) OR (${meta_file} IS_NEWER_THAN ${stamp_file})) - execute_process( - COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/UdpSocketPlugin.h) - execute_process( - COMMAND ${CMAKE_COMMAND} -E touch ${stamp_file}) - endif () - - set ( - ui - UdpSocketConfigWidget.ui - ) - - set (src - UdpSocket.cpp - UdpSocketPlugin.h - UdpSocketPlugin.cpp - UdpSocketConfigWidget.cpp - ) - - add_library (${name} MODULE ${ui} ${src}) - target_link_libraries(${name} PRIVATE cc::${PROJECT_NAME} Qt::Network Qt::Widgets Qt::Core) - - install ( - TARGETS ${name} - DESTINATION ${PLUGIN_INSTALL_DIR}) - -endfunction() - -###################################################################### - -cc_find_qt_components (Network) - -include_directories ( - ${CMAKE_CURRENT_BINARY_DIR} -) - -plugin_udp_client_socket () +add_subdirectory (generic) +add_subdirectory (proxy) \ No newline at end of file diff --git a/plugin/udp_socket/generic/CMakeLists.txt b/plugin/udp_socket/generic/CMakeLists.txt new file mode 100644 index 0000000..3442c1c --- /dev/null +++ b/plugin/udp_socket/generic/CMakeLists.txt @@ -0,0 +1,55 @@ +if (NOT CC_TOOLS_QT_BUILD_PLUGIN_UDP_SOCKET) + return() +endif () + +###################################################################### + +function (plugin_udp_generic_socket) + set (name "cc_tools_plugin_udp_generic_socket") + + if (NOT TARGET Qt::Network) + message(WARNING "Can NOT build ${name} due to missing Qt::Network library") + return() + endif () + + set (meta_file "${CMAKE_CURRENT_SOURCE_DIR}/udp_socket.json") + set (stamp_file "${CMAKE_CURRENT_BINARY_DIR}/refresh_stamp.txt") + + set (refresh_plugin_header TRUE) + if ((NOT EXISTS ${stamp_file}) OR (${meta_file} IS_NEWER_THAN ${stamp_file})) + execute_process( + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/UdpGenericSocketPlugin.h) + execute_process( + COMMAND ${CMAKE_COMMAND} -E touch ${stamp_file}) + endif () + + set ( + ui + UdpGenericSocketConfigWidget.ui + ) + + set (src + UdpGenericSocket.cpp + UdpGenericSocketPlugin.h + UdpGenericSocketPlugin.cpp + UdpGenericSocketConfigWidget.cpp + ) + + add_library (${name} MODULE ${ui} ${src}) + target_link_libraries(${name} PRIVATE cc::${PROJECT_NAME} Qt::Network Qt::Widgets Qt::Core) + + install ( + TARGETS ${name} + DESTINATION ${PLUGIN_INSTALL_DIR}) + +endfunction() + +###################################################################### + +cc_find_qt_components (Network) + +include_directories ( + ${CMAKE_CURRENT_BINARY_DIR} +) + +plugin_udp_generic_socket () diff --git a/plugin/udp_socket/UdpSocket.cpp b/plugin/udp_socket/generic/UdpGenericSocket.cpp similarity index 88% rename from plugin/udp_socket/UdpSocket.cpp rename to plugin/udp_socket/generic/UdpGenericSocket.cpp index 721fb6a..063e242 100644 --- a/plugin/udp_socket/UdpSocket.cpp +++ b/plugin/udp_socket/generic/UdpGenericSocket.cpp @@ -21,7 +21,7 @@ #include #include -#include "UdpSocket.h" +#include "UdpGenericSocket.h" namespace cc_tools_qt { @@ -41,27 +41,27 @@ const QString ToPropName("udp.to"); } // namespace -UdpSocket::UdpSocket() +UdpGenericSocket::UdpGenericSocket() : m_host(DefaultHost) { connect( &m_socket, &QUdpSocket::disconnected, - this, &UdpSocket::socketDisconnected); + this, &UdpGenericSocket::socketDisconnected); connect( &m_socket, &QUdpSocket::readyRead, - this, &UdpSocket::readFromSocket); + this, &UdpGenericSocket::readFromSocket); connect( &m_broadcastSocket, &QUdpSocket::readyRead, - this, &UdpSocket::readFromBroadcastSocket); + this, &UdpGenericSocket::readFromBroadcastSocket); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect( &m_socket, &QUdpSocket::errorOccurred, - this, &UdpSocket::socketErrorOccurred); + this, &UdpGenericSocket::socketErrorOccurred); connect( &m_broadcastSocket, &QUdpSocket::errorOccurred, - this, &UdpSocket::socketErrorOccurred); + this, &UdpGenericSocket::socketErrorOccurred); #else // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect( &m_socket, SIGNAL(error(QAbstractSocket::SocketError)), @@ -72,12 +72,13 @@ UdpSocket::UdpSocket() #endif // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) } -UdpSocket::~UdpSocket() noexcept +UdpGenericSocket::~UdpGenericSocket() noexcept { m_socket.blockSignals(true); + m_broadcastSocket.blockSignals(true); } -bool UdpSocket::socketConnectImpl() +bool UdpGenericSocket::socketConnectImpl() { if ((!m_host.isEmpty()) && (m_port == 0)) { static const QString Error = @@ -125,7 +126,7 @@ bool UdpSocket::socketConnectImpl() return true; } -void UdpSocket::socketDisconnectImpl() +void UdpGenericSocket::socketDisconnectImpl() { m_socket.blockSignals(true); m_socket.close(); @@ -134,7 +135,7 @@ void UdpSocket::socketDisconnectImpl() m_socket.blockSignals(false); } -void UdpSocket::sendDataImpl(DataInfoPtr dataPtr) +void UdpGenericSocket::sendDataImpl(DataInfoPtr dataPtr) { assert(dataPtr); QString from = @@ -205,27 +206,27 @@ void UdpSocket::sendDataImpl(DataInfoPtr dataPtr) } -void UdpSocket::socketDisconnected() +void UdpGenericSocket::socketDisconnected() { reportDisconnected(); } -void UdpSocket::readFromSocket() +void UdpGenericSocket::readFromSocket() { readData(m_socket); } -void UdpSocket::readFromBroadcastSocket() +void UdpGenericSocket::readFromBroadcastSocket() { readData(m_broadcastSocket); } -void UdpSocket::socketErrorOccurred([[maybe_unused]] QAbstractSocket::SocketError err) +void UdpGenericSocket::socketErrorOccurred([[maybe_unused]] QAbstractSocket::SocketError err) { std::cout << "ERROR: UDP Socket: " << m_socket.errorString().toStdString() << std::endl; } -void UdpSocket::readData(QUdpSocket& socket) +void UdpGenericSocket::readData(QUdpSocket& socket) { while (socket.hasPendingDatagrams()) { QHostAddress senderAddress; @@ -260,7 +261,7 @@ void UdpSocket::readData(QUdpSocket& socket) } } -bool UdpSocket::bindSocket(QUdpSocket& socket) +bool UdpGenericSocket::bindSocket(QUdpSocket& socket) { if (!socket.bind(QHostAddress::AnyIPv4, m_localPort, QUdpSocket::ShareAddress)) { return false; diff --git a/plugin/udp_socket/UdpSocket.h b/plugin/udp_socket/generic/UdpGenericSocket.h similarity index 94% rename from plugin/udp_socket/UdpSocket.h rename to plugin/udp_socket/generic/UdpGenericSocket.h index f2ad601..f6aa7e9 100644 --- a/plugin/udp_socket/UdpSocket.h +++ b/plugin/udp_socket/generic/UdpGenericSocket.h @@ -30,7 +30,7 @@ namespace cc_tools_qt namespace plugin { -class UdpSocket : public QObject, public cc_tools_qt::Socket +class UdpGenericSocket : public QObject, public cc_tools_qt::Socket { Q_OBJECT using Base = cc_tools_qt::Socket; @@ -38,8 +38,8 @@ class UdpSocket : public QObject, public cc_tools_qt::Socket public: typedef unsigned short PortType; - UdpSocket(); - ~UdpSocket() noexcept; + UdpGenericSocket(); + ~UdpGenericSocket() noexcept; void setHost(const QString& value) { diff --git a/plugin/udp_socket/UdpSocketConfigWidget.cpp b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.cpp similarity index 71% rename from plugin/udp_socket/UdpSocketConfigWidget.cpp rename to plugin/udp_socket/generic/UdpGenericSocketConfigWidget.cpp index fa98276..ce43076 100644 --- a/plugin/udp_socket/UdpSocketConfigWidget.cpp +++ b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.cpp @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "UdpSocketConfigWidget.h" +#include "UdpGenericSocketConfigWidget.h" #include @@ -25,8 +25,8 @@ namespace cc_tools_qt namespace plugin { -UdpSocketConfigWidget::UdpSocketConfigWidget( - UdpSocket& socket, +UdpGenericSocketConfigWidget::UdpGenericSocketConfigWidget( + UdpGenericSocket& socket, QWidget* parentObj) : Base(parentObj), m_socket(socket) @@ -53,40 +53,40 @@ UdpSocketConfigWidget::UdpSocketConfigWidget( connect( m_ui.m_hostLineEdit, &QLineEdit::textChanged, - this, &UdpSocketConfigWidget::hostValueChanged); + this, &UdpGenericSocketConfigWidget::hostValueChanged); connect( m_ui.m_portSpinBox, qOverload(&QSpinBox::valueChanged), - this, &UdpSocketConfigWidget::portValueChanged); + this, &UdpGenericSocketConfigWidget::portValueChanged); connect( m_ui.m_localPortSpinBox, qOverload(&QSpinBox::valueChanged), - this, &UdpSocketConfigWidget::localPortValueChanged); + this, &UdpGenericSocketConfigWidget::localPortValueChanged); connect( m_ui.m_broadcastMaskLineEdit, &QLineEdit::textChanged, - this, &UdpSocketConfigWidget::broadcastMaskValueChanged); + this, &UdpGenericSocketConfigWidget::broadcastMaskValueChanged); } -UdpSocketConfigWidget::~UdpSocketConfigWidget() noexcept = default; +UdpGenericSocketConfigWidget::~UdpGenericSocketConfigWidget() noexcept = default; -void UdpSocketConfigWidget::hostValueChanged(const QString& value) +void UdpGenericSocketConfigWidget::hostValueChanged(const QString& value) { m_socket.setHost(value); } -void UdpSocketConfigWidget::portValueChanged(int value) +void UdpGenericSocketConfigWidget::portValueChanged(int value) { m_socket.setPort(static_cast(value)); } -void UdpSocketConfigWidget::localPortValueChanged(int value) +void UdpGenericSocketConfigWidget::localPortValueChanged(int value) { m_socket.setLocalPort(static_cast(value)); } -void UdpSocketConfigWidget::broadcastMaskValueChanged(const QString& value) +void UdpGenericSocketConfigWidget::broadcastMaskValueChanged(const QString& value) { m_socket.setBroadcastMask(value); } diff --git a/plugin/udp_socket/UdpSocketConfigWidget.h b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.h similarity index 75% rename from plugin/udp_socket/UdpSocketConfigWidget.h rename to plugin/udp_socket/generic/UdpGenericSocketConfigWidget.h index 708eb25..2f913f2 100644 --- a/plugin/udp_socket/UdpSocketConfigWidget.h +++ b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.h @@ -19,9 +19,9 @@ #pragma once #include -#include "ui_UdpSocketConfigWidget.h" +#include "ui_UdpGenericSocketConfigWidget.h" -#include "UdpSocket.h" +#include "UdpGenericSocket.h" namespace cc_tools_qt { @@ -29,18 +29,18 @@ namespace cc_tools_qt namespace plugin { -class UdpSocketConfigWidget : public QWidget +class UdpGenericSocketConfigWidget : public QWidget { Q_OBJECT typedef QWidget Base; public: - typedef UdpSocket::PortType PortType; + typedef UdpGenericSocket::PortType PortType; - explicit UdpSocketConfigWidget( - UdpSocket& socket, + explicit UdpGenericSocketConfigWidget( + UdpGenericSocket& socket, QWidget* parentObj = nullptr); - ~UdpSocketConfigWidget() noexcept; + ~UdpGenericSocketConfigWidget() noexcept; private slots: void hostValueChanged(const QString& value); @@ -49,8 +49,8 @@ private slots: void broadcastMaskValueChanged(const QString& value); private: - UdpSocket& m_socket; - Ui::UdpSocketConfigWidget m_ui; + UdpGenericSocket& m_socket; + Ui::UdpGenericSocketConfigWidget m_ui; }; } // namespace plugin diff --git a/plugin/udp_socket/UdpSocketConfigWidget.ui b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.ui similarity index 97% rename from plugin/udp_socket/UdpSocketConfigWidget.ui rename to plugin/udp_socket/generic/UdpGenericSocketConfigWidget.ui index 06140e1..934c5a0 100644 --- a/plugin/udp_socket/UdpSocketConfigWidget.ui +++ b/plugin/udp_socket/generic/UdpGenericSocketConfigWidget.ui @@ -1,7 +1,7 @@ - UdpSocketConfigWidget - + UdpGenericSocketConfigWidget + 0 diff --git a/plugin/udp_socket/UdpSocketPlugin.cpp b/plugin/udp_socket/generic/UdpGenericSocketPlugin.cpp similarity index 84% rename from plugin/udp_socket/UdpSocketPlugin.cpp rename to plugin/udp_socket/generic/UdpGenericSocketPlugin.cpp index d1bc3ef..04b34f2 100644 --- a/plugin/udp_socket/UdpSocketPlugin.cpp +++ b/plugin/udp_socket/generic/UdpGenericSocketPlugin.cpp @@ -15,12 +15,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "UdpSocketPlugin.h" +#include "UdpGenericSocketPlugin.h" #include #include -#include "UdpSocketConfigWidget.h" +#include "UdpGenericSocketConfigWidget.h" namespace cc_tools_qt { @@ -39,7 +39,7 @@ const QString BroadcastMaskSubKey("broadcast_prop"); } // namespace -UdpSocketPlugin::UdpSocketPlugin() +UdpGenericSocketPlugin::UdpGenericSocketPlugin() { pluginProperties() .setSocketCreateFunc( @@ -52,13 +52,13 @@ UdpSocketPlugin::UdpSocketPlugin() [this]() -> QWidget* { createSocketIfNeeded(); - return new UdpSocketConfigWidget(*m_socket); + return new UdpGenericSocketConfigWidget(*m_socket); }); } -UdpSocketPlugin::~UdpSocketPlugin() noexcept = default; +UdpGenericSocketPlugin::~UdpGenericSocketPlugin() noexcept = default; -void UdpSocketPlugin::getCurrentConfigImpl(QVariantMap& config) +void UdpGenericSocketPlugin::getCurrentConfigImpl(QVariantMap& config) { createSocketIfNeeded(); @@ -70,7 +70,7 @@ void UdpSocketPlugin::getCurrentConfigImpl(QVariantMap& config) config.insert(MainConfigKey, QVariant::fromValue(subConfig)); } -void UdpSocketPlugin::reconfigureImpl(const QVariantMap& config) +void UdpGenericSocketPlugin::reconfigureImpl(const QVariantMap& config) { auto subConfigVar = config.value(MainConfigKey); if ((!subConfigVar.isValid()) || (!subConfigVar.canConvert())) { @@ -87,7 +87,7 @@ void UdpSocketPlugin::reconfigureImpl(const QVariantMap& config) m_socket->setHost(host); } - typedef UdpSocket::PortType PortType; + typedef UdpGenericSocket::PortType PortType; auto portVar = subConfig.value(PortSubKey); if (portVar.isValid() && portVar.canConvert()) { auto port = portVar.value(); @@ -107,10 +107,10 @@ void UdpSocketPlugin::reconfigureImpl(const QVariantMap& config) } } -void UdpSocketPlugin::createSocketIfNeeded() +void UdpGenericSocketPlugin::createSocketIfNeeded() { if (!m_socket) { - m_socket.reset(new UdpSocket()); + m_socket.reset(new UdpGenericSocket()); } } diff --git a/plugin/udp_socket/UdpSocketPlugin.h b/plugin/udp_socket/generic/UdpGenericSocketPlugin.h similarity index 85% rename from plugin/udp_socket/UdpSocketPlugin.h rename to plugin/udp_socket/generic/UdpGenericSocketPlugin.h index 1047157..2ba83d4 100644 --- a/plugin/udp_socket/UdpSocketPlugin.h +++ b/plugin/udp_socket/generic/UdpGenericSocketPlugin.h @@ -22,7 +22,7 @@ #include "cc_tools_qt/Plugin.h" -#include "UdpSocket.h" +#include "UdpGenericSocket.h" namespace cc_tools_qt { @@ -30,15 +30,15 @@ namespace cc_tools_qt namespace plugin { -class UdpSocketPlugin : public cc_tools_qt::Plugin +class UdpGenericSocketPlugin : public cc_tools_qt::Plugin { Q_OBJECT Q_PLUGIN_METADATA(IID "cc.UdpSocketPlugin" FILE "udp_socket.json") Q_INTERFACES(cc_tools_qt::Plugin) public: - UdpSocketPlugin(); - ~UdpSocketPlugin() noexcept; + UdpGenericSocketPlugin(); + ~UdpGenericSocketPlugin() noexcept; virtual void getCurrentConfigImpl(QVariantMap& config) override; virtual void reconfigureImpl(const QVariantMap& config) override; @@ -47,7 +47,7 @@ class UdpSocketPlugin : public cc_tools_qt::Plugin void createSocketIfNeeded(); - std::shared_ptr m_socket; + std::shared_ptr m_socket; }; } // namespace plugin diff --git a/plugin/udp_socket/udp_socket.json b/plugin/udp_socket/generic/udp_socket.json similarity index 100% rename from plugin/udp_socket/udp_socket.json rename to plugin/udp_socket/generic/udp_socket.json diff --git a/plugin/udp_socket/proxy/CMakeLists.txt b/plugin/udp_socket/proxy/CMakeLists.txt new file mode 100644 index 0000000..f180346 --- /dev/null +++ b/plugin/udp_socket/proxy/CMakeLists.txt @@ -0,0 +1,55 @@ +if (NOT CC_TOOLS_QT_BUILD_PLUGIN_UDP_PROXY_SOCKET) + return() +endif () + +###################################################################### + +function (plugin_udp_proxy_socket) + set (name "cc_tools_plugin_udp_proxy_socket") + + if (NOT TARGET Qt::Network) + message(WARNING "Can NOT build ${name} due to missing Qt::Network library") + return() + endif () + + set (meta_file "${CMAKE_CURRENT_SOURCE_DIR}/udp_proxy_socket.json") + set (stamp_file "${CMAKE_CURRENT_BINARY_DIR}/refresh_stamp.txt") + + set (refresh_plugin_header TRUE) + if ((NOT EXISTS ${stamp_file}) OR (${meta_file} IS_NEWER_THAN ${stamp_file})) + execute_process( + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/UdpProxySocketPlugin.h) + execute_process( + COMMAND ${CMAKE_COMMAND} -E touch ${stamp_file}) + endif () + + set ( + ui + UdpProxySocketConfigWidget.ui + ) + + set (src + UdpProxySocket.cpp + UdpProxySocketPlugin.h + UdpProxySocketPlugin.cpp + UdpProxySocketConfigWidget.cpp + ) + + add_library (${name} MODULE ${ui} ${src}) + target_link_libraries(${name} PRIVATE cc::${PROJECT_NAME} Qt::Network Qt::Widgets Qt::Core) + + install ( + TARGETS ${name} + DESTINATION ${PLUGIN_INSTALL_DIR}) + +endfunction() + +###################################################################### + +cc_find_qt_components (Network) + +include_directories ( + ${CMAKE_CURRENT_BINARY_DIR} +) + +plugin_udp_proxy_socket () diff --git a/plugin/udp_socket/proxy/UdpProxySocket.cpp b/plugin/udp_socket/proxy/UdpProxySocket.cpp new file mode 100644 index 0000000..fb13879 --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocket.cpp @@ -0,0 +1,335 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + +#include +#include + +#include +#include + +#include "UdpProxySocket.h" + +namespace cc_tools_qt +{ + +namespace plugin +{ + +namespace +{ + +const QString DefaultHost("127.0.0.1"); +const QString FromPropName("udp.from"); +const QString ToPropName("udp.to"); + +} // namespace + + +UdpProxySocket::UdpProxySocket() + : m_host(DefaultHost) +{ +} + +UdpProxySocket::~UdpProxySocket() noexcept +{ + if (m_listenSocket) { + m_listenSocket->blockSignals(true); + } +} + +bool UdpProxySocket::socketConnectImpl() +{ + if (m_host.isEmpty()) { + static const QString Error = + "Remote host is not configured."; + reportError(Error); + return false; + } + + if (m_port == 0) { + static const QString Error = + "Remote port must be greater than 0."; + reportError(Error); + return false; + } + + if (m_localPort == 0) { + static const QString Error = + "Local port must be greater than 0."; + reportError(Error); + return false; + } + + if (!createListenSocket()) { + m_listenSocket.reset(); + return false; + } + + m_running = true; + return true; +} + +void UdpProxySocket::socketDisconnectImpl() +{ + if (m_listenSocket) { + m_listenSocket->blockSignals(true); + } + + if (m_remoteSocket) { + m_remoteSocket->blockSignals(true); + } + + m_listenSocket.reset(); + m_remoteSocket.reset(); + m_running = false; +} + +void UdpProxySocket::sendDataImpl(DataInfoPtr dataPtr) +{ + if (!m_running) { + return; + } + + assert(dataPtr); + assert(m_listenSocket); + QString from = + m_listenSocket->localAddress().toString() + ':' + + QString("%1").arg(m_listenSocket->localPort()); + dataPtr->m_extraProperties.insert(FromPropName, from); + + + assert(m_listenSocket); + if (!m_listenSocket->isOpen()) { + return; + } + + std::size_t writtenCount = 0; + while (writtenCount < dataPtr->m_data.size()) { + auto remSize = static_cast(dataPtr->m_data.size() - writtenCount); + auto count = + m_listenSocket->write( + reinterpret_cast(&dataPtr->m_data[writtenCount]), + remSize); + + if (count < 0) { + return; + } + + writtenCount += static_cast(count); + } + + QString to = + m_listenSocket->peerAddress().toString() + ':' + + QString("%1").arg(m_listenSocket->peerPort()); + + dataPtr->m_extraProperties.insert(ToPropName, to); +} + +void UdpProxySocket::listenSocketDisconnected() +{ + reportDisconnected(); + if (m_remoteSocket) { + m_remoteSocket->blockSignals(true); + } + + m_remoteSocket.reset(); + m_listenSocket->blockSignals(true); + m_listenSocket.release()->deleteLater(); +} + +void UdpProxySocket::readFromListenSocket() +{ + createRemoteSocketIfNeeded(); + + assert(m_listenSocket); + while (m_listenSocket->hasPendingDatagrams()) { + QHostAddress senderAddress; + quint16 senderPort; + + auto dataPtr = makeDataInfo(); + dataPtr->m_timestamp = DataInfo::TimestampClock::now(); + dataPtr->m_data.resize(static_cast(m_listenSocket->pendingDatagramSize())); + m_listenSocket->readDatagram( + reinterpret_cast(&dataPtr->m_data[0]), + static_cast(dataPtr->m_data.size()), + &senderAddress, + &senderPort); + + if (!m_running) { + continue; + } + + + QString from = + senderAddress.toString() + ':' + + QString("%1").arg(senderPort); + QString to = + m_listenSocket->localAddress().toString() + ':' + + QString("%1").arg(m_listenSocket->localPort()); + + if (m_remoteSocket) { + m_remoteSocket->write(reinterpret_cast(dataPtr->m_data.data()), static_cast(dataPtr->m_data.size())); + + to = m_remoteSocket->peerAddress().toString() + ':' + + QString("%1").arg(m_remoteSocket->peerPort()); + } + + + dataPtr->m_extraProperties.insert(FromPropName, from); + dataPtr->m_extraProperties.insert(ToPropName, to); + reportDataReceived(std::move(dataPtr)); + } +} + +void UdpProxySocket::listenSocketErrorOccurred([[maybe_unused]] QAbstractSocket::SocketError err) +{ + assert(m_listenSocket); + reportError(QString("Listen socket error: " + m_listenSocket->errorString())); +} + +void UdpProxySocket::remoteSocketDisconnected() +{ + assert(m_remoteSocket); + reportDisconnected(); + + if (m_listenSocket) { + m_remoteSocket->blockSignals(true); + } + + m_listenSocket.reset(); + m_remoteSocket->blockSignals(true); + m_remoteSocket.release()->deleteLater(); +} + +void UdpProxySocket::readFromRemoteSocket() +{ + assert(m_remoteSocket); + while (m_remoteSocket->hasPendingDatagrams()) { + QHostAddress senderAddress; + quint16 senderPort; + + auto dataPtr = makeDataInfo(); + dataPtr->m_timestamp = DataInfo::TimestampClock::now(); + dataPtr->m_data.resize(static_cast(m_remoteSocket->pendingDatagramSize())); + m_remoteSocket->readDatagram( + reinterpret_cast(&dataPtr->m_data[0]), + static_cast(dataPtr->m_data.size()), + &senderAddress, + &senderPort); + + if (!m_running) { + continue; + } + + QString from = + senderAddress.toString() + ':' + + QString("%1").arg(senderPort); + QString to = + m_remoteSocket->localAddress().toString() + ':' + + QString("%1").arg(m_remoteSocket->localPort()); + + if (m_listenSocket) { + m_listenSocket->write(reinterpret_cast(dataPtr->m_data.data()), static_cast(dataPtr->m_data.size())); + + to = m_listenSocket->peerAddress().toString() + ':' + + QString("%1").arg(m_listenSocket->peerPort()); + } + + dataPtr->m_extraProperties.insert(FromPropName, from); + dataPtr->m_extraProperties.insert(ToPropName, to); + reportDataReceived(std::move(dataPtr)); + } +} + +void UdpProxySocket::remoteSocketErrorOccurred([[maybe_unused]] QAbstractSocket::SocketError err) +{ + assert(m_remoteSocket); + reportError(QString("Remote connection socket error: " + m_remoteSocket->errorString())); +} + +bool UdpProxySocket::createListenSocket() +{ + m_listenSocket = std::make_unique(); + + connect( + m_listenSocket.get(), &QUdpSocket::disconnected, + this, &UdpProxySocket::listenSocketDisconnected); + connect( + m_listenSocket.get(), &QUdpSocket::readyRead, + this, &UdpProxySocket::readFromListenSocket); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect( + m_listenSocket.get(), &QUdpSocket::errorOccurred, + this, &UdpProxySocket::listenSocketErrorOccurred); + +#else // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect( + m_listenSocket.get(), SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(listenSocketErrorOccurred(QAbstractSocket::SocketError))); +#endif // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + + if (!m_listenSocket->bind(QHostAddress::AnyIPv4, m_localPort)) { + reportError("Failed to bind UDP socket to port " + QString("%1").arg(m_localPort)); + return false; + } + + if (!m_listenSocket->open(QUdpSocket::ReadWrite)) { + reportError("Failed to open local UDP listening on port " + QString("%1").arg(m_localPort)); + return false; + } + + return true; +} + +void UdpProxySocket::createRemoteSocketIfNeeded() +{ + if (m_remoteSocket) { + return; + } + + m_remoteSocket = std::make_unique(); + + connect( + m_remoteSocket.get(), &QUdpSocket::disconnected, + this, &UdpProxySocket::remoteSocketDisconnected); + connect( + m_remoteSocket.get(), &QUdpSocket::readyRead, + this, &UdpProxySocket::readFromRemoteSocket); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect( + m_remoteSocket.get(), &QUdpSocket::errorOccurred, + this, &UdpProxySocket::remoteSocketErrorOccurred); + +#else // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect( + m_remoteSocket.get(), SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(remoteSocketErrorOccurred(QAbstractSocket::SocketError))); +#endif // #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + + m_remoteSocket->connectToHost(m_host, m_port); + if (!m_remoteSocket->waitForConnected(1000)) { + reportError("Failed to connect to remote " + QString("%1:%2").arg(m_host).arg(m_port)); + m_remoteSocket.reset(); + return; + } +} + +} // namespace plugin + +} // namespace cc_tools_qt diff --git a/plugin/udp_socket/proxy/UdpProxySocket.h b/plugin/udp_socket/proxy/UdpProxySocket.h new file mode 100644 index 0000000..f4051cd --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocket.h @@ -0,0 +1,107 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + +#pragma once + +#include + +#include + +#include "cc_tools_qt/Socket.h" + + +namespace cc_tools_qt +{ + +namespace plugin +{ + +class UdpProxySocket : public QObject, public cc_tools_qt::Socket +{ + Q_OBJECT + using Base = cc_tools_qt::Socket; + +public: + typedef unsigned short PortType; + + UdpProxySocket(); + ~UdpProxySocket() noexcept; + + void setHost(const QString& value) + { + m_host = value; + } + + const QString& getHost() const + { + return m_host; + } + + void setPort(PortType value) + { + m_port = value; + } + + PortType getPort() const + { + return m_port; + } + + void setLocalPort(PortType value) + { + m_localPort = value; + } + + PortType getLocalPort() const + { + return m_localPort; + } + +protected: + virtual bool socketConnectImpl() override; + virtual void socketDisconnectImpl() override; + virtual void sendDataImpl(DataInfoPtr dataPtr) override; + +private slots: + void listenSocketDisconnected(); + void readFromListenSocket(); + void listenSocketErrorOccurred(QAbstractSocket::SocketError err); + void remoteSocketDisconnected(); + void readFromRemoteSocket(); + void remoteSocketErrorOccurred(QAbstractSocket::SocketError err); + + +private: + using SocketPtr = std::unique_ptr; + + void readData(QUdpSocket& socket); + bool createListenSocket(); + void createRemoteSocketIfNeeded(); + + static const PortType DefaultPort = 20000; + + QString m_host; + PortType m_port = DefaultPort; + PortType m_localPort = DefaultPort + 1; + SocketPtr m_listenSocket; + SocketPtr m_remoteSocket; + bool m_running = false; +}; + +} // namespace plugin + +} // namespace cc_tools_qt diff --git a/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.cpp b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.cpp new file mode 100644 index 0000000..1b4c1bb --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.cpp @@ -0,0 +1,86 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + +#include "UdpProxySocketConfigWidget.h" + +#include + +namespace cc_tools_qt +{ + +namespace plugin +{ + +UdpProxySocketConfigWidget::UdpProxySocketConfigWidget( + UdpProxySocket& socket, + QWidget* parentObj) + : Base(parentObj), + m_socket(socket) +{ + m_ui.setupUi(this); + + m_ui.m_portSpinBox->setRange( + 0, + static_cast(std::numeric_limits::max())); + + m_ui.m_localPortSpinBox->setRange( + 0, + static_cast(std::numeric_limits::max())); + + m_ui.m_hostLineEdit->setText(m_socket.getHost()); + + m_ui.m_portSpinBox->setValue( + static_cast(m_socket.getPort())); + + m_ui.m_localPortSpinBox->setValue( + static_cast(m_socket.getLocalPort())); + + connect( + m_ui.m_hostLineEdit, &QLineEdit::textChanged, + this, &UdpProxySocketConfigWidget::hostValueChanged); + + connect( + m_ui.m_portSpinBox, qOverload(&QSpinBox::valueChanged), + this, &UdpProxySocketConfigWidget::portValueChanged); + + connect( + m_ui.m_localPortSpinBox, qOverload(&QSpinBox::valueChanged), + this, &UdpProxySocketConfigWidget::localPortValueChanged); +} + +UdpProxySocketConfigWidget::~UdpProxySocketConfigWidget() noexcept = default; + +void UdpProxySocketConfigWidget::hostValueChanged(const QString& value) +{ + m_socket.setHost(value); +} + +void UdpProxySocketConfigWidget::portValueChanged(int value) +{ + m_socket.setPort(static_cast(value)); +} + +void UdpProxySocketConfigWidget::localPortValueChanged(int value) +{ + m_socket.setLocalPort(static_cast(value)); +} + +} // namespace plugin + +} // namespace cc_tools_qt + + diff --git a/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.h b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.h new file mode 100644 index 0000000..597176c --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.h @@ -0,0 +1,59 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + + +#pragma once + +#include +#include "ui_UdpProxySocketConfigWidget.h" + +#include "UdpProxySocket.h" + +namespace cc_tools_qt +{ + +namespace plugin +{ + +class UdpProxySocketConfigWidget : public QWidget +{ + Q_OBJECT + typedef QWidget Base; +public: + typedef UdpProxySocket::PortType PortType; + + explicit UdpProxySocketConfigWidget( + UdpProxySocket& socket, + QWidget* parentObj = nullptr); + + ~UdpProxySocketConfigWidget() noexcept; + +private slots: + void hostValueChanged(const QString& value); + void portValueChanged(int value); + void localPortValueChanged(int value); + +private: + UdpProxySocket& m_socket; + Ui::UdpProxySocketConfigWidget m_ui; +}; + +} // namespace plugin + +} // namespace cc_tools_qt + + diff --git a/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.ui b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.ui new file mode 100644 index 0000000..85b4338 --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocketConfigWidget.ui @@ -0,0 +1,118 @@ + + + UdpProxySocketConfigWidget + + + + 0 + 0 + 283 + 172 + + + + UDP Proxy Socket Configuration Widget + + + + + + + + Remote host: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Remote Port: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 means not bound, chosen by the OS + + + Local Port: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/plugin/udp_socket/proxy/UdpProxySocketPlugin.cpp b/plugin/udp_socket/proxy/UdpProxySocketPlugin.cpp new file mode 100644 index 0000000..d8618a3 --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocketPlugin.cpp @@ -0,0 +1,113 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + +#include "UdpProxySocketPlugin.h" + +#include +#include + +#include "UdpProxySocketConfigWidget.h" + +namespace cc_tools_qt +{ + +namespace plugin +{ + +namespace +{ + +const QString MainConfigKey("cc_udp_proxy_socket"); +const QString HostSubKey("remote_host"); +const QString PortSubKey("remote_port"); +const QString LocalPortSubKey("local_port"); + +} // namespace + +UdpProxySocketPlugin::UdpProxySocketPlugin() +{ + pluginProperties() + .setSocketCreateFunc( + [this]() -> SocketPtr + { + createSocketIfNeeded(); + return m_socket; + }) + .setConfigWidgetCreateFunc( + [this]() -> QWidget* + { + createSocketIfNeeded(); + return new UdpProxySocketConfigWidget(*m_socket); + }); +} + +UdpProxySocketPlugin::~UdpProxySocketPlugin() noexcept = default; + +void UdpProxySocketPlugin::getCurrentConfigImpl(QVariantMap& config) +{ + createSocketIfNeeded(); + + QVariantMap subConfig; + subConfig.insert(HostSubKey, m_socket->getHost()); + subConfig.insert(PortSubKey, m_socket->getPort()); + subConfig.insert(LocalPortSubKey, m_socket->getLocalPort()); + config.insert(MainConfigKey, QVariant::fromValue(subConfig)); +} + +void UdpProxySocketPlugin::reconfigureImpl(const QVariantMap& config) +{ + auto subConfigVar = config.value(MainConfigKey); + if ((!subConfigVar.isValid()) || (!subConfigVar.canConvert())) { + return; + } + + createSocketIfNeeded(); + assert(m_socket); + + auto subConfig = subConfigVar.value(); + auto hostVar = subConfig.value(HostSubKey); + if (hostVar.isValid() && hostVar.canConvert()) { + auto host = hostVar.value(); + m_socket->setHost(host); + } + + typedef UdpProxySocket::PortType PortType; + auto portVar = subConfig.value(PortSubKey); + if (portVar.isValid() && portVar.canConvert()) { + auto port = portVar.value(); + m_socket->setPort(port); + } + + auto localPortVar = subConfig.value(LocalPortSubKey); + if (localPortVar.isValid() && localPortVar.canConvert()) { + auto port = localPortVar.value(); + m_socket->setLocalPort(port); + } +} + +void UdpProxySocketPlugin::createSocketIfNeeded() +{ + if (!m_socket) { + m_socket.reset(new UdpProxySocket()); + } +} + +} // namespace plugin + +} // namespace cc_tools_qt + + diff --git a/plugin/udp_socket/proxy/UdpProxySocketPlugin.h b/plugin/udp_socket/proxy/UdpProxySocketPlugin.h new file mode 100644 index 0000000..9938595 --- /dev/null +++ b/plugin/udp_socket/proxy/UdpProxySocketPlugin.h @@ -0,0 +1,59 @@ +// +// Copyright 2016 - 2024 (C). Alex Robenko. All rights reserved. +// + +// This file 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 3 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, see . + + +#pragma once + +#include + +#include "cc_tools_qt/Plugin.h" + +#include "UdpProxySocket.h" + +namespace cc_tools_qt +{ + +namespace plugin +{ + +class UdpProxySocketPlugin : public cc_tools_qt::Plugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "cc.UdpSocketPlugin" FILE "udp_proxy_socket.json") + Q_INTERFACES(cc_tools_qt::Plugin) + +public: + UdpProxySocketPlugin(); + ~UdpProxySocketPlugin() noexcept; + + virtual void getCurrentConfigImpl(QVariantMap& config) override; + virtual void reconfigureImpl(const QVariantMap& config) override; + +private: + + void createSocketIfNeeded(); + + std::shared_ptr m_socket; +}; + +} // namespace plugin + +} // namespace cc_tools_qt + + + + diff --git a/plugin/udp_socket/proxy/udp_proxy_socket.json b/plugin/udp_socket/proxy/udp_proxy_socket.json new file mode 100644 index 0000000..349217d --- /dev/null +++ b/plugin/udp_socket/proxy/udp_proxy_socket.json @@ -0,0 +1,7 @@ +{ + "name" : "CC UDP/IP Proxy Socket", + "desc" : [ + "I/O socket that serves as proxy UDP/IP server" + ], + "type" : "socket" +}