282
void CoreConnection::coreSocketError(QAbstractSocket::SocketError)
238
void CoreConnection::coreSocketError(QAbstractSocket::SocketError error, const QString &errorString)
284
disconnectFromCore(_socket->errorString(), true);
242
disconnectFromCore(errorString, true);
288
246
void CoreConnection::coreSocketDisconnected()
248
setState(Disconnected);
290
249
_wasReconnect = false;
291
250
resetConnection(_wantReconnect);
292
// FIXME handle disconnects gracefully
296
// note: this still expects the legacy protocol
297
// note²: after cleaning this up, we can probably get rid of _socket altogether
298
void CoreConnection::coreHasData(const QVariant &item)
300
QVariantMap msg = item.toMap();
301
if (!msg.contains("MsgType")) {
302
// This core is way too old and does not even speak our init protocol...
303
emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
304
disconnectFromCore(QString(), false);
307
if (msg["MsgType"] == "ClientInitAck") {
310
else if (msg["MsgType"] == "ClientInitReject") {
311
emit connectionErrorPopup(msg["Error"].toString());
312
disconnectFromCore(QString(), false);
315
else if (msg["MsgType"] == "CoreSetupAck") {
316
emit coreSetupSuccess();
318
else if (msg["MsgType"] == "CoreSetupReject") {
319
emit coreSetupFailed(msg["Error"].toString());
321
else if (msg["MsgType"] == "ClientLoginReject") {
322
loginFailed(msg["Error"].toString());
324
else if (msg["MsgType"] == "ClientLoginAck") {
327
else if (msg["MsgType"] == "SessionInit") {
328
// that's it, let's hand over to the signal proxy
329
// if the connection is an orphan, the signalProxy adopts it.
330
// -> we don't need to care about it anymore
332
disconnect(_peer, 0, this, 0);
335
Client::signalProxy()->addPeer(_peer);
337
sessionStateReceived(msg["SessionState"].toMap());
340
disconnectFromCore(tr("Invalid data received from core"), false);
346
254
void CoreConnection::disconnectFromCore()
349
disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect
256
disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect
476
388
emit startInternalCore();
478
390
InternalPeer *peer = new InternalPeer();
479
392
Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership
480
393
emit connectToInternalCore(peer);
485
CoreAccountSettings s;
489
QSslSocket *sock = new QSslSocket(this);
490
// make sure the warning is shown if we happen to connect without SSL support later
491
s.setAccountValue("ShowNoClientSslWarning", true);
493
if (_account.useSsl()) {
494
if (s.accountValue("ShowNoClientSslWarning", true).toBool()) {
495
bool accepted = false;
496
emit handleNoSslInClient(&accepted);
498
emit connectionError(tr("Unencrypted connection canceled"));
501
s.setAccountValue("ShowNoClientSslWarning", false);
504
QTcpSocket *sock = new QTcpSocket(this);
507
#ifndef QT_NO_NETWORKPROXY
508
if (_account.useProxy()) {
509
QNetworkProxy proxy(_account.proxyType(), _account.proxyHostName(), _account.proxyPort(), _account.proxyUser(), _account.proxyPassword());
510
sock->setProxy(proxy);
515
connect(sock, SIGNAL(connected()), SLOT(coreSocketConnected()));
516
connect(sock, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
517
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(coreSocketError(QAbstractSocket::SocketError)));
518
connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState)));
520
emit connectionMsg(tr("Connecting to %1...").arg(currentAccount().accountName()));
521
sock->connectToHost(_account.hostName(), _account.port());
525
void CoreConnection::coreSocketConnected()
527
// Create the connection which will handle the incoming data
529
_peer = new LegacyPeer(_socket, this);
530
connect(_peer, SIGNAL(dataReceived(QVariant)), SLOT(coreHasData(QVariant)));
531
connect(_peer, SIGNAL(transferProgress(int,int)), SLOT(updateProgress(int,int)));
533
// Phase One: Send client info and wait for core info
535
emit connectionMsg(tr("Synchronizing to core..."));
537
QVariantMap clientInit;
538
clientInit["MsgType"] = "ClientInit";
539
clientInit["ClientVersion"] = Quassel::buildInfo().fancyVersionString;
540
clientInit["ClientDate"] = Quassel::buildInfo().buildDate;
541
clientInit["ProtocolVersion"] = Quassel::buildInfo().protocolVersion;
543
clientInit["UseSsl"] = _account.useSsl();
545
clientInit["UseSsl"] = false;
547
#ifndef QT_NO_COMPRESS
548
clientInit["UseCompression"] = true;
550
clientInit["UseCompression"] = false;
553
qobject_cast<RemotePeer *>(_peer)->writeSocketData(clientInit);
557
void CoreConnection::clientInitAck(const QVariantMap &msg)
559
// Core has accepted our version info and sent its own. Let's see if we accept it as well...
560
uint ver = msg["ProtocolVersion"].toUInt();
561
if (ver < Quassel::buildInfo().clientNeedsProtocol) {
562
emit connectionErrorPopup(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
563
"Need at least core/client protocol v%1 to connect.").arg(Quassel::buildInfo().clientNeedsProtocol));
564
disconnectFromCore(QString(), false);
568
Client::setCoreFeatures((Quassel::Features)msg["CoreFeatures"].toUInt());
570
#ifndef QT_NO_COMPRESS
571
if (msg["SupportsCompression"].toBool()) {
572
_socket->setProperty("UseCompression", true);
576
_coreMsgBuffer = msg;
579
CoreAccountSettings s;
580
if (currentAccount().useSsl()) {
581
if (msg["SupportSsl"].toBool()) {
582
// Make sure the warning is shown next time we don't have SSL in the core
583
s.setAccountValue("ShowNoCoreSslWarning", true);
585
QSslSocket *sslSocket = qobject_cast<QSslSocket *>(_socket);
587
connect(sslSocket, SIGNAL(encrypted()), SLOT(sslSocketEncrypted()));
588
connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), SLOT(sslErrors()));
589
sslSocket->startClientEncryption();
592
if (s.accountValue("ShowNoCoreSslWarning", true).toBool()) {
593
bool accepted = false;
594
emit handleNoSslInCore(&accepted);
596
disconnectFromCore(tr("Unencrypted connection canceled"), false);
599
s.setAccountValue("ShowNoCoreSslWarning", false);
600
s.setAccountValue("SslCert", QString());
607
// if we use SSL we wait for the next step until every SSL warning has been cleared
614
void CoreConnection::sslSocketEncrypted()
616
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
619
if (!socket->sslErrors().count()) {
620
// Cert is valid, so we don't want to store it as known
621
// That way, a warning will appear in case it becomes invalid at some point
622
CoreAccountSettings s;
623
s.setAccountValue("SSLCert", QString());
626
emit encrypted(true);
631
void CoreConnection::sslErrors()
633
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
636
CoreAccountSettings s;
637
QByteArray knownDigest = s.accountValue("SslCert").toByteArray();
639
if (knownDigest != socket->peerCertificate().digest()) {
640
bool accepted = false;
641
bool permanently = false;
642
emit handleSslErrors(socket, &accepted, &permanently);
645
disconnectFromCore(tr("Unencrypted connection canceled"), false);
650
s.setAccountValue("SslCert", socket->peerCertificate().digest());
652
s.setAccountValue("SslCert", QString());
655
socket->ignoreSslErrors();
659
#endif /* HAVE_SSL */
661
void CoreConnection::connectionReady()
664
emit connectionMsg(tr("Connected to %1").arg(currentAccount().accountName()));
666
if (!_coreMsgBuffer["Configured"].toBool()) {
668
emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList());
670
else if (_coreMsgBuffer["LoginEnabled"].toBool()) {
673
_coreMsgBuffer.clear();
399
_authHandler = new ClientAuthHandler(currentAccount(), this);
401
connect(_authHandler, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
402
connect(_authHandler, SIGNAL(connectionReady()), SLOT(onConnectionReady()));
403
connect(_authHandler, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(coreSocketError(QAbstractSocket::SocketError,QString)));
404
connect(_authHandler, SIGNAL(transferProgress(int,int)), SLOT(updateProgress(int,int)));
405
connect(_authHandler, SIGNAL(requestDisconnect(QString,bool)), SLOT(disconnectFromCore(QString,bool)));
407
connect(_authHandler, SIGNAL(errorMessage(QString)), SIGNAL(connectionError(QString)));
408
connect(_authHandler, SIGNAL(errorPopup(QString)), SIGNAL(connectionErrorPopup(QString)), Qt::QueuedConnection);
409
connect(_authHandler, SIGNAL(statusMessage(QString)), SIGNAL(connectionMsg(QString)));
410
connect(_authHandler, SIGNAL(encrypted(bool)), SIGNAL(encrypted(bool)));
411
connect(_authHandler, SIGNAL(startCoreSetup(QVariantList)), SIGNAL(startCoreSetup(QVariantList)));
412
connect(_authHandler, SIGNAL(coreSetupFailed(QString)), SIGNAL(coreSetupFailed(QString)));
413
connect(_authHandler, SIGNAL(coreSetupSuccessful()), SIGNAL(coreSetupSuccess()));
414
connect(_authHandler, SIGNAL(userAuthenticationRequired(CoreAccount*,bool*,QString)), SIGNAL(userAuthenticationRequired(CoreAccount*,bool*,QString)));
415
connect(_authHandler, SIGNAL(handleNoSslInClient(bool*)), SIGNAL(handleNoSslInClient(bool*)));
416
connect(_authHandler, SIGNAL(handleNoSslInCore(bool*)), SIGNAL(handleNoSslInCore(bool*)));
418
connect(_authHandler, SIGNAL(handleSslErrors(const QSslSocket*,bool*,bool*)), SIGNAL(handleSslErrors(const QSslSocket*,bool*,bool*)));
421
connect(_authHandler, SIGNAL(loginSuccessful(CoreAccount)), SLOT(onLoginSuccessful(CoreAccount)));
422
connect(_authHandler, SIGNAL(handshakeComplete(RemotePeer*,Protocol::SessionState)), SLOT(onHandshakeComplete(RemotePeer*,Protocol::SessionState)));
424
setState(Connecting);
425
_authHandler->connectToCore();
429
void CoreConnection::setupCore(const Protocol::SetupData &setupData)
431
_authHandler->setupCore(setupData);
677
435
void CoreConnection::loginToCore(const QString &user, const QString &password, bool remember)
679
_account.setUser(user);
680
_account.setPassword(password);
681
_account.setStorePassword(remember);
686
void CoreConnection::loginToCore(const QString &prevError)
688
emit connectionMsg(tr("Logging in..."));
689
if (currentAccount().user().isEmpty() || currentAccount().password().isEmpty() || !prevError.isEmpty()) {
691
emit userAuthenticationRequired(&_account, &valid, prevError); // *must* be a synchronous call
692
if (!valid || currentAccount().user().isEmpty() || currentAccount().password().isEmpty()) {
693
disconnectFromCore(tr("Login canceled"), false);
698
QVariantMap clientLogin;
699
clientLogin["MsgType"] = "ClientLogin";
700
clientLogin["User"] = currentAccount().user();
701
clientLogin["Password"] = currentAccount().password();
702
qobject_cast<RemotePeer*>(_peer)->writeSocketData(clientLogin);
706
void CoreConnection::loginFailed(const QString &error)
712
void CoreConnection::loginSuccess()
437
_authHandler->login(user, password, remember);
441
void CoreConnection::onLoginSuccessful(const CoreAccount &account)
714
443
updateProgress(0, 0);
716
445
// save current account data
717
_model->createOrUpdateAccount(currentAccount());
446
accountModel()->createOrUpdateAccount(account);
447
accountModel()->save();
720
449
_reconnectTimer.stop();
722
451
setProgressText(tr("Receiving session state"));
723
452
setState(Synchronizing);
724
emit connectionMsg(tr("Synchronizing to %1...").arg(currentAccount().accountName()));
728
void CoreConnection::sessionStateReceived(const QVariantMap &state)
730
updateProgress(100, 100);
736
void CoreConnection::internalSessionStateReceived(const QVariant &packedState)
738
updateProgress(100, 100);
453
emit connectionMsg(tr("Synchronizing to %1...").arg(account.accountName()));
457
void CoreConnection::onHandshakeComplete(RemotePeer *peer, const Protocol::SessionState &sessionState)
459
updateProgress(100, 100);
461
disconnect(_authHandler, 0, this, 0);
462
_authHandler->deleteLater();
466
connect(peer, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
467
connect(peer, SIGNAL(statusMessage(QString)), SIGNAL(connectionMsg(QString)));
468
connect(peer, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(coreSocketError(QAbstractSocket::SocketError,QString)));
470
Client::signalProxy()->addPeer(_peer); // sigproxy takes ownership of the peer!
472
syncToCore(sessionState);
476
void CoreConnection::internalSessionStateReceived(const Protocol::SessionState &sessionState)
478
updateProgress(100, 100);
480
Client::setCoreFeatures(Quassel::features()); // mono connection...
740
482
setState(Synchronizing);
741
syncToCore(packedState.toMap());
483
syncToCore(sessionState);
745
void CoreConnection::syncToCore(const QVariantMap &sessionState)
487
void CoreConnection::syncToCore(const Protocol::SessionState &sessionState)
747
if (sessionState.contains("CoreFeatures"))
748
Client::setCoreFeatures((Quassel::Features)sessionState["CoreFeatures"].toUInt());
750
489
setProgressText(tr("Receiving network states"));
751
490
updateProgress(0, 100);
753
492
// create identities
754
foreach(QVariant vid, sessionState["Identities"].toList()) {
493
foreach(const QVariant &vid, sessionState.identities) {
755
494
Client::instance()->coreIdentityCreated(vid.value<Identity>());
758
497
// create buffers
759
498
// FIXME: get rid of this crap -- why?
760
QVariantList bufferinfos = sessionState["BufferInfos"].toList();
761
499
NetworkModel *networkModel = Client::networkModel();
762
500
Q_ASSERT(networkModel);
763
foreach(QVariant vinfo, bufferinfos)
764
networkModel->bufferUpdated(vinfo.value<BufferInfo>()); // create BufferItems
766
QVariantList networkids = sessionState["NetworkIds"].toList();
501
foreach(const QVariant &vinfo, sessionState.bufferInfos)
502
networkModel->bufferUpdated(vinfo.value<BufferInfo>()); // create BufferItems
768
504
// prepare sync progress thingys...
769
505
// FIXME: Care about removal of networks
770
_numNetsToSync = networkids.count();
506
_numNetsToSync = sessionState.networkIds.count();
771
507
updateProgress(0, _numNetsToSync);
773
509
// create network objects
774
foreach(QVariant networkid, networkids) {
510
foreach(const QVariant &networkid, sessionState.networkIds) {
775
511
NetworkId netid = networkid.value<NetworkId>();
776
512
if (Client::network(netid))