From 6c39e136fd35dc10f57aef74aff605424469c0bb Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 26 Jun 2024 15:34:45 +0200 Subject: [PATCH] Tasking: Introduce TcpSocketTask Change-Id: I9640a7016dd833394a1e62be93af129f517ae1a2 Reviewed-by: hjk --- src/libs/solutions/tasking/CMakeLists.txt | 2 + src/libs/solutions/tasking/tasking.qbs | 2 + src/libs/solutions/tasking/tcpsocket.cpp | 67 +++++++++++++++++++++++ src/libs/solutions/tasking/tcpsocket.h | 63 +++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 src/libs/solutions/tasking/tcpsocket.cpp create mode 100644 src/libs/solutions/tasking/tcpsocket.h diff --git a/src/libs/solutions/tasking/CMakeLists.txt b/src/libs/solutions/tasking/CMakeLists.txt index 2607a76891f..642fff07790 100644 --- a/src/libs/solutions/tasking/CMakeLists.txt +++ b/src/libs/solutions/tasking/CMakeLists.txt @@ -16,6 +16,8 @@ add_qtc_library(Tasking OBJECT tasktree.h tasktreerunner.cpp tasktreerunner.h + tcpsocket.cpp + tcpsocket.h EXPLICIT_MOC networkquery.h ) diff --git a/src/libs/solutions/tasking/tasking.qbs b/src/libs/solutions/tasking/tasking.qbs index c8a0894b8a8..90f3306e8e2 100644 --- a/src/libs/solutions/tasking/tasking.qbs +++ b/src/libs/solutions/tasking/tasking.qbs @@ -20,6 +20,8 @@ QtcLibrary { "tasktree.h", "tasktreerunner.cpp", "tasktreerunner.h", + "tcpsocket.cpp", + "tcpsocket.h", ] Export { diff --git a/src/libs/solutions/tasking/tcpsocket.cpp b/src/libs/solutions/tasking/tcpsocket.cpp new file mode 100644 index 00000000000..78f35ab21af --- /dev/null +++ b/src/libs/solutions/tasking/tcpsocket.cpp @@ -0,0 +1,67 @@ +// Copyright (C) 2024 Jarek Kobus +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "tcpsocket.h" + +QT_BEGIN_NAMESPACE + +namespace Tasking { + +void TcpSocket::start() +{ + if (m_socket) { + qWarning("The TcpSocket is already running. Ignoring the call to start()."); + return; + } + if (m_address.isNull()) { + qWarning("Can't start the TcpSocket with invalid address. " + "Stopping with an error."); + m_error = QAbstractSocket::HostNotFoundError; + emit done(DoneResult::Error); + return; + } + + m_socket.reset(new QTcpSocket); + connect(m_socket.get(), &QAbstractSocket::errorOccurred, this, + [this](QAbstractSocket::SocketError error) { + m_error = error; + m_socket->disconnect(); + emit done(DoneResult::Error); + m_socket.release()->deleteLater(); + }); + connect(m_socket.get(), &QAbstractSocket::connected, this, [this] { + if (!m_writeData.isEmpty()) + m_socket->write(m_writeData); + emit started(); + }); + connect(m_socket.get(), &QAbstractSocket::disconnected, this, [this] { + m_socket->disconnect(); + emit done(DoneResult::Success); + m_socket.release()->deleteLater(); + }); + + m_socket->connectToHost(m_address, m_port); +} + +TcpSocket::~TcpSocket() +{ + if (m_socket) { + m_socket->disconnect(); + m_socket->abort(); + } +} + +TcpSocketTaskAdapter::TcpSocketTaskAdapter() +{ + connect(task(), &TcpSocket::done, this, &TaskInterface::done); +} + +void TcpSocketTaskAdapter::start() +{ + task()->start(); +} + +} // namespace Tasking + +QT_END_NAMESPACE diff --git a/src/libs/solutions/tasking/tcpsocket.h b/src/libs/solutions/tasking/tcpsocket.h new file mode 100644 index 00000000000..b7d0f1fe1a6 --- /dev/null +++ b/src/libs/solutions/tasking/tcpsocket.h @@ -0,0 +1,63 @@ +// Copyright (C) 2024 Jarek Kobus +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef TASKING_TCPSOCKET_H +#define TASKING_TCPSOCKET_H + +#include "tasking_global.h" + +#include "tasktree.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace Tasking { + +// This class introduces the dependency to Qt::Network, otherwise Tasking namespace +// is independent on Qt::Network. +// Possibly, it could be placed inside Qt::Network library, as a wrapper around QTcpSocket. + +enum class NetworkOperation { Get, Put, Post, Delete }; + +class TASKING_EXPORT TcpSocket final : public QObject +{ + Q_OBJECT + +public: + ~TcpSocket(); + void setAddress(const QHostAddress &address) { m_address = address; } + void setPort(quint16 port) { m_port = port; } + void setWriteData(const QByteArray &data) { m_writeData = data; } + QTcpSocket *socket() const { return m_socket.get(); } + void start(); + +Q_SIGNALS: + void started(); + void done(DoneResult result); + +private: + QHostAddress m_address; + quint16 m_port = 0; + QByteArray m_writeData; + std::unique_ptr m_socket; + QAbstractSocket::SocketError m_error = QAbstractSocket::UnknownSocketError; +}; + +class TASKING_EXPORT TcpSocketTaskAdapter final : public TaskAdapter +{ +public: + TcpSocketTaskAdapter(); + void start() final; +}; + +using TcpSocketTask = CustomTask; + +} // namespace Tasking + +QT_END_NAMESPACE + +#endif // TASKING_TCPSOCKET_H