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 <eike.ziller@qt.io>
This commit is contained in:
Vikas Pachdha
2021-03-10 14:25:17 +01:00
parent b152a7287c
commit 35d7bc49f0
4 changed files with 115 additions and 38 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -26,6 +26,7 @@
#include "relayserver.h"
#include "iostool.h"
#include "mobiledevicelib.h"
#ifdef Q_OS_UNIX
#include <unistd.h>
@@ -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<RelayServer *>(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<GenericRelayServer *>(server());
QmlRelayServer *grServer = qobject_cast<QmlRelayServer *>(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;
}
}
}

View File

@@ -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,26 +121,27 @@ protected:
QList<Relayer *> 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,
QmlRelayServer(IosTool *parent, int remotePort,
Ios::DeviceSession *deviceSession);
protected: