Move consoles to use new socket parsing API, also improve PS3 input support

3DS seems to be broken though, not sure why yet
This commit is contained in:
UnknownShadow200 2023-12-23 23:29:59 +11:00
parent 39d582a88c
commit 4e05f3626f
21 changed files with 362 additions and 375 deletions

View File

@ -480,6 +480,7 @@
<ClCompile Include="Graphics_PSVita.c" /> <ClCompile Include="Graphics_PSVita.c" />
<ClCompile Include="Graphics_SoftGPU.c" /> <ClCompile Include="Graphics_SoftGPU.c" />
<ClCompile Include="Graphics_Xbox.c" /> <ClCompile Include="Graphics_Xbox.c" />
<ClCompile Include="Graphics_Xbox360.c" />
<ClCompile Include="Gui.c" /> <ClCompile Include="Gui.c" />
<ClCompile Include="HeldBlockRenderer.c" /> <ClCompile Include="HeldBlockRenderer.c" />
<ClCompile Include="Http_Web.c" /> <ClCompile Include="Http_Web.c" />
@ -507,6 +508,7 @@
<ClCompile Include="Platform_Web.c" /> <ClCompile Include="Platform_Web.c" />
<ClCompile Include="Platform_Windows.c" /> <ClCompile Include="Platform_Windows.c" />
<ClCompile Include="Platform_Xbox.c" /> <ClCompile Include="Platform_Xbox.c" />
<ClCompile Include="Platform_Xbox360.c" />
<ClCompile Include="Protocol.c" /> <ClCompile Include="Protocol.c" />
<ClCompile Include="Physics.c" /> <ClCompile Include="Physics.c" />
<ClCompile Include="IsometricDrawer.c" /> <ClCompile Include="IsometricDrawer.c" />
@ -550,6 +552,7 @@
<ClCompile Include="Window_Win.c" /> <ClCompile Include="Window_Win.c" />
<ClCompile Include="Window_X11.c" /> <ClCompile Include="Window_X11.c" />
<ClCompile Include="Window_Xbox.c" /> <ClCompile Include="Window_Xbox.c" />
<ClCompile Include="Window_Xbox360.c" />
<ClCompile Include="World.c" /> <ClCompile Include="World.c" />
<ClCompile Include="_autofit.c" /> <ClCompile Include="_autofit.c" />
<ClCompile Include="_cff.c" /> <ClCompile Include="_cff.c" />

View File

@ -704,6 +704,15 @@
<ClCompile Include="Commands.c"> <ClCompile Include="Commands.c">
<Filter>Source Files\Game</Filter> <Filter>Source Files\Game</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Platform_Xbox360.c">
<Filter>Source Files\Platform</Filter>
</ClCompile>
<ClCompile Include="Window_Xbox360.c">
<Filter>Source Files\Window</Filter>
</ClCompile>
<ClCompile Include="Graphics_Xbox360.c">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\misc\windows\CCicon.rc"> <ResourceCompile Include="..\misc\windows\CCicon.rc">

View File

@ -31,7 +31,7 @@ typedef unsigned int GLuint;
typedef float GLfloat; typedef float GLfloat;
typedef void GLvoid; typedef void GLvoid;
/* NOTE: With the OpenGL 1.1 backend "pointer" arguments are actual pointers, /* NOTE: With the OpenGL 1.1 backend "pointer" arguments are actual pointers, */
/* but with VBOs they are just offsets instead */ /* but with VBOs they are just offsets instead */
#ifdef CC_BUILD_GL11 #ifdef CC_BUILD_GL11
typedef const void* GLpointer; typedef const void* GLpointer;

View File

