Skip to content

Commit

Permalink
port to zig 0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
akiroz committed May 8, 2022
1 parent dcea99b commit 599fead
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 134 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Zika

![](https://img.shields.io/badge/zig-0.8.1-informational)
![](https://img.shields.io/badge/zig-0.9.1-informational)

IP Tunneling over MQTT

Expand Down
41 changes: 28 additions & 13 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
const builtin = @import("builtin");
const Builder = @import("std").build.Builder;
const std = @import("std");
const LibExeObjStep = std.build.LibExeObjStep;

pub fn build(b: *Builder) void {
const server = b.addExecutable("zika-server", "src/server.zig");
const client = b.addExecutable("zika-client", "src/client.zig");
server.addIncludeDir("/usr/local/include");
client.addIncludeDir("/usr/local/include");
server.linkSystemLibrary("mosquitto");
client.linkSystemLibrary("mosquitto");
if (builtin.target.isDarwin()) {
server.linkSystemLibrary("pcap");
client.linkSystemLibrary("pcap");
fn commonOpts(exe: *LibExeObjStep) *LibExeObjStep {
exe.setBuildMode(exe.builder.standardReleaseOptions());
if (builtin.target.isDarwin()) { // macOS
if (builtin.cpu.arch == .aarch64) { // Apple
exe.addIncludeDir("/opt/homebrew/include");
exe.addLibPath("/opt/homebrew/lib");
} else { // Intel
exe.addIncludeDir("/usr/local/include");
}
exe.linkSystemLibrary("pcap");
} else { // Linux
exe.addIncludeDir("/usr/include");
exe.addLibPath("/usr/lib");
exe.linkLibC();
// Support down to Ubuntu 18 Bionic
exe.setTarget(.{ .glibc_version = .{ .major = 2, .minor = 27, .patch = 0 } });
}
//server.install();
client.install();
exe.linkSystemLibrary("mosquitto");
return exe;
}

pub fn build(b: *std.build.Builder) void {
const server = commonOpts(b.addExecutable("zika-server", "src/server.zig"));
server.install();

const client = commonOpts(b.addExecutable("zika-client", "src/client.zig"));
client.install();
}
27 changes: 15 additions & 12 deletions src/client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn Tunnel(comptime T: type) type {
const Conf = config.ClientTunnel;

conf: Conf,
alloc: *Allocator,
alloc: Allocator,
ifce: *NetInterface(T),
mqtt: *Mqtt(T),

Expand All @@ -33,7 +33,7 @@ pub fn Tunnel(comptime T: type) type {
up_topic_cstr: [:0]u8,
dn_topic_cstr: [:0]u8,

pub fn create(alloc: *Allocator, ifce: *NetInterface(T), broker: *Mqtt(T), conf: Conf) !*Self {
pub fn create(alloc: Allocator, ifce: *NetInterface(T), broker: *Mqtt(T), conf: Conf) !*Self {
const self = try alloc.create(Self);
self.conf = conf;
self.alloc = alloc;
Expand Down Expand Up @@ -83,6 +83,7 @@ pub const Client = struct {
};

arena: ArenaAllocator,
alloc: Allocator,
ifce: ?*NetInterface(*Self),
mqtt: ?*Mqtt(*Self),
tunnels: []*Tunnel(*Self),
Expand All @@ -91,27 +92,27 @@ pub const Client = struct {
disconnect_callback: ?ConnectHandler(*Mqtt(*Self)),
message_hook: ?MessageHook(*Mqtt(*Self)),

pub fn init(parent_alloc: *Allocator, conf: * const Config) !*Self {
pub fn init(parent_alloc: Allocator, conf: * const Config) !*Self {
const client_conf = conf.client orelse {
std.log.err("missing client config", .{});
return Error.ConfigMissing;
};
var arena = ArenaAllocator.init(parent_alloc);
const self = try arena.allocator.create(Self);
self.arena = arena;
const self = try parent_alloc.create(Self);
self.arena = ArenaAllocator.init(parent_alloc);
self.alloc = self.arena.allocator();
self.ifce = null;
self.mqtt = null;
errdefer self.deinit();
const alloc = &self.arena.allocator;

std.log.info("== Client Config =================================", .{});
self.ifce = try NetInterface(*Self).init(alloc, conf, self, @ptrCast(driver.PacketHandler(*Self), &up));
self.ifce = try NetInterface(*Self).init(self.alloc, conf, self, @ptrCast(driver.PacketHandler(*Self), &up));
const max_subs = client_conf.tunnels.len;
self.mqtt = try Mqtt(*Self).init(alloc, conf, self, @ptrCast(mqtt.PacketHandler(*Self), &down), max_subs);
self.tunnels = try alloc.alloc(*Tunnel(*Self), client_conf.tunnels.len);
self.mqtt = try Mqtt(*Self).init(self.alloc, conf, self, @ptrCast(mqtt.PacketHandler(*Self), &down), max_subs);
std.log.info("Tunnels: {d}", .{client_conf.tunnels.len});
self.tunnels = try self.alloc.alloc(*Tunnel(*Self), client_conf.tunnels.len);
for (client_conf.tunnels) |tunnel, idx| {
self.tunnels[idx] = try Tunnel(*Self).create(
alloc,
self.alloc,
self.ifce orelse unreachable,
self.mqtt orelse unreachable,
.{
Expand Down Expand Up @@ -183,9 +184,11 @@ pub const Client = struct {

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = &gpa.allocator;
var alloc = gpa.allocator();
const conf_path = try std.fs.cwd().realpathAlloc(alloc, "zika_config.json");
const conf = try config.get(alloc, conf_path);
const client = try Client.init(alloc, &conf);
defer client.deinit();
defer alloc.destroy(client);
try client.run();
}
8 changes: 4 additions & 4 deletions src/config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ pub const MqttOptions = struct {
username: ?[]const u8 = null,
password: ?[]const u8 = null,

ca: ?[]const u8 = null,
ca_file: ?[]const u8 = null,
tls_insecure: bool = false,
key: ?[]const u8 = null,
cert: ?[]const u8 = null,
key_file: ?[]const u8 = null,
cert_file: ?[]const u8 = null,
};

pub const MqttBroker = struct {
Expand Down Expand Up @@ -64,7 +64,7 @@ pub const Config = struct {
client: ?ClientConfig = null,
};

pub fn get(alloc: *Allocator, file: []u8) !Config {
pub fn get(alloc: Allocator, file: []u8) !Config {
const cfg_file = try std.fs.openFileAbsolute(file, .{ .read = true });
defer cfg_file.close();

Expand Down
32 changes: 14 additions & 18 deletions src/driver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const Net = @cImport({
const Pcap = @cImport(@cInclude("pcap/pcap.h"));

const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const Ip4Address = std.net.Ip4Address;
const Address = std.net.Address;
pub fn PacketHandler(comptime T: type) type {
Expand All @@ -31,13 +30,13 @@ fn PcapDriver(comptime T: type) type {
NotInitialized,
};

alloc: *Allocator,
alloc: Allocator,
user: T,
handler: PacketHandler(T),
pcap: ?*Pcap.pcap_t,
pcap_header: [4]u8,

pub fn init(alloc: *Allocator, conf: *const Config, user: T, handler: PacketHandler(T)) !*Self {
pub fn init(alloc: Allocator, conf: *const Config, user: T, handler: PacketHandler(T)) !*Self {
const pcap_conf = conf.driver.pcap orelse {
std.log.err("missing pcap driver config", .{});
return Error.ConfigMissing;
Expand Down Expand Up @@ -99,7 +98,7 @@ fn PcapDriver(comptime T: type) type {
}

fn recv(self_ptr: [*c]u8, hdr: [*c]const Pcap.pcap_pkthdr, pkt: [*c]const u8) callconv(.C) void {
const self = @intToPtr(*Self, @ptrToInt(self_ptr));
const self = @ptrCast(*Self, @alignCast(@alignOf(*Self), self_ptr.?));
self.handler.*(self.user, pkt[4..hdr.*.len]);
}

Expand Down Expand Up @@ -135,7 +134,7 @@ fn TunDriver(comptime T: type) type {
tun: ?std.fs.File = null,
buf: []u8,

pub fn init(alloc: *Allocator, conf: * const Config, user: T, handler: PacketHandler(T)) !*Self {
pub fn init(alloc: Allocator, conf: *const Config, user: T, handler: PacketHandler(T)) !*Self {
const tun_conf = conf.driver.tun orelse {
std.log.err("missing tun driver config", .{});
return Error.ConfigMissing;
Expand Down Expand Up @@ -243,16 +242,14 @@ pub fn NetInterface(comptime T: type) type {

return struct {
const Self = @This();

arena: ArenaAllocator,
alloc: Allocator,
local_ip: u32,
driver: ?*Driver(T) = null,

pub fn init(alloc: *Allocator, conf: * const Config, user: T, handler: PacketHandler(T)) !*Self {
var arena = ArenaAllocator.init(alloc);
const self = try arena.allocator.create(Self);
self.arena = arena;
pub fn init(alloc: Allocator, conf: *const Config, user: T, handler: PacketHandler(T)) !*Self {
const self = try alloc.create(Self);
errdefer self.deinit();
self.alloc = alloc;
self.local_ip = (try Ip4Address.parse(conf.driver.local_addr, 0)).sa.addr;
self.driver = try Driver(T).init(alloc, conf, user, handler);
std.log.info("Local IP: {s}", .{conf.driver.local_addr});
Expand All @@ -261,7 +258,6 @@ pub fn NetInterface(comptime T: type) type {

pub fn deinit(self: *Self) void {
self.driver.?.deinit();
self.arena.deinit();
}

pub fn run(self: *Self) !void {
Expand All @@ -274,7 +270,7 @@ pub fn NetInterface(comptime T: type) type {
hdr.src = src;
hdr.dst = self.local_ip;
hdr.cksum = 0; // Zero before recalc
hdr.cksum = try cksum(&self.arena.allocator, pkt[0..payload_offset], 0);
hdr.cksum = try self.cksum(pkt[0..payload_offset], 0);
switch (hdr.proto) {
6, 17 => { // TCP / UDP
var pseudo_buf = std.mem.zeroes([@sizeOf(PseudoHeader)/2]u16);
Expand All @@ -288,26 +284,26 @@ pub fn NetInterface(comptime T: type) type {
const cksum_offset = payload_offset + if (hdr.proto == 6) @as(usize, 16) else 6;
const cksum_slice = pkt[cksum_offset..cksum_offset+2];
std.mem.set(u8, cksum_slice, 0); // Zero before recalc
var sum = try cksum(&self.arena.allocator, pkt[payload_offset..], pseudo_sum);
var sum = try self.cksum(pkt[payload_offset..], pseudo_sum);
std.mem.copy(u8, cksum_slice, @ptrCast(*[2]u8, &sum));
},
else => {}, // No special handling
}
try self.driver.?.write(pkt);
}

fn cksum(alloc: *Allocator, buf: []u8, carry: u32) !u16 {
fn cksum(self: *Self, buf: []u8, carry: u32) !u16 {
var sum: u32 = carry;
const buf2 = try alloc.alloc(u16, buf.len/2 + 1);
defer alloc.free(buf2);
const buf2 = try self.alloc.alloc(u16, buf.len/2 + 1);
defer self.alloc.free(buf2);
std.mem.set(u16, buf2, 0);
const buf2_ptr = @ptrCast([*]u8, buf2);
std.mem.copy(u8, buf2_ptr[0..buf2.len*2], buf);
for (buf2) |word| sum += word;
while (sum > 0xffff) {
sum = (sum & 0xffff) + (sum >> 16);
}
return @intCast(u16, sum ^ 0xffff);
return @truncate(u16, sum ^ 0xffff);
}
};
}
Loading

0 comments on commit 599fead

Please sign in to comment.