1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

GCS/IPConnection: fixed a problem that was causing IP telemetry not to work on Windows, moved socket creation to the UAVTalk thread. Segfaults if you don't press "Disconnect" before closing the window!

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1342 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
cwabbott 2010-08-20 16:23:14 +00:00 committed by cwabbott
parent 9dcae643c1
commit a24daa7c6d
4 changed files with 130 additions and 44 deletions

View File

@ -5,7 +5,8 @@ include(ipconnection_dependencies.pri)
HEADERS += ipconnectionplugin.h \ HEADERS += ipconnectionplugin.h \
ipconnection_global.h \ ipconnection_global.h \
ipconnectionconfiguration.h \ ipconnectionconfiguration.h \
ipconnectionoptionspage.h ipconnectionoptionspage.h \
ipconnection_internal.h
SOURCES += ipconnectionplugin.cpp \ SOURCES += ipconnectionplugin.cpp \
ipconnectionconfiguration.cpp \ ipconnectionconfiguration.cpp \
ipconnectionoptionspage.cpp ipconnectionoptionspage.cpp

View File

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

View File

@ -32,6 +32,7 @@
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include "ipconnection_internal.h"
#include <QtCore/QtPlugin> #include <QtCore/QtPlugin>
#include <QtGui/QMainWindow> #include <QtGui/QMainWindow>
@ -39,9 +40,77 @@
#include <QtNetwork/QAbstractSocket> #include <QtNetwork/QAbstractSocket>
#include <QtNetwork/QTcpSocket> #include <QtNetwork/QTcpSocket>
#include <QtNetwork/QUdpSocket> #include <QtNetwork/QUdpSocket>
#include <QWaitCondition>
#include <coreplugin/threadmanager.h>
#include <QDebug> #include <QDebug>
//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() IPconnectionConnection::IPconnectionConnection()
{ {
ipSocket = NULL; ipSocket = NULL;
@ -51,6 +120,9 @@ IPconnectionConnection::IPconnectionConnection()
m_optionspage = new IPconnectionOptionsPage(m_config,this); m_optionspage = new IPconnectionOptionsPage(m_config,this);
if(!connection)
connection = new IPConnection(this);
//just signal whenever we have a device event... //just signal whenever we have a device event...
QMainWindow *mw = Core::ICore::instance()->mainWindow(); QMainWindow *mw = Core::ICore::instance()->mainWindow();
QObject::connect(mw, SIGNAL(deviceChange()), QObject::connect(mw, SIGNAL(deviceChange()),
@ -65,6 +137,11 @@ IPconnectionConnection::~IPconnectionConnection()
ipSocket->close (); ipSocket->close ();
delete(ipSocket); delete(ipSocket);
} }
if(connection)
{
delete connection;
connection = NULL;
}
} }
void IPconnectionConnection::onEnumerationChanged() void IPconnectionConnection::onEnumerationChanged()
@ -86,58 +163,38 @@ QStringList IPconnectionConnection::availableDevices()
QIODevice *IPconnectionConnection::openDevice(const QString &deviceName) QIODevice *IPconnectionConnection::openDevice(const QString &deviceName)
{ {
const int Timeout = 5 * 1000;
int state;
QString HostName; QString HostName;
int Port; int Port;
bool UseTCP;
QMessageBox msgBox; QMessageBox msgBox;
if (ipSocket){
//Andrew: close any existing socket... this should never occur
ipSocket->close ();
delete(ipSocket);
ipSocket = NULL;
}
if (m_config->UseTCP()) {
ipSocket = new QTcpSocket(this);
} else {
ipSocket = new QUdpSocket(this);
}
//get the configuration info //get the configuration info
HostName = m_config->HostName(); HostName = m_config->HostName();
Port = m_config->Port(); Port = m_config->Port();
UseTCP = m_config->UseTCP();
//do sanity check on hostname and port... if (ipSocket){
if((HostName.length()==0)||(Port<1)){ //Andrew: close any existing socket... this should never occur
msgBox.setText((const QString )"Please configure Host and Port options before opening the connection"); emit CloseSocket(ipSocket);
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; 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; return ipSocket;
} }
void IPconnectionConnection::closeDevice(const QString &deviceName) void IPconnectionConnection::closeDevice(const QString &deviceName)
{ {
if (ipSocket){ if (ipSocket){
ipSocket->close (); emit CloseSocket(ipSocket);
delete(ipSocket);
ipSocket = NULL; ipSocket = NULL;
} }
} }

View File

@ -68,6 +68,11 @@ public:
protected slots: protected slots:
void onEnumerationChanged(); void onEnumerationChanged();
signals: //For the benefit of IPConnection
void CreateSocket(QString HostName, int Port, bool UseTCP);
void CloseSocket(QAbstractSocket *socket);
private: private:
QAbstractSocket *ipSocket; QAbstractSocket *ipSocket;
IPconnectionConfiguration *m_config; IPconnectionConfiguration *m_config;