diff --git a/misc/windows/min-winsock2.h b/misc/windows/min-winsock2.h index 1b9768f61..3cfc1fe0d 100644 --- a/misc/windows/min-winsock2.h +++ b/misc/windows/min-winsock2.h @@ -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), diff --git a/src/Platform_3DS.c b/src/Platform_3DS.c index 0c1b08ffb..97ab7bf49 100644 --- a/src/Platform_3DS.c +++ b/src/Platform_3DS.c @@ -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; diff --git a/src/Platform_Dreamcast.c b/src/Platform_Dreamcast.c index 28fe69ed0..5c7e07644 100644 --- a/src/Platform_Dreamcast.c +++ b/src/Platform_Dreamcast.c @@ -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); diff --git a/src/Platform_GCWii.c b/src/Platform_GCWii.c index ec5728ccf..7aa4bf5a0 100644 --- a/src/Platform_GCWii.c +++ b/src/Platform_GCWii.c @@ -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; diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index 4929f39d1..a9a10dffd 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -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; } diff --git a/src/Platform_PS2.c b/src/Platform_PS2.c index b7a499b2d..a40b6bea0 100644 --- a/src/Platform_PS2.c +++ b/src/Platform_PS2.c @@ -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; diff --git a/src/Platform_PS3.c b/src/Platform_PS3.c index 756f8cd58..54cae18d3 100644 --- a/src/Platform_PS3.c +++ b/src/Platform_PS3.c @@ -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; diff --git a/src/Platform_PS4.c b/src/Platform_PS4.c index 29ff50f9a..fa0f99546 100644 --- a/src/Platform_PS4.c +++ b/src/Platform_PS4.c @@ -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; diff --git a/src/Platform_PSP.c b/src/Platform_PSP.c index 1976868e1..090b2038a 100644 --- a/src/Platform_PSP.c +++ b/src/Platform_PSP.c @@ -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; } diff --git a/src/Platform_PSVita.c b/src/Platform_PSVita.c index eb028ee40..d46478bbc 100644 --- a/src/Platform_PSVita.c +++ b/src/Platform_PSVita.c @@ -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; } diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 4f9655ea4..18f8c469f 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -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; diff --git a/src/Platform_Switch.c b/src/Platform_Switch.c index cf1fa9405..e67b3e275 100644 --- a/src/Platform_Switch.c +++ b/src/Platform_Switch.c @@ -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; diff --git a/src/Platform_Symbian.cpp b/src/Platform_Symbian.cpp index ca8c4cb1d..fdda4279c 100644 --- a/src/Platform_Symbian.cpp +++ b/src/Platform_Symbian.cpp @@ -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; diff --git a/src/Platform_WiiU.c b/src/Platform_WiiU.c index 66b86b10b..8230d940d 100644 --- a/src/Platform_WiiU.c +++ b/src/Platform_WiiU.c @@ -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; diff --git a/src/Platform_Windows.c b/src/Platform_Windows.c index 46f44e6de..732af5495 100644 --- a/src/Platform_Windows.c +++ b/src/Platform_Windows.c @@ -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"); } diff --git a/src/Platform_Xbox.c b/src/Platform_Xbox.c index 34b8957f9..dc69e1254 100644 --- a/src/Platform_Xbox.c +++ b/src/Platform_Xbox.c @@ -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; diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index 2249bff83..405dd5f49 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -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 +