1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
//! By convention, main.zig is where your main function lives in the case that
//! you are building an executable. If you are making a library, the convention
//! is to delete this file and start with root.zig instead.
const is_debug = builtin.mode == .Debug;
const SaprusPacketType = enum(u16) {
relay = 0x003C,
file_transfer = 0x8888,
};
const SaprusHeaderFrame = struct {
msg_type: SaprusPacketType,
payload: []u8,
const Self = @This();
fn toBytes(s: Self, allocator: Allocator) ![]u8 {
const buf = try allocator.alloc(u8, 4 + s.payload.len);
std.mem.writeInt(u16, buf[0..2], @intFromEnum(s.msg_type), .big);
std.mem.writeInt(u16, buf[2..4], @intCast(s.payload.len), .big);
std.mem.copyForwards(u8, buf[4..], s.payload);
return buf;
}
};
const SaprusRelayMessage = struct {
dest: [4]u8,
payload: []u8,
const Self = @This();
fn toBytes(s: Self, allocator: Allocator) ![]u8 {
const buf = try allocator.alloc(u8, 4 + s.payload.len);
std.mem.copyForwards(u8, buf[0..4], &s.dest);
std.mem.copyForwards(u8, buf[4..], s.payload);
std.debug.print("in tobytes {x}\n", .{buf});
return buf;
}
};
pub fn main() !void {
const DBA = std.heap.DebugAllocator(.{});
var dba: ?DBA = if (comptime is_debug) DBA.init else null;
defer if (dba) |*d| {
_ = d.deinit();
};
var allocator = if (dba) |*d| d.allocator() else std.heap.smp_allocator;
const str_msg = "Hello darkness my old friend";
var payload_bytes: [str_msg.len + 1]u8 = @splat(0);
// const payload_bytes = try allocator.alloc(u8, str_msg.len);
// defer allocator.free(payload_bytes);
// std.mem.copyForwards(u8, payload_bytes[0..], str_msg);
std.mem.copyBackwards(u8, payload_bytes[0..], str_msg);
const relay: SaprusRelayMessage = .{
.dest = [_]u8{ 255, 255, 255, 255 },
.payload = payload_bytes[0..str_msg.len],
};
const relay_bytes = try relay.toBytes(allocator);
defer allocator.free(relay_bytes);
const msg: SaprusHeaderFrame = .{
.msg_type = .relay,
.payload = relay_bytes,
};
const msg_bytes = try msg.toBytes(allocator);
defer allocator.free(msg_bytes);
try network.init();
defer network.deinit();
var sock = try network.Socket.create(.ipv4, .udp);
defer sock.close();
try sock.setBroadcast(true);
// Bind to 0.0.0.0:0
const bind_addr = network.EndPoint{
.address = network.Address{ .ipv4 = network.Address.IPv4.any },
.port = 0,
};
const dest_addr = network.EndPoint{
.address = network.Address{ .ipv4 = network.Address.IPv4.broadcast },
.port = 8888,
};
try sock.bind(bind_addr);
// std.debug.print("relay: {x}\n", .{relay_bytes});
std.debug.print("message bytes: {x}\n", .{msg_bytes});
// @breakpoint();
_ = try sock.sendTo(dest_addr, msg_bytes);
// // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
// std.debug.print("All your {any} are belong to us.\n", .{msg});
// // stdout is for the actual output of your application, for example if you
// // are implementing gzip, then only the compressed bytes should be sent to
// // stdout, not any debugging messages.
// const stdout_file = std.io.getStdOut().writer();
// var bw = std.io.bufferedWriter(stdout_file);
// const stdout = bw.writer();
// try stdout.print("Run `zig build test` to run the tests.\n", .{});
// try bw.flush(); // Don't forget to flush!
}
test "simple test" {
var list = std.ArrayList(i32).init(std.testing.allocator);
defer list.deinit(); // Try commenting this out and see if zig detects the memory leak!
try list.append(42);
try std.testing.expectEqual(@as(i32, 42), list.pop());
}
test "fuzz example" {
const Context = struct {
fn testOne(context: @This(), input: []const u8) anyerror!void {
_ = context;
// Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
}
};
try std.testing.fuzz(Context{}, Context.testOne, .{});
}
const builtin = @import("builtin");
const std = @import("std");
const Allocator = std.mem.Allocator;
const network = @import("network");
|