X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fclient%2Fcoreconnection.cpp;h=3d769cc31ef4f9990264ce0840b25234f33dba40;hb=67a80c804797ba432378ad6b81fc82b1aa0d9a1d;hp=f290756dd089cb92ce7b17e132c5cf9a126f43b2;hpb=8f7204aa8928f769a9cd74b3bfca4a4c5982c393;p=quassel.git diff --git a/src/client/coreconnection.cpp b/src/client/coreconnection.cpp index f290756d..3d769cc3 100644 --- a/src/client/coreconnection.cpp +++ b/src/client/coreconnection.cpp @@ -99,10 +99,20 @@ void CoreConnection::resetConnection() { _netsToSync.clear(); _numNetsToSync = 0; - _state = Disconnected; setProgressMaximum(-1); // disable + setState(Disconnected); emit connectionMsg(tr("Disconnected from core.")); + emit encrypted(false); +} + +bool CoreConnection::isEncrypted() const { +#ifndef HAVE_SSL + return false; +#else + QSslSocket *sock = qobject_cast(_socket); + return isConnected() && sock && sock->isEncrypted(); +#endif } void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState) { @@ -110,7 +120,7 @@ void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState switch(socketState) { case QAbstractSocket::UnconnectedState: - text = tr("Disconnected."); + text = tr("Disconnected"); break; case QAbstractSocket::HostLookupState: text = tr("Looking up %1...").arg(currentAccount().hostName()); @@ -119,7 +129,7 @@ void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState text = tr("Connecting to %1...").arg(currentAccount().hostName()); break; case QAbstractSocket::ConnectedState: - text = tr("Connected to %1.").arg(currentAccount().hostName()); + text = tr("Connected to %1").arg(currentAccount().hostName()); break; case QAbstractSocket::ClosingState: text = tr("Disconnecting from %1...").arg(currentAccount().hostName()); @@ -145,9 +155,6 @@ void CoreConnection::setState(QAbstractSocket::SocketState socketState) { case QAbstractSocket::ConnectingState: state = Connecting; break; - case QAbstractSocket::ConnectedState: - state = Connected; - break; default: state = Disconnected; } @@ -159,18 +166,11 @@ void CoreConnection::setState(ConnectionState state) { if(state != _state) { _state = state; emit stateChanged(state); + if(state == Disconnected) + emit disconnected(); } } -void CoreConnection::setWarningsHandler(const char *slot) { - resetWarningsHandler(); - connect(this, SIGNAL(handleIgnoreWarnings(bool)), this, slot); -} - -void CoreConnection::resetWarningsHandler() { - disconnect(this, SIGNAL(handleIgnoreWarnings(bool)), this, 0); -} - void CoreConnection::coreSocketError(QAbstractSocket::SocketError) { qDebug() << "coreSocketError" << _socket << _socket->errorString(); emit connectionError(_socket->errorString()); @@ -178,7 +178,6 @@ void CoreConnection::coreSocketError(QAbstractSocket::SocketError) { } void CoreConnection::coreSocketDisconnected() { - setState(Disconnected); emit disconnected(); resetConnection(); // FIXME handle disconnects gracefully @@ -190,14 +189,14 @@ void CoreConnection::coreHasData() { QVariantMap msg = item.toMap(); if(!msg.contains("MsgType")) { // This core is way too old and does not even speak our init protocol... - emit connectionError(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); + emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); disconnectFromCore(); return; } if(msg["MsgType"] == "ClientInitAck") { clientInitAck(msg); } else if(msg["MsgType"] == "ClientInitReject") { - emit connectionError(msg["Error"].toString()); + emit connectionErrorPopup(msg["Error"].toString()); disconnectFromCore(); return; } else if(msg["MsgType"] == "CoreSetupAck") { @@ -218,8 +217,7 @@ void CoreConnection::coreHasData() { sessionStateReceived(msg["SessionState"].toMap()); break; // this is definitively the last message we process here! } else { - emit connectionError(tr("Invalid data received from core!
Disconnecting.")); - disconnectFromCore(); + disconnectFromCore(tr("Invalid data received from core")); return; } } @@ -228,7 +226,12 @@ void CoreConnection::coreHasData() { } } -void CoreConnection::disconnectFromCore() { +void CoreConnection::disconnectFromCore(const QString &errorString) { + if(errorString.isEmpty()) + emit connectionError(tr("Disconnected")); + else + emit connectionError(errorString); + Client::signalProxy()->removeAllPeers(); resetConnection(); } @@ -244,20 +247,30 @@ bool CoreConnection::connectToCore(AccountId accId) { CoreAccountSettings s; - if(!accId.isValid()) { - // check our settings and figure out what to do - if(!s.autoConnectOnStartup()) - return false; - if(s.autoConnectToFixedAccount()) - accId = s.autoConnectAccount(); - else - accId = s.lastAccount(); - if(!accId.isValid()) + // FIXME: Don't force connection to internal core in mono client + if(Quassel::runMode() == Quassel::Monolithic) { + _account = accountModel()->account(accountModel()->internalAccount()); + Q_ASSERT(_account.isValid()); + } else { + if(!accId.isValid()) { + // check our settings and figure out what to do + if(!s.autoConnectOnStartup()) + return false; + if(s.autoConnectToFixedAccount()) + accId = s.autoConnectAccount(); + else + accId = s.lastAccount(); + if(!accId.isValid()) + return false; + } + _account = accountModel()->account(accId); + if(!_account.accountId().isValid()) { return false; - } - _account = accountModel()->account(accId); - if(!_account.accountId().isValid()) { - return false; + } + if(Quassel::runMode() != Quassel::Monolithic) { + if(_account.isInternal()) + return false; + } } s.setLastAccount(accId); @@ -268,13 +281,34 @@ bool CoreConnection::connectToCore(AccountId accId) { void CoreConnection::connectToCurrentAccount() { resetConnection(); + if(currentAccount().isInternal()) { + if(Quassel::runMode() != Quassel::Monolithic) { + qWarning() << "Cannot connect to internal core in client-only mode!"; + return; + } + emit startInternalCore(); + emit connectToInternalCore(Client::instance()->signalProxy()); + return; + } + + CoreAccountSettings s; + Q_ASSERT(!_socket); #ifdef HAVE_SSL QSslSocket *sock = new QSslSocket(Client::instance()); + // make sure the warning is shown if we happen to connect without SSL support later + s.setAccountValue("ShowNoClientSslWarning", true); #else if(_account.useSsl()) { - emit connectionError(tr("This client is built without SSL Support!
Disable the usage of SSL in the account settings.")); - return; + if(s.accountValue("ShowNoClientSslWarning", true).toBool()) { + bool accepted = false; + emit handleNoSslInClient(&accepted); + if(!accepted) { + emit connectionError(tr("Unencrypted connection canceled")); + return; + } + s.setAccountValue("ShowNoClientSslWarning", false); + } } QTcpSocket *sock = new QTcpSocket(Client::instance()); #endif @@ -321,7 +355,7 @@ void CoreConnection::clientInitAck(const QVariantMap &msg) { // Core has accepted our version info and sent its own. Let's see if we accept it as well... uint ver = msg["ProtocolVersion"].toUInt(); if(ver < Quassel::buildInfo().clientNeedsProtocol) { - emit connectionError(tr("The Quassel Core you are trying to connect to is too old!
" + emit connectionErrorPopup(tr("The Quassel Core you are trying to connect to is too old!
" "Need at least core/client protocol v%1 to connect.").arg(Quassel::buildInfo().clientNeedsProtocol)); disconnectFromCore(); return; @@ -334,28 +368,88 @@ void CoreConnection::clientInitAck(const QVariantMap &msg) { #endif _coreMsgBuffer = msg; + #ifdef HAVE_SSL + CoreAccountSettings s; if(currentAccount().useSsl()) { if(msg["SupportSsl"].toBool()) { + // Make sure the warning is shown next time we don't have SSL in the core + s.setAccountValue("ShowNoCoreSslWarning", true); + QSslSocket *sslSocket = qobject_cast(_socket); Q_ASSERT(sslSocket); - connect(sslSocket, SIGNAL(encrypted()), this, SLOT(sslSocketEncrypted())); - connect(sslSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - + connect(sslSocket, SIGNAL(encrypted()), SLOT(sslSocketEncrypted())); + connect(sslSocket, SIGNAL(sslErrors(const QList &)), SLOT(sslErrors())); sslSocket->startClientEncryption(); } else { - emit connectionError(tr("The Quassel Core you are trying to connect to does not support SSL!
If you want to connect anyways, disable the usage of SSL in the account settings.")); - disconnectFromCore(); + if(s.accountValue("ShowNoCoreSslWarning", true).toBool()) { + bool accepted = false; + emit handleNoSslInCore(&accepted); + if(!accepted) { + disconnectFromCore(tr("Unencrypted connection canceled")); + return; + } + s.setAccountValue("ShowNoCoreSslWarning", false); + s.setAccountValue("SslCert", QString()); + } + connectionReady(); } return; } #endif // if we use SSL we wait for the next step until every SSL warning has been cleared connectionReady(); +} + +#ifdef HAVE_SSL + +void CoreConnection::sslSocketEncrypted() { + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); + if(!socket->sslErrors().count()) { + // Cert is valid, so we don't want to store it as known + // That way, a warning will appear in case it becomes invalid at some point + CoreAccountSettings s; + s.setAccountValue("SSLCert", QString()); + } + + emit encrypted(true); + connectionReady(); } +void CoreConnection::sslErrors() { + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); + + CoreAccountSettings s; + QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); + + if(knownDigest != socket->peerCertificate().digest()) { + bool accepted = false; + bool permanently = false; + emit handleSslErrors(socket, &accepted, &permanently); + + if(!accepted) { + disconnectFromCore(tr("Unencrypted connection canceled")); + return; + } + + if(permanently) + s.setAccountValue("SslCert", socket->peerCertificate().digest()); + else + s.setAccountValue("SslCert", QString()); + } + + socket->ignoreSslErrors(); +} + +#endif /* HAVE_SSL */ + void CoreConnection::connectionReady() { + setState(Connected); + emit connectionMsg(tr("Connected to %1").arg(currentAccount().accountName())); + if(!_coreMsgBuffer["Configured"].toBool()) { // start wizard emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList()); @@ -363,7 +457,6 @@ void CoreConnection::connectionReady() { loginToCore(); } _coreMsgBuffer.clear(); - resetWarningsHandler(); } void CoreConnection::loginToCore(const QString &prevError) { @@ -372,8 +465,7 @@ void CoreConnection::loginToCore(const QString &prevError) { bool valid = false; emit userAuthenticationRequired(&_account, &valid, prevError); // *must* be a synchronous call if(!valid || currentAccount().user().isEmpty() || currentAccount().password().isEmpty()) { - disconnectFromCore(); - emit connectionError(tr("Login canceled")); + disconnectFromCore(tr("Login canceled")); return; } } @@ -408,10 +500,16 @@ void CoreConnection::sessionStateReceived(const QVariantMap &state) { disconnect(_socket, SIGNAL(readyRead()), this, 0); disconnect(_socket, SIGNAL(connected()), this, 0); - //Client::instance()->setConnectedToCore(currentAccount().accountId(), _socket); syncToCore(state); } +void CoreConnection::internalSessionStateReceived(const QVariant &packedState) { + updateProgress(100, 100); + + setState(Synchronizing); + syncToCore(packedState.toMap()); +} + void CoreConnection::syncToCore(const QVariantMap &sessionState) { setProgressText(tr("Receiving network states")); updateProgress(0, 100); @@ -462,7 +560,7 @@ void CoreConnection::networkInitDone() { void CoreConnection::checkSyncState() { if(_netsToSync.isEmpty()) { setState(Synchronized); - setProgressText(QString()); + setProgressText(tr("Synchronized to %1").arg(currentAccount().accountName())); setProgressMaximum(-1); emit synchronized(); }