132 lines
3.9 KiB
Zig
132 lines
3.9 KiB
Zig
const std = @import("std");
|
|
const net = std.net;
|
|
const heap = std.heap;
|
|
const Thread = std.Thread;
|
|
|
|
const log = std.log;
|
|
|
|
const Address = net.Address;
|
|
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
const testing = std.testing;
|
|
const expect = testing.expect;
|
|
|
|
const FakeStream = @import("helpers").FakeStream;
|
|
const is_test = @import("builtin").is_test;
|
|
|
|
const ExchangeConnectionStatus = enum { waiting, trying, active, dead };
|
|
|
|
pub const ExchangeConnection = struct {
|
|
in_address: Address,
|
|
out_address: Address,
|
|
in: if (is_test) *FakeStream else net.Stream = undefined,
|
|
out: if (is_test) *FakeStream else net.Stream = undefined,
|
|
server_status: ExchangeConnectionStatus = .waiting,
|
|
out_status: ExchangeConnectionStatus = .trying,
|
|
listen_thread: Thread = undefined,
|
|
|
|
pub fn init(host: []const u8, port: u16) !ExchangeConnection {
|
|
var buf: [1024]u8 = undefined;
|
|
var pba = heap.FixedBufferAllocator.init(&buf);
|
|
|
|
const addrList = try net.getAddressList(pba.allocator(), host, port);
|
|
defer addrList.deinit();
|
|
|
|
var final_addr: ?Address = null;
|
|
for (addrList.addrs) |addr| {
|
|
final_addr = addr;
|
|
}
|
|
|
|
const in_address = Address.initIp4(.{ 0, 0, 0, 0 }, port);
|
|
|
|
return ExchangeConnection{
|
|
.out_address = final_addr.?,
|
|
.in_address = in_address,
|
|
};
|
|
}
|
|
|
|
pub fn start(self: *ExchangeConnection) void {
|
|
self.listen_thread = Thread.spawn(.{ .stack_size = 1024 * 16 }, ExchangeConnection.listen, .{self}) catch |err| {
|
|
log.err("Was not possible thread secret connection listen {any}", .{err});
|
|
unreachable;
|
|
};
|
|
|
|
_ = Thread.spawn(.{ .stack_size = 1024 * 16 }, ExchangeConnection.tryConnectOut, .{self}) catch |err| {
|
|
log.err("Was not possible create thread tryConenctOut {any}", .{err});
|
|
unreachable;
|
|
};
|
|
}
|
|
|
|
pub fn tryConnectOut(self: *ExchangeConnection) void {
|
|
if (is_test) {
|
|
return;
|
|
}
|
|
|
|
for (0..10) |_| {
|
|
Thread.sleep(1_000_000 * 1000);
|
|
|
|
self.out = net.tcpConnectToAddress(self.out_address) catch |err| {
|
|
log.err("Error connect to secret server {any}", .{err});
|
|
continue;
|
|
};
|
|
|
|
self.out_status = .active;
|
|
return;
|
|
}
|
|
}
|
|
|
|
fn listen(self: *ExchangeConnection) void {
|
|
if (is_test) {
|
|
return;
|
|
}
|
|
|
|
std.debug.print("Listening ...\n", .{});
|
|
|
|
for (0..10) |_| {
|
|
var server = self.in_address.listen(.{ .kernel_backlog = 1 }) catch |err| {
|
|
log.err("Error starting secret server connection {any}", .{err});
|
|
continue;
|
|
};
|
|
|
|
while (true) {
|
|
const server_conn = server.accept() catch |err| {
|
|
log.err("Error when accepting connection secret server {any}", .{err});
|
|
self.server_status = .waiting;
|
|
break;
|
|
};
|
|
|
|
self.server_status = .active;
|
|
self.in = server_conn.stream;
|
|
}
|
|
|
|
server.deinit();
|
|
|
|
Thread.sleep(1_000_000 * 1000);
|
|
}
|
|
|
|
self.server_status = .dead;
|
|
}
|
|
};
|
|
|
|
test "expect create a secret connection" {
|
|
const conn = try ExchangeConnection.init("uchoamp.dev", 80);
|
|
|
|
try expect(conn.in_address.getPort() == 80);
|
|
}
|
|
|
|
//test "expect start secret connection" {
|
|
// var conn1 = try ExchangeConnection.init("localhost", 5002);
|
|
// conn1.out_address.setPort(2323);
|
|
//
|
|
// conn1.start();
|
|
//
|
|
// //_ = try conn1.out.write("hello!\r\n");
|
|
// //Thread.sleep(1_000_000 * 1000 * 10);
|
|
// conn1.listen_thread.join();
|
|
//
|
|
// var buf: [100]u8 = undefined;
|
|
// try expect(conn1.server_status == .active);
|
|
// const size = try conn1.in.read(&buf);
|
|
// std.debug.print("Secret conn response: {s}", .{buf[0..size]});
|
|
//}
|