Skip to content

Instantly share code, notes, and snippets.

@mtortonesi
Last active December 31, 2021 22:50
Show Gist options
  • Save mtortonesi/933d5a6c601eeaabdccf0bd6fd1ec89c to your computer and use it in GitHub Desktop.
Save mtortonesi/933d5a6c601eeaabdccf0bd6fd1ec89c to your computer and use it in GitHub Desktop.
const std = @import("std");
pub const io_mode = .evented;
const ArgStruct = struct {
// Apparently, the following two lines do not compile because of https://github.com/ziglang/zig/issues/10184
// (also see https://github.com/ziglang/zig/pull/4567 and https://github.com/ziglang/zig/issues/1268)
// in: *@TypeOf(std.io.Reader),
// out: *@TypeOf(std.io.Writer),
// Apparently, the following two lines do not compile because of https://github.com/ziglang/zig/issues/5877
in: anytype,
out: anytype,
buf: []u8,
loop: std.event.Loop,
alloc: std.mem.Allocator,
};
pub fn main() !void {
// Shortcut to standard input and output
const stdin = std.io.getStdIn().reader();
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = gpa.allocator();
// Create iterator on argument vector
var arg_it = std.process.args();
defer arg_it.deinit();
_ = arg_it.skip(); // skip name of executable
var hostname = try getNextArg(&arg_it, alloc) orelse {
std.debug.print("Expected first argument to be the hostname\n", .{});
return error.InvalidArgs;
};
var port = try getNextArg(&arg_it, alloc) orelse {
std.debug.print("Expected second argument to be the port\n", .{});
return error.InvalidArgs;
};
var port_number = try std.fmt.parseInt(u16, port, 10);
var sockStream = try std.net.tcpConnectToHost(alloc, hostname, port_number);
var netIn = sockStream.reader();
var netOut = sockStream.writer();
var buf1: [4096]u8 = undefined;
var buf2: [4096]u8 = undefined;
var loop: std.event.Loop = undefined;
try loop.initMultiThreaded();
defer loop.deinit();
try loop.runDetached(alloc, readAndForward, ArgStruct{ .in = netIn, .out = stdout, .buf = &buf1, .loop = loop, .allocator = alloc });
try loop.runDetached(alloc, readAndForward, ArgStruct{ .in = &stdin, .out = &netOut, .buf = &buf2, .loop = loop, .allocator = alloc });
loop.run();
return;
}
// See https://github.com/ziglang/zig/issues/6515
fn getNextArg(arg_it: *std.process.ArgIterator, allocator: std.mem.Allocator) ?anyerror![]u8 {
var arg = arg_it.next(allocator);
return @as(?anyerror![]u8, arg);
}
fn readAndForward(comptime args: ArgStruct) !void {
// read into buffer
var bytesRead = try args.in.read(args.buf);
// write buffer content into output
try args.out.write(args.buf[0..bytesRead]);
// re-register itself
// try args.loop.runDetached(args.allocator, readAndForward, .{ .in = args.in, .out = args.out, .buf = args.buf, .loop = args.loop, .allocator = args.allocator });
try args.loop.runDetached(args.allocator, readAndForward, args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment