main.zig 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const std = @import("std");
  2. const client = @import("client.zig");
  3. fn handle_connections(clients: *client.Clients) !void {
  4. while (true) {
  5. for (clients.clients.items) |c| {
  6. clients.lock.lock();
  7. var buf = [_]u8{0} ** 1024;
  8. const sock = c.sock;
  9. const r = std.posix.recv(sock, &buf, 0) catch |err| switch (err) {
  10. error.WouldBlock => {
  11. clients.lock.unlock();
  12. continue;
  13. },
  14. else => {
  15. std.debug.print("ERROR : {any}", .{err});
  16. clients.lock.unlock();
  17. continue;
  18. },
  19. };
  20. if (r > 0) {
  21. std.debug.print("Got {} bytes\n", .{r});
  22. }
  23. clients.lock.unlock();
  24. }
  25. std.time.sleep(7 * std.time.ns_per_ms);
  26. }
  27. }
  28. pub fn main() !void {
  29. var gpa = std.heap.GeneralPurposeAllocator(.{}){};
  30. defer _ = gpa.deinit();
  31. const allocator = gpa.allocator();
  32. const sock = try std.posix.socket(std.posix.AF.INET, std.posix.SOCK.STREAM, 0);
  33. const parsed_address = try std.net.Address.parseIp4("127.0.0.1", 8080);
  34. var sock_flags = try std.posix.fcntl(sock, std.c.F.GETFD, 0);
  35. if (sock_flags < 0) {
  36. std.debug.print("got incorrect flags");
  37. return;
  38. }
  39. const enable = [_]u8{ 1, 1, 1, 1, 1, 1, 1, 1 };
  40. try std.posix.setsockopt(sock, std.posix.SOL.SOCKET, std.posix.SO.REUSEPORT | std.posix.SO.REUSEADDR, &enable);
  41. sock_flags = sock_flags | std.c.SOCK.NONBLOCK;
  42. const res = try std.posix.fcntl(sock, std.c.F.SETFD, sock_flags);
  43. if (res < 0) {
  44. std.debug.panic("could not fcntl\n");
  45. }
  46. // Only allow ipv4. select parsed_address.any to allow ipv4 and ipv6 or in6 for only ipv6
  47. try std.posix.bind(sock, @ptrCast(&parsed_address.in), parsed_address.getOsSockLen());
  48. try std.posix.listen(sock, 5);
  49. var addr: std.c.sockaddr.in = .{ .addr = 0, .port = 0 };
  50. var addr_size: std.posix.socklen_t = @sizeOf(std.c.sockaddr.in);
  51. var clients = client.Clients.init(allocator);
  52. defer clients.deinit();
  53. const t = try std.Thread.spawn(.{}, handle_connections, .{&clients});
  54. while (true) {
  55. // TODO: loop over this to accept more than one client
  56. const sock2 = try std.posix.accept(sock, @ptrCast(&addr), &addr_size, std.posix.SOCK.NONBLOCK);
  57. try clients.add(.{ .sock = sock2, .address = addr });
  58. std.debug.print("Got client {any}\n", .{addr});
  59. std.time.sleep(16 * std.time.ns_per_ms);
  60. }
  61. t.join();
  62. }