Util: Support IPv6

This commit is contained in:
Jeffrey Pfau 2015-01-09 02:03:42 -08:00
parent 968069ff5e
commit 76bf0427f1
6 changed files with 88 additions and 29 deletions

View File

@ -15,6 +15,7 @@ Features:
- 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

View File

@ -446,11 +446,10 @@ void GDBStubCreate(struct GDBStub* stub) {
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 @@ void GDBStubUpdate(struct GDBStub* stub) {
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;

View File

@ -33,7 +33,7 @@ struct GDBStub {
};
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*);

View File

@ -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 @@ void GDBController::setPort(ushort 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 @@ void GDBController::listen() {
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();
}

View File

@ -26,7 +26,6 @@ public:
public:
ushort port();
uint32_t bindAddress();
bool isAttached();
public slots:
@ -44,7 +43,7 @@ private:
GameController* m_gameController;
ushort m_port;
uint32_t m_bindAddress;
Address m_bindAddress;
};
}

View File

@ -29,6 +29,18 @@ typedef SOCKET Socket;
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;
}
int err;
if (!bindAddress) {
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));
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 @@ static inline Socket SocketOpenTCP(int port, uint32_t bindAddress) {
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;
}
int err;
if (!destinationAddress) {
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));
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) {