Changeset View
Changeset View
Standalone View
Standalone View
src/irc/server.cpp
Show All 34 Lines | |||||
35 | #include "channellistpanel.h" | 35 | #include "channellistpanel.h" | ||
36 | #include "scriptlauncher.h" | 36 | #include "scriptlauncher.h" | ||
37 | #include "serverison.h" | 37 | #include "serverison.h" | ||
38 | #include "notificationhandler.h" | 38 | #include "notificationhandler.h" | ||
39 | #include "awaymanager.h" | 39 | #include "awaymanager.h" | ||
40 | #include "ircinput.h" | 40 | #include "ircinput.h" | ||
41 | 41 | | |||
42 | #include <QTextCodec> | 42 | #include <QTextCodec> | ||
43 | #include <QSslSocket> | ||||
43 | #include <QStringListModel> | 44 | #include <QStringListModel> | ||
44 | #include <QStringBuilder> | 45 | #include <QStringBuilder> | ||
45 | #include <QInputDialog> | 46 | #include <QInputDialog> | ||
46 | #include <QNetworkProxy> | 47 | #include <QNetworkProxy> | ||
47 | 48 | | |||
48 | #include <QDebug> | 49 | #include <QDebug> | ||
49 | #include <KLocalizedString> | 50 | #include <KLocalizedString> | ||
50 | #include <KWindowSystem> | 51 | #include <KWindowSystem> | ||
51 | #include <KShell> | 52 | #include <KShell> | ||
52 | 53 | | |||
54 | #include <KSslErrorUiData> | ||||
53 | #include <kio/sslui.h> | 55 | #include <kio/sslui.h> | ||
54 | 56 | | |||
55 | using namespace Konversation; | 57 | using namespace Konversation; | ||
56 | 58 | | |||
57 | int Server::m_availableConnectionId = 0; | 59 | int Server::m_availableConnectionId = 0; | ||
58 | 60 | | |||
59 | Server::Server(QObject* parent, ConnectionSettings& settings) : QObject(parent) | 61 | Server::Server(QObject* parent, ConnectionSettings& settings) : QObject(parent) | ||
60 | { | 62 | { | ||
▲ Show 20 Lines • Show All 400 Lines • ▼ Show 20 Line(s) | 456 | // } | |||
461 | 463 | | |||
462 | // This is needed to support server groups with mixed SSL and nonSSL servers | 464 | // This is needed to support server groups with mixed SSL and nonSSL servers | ||
463 | delete m_socket; | 465 | delete m_socket; | ||
464 | m_socket = nullptr; | 466 | m_socket = nullptr; | ||
465 | if (m_referenceNicklist != getIdentity()->getNicknameList()) | 467 | if (m_referenceNicklist != getIdentity()->getNicknameList()) | ||
466 | m_nickListModel->setStringList(getIdentity()->getNicknameList()); | 468 | m_nickListModel->setStringList(getIdentity()->getNicknameList()); | ||
467 | resetNickSelection(); | 469 | resetNickSelection(); | ||
468 | 470 | | |||
469 | m_socket = new KTcpSocket(); | 471 | m_socket = new QSslSocket(); | ||
470 | m_socket->setObjectName(QStringLiteral("serverSocket")); | 472 | m_socket->setObjectName(QStringLiteral("serverSocket")); | ||
471 | 473 | | |||
472 | connect(m_socket, SIGNAL(error(KTcpSocket::Error)), SLOT(broken(KTcpSocket::Error)) ); | 474 | connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), | ||
473 | connect(m_socket, &QIODevice::readyRead, this, &Server::incoming); | 475 | this, &Server::broken); | ||
474 | connect(m_socket, &KTcpSocket::disconnected, this, &Server::closed); | | |||
475 | 476 | | |||
476 | connect(m_socket, &KTcpSocket::hostFound, this, &Server::hostFound); | 477 | connect(m_socket, &QIODevice::readyRead, this, &Server::incoming); | ||
478 | connect(m_socket, &QAbstractSocket::disconnected, this, &Server::closed); | ||||
479 | connect(m_socket, &QAbstractSocket::hostFound, this, &Server::hostFound); | ||||
477 | 480 | | |||
478 | getStatusView()->appendServerMessage(i18n("Info"),i18n("Looking for server %1 (port %2)...", | 481 | getStatusView()->appendServerMessage(i18n("Info"),i18n("Looking for server %1 (port %2)...", | ||
479 | getConnectionSettings().server().host(), | 482 | getConnectionSettings().server().host(), | ||
480 | QString::number(getConnectionSettings().server().port()))); | 483 | QString::number(getConnectionSettings().server().port()))); | ||
481 | 484 | | |||
482 | KTcpSocket::ProxyPolicy proxyPolicy = KTcpSocket::AutoProxy; | | |||
483 | if(getConnectionSettings().server().bypassProxy()) { | 485 | if(getConnectionSettings().server().bypassProxy()) { | ||
484 | proxyPolicy = KTcpSocket::ManualProxy; | | |||
485 | m_socket->setProxy(QNetworkProxy::NoProxy); | 486 | m_socket->setProxy(QNetworkProxy::NoProxy); | ||
486 | } | 487 | } | ||
487 | 488 | | |||
488 | // connect() will do a async lookup too | 489 | // connect() will do a async lookup too | ||
489 | if (getConnectionSettings().server().SSLEnabled() | 490 | if (getConnectionSettings().server().SSLEnabled() | ||
490 | || getIdentity()->getAuthType() == QLatin1String("saslexternal") | 491 | || getIdentity()->getAuthType() == QLatin1String("saslexternal") | ||
491 | || getIdentity()->getAuthType() == QLatin1String("pemclientcert")) | 492 | || getIdentity()->getAuthType() == QLatin1String("pemclientcert")) | ||
492 | { | 493 | { | ||
493 | connect(m_socket, &KTcpSocket::encrypted, this, &Server::socketConnected); | 494 | connect(m_socket, &QSslSocket::encrypted, this, &Server::socketConnected); | ||
494 | connect(m_socket, SIGNAL(sslErrors(QList<KSslError>)), SLOT(sslError(QList<KSslError>))); | 495 | connect(m_socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors), | ||
496 | this, &Server::sslError); | ||||
495 | 497 | | |||
496 | if (getIdentity()->getAuthType() == QLatin1String("saslexternal") | 498 | if (getIdentity()->getAuthType() == QLatin1String("saslexternal") | ||
497 | || getIdentity()->getAuthType() == QLatin1String("pemclientcert")) | 499 | || getIdentity()->getAuthType() == QLatin1String("pemclientcert")) | ||
498 | { | 500 | { | ||
499 | m_socket->setLocalCertificate(getIdentity()->getPemClientCertFile().toLocalFile()); | 501 | m_socket->setLocalCertificate(getIdentity()->getPemClientCertFile().toLocalFile()); | ||
500 | m_socket->setPrivateKey(getIdentity()->getPemClientCertFile().toLocalFile()); | 502 | m_socket->setPrivateKey(getIdentity()->getPemClientCertFile().toLocalFile()); | ||
501 | } | 503 | } | ||
502 | 504 | | |||
503 | m_socket->setAdvertisedSslVersion(KTcpSocket::SecureProtocols); | 505 | m_socket->setProtocol(QSsl::SecureProtocols); | ||
504 | 506 | // QIODevice::Unbuffered, see m_socket->connectToHost() call below | |||
505 | m_socket->connectToHostEncrypted(getConnectionSettings().server().host(), getConnectionSettings().server().port()); | 507 | m_socket->connectToHostEncrypted(getConnectionSettings().server().host(), | ||
508 | getConnectionSettings().server().port(), | ||||
509 | (QIODevice::ReadWrite | QIODevice::Unbuffered)); | ||||
506 | } | 510 | } | ||
507 | else | 511 | else | ||
508 | { | 512 | { | ||
509 | connect(m_socket, &KTcpSocket::connected, this, &Server::socketConnected); | 513 | connect(m_socket, &QAbstractSocket::connected, this, &Server::socketConnected); | ||
510 | m_socket->connectToHost(getConnectionSettings().server().host(), getConnectionSettings().server().port(), proxyPolicy); | 514 | // From KTcpSocket::connectToHost(): | ||
515 | // There are enough layers of buffers between us and the network, and there is a quirk | ||||
516 | // in QIODevice that can make it try to readData() twice per read() call if buffered and | ||||
517 | // reaData() does not deliver enough data the first time. Like when the other side is | ||||
518 | // simply not sending any more data... | ||||
519 | // This can *apparently* lead to long delays sometimes which stalls applications. | ||||
520 | // Do not want. | ||||
521 | m_socket->connectToHost(getConnectionSettings().server().host(), | ||||
522 | getConnectionSettings().server().port(), | ||||
523 | (QIODevice::ReadWrite | QIODevice::Unbuffered)); | ||||
511 | } | 524 | } | ||
512 | 525 | | |||
513 | // set up the connection details | 526 | // set up the connection details | ||
514 | setPrefixes(m_serverNickPrefixModes, m_serverNickPrefixes); | 527 | setPrefixes(m_serverNickPrefixModes, m_serverNickPrefixes); | ||
515 | // reset InputFilter (auto request info, /WHO request info) | 528 | // reset InputFilter (auto request info, /WHO request info) | ||
516 | m_inputFilter.reset(); | 529 | m_inputFilter.reset(); | ||
517 | } | 530 | } | ||
518 | else | 531 | else | ||
▲ Show 20 Lines • Show All 336 Lines • ▼ Show 20 Line(s) | 866 | { | |||
855 | 868 | | |||
856 | if (message.isEmpty()) { | 869 | if (message.isEmpty()) { | ||
857 | queue(QStringLiteral("AUTHENTICATE +"), HighPriority); | 870 | queue(QStringLiteral("AUTHENTICATE +"), HighPriority); | ||
858 | } else { | 871 | } else { | ||
859 | queue(QStringLiteral("AUTHENTICATE ") + message, HighPriority); | 872 | queue(QStringLiteral("AUTHENTICATE ") + message, HighPriority); | ||
860 | } | 873 | } | ||
861 | } | 874 | } | ||
862 | 875 | | |||
863 | void Server::broken(KTcpSocket::Error error) | 876 | void Server::broken(QAbstractSocket::SocketError error) | ||
864 | { | 877 | { | ||
865 | Q_UNUSED(error); | 878 | Q_UNUSED(error); | ||
866 | qDebug() << "Connection broken with state" << m_connectionState << "and error:" << m_socket->errorString(); | 879 | qDebug() << "Connection broken with state" << m_connectionState << "and error:" << m_socket->errorString(); | ||
867 | 880 | | |||
868 | m_socket->blockSignals(true); | 881 | m_socket->blockSignals(true); | ||
869 | 882 | | |||
870 | resetQueues(); | 883 | resetQueues(); | ||
871 | 884 | | |||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Line(s) | |||||
930 | { | 943 | { | ||
931 | QInputDialog* nickChangeDialog = getStatusView()->findChild<QInputDialog*>(); | 944 | QInputDialog* nickChangeDialog = getStatusView()->findChild<QInputDialog*>(); | ||
932 | 945 | | |||
933 | if (nickChangeDialog) nickChangeDialog->reject(); | 946 | if (nickChangeDialog) nickChangeDialog->reject(); | ||
934 | } | 947 | } | ||
935 | 948 | | |||
936 | } | 949 | } | ||
937 | 950 | | |||
938 | void Server::sslError( const QList<KSslError>& errors ) | 951 | void Server::sslError(const QList<QSslError> &errors) | ||
939 | { | 952 | { | ||
940 | // We have to explicitly grab the socket we got the error from, | 953 | // We have to explicitly grab the socket we got the error from, | ||
941 | // lest we might end up calling ignoreSslErrors() on a different | 954 | // lest we might end up calling ignoreSslErrors() on a different | ||
942 | // socket later if m_socket has started pointing at something | 955 | // socket later if m_socket has started pointing at something | ||
943 | // else. | 956 | // else. | ||
944 | QPointer<KTcpSocket> socket = qobject_cast<KTcpSocket*>(QObject::sender()); | 957 | QPointer<QSslSocket> socket = qobject_cast<QSslSocket *>(QObject::sender()); | ||
945 | 958 | | |||
946 | m_sslErrorLock = true; | 959 | m_sslErrorLock = true; | ||
947 | bool ignoreSslErrors = KIO::SslUi::askIgnoreSslErrors(socket, KIO::SslUi::RecallAndStoreRules); | 960 | KSslErrorUiData uiData(socket); | ||
961 | bool ignoreSslErrors = KIO::SslUi::askIgnoreSslErrors(uiData, KIO::SslUi::RecallAndStoreRules); | ||||
948 | m_sslErrorLock = false; | 962 | m_sslErrorLock = false; | ||
949 | 963 | | |||
950 | // The dialog-based user interaction above may take an undefined amount | 964 | // The dialog-based user interaction above may take an undefined amount | ||
951 | // of time, and anything could happen to the socket in that span of time. | 965 | // of time, and anything could happen to the socket in that span of time. | ||
952 | // If it was destroyed, let's not do anything and bail out. | 966 | // If it was destroyed, let's not do anything and bail out. | ||
953 | if (!socket) | 967 | if (!socket) | ||
954 | { | 968 | { | ||
955 | qDebug() << "Socket was destroyed while waiting for user interaction."; | 969 | qDebug() << "Socket was destroyed while waiting for user interaction."; | ||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Line(s) | 1072 | { | |||
1061 | else | 1075 | else | ||
1062 | qDebug() << "Got error: " << res.errorString(); | 1076 | qDebug() << "Got error: " << res.errorString(); | ||
1063 | } | 1077 | } | ||
1064 | 1078 | | |||
1065 | bool Server::isSocketConnected() const | 1079 | bool Server::isSocketConnected() const | ||
1066 | { | 1080 | { | ||
1067 | if (!m_socket) return false; | 1081 | if (!m_socket) return false; | ||
1068 | 1082 | | |||
1069 | return (m_socket->state() == KTcpSocket::ConnectedState); | 1083 | return (m_socket->state() == QAbstractSocket::ConnectedState); | ||
1070 | } | 1084 | } | ||
1071 | 1085 | | |||
1072 | void Server::updateConnectionState(Konversation::ConnectionState state) | 1086 | void Server::updateConnectionState(Konversation::ConnectionState state) | ||
1073 | { | 1087 | { | ||
1074 | if (state != m_connectionState) | 1088 | if (state != m_connectionState) | ||
1075 | { | 1089 | { | ||
1076 | m_connectionState = state; | 1090 | m_connectionState = state; | ||
1077 | 1091 | | |||
▲ Show 20 Lines • Show All 2891 Lines • ▼ Show 20 Line(s) | 3982 | { | |||
3969 | Application* konvApp = Application::instance(); | 3983 | Application* konvApp = Application::instance(); | ||
3970 | return konvApp->getMainWindow()->getViewContainer(); | 3984 | return konvApp->getMainWindow()->getViewContainer(); | ||
3971 | } | 3985 | } | ||
3972 | 3986 | | |||
3973 | 3987 | | |||
3974 | bool Server::getUseSSL() const | 3988 | bool Server::getUseSSL() const | ||
3975 | { | 3989 | { | ||
3976 | if ( m_socket ) | 3990 | if ( m_socket ) | ||
3977 | return ( m_socket->encryptionMode() != KTcpSocket::UnencryptedMode ); | 3991 | return ( m_socket->mode() != QSslSocket::UnencryptedMode ); | ||
3978 | else | 3992 | else | ||
3979 | return false; | 3993 | return false; | ||
3980 | } | 3994 | } | ||
3981 | 3995 | | |||
3982 | 3996 | | |||
3983 | QString Server::getSSLInfo() const | 3997 | QString Server::getSSLInfo() const | ||
3984 | { | 3998 | { | ||
3985 | // SSLSocket* sslsocket = dynamic_cast<SSLSocket*>(m_socket); | 3999 | // SSLSocket* sslsocket = dynamic_cast<SSLSocket*>(m_socket); | ||
▲ Show 20 Lines • Show All 423 Lines • Show Last 20 Lines |