Son aktivite 1719876461

This is a http server that serves a infinitely big file filled with random content

adridoesthings's Avatar adridoesthings bu gisti düzenledi 1719876461. Düzenlemeye git

1 file changed, 1 insertion, 1 deletion

unlimited-download.zig

@@ -102,7 +102,7 @@ pub fn main() !void {
102 102 unreachable;
103 103 }
104 104
105 - const listen_address = try std.net.Address.resolveIp(args[3], try std.fmt.parseInt(u16, args[4], 10));
105 + const listen_address = try std.net.Address.parseIp(args[3], try std.fmt.parseInt(u16, args[4], 10));
106 106 var server = try listen_address.listen(.{ .reuse_address = true });
107 107 defer server.deinit();
108 108 std.log.info("Listening on http://{s}:{s}", .{ args[3], args[4] });

adridoesthings's Avatar adridoesthings bu gisti düzenledi 1719864389. Düzenlemeye git

Değişiklik yok

adridoesthings's Avatar adridoesthings bu gisti düzenledi 1719864300. Düzenlemeye git

Değişiklik yok

AdriDoesThings bu gisti düzenledi 1719864205. Düzenlemeye git

1 file changed, 114 insertions

unlimited-download.zig(dosya oluşturuldu)

@@ -0,0 +1,114 @@
1 + const std = @import("std");
2 + const eql = std.mem.eql;
3 +
4 + pub const std_options = .{
5 + .log_level = .info,
6 + };
7 +
8 + fn http_error(writer: std.net.Stream.Writer, status_code: u16) !void {
9 + const status = switch (status_code) {
10 + 200 => "OK",
11 + 400 => "Bad Request",
12 + 404 => "Not Found",
13 + 405 => "Method Not Allowed",
14 + else => @panic("Invalid status"),
15 + };
16 +
17 + try writer.print("HTTP/1.1 {d} {s}\r\nServer: zig\r\nContent-Type: text/plain\r\nContent-Length: {d}\r\n\r\n{s}", .{ status_code, status, status.len, status });
18 + }
19 +
20 + fn format_bytes(buf: []u8, bytes: usize) ![]u8 {
21 + const fbytes: f32 = @floatFromInt(bytes);
22 + return switch (bytes) {
23 + 0...1024 => std.fmt.bufPrint(buf, "{d} B", .{bytes}),
24 + 1025...(1024 * 1024) => std.fmt.bufPrint(buf, "{d:.1} KiB", .{fbytes / 1024}),
25 + (1024 * 1024 + 1)...(1024 * 1024 * 1024) => std.fmt.bufPrint(buf, "{d:.1} MiB", .{fbytes / 1024 / 1024}),
26 + else => std.fmt.bufPrint(buf, "{d:.1} GiB", .{fbytes / 1024 / 1024 / 1024}),
27 + };
28 + }
29 +
30 + fn handle_connection(connection: std.net.Server.Connection, path: []u8, filename: []u8) !void {
31 + const writer = connection.stream.writer();
32 +
33 + {
34 + var buffer: [255]u8 = undefined;
35 + const n = try connection.stream.read(&buffer);
36 + if (n < 12) {
37 + return http_error(writer, 400);
38 + }
39 +
40 + if (!eql(u8, buffer[0..4], "GET ")) {
41 + return http_error(writer, 405);
42 + }
43 +
44 + if (n < (11 + path.len) or !eql(u8, buffer[4 .. 4 + path.len], path)) {
45 + return http_error(writer, 404);
46 + }
47 + }
48 +
49 + var prng = std.rand.DefaultPrng.init(blk: {
50 + var seed: u64 = undefined;
51 + try std.posix.getrandom(std.mem.asBytes(&seed));
52 + break :blk seed;
53 + });
54 + const random = prng.random();
55 +
56 + std.log.info("Client {} connected", .{connection.address});
57 + defer {
58 + connection.stream.close();
59 + std.log.info("Client {} disconnected", .{connection.address});
60 + }
61 +
62 + try writer.print("HTTP/1.1 200 OK\r\nServer: zig\r\nContent-Type: application/octet-stream\r\nContent-Disposition: attachment; filename=\"{s}\"\r\n\r\n", .{filename});
63 +
64 + var downloaded: usize = 0;
65 + var out_counter: usize = 0;
66 +
67 + while (true) {
68 + var writeBuffer: [1024]u8 = undefined;
69 + random.bytes(&writeBuffer);
70 + const wrote = connection.stream.write(&writeBuffer) catch |err| switch (err) {
71 + error.BrokenPipe => break,
72 + error.ConnectionResetByPeer => break,
73 + else => return err,
74 + };
75 + downloaded += wrote;
76 + out_counter += wrote;
77 +
78 + if (out_counter >= 1024 * 1024 * 100) {
79 + var buf: [16]u8 = undefined;
80 + const downloaded_fmt = try format_bytes(&buf, downloaded);
81 + std.log.info("Client {} downloaded {s}", .{ connection.address, downloaded_fmt });
82 + out_counter = 0;
83 + }
84 + }
85 + }
86 +
87 + pub fn main() !void {
88 + var gpa = std.heap.GeneralPurposeAllocator(.{}){};
89 + const allocator = gpa.allocator();
90 + defer {
91 + const check = gpa.deinit();
92 + if (check == .leak) @panic("memory leaks");
93 + }
94 +
95 + const args = try std.process.argsAlloc(allocator);
96 + defer std.process.argsFree(allocator, args);
97 +
98 + if (args.len != 5) {
99 + const writer = std.io.getStdErr().writer();
100 + try writer.print("Usage: {s} DOWNLOAD_PATH DOWNLOAD_FILENAME ADDRESS PORT\n", .{args[0]});
101 + std.process.exit(1);
102 + unreachable;
103 + }
104 +
105 + const listen_address = try std.net.Address.resolveIp(args[3], try std.fmt.parseInt(u16, args[4], 10));
106 + var server = try listen_address.listen(.{ .reuse_address = true });
107 + defer server.deinit();
108 + std.log.info("Listening on http://{s}:{s}", .{ args[3], args[4] });
109 +
110 + while (true) {
111 + const connection = try server.accept();
112 + _ = try std.Thread.spawn(.{}, handle_connection, .{ connection, args[1], args[2] });
113 + }
114 + }
Daha yeni Daha eski