mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-08 06:47:23 -04:00
Add support for resolving domains to IPv6 addresses on Windows, also support IPV6 addresses for host component of a URL in HttpClient http backend
This commit is contained in:
parent
fefc2c5ff4
commit
c82ec9e4b9
@ -512,6 +512,21 @@ struct HttpConnection {
|
||||
cc_bool valid;
|
||||
};
|
||||
|
||||
static void ExtractHostPort(const struct HttpUrl* url, cc_string* host, cc_string* port) {
|
||||
/* address can have the form of either "host" or "host:port" */
|
||||
/* Slightly more complicated because IPv6 hosts can be e.g. [::1] */
|
||||
cc_string* str = &url->address;
|
||||
int idx = String_LastIndexOf(str, ':');
|
||||
|
||||
if (idx == -1) {
|
||||
*host = *str;
|
||||
*port = String_Empty;
|
||||
} else {
|
||||
*host = String_UNSAFE_Substring(str, 0, idx);
|
||||
*port = String_UNSAFE_SubstringAt(str, idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct HttpUrl* url) {
|
||||
cc_string host, port;
|
||||
cc_uint16 portNum;
|
||||
@ -519,8 +534,7 @@ static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct H
|
||||
cc_sockaddr addrs[SOCKET_MAX_ADDRS];
|
||||
int numValidAddrs;
|
||||
|
||||
/* address can be either "host" or "host:port" */
|
||||
String_UNSAFE_Separate(&url->address, ':', &host, &port);
|
||||
ExtractHostPort(url, &host, &port);
|
||||
if (!Convert_ParseUInt16(&port, &portNum)) {
|
||||
portNum = url->https ? 443 : 80;
|
||||
}
|
||||
|
@ -416,6 +416,9 @@ static int (WSAAPI *_select)(int nfds, fd_set* readfds, fd_set* writefds, fd_set
|
||||
|
||||
static struct hostent* (WSAAPI *_gethostbyname)(const char* name);
|
||||
static unsigned short (WSAAPI *_htons)(u_short hostshort);
|
||||
static int (WSAAPI *_getaddrinfo )(PCSTR nodeName, PCSTR serviceName, const ADDRINFOA* hints, PADDRINFOA* result);
|
||||
static void (WSAAPI* _freeaddrinfo)(PADDRINFOA addrInfo);
|
||||
|
||||
|
||||
|
||||
static INT WSAAPI FallbackParseAddress(LPWSTR addressString, INT addressFamily, LPVOID protocolInfo, LPVOID address, LPINT addressLength) {
|
||||
@ -445,6 +448,7 @@ static void LoadWinsockFuncs(void) {
|
||||
DynamicLib_Sym(connect), DynamicLib_Sym(shutdown),
|
||||
DynamicLib_Sym(ioctlsocket), DynamicLib_Sym(getsockopt),
|
||||
DynamicLib_Sym(gethostbyname), DynamicLib_Sym(htons),
|
||||
DynamicLib_Sym(getaddrinfo), DynamicLib_Sym(freeaddrinfo),
|
||||
DynamicLib_Sym(recv), DynamicLib_Sym(send), DynamicLib_Sym(select)
|
||||
};
|
||||
static const cc_string winsock1 = String_FromConst("wsock32.DLL");
|
||||
@ -459,7 +463,7 @@ static void LoadWinsockFuncs(void) {
|
||||
if (!_WSAStringToAddressW) _WSAStringToAddressW = FallbackParseAddress;
|
||||
}
|
||||
|
||||
static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
|
||||
static cc_result ParseHostOld(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
|
||||
struct hostent* res;
|
||||
cc_result wsa_res;
|
||||
SOCKADDR_IN* addr4;
|
||||
@ -496,6 +500,44 @@ static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numVal
|
||||
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
|
||||
}
|
||||
|
||||
static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
|
||||
char portRaw[32]; cc_string portStr;
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* result;
|
||||
struct addrinfo* cur;
|
||||
int res, i = 0;
|
||||
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
String_InitArray(portStr, portRaw);
|
||||
String_AppendInt(&portStr, port);
|
||||
portRaw[portStr.length] = '\0';
|
||||
|
||||
res = _getaddrinfo(host, portRaw, &hints, &result);
|
||||
if (res == EAI_NONAME) return SOCK_ERR_UNKNOWN_HOST;
|
||||
if (res) return res;
|
||||
|
||||
/* Prefer IPv4 addresses first */
|
||||
for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next)
|
||||
{
|
||||
if (cur->ai_family != AF_INET) continue;
|
||||
Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
|
||||
addrs[i].size = cur->ai_addrlen; i++;
|
||||
}
|
||||
|
||||
for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next)
|
||||
{
|
||||
if (cur->ai_family == AF_INET) continue;
|
||||
Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
|
||||
addrs[i].size = cur->ai_addrlen; i++;
|
||||
}
|
||||
|
||||
_freeaddrinfo(result);
|
||||
*numValidAddrs = i;
|
||||
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
|
||||
}
|
||||
|
||||
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
|
||||
SOCKADDR_IN* addr4 = (SOCKADDR_IN* )addrs[0].data;
|
||||
SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)addrs[0].data;
|
||||
@ -523,7 +565,11 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ParseHost(str.ansi, port, addrs, numValidAddrs);
|
||||
if (_getaddrinfo) {
|
||||
return ParseHostNew(str.ansi, port, addrs, numValidAddrs);
|
||||
} else {
|
||||
return ParseHostOld(str.ansi, port, addrs, numValidAddrs);
|
||||
}
|
||||
}
|
||||
|
||||
cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user