diff --git a/ground/src/plugins/ipconnection/ipconnection.pro b/ground/src/plugins/ipconnection/ipconnection.pro index 6447529b8..985c8f442 100644 --- a/ground/src/plugins/ipconnection/ipconnection.pro +++ b/ground/src/plugins/ipconnection/ipconnection.pro @@ -5,7 +5,8 @@ include(ipconnection_dependencies.pri) HEADERS += ipconnectionplugin.h \ ipconnection_global.h \ ipconnectionconfiguration.h \ - ipconnectionoptionspage.h + ipconnectionoptionspage.h \ + ipconnection_internal.h SOURCES += ipconnectionplugin.cpp \ ipconnectionconfiguration.cpp \ ipconnectionoptionspage.cpp diff --git a/ground/src/plugins/ipconnection/ipconnection_internal.h b/ground/src/plugins/ipconnection/ipconnection_internal.h new file mode 100644 index 000000000..35207516b --- /dev/null +++ b/ground/src/plugins/ipconnection/ipconnection_internal.h @@ -0,0 +1,23 @@ +#ifndef IPCONNECTION_INTERNAL_H +#define IPCONNECTION_INTERNAL_H + +#include "ipconnectionplugin.h" + +//Simple class for creating & destroying a socket in the real-time thread +//Needed because sockets need to be created in the same thread that they're used +class IPConnection : public QObject +{ + Q_OBJECT + +public: + + IPConnection(IPconnectionConnection *connection); + //virtual ~IPConnection(); + +public slots: + + void onOpenDevice(QString HostName, int Port, bool UseTCP); + void onCloseDevice(QAbstractSocket *ipSocket); +}; + +#endif // IPCONNECTION_INTERNAL_H diff --git a/ground/src/plugins/ipconnection/ipconnectionplugin.cpp b/ground/src/plugins/ipconnection/ipconnectionplugin.cpp index 8800507fe..3995f52f3 100644 --- a/ground/src/plugins/ipconnection/ipconnectionplugin.cpp +++ b/ground/src/plugins/ipconnection/ipconnectionplugin.cpp @@ -32,6 +32,7 @@ #include #include +#include "ipconnection_internal.h" #include #include @@ -39,9 +40,77 @@ #include #include #include +#include +#include #include +//Communication between IPconnectionConnection::OpenDevice() and IPConnection::onOpenDevice() +QString errorMsg; +QWaitCondition openDeviceWait; +QReadWriteLock dummyLock; +QAbstractSocket *ret; + +IPConnection::IPConnection(IPconnectionConnection *connection) : QObject() +{ + moveToThread(Core::ICore::instance()->threadManager()->getRealTimeThread()); + + QObject::connect(connection, SIGNAL(CreateSocket(QString,int,bool)), + this, SLOT(onOpenDevice(QString,int,bool))); + QObject::connect(connection, SIGNAL(CloseSocket(QAbstractSocket*)), + this, SLOT(onCloseDevice(QAbstractSocket*))); +} + +/*IPConnection::~IPConnection() +{ + +}*/ + +void IPConnection::onOpenDevice(QString HostName, int Port, bool UseTCP) +{ + QAbstractSocket *ipSocket; + const int Timeout = 5 * 1000; + int state; + + if (UseTCP) { + ipSocket = new QTcpSocket(this); + } else { + ipSocket = new QUdpSocket(this); + } + + //do sanity check on hostname and port... + if((HostName.length()==0)||(Port<1)){ + errorMsg = "Please configure Host and Port options before opening the connection"; + + } + else { + //try to connect... + ipSocket->connectToHost(HostName, Port); + + //in blocking mode so we wait for the connection to succeed + if (ipSocket->waitForConnected(Timeout)) { + ret = ipSocket; + openDeviceWait.wakeAll(); + return; + } + //tell user something went wrong + errorMsg = ipSocket->errorString (); + } + /* BUGBUG TODO - returning null here leads to segfault because some caller still calls disconnect without checking our return value properly + * someone needs to debug this, I got lost in the calling chain.*/ + ret = NULL; + openDeviceWait.wakeAll(); +} + +void IPConnection::onCloseDevice(QAbstractSocket *ipSocket) +{ + ipSocket->close (); + delete(ipSocket); +} + + +IPConnection * connection = 0; + IPconnectionConnection::IPconnectionConnection() { ipSocket = NULL; @@ -51,6 +120,9 @@ IPconnectionConnection::IPconnectionConnection() m_optionspage = new IPconnectionOptionsPage(m_config,this); + if(!connection) + connection = new IPConnection(this); + //just signal whenever we have a device event... QMainWindow *mw = Core::ICore::instance()->mainWindow(); QObject::connect(mw, SIGNAL(deviceChange()), @@ -65,6 +137,11 @@ IPconnectionConnection::~IPconnectionConnection() ipSocket->close (); delete(ipSocket); } + if(connection) + { + delete connection; + connection = NULL; + } } void IPconnectionConnection::onEnumerationChanged() @@ -86,58 +163,38 @@ QStringList IPconnectionConnection::availableDevices() QIODevice *IPconnectionConnection::openDevice(const QString &deviceName) { - const int Timeout = 5 * 1000; - int state; - QString HostName; - int Port; - QMessageBox msgBox; + QString HostName; + int Port; + bool UseTCP; + QMessageBox msgBox; - if (ipSocket){ - //Andrew: close any existing socket... this should never occur - ipSocket->close (); - delete(ipSocket); - ipSocket = NULL; - } + //get the configuration info + HostName = m_config->HostName(); + Port = m_config->Port(); + UseTCP = m_config->UseTCP(); - if (m_config->UseTCP()) { - ipSocket = new QTcpSocket(this); - } else { - ipSocket = new QUdpSocket(this); - } + if (ipSocket){ + //Andrew: close any existing socket... this should never occur + emit CloseSocket(ipSocket); + ipSocket = NULL; + } - //get the configuration info - HostName = m_config->HostName(); - Port = m_config->Port(); - - //do sanity check on hostname and port... - if((HostName.length()==0)||(Port<1)){ - msgBox.setText((const QString )"Please configure Host and Port options before opening the connection"); - msgBox.exec(); - - } - else { - //try to connect... - ipSocket->connectToHost((const QString )HostName, Port); - - //in blocking mode so we wait for the connection to succeed - if (ipSocket->waitForConnected(Timeout)) { - return ipSocket; - } - //tell user something went wrong - msgBox.setText((const QString )ipSocket->errorString ()); - msgBox.exec(); - } -/* BUGBUG TODO - returning null here leads to segfault because some caller still calls disconnect without checking our return value properly - * someone needs to debug this, I got lost in the calling chain.*/ - ipSocket = NULL; + dummyLock.lockForRead(); + emit CreateSocket(HostName, Port, UseTCP); + openDeviceWait.wait(&dummyLock); + ipSocket = ret; + if(ipSocket == NULL) + { + msgBox.setText((const QString )errorMsg); + msgBox.exec(); + } return ipSocket; } void IPconnectionConnection::closeDevice(const QString &deviceName) { if (ipSocket){ - ipSocket->close (); - delete(ipSocket); + emit CloseSocket(ipSocket); ipSocket = NULL; } } diff --git a/ground/src/plugins/ipconnection/ipconnectionplugin.h b/ground/src/plugins/ipconnection/ipconnectionplugin.h index ac884b14e..03a34a102 100644 --- a/ground/src/plugins/ipconnection/ipconnectionplugin.h +++ b/ground/src/plugins/ipconnection/ipconnectionplugin.h @@ -68,6 +68,11 @@ public: protected slots: void onEnumerationChanged(); + +signals: //For the benefit of IPConnection + void CreateSocket(QString HostName, int Port, bool UseTCP); + void CloseSocket(QAbstractSocket *socket); + private: QAbstractSocket *ipSocket; IPconnectionConfiguration *m_config;