@ -450,7 +450,7 @@ void Gfx_SetVertexFormat(VertexFormat fmt) {
// TODO update cached primitive state // TODO update cached primitive state
} }
typedef struct Vector4 { float X, Y, Z, W; } Vector4; typedef struct Vector4 { float x, y, z, w; } Vector4;
static cc_bool NotClipped(Vector4 pos) { static cc_bool NotClipped(Vector4 pos) {
// The code below clips to the viewport clip planes // The code below clips to the viewport clip planes

View File

@ -517,7 +517,7 @@ static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct H
cc_uint16 portNum; cc_uint16 portNum;
cc_result res; cc_result res;
cc_sockaddr addrs[SOCKET_MAX_ADDRS]; cc_sockaddr addrs[SOCKET_MAX_ADDRS];
int numAddrs; int numValidAddrs;
/* address can be either "host" or "host:port" */ /* address can be either "host" or "host:port" */
String_UNSAFE_Separate(&url->address, ':', &host, &port); String_UNSAFE_Separate(&url->address, ':', &host, &port);
@ -527,7 +527,7 @@ static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct H
conn->socket = -1; conn->socket = -1;
conn->sslCtx = NULL; conn->sslCtx = NULL;
if ((res = Socket_ParseAddress(&host, portNum, addrs, &numAddrs))) return res; if ((res = Socket_ParseAddress(&host, portNum, addrs, &numValidAddrs))) return res;
/* TODO multi addresses support */ /* TODO multi addresses support */
if ((res = Socket_Connect(&conn->socket, &addrs[0], false))) return res; if ((res = Socket_Connect(&conn->socket, &addrs[0], false))) return res;

View File

@ -243,7 +243,7 @@ CC_API void Waitable_WaitFor(void* handle, cc_uint32 milliseconds);
void Platform_LoadSysFonts(void); void Platform_LoadSysFonts(void);
#define CC_SOCKETADDR_MAXSIZE 512 #define CC_SOCKETADDR_MAXSIZE 512
#define SOCKET_MAX_ADDRS 5 #define SOCKET_MAX_ADDRS 8
typedef struct cc_sockaddr_ { typedef struct cc_sockaddr_ {
int size; /* Actual size of the raw socket address */ int size; /* Actual size of the raw socket address */
@ -257,7 +257,7 @@ cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable);
cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable); cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable);
/* If the input represents an IP address, then parses the input into a single IP address */ /* If the input represents an IP address, then parses the input into a single IP address */
/* Otherwise, attempts to resolve the input via DNS into one or more IP addresses */ /* Otherwise, attempts to resolve the input via DNS into one or more IP addresses */
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numAddrs); cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs);
/* Allocates a new socket and then begins connecting to the given address */ /* Allocates a new socket and then begins connecting to the given address */
cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking); cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking);

View File

@ -285,59 +285,60 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw; char str[NATIVE_STR_LEN];
struct sockaddr_in v4; char portRaw[32]; cc_string portStr;
struct sockaddr_storage total; // matches max size of addr returned by getaddrinfo
};
static int ParseHost(union SocketAddress* addr, const char* host) {
struct addrinfo hints = { 0 }; struct addrinfo hints = { 0 };
struct addrinfo* result; struct addrinfo* result;
struct addrinfo* cur; struct addrinfo* cur;
int found = false; 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 have to have this path, otherwise Citra crashes when crashing connecting to server if you always use getaddrinfo instead
// Need to investigate further as I'm probably doing something wrong
// TODO still doesn't work
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
*numValidAddrs = 1;
return 0;
}
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
int res = getaddrinfo(host, NULL, &hints, &result); int res = getaddrinfo(str, portRaw, &hints, &result);
if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST; if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res; if (res) return res;
for (cur = result; cur; cur = cur->ai_next) { for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++)
if (cur->ai_family != AF_INET) continue; {
found = true; if (!cur->ai_addrlen) break;
// TODO citra returns empty addresses past first one? does that happen on real hardware too?
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
break; Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
addrs[i].size = cur->ai_addrlen;
} }
freeaddrinfo(result); freeaddrinfo(result);
return found ? 0 : ERR_INVALID_ARGUMENT; *numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
char str[NATIVE_STR_LEN]; struct sockaddr* raw = (struct sockaddr*)addr->data;
String_EncodeUtf8(str, address);
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) return 0;
return ParseHost(addr, str);
}
int Socket_ValidAddress(const cc_string* address) {
union SocketAddress addr;
return ParseAddress(&addr, address) == 0;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; *s = socket(raw->sa_family, SOCK_STREAM, 0); // https://www.3dbrew.org/wiki/SOCU:socket
if ((res = ParseAddress(&addr, address))) return res;
*s = socket(AF_INET, SOCK_STREAM, 0); // https://www.3dbrew.org/wiki/SOCU:socket
if (*s == -1) return errno; if (*s == -1) return errno;
if (nonblocking) { if (nonblocking) {
@ -345,10 +346,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
if (flags >= 0) fcntl(*s, F_SETFL, flags | O_NONBLOCK); if (flags >= 0) fcntl(*s, F_SETFL, flags | O_NONBLOCK);
} }
addr.v4.sin_family = AF_INET; res = connect(*s, raw, addr->size);
addr.v4.sin_port = htons(port);
res = connect(*s, &addr.raw, sizeof(addr.v4));
return res == -1 ? errno : 0; return res == -1 ? errno : 0;
} }

View File

