Unify IPv4 address parsing

This commit is contained in:
UnknownShadow200 2025-05-27 23:49:18 +10:00
parent 651d80b27d
commit cb0b2fb7cf
17 changed files with 392 additions and 380 deletions

View File

@ -127,7 +127,7 @@ typedef struct WSAData {
CC_WINSOCK_FUNC int (WINAPI *_WSAStartup)(WORD versionRequested, WSADATA* wsaData);
CC_WINSOCK_FUNC int (WINAPI *_WSACleanup)(void);
CC_WINSOCK_FUNC int (WINAPI *_WSAGetLastError)(void);
CC_WINSOCK_FUNC int (WINAPI *_WSAStringToAddressW)(LPWSTR addressString, INT addressFamily, LPVOID protocolInfo, LPVOID address, LPINT addressLength);
CC_WINSOCK_FUNC int (WINAPI *_WSAStringToAddressA)(LPSTR addressString, INT addressFamily, LPVOID protocolInfo, LPVOID address, LPINT addressLength);
CC_WINSOCK_FUNC int (WINAPI *_socket)(int af, int type, int protocol);
CC_WINSOCK_FUNC int (WINAPI *_closesocket)(SOCKET s);
@ -148,7 +148,7 @@ CC_WINSOCK_FUNC void (WINAPI* _freeaddrinfo)(ADDRINFOA* addrInfo);
static void Winsock_LoadDynamicFuncs(void) {
static const struct DynamicLibSym funcs[] = {
DynamicLib_ReqSym(WSAStartup), DynamicLib_ReqSym(WSACleanup),
DynamicLib_ReqSym(WSAGetLastError), DynamicLib_OptSym(WSAStringToAddressW),
DynamicLib_ReqSym(WSAGetLastError), DynamicLib_OptSym(WSAStringToAddressA),
DynamicLib_ReqSym(socket), DynamicLib_ReqSym(closesocket),
DynamicLib_ReqSym(connect), DynamicLib_ReqSym(shutdown),
DynamicLib_ReqSym(ioctlsocket), DynamicLib_ReqSym(getsockopt),

View File

@ -275,26 +275,29 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char str[NATIVE_STR_LEN];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const 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 i = 0;
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
if (inet_aton(str, &addr4->sin_addr) > 0) {
// TODO eliminate this path?
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}
hints.ai_family = AF_INET; // TODO: you need this, otherwise resolving dl.dropboxusercontent.com crashes in Citra. probably something to do with IPv6 addresses
hints.ai_socktype = SOCK_STREAM;
@ -304,7 +307,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
int res = getaddrinfo(str, portRaw, &hints, &result);
int res = getaddrinfo(host, portRaw, &hints, &result);
if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;

View File

@ -526,17 +526,28 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char str[NATIVE_STR_LEN];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(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;
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
@ -544,24 +555,12 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
// getaddrinfo IP address resolution was only added in Nov 2023
// https://github.com/KallistiOS/KallistiOS/pull/358
// So include this special case for backwards compatibility
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
if (inet_pton(AF_INET, str, &addr4->sin_addr) > 0) {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(struct sockaddr_in);
*numValidAddrs = 1;
return 0;
}
res = getaddrinfo(str, portRaw, &hints, &result);
int res = getaddrinfo(host, portRaw, &hints, &result);
if (res == EAI_NONAME) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;
int i = 0;
for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++)
{
SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen);

View File

@ -380,7 +380,24 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
#ifdef HW_RVL
struct hostent* res = net_gethostbyname(host);
struct sockaddr_in* addr4;
@ -414,21 +431,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
return ERR_NOT_SUPPORTED;
#endif
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 1;
if (inet_aton(str, &addr4->sin_addr) > 0) {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -391,12 +391,31 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
*#########################################################################################################################*/
static cc_bool net_supported = true;
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!net_supported) return false; // TODO still accept?
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct hostent* res = gethostbyname(host);
struct sockaddr_in* addr4;
char* src_addr;
int i;
if (!net_supported) return ERR_NO_NETWORKING;
// avoid confusion with SSL error codes
// e.g. FFFF FFF7 > FF00 FFF7
if (!res) return -0xFF0000 + errno;
@ -407,7 +426,7 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
for (i = 0; i < SOCKET_MAX_ADDRS; i++)
{
src_addr = res->h_addr_list[i];
char* src_addr = res->h_addr_list[i];
if (!src_addr) break;
addrs[i].size = sizeof(struct sockaddr_in);
@ -421,25 +440,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
if (!net_supported) return ERR_NO_NETWORKING;
*numValidAddrs = 1;
if (inet_aton(str, &addr4->sin_addr) > 0) {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;
if (!net_supported) { *s = -1; return ERR_NO_NETWORKING; }

View File

@ -488,20 +488,35 @@ static void Networking_LoadIOPModules(void) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
int lwip_shutdown(int s, int how);
int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
int lwip_close(int s);
int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen);
int lwip_recv(int s, void *mem, size_t len, int flags);
int lwip_send(int s, const void *dataptr, size_t size, int flags);
int lwip_socket(int domain, int type, int protocol);
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
int lwip_ioctl(int s, long cmd, void *argp);
int lwip_shutdown(int s, int how);
int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
int lwip_close(int s);
int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen);
int lwip_recv(int s, void *mem, size_t len, int flags);
int lwip_send(int s, const void *dataptr, size_t size, int flags);
int lwip_socket(int domain, int type, int protocol);
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
int lwip_ioctl(int s, long cmd, void *argp);
int netconn_gethostbyname(const char *name, ip4_addr_t *addr);
int ip4addr_aton(const char *cp, ip4_addr_t *addr);
int netconn_gethostbyname(const char *name, ip4_addr_t *addr);
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
@ -520,25 +535,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
return 0;
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (ip4addr_aton(str, (ip4_addr_t*)&addr4->sin_addr) > 0) {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
static cc_result GetSocketError(cc_socket s) {
socklen_t resultSize = sizeof(socklen_t);
cc_result res = 0;

View File

@ -335,10 +335,23 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
union SocketAddress {
struct sockaddr raw;
struct sockaddr_in v4;
};
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct net_hostent* res = netGetHostByName(host);
struct sockaddr_in* addr4;
@ -350,41 +363,24 @@ static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numVal
// each address pointer is only 4 bytes long
u32* addr_list = (u32*)res->h_addr_list;
char* src_addr;
int i;
for (i = 0; i < SOCKET_MAX_ADDRS; i++)
{
src_addr = (char*)addr_list[i];
char* src_addr = (char*)addr_list[i];
if (!src_addr) break;
addrs[i].size = sizeof(struct sockaddr_in);
addr4 = (struct sockaddr_in*)addrs[i].data;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addr4->sin_addr = *(struct in_addr*)src_addr;
}
*numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_aton(str, &addr4->sin_addr) > 0) {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -387,15 +387,36 @@ void Platform_LoadSysFonts(void) { }
union SocketAddress {
struct sockaddr raw;
struct sockaddr_in v4;
#ifdef AF_INET6
struct sockaddr_in6 v6;
struct sockaddr_storage total;
#endif
};
/* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */
static char sockaddr_size_check[sizeof(union SocketAddress) < CC_SOCKETADDR_MAXSIZE ? 1 : -1];
#if SUPPORTS_GETADDRINFO
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
union SocketAddress* addr = (union SocketAddress*)dst->data;
if (inet_pton(AF_INET6, ip, &addr->v6.sin6_addr) <= 0) return false;
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
dst->size = sizeof(addr->v6);
return true;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char portRaw[32]; cc_string portStr;
struct addrinfo hints = { 0 };
@ -431,63 +452,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
*numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
#else
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct hostent* res = gethostbyname(host);
struct sockaddr_in* addr4;
char* src_addr;
int i;
// Must have at least one IPv4 address
if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT;
if (!res->h_addr_list) return ERR_INVALID_ARGUMENT;
for (i = 0; i < SOCKET_MAX_ADDRS; i++)
{
src_addr = res->h_addr_list[i];
if (!src_addr) break;
addrs[i].size = sizeof(struct sockaddr_in);
addr4 = (struct sockaddr_in*)addrs[i].data;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addr4->sin_addr = *(struct in_addr*)src_addr;
}
*numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
#endif
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
union SocketAddress* addr = (union SocketAddress*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) {
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = htons(port);
addrs[0].size = sizeof(addr->v4);
*numValidAddrs = 1;
return 0;
}
#ifdef AF_INET6
if (inet_pton(AF_INET6, str, &addr->v6.sin6_addr) > 0) {
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
addrs[0].size = sizeof(addr->v6);
*numValidAddrs = 1;
return 0;
}
#endif
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -298,29 +298,41 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN];
char buf[1024];
int rid, ret;
String_EncodeUtf8(str, address);
*numValidAddrs = 1;
int rid;
if (sceNetInetInetPton(AF_INET, str, &addr4->sin_addr) <= 0) {
/* Fallback to resolving as DNS name */
if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0)
return ERR_INVALID_ARGUMENT;
/* Fallback to resolving as DNS name */
if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0)
return ERR_INVALID_ARGUMENT;
ret = sceNetResolverStartNtoA(rid, str, &addr4->sin_addr, 1 /* timeout */, 5 /* retries */);
sceNetResolverDelete(rid);
if (ret < 0) return ret;
}
int ret = sceNetResolverStartNtoA(rid, host, &addr4->sin_addr, 1 /* timeout */, 5 /* retries */);
sceNetResolverDelete(rid);
if (ret < 0) return ret;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}

View File

@ -281,29 +281,40 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct SceNetSockaddrIn* addr4 = (struct SceNetSockaddrIn*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = SCE_NET_AF_INET;
addr4->sin_port = sceNetHtons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct SceNetSockaddrIn* addr4 = (struct SceNetSockaddrIn*)addrs[0].data;
char str[NATIVE_STR_LEN];
char buf[1024];
int rid, ret;
String_EncodeUtf8(str, address);
*numValidAddrs = 1;
/* Fallback to resolving as DNS name */
int rid = sceNetResolverCreate("CC resolver", NULL, 0);
if (rid < 0) return ERR_INVALID_ARGUMENT;
if (sceNetInetPton(SCE_NET_AF_INET, str, &addr4->sin_addr) <= 0) {
/* Fallback to resolving as DNS name */
rid = sceNetResolverCreate("CC resolver", NULL, 0);
if (rid < 0) return ERR_INVALID_ARGUMENT;
ret = sceNetResolverStartNtoa(rid, str, &addr4->sin_addr, 0, 0, 0);
sceNetResolverDestroy(rid);
if (ret) return ret;
}
int ret = sceNetResolverStartNtoa(rid, host, &addr4->sin_addr, 0, 0, 0);
sceNetResolverDestroy(rid);
if (ret) return ret;
addr4->sin_family = SCE_NET_AF_INET;
addr4->sin_port = sceNetHtons(port);
addrs[0].size = sizeof(*addr4);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}

View File

@ -667,6 +667,36 @@ union SocketAddress {
/* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */
static char sockaddr_size_check[sizeof(union SocketAddress) < CC_SOCKETADDR_MAXSIZE ? 1 : -1];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
#ifdef AF_INET6
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
union SocketAddress* addr = (union SocketAddress*)dst->data;
if (inet_pton(AF_INET6, ip, &addr->v6.sin6_addr) <= 0) return false;
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
dst->size = sizeof(addr->v6);
return true;
}
#else
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
#endif
#if SUPPORTS_GETADDRINFO
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char portRaw[32]; cc_string portStr;
@ -731,36 +761,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
}
#endif
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
union SocketAddress* addr = (union SocketAddress*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) {
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = htons(port);
addrs[0].size = sizeof(addr->v4);
*numValidAddrs = 1;
return 0;
}
#ifdef AF_INET6
if (inet_pton(AF_INET6, str, &addr->v6.sin6_addr) > 0) {
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
addrs[0].size = sizeof(addr->v6);
*numValidAddrs = 1;
return 0;
}
#endif
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -367,6 +367,30 @@ union SocketAddress {
struct sockaddr_storage total;
};
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
union SocketAddress* addr = (union SocketAddress*)dst->data;
if (inet_pton(AF_INET6, ip, &addr->v6.sin6_addr) <= 0) return false;
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
dst->size = sizeof(addr->v6);
return true;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char portRaw[32]; cc_string portStr;
struct addrinfo hints = { 0 };
@ -403,34 +427,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
union SocketAddress* addr = (union SocketAddress*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) {
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = htons(port);
addrs[0].size = sizeof(addr->v4);
*numValidAddrs = 1;
return 0;
}
if (inet_pton(AF_INET6, str, &addr->v6.sin6_addr) > 0) {
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = htons(port);
addrs[0].size = sizeof(addr->v6);
*numValidAddrs = 1;
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -417,12 +417,22 @@ void Platform_LoadSysFonts(void) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
union SocketAddress {
struct sockaddr raw;
struct sockaddr_in v4;
};
/* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */
static char sockaddr_size_check[sizeof(union SocketAddress) < CC_SOCKETADDR_MAXSIZE ? 1 : -1];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
#if SUPPORTS_GETADDRINFO
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
@ -488,25 +498,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
}
#endif
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
union SocketAddress* addr = (union SocketAddress*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) {
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = htons(port);
addrs[0].size = sizeof(addr->v4);
*numValidAddrs = 1;
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -313,6 +313,23 @@ union SocketAddress {
struct sockaddr_storage total;
};
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char portRaw[32]; cc_string portStr;
struct addrinfo hints = { 0 };
@ -350,24 +367,6 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int*
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
union SocketAddress* addr = (union SocketAddress*)addrs[0].data;
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) {
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = htons(port);
addrs[0].size = sizeof(addr->v4);
*numValidAddrs = 1;
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
}
cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
struct sockaddr* raw = (struct sockaddr*)addr->data;

