From 278a5adf252bdb233e75ac68ec9afe8f60129a93 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 14 Dec 2022 22:54:08 -0400 Subject: [PATCH] chore: reorganize code --- src/main.zig | 189 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 79 deletions(-) diff --git a/src/main.zig b/src/main.zig index f8f4e7f..440d346 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,8 +4,6 @@ const network = @import("network"); const Allocator = std.mem.Allocator; const Socket = network.Socket; -const port: u16 = 2424; - const target: []const u8 = \\ \\ armv4t @@ -33,103 +31,136 @@ const target: []const u8 = ; pub fn main() !void { - const log = std.log.scoped(.Server); + const log = std.log.scoped(.Main); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer std.debug.assert(!gpa.deinit()); const allocator = gpa.allocator(); - try network.init(); - defer network.deinit(); + var server = try Server.init(); + defer server.deinit(allocator); - var socket = try Socket.create(.ipv4, .tcp); - defer socket.close(); - - try socket.bindToPort(port); - try socket.listen(); - - var client = try socket.accept(); - defer client.close(); - - const endpoint = try client.getLocalEndPoint(); - log.info("client connected from {}", .{endpoint}); - - try gdbStubServer(allocator, client); + try server.run(allocator); log.info("Client disconnected", .{}); } -fn gdbStubServer(allocator: Allocator, client: Socket) !void { - var buf: [Packet.size]u8 = undefined; - var previous: ?[]const u8 = null; - defer if (previous) |packet| allocator.free(packet); +const Server = struct { + const Self = @This(); + const log = std.log.scoped(.Server); + const port: u16 = 2424; - while (true) { - const len = try client.receive(&buf); - if (len == 0) break; + // FIXME: Shouldn't this be a Packet Struct? + pkt_cache: ?[]const u8 = null, - switch (try parse(allocator, client, previous, buf[0..len])) { - .send => |response| { - if (previous) |packet| allocator.free(packet); - previous = response; - }, - .recv_ack => { - if (previous) |packet| allocator.free(packet); - previous = null; - }, - .recv_nack => {}, + client: Socket, + _socket: Socket, + + pub fn init() !Self { + try network.init(); + + var socket = try Socket.create(.ipv4, .tcp); + try socket.bindToPort(port); + try socket.listen(); + + var client = try socket.accept(); // TODO: This blocks, is this OK? + + const endpoint = try client.getLocalEndPoint(); + log.info("client connected from {}", .{endpoint}); + + return .{ ._socket = socket, .client = client }; + } + + pub fn deinit(self: *Self, allocator: Allocator) void { + self.reset(allocator); + + self.client.close(); + self._socket.close(); + network.deinit(); + + self.* = undefined; + } + + const Action = union(enum) { + nothing, + send: []const u8, + retry, + ack, + nack, + }; + + pub fn run(self: *Self, allocator: Allocator) !void { + var buf: [Packet.max_len]u8 = undefined; + + while (true) { + const len = try self.client.receive(&buf); + if (len == 0) break; + + const action = try Self.parse(allocator, buf[0..len]); + try self.send(allocator, action); } } -} -const Action = union(enum) { - send: []const u8, - recv_nack, - recv_ack, + fn parse(allocator: Allocator, input: []const u8) !Action { + return switch (input[0]) { + '+' => .nothing, + '-' => .retry, + '$' => blk: { + // Packet + var packet = Packet.from(allocator, input) catch return .nack; + defer packet.deinit(allocator); + + var string = packet.parse(allocator) catch return .nack; + defer string.deinit(allocator); + + const reply = string.inner(); + + // deallocated by the caller + const response = try std.fmt.allocPrint(allocator, "${s}#{x:0>2}", .{ reply, Packet.checksum(reply) }); + + break :blk .{ .send = response }; + }, + else => std.debug.panic("Unknown: {s}", .{input}), + }; + } + + fn send(self: *Self, allocator: Allocator, action: Action) !void { + switch (action) { + .send => |pkt| { + _ = try self.client.send("+"); // ACK + _ = try self.client.send(pkt); + + self.reset(allocator); + self.pkt_cache = pkt; + }, + .retry => { + log.warn("received nack, resending: \"{?s}\"", .{self.pkt_cache}); + + if (self.pkt_cache) |pkt| _ = try self.client.send(pkt); // FIXME: is an ack to a nack necessary? + }, + .ack => { + _ = try self.client.send("+"); + self.reset(allocator); + }, + .nack => { + _ = try self.client.send("-"); + self.reset(allocator); + }, + .nothing => self.reset(allocator), + } + } + + fn reset(self: *Self, allocator: Allocator) void { + if (self.pkt_cache) |pkt| allocator.free(pkt); + self.pkt_cache = null; + } }; -fn parse(allocator: Allocator, client: Socket, previous: ?[]const u8, input: []const u8) !Action { - const log = std.log.scoped(.GdbStubParser); - - return switch (input[0]) { - '+' => .recv_ack, - '-' => blk: { - if (previous) |packet| { - log.warn("received nack, resending: \"{s}\"", .{packet}); - _ = try client.send(packet); - } else { - log.err("received nack, but we don't recall sending anything", .{}); - } - - break :blk .recv_nack; - }, - '$' => blk: { - // Packet - var packet = try Packet.from(allocator, input); - defer packet.deinit(allocator); - - var string = try packet.parse(allocator); - defer string.deinit(allocator); - - const reply = string.inner(); - - _ = try client.send("+"); // Acknowledge - - // deallocated by the caller - const response = try std.fmt.allocPrint(allocator, "${s}#{x:0>2}", .{ reply, Packet.checksum(reply) }); - _ = try client.send(response); - - break :blk .{ .send = response }; - }, - else => std.debug.panic("Unknown: {s}", .{input}), - }; -} - const Packet = struct { const Self = @This(); const log = std.log.scoped(.Packet); - const size: usize = 0x1000; + const max_len: usize = 0x1000; contents: []const u8, @@ -212,7 +243,7 @@ const Packet = struct { const format = "PacketSize={x:};qXfer:features:read+;qXfer:memory-map:read+"; // TODO: Anything else? - const ret = try std.fmt.allocPrint(allocator, format, .{Packet.size}); + const ret = try std.fmt.allocPrint(allocator, format, .{Packet.max_len}); return .{ .alloc = ret }; }