mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-26 19:39:53 +03:00
Merge pull request #1512 from domosekai/he
Perform TCP connection via IPv6 and IPv4 in parallel threads
This commit is contained in:
commit
2a40d21ef9
@ -6403,7 +6403,7 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
|
|||||||
|
|
||||||
if (additional_connect == false || IsZeroIP(&sock->RemoteIP))
|
if (additional_connect == false || IsZeroIP(&sock->RemoteIP))
|
||||||
{
|
{
|
||||||
if (((sock->IsRUDPSocket || sock->IPv6) && IsZeroIP(&sock->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, hostname) == false)
|
if (IsZeroIP(&sock->RemoteIP) == false || (sock->IPv6 && GetIP6(&c->Session->ServerIP, hostname) == false) || (sock->IPv6 == false && GetIP4(&c->Session->ServerIP, hostname) == false))
|
||||||
{
|
{
|
||||||
Copy(&c->Session->ServerIP, &sock->RemoteIP, sizeof(c->Session->ServerIP));
|
Copy(&c->Session->ServerIP, &sock->RemoteIP, sizeof(c->Session->ServerIP));
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,8 @@ void DnsFree()
|
|||||||
{
|
{
|
||||||
DNS_CACHE *entry = LIST_DATA(cache, i);
|
DNS_CACHE *entry = LIST_DATA(cache, i);
|
||||||
Free((void *)entry->Hostname);
|
Free((void *)entry->Hostname);
|
||||||
|
FreeHostIPAddressList(entry->IPList_v6);
|
||||||
|
FreeHostIPAddressList(entry->IPList_v4);
|
||||||
Free(entry);
|
Free(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,6 +155,35 @@ DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIST *iplist_v6 = NULL;
|
||||||
|
LIST *iplist_v4 = NULL;
|
||||||
|
|
||||||
|
if (ipv6 != NULL)
|
||||||
|
{
|
||||||
|
iplist_v6 = NewListFast(NULL);
|
||||||
|
AddHostIPAddressToList(iplist_v6, ipv6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipv4 != NULL)
|
||||||
|
{
|
||||||
|
iplist_v4 = NewListFast(NULL);
|
||||||
|
AddHostIPAddressToList(iplist_v4, ipv4);
|
||||||
|
}
|
||||||
|
|
||||||
|
DNS_CACHE *ret = DnsCacheUpdateEx(hostname, iplist_v6, iplist_v4);
|
||||||
|
|
||||||
|
FreeHostIPAddressList(iplist_v6);
|
||||||
|
FreeHostIPAddressList(iplist_v4);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
DNS_CACHE *DnsCacheUpdateEx(const char *hostname, const LIST *iplist_v6, const LIST *iplist_v4)
|
||||||
|
{
|
||||||
|
if (DnsCacheIsEnabled() == false || IsEmptyStr(hostname))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DNS_CACHE *entry;
|
DNS_CACHE *entry;
|
||||||
|
|
||||||
LockList(cache);
|
LockList(cache);
|
||||||
@ -161,11 +192,14 @@ DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4)
|
|||||||
t.Hostname = hostname;
|
t.Hostname = hostname;
|
||||||
entry = Search(cache, &t);
|
entry = Search(cache, &t);
|
||||||
|
|
||||||
if (ipv6 == NULL && ipv4 == NULL)
|
if (iplist_v6 == NULL && iplist_v4 == NULL)
|
||||||
{
|
{
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
Delete(cache, entry);
|
Delete(cache, entry);
|
||||||
|
Free((void *)entry->Hostname);
|
||||||
|
FreeHostIPAddressList(entry->IPList_v6);
|
||||||
|
FreeHostIPAddressList(entry->IPList_v4);
|
||||||
Free(entry);
|
Free(entry);
|
||||||
entry = NULL;
|
entry = NULL;
|
||||||
}
|
}
|
||||||
@ -182,19 +216,25 @@ DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4)
|
|||||||
|
|
||||||
entry->Expiration = Tick64();
|
entry->Expiration = Tick64();
|
||||||
|
|
||||||
if (ipv6 != NULL)
|
FreeHostIPAddressList(entry->IPList_v6);
|
||||||
|
FreeHostIPAddressList(entry->IPList_v4);
|
||||||
|
|
||||||
|
if (iplist_v6 != NULL)
|
||||||
{
|
{
|
||||||
if (CmpIpAddr(&entry->IPv6, ipv6) != 0)
|
entry->IPList_v6 = CloneIPAddressList(iplist_v6);
|
||||||
{
|
|
||||||
Copy(&entry->IPv6, ipv6, sizeof(entry->IPv6));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (CmpIpAddr(&entry->IPv4, ipv4) != 0)
|
entry->IPList_v6 = NULL;
|
||||||
{
|
|
||||||
Copy(&entry->IPv4, ipv4, sizeof(entry->IPv4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iplist_v4 != NULL)
|
||||||
|
{
|
||||||
|
entry->IPList_v4 = CloneIPAddressList(iplist_v4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry->IPList_v4 = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +265,7 @@ DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip)
|
|||||||
|
|
||||||
DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname)
|
DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname)
|
||||||
{
|
{
|
||||||
if (DnsCacheIsEnabled() == false || IsZeroIP(&ip))
|
if (DnsCacheIsEnabled() == false || IsZeroIP(ip))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -278,10 +318,50 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIST *iplist_v6 = NewListFast(NULL);
|
||||||
|
LIST *iplist_v4 = NewListFast(NULL);
|
||||||
|
|
||||||
|
bool ret = DnsResolveEx(iplist_v6, iplist_v4, hostname, timeout, cancel_flag);
|
||||||
|
|
||||||
|
if (ipv6 != NULL && LIST_NUM(iplist_v6) > 0)
|
||||||
|
{
|
||||||
|
IP *ip = LIST_DATA(iplist_v6, 0);
|
||||||
|
Copy(ipv6, ip, sizeof(IP));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Zero(ipv6, sizeof(ipv6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipv4 != NULL && LIST_NUM(iplist_v4) > 0)
|
||||||
|
{
|
||||||
|
IP *ip = LIST_DATA(iplist_v4, 0);
|
||||||
|
Copy(ipv4, ip, sizeof(IP));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ZeroIP4(ipv4);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeHostIPAddressList(iplist_v6);
|
||||||
|
FreeHostIPAddressList(iplist_v4);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag)
|
||||||
|
{
|
||||||
|
if (iplist_v6 == NULL || iplist_v4 == NULL || IsEmptyStr(hostname))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (StrCmpi(hostname, "localhost") == 0)
|
if (StrCmpi(hostname, "localhost") == 0)
|
||||||
{
|
{
|
||||||
GetLocalHostIP6(ipv6);
|
IP ipv6, ipv4;
|
||||||
GetLocalHostIP4(ipv4);
|
GetLocalHostIP6(&ipv6);
|
||||||
|
GetLocalHostIP4(&ipv4);
|
||||||
|
AddHostIPAddressToList(iplist_v6, &ipv6);
|
||||||
|
AddHostIPAddressToList(iplist_v4, &ipv4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,22 +370,14 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
|
|||||||
{
|
{
|
||||||
if (IsIP6(&ip))
|
if (IsIP6(&ip))
|
||||||
{
|
{
|
||||||
if (ipv6 != NULL)
|
AddHostIPAddressToList(iplist_v6, &ip);
|
||||||
{
|
|
||||||
ZeroIP4(ipv4);
|
|
||||||
Copy(ipv6, &ip, sizeof(IP));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ipv4 != NULL)
|
AddHostIPAddressToList(iplist_v4, &ip);
|
||||||
{
|
|
||||||
Zero(ipv6, sizeof(IP));
|
|
||||||
Copy(ipv4, &ip, sizeof(IP));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -332,7 +404,8 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
|
|||||||
|
|
||||||
DNS_RESOLVER resolver;
|
DNS_RESOLVER resolver;
|
||||||
Zero(&resolver, sizeof(resolver));
|
Zero(&resolver, sizeof(resolver));
|
||||||
ZeroIP4(&resolver.IPv4);
|
resolver.IPList_v6 = iplist_v6;
|
||||||
|
resolver.IPList_v4 = iplist_v4;
|
||||||
resolver.Hostname = hostname;
|
resolver.Hostname = hostname;
|
||||||
|
|
||||||
THREAD *worker = NewThread(DnsResolver, &resolver);
|
THREAD *worker = NewThread(DnsResolver, &resolver);
|
||||||
@ -368,10 +441,7 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
|
|||||||
|
|
||||||
if (resolver.OK)
|
if (resolver.OK)
|
||||||
{
|
{
|
||||||
Copy(ipv6, &resolver.IPv6, sizeof(IP));
|
DnsCacheUpdateEx(hostname, iplist_v6, iplist_v4);
|
||||||
Copy(ipv4, &resolver.IPv4, sizeof(IP));
|
|
||||||
|
|
||||||
DnsCacheUpdate(hostname, ipv6, ipv4);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -384,8 +454,19 @@ CACHE:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(ipv6, &cached->IPv6, sizeof(IP));
|
UINT i;
|
||||||
Copy(ipv4, &cached->IPv4, sizeof(IP));
|
|
||||||
|
for (i = 0; i < LIST_NUM(cached->IPList_v6); ++i)
|
||||||
|
{
|
||||||
|
IP *ip = LIST_DATA(cached->IPList_v6, i);
|
||||||
|
AddHostIPAddressToList(iplist_v6, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(cached->IPList_v4); ++i)
|
||||||
|
{
|
||||||
|
IP *ip = LIST_DATA(cached->IPList_v4, i);
|
||||||
|
AddHostIPAddressToList(iplist_v4, ip);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -428,24 +509,16 @@ void DnsResolver(THREAD *t, void *param)
|
|||||||
{
|
{
|
||||||
const struct sockaddr_in6 *in = (struct sockaddr_in6 *)result->ai_addr;
|
const struct sockaddr_in6 *in = (struct sockaddr_in6 *)result->ai_addr;
|
||||||
InAddrToIP6(&ip, &in->sin6_addr);
|
InAddrToIP6(&ip, &in->sin6_addr);
|
||||||
if (IsIP6(&ip) && ipv6_ok == false)
|
if (IsIP6(&ip))
|
||||||
{
|
{
|
||||||
Copy(&resolver->IPv6, &ip, sizeof(resolver->IPv6));
|
ip.ipv6_scope_id = in->sin6_scope_id;
|
||||||
resolver->IPv6.ipv6_scope_id = in->sin6_scope_id;
|
AddHostIPAddressToList(resolver->IPList_v6, &ip);
|
||||||
ipv6_ok = true;
|
ipv6_ok = true;
|
||||||
if (ipv4_ok)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else if (IsIP4(&ip))
|
||||||
else if (IsIP4(&ip) && ipv4_ok == false)
|
|
||||||
{
|
{
|
||||||
Copy(&resolver->IPv4, &ip, sizeof(resolver->IPv4));
|
AddHostIPAddressToList(resolver->IPList_v4, &ip);
|
||||||
ipv4_ok = true;
|
ipv4_ok = true;
|
||||||
if (ipv6_ok)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -454,9 +527,8 @@ void DnsResolver(THREAD *t, void *param)
|
|||||||
InAddrToIP(&ip, &in->sin_addr);
|
InAddrToIP(&ip, &in->sin_addr);
|
||||||
if (IsIP4(&ip))
|
if (IsIP4(&ip))
|
||||||
{
|
{
|
||||||
Copy(&resolver->IPv4, &ip, sizeof(resolver->IPv4));
|
AddHostIPAddressToList(resolver->IPList_v4, &ip);
|
||||||
ipv4_ok = true;
|
ipv4_ok = true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
struct DNS_CACHE
|
struct DNS_CACHE
|
||||||
{
|
{
|
||||||
const char *Hostname;
|
const char *Hostname;
|
||||||
IP IPv4;
|
LIST *IPList_v4;
|
||||||
IP IPv6;
|
LIST *IPList_v6;
|
||||||
UINT64 Expiration;
|
UINT64 Expiration;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ struct DNS_CACHE_REVERSE
|
|||||||
struct DNS_RESOLVER
|
struct DNS_RESOLVER
|
||||||
{
|
{
|
||||||
const char *Hostname;
|
const char *Hostname;
|
||||||
IP IPv4;
|
LIST *IPList_v4;
|
||||||
IP IPv6;
|
LIST *IPList_v6;
|
||||||
bool OK;
|
bool OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,11 +63,13 @@ void DnsCacheToggle(const bool enabled);
|
|||||||
|
|
||||||
DNS_CACHE *DnsCacheFind(const char *hostname);
|
DNS_CACHE *DnsCacheFind(const char *hostname);
|
||||||
DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4);
|
DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4);
|
||||||
|
DNS_CACHE *DnsCacheUpdateEx(const char *hostname, const LIST *iplist_v6, const LIST *iplist_v4);
|
||||||
|
|
||||||
DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip);
|
DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip);
|
||||||
DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname);
|
DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname);
|
||||||
|
|
||||||
bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
|
bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
|
||||||
|
bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
|
||||||
void DnsResolver(THREAD *t, void *param);
|
void DnsResolver(THREAD *t, void *param);
|
||||||
|
|
||||||
bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag);
|
bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag);
|
||||||
|
@ -380,6 +380,7 @@ typedef struct RUDP_STACK RUDP_STACK;
|
|||||||
typedef struct RUDP_SOURCE_IP RUDP_SOURCE_IP;
|
typedef struct RUDP_SOURCE_IP RUDP_SOURCE_IP;
|
||||||
typedef struct RUDP_SESSION RUDP_SESSION;
|
typedef struct RUDP_SESSION RUDP_SESSION;
|
||||||
typedef struct RUDP_SEGMENT RUDP_SEGMENT;
|
typedef struct RUDP_SEGMENT RUDP_SEGMENT;
|
||||||
|
typedef struct CONNECT_SERIAL_PARAM CONNECT_SERIAL_PARAM;
|
||||||
typedef struct CONNECT_TCP_RUDP_PARAM CONNECT_TCP_RUDP_PARAM;
|
typedef struct CONNECT_TCP_RUDP_PARAM CONNECT_TCP_RUDP_PARAM;
|
||||||
typedef struct TCP_PAIR_HEADER TCP_PAIR_HEADER;
|
typedef struct TCP_PAIR_HEADER TCP_PAIR_HEADER;
|
||||||
typedef struct NIC_ENTRY NIC_ENTRY;
|
typedef struct NIC_ENTRY NIC_ENTRY;
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
#ifdef UNIX_SOLARIS
|
#ifdef UNIX_SOLARIS
|
||||||
#define USE_STATVFS
|
#define USE_STATVFS
|
||||||
#include <sys/statvfs.h>'
|
#include <sys/statvfs.h>
|
||||||
#else
|
#else
|
||||||
#define MAYAQUA_SUPPORTS_GETIFADDRS
|
#define MAYAQUA_SUPPORTS_GETIFADDRS
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
@ -13880,163 +13880,73 @@ void ConnectThreadForRUDP(THREAD *thread, void *param)
|
|||||||
Set(p->FinishEvent);
|
Set(p->FinishEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCP connection
|
// IPv4 connection thread (multiple protocols, multiple addresses)
|
||||||
SOCK *Connect(char *hostname, UINT port)
|
void ConnectThreadForIPv4(THREAD *thread, void *param)
|
||||||
{
|
{
|
||||||
return ConnectEx(hostname, port, 0);
|
SOCKET s = INVALID_SOCKET;
|
||||||
}
|
|
||||||
SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
|
|
||||||
{
|
|
||||||
return ConnectEx2(hostname, port, timeout, NULL);
|
|
||||||
}
|
|
||||||
SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
|
|
||||||
{
|
|
||||||
return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, true);
|
|
||||||
}
|
|
||||||
SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname)
|
|
||||||
{
|
|
||||||
return ConnectEx4(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL);
|
|
||||||
}
|
|
||||||
SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip)
|
|
||||||
{
|
|
||||||
SOCK *sock;
|
|
||||||
SOCKET s;
|
|
||||||
struct linger ling;
|
|
||||||
IP ip4;
|
|
||||||
IP ip6;
|
|
||||||
char tmp[MAX_SIZE];
|
|
||||||
IP current_ip;
|
IP current_ip;
|
||||||
bool is_ipv6 = false;
|
UINT i;
|
||||||
bool dummy = false;
|
CONNECT_SERIAL_PARAM *p = (CONNECT_SERIAL_PARAM *)param;
|
||||||
bool use_natt = false;
|
if (thread == NULL || p == NULL)
|
||||||
char hostname_original[MAX_SIZE];
|
|
||||||
char hint_str[MAX_SIZE];
|
|
||||||
bool force_use_natt = false;
|
|
||||||
UINT dummy_int = 0;
|
|
||||||
IP dummy_ret_ip;
|
|
||||||
// Validate arguments
|
|
||||||
if (hostname == NULL || port == 0 || port >= 65536 || IsEmptyStr(hostname))
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return;
|
||||||
}
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
timeout = TIMEOUT_TCP_PORT_CHECK;
|
|
||||||
}
|
|
||||||
if (cancel_flag == NULL)
|
|
||||||
{
|
|
||||||
cancel_flag = &dummy;
|
|
||||||
}
|
|
||||||
if (nat_t_error_code == NULL)
|
|
||||||
{
|
|
||||||
nat_t_error_code = &dummy_int;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Zero(&dummy_ret_ip, sizeof(IP));
|
// Delay before start
|
||||||
if (ret_ip == NULL)
|
if (p->Delay >= 1)
|
||||||
{
|
{
|
||||||
ret_ip = &dummy_ret_ip;
|
WaitEx(NULL, p->Delay, p->NoDelayFlag);
|
||||||
}
|
|
||||||
|
|
||||||
Zero(hint_str, sizeof(hint_str));
|
|
||||||
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
|
||||||
|
|
||||||
use_natt = (IsEmptyStr(nat_t_svc_name) ? false : true);
|
|
||||||
|
|
||||||
if (use_natt)
|
|
||||||
{
|
|
||||||
// In case of using NAT-T, split host name if the '/' is included in the host name
|
|
||||||
UINT i = SearchStrEx(hostname, "/", 0, false);
|
|
||||||
|
|
||||||
if (i == INFINITE)
|
|
||||||
{
|
|
||||||
// Not included
|
|
||||||
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Included
|
|
||||||
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
|
||||||
hostname_original[i] = 0;
|
|
||||||
|
|
||||||
// Force to use the NAT-T
|
|
||||||
force_use_natt = true;
|
|
||||||
|
|
||||||
// Copy the hint string
|
|
||||||
StrCpy(hint_str, sizeof(hint_str), hostname + i + 1);
|
|
||||||
|
|
||||||
if (StrCmpi(hint_str, "tcp") == 0 || StrCmpi(hint_str, "disable") == 0
|
|
||||||
|| StrCmpi(hint_str, "disabled") == 0
|
|
||||||
|| StrCmpi(hint_str, "no") == 0 || StrCmpi(hint_str, "none") == 0)
|
|
||||||
{
|
|
||||||
// Force not to use the NAT-T
|
|
||||||
force_use_natt = false;
|
|
||||||
use_natt = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Zero(¤t_ip, sizeof(current_ip));
|
Zero(¤t_ip, sizeof(current_ip));
|
||||||
|
|
||||||
Zero(&ip4, sizeof(ip4));
|
for (i = 0; i < LIST_NUM(p->IpList); ++i)
|
||||||
Zero(&ip6, sizeof(ip6));
|
{
|
||||||
|
IP *ip = LIST_DATA(p->IpList, i);
|
||||||
|
|
||||||
if (IsZeroIp(ret_ip) == false)
|
if (IsZeroIp(ip))
|
||||||
{
|
{
|
||||||
// Skip name resolution
|
continue;
|
||||||
if (IsIP6(ret_ip))
|
|
||||||
{
|
|
||||||
Copy(&ip6, ret_ip, sizeof(IP));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Copy(&ip4, ret_ip, sizeof(IP));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Debug("Using cached IP address: %s = %r\n", hostname_original, ret_ip);
|
// Delay before retry
|
||||||
}
|
if (i > 0 && p->RetryDelay >= 1)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Forward resolution
|
WaitEx(NULL, p->RetryDelay, p->CancelFlag);
|
||||||
if (DnsResolve(&ip6, &ip4, hostname_original, 0, cancel_flag) == false)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsZeroIp(&ip4) == false && IsIPLocalHostOrMySelf(&ip4))
|
if (*p->CancelFlag)
|
||||||
|
{
|
||||||
|
// Cancel by the user
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool use_natt = p->Use_NatT;
|
||||||
|
bool force_use_natt = p->Force_NatT;
|
||||||
|
|
||||||
|
if (IsIPLocalHostOrMySelf(ip))
|
||||||
{
|
{
|
||||||
// NAT-T isn't used in the case of connection to localhost
|
// NAT-T isn't used in the case of connection to localhost
|
||||||
force_use_natt = false;
|
force_use_natt = false;
|
||||||
use_natt = false;
|
use_natt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = INVALID_SOCKET;
|
|
||||||
|
|
||||||
// Attempt to connect with IPv4
|
|
||||||
if (IsZeroIp(&ip4) == false)
|
|
||||||
{
|
|
||||||
if (use_natt == false)
|
if (use_natt == false)
|
||||||
{
|
{
|
||||||
// Normal connection without using NAT-T
|
// Normal connection without using NAT-T
|
||||||
s = ConnectTimeoutIPv4(&ip4, port, timeout, cancel_flag);
|
s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag);
|
||||||
|
|
||||||
if (s != INVALID_SOCKET)
|
if (s != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
Copy(¤t_ip, &ip4, sizeof(IP));
|
Copy(¤t_ip, ip, sizeof(IP));
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (force_use_natt)
|
else if (force_use_natt)
|
||||||
{
|
{
|
||||||
// The connection by forcing the use of NAT-T (not to connection with normal TCP)
|
// The connection by forcing the use of NAT-T (not to connection with normal TCP)
|
||||||
SOCK *nat_t_sock = NewRUDPClientNatT(nat_t_svc_name, &ip4, nat_t_error_code, timeout, cancel_flag,
|
SOCK *nat_t_sock = NewRUDPClientNatT(p->NatT_SvcName, ip, p->NatT_ErrorCode, p->Timeout, p->CancelFlag, p->HintStr, p->Hostname);
|
||||||
hint_str, hostname);
|
|
||||||
|
|
||||||
if (nat_t_sock != NULL)
|
if (nat_t_sock != NULL)
|
||||||
{
|
{
|
||||||
@ -14044,9 +13954,10 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
AddProtocolDetailsStr(nat_t_sock->ProtocolDetails, sizeof(nat_t_sock->ProtocolDetails), "RUDP");
|
AddProtocolDetailsStr(nat_t_sock->ProtocolDetails, sizeof(nat_t_sock->ProtocolDetails), "RUDP");
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
return nat_t_sock;
|
p->Sock = nat_t_sock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -14068,47 +13979,47 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
Zero(&p4, sizeof(p4));
|
Zero(&p4, sizeof(p4));
|
||||||
|
|
||||||
// p1: TCP
|
// p1: TCP
|
||||||
StrCpy(p1.Hostname, sizeof(p1.Hostname), hostname_original);
|
StrCpy(p1.Hostname, sizeof(p1.Hostname), p->Hostname_Original);
|
||||||
Copy(&p1.Ip, &ip4, sizeof(IP));
|
Copy(&p1.Ip, ip, sizeof(IP));
|
||||||
p1.Port = port;
|
p1.Port = p->Port;
|
||||||
p1.Timeout = timeout;
|
p1.Timeout = p->Timeout;
|
||||||
p1.CancelFlag = &cancel_flag2;
|
p1.CancelFlag = &cancel_flag2;
|
||||||
p1.FinishEvent = finish_event;
|
p1.FinishEvent = finish_event;
|
||||||
p1.Tcp_TryStartSsl = try_start_ssl;
|
p1.Tcp_TryStartSsl = p->Tcp_TryStartSsl;
|
||||||
p1.CancelLock = NewLock();
|
p1.CancelLock = NewLock();
|
||||||
|
|
||||||
// p2: NAT-T
|
// p2: NAT-T
|
||||||
StrCpy(p2.Hostname, sizeof(p2.Hostname), hostname_original);
|
StrCpy(p2.Hostname, sizeof(p2.Hostname), p->Hostname_Original);
|
||||||
Copy(&p2.Ip, &ip4, sizeof(IP));
|
Copy(&p2.Ip, ip, sizeof(IP));
|
||||||
p2.Port = port;
|
p2.Port = p->Port;
|
||||||
p2.Timeout = timeout;
|
p2.Timeout = p->Timeout;
|
||||||
p2.CancelFlag = &cancel_flag2;
|
p2.CancelFlag = &cancel_flag2;
|
||||||
p2.FinishEvent = finish_event;
|
p2.FinishEvent = finish_event;
|
||||||
|
|
||||||
StrCpy(p2.HintStr, sizeof(p2.HintStr), hint_str);
|
StrCpy(p2.HintStr, sizeof(p2.HintStr), p->HintStr);
|
||||||
StrCpy(p2.TargetHostname, sizeof(p2.TargetHostname), hostname);
|
StrCpy(p2.TargetHostname, sizeof(p2.TargetHostname), p->Hostname);
|
||||||
StrCpy(p2.SvcName, sizeof(p2.SvcName), nat_t_svc_name);
|
StrCpy(p2.SvcName, sizeof(p2.SvcName), p->NatT_SvcName);
|
||||||
p2.Delay = 30; // Delay by 30ms
|
p2.Delay = 30; // Delay by 30ms
|
||||||
|
|
||||||
// p3: over ICMP
|
// p3: over ICMP
|
||||||
StrCpy(p3.Hostname, sizeof(p3.Hostname), hostname_original);
|
StrCpy(p3.Hostname, sizeof(p3.Hostname), p->Hostname_Original);
|
||||||
Copy(&p3.Ip, &ip4, sizeof(IP));
|
Copy(&p3.Ip, ip, sizeof(IP));
|
||||||
p3.Port = port;
|
p3.Port = p->Port;
|
||||||
p3.Timeout = timeout;
|
p3.Timeout = p->Timeout;
|
||||||
p3.CancelFlag = &cancel_flag2;
|
p3.CancelFlag = &cancel_flag2;
|
||||||
p3.FinishEvent = finish_event;
|
p3.FinishEvent = finish_event;
|
||||||
StrCpy(p3.SvcName, sizeof(p3.SvcName), nat_t_svc_name);
|
StrCpy(p3.SvcName, sizeof(p3.SvcName), p->NatT_SvcName);
|
||||||
p3.RUdpProtocol = RUDP_PROTOCOL_ICMP;
|
p3.RUdpProtocol = RUDP_PROTOCOL_ICMP;
|
||||||
p3.Delay = 200; // Delay by 200ms
|
p3.Delay = 200; // Delay by 200ms
|
||||||
|
|
||||||
// p4: over DNS
|
// p4: over DNS
|
||||||
StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname_original);
|
StrCpy(p4.Hostname, sizeof(p4.Hostname), p->Hostname_Original);
|
||||||
Copy(&p4.Ip, &ip4, sizeof(IP));
|
Copy(&p4.Ip, ip, sizeof(IP));
|
||||||
p4.Port = port;
|
p4.Port = p->Port;
|
||||||
p4.Timeout = timeout;
|
p4.Timeout = p->Timeout;
|
||||||
p4.CancelFlag = &cancel_flag2;
|
p4.CancelFlag = &cancel_flag2;
|
||||||
p4.FinishEvent = finish_event;
|
p4.FinishEvent = finish_event;
|
||||||
StrCpy(p4.SvcName, sizeof(p4.SvcName), nat_t_svc_name);
|
StrCpy(p4.SvcName, sizeof(p4.SvcName), p->NatT_SvcName);
|
||||||
p4.RUdpProtocol = RUDP_PROTOCOL_DNS;
|
p4.RUdpProtocol = RUDP_PROTOCOL_DNS;
|
||||||
p4.Delay = 100; // Delay by 100ms
|
p4.Delay = 100; // Delay by 100ms
|
||||||
|
|
||||||
@ -14121,7 +14032,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
{
|
{
|
||||||
UINT64 now = Tick64();
|
UINT64 now = Tick64();
|
||||||
|
|
||||||
if (*cancel_flag)
|
if (*p->CancelFlag)
|
||||||
{
|
{
|
||||||
// Cancel by the user
|
// Cancel by the user
|
||||||
break;
|
break;
|
||||||
@ -14219,7 +14130,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
|
|
||||||
DeleteLock(p1.CancelLock);
|
DeleteLock(p1.CancelLock);
|
||||||
|
|
||||||
if (*cancel_flag)
|
if (*p->CancelFlag)
|
||||||
{
|
{
|
||||||
// Abandon all the results because the user canceled
|
// Abandon all the results because the user canceled
|
||||||
Disconnect(p1.Result_Nat_T_Sock);
|
Disconnect(p1.Result_Nat_T_Sock);
|
||||||
@ -14231,7 +14142,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
Disconnect(p4.Result_Nat_T_Sock);
|
Disconnect(p4.Result_Nat_T_Sock);
|
||||||
ReleaseSock(p4.Result_Nat_T_Sock);
|
ReleaseSock(p4.Result_Nat_T_Sock);
|
||||||
|
|
||||||
return NULL;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p1.Ok)
|
if (p1.Ok)
|
||||||
@ -14247,15 +14158,16 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
Disconnect(p4.Result_Nat_T_Sock);
|
Disconnect(p4.Result_Nat_T_Sock);
|
||||||
ReleaseSock(p4.Result_Nat_T_Sock);
|
ReleaseSock(p4.Result_Nat_T_Sock);
|
||||||
|
|
||||||
if (GetHostName(hostname, sizeof(hostname), &ip4))
|
if (GetHostName(hostname, sizeof(hostname), ip))
|
||||||
{
|
{
|
||||||
Free(p1.Result_Tcp_Sock->RemoteHostname);
|
Free(p1.Result_Tcp_Sock->RemoteHostname);
|
||||||
p1.Result_Tcp_Sock->RemoteHostname = CopyStr(hostname);
|
p1.Result_Tcp_Sock->RemoteHostname = CopyStr(hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
return p1.Result_Tcp_Sock;
|
p->Sock = p1.Result_Tcp_Sock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (p2.Ok)
|
else if (p2.Ok)
|
||||||
{
|
{
|
||||||
@ -14269,9 +14181,10 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
StrCpy(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
|
StrCpy(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
|
||||||
AddProtocolDetailsStr(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/UDP");
|
AddProtocolDetailsStr(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/UDP");
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
return p2.Result_Nat_T_Sock;
|
p->Sock = p2.Result_Nat_T_Sock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (p4.Ok)
|
else if (p4.Ok)
|
||||||
{
|
{
|
||||||
@ -14283,9 +14196,10 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
StrCpy(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_DNS);
|
StrCpy(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_DNS);
|
||||||
AddProtocolDetailsStr(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/DNS");
|
AddProtocolDetailsStr(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/DNS");
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
return p4.Result_Nat_T_Sock;
|
p->Sock = p4.Result_Nat_T_Sock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (p3.Ok)
|
else if (p3.Ok)
|
||||||
{
|
{
|
||||||
@ -14293,21 +14207,73 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
StrCpy(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_ICMP);
|
StrCpy(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol), SOCK_UNDERLAY_ICMP);
|
||||||
AddProtocolDetailsStr(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/ICMP");
|
AddProtocolDetailsStr(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol), "RUDP/ICMP");
|
||||||
|
|
||||||
Copy(ret_ip, &ip4, sizeof(IP));
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
return p3.Result_Nat_T_Sock;
|
p->Sock = p3.Result_Nat_T_Sock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Continue the process if all trials failed
|
// Continue the process if all trials failed
|
||||||
*nat_t_error_code = p2.NatT_ErrorCode;
|
*p->NatT_ErrorCode = p2.NatT_ErrorCode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to connect with IPv6
|
if (s != INVALID_SOCKET)
|
||||||
if (s == INVALID_SOCKET && IsZeroIp(&ip6) == false)
|
|
||||||
{
|
{
|
||||||
|
p->Sock = CreateTCPSock(s, false, ¤t_ip, p->No_Get_Hostname, p->Hostname_Original);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->Ok = (p->Sock == NULL ? false : true);
|
||||||
|
p->FinishedTick = Tick64();
|
||||||
|
p->Finished = true;
|
||||||
|
|
||||||
|
Set(p->FinishEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv6 connection thread (multiple addresses)
|
||||||
|
void ConnectThreadForIPv6(THREAD *thread, void *param)
|
||||||
|
{
|
||||||
|
SOCKET s = INVALID_SOCKET;
|
||||||
|
IP current_ip;
|
||||||
|
UINT i;
|
||||||
|
CONNECT_SERIAL_PARAM *p = (CONNECT_SERIAL_PARAM *)param;
|
||||||
|
if (thread == NULL || p == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay before start
|
||||||
|
if (p->Delay >= 1)
|
||||||
|
{
|
||||||
|
WaitEx(NULL, p->Delay, p->NoDelayFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
Zero(¤t_ip, sizeof(current_ip));
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(p->IpList); ++i)
|
||||||
|
{
|
||||||
|
IP *ip = LIST_DATA(p->IpList, i);
|
||||||
|
|
||||||
|
if (IsZeroIp(ip))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay before retry
|
||||||
|
if (i > 0 && p->RetryDelay >= 1)
|
||||||
|
{
|
||||||
|
WaitEx(NULL, p->RetryDelay, p->CancelFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p->CancelFlag)
|
||||||
|
{
|
||||||
|
// Cancel by the user
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
struct sockaddr_in6 sockaddr6;
|
struct sockaddr_in6 sockaddr6;
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
|
|
||||||
@ -14315,10 +14281,10 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
Zero(&addr6, sizeof(addr6));
|
Zero(&addr6, sizeof(addr6));
|
||||||
|
|
||||||
// Generation of the sockaddr_in6
|
// Generation of the sockaddr_in6
|
||||||
IPToInAddr6(&addr6, &ip6);
|
IPToInAddr6(&addr6, ip);
|
||||||
sockaddr6.sin6_port = htons((USHORT)port);
|
sockaddr6.sin6_port = htons((USHORT)p->Port);
|
||||||
sockaddr6.sin6_family = AF_INET6;
|
sockaddr6.sin6_family = AF_INET6;
|
||||||
sockaddr6.sin6_scope_id = ip6.ipv6_scope_id;
|
sockaddr6.sin6_scope_id = ip->ipv6_scope_id;
|
||||||
Copy(&sockaddr6.sin6_addr, &addr6, sizeof(addr6));
|
Copy(&sockaddr6.sin6_addr, &addr6, sizeof(addr6));
|
||||||
|
|
||||||
// Socket creation
|
// Socket creation
|
||||||
@ -14326,7 +14292,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
if (s != INVALID_SOCKET)
|
if (s != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
// Connection
|
// Connection
|
||||||
if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), timeout, cancel_flag) != 0)
|
if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), p->Timeout, p->CancelFlag) != 0)
|
||||||
{
|
{
|
||||||
// Connection failure
|
// Connection failure
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
@ -14334,18 +14300,35 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Copy(¤t_ip, &ip6, sizeof(IP));
|
Copy(¤t_ip, ip, sizeof(IP));
|
||||||
|
|
||||||
is_ipv6 = true;
|
Copy(p->Ret_Ip, ip, sizeof(IP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Copy(ret_ip, &ip6, sizeof(IP));
|
if (s != INVALID_SOCKET)
|
||||||
}
|
{
|
||||||
|
p->Sock = CreateTCPSock(s, true, ¤t_ip, p->No_Get_Hostname, p->Hostname_Original);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->Ok = (p->Sock == NULL ? false : true);
|
||||||
|
p->FinishedTick = Tick64();
|
||||||
|
p->Finished = true;
|
||||||
|
|
||||||
|
Set(p->FinishEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating a TCP SOCK from a SOCKET
|
||||||
|
SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original)
|
||||||
|
{
|
||||||
|
struct linger ling;
|
||||||
|
char tmp[MAX_SIZE];
|
||||||
|
SOCK *sock;
|
||||||
|
|
||||||
if (s == INVALID_SOCKET)
|
if (s == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
// Connection fails on both of IPv4, IPv6
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14359,7 +14342,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
AddProtocolDetailsStr(sock->ProtocolDetails, sizeof(sock->ProtocolDetails), is_ipv6 ? "IPv6" : "IPv4");
|
AddProtocolDetailsStr(sock->ProtocolDetails, sizeof(sock->ProtocolDetails), is_ipv6 ? "IPv6" : "IPv4");
|
||||||
|
|
||||||
// Host name resolution
|
// Host name resolution
|
||||||
if (no_get_hostname || (GetHostName(tmp, sizeof(tmp), ¤t_ip) == false))
|
if (no_get_hostname || (GetHostName(tmp, sizeof(tmp), current_ip) == false))
|
||||||
{
|
{
|
||||||
StrCpy(tmp, sizeof(tmp), hostname_original);
|
StrCpy(tmp, sizeof(tmp), hostname_original);
|
||||||
}
|
}
|
||||||
@ -14409,6 +14392,255 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TCP connection
|
||||||
|
SOCK *Connect(char *hostname, UINT port)
|
||||||
|
{
|
||||||
|
return ConnectEx(hostname, port, 0);
|
||||||
|
}
|
||||||
|
SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
|
||||||
|
{
|
||||||
|
return ConnectEx2(hostname, port, timeout, NULL);
|
||||||
|
}
|
||||||
|
SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
|
||||||
|
{
|
||||||
|
return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, true);
|
||||||
|
}
|
||||||
|
SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname)
|
||||||
|
{
|
||||||
|
return ConnectEx4(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL);
|
||||||
|
}
|
||||||
|
SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip)
|
||||||
|
{
|
||||||
|
bool dummy = false;
|
||||||
|
bool use_natt = false;
|
||||||
|
char hostname_original[MAX_SIZE];
|
||||||
|
char hint_str[MAX_SIZE];
|
||||||
|
bool force_use_natt = false;
|
||||||
|
UINT dummy_int = 0;
|
||||||
|
IP dummy_ret_ip;
|
||||||
|
// Validate arguments
|
||||||
|
if (hostname == NULL || port == 0 || port >= 65536 || IsEmptyStr(hostname))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (timeout == 0)
|
||||||
|
{
|
||||||
|
timeout = TIMEOUT_TCP_PORT_CHECK;
|
||||||
|
}
|
||||||
|
if (cancel_flag == NULL)
|
||||||
|
{
|
||||||
|
cancel_flag = &dummy;
|
||||||
|
}
|
||||||
|
if (nat_t_error_code == NULL)
|
||||||
|
{
|
||||||
|
nat_t_error_code = &dummy_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zero(&dummy_ret_ip, sizeof(IP));
|
||||||
|
if (ret_ip == NULL)
|
||||||
|
{
|
||||||
|
ret_ip = &dummy_ret_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zero(hint_str, sizeof(hint_str));
|
||||||
|
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
||||||
|
|
||||||
|
use_natt = (IsEmptyStr(nat_t_svc_name) ? false : true);
|
||||||
|
|
||||||
|
if (use_natt)
|
||||||
|
{
|
||||||
|
// In case of using NAT-T, split host name if the '/' is included in the host name
|
||||||
|
UINT i = SearchStrEx(hostname, "/", 0, false);
|
||||||
|
|
||||||
|
if (i == INFINITE)
|
||||||
|
{
|
||||||
|
// Not included
|
||||||
|
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Included
|
||||||
|
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
||||||
|
hostname_original[i] = 0;
|
||||||
|
|
||||||
|
// Force to use the NAT-T
|
||||||
|
force_use_natt = true;
|
||||||
|
|
||||||
|
// Copy the hint string
|
||||||
|
StrCpy(hint_str, sizeof(hint_str), hostname + i + 1);
|
||||||
|
|
||||||
|
if (StrCmpi(hint_str, "tcp") == 0 || StrCmpi(hint_str, "disable") == 0
|
||||||
|
|| StrCmpi(hint_str, "disabled") == 0
|
||||||
|
|| StrCmpi(hint_str, "no") == 0 || StrCmpi(hint_str, "none") == 0)
|
||||||
|
{
|
||||||
|
// Force not to use the NAT-T
|
||||||
|
force_use_natt = false;
|
||||||
|
use_natt = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StrCpy(hostname_original, sizeof(hostname_original), hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST *iplist_v6 = NewListFast(NULL);
|
||||||
|
LIST *iplist_v4 = NewListFast(NULL);
|
||||||
|
|
||||||
|
if (IsZeroIp(ret_ip) == false)
|
||||||
|
{
|
||||||
|
// Skip name resolution
|
||||||
|
if (IsIP6(ret_ip))
|
||||||
|
{
|
||||||
|
AddHostIPAddressToList(iplist_v6, ret_ip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddHostIPAddressToList(iplist_v4, ret_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Debug("Using cached IP address: %s = %r\n", hostname_original, ret_ip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Forward resolution
|
||||||
|
if (DnsResolveEx(iplist_v6, iplist_v4, hostname_original, 0, cancel_flag) == false)
|
||||||
|
{
|
||||||
|
FreeHostIPAddressList(iplist_v6);
|
||||||
|
FreeHostIPAddressList(iplist_v4);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECT_SERIAL_PARAM p4, p6;
|
||||||
|
EVENT *finish_event;
|
||||||
|
THREAD *t4 = NULL;
|
||||||
|
THREAD *t6 = NULL;
|
||||||
|
UINT64 start_tick = Tick64();
|
||||||
|
bool cancel_flag2 = false;
|
||||||
|
bool no_delay_flag = false;
|
||||||
|
|
||||||
|
finish_event = NewEvent();
|
||||||
|
|
||||||
|
Zero(&p4, sizeof(p4));
|
||||||
|
Zero(&p6, sizeof(p6));
|
||||||
|
|
||||||
|
// IPv6 connection thread
|
||||||
|
if (LIST_NUM(iplist_v6) > 0)
|
||||||
|
{
|
||||||
|
p6.IpList = iplist_v6;
|
||||||
|
p6.Port = port;
|
||||||
|
p6.Timeout = timeout;
|
||||||
|
StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname);
|
||||||
|
StrCpy(p6.Hostname_Original, sizeof(p6.Hostname_Original), hostname_original);
|
||||||
|
p6.No_Get_Hostname = no_get_hostname;
|
||||||
|
p6.CancelFlag = &cancel_flag2;
|
||||||
|
p6.NoDelayFlag = &no_delay_flag;
|
||||||
|
p6.FinishEvent = finish_event;
|
||||||
|
p6.Tcp_TryStartSsl = try_start_ssl;
|
||||||
|
p6.Ret_Ip = ret_ip;
|
||||||
|
p6.RetryDelay = 250;
|
||||||
|
p6.Delay = 0;
|
||||||
|
t6 = NewThread(ConnectThreadForIPv6, &p6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv4 connection thread
|
||||||
|
if (LIST_NUM(iplist_v4) > 0)
|
||||||
|
{
|
||||||
|
p4.IpList = iplist_v4;
|
||||||
|
p4.Port = port;
|
||||||
|
p4.Timeout = timeout;
|
||||||
|
StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname);
|
||||||
|
StrCpy(p4.Hostname_Original, sizeof(p4.Hostname_Original), hostname_original);
|
||||||
|
StrCpy(p4.HintStr, sizeof(p4.HintStr), hint_str);
|
||||||
|
p4.No_Get_Hostname = no_get_hostname;
|
||||||
|
p4.CancelFlag = &cancel_flag2;
|
||||||
|
p4.NoDelayFlag = &no_delay_flag;
|
||||||
|
p4.NatT_ErrorCode = nat_t_error_code;
|
||||||
|
StrCpy(p4.NatT_SvcName, sizeof(p4.NatT_SvcName), nat_t_svc_name);
|
||||||
|
p4.FinishEvent = finish_event;
|
||||||
|
p4.Tcp_TryStartSsl = try_start_ssl;
|
||||||
|
p4.Use_NatT = use_natt;
|
||||||
|
p4.Force_NatT = force_use_natt;
|
||||||
|
p4.Ret_Ip = ret_ip;
|
||||||
|
p4.RetryDelay = 250;
|
||||||
|
p4.Delay = 250; // Delay by 250ms to prioritize IPv6 (RFC 6555 recommends 150-250ms, Chrome uses 300ms)
|
||||||
|
t4 = NewThread(ConnectThreadForIPv4, &p4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t6 == NULL || t4 == NULL)
|
||||||
|
{
|
||||||
|
// No need to delay if there is only one thread
|
||||||
|
no_delay_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (*cancel_flag)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((t6 == NULL || p6.Finished) && (t4 == NULL || p4.Finished))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p6.Finished && p6.Ok) || (p4.Finished && p4.Ok))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This check must be placed last to avoid race condition with cancel flag
|
||||||
|
if (no_delay_flag == false && (p6.Finished || p4.Finished))
|
||||||
|
{
|
||||||
|
no_delay_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wait(finish_event, 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel_flag2 = true;
|
||||||
|
no_delay_flag = true;
|
||||||
|
|
||||||
|
WaitThread(t6, INFINITE);
|
||||||
|
WaitThread(t4, INFINITE);
|
||||||
|
ReleaseThread(t6);
|
||||||
|
ReleaseThread(t4);
|
||||||
|
ReleaseEvent(finish_event);
|
||||||
|
FreeHostIPAddressList(iplist_v6);
|
||||||
|
FreeHostIPAddressList(iplist_v4);
|
||||||
|
|
||||||
|
if (*cancel_flag)
|
||||||
|
{
|
||||||
|
// Abandon all the results because the user canceled
|
||||||
|
Disconnect(p6.Sock);
|
||||||
|
ReleaseSock(p6.Sock);
|
||||||
|
Disconnect(p4.Sock);
|
||||||
|
ReleaseSock(p4.Sock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p6.Ok)
|
||||||
|
{
|
||||||
|
Disconnect(p4.Sock);
|
||||||
|
ReleaseSock(p4.Sock);
|
||||||
|
|
||||||
|
return p6.Sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p4.Ok)
|
||||||
|
{
|
||||||
|
Disconnect(p6.Sock);
|
||||||
|
ReleaseSock(p6.Sock);
|
||||||
|
|
||||||
|
return p4.Sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Add a protocol details strings
|
// Add a protocol details strings
|
||||||
void AddProtocolDetailsStr(char *dst, UINT dst_size, char *str)
|
void AddProtocolDetailsStr(char *dst, UINT dst_size, char *str)
|
||||||
{
|
{
|
||||||
@ -17059,14 +17291,32 @@ bool IsMyIPAddress(IP *ip)
|
|||||||
// Add the IP address to the list
|
// Add the IP address to the list
|
||||||
void AddHostIPAddressToList(LIST *o, IP *ip)
|
void AddHostIPAddressToList(LIST *o, IP *ip)
|
||||||
{
|
{
|
||||||
IP *r;
|
IP *r = NULL;
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (o == NULL || ip == NULL)
|
if (o == NULL || ip == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (o->cmp != NULL)
|
||||||
|
{
|
||||||
r = Search(o, ip);
|
r = Search(o, ip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < LIST_NUM(o); i++)
|
||||||
|
{
|
||||||
|
IP *a = LIST_DATA(o, i);
|
||||||
|
|
||||||
|
if (CmpIpAddr(ip, a) == 0)
|
||||||
|
{
|
||||||
|
r = ip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (r != NULL)
|
if (r != NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -17229,7 +17479,7 @@ LIST *CloneIPAddressList(LIST *o)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = NewListFast(CmpIpAddressList);
|
ret = NewListFast(o->cmp);
|
||||||
|
|
||||||
for (i = 0; i < LIST_NUM(o); i++)
|
for (i = 0; i < LIST_NUM(o); i++)
|
||||||
{
|
{
|
||||||
|
@ -795,6 +795,33 @@ struct RUDP_STACK
|
|||||||
USHORT Client_IcmpId, Client_IcmpSeqNo; // Sequence number and ICMP ID that is randomly generated on the client side
|
USHORT Client_IcmpId, Client_IcmpSeqNo; // Sequence number and ICMP ID that is randomly generated on the client side
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Data for the thread for serial connection attempts to a list of addresses
|
||||||
|
struct CONNECT_SERIAL_PARAM
|
||||||
|
{
|
||||||
|
LIST *IpList;
|
||||||
|
UINT Port;
|
||||||
|
UINT Timeout;
|
||||||
|
char Hostname[MAX_SIZE];
|
||||||
|
char Hostname_Original[MAX_SIZE];
|
||||||
|
char HintStr[MAX_SIZE];
|
||||||
|
bool No_Get_Hostname;
|
||||||
|
bool *CancelFlag;
|
||||||
|
bool *NoDelayFlag;
|
||||||
|
UINT *NatT_ErrorCode;
|
||||||
|
char NatT_SvcName[MAX_SIZE];
|
||||||
|
SOCK *Sock;
|
||||||
|
bool Finished;
|
||||||
|
bool Ok;
|
||||||
|
UINT64 FinishedTick;
|
||||||
|
EVENT *FinishEvent;
|
||||||
|
UINT Delay;
|
||||||
|
UINT RetryDelay;
|
||||||
|
bool Tcp_TryStartSsl;
|
||||||
|
bool Use_NatT;
|
||||||
|
bool Force_NatT;
|
||||||
|
IP *Ret_Ip;
|
||||||
|
};
|
||||||
|
|
||||||
// Data for the thread for concurrent connection attempts for the R-UDP and TCP
|
// Data for the thread for concurrent connection attempts for the R-UDP and TCP
|
||||||
struct CONNECT_TCP_RUDP_PARAM
|
struct CONNECT_TCP_RUDP_PARAM
|
||||||
{
|
{
|
||||||
@ -895,6 +922,9 @@ bool DetectIsServerSoftEtherVPN(SOCK *s);
|
|||||||
void ConnectThreadForTcp(THREAD *thread, void *param);
|
void ConnectThreadForTcp(THREAD *thread, void *param);
|
||||||
void ConnectThreadForRUDP(THREAD *thread, void *param);
|
void ConnectThreadForRUDP(THREAD *thread, void *param);
|
||||||
void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
|
void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
|
||||||
|
void ConnectThreadForIPv4(THREAD *thread, void *param);
|
||||||
|
void ConnectThreadForIPv6(THREAD *thread, void *param);
|
||||||
|
SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original);
|
||||||
SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
|
SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
|
||||||
RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip);
|
RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip);
|
||||||
SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode);
|
SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode);
|
||||||
|
Loading…
Reference in New Issue
Block a user