_userInputHandler(new CoreUserInputHandler(this)),
_autoReconnectCount(0),
_quitRequested(false),
+ _disconnectExpected(false),
_previousConnectionAttemptFailed(false),
_lastUsedServerIndex(0),
}
-void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool withReconnect)
+void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool withReconnect,
+ bool forceImmediate)
{
+ // Disconnecting from the network, should expect a socket close or error
+ _disconnectExpected = true;
_quitRequested = requested; // see socketDisconnected();
if (!withReconnect) {
_autoReconnectTimer.stop();
socketDisconnected();
} else {
if (socket.state() == QAbstractSocket::ConnectedState) {
- userInputHandler()->issueQuit(_quitReason);
+ userInputHandler()->issueQuit(_quitReason, forceImmediate);
} else {
socket.close();
}
}
-void CoreNetwork::putRawLine(QByteArray s)
+void CoreNetwork::putRawLine(const QByteArray s, const bool prepend)
{
- if (_tokenBucket > 0)
+ if (_tokenBucket > 0) {
writeToSocket(s);
- else
- _msgQueue.append(s);
+ } else {
+ if (prepend) {
+ _msgQueue.prepend(s);
+ } else {
+ _msgQueue.append(s);
+ }
+ }
}
-void CoreNetwork::putCmd(const QString &cmd, const QList<QByteArray> ¶ms, const QByteArray &prefix)
+void CoreNetwork::putCmd(const QString &cmd, const QList<QByteArray> ¶ms, const QByteArray &prefix, const bool prepend)
{
QByteArray msg;
msg += params[i];
}
- putRawLine(msg);
+ putRawLine(msg, prepend);
}
-void CoreNetwork::putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, const QByteArray &prefix)
+void CoreNetwork::putCmd(const QString &cmd, const QList<QList<QByteArray>> ¶ms, const QByteArray &prefix, const bool prependAll)
{
QListIterator<QList<QByteArray>> i(params);
while (i.hasNext()) {
QList<QByteArray> msg = i.next();
- putCmd(cmd, msg, prefix);
+ putCmd(cmd, msg, prefix, prependAll);
}
}
void CoreNetwork::socketError(QAbstractSocket::SocketError error)
{
- if (_quitRequested && error == QAbstractSocket::RemoteHostClosedError)
+ // Ignore socket closed errors if expected
+ if (_disconnectExpected && error == QAbstractSocket::RemoteHostClosedError) {
return;
+ }
_previousConnectionAttemptFailed = true;
qWarning() << qPrintable(tr("Could not connect to %1 (%2)").arg(networkName(), socket.errorString()));
setConnected(false);
emit disconnected(networkId());
emit socketDisconnected(identityPtr(), localAddress(), localPort(), peerAddress(), peerPort());
+ // Reset disconnect expectations
+ _disconnectExpected = false;
if (_quitRequested) {
_quitRequested = false;
setConnectionState(Network::Disconnected);
{
setConnectionState(Network::Initialized);
setConnected(true);
+ _disconnectExpected = false;
_quitRequested = false;
if (useAutoReconnect()) {
#ifdef HAVE_SSL
void CoreNetwork::sslErrors(const QList<QSslError> &sslErrors)
{
- Q_UNUSED(sslErrors)
- socket.ignoreSslErrors();
- // TODO errorhandling
+ Server server = usedServer();
+ if (server.sslVerify) {
+ // Treat the SSL error as a hard error
+ QString sslErrorMessage = tr("Encrypted connection couldn't be verified, disconnecting "
+ "since verification is required");
+ if (!sslErrors.empty()) {
+ // Add the error reason if known
+ sslErrorMessage.append(tr(" (Reason: %1)").arg(sslErrors.first().errorString()));
+ }
+ displayMsg(Message::Error, BufferInfo::StatusBuffer, "", sslErrorMessage);
+
+ // Disconnect, triggering a reconnect in case it's a temporary issue with certificate
+ // validity, network trouble, etc.
+ disconnectFromIrc(false, QString("Encrypted connection not verified"), true /* withReconnect */);
+ } else {
+ // Treat the SSL error as a warning, continue to connect anyways
+ QString sslErrorMessage = tr("Encrypted connection couldn't be verified, continuing "
+ "since verification is not required");
+ if (!sslErrors.empty()) {
+ // Add the error reason if known
+ sslErrorMessage.append(tr(" (Reason: %1)").arg(sslErrors.first().errorString()));
+ }
+ displayMsg(Message::Info, BufferInfo::StatusBuffer, "", sslErrorMessage);
+
+ // Proceed with the connection
+ socket.ignoreSslErrors();
+ }
}