| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtQml module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qtcpserverconnectionfactory.h" |
| |
| #include <private/qqmldebugserver_p.h> |
| |
| #include <QtCore/qplugin.h> |
| #include <QtNetwork/qtcpserver.h> |
| #include <QtNetwork/qtcpsocket.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| class QTcpServerConnection : public QQmlDebugServerConnection |
| { |
| Q_OBJECT |
| Q_DISABLE_COPY(QTcpServerConnection) |
| |
| public: |
| QTcpServerConnection(); |
| ~QTcpServerConnection() override; |
| |
| void setServer(QQmlDebugServer *server) override; |
| bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) override; |
| bool setFileName(const QString &fileName, bool block) override; |
| |
| bool isConnected() const override; |
| void disconnect() override; |
| |
| void waitForConnection() override; |
| void flush() override; |
| |
| private: |
| void newConnection(); |
| bool listen(); |
| |
| int m_portFrom = 0; |
| int m_portTo = 0; |
| bool m_block = false; |
| QString m_hostaddress; |
| QTcpSocket *m_socket = nullptr; |
| QTcpServer *m_tcpServer = nullptr; |
| QQmlDebugServer *m_debugServer = nullptr; |
| }; |
| |
| QTcpServerConnection::QTcpServerConnection() {} |
| |
| QTcpServerConnection::~QTcpServerConnection() |
| { |
| if (isConnected()) |
| disconnect(); |
| } |
| |
| void QTcpServerConnection::setServer(QQmlDebugServer *server) |
| { |
| m_debugServer = server; |
| } |
| |
| bool QTcpServerConnection::isConnected() const |
| { |
| return m_socket && m_socket->state() == QTcpSocket::ConnectedState; |
| } |
| |
| void QTcpServerConnection::disconnect() |
| { |
| while (m_socket && m_socket->bytesToWrite() > 0) { |
| if (!m_socket->waitForBytesWritten()) { |
| qWarning("QML Debugger: Failed to send remaining %lld bytes on disconnect.", |
| m_socket->bytesToWrite()); |
| break; |
| } |
| } |
| |
| m_socket->deleteLater(); |
| m_socket = nullptr; |
| } |
| |
| bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block, |
| const QString &hostaddress) |
| { |
| m_portFrom = portFrom; |
| m_portTo = portTo; |
| m_block = block; |
| m_hostaddress = hostaddress; |
| |
| return listen(); |
| } |
| |
| bool QTcpServerConnection::setFileName(const QString &fileName, bool block) |
| { |
| Q_UNUSED(fileName); |
| Q_UNUSED(block); |
| return false; |
| } |
| |
| void QTcpServerConnection::waitForConnection() |
| { |
| m_tcpServer->waitForNewConnection(-1); |
| } |
| |
| void QTcpServerConnection::flush() |
| { |
| if (m_socket) |
| m_socket->flush(); |
| } |
| |
| bool QTcpServerConnection::listen() |
| { |
| m_tcpServer = new QTcpServer(this); |
| QObject::connect(m_tcpServer, &QTcpServer::newConnection, |
| this, &QTcpServerConnection::newConnection); |
| QHostAddress hostaddress; |
| if (!m_hostaddress.isEmpty()) { |
| if (!hostaddress.setAddress(m_hostaddress)) { |
| hostaddress = QHostAddress::Any; |
| qDebug("QML Debugger: Incorrect host address provided. So accepting connections " |
| "from any host."); |
| } |
| } else { |
| hostaddress = QHostAddress::Any; |
| } |
| int port = m_portFrom; |
| do { |
| if (m_tcpServer->listen(hostaddress, port)) { |
| qDebug("QML Debugger: Waiting for connection on port %d...", port); |
| break; |
| } |
| ++port; |
| } while (port <= m_portTo); |
| if (port > m_portTo) { |
| if (m_portFrom == m_portTo) |
| qWarning("QML Debugger: Unable to listen to port %d.", m_portFrom); |
| else |
| qWarning("QML Debugger: Unable to listen to ports %d - %d.", m_portFrom, m_portTo); |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| void QTcpServerConnection::newConnection() |
| { |
| if (m_socket && m_socket->peerPort()) { |
| qWarning("QML Debugger: Another client is already connected."); |
| QTcpSocket *faultyConnection = m_tcpServer->nextPendingConnection(); |
| delete faultyConnection; |
| return; |
| } |
| |
| delete m_socket; |
| m_socket = m_tcpServer->nextPendingConnection(); |
| m_socket->setParent(this); |
| m_debugServer->setDevice(m_socket); |
| } |
| |
| QQmlDebugServerConnection *QTcpServerConnectionFactory::create(const QString &key) |
| { |
| return (key == QLatin1String("QTcpServerConnection") ? new QTcpServerConnection : nullptr); |
| } |
| |
| QT_END_NAMESPACE |
| |
| #include "qtcpserverconnection.moc" |