View File

@ -545,27 +545,36 @@ void Platform_LoadSysFonts(void) {
/* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */
static char sockaddr_size_check[sizeof(SOCKADDR_STORAGE) < CC_SOCKETADDR_MAXSIZE ? 1 : -1];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst->data;
cc_uint32 ip_addr;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
static INT WINAPI FallbackParseAddress(LPWSTR addressString, INT addressFamily, LPVOID protocolInfo, LPVOID address, LPINT addressLength) {
SOCKADDR_IN* addr4 = (SOCKADDR_IN*)address;
cc_uint8* addr = (cc_uint8*)&addr4->sin_addr;
cc_string ip, parts[4 + 1];
cc_winstring* addrStr = (cc_winstring*)addressString;
ip = String_FromReadonly(addrStr->ansi);
/* 4+1 in case user tries '1.1.1.1.1' */
if (String_UNSAFE_Split(&ip, '.', parts, 4 + 1) != 4)
return ERR_INVALID_ARGUMENT;
if (!Convert_ParseUInt8(&parts[0], &addr[0]) || !Convert_ParseUInt8(&parts[1], &addr[1]) ||
!Convert_ParseUInt8(&parts[2], &addr[2]) || !Convert_ParseUInt8(&parts[3], &addr[3]))
return ERR_INVALID_ARGUMENT;
addr4->sin_family = AF_INET;
return 0;
addr4->sin_addr.S_un.S_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = _htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_result ParseHostOld(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
#ifdef AF_INET6
SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)dst->data;
INT size = sizeof(*addr6);
if (!_WSAStringToAddressA) return false;
if (!_WSAStringToAddressA(ip, AF_INET6, NULL, addr6, &size)) {
addr6->sin6_port = _htons(port);
dst->size = size;
return true;
}
#endif
return false;
}
static cc_result ParseHostOld(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct hostent* res;
cc_result wsa_res;
SOCKADDR_IN* addr4;
@ -602,7 +611,7 @@ static cc_result ParseHostOld(char* host, int port, cc_sockaddr* addrs, int* num
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
}
static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static cc_result ParseHostNew(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char portRaw[32]; cc_string portStr;
struct addrinfo hints = { 0 };
struct addrinfo* result;
@ -638,39 +647,11 @@ static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* num
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;
cc_winstring str;
INT size;
*numValidAddrs = 0;
Platform_EncodeString(&str, address);
size = sizeof(*addr4);
if (!_WSAStringToAddressW(str.uni, AF_INET, NULL, addr4, &size)) {
addr4->sin_port = _htons(port);
addrs[0].size = size;
*numValidAddrs = 1;
return 0;
}
#ifdef AF_INET6
size = sizeof(*addr6);
if (!_WSAStringToAddressW(str.uni, AF_INET6, NULL, addr6, &size)) {
addr6->sin6_port = _htons(port);
addrs[0].size = size;
*numValidAddrs = 1;
return 0;
}
#endif
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
if (_getaddrinfo) {
return ParseHostNew(str.ansi, port, addrs, numValidAddrs);
return ParseHostNew(host, port, addrs, numValidAddrs);
} else {
return ParseHostOld(str.ansi, port, addrs, numValidAddrs);
return ParseHostOld(host, port, addrs, numValidAddrs);
}
}
@ -1040,9 +1021,7 @@ void Platform_Init(void) {
if (conHandle == INVALID_HANDLE_VALUE) conHandle = NULL;
Winsock_LoadDynamicFuncs();
/* Fallback for older OS versions which lack WSAStringToAddressW */
if (!_WSAStringToAddressW) _WSAStringToAddressW = FallbackParseAddress;
res = _WSAStartup(MAKEWORD(2, 2), &wsaData);
if (res) Logger_SysWarn(res, "starting WSA");
}

View File

@ -314,16 +314,29 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char str[NATIVE_STR_LEN];
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)dst->data;
cc_uint32 ip_addr = 0;
if (!ParseIPv4Address(ip, &ip_addr)) return false;
addr4->sin_addr.s_addr = ip_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
dst->size = sizeof(*addr4);
return true;
}
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) {
return false;
}
static cc_result ParseHost(const 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 i = 0;
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
@ -332,7 +345,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
int res = lwip_getaddrinfo(str, portRaw, &hints, &result);
int res = lwip_getaddrinfo(host, portRaw, &hints, &result);
if (res == EAI_FAIL) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;

View File

@ -285,3 +285,54 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) {
}
#endif
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
#ifdef CC_BUILD_NETWORKING
/* Parses IPv4 addresses in the form a.b.c.d */
static CC_INLINE cc_bool ParseIPv4Address(const cc_string* addr, cc_uint32* ip) {
cc_string parts[5];
int i;
union ipv4_addr_raw {
cc_uint8 bytes[4];
cc_uint32 value;
} raw;
/* 4+1 in case user tries '1.1.1.1.1' */
if (String_UNSAFE_Split(addr, '.', parts, 4 + 1) != 4) return false;
for (i = 0; i < 4; i++)
{
if (!Convert_ParseUInt8(&parts[i], &raw.bytes[i])) return false;
}
*ip = raw.value;
return true;
}
static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst);
static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst);
static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs);
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
char str[NATIVE_STR_LEN];
if (ParseIPv4(address, port, &addrs[0])) {
*numValidAddrs = 1;
return 0;
}
String_EncodeUtf8(str, address);
if (ParseIPv6(str, port, &addrs[0])) {
*numValidAddrs = 1;
return 0;
}
*numValidAddrs = 0;
return ParseHost(str, port, addrs, numValidAddrs);
}
#endif