@ -284,86 +284,52 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw; char str[NATIVE_STR_LEN];
struct sockaddr_in v4;
#ifdef AF_INET6
struct sockaddr_in6 v6;
struct sockaddr_storage total;
#endif
};
static int ParseHost(union SocketAddress* addr, const char* host) { char portRaw[32]; cc_string portStr;
struct addrinfo hints = { 0 }; struct addrinfo hints = { 0 };
struct addrinfo* result; struct addrinfo* result;
struct addrinfo* cur; struct addrinfo* cur;
int family = 0, res; int res, i = 0;
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
res = getaddrinfo(host, NULL, &hints, &result); res = getaddrinfo(str, portRaw, &hints, &result);
if (res) return 0; if (res == EAI_NONAME) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;
for (cur = result; cur; cur = cur->ai_next) { for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++)
if (cur->ai_family != AF_INET) continue; {
family = AF_INET; Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
addrs[i].size = cur->ai_addrlen;
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
break;
} }
freeaddrinfo(result); freeaddrinfo(result);
return family; *numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
char str[NATIVE_STR_LEN]; struct sockaddr* raw = (struct sockaddr*)addr->data;
String_EncodeUtf8(str, address);
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) return AF_INET;
#ifdef AF_INET6
if (inet_pton(AF_INET6, str, &addr->v6.sin6_addr) > 0) return AF_INET6;
#endif
return ParseHost(addr, str);
}
int Socket_ValidAddress(const cc_string* address) {
union SocketAddress addr;
return ParseAddress(&addr, address);
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
int family, addrSize = 0;
union SocketAddress addr;
cc_result res; cc_result res;
*s = -1; *s = socket(raw->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (!(family = ParseAddress(&addr, address)))
return ERR_INVALID_ARGUMENT;
*s = socket(family, SOCK_STREAM, IPPROTO_TCP);
if (*s == -1) return errno; if (*s == -1) return errno;
if (nonblocking) { if (nonblocking) {
fcntl(*s, F_SETFL, O_NONBLOCK); fcntl(*s, F_SETFL, O_NONBLOCK);
} }
#ifdef AF_INET6 res = connect(*s, raw, addr->size);
if (family == AF_INET6) {
addr.v6.sin6_family = AF_INET6;
addr.v6.sin6_port = htons(port);
addrSize = sizeof(addr.v6);
}
#endif
if (family == AF_INET) {
addr.v4.sin_family = AF_INET;
addr.v4.sin_port = htons(port);
addrSize = sizeof(addr.v4);
}
res = connect(*s, &addr.raw, addrSize);
return res == -1 ? errno : 0; return res == -1 ? errno : 0;
} }

View File

@ -360,51 +360,61 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw;
struct sockaddr_in v4;
};
static int ParseHost(union SocketAddress* addr, const char* host) {
#ifdef HW_RVL #ifdef HW_RVL
struct hostent* res = net_gethostbyname(host); struct hostent* res = net_gethostbyname(host);
struct sockaddr_in* addr4;
char* src_addr;
int i;
// avoid confusion with SSL error codes // avoid confusion with SSL error codes
// e.g. FFFF FFF7 > FF00 FFF7 // e.g. FFFF FFF7 > FF00 FFF7
if (!res) return -0xFF0000 + errno; if (!res) return -0xFF0000 + errno;
// Must have at least one IPv4 address // Must have at least one IPv4 address
if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT; if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT;
if (!res->h_addr_list[0]) return ERR_INVALID_ARGUMENT; if (!res->h_addr_list) return ERR_INVALID_ARGUMENT;
addr->v4.sin_addr = *(struct in_addr*)res->h_addr_list[0]; for (i = 0; i < SOCKET_MAX_ADDRS; i++)
return 0; {
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;
#else #else
// DNS resolution not implemented in gamecube libbba // DNS resolution not implemented in gamecube libbba
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
#endif #endif
} }
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
char str[NATIVE_STR_LEN]; char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 1;
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0; if (inet_aton(str, &addr4->sin_addr) > 0) {
return ParseHost(addr, str); addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
} }
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct sockaddr* raw = (struct sockaddr*)addr->data;
return ParseAddress(&addr, address) == 0;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; *s = net_socket(raw->sa_family, SOCK_STREAM, 0);
if ((res = ParseAddress(&addr, address))) return res;
*s = net_socket(AF_INET, SOCK_STREAM, 0);
if (*s < 0) return *s; if (*s < 0) return *s;
if (nonblocking) { if (nonblocking) {
@ -412,10 +422,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
net_ioctl(*s, FIONBIO, &blocking_raw); net_ioctl(*s, FIONBIO, &blocking_raw);
} }
addr.v4.sin_family = AF_INET; res = net_connect(*s, raw, addr->size);
addr.v4.sin_port = htons(port);
res = net_connect(*s, &addr.raw, sizeof(addr.v4));
return res < 0 ? res : 0; return res < 0 ? res : 0;
} }

View File

@ -219,11 +219,11 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
return false; return ERR_NOT_SUPPORTED;
} }
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
} }

View File

