Util: Support IPv6
@@ -15,6 +15,7 @@ - Support for games using the tilt sensor
- Remappable shortcuts for keyboard and gamepad - Rewinding of emulation - Implemented BIOS routines SoftReset, RegisterRamReset, Diff8bitUnFilterWram, Diff8bitUnFilterVram, and Diff16bitUnFilter + - Support IPv6 Bugfixes: - Qt: Fix issue with set frame sizes being the wrong height - Qt: Fix emulator crashing when full screen if a game is not running
@@ -446,11 +446,10 @@ stub->d.entered = _gdbStubEntered;
stub->d.log = 0; } -int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) { +int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) { if (!SOCKET_FAILED(stub->socket)) { GDBStubShutdown(stub); } - // TODO: support IPv6 stub->socket = SocketOpenTCP(port, bindAddress); if (SOCKET_FAILED(stub->socket)) { if (stub->d.log) {@@ -500,7 +499,7 @@ if (stub->socket == INVALID_SOCKET) {
return; } if (stub->connection == INVALID_SOCKET) { - stub->connection = SocketAccept(stub->socket, 0, 0); + stub->connection = SocketAccept(stub->socket, 0); if (!SOCKET_FAILED(stub->connection)) { if (!SocketSetBlocking(stub->connection, 0)) { goto connectionLost;
@@ -33,7 +33,7 @@ Socket connection;
}; void GDBStubCreate(struct GDBStub*); -int GDBStubListen(struct GDBStub*, int port, uint32_t bindAddress); +int GDBStubListen(struct GDBStub*, int port, const struct Address* bindAddress); void GDBStubHangup(struct GDBStub*); void GDBStubShutdown(struct GDBStub*);
@@ -13,7 +13,7 @@ GDBController::GDBController(GameController* controller, QObject* parent)
: QObject(parent) , m_gameController(controller) , m_port(2345) - , m_bindAddress(0) + , m_bindAddress({ IPV4, 0 }) { GDBStubCreate(&m_gdbStub); }@@ -22,10 +22,6 @@ ushort GDBController::port() {
return m_port; } -uint32_t GDBController::bindAddress() { - return m_bindAddress; -} - bool GDBController::isAttached() { return m_gameController->debugger() == &m_gdbStub.d; }@@ -35,7 +31,8 @@ m_port = port;
} void GDBController::setBindAddress(uint32_t bindAddress) { - m_bindAddress = bindAddress; + m_bindAddress.version = IPV4; + m_bindAddress.ipv4 = htonl(bindAddress); } void GDBController::attach() {@@ -62,7 +59,7 @@ if (!isAttached()) {
attach(); } connect(m_gameController, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateGDB())); - GDBStubListen(&m_gdbStub, m_port, m_bindAddress); + GDBStubListen(&m_gdbStub, m_port, &m_bindAddress); m_gameController->threadContinue(); }
@@ -26,7 +26,6 @@ GDBController(GameController* controller, QObject* parent = nullptr);
public: ushort port(); - uint32_t bindAddress(); bool isAttached(); public slots:@@ -44,7 +43,7 @@ GDBStub m_gdbStub;
GameController* m_gameController; ushort m_port; - uint32_t m_bindAddress; + Address m_bindAddress; }; }
@@ -29,6 +29,18 @@ #define SOCKET_FAILED(s) (s) < 0
typedef int Socket; #endif +enum IP { + IPV4, + IPV6 +}; + +struct Address { + enum IP version; + union { + uint32_t ipv4; + uint8_t ipv6[16]; + }; +}; static inline void SocketSubsystemInitialize() { #ifdef _WIN32@@ -44,18 +56,35 @@ static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) {
return read(socket, buffer, size); } -static inline Socket SocketOpenTCP(int port, uint32_t bindAddress) { +static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) { Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SOCKET_FAILED(sock)) { return sock; } - struct sockaddr_in bindInfo; - memset(&bindInfo, 0, sizeof(bindInfo)); - bindInfo.sin_family = AF_INET; - bindInfo.sin_port = htons(port); - bindInfo.sin_addr.s_addr = htonl(bindAddress); - int err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in)); + int err; + if (!bindAddress) { + struct sockaddr_in bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin_family = AF_INET; + bindInfo.sin_port = htons(port); + err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + } else if (bindAddress->version == IPV4) { + struct sockaddr_in bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin_family = AF_INET; + bindInfo.sin_port = htons(port); + bindInfo.sin_addr.s_addr = bindAddress->ipv4; + err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + } else { + struct sockaddr_in6 bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin6_family = AF_INET6; + bindInfo.sin6_port = htons(port); + memcpy(bindInfo.sin6_addr.s6_addr, bindAddress->ipv6, sizeof(bindInfo.sin6_addr.s6_addr)); + err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + + } if (err) { close(sock); return -1;@@ -63,18 +92,35 @@ }
return sock; } -static inline Socket SocketConnectTCP(int port, uint32_t destinationAddress) { +static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) { Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SOCKET_FAILED(sock)) { return sock; } - struct sockaddr_in bindInfo; - memset(&bindInfo, 0, sizeof(bindInfo)); - bindInfo.sin_family = AF_INET; - bindInfo.sin_port = htons(port); - bindInfo.sin_addr.s_addr = htonl(destinationAddress); - int err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in)); + int err; + if (!destinationAddress) { + struct sockaddr_in bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin_family = AF_INET; + bindInfo.sin_port = htons(port); + err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + } else if (destinationAddress->version == IPV4) { + struct sockaddr_in bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin_family = AF_INET; + bindInfo.sin_port = htons(port); + bindInfo.sin_addr.s_addr = destinationAddress->ipv4; + err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + } else { + struct sockaddr_in6 bindInfo; + memset(&bindInfo, 0, sizeof(bindInfo)); + bindInfo.sin6_family = AF_INET6; + bindInfo.sin6_port = htons(port); + memcpy(bindInfo.sin6_addr.s6_addr, destinationAddress->ipv6, sizeof(bindInfo.sin6_addr.s6_addr)); + err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); + } + if (err) { close(sock); return -1;@@ -86,8 +132,25 @@ static inline Socket SocketListen(Socket socket, int queueLength) {
return listen(socket, queueLength); } -static inline Socket SocketAccept(Socket socket, struct sockaddr* restrict address, socklen_t* restrict addressLength) { - return accept(socket, address, addressLength); +static inline Socket SocketAccept(Socket socket, struct Address* address) { + if (!address) { + return accept(socket, 0, 0); + } + if (address->version == IPV4) { + struct sockaddr_in addrInfo; + memset(&addrInfo, 0, sizeof(addrInfo)); + addrInfo.sin_family = AF_INET; + addrInfo.sin_addr.s_addr = address->ipv4; + socklen_t len = sizeof(addrInfo); + return accept(socket, (struct sockaddr*) &addrInfo, &len); + } else { + struct sockaddr_in6 addrInfo; + memset(&addrInfo, 0, sizeof(addrInfo)); + addrInfo.sin6_family = AF_INET6; + memcpy(addrInfo.sin6_addr.s6_addr, address->ipv6, sizeof(addrInfo.sin6_addr.s6_addr)); + socklen_t len = sizeof(addrInfo); + return accept(socket, (struct sockaddr*) &addrInfo, &len); + } } static inline int SocketClose(Socket socket) {