Do not discard WSAECONNRESET error code from UDP under Windows

When a datagram is sent to a closed host/port combination, the host will
likely send back an ICMP error message. In the regular socket API, there
isn't a good way of actually receiving this error, so some Windows kernels
wired that message back up to the call to WSARecvFrom() as a synthetic
datagram. Reading this datagram results in a WSAECONNRESET error code,
which should reported to the user as a refused connection attempt.

To make the errors a bit more informative, the native error strings for
WSAECONNRESET and WSAENETRESET were also added.

Task-number: QTBUG-49301
Change-Id: If659be54ba1b39965b5f481f0c0cb9eeea0a06d2
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
bb10
Alex Trotsenko 2015-12-08 16:14:57 +02:00
parent 090bf50771
commit 55f0343a99
3 changed files with 19 additions and 1 deletions

View File

@ -275,6 +275,12 @@ void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, Er
case TemporaryErrorString:
socketErrorString = QNativeSocketEngine::tr("Temporary error");
break;
case NetworkDroppedConnectionErrorString:
socketErrorString = QNativeSocketEngine::tr("Network dropped connection on reset");
break;
case ConnectionResetErrorString:
socketErrorString = QNativeSocketEngine::tr("Connection reset by peer");
break;
case UnknownSocketErrorString:
socketErrorString = QNativeSocketEngine::tr("Unknown error");
break;

View File

@ -229,6 +229,8 @@ public:
NotSocketErrorString,
InvalidProxyTypeString,
TemporaryErrorString,
NetworkDroppedConnectionErrorString,
ConnectionResetErrorString,
UnknownSocketErrorString = -1
};

View File

@ -1250,7 +1250,17 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
} else {
WS_ERROR_DEBUG(err);
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
switch (err) {
case WSAENETRESET:
setError(QAbstractSocket::NetworkError, NetworkDroppedConnectionErrorString);
break;
case WSAECONNRESET:
setError(QAbstractSocket::ConnectionRefusedError, ConnectionResetErrorString);
break;
default:
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
break;
}
ret = -1;
}
} else {