mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-21 11:20:49 +08:00
Merge pull request #597 from Qv2ray/dev-nonblock-TCPing
add nonblocking TCPing
This commit is contained in:
commit
6b472840b6
@ -1 +1 @@
|
|||||||
5366
|
5367
|
@ -2,7 +2,9 @@
|
|||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
#else
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -11,6 +13,110 @@
|
|||||||
#include "QvTCPing.hpp"
|
#include "QvTCPing.hpp"
|
||||||
#include "core/handler/ConfigHandler.hpp"
|
#include "core/handler/ConfigHandler.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
using qv_socket_t = SOCKET;
|
||||||
|
#else
|
||||||
|
using qv_socket_t = int;
|
||||||
|
#endif
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
inline int setnonblocking(qv_socket_t sockno, int &opt)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
ULONG block = 1;
|
||||||
|
if (ioctlsocket(sockno, FIONBIO, &block) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((opt = fcntl(sockno, F_GETFL, NULL)) < 0)
|
||||||
|
{
|
||||||
|
// get socket flags
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fcntl(sockno, F_SETFL, opt | O_NONBLOCK) < 0)
|
||||||
|
{
|
||||||
|
// set socket non-blocking
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int setblocking(qv_socket_t sockno, int &opt)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
ULONG block = 0;
|
||||||
|
if (ioctlsocket(sockno, FIONBIO, &block) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (fcntl(sockno, F_SETFL, opt) < 0)
|
||||||
|
{
|
||||||
|
// reset socket flags
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect_wait(qv_socket_t sockno, struct sockaddr *addr, size_t addrlen, int timeout_sec = 5)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int opt;
|
||||||
|
timeval tv = { 0 };
|
||||||
|
tv.tv_sec = timeout_sec;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
if ((res = setnonblocking(sockno, opt)) != 0)
|
||||||
|
return -1;
|
||||||
|
if ((res = ::connect(sockno, addr, addrlen)) < 0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
if (errno == EINPROGRESS)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
// connecting
|
||||||
|
fd_set wait_set;
|
||||||
|
FD_ZERO(&wait_set);
|
||||||
|
FD_SET(sockno, &wait_set);
|
||||||
|
res = select(sockno + 1, NULL, &wait_set, NULL, &tv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// connect immediately
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
if (setblocking(sockno, opt) != 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
// an error occured
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (res == 0)
|
||||||
|
{
|
||||||
|
// timeout
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
socklen_t len = sizeof(opt);
|
||||||
|
if (getsockopt(sockno, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&opt), &len) < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace Qv2ray::components::tcping
|
namespace Qv2ray::components::tcping
|
||||||
{
|
{
|
||||||
static int resolveHost(const std::string &host, int portnr, struct addrinfo **res);
|
static int resolveHost(const std::string &host, int portnr, struct addrinfo **res);
|
||||||
@ -159,11 +265,8 @@ namespace Qv2ray::components::tcping
|
|||||||
|
|
||||||
int testLatency(struct addrinfo *addr, std::chrono::system_clock::time_point *start, std::chrono::system_clock::time_point *end)
|
int testLatency(struct addrinfo *addr, std::chrono::system_clock::time_point *start, std::chrono::system_clock::time_point *end)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
qv_socket_t fd;
|
||||||
SOCKET fd;
|
|
||||||
#else
|
|
||||||
int fd;
|
|
||||||
#endif
|
|
||||||
const int on = 1;
|
const int on = 1;
|
||||||
/* int flags; */
|
/* int flags; */
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
@ -198,7 +301,7 @@ namespace Qv2ray::components::tcping
|
|||||||
/* connect to peer */
|
/* connect to peer */
|
||||||
// Qt has its own connect() function in QObject....
|
// Qt has its own connect() function in QObject....
|
||||||
// So we add "::" here
|
// So we add "::" here
|
||||||
if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0)
|
if (connect_wait(fd, addr->ai_addr, addr->ai_addrlen) == 0)
|
||||||
{
|
{
|
||||||
*end = system_clock::now();
|
*end = system_clock::now();
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
Loading…
Reference in New Issue
Block a user