forked from qt-creator/qt-creator
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:
@@ -259,12 +259,12 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId,
|
|||||||
if (deviceSession) {
|
if (deviceSession) {
|
||||||
int qmlPort = deviceSession->qmljsDebugPort();
|
int qmlPort = deviceSession->qmljsDebugPort();
|
||||||
if (qmlPort) {
|
if (qmlPort) {
|
||||||
qmlServer = new GenericRelayServer(this, qmlPort, deviceSession);
|
qmlServer = new QmlRelayServer(this, qmlPort, deviceSession);
|
||||||
qmlServer->startServer();
|
qmlServer->startServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug) {
|
if (debug) {
|
||||||
gdbServer = new SingleRelayServer(this, gdbFd);
|
gdbServer = new GdbRelayServer(this, gdbFd, conn);
|
||||||
if (!gdbServer->startServer()) {
|
if (!gdbServer->startServer()) {
|
||||||
doExit(-4);
|
doExit(-4);
|
||||||
return;
|
return;
|
||||||
|
@@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
namespace Ios {
|
namespace Ios {
|
||||||
class GdbRunner;
|
class GdbRunner;
|
||||||
class SingleRelayServer;
|
class GdbRelayServer;
|
||||||
class GenericRelayServer;
|
class QmlRelayServer;
|
||||||
|
|
||||||
class IosTool: public QObject
|
class IosTool: public QObject
|
||||||
{
|
{
|
||||||
@@ -79,8 +79,8 @@ private:
|
|||||||
QFile outFile;
|
QFile outFile;
|
||||||
QString m_qmlPort;
|
QString m_qmlPort;
|
||||||
QXmlStreamWriter out;
|
QXmlStreamWriter out;
|
||||||
SingleRelayServer *gdbServer;
|
GdbRelayServer *gdbServer;
|
||||||
GenericRelayServer *qmlServer;
|
QmlRelayServer *qmlServer;
|
||||||
GdbRunner *gdbRunner;
|
GdbRunner *gdbRunner;
|
||||||
bool m_echoRelays = false;
|
bool m_echoRelays = false;
|
||||||
friend class GdbRunner;
|
friend class GdbRunner;
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "relayserver.h"
|
#include "relayserver.h"
|
||||||
|
|
||||||
#include "iostool.h"
|
#include "iostool.h"
|
||||||
|
#include "mobiledevicelib.h"
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -45,15 +46,7 @@ Relayer::Relayer(RelayServer *parent, QTcpSocket *clientSocket) :
|
|||||||
|
|
||||||
Relayer::~Relayer()
|
Relayer::~Relayer()
|
||||||
{
|
{
|
||||||
if (m_serverFileDescriptor > 0) {
|
closeConnection();
|
||||||
::close(m_serverFileDescriptor);
|
|
||||||
m_serverFileDescriptor = -1;
|
|
||||||
if (m_serverNotifier)
|
|
||||||
delete m_serverNotifier;
|
|
||||||
}
|
|
||||||
if (m_clientSocket->isOpen())
|
|
||||||
m_clientSocket->close();
|
|
||||||
delete m_clientSocket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Relayer::setClientSocket(QTcpSocket *clientSocket)
|
void Relayer::setClientSocket(QTcpSocket *clientSocket)
|
||||||
@@ -93,7 +86,7 @@ void Relayer::handleSocketHasData(int socket)
|
|||||||
m_serverNotifier->setEnabled(false);
|
m_serverNotifier->setEnabled(false);
|
||||||
char buf[255];
|
char buf[255];
|
||||||
while (true) {
|
while (true) {
|
||||||
qptrdiff rRead = read(socket, &buf, sizeof(buf)-1);
|
qptrdiff rRead = readData(socket, &buf, sizeof(buf)-1);
|
||||||
if (rRead == -1) {
|
if (rRead == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -158,7 +151,7 @@ void Relayer::handleClientHasData()
|
|||||||
.arg((quintptr)(void *)this), buf, rRead);
|
.arg((quintptr)(void *)this), buf, rRead);
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
qptrdiff written = write(m_serverFileDescriptor, buf + pos, rRead);
|
qptrdiff written = writeData(m_serverFileDescriptor, buf + pos, rRead);
|
||||||
if (written == -1) {
|
if (written == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -193,6 +186,32 @@ void Relayer::handleClientHasError(QAbstractSocket::SocketError error)
|
|||||||
server()->removeRelayConnection(this);
|
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
|
IosTool *Relayer::iosTool() const
|
||||||
{
|
{
|
||||||
return (server() ? server()->iosTool() : 0);
|
return (server() ? server()->iosTool() : 0);
|
||||||
@@ -203,7 +222,7 @@ RelayServer *Relayer::server() const
|
|||||||
return qobject_cast<RelayServer *>(parent());
|
return qobject_cast<RelayServer *>(parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
RemotePortRelayer::RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket) :
|
RemotePortRelayer::RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket) :
|
||||||
Relayer(parent, clientSocket)
|
Relayer(parent, clientSocket)
|
||||||
{
|
{
|
||||||
m_remoteConnectTimer.setSingleShot(true);
|
m_remoteConnectTimer.setSingleShot(true);
|
||||||
@@ -217,7 +236,7 @@ void RemotePortRelayer::tryRemoteConnect()
|
|||||||
if (m_serverFileDescriptor > 0)
|
if (m_serverFileDescriptor > 0)
|
||||||
return;
|
return;
|
||||||
ServiceSocket ss;
|
ServiceSocket ss;
|
||||||
GenericRelayServer *grServer = qobject_cast<GenericRelayServer *>(server());
|
QmlRelayServer *grServer = qobject_cast<QmlRelayServer *>(server());
|
||||||
if (!grServer)
|
if (!grServer)
|
||||||
return;
|
return;
|
||||||
if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) {
|
if (grServer->m_deviceSession->connectToPort(grServer->m_remotePort, &ss)) {
|
||||||
@@ -294,16 +313,17 @@ void RelayServer::removeRelayConnection(Relayer *relayer)
|
|||||||
relayer->deleteLater();
|
relayer->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleRelayServer::SingleRelayServer(IosTool *parent,
|
GdbRelayServer::GdbRelayServer(IosTool *parent,
|
||||||
int serverFileDescriptor) :
|
int serverFileDescriptor, ServiceConnRef conn) :
|
||||||
RelayServer(parent)
|
RelayServer(parent),
|
||||||
|
m_serverFileDescriptor(serverFileDescriptor),
|
||||||
|
m_serviceConn(conn)
|
||||||
{
|
{
|
||||||
m_serverFileDescriptor = serverFileDescriptor;
|
|
||||||
if (m_serverFileDescriptor > 0)
|
if (m_serverFileDescriptor > 0)
|
||||||
fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK);
|
fcntl(m_serverFileDescriptor, F_SETFL, fcntl(m_serverFileDescriptor, F_GETFL, 0) | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleRelayServer::newRelayConnection()
|
void GdbRelayServer::newRelayConnection()
|
||||||
{
|
{
|
||||||
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
|
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
|
||||||
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
|
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
|
||||||
@@ -312,13 +332,13 @@ void SingleRelayServer::newRelayConnection()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (clientSocket) {
|
if (clientSocket) {
|
||||||
Relayer *newConnection = new Relayer(this, clientSocket);
|
Relayer *newConnection = new ServiceConnectionRelayer(this, clientSocket, m_serviceConn);
|
||||||
m_connections.append(newConnection);
|
m_connections.append(newConnection);
|
||||||
newConnection->startRelay(m_serverFileDescriptor);
|
newConnection->startRelay(m_serverFileDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort,
|
QmlRelayServer::QmlRelayServer(IosTool *parent, int remotePort,
|
||||||
Ios::DeviceSession *deviceSession) :
|
Ios::DeviceSession *deviceSession) :
|
||||||
RelayServer(parent),
|
RelayServer(parent),
|
||||||
m_remotePort(remotePort),
|
m_remotePort(remotePort),
|
||||||
@@ -328,7 +348,7 @@ GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GenericRelayServer::newRelayConnection()
|
void QmlRelayServer::newRelayConnection()
|
||||||
{
|
{
|
||||||
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
|
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
|
||||||
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
|
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
|
||||||
@@ -339,4 +359,42 @@ void GenericRelayServer::newRelayConnection()
|
|||||||
newConnection->tryRemoteConnect();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@ namespace Ios {
|
|||||||
class DeviceSession;
|
class DeviceSession;
|
||||||
class IosTool;
|
class IosTool;
|
||||||
class RelayServer;
|
class RelayServer;
|
||||||
class GenericRelayServer;
|
class QmlRelayServer;
|
||||||
|
|
||||||
class Relayer: public QObject
|
class Relayer: public QObject
|
||||||
{
|
{
|
||||||
@@ -55,11 +55,29 @@ public:
|
|||||||
void handleClientHasError(QAbstractSocket::SocketError error);
|
void handleClientHasError(QAbstractSocket::SocketError error);
|
||||||
|
|
||||||
protected:
|
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;
|
IosTool *iosTool() const;
|
||||||
RelayServer *server() const;
|
RelayServer *server() const;
|
||||||
ServiceSocket m_serverFileDescriptor;
|
ServiceSocket m_serverFileDescriptor;
|
||||||
QTcpSocket *m_clientSocket;
|
QTcpSocket *m_clientSocket = nullptr;
|
||||||
QSocketNotifier *m_serverNotifier;
|
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
|
class RemotePortRelayer: public Relayer
|
||||||
@@ -69,11 +87,11 @@ class RemotePortRelayer: public Relayer
|
|||||||
public:
|
public:
|
||||||
static const int reconnectMsecDelay = 500;
|
static const int reconnectMsecDelay = 500;
|
||||||
static const int maxReconnectAttempts = 2*60*5; // 5 min
|
static const int maxReconnectAttempts = 2*60*5; // 5 min
|
||||||
RemotePortRelayer(GenericRelayServer *parent, QTcpSocket *clientSocket);
|
RemotePortRelayer(QmlRelayServer *parent, QTcpSocket *clientSocket);
|
||||||
void tryRemoteConnect();
|
void tryRemoteConnect();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void didConnect(GenericRelayServer *serv);
|
void didConnect(QmlRelayServer *serv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer m_remoteConnectTimer;
|
QTimer m_remoteConnectTimer;
|
||||||
@@ -103,27 +121,28 @@ protected:
|
|||||||
QList<Relayer *> m_connections;
|
QList<Relayer *> m_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleRelayServer: public RelayServer
|
class GdbRelayServer: public RelayServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SingleRelayServer(IosTool *parent, int serverFileDescriptor);
|
GdbRelayServer(IosTool *parent, int serverFileDescriptor, ServiceConnRef conn);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void newRelayConnection() override;
|
void newRelayConnection() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_serverFileDescriptor;
|
int m_serverFileDescriptor = -1;
|
||||||
|
ServiceConnRef m_serviceConn = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenericRelayServer: public RelayServer
|
class QmlRelayServer: public RelayServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GenericRelayServer(IosTool *parent, int remotePort,
|
QmlRelayServer(IosTool *parent, int remotePort,
|
||||||
Ios::DeviceSession *deviceSession);
|
Ios::DeviceSession *deviceSession);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void newRelayConnection() override;
|
void newRelayConnection() override;
|
||||||
|
Reference in New Issue
Block a user