@ -460,49 +460,52 @@ static void Networking_LoadIOPModules(void) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw; char portRaw[32]; cc_string portStr;
struct sockaddr_in v4;
struct sockaddr_storage total; // matches max size of addr returned by getaddrinfo
};
static int ParseHost(union SocketAddress* addr, const char* host) {
struct addrinfo hints = { 0 }; struct addrinfo hints = { 0 };
struct addrinfo* result; struct addrinfo* result;
struct addrinfo* cur; struct addrinfo* cur;
int found = false; int res, i = 0;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
int res = getaddrinfo(host, NULL, &hints, &result); res = getaddrinfo(host, portRaw, &hints, &result);
if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST; if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res; if (res) return res;
for (cur = result; cur; cur = cur->ai_next) { for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++)
if (cur->ai_family != AF_INET) continue; {
found = true; Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
addrs[i].size = cur->ai_addrlen;
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
break;
} }
freeaddrinfo(result); freeaddrinfo(result);
return found ? 0 : ERR_INVALID_ARGUMENT; *numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { 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]; char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0; if (inet_aton(str, &addr4->sin_addr) > 0) {
return ParseHost(addr, str); addr4->sin_family = AF_INET;
} addr4->sin_port = htons(port);
int Socket_ValidAddress(const cc_string* address) { addrs[0].size = sizeof(*addr4);
union SocketAddress addr; *numValidAddrs = 1;
return ParseAddress(&addr, address) == 0; return 0;
}
return ParseHost(str, port, addrs, numValidAddrs);
} }
static cc_result GetSocketError(cc_socket s) { static cc_result GetSocketError(cc_socket s) {
@ -512,14 +515,11 @@ static cc_result GetSocketError(cc_socket s) {
return res; return res;
} }
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct sockaddr* raw = (struct sockaddr*)addr->data;
int res; int res;
*s = -1; *s = socket(raw->sa_family, SOCK_STREAM, 0);
if ((res = ParseAddress(&addr, address))) return res;
*s = socket(AF_INET, SOCK_STREAM, 0);
if (*s < 0) return *s; if (*s < 0) return *s;
if (nonblocking) { if (nonblocking) {
@ -527,10 +527,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
//ioctlsocket(*s, FIONBIO, &blocking_raw); TODO doesn't work //ioctlsocket(*s, FIONBIO, &blocking_raw); TODO doesn't work
} }
addr.v4.sin_family = AF_INET; res = connect(*s, raw, addr->size);
addr.v4.sin_port = htons(port);
res = connect(*s, &addr.raw, sizeof(addr.v4));
return res == -1 ? GetSocketError(*s) : 0; return res == -1 ? GetSocketError(*s) : 0;
} }

View File

@ -339,44 +339,57 @@ union SocketAddress {
struct sockaddr raw; struct sockaddr raw;
struct sockaddr_in v4; struct sockaddr_in v4;
}; };
static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
static int ParseHost(union SocketAddress* addr, const char* host) {
struct net_hostent* res = netGetHostByName(host); struct net_hostent* res = netGetHostByName(host);
struct sockaddr_in* addr4;
if (!res) return net_h_errno; if (!res) return net_h_errno;
// Must have at least one IPv4 address // Must have at least one IPv4 address
if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT; if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT;
if (!res->h_addr_list) return ERR_INVALID_ARGUMENT; if (!res->h_addr_list) return ERR_INVALID_ARGUMENT;
u32* addrlist = (u32*)res->h_addr_list; // each address pointer is only 4 bytes long
char* addr0 = (char*)addrlist[0]; u32* addr_list = (u32*)res->h_addr_list;
char* src_addr;
addr->v4.sin_addr = *(struct in_addr*)addr0; int i;
return 0;
for (i = 0; i < SOCKET_MAX_ADDRS; i++)
{
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;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { 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]; char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0; if (inet_aton(str, &addr4->sin_addr) > 0) {
return ParseHost(addr, str); 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);
} }
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct sockaddr* raw = (struct sockaddr*)addr->data;
return ParseAddress(&addr, address) == 0;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; res = netSocket(raw->sa_family, SOCK_STREAM, IPPROTO_TCP);
res = ParseAddress(&addr, address);
if (res) return res;
res = netSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (res < 0) return net_errno; if (res < 0) return net_errno;
*s = res; *s = res;
@ -385,10 +398,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
netSetSockOpt(*s, SOL_SOCKET, SO_NBIO, &on, sizeof(int)); netSetSockOpt(*s, SOL_SOCKET, SO_NBIO, &on, sizeof(int));
} }
addr.v4.sin_family = AF_INET; res = netConnect(*s, raw, addr->size);
addr.v4.sin_port = htons(port);
res = netConnect(*s, &addr.raw, sizeof(addr.v4));
return res < 0 ? net_errno : 0; return res < 0 ? net_errno : 0;
} }

