tangled
alpha
login
or
join now
altagos.dev
/
aether
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
BytePacketBuffer read api
altagos.dev
9 months ago
326d319f
ef43edf7
verified
This commit was signed with the committer's
known signature
.
altagos.dev
SSH Key Fingerprint:
SHA256:UbTjEcCZlc6GzQWLCuDK3D//HESWD2xFPkzue9XMras=
+149
-11
2 changed files
expand all
collapse all
unified
split
src
main.zig
root.zig
-1
src/main.zig
···
3
3
4
4
pub fn main() !void {
5
5
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
6
6
-
try aether.advancedPrint();
7
6
}
8
7
9
8
test "simple test" {
+149
-10
src/root.zig
···
1
1
const std = @import("std");
2
2
3
3
-
pub fn advancedPrint() !void {
4
4
-
const stdout_file = std.io.getStdOut().writer();
5
5
-
var bw = std.io.bufferedWriter(stdout_file);
6
6
-
const stdout = bw.writer();
3
3
+
pub const BytePacketBuffer = struct {
4
4
+
buf: [512]u8 = undefined,
5
5
+
pos: usize = 0,
6
6
+
7
7
+
/// Change the buffer position forward a specific number of steps
8
8
+
pub fn step(self: *BytePacketBuffer, pos: usize) void {
9
9
+
self.pos += pos;
10
10
+
}
11
11
+
12
12
+
/// Chanke the buffer position
13
13
+
pub fn seek(self: *BytePacketBuffer, pos: usize) void {
14
14
+
self.pos = pos;
15
15
+
}
16
16
+
17
17
+
/// Read a single byte and move the position one step forward
18
18
+
pub fn read(self: *BytePacketBuffer) error{EndOfBuffer}!u8 {
19
19
+
if (self.pos >= comptime self.buf.len) return error.EndOfBuffer;
20
20
+
const res = self.buf[self.pos];
21
21
+
self.pos += 1;
22
22
+
return res;
23
23
+
}
24
24
+
25
25
+
/// Get a single byte without changing the buffer position
26
26
+
pub fn get(self: *const BytePacketBuffer, pos: usize) error{EndOfBuffer}!u8 {
27
27
+
if (pos >= comptime self.buf.len) return error.EndOfBuffer;
28
28
+
return self.buf[pos];
29
29
+
}
30
30
+
31
31
+
/// Get a range of bytes
32
32
+
pub fn get_range(self: *const BytePacketBuffer, start: usize, len: usize) error{EndOfBuffer}![]const u8 {
33
33
+
if (start + len >= comptime self.buf.len) return error.EndOfBuffer;
34
34
+
return self.buf[start .. start + len];
35
35
+
}
36
36
+
37
37
+
/// Read two bytes, stepping two steps forward
38
38
+
pub fn read_u16(self: *BytePacketBuffer) error{EndOfBuffer}!u16 {
39
39
+
return (@as(u16, try self.read()) << 8) |
40
40
+
@as(u16, try self.read());
41
41
+
}
42
42
+
43
43
+
/// Read two bytes, stepping two steps forward
44
44
+
pub fn read_u32(self: *BytePacketBuffer) error{EndOfBuffer}!u32 {
45
45
+
return @as(u32, try self.read()) << 24 |
46
46
+
(@as(u32, try self.read()) << 16) |
47
47
+
(@as(u32, try self.read()) << 8) |
48
48
+
(@as(u32, try self.read()));
49
49
+
}
50
50
+
51
51
+
/// Read a qname
52
52
+
///
53
53
+
/// The tricky part: Reading domain names, taking labels into consideration.
54
54
+
/// Will take something like [3]www[6]google[3]com and append
55
55
+
/// www.google.com to outstr.
56
56
+
pub fn read_qname(self: *BytePacketBuffer, outstr: []u8) !void {
57
57
+
// We might encounter jumps, therefore we need to keep thrack of our position locally
58
58
+
var pos = self.pos;
59
59
+
var out_pos: usize = 0;
60
60
+
61
61
+
// track whether or nor we've jumped
62
62
+
var jumped = false;
63
63
+
const max_jumps: usize = 5;
64
64
+
var jumps_performed: usize = 0;
65
65
+
66
66
+
var delim: ?[]const u8 = null;
67
67
+
while (true) {
68
68
+
if (jumps_performed > max_jumps) return error.JumpLimitExceeded;
69
69
+
70
70
+
// Each label starts with a length byte
71
71
+
const len = try self.get(pos);
72
72
+
73
73
+
// If len has the two most signigicant bit set, it represents a jump to some other
74
74
+
// offset in the packet:
75
75
+
if ((len & 0xC0) == 0xC0) {
76
76
+
// Update the buffer position to a point past the current label
77
77
+
if (!jumped) self.seek(2);
78
78
+
79
79
+
// Read another byte, calculate offset and performe the jump by updating our
80
80
+
// local position variable
81
81
+
const b2 = @as(u16, try self.get(pos + 1));
82
82
+
const offset = ((@as(u16, len) ^ 0xC0) << 8) | b2;
83
83
+
pos = @as(usize, offset);
7
84
8
8
-
try stdout.print("Run `zig build test` to run the tests.\n", .{});
85
85
+
// Indicate that a jump was performed
86
86
+
jumped = true;
87
87
+
jumps_performed += 1;
88
88
+
89
89
+
continue;
90
90
+
} else {
91
91
+
// Move a single byte forward to move path the length
92
92
+
pos += 1;
93
93
+
94
94
+
// Domain names are terminated by an empty label of length 0, so if the length
95
95
+
// is zero we're done
96
96
+
if (len == 0) break;
97
97
+
98
98
+
if (delim) |del| {
99
99
+
@memcpy(outstr[out_pos .. out_pos + del.len], del);
100
100
+
out_pos += del.len;
101
101
+
}
102
102
+
103
103
+
@memcpy(outstr[out_pos .. out_pos + len], try self.get_range(pos, len));
104
104
+
delim = ".";
105
105
+
106
106
+
pos += len;
107
107
+
out_pos += len;
108
108
+
}
109
109
+
}
110
110
+
111
111
+
if (!jumped) self.seek(1);
112
112
+
}
113
113
+
};
114
114
+
115
115
+
test "BytePacketBuffer.read" {
116
116
+
const testing = std.testing;
117
117
+
var buf = BytePacketBuffer{};
118
118
+
buf.buf[0] = 0x1;
119
119
+
try testing.expectEqual(0x1, try buf.read());
120
120
+
}
9
121
10
10
-
try bw.flush(); // Don't forget to flush!
122
122
+
test "BytePacketBuffer.read_u16" {
123
123
+
const testing = std.testing;
124
124
+
var buf = BytePacketBuffer{};
125
125
+
buf.buf[0] = 0x1;
126
126
+
buf.buf[1] = 0x1;
127
127
+
try testing.expectEqual(0x101, try buf.read_u16());
11
128
}
12
129
13
13
-
pub fn add(a: i32, b: i32) i32 {
14
14
-
return a + b;
130
130
+
test "BytePacketBuffer.read_u32" {
131
131
+
const testing = std.testing;
132
132
+
var buf = BytePacketBuffer{};
133
133
+
buf.buf[0] = 0x1;
134
134
+
buf.buf[1] = 0x1;
135
135
+
buf.buf[2] = 0x1;
136
136
+
buf.buf[3] = 0x1;
137
137
+
try testing.expectEqual(0x1010101, try buf.read_u32());
15
138
}
16
139
17
17
-
test "basic add functionality" {
18
18
-
try std.testing.expect(add(3, 7) == 10);
140
140
+
test "BytePacketBuffer.read_qname" {
141
141
+
const testing = std.testing;
142
142
+
const allocator = testing.allocator;
143
143
+
144
144
+
const input = [_]u8{ 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00 };
145
145
+
var buf = BytePacketBuffer{};
146
146
+
147
147
+
for (input, 0..) |char, idx| {
148
148
+
buf.buf[idx] = char;
149
149
+
}
150
150
+
151
151
+
const expected = "google.com";
152
152
+
const outstr = try allocator.alloc(u8, expected.len);
153
153
+
defer allocator.free(outstr);
154
154
+
155
155
+
try buf.read_qname(outstr);
156
156
+
157
157
+
try testing.expectEqualStrings(expected, outstr);
19
158
}