From 4ff6665c22f118d800723e97a7eb2d830e910804 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 30 May 2021 16:21:24 +1000 Subject: [PATCH 1/5] Windows: WIP on connecting to ipv6 address --- src/LScreens.c | 3 +-- src/Platform.h | 8 ++++---- src/Platform_Web.c | 14 ++++++------- src/Platform_WinApi.c | 47 +++++++++++++++++++++++++++---------------- src/Program.c | 4 ++-- src/Server.c | 25 ++++++++++------------- src/Server.h | 4 ++-- src/Utils.c | 10 --------- src/Utils.h | 1 - 9 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/LScreens.c b/src/LScreens.c index 2b0546eba..7d611b64f 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -542,7 +542,6 @@ static void DirectConnectScreen_StartClient(void* w, int idx) { const cc_string* mppass = &DirectConnectScreen_Instance.iptMppass.text; cc_string ip, port; - cc_uint8 raw_ip[4]; cc_uint16 raw_port; int index = String_LastIndexOf(addr, ':'); @@ -557,7 +556,7 @@ static void DirectConnectScreen_StartClient(void* w, int idx) { if (!user->length) { DirectConnectScreen_SetStatus("&eUsername required"); return; } - if (!Utils_ParseIP(&ip, raw_ip)) { + if (!Socket_ValidAddress(&ip)) { DirectConnectScreen_SetStatus("&eInvalid ip"); return; } if (!Convert_ParseUInt16(&port, &raw_port)) { diff --git a/src/Platform.h b/src/Platform.h index 560fa1b61..4818c05a0 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -218,15 +218,15 @@ CC_API void Waitable_WaitFor(void* handle, cc_uint32 milliseconds); /* Calls SysFonts_Register on each font that is available on this platform. */ void Platform_LoadSysFonts(void); -/* Allocates a new non-blocking socket. */ -CC_API cc_result Socket_Create(cc_socket* s); /* Returns how much data is available to be read from the given socket. */ CC_API cc_result Socket_Available(cc_socket s, int* available); /* Returns (and resets) the last error generated by the given socket. */ CC_API cc_result Socket_GetError(cc_socket s, cc_result* result); +/* Returns non-zero if the given address is valid for a socket to connect to */ +CC_API int Socket_ValidAddress(const cc_string* address); -/* Attempts to open a connection to the given IP address:port. */ -CC_API cc_result Socket_Connect(cc_socket s, const cc_string* ip, int port); +/* Allocates a new non-blocking socket and then begins connecting to the given address:port. */ +CC_API cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port); /* Attempts to read data from the given socket. */ CC_API cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified); /* Attempts to write data to the given socket. */ diff --git a/src/Platform_Web.c b/src/Platform_Web.c index 6fb958a55..0a64c5b63 100644 --- a/src/Platform_Web.c +++ b/src/Platform_Web.c @@ -257,11 +257,6 @@ extern int interop_SocketGetPending(int sock); extern int interop_SocketGetError(int sock); extern int interop_SocketPoll(int sock); -cc_result Socket_Create(cc_socket* s) { - *s = interop_SocketCreate(); - return 0; -} - cc_result Socket_Available(cc_socket s, int* available) { int res = interop_SocketGetPending(s); /* returned result is negative for error */ @@ -283,13 +278,16 @@ cc_result Socket_GetError(cc_socket s, cc_result* result) { *result = 0; return -res; } } +int Socket_ValidAddress(const cc_string* address) { return true; } -cc_result Socket_Connect(cc_socket s, const cc_string* ip, int port) { +cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { char addr[NATIVE_STR_LEN]; int res; - Platform_EncodeUtf8(addr, ip); + Platform_EncodeUtf8(addr, address); + + *s = interop_SocketCreate(); /* returned result is negative for error */ - res = -interop_SocketConnect(s, addr, port); + res = -interop_SocketConnect(*s, addr, port); /* error returned when invalid address provided */ if (res == _EHOSTUNREACH) return ERR_INVALID_ARGUMENT; diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index 02943c2ee..12db91971 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -373,16 +373,6 @@ void Platform_LoadSysFonts(void) { /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ -cc_result Socket_Create(cc_socket* s) { - int blockingMode = -1; /* non-blocking mode */ - - *s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (*s == -1) return WSAGetLastError(); - - ioctlsocket(*s, FIONBIO, &blockingMode); - return 0; -} - cc_result Socket_Available(cc_socket s, int* available) { return ioctlsocket(s, FIONREAD, available); } @@ -392,16 +382,39 @@ cc_result Socket_GetError(cc_socket s, cc_result* result) { return getsockopt(s, SOL_SOCKET, SO_ERROR, result, &resultSize); } -cc_result Socket_Connect(cc_socket s, const cc_string* ip, int port) { - struct sockaddr addr; +static int Socket_ParseAddress(struct sockaddr* dst, const cc_string* address) { + WCHAR str[NATIVE_STR_LEN]; + DWORD size; + Platform_EncodeUtf16(str, address); + + size = sizeof(SOCKADDR_IN); + if (!WSAStringToAddressW(str, AF_INET, NULL, dst, &size)) return true; + + size = sizeof(SOCKADDR_IN6); + if (!WSAStringToAddressW(str, AF_INET6, NULL, dst, &size)) return true; + + return false; +} + +int Socket_ValidAddress(const cc_string* address) { + SOCKADDR_IN6 addr; + return Socket_ParseAddress(&addr, address); +} + +cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { + int blockingMode = -1; /* non-blocking mode */ + SOCKADDR_IN6 addr; cc_result res; - addr.sa_family = AF_INET; - Stream_SetU16_BE( (cc_uint8*)&addr.sa_data[0], port); - if (!Utils_ParseIP(ip, (cc_uint8*)&addr.sa_data[2])) - return ERR_INVALID_ARGUMENT; + *s = -1; + if (!Socket_ParseAddress(&addr, address)) return ERR_INVALID_ARGUMENT; + Stream_SetU16_BE((cc_uint8*)&addr.sin6_port, port); - res = connect(s, &addr, sizeof(addr)); + *s = socket(addr.sin6_family, SOCK_STREAM, IPPROTO_TCP); + if (*s == -1) return WSAGetLastError(); + ioctlsocket(*s, FIONBIO, &blockingMode); + + res = connect(*s, &addr, sizeof(addr)); return res == -1 ? WSAGetLastError() : 0; } diff --git a/src/Program.c b/src/Program.c index b593c04cf..c0fcf71f6 100644 --- a/src/Program.c +++ b/src/Program.c @@ -121,7 +121,7 @@ static int Program_Run(int argc, char** argv) { } else { String_Copy(&Game_Username, &args[0]); String_Copy(&Game_Mppass, &args[1]); - String_Copy(&Server.IP, &args[2]); + String_Copy(&Server.Address,&args[2]); if (!Convert_ParseUInt16(&args[3], &port)) { WarnInvalidArg("Invalid port", &args[3]); @@ -154,7 +154,7 @@ int main(int argc, char** argv) { main_imdct(); #endif Platform_LogConst("Starting " GAME_APP_NAME " .."); - String_InitArray(Server.IP, ipBuffer); + String_InitArray(Server.Address, ipBuffer); Options_Load(); res = Program_Run(argc, argv); diff --git a/src/Server.c b/src/Server.c index 56755d21f..423a0e620 100644 --- a/src/Server.c +++ b/src/Server.c @@ -241,7 +241,7 @@ static void MPConnection_Fail(const cc_string* reason) { String_InitArray(msg, msgBuffer); net_connecting = false; - String_Format2(&msg, "Failed to connect to %s:%i", &Server.IP, &Server.Port); + String_Format2(&msg, "Failed to connect to %s:%i", &Server.Address, &Server.Port); Game_Disconnect(&msg, reason); OnClose(); } @@ -252,7 +252,7 @@ static void MPConnection_FailConnect(cc_result result) { String_InitArray(msg, msgBuffer); if (result) { - String_Format3(&msg, "Error connecting to %s:%i: %i" _NL, &Server.IP, &Server.Port, &result); + String_Format3(&msg, "Error connecting to %s:%i: %i" _NL, &Server.Address, &Server.Port, &result); Logger_Log(&msg); } MPConnection_Fail(&reason); @@ -292,21 +292,18 @@ static void MPConnection_BeginConnect(void) { Blocks.CanPlace[BLOCK_STILL_WATER] = false; Blocks.CanDelete[BLOCK_STILL_WATER] = false; Blocks.CanPlace[BLOCK_BEDROCK] = false; Blocks.CanDelete[BLOCK_BEDROCK] = false; - res = Socket_Create(&net_socket); - if (res) { MPConnection_FailConnect(res); return; } - Server.Disconnected = false; - - net_connecting = true; - net_connectTimeout = Game.Time + NET_TIMEOUT_SECS; - res = Socket_Connect(net_socket, &Server.IP, Server.Port); - + res = Socket_Connect(&net_socket, &Server.Address, Server.Port); if (res == ERR_INVALID_ARGUMENT) { static const cc_string reason = String_FromConst("Invalid IP address"); MPConnection_Fail(&reason); } else if (res && res != ReturnCode_SocketInProgess && res != ReturnCode_SocketWouldBlock) { MPConnection_FailConnect(res); } else { - String_Format2(&title, "Connecting to %s:%i..", &Server.IP, &Server.Port); + Server.Disconnected = false; + net_connecting = true; + net_connectTimeout = Game.Time + NET_TIMEOUT_SECS; + + String_Format2(&title, "Connecting to %s:%i..", &Server.Address, &Server.Port); LoadingScreen_Show(&title, &String_Empty); } } @@ -397,7 +394,7 @@ static void MPConnection_Tick(struct ScheduledTask* task) { if (res) { String_InitArray(msg, msgBuffer); - String_Format3(&msg, "Error reading from %s:%i: %i" _NL, &Server.IP, &Server.Port, &res); + String_Format3(&msg, "Error reading from %s:%i: %i" _NL, &Server.Address, &Server.Port, &res); Logger_Log(&msg); Game_Disconnect(&title_lost, &reason_err); @@ -504,7 +501,7 @@ static void OnInit(void) { String_InitArray(Server.MOTD, motdBuffer); String_InitArray(Server.AppName, appBuffer); - if (!Server.IP.length) { + if (!Server.Address.length) { SPConnection_Init(); } else { MPConnection_Init(); @@ -527,7 +524,7 @@ static void OnReset(void) { } static void OnFree(void) { - Server.IP.length = 0; + Server.Address.length = 0; OnClose(); } diff --git a/src/Server.h b/src/Server.h index 4b104a675..bd24c3d9a 100644 --- a/src/Server.h +++ b/src/Server.h @@ -57,8 +57,8 @@ CC_VAR extern struct _ServerConnectionData { /* Whether the server supports all of code page 437, not just ASCII. */ cc_bool SupportsFullCP437; - /* IP address of the server if multiplayer, empty string if singleplayer. */ - cc_string IP; + /* Address of the server if multiplayer, empty string if singleplayer. */ + cc_string Address; /* Port of the server if multiplayer, 0 if singleplayer. */ int Port; } Server; diff --git a/src/Utils.c b/src/Utils.c index 84c132896..5151e8608 100644 --- a/src/Utils.c +++ b/src/Utils.c @@ -138,16 +138,6 @@ void Utils_Resize(void** buffer, int* capacity, cc_uint32 elemSize, int defCapac } } -cc_bool Utils_ParseIP(const cc_string* ip, cc_uint8* data) { - cc_string parts[4 + 1]; - int count = String_UNSAFE_Split(ip, '.', parts, 4 + 1); - if (count != 4) return false; - - return - Convert_ParseUInt8(&parts[0], &data[0]) && Convert_ParseUInt8(&parts[1], &data[1]) && - Convert_ParseUInt8(&parts[2], &data[2]) && Convert_ParseUInt8(&parts[3], &data[3]); -} - static const char base64_table[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', diff --git a/src/Utils.h b/src/Utils.h index 5b6aef562..f86f4105c 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -44,7 +44,6 @@ cc_uint32 Utils_CRC32(const cc_uint8* data, cc_uint32 length); /* NOTE: This cannot be just indexed by byte value - see Utils_CRC32 implementation. */ extern const cc_uint32 Utils_Crc32Table[256]; CC_NOINLINE void Utils_Resize(void** buffer, int* capacity, cc_uint32 elemSize, int defCapacity, int expandElems); -CC_NOINLINE cc_bool Utils_ParseIP(const cc_string* ip, cc_uint8* data); /* Converts blocks of 3 bytes into 4 ASCII characters. (pads if needed) */ /* Returns the number of ASCII characters written. */ From 968e16a9f20c37cb99e79333166f49ebb058cd11 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 30 May 2021 17:25:33 +1000 Subject: [PATCH 2/5] Mac/Linux: Support ipv6 addresses too --- src/Platform_Posix.c | 52 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 65648fbc8..b9ad561c1 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -450,16 +450,6 @@ void Platform_LoadSysFonts(void) { /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ -cc_result Socket_Create(cc_socket* s) { - int blockingMode = -1; /* non-blocking mode */ - - *s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (*s == -1) return errno; - - ioctl(*s, FIONBIO, &blockingMode); - return 0; -} - cc_result Socket_Available(cc_socket s, int* available) { return ioctl(s, FIONREAD, available); } @@ -469,16 +459,44 @@ cc_result Socket_GetError(cc_socket s, cc_result* result) { return getsockopt(s, SOL_SOCKET, SO_ERROR, result, &resultSize); } -cc_result Socket_Connect(cc_socket s, const cc_string* ip, int port) { - struct sockaddr addr; - cc_result res; - addr.sa_family = AF_INET; +static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { + struct sockaddr_in* addr4 = (struct sockaddr_in* )dst; + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)dst; + char str[NATIVE_STR_LEN]; + Platform_EncodeUtf8(str, address); - Stream_SetU16_BE( (cc_uint8*)&addr.sa_data[0], port); - if (!Utils_ParseIP(ip, (cc_uint8*)&addr.sa_data[2])) + if (inet_pton(AF_INET, str, &addr4->sin_addr) > 0) { + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + return AF_INET; + } + if (inet_pton(AF_INET6, str, &addr6->sin6_addr) > 0) { + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(port); + return AF_INET6; + } + return 0; +} + +int Socket_ValidAddress(const cc_string* address) { + struct sockaddr_in6 addr; + return Socket_ParseAddress(&addr, address, 0); +} + +cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { + int family, blocking_raw = -1; /* non-blocking mode */ + struct sockaddr_in6 addr; + cc_result res; + + *s = -1; + if (!(family = Socket_ParseAddress(&addr, address, port))) return ERR_INVALID_ARGUMENT; - res = connect(s, &addr, sizeof(addr)); + *s = socket(family, SOCK_STREAM, IPPROTO_TCP); + if (*s == -1) return errno; + ioctl(*s, FIONBIO, &blocking_raw); + + res = connect(*s, &addr, sizeof(addr)); return res == -1 ? errno : 0; } From 12c889efad175758fbb0fd8e82d439582ab881e9 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 4 Jun 2021 17:24:09 +1000 Subject: [PATCH 3/5] Fix not working on windows 95/98 --- src/Platform_Posix.c | 4 +-- src/Platform_WinApi.c | 68 ++++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index b9ad561c1..af2cfe141 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -479,13 +479,13 @@ static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { } int Socket_ValidAddress(const cc_string* address) { - struct sockaddr_in6 addr; + struct sockaddr_storage addr; return Socket_ParseAddress(&addr, address, 0); } cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { int family, blocking_raw = -1; /* non-blocking mode */ - struct sockaddr_in6 addr; + struct sockaddr_storage addr; cc_result res; *s = -1; diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index 12db91971..df6527cf0 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -29,6 +29,12 @@ const cc_result ReturnCode_SocketInProgess = WSAEINPROGRESS; const cc_result ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK; const cc_result ReturnCode_DirectoryExists = ERROR_ALREADY_EXISTS; +static void LoadDynamicFuncs(const cc_string* path, const struct DynamicLibSym* syms, int count) { + void* lib = DynamicLib_Load2(path); + if (!lib) { Logger_DynamicLibWarn("loading", path); return; } + DynamicLib_GetAll(lib, syms, count); +} + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ @@ -373,6 +379,17 @@ void Platform_LoadSysFonts(void) { /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ +static INT (WSAAPI *_WSAStringToAddressW)(LPWSTR addressString, INT addressFamily, LPVOID lpProtocolInfo, LPVOID address, LPINT addressLength); + +static void LoadWinsockFuncs(void) { + static const struct DynamicLibSym funcs[1] = { + DynamicLib_Sym(WSAStringToAddressW) + }; + + static const cc_string winsock32 = String_FromConst("WS2_32.DLL"); + LoadDynamicFuncs(&winsock32, funcs, Array_Elems(funcs)); +} + cc_result Socket_Available(cc_socket s, int* available) { return ioctlsocket(s, FIONREAD, available); } @@ -382,39 +399,45 @@ cc_result Socket_GetError(cc_socket s, cc_result* result) { return getsockopt(s, SOL_SOCKET, SO_ERROR, result, &resultSize); } -static int Socket_ParseAddress(struct sockaddr* dst, const cc_string* address) { +static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { + SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst; + SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)dst; WCHAR str[NATIVE_STR_LEN]; DWORD size; Platform_EncodeUtf16(str, address); - size = sizeof(SOCKADDR_IN); - if (!WSAStringToAddressW(str, AF_INET, NULL, dst, &size)) return true; - - size = sizeof(SOCKADDR_IN6); - if (!WSAStringToAddressW(str, AF_INET6, NULL, dst, &size)) return true; - - return false; + size = sizeof(*addr4); + if (!_WSAStringToAddressW(str, AF_INET, NULL, (SOCKADDR*)addr4, &size)) { + addr4->sin_port = htons(port); + return AF_INET; + } + size = sizeof(*addr6); + if (!_WSAStringToAddressW(str, AF_INET6, NULL, (SOCKADDR*)addr6, &size)) { + addr6->sin6_port = htons(port); + return AF_INET6; + } + return 0; } int Socket_ValidAddress(const cc_string* address) { - SOCKADDR_IN6 addr; - return Socket_ParseAddress(&addr, address); + SOCKADDR_STORAGE addr; + return Socket_ParseAddress(&addr, address, 0); } cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { - int blockingMode = -1; /* non-blocking mode */ - SOCKADDR_IN6 addr; + int family, blockingMode = -1; /* non-blocking mode */ + SOCKADDR_STORAGE addr; cc_result res; *s = -1; - if (!Socket_ParseAddress(&addr, address)) return ERR_INVALID_ARGUMENT; - Stream_SetU16_BE((cc_uint8*)&addr.sin6_port, port); + if (!(family = Socket_ParseAddress(&addr, address, port))) + return ERR_INVALID_ARGUMENT; - *s = socket(addr.sin6_family, SOCK_STREAM, IPPROTO_TCP); + *s = socket(family, SOCK_STREAM, IPPROTO_TCP); if (*s == -1) return WSAGetLastError(); ioctlsocket(*s, FIONBIO, &blockingMode); - res = connect(*s, &addr, sizeof(addr)); + res = connect(*s, (SOCKADDR*)&addr, sizeof(addr)); return res == -1 ? WSAGetLastError() : 0; } @@ -680,11 +703,9 @@ static void LoadKernelFuncs(void) { static const struct DynamicLibSym funcs[2] = { DynamicLib_Sym(AttachConsole), DynamicLib_Sym(IsDebuggerPresent) }; - static const cc_string kernel32 = String_FromConst("KERNEL32.DLL"); - void* lib = DynamicLib_Load2(&kernel32); - if (!lib) { Logger_DynamicLibWarn("loading", &kernel32); return; } - DynamicLib_GetAll(lib, funcs, Array_Elems(funcs)); + static const cc_string kernel32 = String_FromConst("KERNEL32.DLL"); + LoadDynamicFuncs(&kernel32, funcs, Array_Elems(funcs)); } void Platform_Init(void) { @@ -698,6 +719,7 @@ void Platform_Init(void) { if (res) Logger_SysWarn(res, "starting WSA"); LoadKernelFuncs(); + LoadWinsockFuncs(); if (_IsDebuggerPresent) hasDebugger = _IsDebuggerPresent(); /* For when user runs from command prompt */ if (_AttachConsole) _AttachConsole(-1); /* ATTACH_PARENT_PROCESS */ @@ -739,11 +761,9 @@ static void LoadCryptFuncs(void) { static const struct DynamicLibSym funcs[2] = { DynamicLib_Sym(CryptProtectData), DynamicLib_Sym(CryptUnprotectData) }; - static const cc_string crypt32 = String_FromConst("CRYPT32.DLL"); - void* lib = DynamicLib_Load2(&crypt32); - if (!lib) { Logger_DynamicLibWarn("loading", &crypt32); return; } - DynamicLib_GetAll(lib, funcs, Array_Elems(funcs)); + static const cc_string crypt32 = String_FromConst("CRYPT32.DLL"); + LoadDynamicFuncs(&crypt32, funcs, Array_Elems(funcs)); } cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { From 9a9114a9f9feccf05d50907cb0511ee16d755a42 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 4 Jun 2021 17:53:49 +1000 Subject: [PATCH 4/5] and implmenet fallback IP address parsing --- src/Platform_WinApi.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index df6527cf0..2a74252b4 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -381,6 +381,22 @@ void Platform_LoadSysFonts(void) { *#########################################################################################################################*/ static INT (WSAAPI *_WSAStringToAddressW)(LPWSTR addressString, INT addressFamily, LPVOID lpProtocolInfo, LPVOID address, LPINT addressLength); +static int FallbackParseAddress(SOCKADDR_IN* dst, const cc_string* ip, int port) { + cc_uint8* addr; + cc_string parts[4 + 1]; + /* +1 in case user tries '1.1.1.1.1' */ + if (String_UNSAFE_Split(ip, '.', parts, 4 + 1) != 4) return 0; + addr = (cc_uint8*)&dst->sin_addr; + + 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 0; + + dst->sin_family = AF_INET; + dst->sin_port = htons(port); + return AF_INET; +} + static void LoadWinsockFuncs(void) { static const struct DynamicLibSym funcs[1] = { DynamicLib_Sym(WSAStringToAddressW) @@ -388,6 +404,7 @@ static void LoadWinsockFuncs(void) { static const cc_string winsock32 = String_FromConst("WS2_32.DLL"); LoadDynamicFuncs(&winsock32, funcs, Array_Elems(funcs)); + _WSAStringToAddressW = NULL; } cc_result Socket_Available(cc_socket s, int* available) { @@ -406,6 +423,10 @@ static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { DWORD size; Platform_EncodeUtf16(str, address); + /* Fallback for older OS versions which lack WSAStringToAddressW */ + if (!_WSAStringToAddressW) + return FallbackParseAddress(addr4, address, port); + size = sizeof(*addr4); if (!_WSAStringToAddressW(str, AF_INET, NULL, (SOCKADDR*)addr4, &size)) { addr4->sin_port = htons(port); From 50b084dfbd559e77487f13cf5b9eae3c99793646 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 4 Jun 2021 19:35:43 +1000 Subject: [PATCH 5/5] Fix not connecting on old macOS --- src/Makefile | 2 +- src/Platform_Posix.c | 16 +++++++++++----- src/Platform_WinApi.c | 1 - 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 7ae38a656..7c8fe5b4f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,7 +41,7 @@ endif ifeq ($(PLAT),darwin) LIBS= -LDFLAGS=-rdynamic -framework Carbon -framework AGL -framework OpenGL +LDFLAGS=-rdynamic -framework Carbon -framework AGL -framework OpenGL -framework IOKit endif ifeq ($(PLAT),freebsd) diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index af2cfe141..3b2e7043d 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -459,7 +459,7 @@ cc_result Socket_GetError(cc_socket s, cc_result* result) { return getsockopt(s, SOL_SOCKET, SO_ERROR, result, &resultSize); } -static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { +static int ParseAddress(void* dst, const cc_string* address, int port, int* addrSize) { struct sockaddr_in* addr4 = (struct sockaddr_in* )dst; struct sockaddr_in6* addr6 = (struct sockaddr_in6*)dst; char str[NATIVE_STR_LEN]; @@ -468,11 +468,13 @@ static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { if (inet_pton(AF_INET, str, &addr4->sin_addr) > 0) { addr4->sin_family = AF_INET; addr4->sin_port = htons(port); + *addrSize = sizeof(struct sockaddr_in); return AF_INET; } if (inet_pton(AF_INET6, str, &addr6->sin6_addr) > 0) { addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(port); + *addrSize = sizeof(struct sockaddr_in6); return AF_INET6; } return 0; @@ -480,23 +482,24 @@ static int Socket_ParseAddress(void* dst, const cc_string* address, int port) { int Socket_ValidAddress(const cc_string* address) { struct sockaddr_storage addr; - return Socket_ParseAddress(&addr, address, 0); + int addrSize; + return ParseAddress(&addr, address, 0, &addrSize); } cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port) { - int family, blocking_raw = -1; /* non-blocking mode */ + int family, addrSize, blocking_raw = -1; /* non-blocking mode */ struct sockaddr_storage addr; cc_result res; *s = -1; - if (!(family = Socket_ParseAddress(&addr, address, port))) + if (!(family = ParseAddress(&addr, address, port, &addrSize))) return ERR_INVALID_ARGUMENT; *s = socket(family, SOCK_STREAM, IPPROTO_TCP); if (*s == -1) return errno; ioctl(*s, FIONBIO, &blocking_raw); - res = connect(*s, &addr, sizeof(addr)); + res = connect(*s, &addr, addrSize); return res == -1 ? errno : 0; } @@ -1195,6 +1198,7 @@ int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* arg argc--; argv++; /* skip executable path argument */ #ifdef CC_BUILD_DARWIN + /* Sometimes a "-psn_0_[number]" argument is added before actual args */ if (argc) { static const cc_string psn = String_FromConst("-psn_0_"); cc_string arg0 = String_FromReadonly(argv[0]); @@ -1204,6 +1208,7 @@ int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* arg count = min(argc, GAME_MAX_CMDARGS); for (i = 0; i < count; i++) { + /* -d[directory] argument to change directory data is stored in */ if (argv[i][0] == '-' && argv[i][1] == 'd' && argv[i][2]) { --count; continue; @@ -1242,6 +1247,7 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { static const cc_string bundle = String_FromConst(".app/Contents/MacOS/"); cc_string raw = String_Init(path, len, 0); + /* If running from within a bundle, set data folder to folder containing bundle */ if (String_CaselessEnds(&raw, &bundle)) { len -= bundle.length; diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index 2a74252b4..a16ec61c6 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -404,7 +404,6 @@ static void LoadWinsockFuncs(void) { static const cc_string winsock32 = String_FromConst("WS2_32.DLL"); LoadDynamicFuncs(&winsock32, funcs, Array_Elems(funcs)); - _WSAStringToAddressW = NULL; } cc_result Socket_Available(cc_socket s, int* available) {