all repos — mgba @ 76bf0427f149344cd1df120207d477ab5b36d0df

mGBA Game Boy Advance Emulator

Util: Support IPv6
Jeffrey Pfau jeffrey@endrift.com
Fri, 09 Jan 2015 02:03:42 -0800
commit

76bf0427f149344cd1df120207d477ab5b36d0df

parent

968069ff5e9258ed6ceb1e033a6ebf84bd63cfa0

M CHANGESCHANGES

@@ -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
M src/debugger/gdb-stub.csrc/debugger/gdb-stub.c

@@ -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;
M src/debugger/gdb-stub.hsrc/debugger/gdb-stub.h

@@ -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*);
M src/platform/qt/GDBController.cppsrc/platform/qt/GDBController.cpp

@@ -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(); }
M src/platform/qt/GDBController.hsrc/platform/qt/GDBController.h

@@ -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; }; }
M src/util/socket.hsrc/util/socket.h

@@ -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) {