first
This commit is contained in:
commit
dcb58a7554
7 changed files with 792 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/zig-cache
|
||||||
|
/zig-out
|
||||||
|
|
70
build.zig
Normal file
70
build.zig
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Although this function looks imperative, note that its job is to
|
||||||
|
// declaratively construct a build graph that will be executed by an external
|
||||||
|
// runner.
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard optimization options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||||
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "ztacacs",
|
||||||
|
// In this case the main source file is merely a path, however, in more
|
||||||
|
// complicated build scripts, this could be a generated file.
|
||||||
|
.root_source_file = .{ .path = "src/main.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
// This declares intent for the executable to be installed into the
|
||||||
|
// standard location when the user invokes the "install" step (the default
|
||||||
|
// step when running `zig build`).
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
// This *creates* a Run step in the build graph, to be executed when another
|
||||||
|
// step is evaluated that depends on it. The next line below will establish
|
||||||
|
// such a dependency.
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
|
// By making the run step depend on the install step, it will be run from the
|
||||||
|
// installation directory rather than directly from within the cache directory.
|
||||||
|
// This is not necessary, however, if the application depends on other installed
|
||||||
|
// files, this ensures they will be present and in the expected location.
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
// This allows the user to pass arguments to the application in the build
|
||||||
|
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||||
|
// and can be selected like this: `zig build run`
|
||||||
|
// This will evaluate the `run` step rather than the default, which is "install".
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
// Creates a step for unit testing. This only builds the test executable
|
||||||
|
// but does not run it.
|
||||||
|
const unit_tests = b.addTest(.{
|
||||||
|
.root_source_file = .{ .path = "src/main.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
const run_unit_tests = b.addRunArtifact(unit_tests);
|
||||||
|
|
||||||
|
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||||
|
// the `zig build --help` menu, providing a way for the user to request
|
||||||
|
// running the unit tests.
|
||||||
|
const test_step = b.step("test", "Run unit tests");
|
||||||
|
test_step.dependOn(&run_unit_tests.step);
|
||||||
|
}
|
292
flake.lock
Normal file
292
flake.lock
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"bash": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1678247195,
|
||||||
|
"narHash": "sha256-m/wSwlSket+hob3JED4XUvoWJLtW7yhtOiZrlRDMShs=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "e7a00dcc0e75bc3ef6856bdd94d7d809245f5636",
|
||||||
|
"revCount": 1,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.ocjtech.us/jeff/nixos-bash-prompt-builder.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.ocjtech.us/jeff/nixos-bash-prompt-builder.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binned_allocator": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-m/kr4kmkG2rLkAj5YwvM0HmXTd+chAiQHzYK6ozpWlw=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://gist.github.com/antlilja/8372900fcc09e38d7b0b6bbaddad3904/archive/6c3321e0969ff2463f8335da5601986cf2108690.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://gist.github.com/antlilja/8372900fcc09e38d7b0b6bbaddad3904/archive/6c3321e0969ff2463f8335da5601986cf2108690.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diffz": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-3CdYo6WevT0alRwKmbABahjhFKz7V9rdkDUZ43VtDeU=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/diffz/archive/90353d401c59e2ca5ed0abe5444c29ad3d7489aa.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/diffz/archive/90353d401c59e2ca5ed0abe5444c29ad3d7489aa.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1673956053,
|
||||||
|
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1659877975,
|
||||||
|
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_3": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"zls",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694102001,
|
||||||
|
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"known_folders": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-bZfn+jgCzrtm8vKPDDMNWLkJYoo7vKxZu+e2tGvSGHY=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/known-folders/archive/a564f582122326328dad6b59209d070d57c4e6ae.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/known-folders/archive/a564f582122326328dad6b59209d070d57c4e6ae.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"langref": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-UDwr6vJynfpD5SEoZzhXouoKu+Okdtpv20Vx2E5Ltcc=",
|
||||||
|
"type": "file",
|
||||||
|
"url": "https://raw.githubusercontent.com/ziglang/zig/f1992a39a59b941f397b8501a525b38e5863a527/doc/langref.html.in"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "file",
|
||||||
|
"url": "https://raw.githubusercontent.com/ziglang/zig/f1992a39a59b941f397b8501a525b38e5863a527/doc/langref.html.in"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"make-shell": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1634940815,
|
||||||
|
"narHash": "sha256-P69OmveboXzS+es1vQGS4bt+ckwbeIExqxfGLjGuJqA=",
|
||||||
|
"owner": "ursi",
|
||||||
|
"repo": "nix-make-shell",
|
||||||
|
"rev": "8add91681170924e4d0591b22f294aee3f5516f9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ursi",
|
||||||
|
"repo": "nix-make-shell",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694959747,
|
||||||
|
"narHash": "sha256-CXQ2MuledDVlVM5dLC4pB41cFlBWxRw4tCBsFrq3cRk=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "970a59bd19eff3752ce552935687100c46e820a5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689088367,
|
||||||
|
"narHash": "sha256-Y2tl2TlKCWEHrOeM9ivjCLlRAKH3qoPUE/emhZECU14=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "5c9ddb86679c400d6b7360797b8a22167c2053f8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "release-23.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"bash": "bash",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"make-shell": "make-shell",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"zig": "zig",
|
||||||
|
"zls": "zls"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zig": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1695125316,
|
||||||
|
"narHash": "sha256-9Ewco7m4zgajBhppCM1mEmQE/K6ObkbwUhtJ3lJlfto=",
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"rev": "078666381440c3303566a8a0f34628703202b54e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zls": {
|
||||||
|
"inputs": {
|
||||||
|
"binned_allocator": "binned_allocator",
|
||||||
|
"diffz": "diffz",
|
||||||
|
"flake-utils": "flake-utils_3",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"known_folders": "known_folders",
|
||||||
|
"langref": "langref",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"zig-overlay": [
|
||||||
|
"zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1695231678,
|
||||||
|
"narHash": "sha256-R6z0+6U7okQxmOR867nUTCzbRwtuGokGgtqvXP78XK8=",
|
||||||
|
"owner": "zigtools",
|
||||||
|
"repo": "zls",
|
||||||
|
"rev": "20b80784998e342296473a2192ea70935ab84b8d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "zigtools",
|
||||||
|
"repo": "zls",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
78
flake.nix
Normal file
78
flake.nix
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
{
|
||||||
|
description = "ztacacs";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs = {
|
||||||
|
url = "nixpkgs/nixos-unstable";
|
||||||
|
};
|
||||||
|
flake-utils = {
|
||||||
|
url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
bash = {
|
||||||
|
url = "git+https://git.ocjtech.us/jeff/nixos-bash-prompt-builder.git";
|
||||||
|
};
|
||||||
|
make-shell = {
|
||||||
|
url = "github:ursi/nix-make-shell";
|
||||||
|
};
|
||||||
|
zig = {
|
||||||
|
url = "github:mitchellh/zig-overlay";
|
||||||
|
};
|
||||||
|
zls = {
|
||||||
|
url = "github:zigtools/zls";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.zig-overlay.follows = "zig";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils, bash, ... }@inputs:
|
||||||
|
let
|
||||||
|
# overlays = [
|
||||||
|
# (
|
||||||
|
# final: prev: {
|
||||||
|
# zigpkgs = inputs.zig.packages.${prev.system};
|
||||||
|
# }
|
||||||
|
|
||||||
|
# )
|
||||||
|
# ];
|
||||||
|
systems = builtins.attrNames inputs.zig.packages;
|
||||||
|
in
|
||||||
|
flake-utils.lib.eachSystem systems (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default =
|
||||||
|
let
|
||||||
|
project = "ztacacs";
|
||||||
|
prompt = (
|
||||||
|
bash.build_prompt
|
||||||
|
bash.ansi_normal_blue
|
||||||
|
"${project} - ${bash.username}@${bash.hostname_short}: ${bash.current_working_directory}"
|
||||||
|
"${project}:${bash.current_working_directory}"
|
||||||
|
);
|
||||||
|
make-shell = import inputs.make-shell {
|
||||||
|
inherit system;
|
||||||
|
pkgs = pkgs;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
make-shell {
|
||||||
|
packages = [
|
||||||
|
inputs.zig.packages.${system}.master
|
||||||
|
inputs.zls.packages.${system}.zls
|
||||||
|
];
|
||||||
|
env = {
|
||||||
|
PS1 = prompt;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# packages.default = inputs.zig.packages.${system}.zigStdenv.mkDerivation {
|
||||||
|
# pname = "ztacacs";
|
||||||
|
# version = "0.1.0";
|
||||||
|
# buildInputs = [ ];
|
||||||
|
# src = ./.;
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
57
src/main.zig
Normal file
57
src/main.zig
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const serde = @import("serde.zig");
|
||||||
|
const packet = @import("packet.zig");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
var socket = std.net.StreamServer.init(.{ .reuse_address = true, .reuse_port = true });
|
||||||
|
defer socket.deinit();
|
||||||
|
|
||||||
|
try socket.listen(std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 4949));
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const server = try allocator.create(Server);
|
||||||
|
server.* = Server{
|
||||||
|
.allocator = allocator,
|
||||||
|
.conn = try socket.accept(),
|
||||||
|
};
|
||||||
|
const thread = try std.Thread.spawn(.{ .allocator = allocator }, Server.run, .{server});
|
||||||
|
thread.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Server = struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
conn: std.net.StreamServer.Connection,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn run(self: *Self) !void {
|
||||||
|
std.debug.print("starting: {}\n", .{self.conn.address});
|
||||||
|
defer self.deinit();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var buffer: [@sizeOf(packet.Header)]u8 = undefined;
|
||||||
|
const len = try self.conn.stream.read(buffer[0..]);
|
||||||
|
// if (len < @sizeOf(packet.Header)) break;
|
||||||
|
if (len == 0) break;
|
||||||
|
std.debug.print("{}\n", .{len});
|
||||||
|
_ = try self.conn.stream.write(buffer[0..len]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.print("finished\n", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *Self) void {
|
||||||
|
std.debug.print("start deinit\n", .{});
|
||||||
|
self.conn.stream.close();
|
||||||
|
self.allocator.destroy(self);
|
||||||
|
std.debug.print("end deinit\n", .{});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "main" {
|
||||||
|
std.debug.print("hello\n", .{});
|
||||||
|
}
|
189
src/packet.zig
Normal file
189
src/packet.zig
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const serde = @import("serde.zig");
|
||||||
|
|
||||||
|
pub const MajorVersion = enum(u4) {
|
||||||
|
Default = 0xc,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MinorVersion = enum(u4) {
|
||||||
|
Default = 0x0,
|
||||||
|
One = 0x1,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PacketType = enum(u8) {
|
||||||
|
Authentication = 1,
|
||||||
|
Authorization = 2,
|
||||||
|
Accounting = 3,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const HeaderFlags = packed struct(u8) {
|
||||||
|
Unencrypted: bool = false,
|
||||||
|
_p1: u1 = 0,
|
||||||
|
SingleConnect: bool = false,
|
||||||
|
_p2: u5 = 0,
|
||||||
|
|
||||||
|
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
|
||||||
|
try writer.print("{s}{{ .Unencrypted = {}, .SingleConnect = {} }}", .{
|
||||||
|
@typeName(@This()),
|
||||||
|
value.Unencrypted,
|
||||||
|
value.SingleConnect,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Header = struct {
|
||||||
|
major: MajorVersion,
|
||||||
|
minor: MinorVersion,
|
||||||
|
type: PacketType,
|
||||||
|
seq_no: u8,
|
||||||
|
flags: HeaderFlags,
|
||||||
|
session_id: u32,
|
||||||
|
length: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
test "header 1" {
|
||||||
|
const packet = [_]u8{ 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
var reader = serde.Reader.init(&packet);
|
||||||
|
const header = try reader.read(Header);
|
||||||
|
std.debug.print("{}\n", .{header});
|
||||||
|
try std.testing.expect(header.major == .Default);
|
||||||
|
try std.testing.expect(header.minor == .Default);
|
||||||
|
try std.testing.expect(header.type == .Authentication);
|
||||||
|
try std.testing.expect(header.seq_no == 0);
|
||||||
|
try std.testing.expect(!header.flags.Unencrypted);
|
||||||
|
try std.testing.expect(!header.flags.SingleConnect);
|
||||||
|
try std.testing.expect(header.session_id == 0);
|
||||||
|
try std.testing.expect(header.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "header 2" {
|
||||||
|
const packet = [_]u8{ 0xc0, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
var reader = serde.Reader.init(&packet);
|
||||||
|
const header = try reader.read(Header);
|
||||||
|
std.debug.print("{}\n", .{header});
|
||||||
|
try std.testing.expect(header.major == .Default);
|
||||||
|
try std.testing.expect(header.minor == .Default);
|
||||||
|
try std.testing.expect(header.type == .Authorization);
|
||||||
|
try std.testing.expect(header.seq_no == 2);
|
||||||
|
try std.testing.expect(header.flags.Unencrypted);
|
||||||
|
try std.testing.expect(!header.flags.SingleConnect);
|
||||||
|
try std.testing.expect(header.session_id == 0);
|
||||||
|
try std.testing.expect(header.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "header 3" {
|
||||||
|
const packet = [_]u8{ 0xc0, 0x03, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
var reader = serde.Reader.init(&packet);
|
||||||
|
const header = try reader.read(Header);
|
||||||
|
std.debug.print("{}\n", .{header});
|
||||||
|
try std.testing.expect(header.major == .Default);
|
||||||
|
try std.testing.expect(header.minor == .Default);
|
||||||
|
try std.testing.expect(header.type == .Accounting);
|
||||||
|
try std.testing.expect(header.seq_no == 255);
|
||||||
|
try std.testing.expect(!header.flags.Unencrypted);
|
||||||
|
try std.testing.expect(header.flags.SingleConnect);
|
||||||
|
try std.testing.expect(header.session_id == 0);
|
||||||
|
try std.testing.expect(header.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const AuthenticationAction = enum(u8) {
|
||||||
|
Login = 0x01,
|
||||||
|
ChangePassword = 0x02,
|
||||||
|
SendAuth = 0x03,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationType = enum(u8) {
|
||||||
|
ASCII = 0x01,
|
||||||
|
PAP = 0x02,
|
||||||
|
CHAP = 0x03,
|
||||||
|
MSCHAP = 0x05,
|
||||||
|
MSCHAPV2 = 0x06,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationService = enum(u8) {
|
||||||
|
NONE = 0x00,
|
||||||
|
LOGIN = 0x01,
|
||||||
|
ENABLE = 0x02,
|
||||||
|
PPP = 0x03,
|
||||||
|
PT = 0x05,
|
||||||
|
RCMD = 0x06,
|
||||||
|
X25 = 0x07,
|
||||||
|
NASI = 0x08,
|
||||||
|
FWPROXY = 0x09,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationStartHeader = struct {
|
||||||
|
action: AuthenticationAction,
|
||||||
|
priv_lvl: u8,
|
||||||
|
authen_type: AuthenticationType,
|
||||||
|
authen_service: AuthenticationService,
|
||||||
|
user_len: u8,
|
||||||
|
port_len: u8,
|
||||||
|
rem_addr_len: u8,
|
||||||
|
data_len: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationStatus = enum(u8) {
|
||||||
|
PASS = 0x01,
|
||||||
|
FAIL = 0x02,
|
||||||
|
GETDATA = 0x03,
|
||||||
|
GETUSER = 0x04,
|
||||||
|
GETPASS = 0x05,
|
||||||
|
RESTART = 0x06,
|
||||||
|
ERROR = 0x07,
|
||||||
|
FOLLOW = 0x21,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationReplyFlags = packed struct(u8) {
|
||||||
|
NoEcho: bool,
|
||||||
|
_p1: u7 = 0,
|
||||||
|
|
||||||
|
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
|
||||||
|
try writer.print("{s}{{ .NoEcho = {}, }}", .{
|
||||||
|
@typeName(@This()),
|
||||||
|
value.NoEcho,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationReplyHeader = struct {
|
||||||
|
status: AuthenticationStatus,
|
||||||
|
flags: AuthenticationReplyFlags,
|
||||||
|
server_msg_len: u16,
|
||||||
|
data_len: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationContinueFlags = packed struct(u8) {
|
||||||
|
Abort: bool,
|
||||||
|
_p1: u7 = 0,
|
||||||
|
|
||||||
|
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
|
||||||
|
try writer.print("{s}{{ .Abort = {}, }}", .{
|
||||||
|
@typeName(@This()),
|
||||||
|
value.Abort,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthenticationContinueHeader = struct {
|
||||||
|
user_msg: u16,
|
||||||
|
data_len: u16,
|
||||||
|
flags: AuthenticationContinueFlags,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AuthorizationRequestHeader = struct {
|
||||||
|
authen_method: u8,
|
||||||
|
priv_lvl: u8,
|
||||||
|
authen_type: u8,
|
||||||
|
authen_service: u8,
|
||||||
|
user_len: u8,
|
||||||
|
port_len: u8,
|
||||||
|
rem_addr_len: u8,
|
||||||
|
arg_cnt: u8,
|
||||||
|
};
|
103
src/serde.zig
Normal file
103
src/serde.zig
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const SerdeError = error{
|
||||||
|
IllegalSize,
|
||||||
|
LeftoverBits,
|
||||||
|
NotEnoughBitsLeft,
|
||||||
|
NotEnoughBytesLeft,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Reader = struct {
|
||||||
|
bytes: []const u8,
|
||||||
|
index: usize,
|
||||||
|
bits_left: usize,
|
||||||
|
|
||||||
|
pub fn init(bytes: []const u8) Reader {
|
||||||
|
return .{
|
||||||
|
.bytes = bytes,
|
||||||
|
.index = 0,
|
||||||
|
.bits_left = 8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(self: *Reader, comptime T: type) SerdeError!T {
|
||||||
|
if (self.index >= self.bytes.len) return error.NotEnoughBytesLeft;
|
||||||
|
return switch (@typeInfo(T)) {
|
||||||
|
.Int => try self.readInt(T),
|
||||||
|
.Bool => try self.readBool(T),
|
||||||
|
.Enum => try self.readEnum(T),
|
||||||
|
.Struct => try self.readStruct(T),
|
||||||
|
.Array => |array| {
|
||||||
|
var arr: [array.len]array.child = undefined;
|
||||||
|
var index: usize = 0;
|
||||||
|
while (index < array.len) : (index += 1) {
|
||||||
|
arr[index] = try self.read(array.child);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
else => @compileError("unsupported type"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readInt(self: *Reader, comptime T: type) SerdeError!T {
|
||||||
|
const bits = @typeInfo(T).Int.bits;
|
||||||
|
|
||||||
|
if (bits < 8) {
|
||||||
|
if (bits > self.bits_left) return error.NotEnoughBitsLeft;
|
||||||
|
const shift: u3 = @truncate(self.bits_left - bits);
|
||||||
|
const mask = (1 << bits) - 1;
|
||||||
|
const b = (self.bytes[self.index] >> shift) & mask;
|
||||||
|
self.bits_left -= bits;
|
||||||
|
if (self.bits_left == 0) {
|
||||||
|
self.bits_left = 8;
|
||||||
|
self.index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return @intCast(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits % 8 == 0 and self.bits_left != 8) return error.LeftoverBits;
|
||||||
|
if (bits % 8 != 0) return error.IllegalSize;
|
||||||
|
|
||||||
|
const size = bits / 8;
|
||||||
|
|
||||||
|
if (self.index + size > self.bytes.len) return error.NotEnoughBytesLeft;
|
||||||
|
|
||||||
|
const slice = self.bytes[self.index .. self.index + size];
|
||||||
|
const value = @as(*align(1) const T, @ptrCast(slice)).*;
|
||||||
|
|
||||||
|
self.index += size;
|
||||||
|
return std.mem.bigToNative(T, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readBool(self: *Reader, comptime T: type) SerdeError!T {
|
||||||
|
const x = try self.read(u1);
|
||||||
|
std.debug.print("bool {}\n", .{x});
|
||||||
|
return x == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readEnum(self: *Reader, comptime T: type) SerdeError!T {
|
||||||
|
return @enumFromInt(try self.read(@typeInfo(T).Enum.tag_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readStruct(self: *Reader, comptime T: type) SerdeError!T {
|
||||||
|
if (@typeInfo(T).Struct.layout == .Packed) {
|
||||||
|
const value = try self.read(@typeInfo(T).Struct.backing_integer.?);
|
||||||
|
return @as(*const T, @ptrCast(&value)).*;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields = std.meta.fields(T);
|
||||||
|
|
||||||
|
var value: T = undefined;
|
||||||
|
|
||||||
|
inline for (fields) |field| {
|
||||||
|
@field(value, field.name) = try self.read(field.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isComplete(self: *Reader) bool {
|
||||||
|
return self.index >= self.bytes.len;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue