X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fclient%2Fcoreconnection.cpp;h=7112b85468e5312dd7163a0a7d4c8e5699206c55;hp=6b498157255465299bc394dff902050cf1e6f453;hb=5d99995ceee2fb9a5291d470e36319319b345276;hpb=5b686746c880e5cda6d5de3e08180ea4332ff222 diff --git a/src/client/coreconnection.cpp b/src/client/coreconnection.cpp index 6b498157..7112b854 100644 --- a/src/client/coreconnection.cpp +++ b/src/client/coreconnection.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2012 by the Quassel Project * + * Copyright (C) 2005-2013 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -28,23 +28,25 @@ #include "clientsettings.h" #include "coreaccountmodel.h" #include "identity.h" +#include "internalpeer.h" #include "network.h" #include "networkmodel.h" #include "quassel.h" #include "signalproxy.h" #include "util.h" +#include "protocols/legacy/legacypeer.h" + CoreConnection::CoreConnection(CoreAccountModel *model, QObject *parent) : QObject(parent), _model(model), - _blockSize(0), _state(Disconnected), _wantReconnect(false), + _wasReconnect(false), _progressMinimum(0), _progressMaximum(-1), _progressValue(-1), - _wasReconnect(false), - _requestedDisconnect(false) + _resetting(false) { qRegisterMetaType("CoreConnection::ConnectionState"); } @@ -53,7 +55,6 @@ CoreConnection::CoreConnection(CoreAccountModel *model, QObject *parent) void CoreConnection::init() { Client::signalProxy()->setHeartBeatInterval(30); - connect(Client::signalProxy(), SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); connect(Client::signalProxy(), SIGNAL(lagUpdated(int)), SIGNAL(lagUpdated(int))); _reconnectTimer.setSingleShot(true); @@ -120,7 +121,7 @@ void CoreConnection::updateProgress(int value, int max) void CoreConnection::reconnectTimeout() { - if (!_socket) { + if (!_peer) { CoreConnectionSettings s; if (_wantReconnect && s.autoReconnect()) { #ifdef HAVE_KDE @@ -198,12 +199,7 @@ void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status) bool CoreConnection::isEncrypted() const { -#ifndef HAVE_SSL - return false; -#else - QSslSocket *sock = qobject_cast(_socket); - return isConnected() && sock && sock->isEncrypted(); -#endif + return _peer && _peer->isSecure(); } @@ -213,7 +209,7 @@ bool CoreConnection::isLocalConnection() const return false; if (currentAccount().isInternal()) return true; - if (_socket->peerAddress().isInSubnet(QHostAddress::LocalHost, 0x00ffffff)) + if (_peer->isLocal()) return true; return false; @@ -285,110 +281,120 @@ void CoreConnection::setState(ConnectionState state) void CoreConnection::coreSocketError(QAbstractSocket::SocketError) { - qDebug() << "coreSocketError" << _socket << _socket->errorString(); disconnectFromCore(_socket->errorString(), true); } void CoreConnection::coreSocketDisconnected() { - // qDebug() << Q_FUNC_INFO; - _wasReconnect = !_requestedDisconnect; - resetConnection(true); + _wasReconnect = false; + resetConnection(_wantReconnect); // FIXME handle disconnects gracefully } -void CoreConnection::coreHasData() +// note: this still expects the legacy protocol +// note²: after cleaning this up, we can probably get rid of _socket altogether +void CoreConnection::coreHasData(const QVariant &item) { - QVariant item; - while (SignalProxy::readDataFromDevice(_socket, _blockSize, item)) { - QVariantMap msg = item.toMap(); - if (!msg.contains("MsgType")) { - // This core is way too old and does not even speak our init protocol... - emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); - disconnectFromCore(QString(), false); - return; - } - if (msg["MsgType"] == "ClientInitAck") { - clientInitAck(msg); - } - else if (msg["MsgType"] == "ClientInitReject") { - emit connectionErrorPopup(msg["Error"].toString()); - disconnectFromCore(QString(), false); - return; - } - else if (msg["MsgType"] == "CoreSetupAck") { - emit coreSetupSuccess(); - } - else if (msg["MsgType"] == "CoreSetupReject") { - emit coreSetupFailed(msg["Error"].toString()); - } - else if (msg["MsgType"] == "ClientLoginReject") { - loginFailed(msg["Error"].toString()); - } - else if (msg["MsgType"] == "ClientLoginAck") { - loginSuccess(); - } - else if (msg["MsgType"] == "SessionInit") { - // that's it, let's hand over to the signal proxy - // if the socket is an orphan, the signalProxy adopts it. - // -> we don't need to care about it anymore - _socket->setParent(0); - Client::signalProxy()->addPeer(_socket); - - sessionStateReceived(msg["SessionState"].toMap()); - break; // this is definitively the last message we process here! - } - else { - disconnectFromCore(tr("Invalid data received from core"), false); - return; - } + QVariantMap msg = item.toMap(); + if (!msg.contains("MsgType")) { + // This core is way too old and does not even speak our init protocol... + emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); + disconnectFromCore(QString(), false); + return; + } + if (msg["MsgType"] == "ClientInitAck") { + clientInitAck(msg); + } + else if (msg["MsgType"] == "ClientInitReject") { + emit connectionErrorPopup(msg["Error"].toString()); + disconnectFromCore(QString(), false); + return; + } + else if (msg["MsgType"] == "CoreSetupAck") { + emit coreSetupSuccess(); } - if (_blockSize > 0) { - updateProgress(_socket->bytesAvailable(), _blockSize); + else if (msg["MsgType"] == "CoreSetupReject") { + emit coreSetupFailed(msg["Error"].toString()); + } + else if (msg["MsgType"] == "ClientLoginReject") { + loginFailed(msg["Error"].toString()); + } + else if (msg["MsgType"] == "ClientLoginAck") { + loginSuccess(); + } + else if (msg["MsgType"] == "SessionInit") { + // that's it, let's hand over to the signal proxy + // if the connection is an orphan, the signalProxy adopts it. + // -> we don't need to care about it anymore + + disconnect(_peer, 0, this, 0); + + _peer->setParent(0); + Client::signalProxy()->addPeer(_peer); + + sessionStateReceived(msg["SessionState"].toMap()); + } + else { + disconnectFromCore(tr("Invalid data received from core"), false); + return; } } void CoreConnection::disconnectFromCore() { - _requestedDisconnect = true; - disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect + if (_socket) + disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect } void CoreConnection::disconnectFromCore(const QString &errorString, bool wantReconnect) { - if (!wantReconnect) + if (wantReconnect) + _reconnectTimer.start(); + else _reconnectTimer.stop(); - _wasReconnect = wantReconnect; // store if disconnect was requested + _wantReconnect = wantReconnect; // store if disconnect was requested + _wasReconnect = false; + + if (_socket) + _socket->close(); if (errorString.isEmpty()) emit connectionError(tr("Disconnected")); else emit connectionError(errorString); - - Client::signalProxy()->removeAllPeers(); - resetConnection(wantReconnect); } void CoreConnection::resetConnection(bool wantReconnect) { + if (_resetting) + return; + _resetting = true; + _wantReconnect = wantReconnect; - if (_socket) { + if (_peer) { + disconnect(_socket, 0, this, 0); + disconnect(_peer, 0, this, 0); + _peer->close(); + + if (_peer->parent() == this) + _peer->deleteLater(); // if it's not us, it belongs to the sigproxy which will delete it + _socket = 0; // socket is owned and will be deleted by RemoteConnection + _peer = 0; + } + else if (_socket) { disconnect(_socket, 0, this, 0); _socket->deleteLater(); _socket = 0; } - _requestedDisconnect = false; - _blockSize = 0; _coreMsgBuffer.clear(); - _netsToSync.clear(); _numNetsToSync = 0; @@ -404,13 +410,17 @@ void CoreConnection::resetConnection(bool wantReconnect) if (wantReconnect && s.autoReconnect()) { _reconnectTimer.start(); } + + _resetting = false; } void CoreConnection::reconnectToCore() { - if (currentAccount().isValid()) + if (currentAccount().isValid()) { + _wasReconnect = true; connectToCore(currentAccount().accountId()); + } } @@ -464,7 +474,11 @@ void CoreConnection::connectToCurrentAccount() return; } emit startInternalCore(); - emit connectToInternalCore(Client::instance()->signalProxy()); + + InternalPeer *peer = new InternalPeer(); + Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership + emit connectToInternalCore(peer); + return; } @@ -472,7 +486,7 @@ void CoreConnection::connectToCurrentAccount() Q_ASSERT(!_socket); #ifdef HAVE_SSL - QSslSocket *sock = new QSslSocket(Client::instance()); + QSslSocket *sock = new QSslSocket(this); // make sure the warning is shown if we happen to connect without SSL support later s.setAccountValue("ShowNoClientSslWarning", true); #else @@ -487,7 +501,7 @@ void CoreConnection::connectToCurrentAccount() s.setAccountValue("ShowNoClientSslWarning", false); } } - QTcpSocket *sock = new QTcpSocket(Client::instance()); + QTcpSocket *sock = new QTcpSocket(this); #endif #ifndef QT_NO_NETWORKPROXY @@ -498,7 +512,6 @@ void CoreConnection::connectToCurrentAccount() #endif _socket = sock; - connect(sock, SIGNAL(readyRead()), SLOT(coreHasData())); connect(sock, SIGNAL(connected()), SLOT(coreSocketConnected())); connect(sock, SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(coreSocketError(QAbstractSocket::SocketError))); @@ -511,6 +524,12 @@ void CoreConnection::connectToCurrentAccount() void CoreConnection::coreSocketConnected() { + // Create the connection which will handle the incoming data + Q_ASSERT(!_peer); + _peer = new LegacyPeer(_socket, this); + connect(_peer, SIGNAL(dataReceived(QVariant)), SLOT(coreHasData(QVariant))); + connect(_peer, SIGNAL(transferProgress(int,int)), SLOT(updateProgress(int,int))); + // Phase One: Send client info and wait for core info emit connectionMsg(tr("Synchronizing to core...")); @@ -527,7 +546,7 @@ void CoreConnection::coreSocketConnected() clientInit["UseCompression"] = false; #endif - SignalProxy::writeDataToDevice(_socket, clientInit); + qobject_cast(_peer)->writeSocketData(clientInit); } @@ -676,7 +695,7 @@ void CoreConnection::loginToCore(const QString &prevError) clientLogin["MsgType"] = "ClientLogin"; clientLogin["User"] = currentAccount().user(); clientLogin["Password"] = currentAccount().password(); - SignalProxy::writeDataToDevice(_socket, clientLogin); + qobject_cast(_peer)->writeSocketData(clientLogin); } @@ -706,10 +725,6 @@ void CoreConnection::sessionStateReceived(const QVariantMap &state) { updateProgress(100, 100); - // rest of communication happens through SignalProxy... - disconnect(_socket, SIGNAL(readyRead()), this, 0); - disconnect(_socket, SIGNAL(connected()), this, 0); - syncToCore(state); } @@ -794,5 +809,5 @@ void CoreConnection::doCoreSetup(const QVariant &setupData) QVariantMap setup; setup["MsgType"] = "CoreSetupData"; setup["SetupData"] = setupData; - SignalProxy::writeDataToDevice(_socket, setup); + qobject_cast(_peer)->writeSocketData(setup); }