View File

@ -292,54 +292,45 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw; struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data;
struct sockaddr_in v4; char str[NATIVE_STR_LEN];
};
static int ParseHost(union SocketAddress* addr, const char* host) {
char buf[1024]; char buf[1024];
int rid, ret; int rid, ret;
if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0) return 0;
ret = sceNetResolverStartNtoA(rid, host, &addr->v4.sin_addr, 1 /* timeout */, 5 /* retries */);
sceNetResolverDelete(rid);
return ret >= 0;
}
static int ParseAddress(union SocketAddress* addr, const cc_string* address) {
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 1;
if (sceNetInetInetPton(AF_INET,str, &addr->v4.sin_addr) > 0) return true; if (sceNetInetInetPton(AF_INET, str, &addr4->sin_addr) <= 0) {
return ParseHost(addr, str); /* 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;
}
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
addrs[0].size = sizeof(*addr4);
return 0;
} }
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct sockaddr* raw = (struct sockaddr*)addr->data;
return ParseAddress(&addr, address);
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; *s = sceNetInetSocket(raw->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (!ParseAddress(&addr, address)) return ERR_INVALID_ARGUMENT;
*s = sceNetInetSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*s < 0) return sceNetInetGetErrno(); if (*s < 0) return sceNetInetGetErrno();
if (nonblocking) { if (nonblocking) {
int on = 1; int on = 1;
sceNetInetSetsockopt(*s, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)); sceNetInetSetsockopt(*s, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int));
} }
addr.v4.sin_family = AF_INET;
addr.v4.sin_port = htons(port);
res = sceNetInetConnect(*s, &addr.raw, sizeof(addr.v4)); res = sceNetInetConnect(*s, raw, addr->size);
return res < 0 ? sceNetInetGetErrno() : 0; return res < 0 ? sceNetInetGetErrno() : 0;
} }

View File

@ -280,52 +280,45 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct SceNetSockaddr raw; struct SceNetSockaddrIn* addr4 = (struct SceNetSockaddrIn*)addrs[0].data;
struct SceNetSockaddrIn v4;
};
static int ParseHost(union SocketAddress* addr, const char* host) {
int rid = sceNetResolverCreate("CC resolver", NULL, 0);
if (rid < 0) return ERR_INVALID_ARGUMENT;
int ret = sceNetResolverStartNtoa(rid, host, &addr->v4.sin_addr, 0, 0, 0);
sceNetResolverDestroy(rid);
return ret;
}
static int ParseAddress(union SocketAddress* addr, const cc_string* address) {
char str[NATIVE_STR_LEN]; char str[NATIVE_STR_LEN];
char buf[1024];
int rid, ret;
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 1;
if (sceNetInetPton(SCE_NET_AF_INET, str, &addr->v4.sin_addr) > 0) return 0; if (sceNetInetPton(SCE_NET_AF_INET, str, &addr4->sin_addr) <= 0) {
return ParseHost(addr, str); /* 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;
}
addr4->sin_family = SCE_NET_AF_INET;
addr4->sin_port = sceNetHtons(port);
addrs[0].size = sizeof(*addr4);
return 0;
} }
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct SceNetSockaddr* raw = (struct SceNetSockaddr*)addr->data;
return ParseAddress(&addr, address) == 0;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; *s = sceNetSocket("CC socket", raw->sa_family, SCE_NET_SOCK_STREAM, SCE_NET_IPPROTO_TCP);
if ((res = ParseAddress(&addr, address))) return res;
*s = sceNetSocket("CC socket", SCE_NET_AF_INET, SCE_NET_SOCK_STREAM, SCE_NET_IPPROTO_TCP);
if (*s < 0) return *s; if (*s < 0) return *s;
if (nonblocking) { if (nonblocking) {
int on = 1; int on = 1;
sceNetSetsockopt(*s, SCE_NET_SOL_SOCKET, SCE_NET_SO_NBIO, &on, sizeof(int)); sceNetSetsockopt(*s, SCE_NET_SOL_SOCKET, SCE_NET_SO_NBIO, &on, sizeof(int));
} }
addr.v4.sin_family = SCE_NET_AF_INET;
addr.v4.sin_port = sceNetHtons(port);
res = sceNetConnect(*s, &addr.raw, sizeof(addr.v4)); res = sceNetConnect(*s, raw, addr->size);
return res; return res;
} }

View File

@ -528,58 +528,82 @@ union SocketAddress {
struct sockaddr_storage total; struct sockaddr_storage total;
#endif #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];
static int ParseHost(union SocketAddress* addr, const char* host) { 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 hints = { 0 };
struct addrinfo* result; struct addrinfo* result;
struct addrinfo* cur; struct addrinfo* cur;
int family = 0, res; int res, i = 0;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
res = getaddrinfo(host, NULL, &hints, &result); res = getaddrinfo(host, portRaw, &hints, &result);
if (res) return 0; if (res == EAI_AGAIN) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;
for (cur = result; cur; cur = cur->ai_next) { /* Prefer IPv4 addresses first */
for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next)
{
if (cur->ai_family != AF_INET) continue; if (cur->ai_family != AF_INET) continue;
family = AF_INET; Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
addrs[i].size = cur->ai_addrlen; i++;
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen); }
break;
for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next)
{
if (cur->ai_family == AF_INET) continue;
Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
addrs[i].size = cur->ai_addrlen; i++;
} }
freeaddrinfo(result); freeaddrinfo(result);
return family; *numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { 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]; char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address); String_EncodeUtf8(str, address);
*numValidAddrs = 0;
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) return AF_INET; 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 #ifdef AF_INET6
if (inet_pton(AF_INET6, str, &addr->v6.sin6_addr) > 0) return 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 #endif
return ParseHost(addr, str);
return ParseHost(str, port, addrs, numValidAddrs);
} }
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
union SocketAddress addr; struct sockaddr* raw = (struct sockaddr*)addr->data;
return ParseAddress(&addr, address);
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
int family, addrSize = 0;
union SocketAddress addr;
cc_result res; cc_result res;
*s = -1; *s = socket(raw->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (!(family = ParseAddress(&addr, address)))
return ERR_INVALID_ARGUMENT;
*s = socket(family, SOCK_STREAM, IPPROTO_TCP);
if (*s == -1) return errno; if (*s == -1) return errno;
if (nonblocking) { if (nonblocking) {
@ -587,20 +611,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
ioctl(*s, FIONBIO, &blocking_raw); ioctl(*s, FIONBIO, &blocking_raw);
} }
#ifdef AF_INET6 res = connect(*s, raw, addr->size);
if (family == AF_INET6) {
addr.v6.sin6_family = AF_INET6;
addr.v6.sin6_port = htons(port);
addrSize = sizeof(addr.v6);
}
#endif
if (family == AF_INET) {
addr.v4.sin_family = AF_INET;
addr.v4.sin_port = htons(port);
addrSize = sizeof(addr.v4);
}
res = connect(*s, &addr.raw, addrSize);
return res == -1 ? errno : 0; return res == -1 ? errno : 0;
} }
@ -1421,4 +1432,4 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) {
return chdir(path) == -1 ? errno : 0; return chdir(path) == -1 ? errno : 0;
} }
#endif #endif
#endif #endif

