From 35d7bc49f0b8766c541274489a37334d3acb6a92 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Wed, 10 Mar 2021 14:25:17 +0100 Subject: [PATCH] iOS: Add relay server to route gdb data via service connection Communication using sockets can no longer be done for gdb server, though a TCP socket opened using USB MUX still operates normally. I.e the QML debug server communication remains as is but GDB server data has to be routed via the secure service connection Task-number: QTCREATORBUG-24672 Change-Id: I64631d66dc845dd2d7a20c771534ae17e183a9b8 Reviewed-by: Eike Ziller --- src/tools/iostool/iostool.cpp | 4 +- src/tools/iostool/iostool.h | 8 +-- src/tools/iostool/relayserver.cpp | 100 +++++++++++++++++++++++------- src/tools/iostool/relayserver.h | 41 ++++++++---- 4 files changed, 115 insertions(+), 38 deletions(-) diff --git a/src/tools/iostool/iostool.cpp b/src/tools/iostool/iostool.cpp index d0be8ede5e9..e65cae852a4 100644 --- a/src/tools/iostool/iostool.cpp +++ b/src/tools/iostool/iostool.cpp @@ -259,12 +259,12 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId, if (deviceSession) { int qmlPort = deviceSession->qmljsDebugPort(); if (qmlPort) { - qmlServer = new GenericRelayServer(this, qmlPort, deviceSession); + qmlServer = new QmlRelayServer(this, qmlPort, deviceSession); qmlServer->startServer(); } } if (debug) { - gdbServer = new SingleRelayServer(this, gdbFd); + gdbServer = new GdbRelayServer(this, gdbFd, conn); if (!gdbServer->startServer()) { doExit(-4); return; diff --git a/src/tools/iostool/iostool.h b/src/tools/iostool/iostool.h index 3519982c9b9..a2fd1f040e4 100644 --- a/src/tools/iostool/iostool.h +++ b/src/tools/iostool/iostool.h @@ -34,8 +34,8 @@ namespace Ios { class GdbRunner; -class SingleRelayServer; -class GenericRelayServer; +class GdbRelayServer; +class QmlRelayServer; class IosTool: public QObject { @@ -79,8 +79,8 @@ private: QFile outFile; QString m_qmlPort; QXmlStreamWriter out; - SingleRelayServer *gdbServer; - GenericRelayServer *qmlServer; + GdbRelayServer *gdbServer; + QmlRelayServer *qmlServer; GdbRunner *gdbRunner; bool m_echoRelays = false; friend class GdbRunner; diff --git a/src/tools/iostool/relayserver.cpp b/src/tools/iostool/relayserver.cpp index f952560752a..449f86057db 100644 --- a/src/tools/iostool/relayserver.cpp +++ b/src/tools/iostool/relayserver.cpp @@ -26,6 +26,7 @@ #include "relayserver.h" #include "iostool.h" +#include "mobiledevicelib.h" #ifdef Q_OS_UNIX #include @@ -45,15 +46,7 @@ Relayer::Relayer(RelayServer *parent, QTcpSocket *clientSocket) : Relayer::~Relayer() { - if (m_serverFileDescriptor > 0) { - ::close(m_serverFileDescriptor); - m_serverFileDescriptor = -1; - if (m_serverNotifier) - delete m_serverNotifier; - } - if (m_clientSocket->isOpen()) - m_clientSocket->close(); - delete m_clientSocket; + closeConnection(); } void Relayer::setClientSocket(QTcpSocket *clientSocket) @@ -93,7 +86,7 @@ void Relayer::handleSocketHasData(int socket) m_serverNotifier->setEnabled(false); char buf[255]; while (true) { - qptrdiff rRead = read(socket, &buf, sizeof(buf)-1); + qptrdiff rRead = readData(socket, &buf, sizeof(buf)-1); if (rRead == -1) { if (errno == EINTR) continue; @@ -158,7 +151,7 @@ void Relayer::handleClientHasData() .arg((quintptr)(void *)this), buf, rRead); } while (true) { - qptrdiff written = write(m_serverFileDescriptor, buf + pos, rRead); + qptrdiff written = writeData(m_serverFileDescriptor, buf + pos, rRead); if (written == -1) { if (errno == EINTR) continue; @@ -193,6 +186,32 @@ void Relayer::handleClientHasError(QAbstractSocket::SocketError error) server()->removeRelayConnection(this); } +int Relayer::readData(int socketFd, void *buf, size_t size) +{ + return read(socketFd, buf, size); +} + +int Relayer::writeData(int socketFd, const void *data, size_t size) +{ + return write(socketFd, data, size); +} + +void Relayer::closeConnection() +{ + if (m_serverFileDescriptor > 0) { + ::close(m_serverFileDescriptor); + m_serverFileDescriptor = -1; + if (m_serverNotifier) { + delete m_serverNotifier; + m_serverNotifier = nullptr; + } + } + if (m_clientSocket->isOpen()) + m_clientSocket->close(); + delete m_clientSocket; + m_clientSocket = nullptr; +} + IosTool *Relayer::iosTool() const { return (server() ? server()->iosTool() : 0); @@ -203,7 +222,7 @@ RelayServer *Relayer::server() const return qobject_cast(parent()); } -RemotePortRelayer::RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket) : +RemotePortRelayer::RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket) : Relayer(parent, clientSocket) { m_remoteConnectTimer.setSingleShot(true); @@ -217,7 +236,7 @@ void RemotePortRelayer::tryRemoteConnect() if (m_serverFileDescriptor > 0) return; ServiceSocket ss; - GenericRelayServer *grServer = qobject_cast(server()); + QmlRelayServer *grServer = qobject_cast(server()); if (!grServer) return; if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) { @@ -294,16 +313,17 @@ void RelayServer::removeRelayConnection(Relayer *relayer) relayer->deleteLater(); } -SingleRelayServer::SingleRelayServer(IosTool *parent, - int serverFileDescriptor) : - RelayServer(parent) +GdbRelayServer::GdbRelayServer(IosTool *parent, + int serverFileDescriptor, ServiceConnRef conn) : + RelayServer(parent), + m_serverFileDescriptor(serverFileDescriptor), + m_serviceConn(conn) { - m_serverFileDescriptor = serverFileDescriptor; if (m_serverFileDescriptor > 0) fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK); } -void SingleRelayServer::newRelayConnection() +void GdbRelayServer::newRelayConnection() { QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); @@ -312,13 +332,13 @@ void SingleRelayServer::newRelayConnection() return; } if (clientSocket) { - Relayer *newConnection = new Relayer(this, clientSocket); + Relayer *newConnection = new ServiceConnectionRelayer(this, clientSocket, m_serviceConn); m_connections.append(newConnection); newConnection->startRelay(m_serverFileDescriptor); } } -GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, +QmlRelayServer::QmlRelayServer(IosTool *parent, int remotePort, Ios::DeviceSession *deviceSession) : RelayServer(parent), m_remotePort(remotePort), @@ -328,7 +348,7 @@ GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, } -void GenericRelayServer::newRelayConnection() +void QmlRelayServer::newRelayConnection() { QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections() ? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection(); @@ -339,4 +359,42 @@ void GenericRelayServer::newRelayConnection() newConnection->tryRemoteConnect(); } } + +ServiceConnectionRelayer::ServiceConnectionRelayer(RelayServer *parent, QTcpSocket *clientSocket, + ServiceConnRef conn) + : Relayer(parent, clientSocket), + m_serviceConn(conn) +{ + +} + +int ServiceConnectionRelayer::readData(int socketFd, void *buf, size_t size) +{ + Q_UNUSED(socketFd) + if (!buf || !m_serviceConn) + return 0; + MobileDeviceLib &mlib = MobileDeviceLib::instance(); + return mlib.serviceConnectionReceive(m_serviceConn, buf, size); +} + +int ServiceConnectionRelayer::writeData(int socketFd, const void *data, size_t size) +{ + Q_UNUSED(socketFd) + if (!data || !m_serviceConn) + return 0; + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + return mLib.serviceConnectionSend(m_serviceConn, data, size); +} + +void ServiceConnectionRelayer::closeConnection() +{ + Relayer::closeConnection(); + if (m_serviceConn) { + MobileDeviceLib &mLib = MobileDeviceLib::instance(); + mLib.serviceConnectionInvalidate(m_serviceConn); + m_serviceConn = nullptr; + } + +} + } diff --git a/src/tools/iostool/relayserver.h b/src/tools/iostool/relayserver.h index d41932f47d2..0b01b7271e1 100644 --- a/src/tools/iostool/relayserver.h +++ b/src/tools/iostool/relayserver.h @@ -38,7 +38,7 @@ namespace Ios { class DeviceSession; class IosTool; class RelayServer; -class GenericRelayServer; +class QmlRelayServer; class Relayer: public QObject { @@ -55,11 +55,29 @@ public: void handleClientHasError(QAbstractSocket::SocketError error); protected: + virtual int readData(int socketFd, void* buf, size_t size); + virtual int writeData(int socketFd, const void *data, size_t size); + virtual void closeConnection(); + IosTool *iosTool() const; RelayServer *server() const; ServiceSocket m_serverFileDescriptor; - QTcpSocket *m_clientSocket; - QSocketNotifier *m_serverNotifier; + QTcpSocket *m_clientSocket = nullptr; + QSocketNotifier *m_serverNotifier = nullptr; +}; + +class ServiceConnectionRelayer : public Relayer +{ +public: + ServiceConnectionRelayer(RelayServer *parent, QTcpSocket *clientSocket, ServiceConnRef conn); + +protected: + int readData(int socketFd, void* buf, size_t size) override; + int writeData(int socketFd, const void *data, size_t size) override; + void closeConnection() override; + +private: + ServiceConnRef m_serviceConn; }; class RemotePortRelayer: public Relayer @@ -69,11 +87,11 @@ class RemotePortRelayer: public Relayer public: static const int reconnectMsecDelay = 500; static const int maxReconnectAttempts = 2*60*5; // 5 min - RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket); + RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket); void tryRemoteConnect(); signals: - void didConnect(GenericRelayServer *serv); + void didConnect(QmlRelayServer *serv); private: QTimer m_remoteConnectTimer; @@ -103,27 +121,28 @@ protected: QList m_connections; }; -class SingleRelayServer: public RelayServer +class GdbRelayServer: public RelayServer { Q_OBJECT public: - SingleRelayServer(IosTool *parent, int serverFileDescriptor); + GdbRelayServer(IosTool *parent, int serverFileDescriptor, ServiceConnRef conn); protected: void newRelayConnection() override; private: - int m_serverFileDescriptor; + int m_serverFileDescriptor = -1; + ServiceConnRef m_serviceConn = nullptr; }; -class GenericRelayServer: public RelayServer +class QmlRelayServer: public RelayServer { Q_OBJECT public: - GenericRelayServer(IosTool *parent, int remotePort, - Ios::DeviceSession *deviceSession); + QmlRelayServer(IosTool *parent, int remotePort, + Ios::DeviceSession *deviceSession); protected: void newRelayConnection() override;