feat: drop use std.net instead of zig-network
This commit is contained in:
parent
e5c1d4d2b7
commit
93cd6b1c5b
|
@ -15,11 +15,9 @@ pub fn build(b: *std.Build) void {
|
||||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const zig_network = b.dependency("zig-network", .{}); // https://github.com/MasterQ32/zig-network
|
|
||||||
|
|
||||||
_ = b.addModule("gdbstub", .{
|
_ = b.addModule("gdbstub", .{
|
||||||
.source_file = .{ .path = "src/lib.zig" },
|
.source_file = .{ .path = "src/lib.zig" },
|
||||||
.dependencies = &.{.{ .name = "network", .module = zig_network.module("network") }},
|
.dependencies = &.{},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Creates a step for unit testing. This only builds the test executable
|
// Creates a step for unit testing. This only builds the test executable
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
.{
|
.{
|
||||||
.name = "zba-gdbstub",
|
.name = "zba-gdbstub",
|
||||||
.version = "0.1.0",
|
.version = "0.1.0",
|
||||||
.dependencies = .{
|
.dependencies = .{},
|
||||||
.@"zig-network" = .{
|
|
||||||
.url = "https://github.com/MasterQ32/zig-network/archive/07ef40cacd7b00bc0f26e254d97d4d4c9071195a.tar.gz",
|
|
||||||
.hash = "12204d3d4c1184d379a78399e5ddd8a46fe19ca6c991d5c9b909c1980d14acb1dede",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const network = @import("network");
|
|
||||||
const Packet = @import("Packet.zig");
|
const Packet = @import("Packet.zig");
|
||||||
|
|
||||||
const Socket = network.Socket;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const Atomic = std.atomic.Atomic;
|
|
||||||
const Emulator = @import("lib.zig").Emulator;
|
const Emulator = @import("lib.zig").Emulator;
|
||||||
|
|
||||||
|
const Atomic = std.atomic.Atomic;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Server = std.net.StreamServer;
|
||||||
|
const Connection = Server.Connection;
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const log = std.log.scoped(.Server);
|
const log = std.log.scoped(.Server);
|
||||||
const port: u16 = 2424;
|
const port: u16 = 2424;
|
||||||
|
@ -57,32 +57,20 @@ pub const memory_map: []const u8 =
|
||||||
// FIXME: Shouldn't this be a Packet Struct?
|
// FIXME: Shouldn't this be a Packet Struct?
|
||||||
pkt_cache: ?[]const u8 = null,
|
pkt_cache: ?[]const u8 = null,
|
||||||
|
|
||||||
client: Socket,
|
server: Server,
|
||||||
_socket: Socket,
|
|
||||||
|
|
||||||
emu: Emulator,
|
emu: Emulator,
|
||||||
|
|
||||||
pub fn init(emulator: Emulator) !Self {
|
pub fn init(emulator: Emulator) !Self {
|
||||||
try network.init();
|
var server = std.net.StreamServer.init(.{});
|
||||||
|
try server.listen(std.net.Address.initIp4([_]u8{0} ** 4, port));
|
||||||
|
|
||||||
var socket = try Socket.create(.ipv4, .tcp);
|
return .{ .emu = emulator, .server = server };
|
||||||
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 .{ .emu = emulator, ._socket = socket, .client = client };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self, allocator: Allocator) void {
|
pub fn deinit(self: *Self, allocator: Allocator) void {
|
||||||
self.reset(allocator);
|
self.reset(allocator);
|
||||||
|
self.server.deinit();
|
||||||
self.client.close();
|
|
||||||
self._socket.close();
|
|
||||||
network.deinit();
|
|
||||||
|
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
@ -98,13 +86,17 @@ const Action = union(enum) {
|
||||||
pub fn run(self: *Self, allocator: Allocator, quit: *Atomic(bool)) !void {
|
pub fn run(self: *Self, allocator: Allocator, quit: *Atomic(bool)) !void {
|
||||||
var buf: [Packet.max_len]u8 = undefined;
|
var buf: [Packet.max_len]u8 = undefined;
|
||||||
|
|
||||||
|
var client = try self.server.accept();
|
||||||
|
log.info("client connected from {}", .{client.address});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const len = try self.client.receive(&buf);
|
const len = try client.stream.readAll(&buf);
|
||||||
if (len == 0) break;
|
if (len == 0) break;
|
||||||
|
|
||||||
if (quit.load(.Monotonic)) break;
|
if (quit.load(.Monotonic)) break;
|
||||||
const action = try self.parse(allocator, buf[0..len]);
|
const action = try self.parse(allocator, buf[0..len]);
|
||||||
try self.send(allocator, action);
|
|
||||||
|
try self.send(allocator, client, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just in case its the gdbstub that exited first,
|
// Just in case its the gdbstub that exited first,
|
||||||
|
@ -113,7 +105,7 @@ pub fn run(self: *Self, allocator: Allocator, quit: *Atomic(bool)) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(self: *Self, allocator: Allocator, input: []const u8) !Action {
|
fn parse(self: *Self, allocator: Allocator, input: []const u8) !Action {
|
||||||
// log.debug("-> {s}", .{input});
|
log.debug("-> {s}", .{input});
|
||||||
|
|
||||||
return switch (input[0]) {
|
return switch (input[0]) {
|
||||||
'+' => blk: {
|
'+' => blk: {
|
||||||
|
@ -146,11 +138,11 @@ fn handlePacket(self: *Self, allocator: Allocator, input: []const u8) !Action {
|
||||||
return .{ .send = response };
|
return .{ .send = response };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(self: *Self, allocator: Allocator, action: Action) !void {
|
fn send(self: *Self, allocator: Allocator, client: Server.Connection, action: Action) !void {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.send => |pkt| {
|
.send => |pkt| {
|
||||||
_ = try self.client.send(pkt);
|
_ = try client.stream.writeAll(pkt);
|
||||||
// log.debug("<- {s}", .{pkt});
|
log.debug("<- {s}", .{pkt});
|
||||||
|
|
||||||
self.reset(allocator);
|
self.reset(allocator);
|
||||||
self.pkt_cache = pkt;
|
self.pkt_cache = pkt;
|
||||||
|
@ -159,19 +151,19 @@ fn send(self: *Self, allocator: Allocator, action: Action) !void {
|
||||||
log.warn("received nack, resending: \"{?s}\"", .{self.pkt_cache});
|
log.warn("received nack, resending: \"{?s}\"", .{self.pkt_cache});
|
||||||
|
|
||||||
if (self.pkt_cache) |pkt| {
|
if (self.pkt_cache) |pkt| {
|
||||||
_ = try self.client.send(pkt);
|
_ = try client.stream.writeAll(pkt);
|
||||||
// log.debug("<- {s}", .{pkt});
|
log.debug("<- {s}", .{pkt});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ack => {
|
.ack => {
|
||||||
_ = try self.client.send("+");
|
_ = try client.stream.writeAll("+");
|
||||||
// log.debug("<- +", .{});
|
log.debug("<- +", .{});
|
||||||
|
|
||||||
self.reset(allocator);
|
self.reset(allocator);
|
||||||
},
|
},
|
||||||
.nack => {
|
.nack => {
|
||||||
_ = try self.client.send("-");
|
_ = try client.stream.writeAll("-");
|
||||||
// log.debug("<- -", .{});
|
log.debug("<- -", .{});
|
||||||
|
|
||||||
self.reset(allocator);
|
self.reset(allocator);
|
||||||
},
|
},
|
||||||
|
|
|
@ -142,3 +142,7 @@ pub const Emulator = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = @import("test.zig");
|
||||||
|
}
|
||||||
|
|
18
src/main.zig
18
src/main.zig
|
@ -1,18 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const Server = @import("gdbstub").Server;
|
|
||||||
|
|
||||||
pub fn main() !void {
|
|
||||||
const log = std.log.scoped(.Main);
|
|
||||||
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
||||||
defer std.debug.assert(!gpa.deinit());
|
|
||||||
|
|
||||||
const allocator = gpa.allocator();
|
|
||||||
|
|
||||||
var server = try Server.init();
|
|
||||||
defer server.deinit(allocator);
|
|
||||||
|
|
||||||
try server.run(allocator);
|
|
||||||
|
|
||||||
log.info("Client disconnected", .{});
|
|
||||||
}
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const Emulator = @import("lib.zig").Emulator;
|
||||||
|
const Server = @import("Server.zig");
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const BarebonesEmulator = struct {
|
||||||
|
r: [16]u32 = [_]u32{0} ** 16,
|
||||||
|
|
||||||
|
pub fn interface(self: *@This(), allocator: Allocator) Emulator {
|
||||||
|
return Emulator.init(allocator, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(_: *const @This(), _: u32) u8 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(_: *@This(), _: u32, _: u8) void {}
|
||||||
|
|
||||||
|
pub fn registers(self: *@This()) *[16]u32 {
|
||||||
|
return &self.r;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cpsr(_: *const @This()) u32 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(_: *@This()) void {
|
||||||
|
// execute 1 instruction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test Server {
|
||||||
|
// https://github.com/ziglang/zig/blob/225fe6ddbfae016395762850e0cd5c51f9e7751c/lib/std/net/test.zig#L146C1-L156
|
||||||
|
if (builtin.single_threaded) return error.SkipZigTest;
|
||||||
|
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||||
|
|
||||||
|
if (builtin.os.tag == .windows)
|
||||||
|
_ = try std.os.windows.WSAStartup(2, 2);
|
||||||
|
|
||||||
|
defer if (builtin.os.tag == .windows) std.os.windows.WSACleanup() catch unreachable;
|
||||||
|
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
|
||||||
|
var impl = BarebonesEmulator{};
|
||||||
|
var iface = impl.interface(allocator);
|
||||||
|
defer iface.deinit();
|
||||||
|
|
||||||
|
const clientFn = struct {
|
||||||
|
fn inner(address: std.net.Address) !void {
|
||||||
|
const socket = try std.net.tcpConnectToAddress(address);
|
||||||
|
defer socket.close();
|
||||||
|
|
||||||
|
_ = try socket.writer().writeAll("+");
|
||||||
|
}
|
||||||
|
}.inner;
|
||||||
|
|
||||||
|
var server = try Server.init(iface);
|
||||||
|
defer server.deinit(allocator);
|
||||||
|
|
||||||
|
const t = try std.Thread.spawn(.{}, clientFn, .{server.server.listen_address});
|
||||||
|
defer t.join();
|
||||||
|
|
||||||
|
var should_quit = std.atomic.Atomic(bool).init(false);
|
||||||
|
|
||||||
|
try server.run(std.testing.allocator, &should_quit);
|
||||||
|
}
|
||||||
|
|
||||||
|
test Emulator {
|
||||||
|
const ExampleImpl = struct {
|
||||||
|
r: [16]u32 = [_]u32{0} ** 16,
|
||||||
|
|
||||||
|
pub fn interface(self: *@This(), allocator: std.mem.Allocator) Emulator {
|
||||||
|
return Emulator.init(allocator, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(_: *const @This(), _: u32) u8 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(_: *@This(), _: u32, _: u8) void {}
|
||||||
|
|
||||||
|
pub fn registers(self: *@This()) *[16]u32 {
|
||||||
|
return &self.r;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cpsr(_: *const @This()) u32 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(_: *@This()) void {
|
||||||
|
// execute 1 instruction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var impl = ExampleImpl{};
|
||||||
|
var emu = Emulator.init(std.testing.allocator, &impl);
|
||||||
|
|
||||||
|
_ = emu.read(0x0000_0000);
|
||||||
|
emu.write(0x0000_0000, 0x00);
|
||||||
|
|
||||||
|
_ = emu.registers();
|
||||||
|
_ = emu.cpsr();
|
||||||
|
|
||||||
|
_ = emu.step();
|
||||||
|
}
|
Loading…
Reference in New Issue