mirror of https://github.com/mgba-emu/mgba.git
Abstract out sockets
This commit is contained in:
parent
23e0737649
commit
20a5fa8476
|
@ -1,13 +1,8 @@
|
||||||
#include "gdb-stub.h"
|
#include "gdb-stub.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
enum GDBError {
|
enum GDBError {
|
||||||
GDB_NO_ERROR = 0x00,
|
GDB_NO_ERROR = 0x00,
|
||||||
|
@ -50,15 +45,12 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas
|
||||||
|
|
||||||
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
||||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||||
int flags;
|
|
||||||
while (stub->d.state == DEBUGGER_PAUSED) {
|
while (stub->d.state == DEBUGGER_PAUSED) {
|
||||||
if (stub->connection >= 0) {
|
if (stub->connection >= 0) {
|
||||||
flags = fcntl(stub->connection, F_GETFL);
|
if (!SocketSetBlocking(stub->connection, 1)) {
|
||||||
if (flags == -1) {
|
|
||||||
GDBStubHangup(stub);
|
GDBStubHangup(stub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fcntl(stub->connection, F_SETFL, flags & ~O_NONBLOCK);
|
|
||||||
}
|
}
|
||||||
GDBStubUpdate(stub);
|
GDBStubUpdate(stub);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +58,7 @@ static void _gdbStubPoll(struct ARMDebugger* debugger) {
|
||||||
|
|
||||||
static void _ack(struct GDBStub* stub) {
|
static void _ack(struct GDBStub* stub) {
|
||||||
char ack = '+';
|
char ack = '+';
|
||||||
send(stub->connection, &ack, 1, 0);
|
SocketSend(stub->connection, &ack, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _nak(struct GDBStub* stub) {
|
static void _nak(struct GDBStub* stub) {
|
||||||
|
@ -74,7 +66,7 @@ static void _nak(struct GDBStub* stub) {
|
||||||
if (stub->d.log) {
|
if (stub->d.log) {
|
||||||
stub->d.log(&stub->d, DEBUGGER_LOG_WARN, "Packet error");
|
stub->d.log(&stub->d, DEBUGGER_LOG_WARN, "Packet error");
|
||||||
}
|
}
|
||||||
send(stub->connection, &nak, 1, 0);
|
SocketSend(stub->connection, &nak, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _hex2int(const char* hex, int maxDigits) {
|
static uint32_t _hex2int(const char* hex, int maxDigits) {
|
||||||
|
@ -155,7 +147,7 @@ static void _sendMessage(struct GDBStub* stub) {
|
||||||
if (stub->d.log) {
|
if (stub->d.log) {
|
||||||
stub->d.log(&stub->d, DEBUGGER_LOG_DEBUG, "> %s", stub->outgoing);
|
stub->d.log(&stub->d, DEBUGGER_LOG_DEBUG, "> %s", stub->outgoing);
|
||||||
}
|
}
|
||||||
send(stub->connection, stub->outgoing, i + 3, 0);
|
SocketSend(stub->connection, stub->outgoing, i + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _error(struct GDBStub* stub, enum GDBError error) {
|
static void _error(struct GDBStub* stub, enum GDBError error) {
|
||||||
|
@ -171,12 +163,10 @@ static void _writeHostInfo(struct GDBStub* stub) {
|
||||||
static void _continue(struct GDBStub* stub, const char* message) {
|
static void _continue(struct GDBStub* stub, const char* message) {
|
||||||
stub->d.state = DEBUGGER_RUNNING;
|
stub->d.state = DEBUGGER_RUNNING;
|
||||||
if (stub->connection >= 0) {
|
if (stub->connection >= 0) {
|
||||||
int flags = fcntl(stub->connection, F_GETFL);
|
if (!SocketSetBlocking(stub->connection, 0)) {
|
||||||
if (flags == -1) {
|
|
||||||
GDBStubHangup(stub);
|
GDBStubHangup(stub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
}
|
}
|
||||||
// TODO: parse message
|
// TODO: parse message
|
||||||
(void) (message);
|
(void) (message);
|
||||||
|
@ -445,34 +435,20 @@ int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
|
||||||
GDBStubShutdown(stub);
|
GDBStubShutdown(stub);
|
||||||
}
|
}
|
||||||
// TODO: support IPv6
|
// TODO: support IPv6
|
||||||
stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
stub->socket = SocketOpenTCP(port, bindAddress);
|
||||||
if (stub->socket < 0) {
|
if (stub->socket < 0) {
|
||||||
if (stub->d.log) {
|
if (stub->d.log) {
|
||||||
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't open socket");
|
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't open socket");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int err = SocketListen(stub->socket, 1);
|
||||||
struct sockaddr_in bindInfo = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(port),
|
|
||||||
.sin_addr = {
|
|
||||||
.s_addr = htonl(bindAddress)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
int err = bind(stub->socket, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
|
|
||||||
if (err) {
|
if (err) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
err = listen(stub->socket, 1);
|
if (!SocketSetBlocking(stub->socket, 0)) {
|
||||||
if (err) {
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
int flags = fcntl(stub->socket, F_GETFL);
|
|
||||||
if (flags == -1) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
fcntl(stub->socket, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -480,14 +456,14 @@ cleanup:
|
||||||
if (stub->d.log) {
|
if (stub->d.log) {
|
||||||
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't listen on port");
|
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't listen on port");
|
||||||
}
|
}
|
||||||
close(stub->socket);
|
SocketClose(stub->socket);
|
||||||
stub->socket = -1;
|
stub->socket = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDBStubHangup(struct GDBStub* stub) {
|
void GDBStubHangup(struct GDBStub* stub) {
|
||||||
if (stub->connection >= 0) {
|
if (stub->connection >= 0) {
|
||||||
close(stub->connection);
|
SocketClose(stub->connection);
|
||||||
stub->connection = -1;
|
stub->connection = -1;
|
||||||
}
|
}
|
||||||
if (stub->d.state == DEBUGGER_PAUSED) {
|
if (stub->d.state == DEBUGGER_PAUSED) {
|
||||||
|
@ -498,7 +474,7 @@ void GDBStubHangup(struct GDBStub* stub) {
|
||||||
void GDBStubShutdown(struct GDBStub* stub) {
|
void GDBStubShutdown(struct GDBStub* stub) {
|
||||||
GDBStubHangup(stub);
|
GDBStubHangup(stub);
|
||||||
if (stub->socket >= 0) {
|
if (stub->socket >= 0) {
|
||||||
close(stub->socket);
|
SocketClose(stub->socket);
|
||||||
stub->socket = -1;
|
stub->socket = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,13 +484,11 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stub->connection == -1) {
|
if (stub->connection == -1) {
|
||||||
stub->connection = accept(stub->socket, 0, 0);
|
stub->connection = SocketAccept(stub->socket, 0, 0);
|
||||||
if (stub->connection >= 0) {
|
if (stub->connection >= 0) {
|
||||||
int flags = fcntl(stub->connection, F_GETFL);
|
if (!SocketSetBlocking(stub->connection, 0)) {
|
||||||
if (flags == -1) {
|
|
||||||
goto connectionLost;
|
goto connectionLost;
|
||||||
}
|
}
|
||||||
fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
|
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
|
||||||
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||||
return;
|
return;
|
||||||
|
@ -523,7 +497,7 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
ssize_t messageLen = recv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1, 0);
|
ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
|
||||||
if (messageLen == 0) {
|
if (messageLen == 0) {
|
||||||
goto connectionLost;
|
goto connectionLost;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GDB_STUB_H
|
#define GDB_STUB_H
|
||||||
|
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
#define GDB_STUB_MAX_LINE 1200
|
#define GDB_STUB_MAX_LINE 1200
|
||||||
|
|
||||||
|
@ -19,8 +20,8 @@ struct GDBStub {
|
||||||
char outgoing[GDB_STUB_MAX_LINE];
|
char outgoing[GDB_STUB_MAX_LINE];
|
||||||
enum GDBStubAckState lineAck;
|
enum GDBStubAckState lineAck;
|
||||||
|
|
||||||
int socket;
|
Socket socket;
|
||||||
int connection;
|
Socket connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GDBStubCreate(struct GDBStub*);
|
void GDBStubCreate(struct GDBStub*);
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#ifndef SOCKET_H
|
||||||
|
#define SOCKET_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
typedef SOCKET Socket;
|
||||||
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef int Socket;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void SocketSubsystemInitialize() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSAStartup(MAKEWORD(2, 2), 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t SocketSend(Socket socket, const void* buffer, size_t size) {
|
||||||
|
return write(socket, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t SocketRecv(Socket socket, void* buffer, size_t size) {
|
||||||
|
return read(socket, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket SocketOpenTCP(int port, uint32_t bindAddress) {
|
||||||
|
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sock < 0) {
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in bindInfo = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = htons(port),
|
||||||
|
.sin_addr = {
|
||||||
|
.s_addr = htonl(bindAddress)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
int err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
|
||||||
|
if (err) {
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket SocketListen(Socket socket, int queueLength) {
|
||||||
|
return listen(socket, queueLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket SocketAccept(Socket socket, struct sockaddr* restrict address, socklen_t* restrict addressLength) {
|
||||||
|
return accept(socket, address, addressLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketClose(Socket socket) {
|
||||||
|
return close(socket) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketSetBlocking(Socket socket, int blocking) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
blocking = !blocking;
|
||||||
|
return ioctlsocket(socket, FIONBIO, &blocking) == NO_ERROR;
|
||||||
|
#else
|
||||||
|
int flags = fcntl(socket, F_GETFL);
|
||||||
|
if (flags == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (blocking) {
|
||||||
|
flags &= ~O_NONBLOCK;
|
||||||
|
} else {
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
}
|
||||||
|
return fcntl(socket, F_SETFL, flags) >= 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue