Skip to content

Commit 7639d38

Browse files
committed
Merge #9726: netbase: Do not print an error on connection timeouts through proxy
3ddfe29 netbase: Do not print an error on connection timeouts through proxy (Wladimir J. van der Laan) 13f6085 netbase: Make InterruptibleRecv return an error code instead of bool (Wladimir J. van der Laan)
2 parents aa791e2 + 3ddfe29 commit 7639d38

File tree

1 file changed

+34
-18
lines changed

1 file changed

+34
-18
lines changed

src/netbase.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ struct timeval MillisToTimeval(int64_t nTimeout)
198198
return timeout;
199199
}
200200

201+
enum class IntrRecvError {
202+
OK,
203+
Timeout,
204+
Disconnected,
205+
NetworkError,
206+
Interrupted
207+
};
208+
201209
/**
202210
* Read bytes from socket. This will either read the full number of bytes requested
203211
* or return False on error or timeout.
@@ -209,7 +217,7 @@ struct timeval MillisToTimeval(int64_t nTimeout)
209217
*
210218
* @note This function requires that hSocket is in non-blocking mode.
211219
*/
212-
bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
220+
static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
213221
{
214222
int64_t curTime = GetTimeMillis();
215223
int64_t endTime = curTime + timeout;
@@ -222,30 +230,30 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock
222230
len -= ret;
223231
data += ret;
224232
} else if (ret == 0) { // Unexpected disconnection
225-
return false;
233+
return IntrRecvError::Disconnected;
226234
} else { // Other error or blocking
227235
int nErr = WSAGetLastError();
228236
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
229237
if (!IsSelectableSocket(hSocket)) {
230-
return false;
238+
return IntrRecvError::NetworkError;
231239
}
232240
struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
233241
fd_set fdset;
234242
FD_ZERO(&fdset);
235243
FD_SET(hSocket, &fdset);
236244
int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval);
237245
if (nRet == SOCKET_ERROR) {
238-
return false;
246+
return IntrRecvError::NetworkError;
239247
}
240248
} else {
241-
return false;
249+
return IntrRecvError::NetworkError;
242250
}
243251
}
244252
if (interruptSocks5Recv)
245-
return false;
253+
return IntrRecvError::Interrupted;
246254
curTime = GetTimeMillis();
247255
}
248-
return len == 0;
256+
return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
249257
}
250258

251259
struct ProxyCredentials
@@ -272,6 +280,7 @@ std::string Socks5ErrorString(int err)
272280
/** Connect using SOCKS5 (as described in RFC1928) */
273281
static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
274282
{
283+
IntrRecvError recvr;
275284
LogPrint("net", "SOCKS5 connecting %s\n", strDest);
276285
if (strDest.size() > 255) {
277286
CloseSocket(hSocket);
@@ -294,7 +303,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
294303
return error("Error sending to proxy");
295304
}
296305
char pchRet1[2];
297-
if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
306+
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
298307
CloseSocket(hSocket);
299308
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
300309
return false;
@@ -320,7 +329,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
320329
}
321330
LogPrint("proxy", "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
322331
char pchRetA[2];
323-
if (!InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
332+
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
324333
CloseSocket(hSocket);
325334
return error("Error reading proxy authentication response");
326335
}
@@ -349,9 +358,16 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
349358
return error("Error sending to proxy");
350359
}
351360
char pchRet2[4];
352-
if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) {
361+
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
353362
CloseSocket(hSocket);
354-
return error("Error reading proxy response");
363+
if (recvr == IntrRecvError::Timeout) {
364+
/* If a timeout happens here, this effectively means we timed out while connecting
365+
* to the remote node. This is very common for Tor, so do not print an
366+
* error message. */
367+
return false;
368+
} else {
369+
return error("Error while reading proxy response");
370+
}
355371
}
356372
if (pchRet2[0] != 0x05) {
357373
CloseSocket(hSocket);
@@ -370,26 +386,26 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
370386
char pchRet3[256];
371387
switch (pchRet2[3])
372388
{
373-
case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
374-
case 0x04: ret = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
389+
case 0x01: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
390+
case 0x04: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
375391
case 0x03:
376392
{
377-
ret = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
378-
if (!ret) {
393+
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
394+
if (recvr != IntrRecvError::OK) {
379395
CloseSocket(hSocket);
380396
return error("Error reading from proxy");
381397
}
382398
int nRecv = pchRet3[0];
383-
ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
399+
recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
384400
break;
385401
}
386402
default: CloseSocket(hSocket); return error("Error: malformed proxy response");
387403
}
388-
if (!ret) {
404+
if (recvr != IntrRecvError::OK) {
389405
CloseSocket(hSocket);
390406
return error("Error reading from proxy");
391407
}
392-
if (!InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
408+
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
393409
CloseSocket(hSocket);
394410
return error("Error reading from proxy");
395411
}

0 commit comments

Comments
 (0)