/* SPDX-License-Identifier: Unlicense */ #include "gdbremote_parser.hpp" #include #include #include #include #include #include #include #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(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); }