Wii: Add network socket support

This commit is contained in:
Vicki Pfau 2020-02-08 17:46:56 -08:00
parent 5d20aac7ed
commit 4f327de210
1 changed files with 77 additions and 6 deletions

View File

@ -20,15 +20,21 @@ CXX_GUARD_START
#define SOCKET_FAILED(s) ((s) == INVALID_SOCKET) #define SOCKET_FAILED(s) ((s) == INVALID_SOCKET)
typedef SOCKET Socket; typedef SOCKET Socket;
#else #else
#ifdef GEKKO
#include <network.h>
#else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#ifndef GEKKO
#define INVALID_SOCKET (-1) #define INVALID_SOCKET (-1)
#endif
#define SOCKET_FAILED(s) ((s) < 0) #define SOCKET_FAILED(s) ((s) < 0)
typedef int Socket; typedef int Socket;
#endif #endif
@ -70,6 +76,8 @@ static inline void SocketSubsystemInit() {
} }
#elif defined(__SWITCH__) #elif defined(__SWITCH__)
socketInitializeDefault(); socketInitializeDefault();
#elif defined(GEKKO)
net_init();
#endif #endif
} }
@ -82,6 +90,8 @@ static inline void SocketSubsystemDeinit() {
SOCUBuffer = NULL; SOCUBuffer = NULL;
#elif defined(__SWITCH__) #elif defined(__SWITCH__)
socketExit(); socketExit();
#elif defined(GEKKO)
net_deinit();
#endif #endif
} }
@ -104,6 +114,8 @@ static inline bool SocketWouldBlock() {
static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) { static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) {
#ifdef _WIN32 #ifdef _WIN32
return send(socket, (const char*) buffer, size, 0); return send(socket, (const char*) buffer, size, 0);
#elif defined(GEKKO)
return net_write(socket, buffer, size);
#else #else
return write(socket, buffer, size); return write(socket, buffer, size);
#endif #endif
@ -112,6 +124,8 @@ static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size)
static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) { static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) {
#if defined(_WIN32) || defined(__SWITCH__) #if defined(_WIN32) || defined(__SWITCH__)
return recv(socket, (char*) buffer, size, 0); return recv(socket, (char*) buffer, size, 0);
#elif defined(GEKKO)
return net_read(socket, buffer, size);
#else #else
return read(socket, buffer, size); return read(socket, buffer, size);
#endif #endif
@ -120,13 +134,19 @@ static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) {
static inline int SocketClose(Socket socket) { static inline int SocketClose(Socket socket) {
#ifdef _WIN32 #ifdef _WIN32
return closesocket(socket) == 0; return closesocket(socket) == 0;
#elif defined(GEKKO)
return net_close(socket) >= 0;
#else #else
return close(socket) >= 0; return close(socket) >= 0;
#endif #endif
} }
static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) { static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) {
#ifdef GEKKO
Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
#else
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
if (SOCKET_FAILED(sock)) { if (SOCKET_FAILED(sock)) {
return sock; return sock;
} }
@ -142,15 +162,23 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
#else #else
bindInfo.sin_addr.s_addr = gethostid(); bindInfo.sin_addr.s_addr = gethostid();
#endif #endif
#ifdef GEKKO
err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo));
#else
err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#endif
} else if (bindAddress->version == IPV4) { } else if (bindAddress->version == IPV4) {
struct sockaddr_in bindInfo; struct sockaddr_in bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo)); memset(&bindInfo, 0, sizeof(bindInfo));
bindInfo.sin_family = AF_INET; bindInfo.sin_family = AF_INET;
bindInfo.sin_port = htons(port); bindInfo.sin_port = htons(port);
bindInfo.sin_addr.s_addr = htonl(bindAddress->ipv4); bindInfo.sin_addr.s_addr = htonl(bindAddress->ipv4);
#ifdef GEKKO
err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo));
#else
err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#ifndef _3DS #endif
#if !defined(_3DS) && !defined(GEKKO)
} else { } else {
struct sockaddr_in6 bindInfo; struct sockaddr_in6 bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo)); memset(&bindInfo, 0, sizeof(bindInfo));
@ -168,7 +196,11 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
} }
static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) { static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) {
#ifdef GEKKO
Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
#else
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
if (SOCKET_FAILED(sock)) { if (SOCKET_FAILED(sock)) {
return sock; return sock;
} }
@ -179,15 +211,23 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio
memset(&bindInfo, 0, sizeof(bindInfo)); memset(&bindInfo, 0, sizeof(bindInfo));
bindInfo.sin_family = AF_INET; bindInfo.sin_family = AF_INET;
bindInfo.sin_port = htons(port); bindInfo.sin_port = htons(port);
#ifdef GEKKO
err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo));
#else
err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#endif
} else if (destinationAddress->version == IPV4) { } else if (destinationAddress->version == IPV4) {
struct sockaddr_in bindInfo; struct sockaddr_in bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo)); memset(&bindInfo, 0, sizeof(bindInfo));
bindInfo.sin_family = AF_INET; bindInfo.sin_family = AF_INET;
bindInfo.sin_port = htons(port); bindInfo.sin_port = htons(port);
bindInfo.sin_addr.s_addr = htonl(destinationAddress->ipv4); bindInfo.sin_addr.s_addr = htonl(destinationAddress->ipv4);
#ifdef GEKKO
err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo));
#else
err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
#ifndef _3DS #endif
#if !defined(_3DS) && !defined(GEKKO)
} else { } else {
struct sockaddr_in6 bindInfo; struct sockaddr_in6 bindInfo;
memset(&bindInfo, 0, sizeof(bindInfo)); memset(&bindInfo, 0, sizeof(bindInfo));
@ -206,12 +246,23 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio
} }
static inline Socket SocketListen(Socket socket, int queueLength) { static inline Socket SocketListen(Socket socket, int queueLength) {
#ifdef GEKKO
return net_listen(socket, queueLength);
#else
return listen(socket, queueLength); return listen(socket, queueLength);
#endif
} }
static inline Socket SocketAccept(Socket socket, struct Address* address) { static inline Socket SocketAccept(Socket socket, struct Address* address) {
if (!address) { if (!address) {
#ifdef GEKKO
struct sockaddr_in addrInfo;
memset(&addrInfo, 0, sizeof(addrInfo));
socklen_t len = sizeof(addrInfo);
return net_accept(socket, (struct sockaddr*) &addrInfo, &len);
#else
return accept(socket, 0, 0); return accept(socket, 0, 0);
#endif
} }
if (address->version == IPV4) { if (address->version == IPV4) {
struct sockaddr_in addrInfo; struct sockaddr_in addrInfo;
@ -219,8 +270,12 @@ static inline Socket SocketAccept(Socket socket, struct Address* address) {
addrInfo.sin_family = AF_INET; addrInfo.sin_family = AF_INET;
addrInfo.sin_addr.s_addr = address->ipv4; addrInfo.sin_addr.s_addr = address->ipv4;
socklen_t len = sizeof(addrInfo); socklen_t len = sizeof(addrInfo);
#ifdef GEKKO
return net_accept(socket, (struct sockaddr*) &addrInfo, &len);
#else
return accept(socket, (struct sockaddr*) &addrInfo, &len); return accept(socket, (struct sockaddr*) &addrInfo, &len);
#ifndef _3DS #endif
#if !defined(_3DS) && !defined(GEKKO)
} else { } else {
struct sockaddr_in6 addrInfo; struct sockaddr_in6 addrInfo;
memset(&addrInfo, 0, sizeof(addrInfo)); memset(&addrInfo, 0, sizeof(addrInfo));
@ -237,8 +292,12 @@ static inline int SocketSetBlocking(Socket socket, bool blocking) {
#ifdef _WIN32 #ifdef _WIN32
u_long unblocking = !blocking; u_long unblocking = !blocking;
return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR; return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR;
#else
#ifdef GEKKO
int flags = net_fcntl(socket, F_GETFL, 0);
#else #else
int flags = fcntl(socket, F_GETFL); int flags = fcntl(socket, F_GETFL);
#endif
if (flags == -1) { if (flags == -1) {
return 0; return 0;
} }
@ -247,12 +306,20 @@ static inline int SocketSetBlocking(Socket socket, bool blocking) {
} else { } else {
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
} }
#ifdef GEKKO
return net_fcntl(socket, F_SETFL, flags) >= 0;
#else
return fcntl(socket, F_SETFL, flags) >= 0; return fcntl(socket, F_SETFL, flags) >= 0;
#endif #endif
#endif
} }
static inline int SocketSetTCPPush(Socket socket, int push) { static inline int SocketSetTCPPush(Socket socket, int push) {
#ifdef GEKKO
return net_setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0;
#else
return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0; return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0;
#endif
} }
static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Socket* errors, int64_t timeoutMillis) { static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Socket* errors, int64_t timeoutMillis) {
@ -304,7 +371,11 @@ static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Soc
struct timeval tv; struct timeval tv;
tv.tv_sec = timeoutMillis / 1000; tv.tv_sec = timeoutMillis / 1000;
tv.tv_usec = (timeoutMillis % 1000) * 1000; tv.tv_usec = (timeoutMillis % 1000) * 1000;
#ifdef GEKKO
int result = net_select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv);
#else
int result = select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv); int result = select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv);
#endif
int r = 0; int r = 0;
int w = 0; int w = 0;
int e = 0; int e = 0;