@@ -241,6 +241,14 @@ struct timeval MillisToTimeval(int64_t nTimeout)
241241 return timeout;
242242}
243243
244+ enum class IntrRecvError {
245+ OK,
246+ Timeout,
247+ Disconnected,
248+ NetworkError,
249+ Interrupted
250+ };
251+
244252/* *
245253 * Read bytes from socket. This will either read the full number of bytes requested
246254 * or return False on error or timeout.
@@ -252,7 +260,7 @@ struct timeval MillisToTimeval(int64_t nTimeout)
252260 *
253261 * @note This function requires that hSocket is in non-blocking mode.
254262 */
255- bool static InterruptibleRecv (char * data, size_t len, int timeout, SOCKET& hSocket)
263+ static IntrRecvError InterruptibleRecv (char * data, size_t len, int timeout, SOCKET& hSocket)
256264{
257265 int64_t curTime = GetTimeMillis ();
258266 int64_t endTime = curTime + timeout;
@@ -265,29 +273,29 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock
265273 len -= ret;
266274 data += ret;
267275 } else if (ret == 0 ) { // Unexpected disconnection
268- return false ;
276+ return IntrRecvError::Disconnected ;
269277 } else { // Other error or blocking
270278 int nErr = WSAGetLastError ();
271279 if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
272280 if (!IsSelectableSocket (hSocket)) {
273- return false ;
281+ return IntrRecvError::NetworkError ;
274282 }
275283 struct timeval tval = MillisToTimeval (std::min (endTime - curTime, maxWait));
276284 fd_set fdset;
277285 FD_ZERO (&fdset);
278286 FD_SET (hSocket, &fdset);
279287 int nRet = select (hSocket + 1 , &fdset, NULL , NULL , &tval);
280288 if (nRet == SOCKET_ERROR) {
281- return false ;
289+ return IntrRecvError::NetworkError ;
282290 }
283291 } else {
284- return false ;
292+ return IntrRecvError::NetworkError ;
285293 }
286294 }
287295 boost::this_thread::interruption_point ();
288296 curTime = GetTimeMillis ();
289297 }
290- return len == 0 ;
298+ return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout ;
291299}
292300
293301struct ProxyCredentials
@@ -299,6 +307,7 @@ struct ProxyCredentials
299307/* * Connect using SOCKS5 (as described in RFC1928) */
300308bool static Socks5 (std::string strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
301309{
310+ IntrRecvError recvr;
302311 LogPrintf (" SOCKS5 connecting %s\n " , strDest);
303312 if (strDest.size () > 255 ) {
304313 CloseSocket (hSocket);
@@ -321,7 +330,7 @@ bool static Socks5(std::string strDest, int port, const ProxyCredentials *auth,
321330 return error (" Error sending to proxy" );
322331 }
323332 char pchRet1[2 ];
324- if (! InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
333+ if ((recvr = InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
325334 CloseSocket (hSocket);
326335 return error (" Error reading proxy response" );
327336 }
@@ -346,7 +355,7 @@ bool static Socks5(std::string strDest, int port, const ProxyCredentials *auth,
346355 }
347356 LogPrint (" proxy" , " SOCKS5 sending proxy authentication %s:%s\n " , auth->username , auth->password );
348357 char pchRetA[2 ];
349- if (! InterruptibleRecv (pchRetA, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
358+ if ((recvr = InterruptibleRecv (pchRetA, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
350359 CloseSocket (hSocket);
351360 return error (" Error reading proxy authentication response" );
352361 }
@@ -375,9 +384,9 @@ bool static Socks5(std::string strDest, int port, const ProxyCredentials *auth,
375384 return error (" Error sending to proxy" );
376385 }
377386 char pchRet2[4 ];
378- if (! InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket)) {
387+ if ((recvr = InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
379388 CloseSocket (hSocket);
380- return error (" Error reading proxy response" );
389+ return error (" Error while reading proxy response" );
381390 }
382391 if (pchRet2[0 ] != 0x05 ) {
383392 CloseSocket (hSocket);
@@ -413,30 +422,30 @@ bool static Socks5(std::string strDest, int port, const ProxyCredentials *auth,
413422 char pchRet3[256 ];
414423 switch (pchRet2[3 ]) {
415424 case 0x01 :
416- ret = InterruptibleRecv (pchRet3, 4 , SOCKS5_RECV_TIMEOUT, hSocket);
425+ recvr = InterruptibleRecv (pchRet3, 4 , SOCKS5_RECV_TIMEOUT, hSocket);
417426 break ;
418427 case 0x04 :
419- ret = InterruptibleRecv (pchRet3, 16 , SOCKS5_RECV_TIMEOUT, hSocket);
428+ recvr = InterruptibleRecv (pchRet3, 16 , SOCKS5_RECV_TIMEOUT, hSocket);
420429 break ;
421430 case 0x03 : {
422- ret = InterruptibleRecv (pchRet3, 1 , SOCKS5_RECV_TIMEOUT, hSocket);
423- if (!ret ) {
431+ recvr = InterruptibleRecv (pchRet3, 1 , SOCKS5_RECV_TIMEOUT, hSocket);
432+ if (recvr != IntrRecvError::OK ) {
424433 CloseSocket (hSocket);
425434 return error (" Error reading from proxy" );
426435 }
427436 int nRecv = pchRet3[0 ];
428- ret = InterruptibleRecv (pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
437+ recvr = InterruptibleRecv (pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
429438 break ;
430439 }
431440 default :
432441 CloseSocket (hSocket);
433442 return error (" Error: malformed proxy response" );
434443 }
435- if (!ret ) {
444+ if (recvr != IntrRecvError::OK ) {
436445 CloseSocket (hSocket);
437446 return error (" Error reading from proxy" );
438447 }
439- if (! InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
448+ if ((recvr = InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
440449 CloseSocket (hSocket);
441450 return error (" Error reading from proxy" );
442451 }
0 commit comments