diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common/private')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.cpp | 130 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.h | 38 |
2 files changed, 168 insertions, 0 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.cpp b/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.cpp new file mode 100644 index 0000000..a3d696e --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.cpp @@ -0,0 +1,130 @@ +#include "blockingsocketprivate.h" +#include <QTcpSocket> +#include <QCoreApplication> +#include <QTimer> +#include <QThread> + +BlockingSocketPrivate::BlockingSocketPrivate() +{ +} + +BlockingSocketPrivate::~BlockingSocketPrivate() +{ +} + +void BlockingSocketPrivate::setError(QAbstractSocket::SocketError errorCode, const QString& errMsg) +{ + this->errorCode = errorCode; + this->errorText = errMsg; +} + +bool BlockingSocketPrivate::isConnected() +{ + return (socket && socket->isOpen() && socket->state() == QAbstractSocket::ConnectedState); +} + +QAbstractSocket::SocketError BlockingSocketPrivate::getErrorCode() +{ + return errorCode; +} + +void BlockingSocketPrivate::createSocketIfNecessary() +{ + // This method is called only when the socket is already called, + // so we're sure the socket is created in the target thread. + if (socket) + return; + + socket = new QTcpSocket(this); + connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected())); +} + +QString BlockingSocketPrivate::getErrorText() +{ + return errorText; +} + +void BlockingSocketPrivate::handleSendCall(const QByteArray& bytes, bool& result) +{ + createSocketIfNecessary(); + result = true; + qint64 size = bytes.size(); + qint64 totalBytesSent = 0; + qint64 bytesSent = 0; + while (totalBytesSent < size) + { + bytesSent = socket->write(totalBytesSent == 0 ? bytes : bytes.mid(totalBytesSent)); + if (bytesSent < 0) + { + result = false; + setError(socket->error(), socket->errorString()); + return; + } + totalBytesSent += bytesSent; + } +} + +void BlockingSocketPrivate::handleReadCall(qint64 count, int timeout, QByteArray& resultBytes, bool& result) +{ + createSocketIfNecessary(); + resultBytes.clear(); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + + QTimer timer; + timer.setSingleShot(true); + timer.setInterval(timeout); + timer.start(); + + while (resultBytes.size() < count && timer.isActive()) + { + if (!isConnected()) + { + qWarning() << "Blocking socket closed in the middle of reading."; + result = false; + setError(socket->error(), socket->errorString()); + return; + } + + if (socket->bytesAvailable() == 0) + { + QThread::msleep(1); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + continue; + } + + resultBytes += socket->read(qMin(socket->bytesAvailable(), count)); + } + + result = (resultBytes.size() >= count && timer.isActive()); +} + +void BlockingSocketPrivate::handleConnectCall(const QString& host, int port, bool& result) +{ + result = true; + if (isConnected()) + return; + + createSocketIfNecessary(); + socket->connectToHost(host, port); + if (!socket->waitForConnected()) + { + result = false; + setError(socket->error(), socket->errorString()); + } +} + +void BlockingSocketPrivate::handleDisconnectCall() +{ + if (!isConnected()) + return; + + createSocketIfNecessary(); + socket->abort(); + socket->close(); + +} + +void BlockingSocketPrivate::handleIsConnectedCall(bool& connected) +{ + connected = isConnected(); +} diff --git a/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.h b/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.h new file mode 100644 index 0000000..8d7b994 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/private/blockingsocketprivate.h @@ -0,0 +1,38 @@ +#ifndef BLOCKINGSOCKETPRIVATE_H +#define BLOCKINGSOCKETPRIVATE_H + +#include <QObject> +#include <QAbstractSocket> + +class BlockingSocketPrivate : public QObject +{ + Q_OBJECT + + public: + BlockingSocketPrivate(); + ~BlockingSocketPrivate(); + + QString getErrorText(); + QAbstractSocket::SocketError getErrorCode(); + + private: + void createSocketIfNecessary(); + void setError(QAbstractSocket::SocketError errorCode, const QString& errMsg); + bool isConnected(); + + QAbstractSocket* socket = nullptr; + QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError; + QString errorText; + + private slots: + void handleSendCall(const QByteArray& bytes, bool& result); + void handleReadCall(qint64 count, int timeout, QByteArray& resultBytes, bool& result); + void handleConnectCall(const QString& host, int port, bool& result); + void handleDisconnectCall(); + void handleIsConnectedCall(bool& connected); + + signals: + void disconnected(); +}; + +#endif // BLOCKINGSOCKETPRIVATE_H |
