diff options
author | Oxore <oxore@protonmail.com> | 2022-08-27 15:12:08 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-08-27 15:13:13 +0300 |
commit | 9580a9a8daa4426914f396a694903ab880ecd3f2 (patch) | |
tree | 46394ea036316ffccf3357bcc35f1c18635ae890 /gdbremote.cpp | |
parent | 903b8dbcaad887f6e14cc8cffc22ddda08dc9f85 (diff) |
Add initial gdbremote implementation
Diffstat (limited to 'gdbremote.cpp')
-rw-r--r-- | gdbremote.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/gdbremote.cpp b/gdbremote.cpp new file mode 100644 index 0000000..98a0e2a --- /dev/null +++ b/gdbremote.cpp @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: Unlicense + */ + +#include "gdbremote_parser.hpp" + +#include <cstdlib> +#include <cstdio> +#include <cstdint> +#include <cstring> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> + +#define MESSAGE_BUFFER_SIZE 1 + +char msg_buf[MESSAGE_BUFFER_SIZE]; + +static int set_socket_reuseaddr(int socket_fd) +{ + const int val = 1; + const socklen_t len = sizeof(val); + return setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, len); +} + +static inline struct sockaddr_in sockaddr_in_any_ip_with_port(uint16_t port) { + struct sockaddr_in server{}; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + return server; +} + +static int setup_socket(uint16_t port) +{ + // This creates the socket - or quits + const int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd == -1) { + perror("Could not create socket"); + return -1; + } + // Make TCP port reusable in case of kill or crash. + // Deliberate explanation: https://stackoverflow.com/a/3233022 + if (set_socket_reuseaddr(socket_fd) == -1) { + perror("setsockopt failed"); + close(socket_fd); + return -1; + } + puts("Socket created"); + const struct sockaddr_in server = sockaddr_in_any_ip_with_port(port); + if (bind(socket_fd, (struct sockaddr *)&server, sizeof(server)) == -1) { + perror("Bind failed"); + close(socket_fd); + return -1; + } + printf("Binding to 0.0.0.0:%u done\n", port); + return socket_fd; +} + +int main(int argc, char *argv[]) +{ + const int port = argc > 1 ? atoi(argv[1]) : 3333; + const int socket_fd = setup_socket(port); + if (socket_fd == -1) + return EXIT_FAILURE; + printf("Listening TCP 0.0.0.0:%u\n", port); + listen(socket_fd, 4); // Mark socket as listener + struct sockaddr client_address; + socklen_t address_len; + const int conn_fd = accept(socket_fd, &client_address, &address_len); + if (conn_fd == -1) { + perror("Accept failed"); + close(socket_fd); + return EXIT_FAILURE; + } + puts("Connection accepted"); + GDBRemote::ExchangeContext exchange_ctx{}; + ssize_t read_size; + while ((read_size = recv(conn_fd, msg_buf, MESSAGE_BUFFER_SIZE, 0)) > 0) { + for (size_t i = 0; i < static_cast<size_t>(read_size); i++) { + const auto res = exchange_ctx.Consume(msg_buf[i]); + if (res != nullptr) { + if (res->packet.length() > 0) { + printf("<- \"%s\"\n", res->packet.c_str()); + } + if (res->response.length() > 0) { + printf("-> \"%s\"\n", res->response.c_str()); + if (send(conn_fd, &res->response[0], res->response.length(), 0) == -1) + perror("Send failed"); + } + } + } + memset(msg_buf, '\0', MESSAGE_BUFFER_SIZE); + } + if (read_size == 0) { + puts("Client disconnected"); + } else if (read_size == -1) { + perror("Recv failed"); + } + close(socket_fd); +} |