View File

@ -251,13 +251,13 @@ void Platform_LoadSysFonts(void) { }
*#########################################################################################################################*/ *#########################################################################################################################*/
extern void interop_InitSockets(void); extern void interop_InitSockets(void);
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numAddrs) { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
int len = String_EncodeUtf8(addrs[0].data, address); int len = String_EncodeUtf8(addrs[0].data, address);
/* TODO can this ever happen */ /* TODO can this ever happen */
if (len >= CC_SOCKETADDR_MAXSIZE) Logger_Abort("Overrun in Socket_ParseAddress"); if (len >= CC_SOCKETADDR_MAXSIZE) Logger_Abort("Overrun in Socket_ParseAddress");
addrs[0].size = port; addrs[0].size = port;
*numAddrs = 1; *numValidAddrs = 1;
return 0; return 0;
} }

View File

@ -459,10 +459,9 @@ static void LoadWinsockFuncs(void) {
if (!_WSAStringToAddressW) _WSAStringToAddressW = FallbackParseAddress; if (!_WSAStringToAddressW) _WSAStringToAddressW = FallbackParseAddress;
} }
static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numAddrs) { static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct hostent* res; struct hostent* res;
cc_result wsa_res; cc_result wsa_res;
cc_sockaddr* dst_addr;
SOCKADDR_IN* addr4; SOCKADDR_IN* addr4;
char* src_addr; char* src_addr;
int i; int i;
@ -478,41 +477,40 @@ static cc_result ParseHost(char* host, int port, cc_sockaddr* addrs, int* numAdd
/* per MSDN, should only be getting AF_INET returned from this */ /* per MSDN, should only be getting AF_INET returned from this */
if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT; 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++) for (i = 0; i < SOCKET_MAX_ADDRS; i++)
{ {
src_addr = res->h_addr_list[i]; src_addr = res->h_addr_list[i];
if (!src_addr) break; if (!src_addr) break;
addrs[i].size = sizeof(SOCKADDR_IN);
dst_addr = &addrs[i]; addr4 = (SOCKADDR_IN*)addrs[i].data;
dst_addr->size = sizeof(SOCKADDR_IN);
addr4 = (SOCKADDR_IN*)dst_addr->data;
addr4->sin_family = AF_INET; addr4->sin_family = AF_INET;
addr4->sin_port = _htons(port); addr4->sin_port = _htons(port);
addr4->sin_addr = *(IN_ADDR*)src_addr; addr4->sin_addr = *(IN_ADDR*)src_addr;
} }
*numAddrs = i; *numValidAddrs = i;
/* Must have at least one IPv4 address */ /* Must have at least one IPv4 address */
return i == 0 ? ERR_INVALID_ARGUMENT : 0; return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numAddrs) { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
SOCKADDR_IN* addr4 = (SOCKADDR_IN* )addrs[0].data; SOCKADDR_IN* addr4 = (SOCKADDR_IN* )addrs[0].data;
SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)addrs[0].data; SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)addrs[0].data;
cc_winstring str; cc_winstring str;
INT size; INT size;
*numAddrs = 0; *numValidAddrs = 0;
Platform_EncodeString(&str, address); Platform_EncodeString(&str, address);
size = sizeof(*addr4); size = sizeof(*addr4);
if (!_WSAStringToAddressW(str.uni, AF_INET, NULL, addr4, &size)) { if (!_WSAStringToAddressW(str.uni, AF_INET, NULL, addr4, &size)) {
addr4->sin_port = _htons(port); addr4->sin_port = _htons(port);
addrs[0].size = size; addrs[0].size = size;
*numAddrs = 1; *numValidAddrs = 1;
return 0; return 0;
} }
@ -520,12 +518,12 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a
if (!_WSAStringToAddressW(str.uni, AF_INET6, NULL, addr6, &size)) { if (!_WSAStringToAddressW(str.uni, AF_INET6, NULL, addr6, &size)) {
addr6->sin6_port = _htons(port); addr6->sin6_port = _htons(port);
addrs[0].size = size; addrs[0].size = size;
*numAddrs = 1; *numValidAddrs = 1;
return 0; return 0;
} }
return ParseHost(str.ansi, port, addrs, numAddrs); return ParseHost(str.ansi, port, addrs, numValidAddrs);
} }
cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {

View File

@ -296,62 +296,44 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
union SocketAddress { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
struct sockaddr raw; char str[NATIVE_STR_LEN];
struct sockaddr_in v4; char portRaw[32]; cc_string portStr;
struct sockaddr_storage total; // needed for lwip_getaddrinfo
};
static int ParseHost(union SocketAddress* addr, const char* host) {
struct addrinfo hints = { 0 }; struct addrinfo hints = { 0 };
struct addrinfo* result; struct addrinfo* result;
struct addrinfo* cur; struct addrinfo* cur;
int found = 0, res; int i = 0;
String_EncodeUtf8(str, address);
*numValidAddrs = 0;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
String_InitArray(portStr, portRaw);
String_AppendInt(&portStr, port);
portRaw[portStr.length] = '\0';
res = lwip_getaddrinfo(host, NULL, &hints, &result); int res = lwip_getaddrinfo(str, portRaw, &hints, &result);
if (res == EAI_FAIL) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res; if (res) return res;
for (cur = result; cur; cur = cur->ai_next) for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++)
{ {
if (cur->ai_family != AF_INET) continue; Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen);
found = true; addrs[i].size = cur->ai_addrlen;
// NOTE: cur->ai_addrlen will always be set to sizeof(struct sockaddr_storage) by lwip
// https://github.com/m-labs/lwip/blob/0178d1d2ee35fb82ab0a13256425f9aa33b08f60/src/api/netdb.c#L402C20-L402C52
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
break;
} }
lwip_freeaddrinfo(result); lwip_freeaddrinfo(result);
return found ? 0 : ERR_INVALID_ARGUMENT; *numValidAddrs = i;
return i == 0 ? ERR_INVALID_ARGUMENT : 0;
} }
static int ParseAddress(union SocketAddress* addr, const cc_string* address) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
char str[NATIVE_STR_LEN]; struct sockaddr* raw = (struct sockaddr*)addr->data;
String_EncodeUtf8(str, address);
if (inet_pton(AF_INET, str, &addr->v4.sin_addr) > 0) return 0;
return ParseHost(addr, str);
}
int Socket_ValidAddress(const cc_string* address) {
union SocketAddress addr;
return ParseAddress(&addr, address) == 0;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
union SocketAddress addr;
int res; int res;
*s = -1; *s = lwip_socket(raw->sa_family, SOCK_STREAM, 0);
res = ParseAddress(&addr, address);
if (res) return res;
*s = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (*s == -1) return errno; if (*s == -1) return errno;
if (nonblocking) { if (nonblocking) {
@ -359,10 +341,7 @@ cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bo
lwip_ioctl(*s, FIONBIO, &blocking_raw); lwip_ioctl(*s, FIONBIO, &blocking_raw);
} }
addr.v4.sin_family = AF_INET; res = lwip_connect(*s, raw, addr->size);
addr.v4.sin_port = htons(port);
res = lwip_connect(*s, &addr.raw, sizeof(addr.v4));
return res == -1 ? errno : 0; return res == -1 ? errno : 0;
} }

View File

@ -241,11 +241,11 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
int Socket_ValidAddress(const cc_string* address) { cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
return false; return ERR_NOT_SUPPORTED;
} }
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) { cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
} }

View File

@ -280,7 +280,7 @@ static void MPConnection_BeginConnect(void) {
static const cc_string invalid_reason = String_FromConst("Invalid IP address"); static const cc_string invalid_reason = String_FromConst("Invalid IP address");
cc_string title; char titleBuffer[STRING_SIZE]; cc_string title; char titleBuffer[STRING_SIZE];
cc_sockaddr addrs[SOCKET_MAX_ADDRS]; cc_sockaddr addrs[SOCKET_MAX_ADDRS];
int numAddrs; int numValidAddrs;
cc_result res; cc_result res;
String_InitArray(title, titleBuffer); String_InitArray(title, titleBuffer);
@ -292,7 +292,7 @@ static void MPConnection_BeginConnect(void) {
Blocks.CanPlace[BLOCK_STILL_WATER] = false; Blocks.CanDelete[BLOCK_STILL_WATER] = false; Blocks.CanPlace[BLOCK_STILL_WATER] = false; Blocks.CanDelete[BLOCK_STILL_WATER] = false;
Blocks.CanPlace[BLOCK_BEDROCK] = false; Blocks.CanDelete[BLOCK_BEDROCK] = false; Blocks.CanPlace[BLOCK_BEDROCK] = false; Blocks.CanDelete[BLOCK_BEDROCK] = false;
res = Socket_ParseAddress(&Server.Address, Server.Port, addrs, &numAddrs); res = Socket_ParseAddress(&Server.Address, Server.Port, addrs, &numValidAddrs);
if (res == ERR_INVALID_ARGUMENT) { if (res == ERR_INVALID_ARGUMENT) {
MPConnection_Fail(&invalid_reason); return; MPConnection_Fail(&invalid_reason); return;
} else if (res) { } else if (res) {

View File

@ -155,11 +155,36 @@ static int MapKey(int k) {
} }
return 0; return 0;
} }
static cc_bool kb_deferredClear;
static void ProcessKBButtons(void) { static void ProcessKBButtons(void) {
// PS3 keyboard APIs only seem to return current keys pressed ? // PS3 keyboard APIs only seem to return current keys pressed,
if (!kb_data.nb_keycode) return; // which is a massive pain to work with
//
// The API is really strange and when pressing two keys produces e.g.
// - Event 1) pressed 82
// - Event 2) pressed 46
// instead of
// - Event 1) pressed 82
// - Event 2) pressed 82 46
//
// Additionally on real hardware, the following events when observed
// - Releasing key: [key] [0]
// - Holding key: [key] [0] [key] [0] [key] [0]
// I don't really know why this happens, so try to detect this by
// deferring resetting all keys to next Window_ProcessEvents
// TODO properly investigate this
if (kb_deferredClear && (kb_data.nb_keycode == 0 || kb_data.keycode[0] == 0)) {
Mem_Set(now_pressed, 0, sizeof(now_pressed));
kb_deferredClear = false;
} else {
kb_deferredClear = false;
if (!kb_data.nb_keycode) return;
}
// possibly unpress all keys next time around
if (kb_data.keycode[0] == 0) kb_deferredClear = true;
Mem_Set(now_pressed, 0, sizeof(now_pressed));
for (int i = 0; i < kb_data.nb_keycode; i++) for (int i = 0; i < kb_data.nb_keycode; i++)
{ {
int rawcode = kb_data.keycode[i]; int rawcode = kb_data.keycode[i];
@ -248,7 +273,7 @@ static void HandleJoystick_Left(int x, int y) {
} }
static void HandleJoystick_Right(int x, int y, double delta) { static void HandleJoystick_Right(int x, int y, double delta) {
float scale = (delta * 60.0) / 64.0f; float scale = (delta * 60.0) / 32.0f;
if (Math_AbsI(x) <= 32) x = 0; if (Math_AbsI(x) <= 32) x = 0;
if (Math_AbsI(y) <= 32) y = 0; if (Math_AbsI(y) <= 32) y = 0;