@@ -198,6 +198,14 @@ struct timeval MillisToTimeval(int64_t nTimeout)
198
198
return timeout;
199
199
}
200
200
201
+ enum class IntrRecvError {
202
+ OK,
203
+ Timeout,
204
+ Disconnected,
205
+ NetworkError,
206
+ Interrupted
207
+ };
208
+
201
209
/* *
202
210
* Read bytes from socket. This will either read the full number of bytes requested
203
211
* or return False on error or timeout.
@@ -209,7 +217,7 @@ struct timeval MillisToTimeval(int64_t nTimeout)
209
217
*
210
218
* @note This function requires that hSocket is in non-blocking mode.
211
219
*/
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)
213
221
{
214
222
int64_t curTime = GetTimeMillis ();
215
223
int64_t endTime = curTime + timeout;
@@ -222,30 +230,30 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock
222
230
len -= ret;
223
231
data += ret;
224
232
} else if (ret == 0 ) { // Unexpected disconnection
225
- return false ;
233
+ return IntrRecvError::Disconnected ;
226
234
} else { // Other error or blocking
227
235
int nErr = WSAGetLastError ();
228
236
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
229
237
if (!IsSelectableSocket (hSocket)) {
230
- return false ;
238
+ return IntrRecvError::NetworkError ;
231
239
}
232
240
struct timeval tval = MillisToTimeval (std::min (endTime - curTime, maxWait));
233
241
fd_set fdset;
234
242
FD_ZERO (&fdset);
235
243
FD_SET (hSocket, &fdset);
236
244
int nRet = select (hSocket + 1 , &fdset, NULL , NULL , &tval);
237
245
if (nRet == SOCKET_ERROR) {
238
- return false ;
246
+ return IntrRecvError::NetworkError ;
239
247
}
240
248
} else {
241
- return false ;
249
+ return IntrRecvError::NetworkError ;
242
250
}
243
251
}
244
252
if (interruptSocks5Recv)
245
- return false ;
253
+ return IntrRecvError::Interrupted ;
246
254
curTime = GetTimeMillis ();
247
255
}
248
- return len == 0 ;
256
+ return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout ;
249
257
}
250
258
251
259
struct ProxyCredentials
@@ -272,6 +280,7 @@ std::string Socks5ErrorString(int err)
272
280
/* * Connect using SOCKS5 (as described in RFC1928) */
273
281
static bool Socks5 (const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
274
282
{
283
+ IntrRecvError recvr;
275
284
LogPrint (" net" , " SOCKS5 connecting %s\n " , strDest);
276
285
if (strDest.size () > 255 ) {
277
286
CloseSocket (hSocket);
@@ -294,7 +303,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
294
303
return error (" Error sending to proxy" );
295
304
}
296
305
char pchRet1[2 ];
297
- if (! InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
306
+ if ((recvr = InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
298
307
CloseSocket (hSocket);
299
308
LogPrintf (" Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n " , strDest, port);
300
309
return false ;
@@ -320,7 +329,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
320
329
}
321
330
LogPrint (" proxy" , " SOCKS5 sending proxy authentication %s:%s\n " , auth->username , auth->password );
322
331
char pchRetA[2 ];
323
- if (! InterruptibleRecv (pchRetA, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
332
+ if ((recvr = InterruptibleRecv (pchRetA, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
324
333
CloseSocket (hSocket);
325
334
return error (" Error reading proxy authentication response" );
326
335
}
@@ -349,9 +358,9 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
349
358
return error (" Error sending to proxy" );
350
359
}
351
360
char pchRet2[4 ];
352
- if (! InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket)) {
361
+ if ((recvr = InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
353
362
CloseSocket (hSocket);
354
- return error (" Error reading proxy response" );
363
+ return error (" Error while reading proxy response" );
355
364
}
356
365
if (pchRet2[0 ] != 0x05 ) {
357
366
CloseSocket (hSocket);
@@ -370,26 +379,26 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
370
379
char pchRet3[256 ];
371
380
switch (pchRet2[3 ])
372
381
{
373
- case 0x01 : ret = InterruptibleRecv (pchRet3, 4 , SOCKS5_RECV_TIMEOUT, hSocket); break ;
374
- case 0x04 : ret = InterruptibleRecv (pchRet3, 16 , SOCKS5_RECV_TIMEOUT, hSocket); break ;
382
+ case 0x01 : recvr = InterruptibleRecv (pchRet3, 4 , SOCKS5_RECV_TIMEOUT, hSocket); break ;
383
+ case 0x04 : recvr = InterruptibleRecv (pchRet3, 16 , SOCKS5_RECV_TIMEOUT, hSocket); break ;
375
384
case 0x03 :
376
385
{
377
- ret = InterruptibleRecv (pchRet3, 1 , SOCKS5_RECV_TIMEOUT, hSocket);
378
- if (!ret ) {
386
+ recvr = InterruptibleRecv (pchRet3, 1 , SOCKS5_RECV_TIMEOUT, hSocket);
387
+ if (recvr != IntrRecvError::OK ) {
379
388
CloseSocket (hSocket);
380
389
return error (" Error reading from proxy" );
381
390
}
382
391
int nRecv = pchRet3[0 ];
383
- ret = InterruptibleRecv (pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
392
+ recvr = InterruptibleRecv (pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
384
393
break ;
385
394
}
386
395
default : CloseSocket (hSocket); return error (" Error: malformed proxy response" );
387
396
}
388
- if (!ret ) {
397
+ if (recvr != IntrRecvError::OK ) {
389
398
CloseSocket (hSocket);
390
399
return error (" Error reading from proxy" );
391
400
}
392
- if (! InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
401
+ if ((recvr = InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK ) {
393
402
CloseSocket (hSocket);
394
403
return error (" Error reading from proxy" );
395
404
}
0 commit comments