Commit cbda0fa78c

Andrew Kelley <superjoe30@gmail.com>
2018-04-09 02:08:40
basic tcp server working when used with netcat
1 parent acd8f6e
Changed files (3)
std/os/index.zig
@@ -2229,3 +2229,27 @@ pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usiz
         }
     }
 }
+
+pub const PosixGetSockNameError = error {
+    /// Insufficient resources were available in the system to perform the operation.
+    SystemResources,
+
+    Unexpected,
+};
+
+pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr {
+    var addr: posix.sockaddr = undefined;
+    var addrlen: posix.socklen_t = @sizeOf(posix.sockaddr);
+    const rc = posix.getsockname(sockfd, &addr, &addrlen);
+    const err = posix.getErrno(rc);
+    switch (err) {
+        0 => return addr,
+        else => return unexpectedErrorPosix(err),
+
+        posix.EBADF => unreachable,
+        posix.EFAULT => unreachable,
+        posix.EINVAL => unreachable,
+        posix.ENOTSOCK => unreachable,
+        posix.ENOBUFS => return PosixGetSockNameError.SystemResources,
+    }
+}
std/event.zig
@@ -5,11 +5,12 @@ const mem = std.mem;
 const posix = std.os.posix;
 
 pub const TcpServer = struct {
-    handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
+    handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
 
     loop: &Loop,
     sockfd: i32,
     accept_coro: ?promise,
+    listen_address: std.net.Address,
 
     waiting_for_emfile_node: PromiseNode,
 
@@ -28,18 +29,20 @@ pub const TcpServer = struct {
             .accept_coro = null,
             .handleRequestFn = undefined,
             .waiting_for_emfile_node = undefined,
+            .listen_address = undefined,
         };
     }
 
     pub fn listen(self: &TcpServer, address: &const std.net.Address,
-        handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
+        handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
     {
         self.handleRequestFn = handleRequestFn;
 
         try std.os.posixBind(self.sockfd, &address.sockaddr);
         try std.os.posixListen(self.sockfd, posix.SOMAXCONN);
+        self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(self.sockfd));
 
-        self.accept_coro = try async(self.loop.allocator) (TcpServer.handler)(self); // TODO #817
+        self.accept_coro = try async<self.loop.allocator> TcpServer.handler(self);
         errdefer cancel ??self.accept_coro;
 
         try self.loop.addFd(self.sockfd, ??self.accept_coro);
@@ -60,10 +63,7 @@ pub const TcpServer = struct {
                 posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
             {
                 var socket = std.os.File.openHandle(accepted_fd);
-                // TODO #817
-                _ = async(self.loop.allocator) (self.handleRequestFn)(self, accepted_addr,
-                    socket) catch |err| switch (err)
-                {
+                _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
                     error.OutOfMemory => {
                         socket.close();
                         continue;
@@ -161,7 +161,7 @@ test "listen on a port, send bytes, receive bytes" {
 
         const Self = this;
 
-        async(&mem.Allocator) fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
+        async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
             _socket: &const std.os.File) void
         {
             const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
@@ -198,5 +198,11 @@ test "listen on a port, send bytes, receive bytes" {
     defer server.tcp_server.deinit();
     try server.tcp_server.listen(addr, MyServer.handler);
 
+    var stderr_file = try std.io.getStdErr();
+    var stderr_stream = &std.io.FileOutStream.init(&stderr_file).stream;
+    try stderr_stream.print("\nlistening at ");
+    try server.tcp_server.listen_address.format(stderr_stream);
+    try stderr_stream.print("\n");
+
     loop.run();
 }
std/net.zig
@@ -35,6 +35,12 @@ pub const Address = struct {
         };
     }
 
+    pub fn initPosix(addr: &const posix.sockaddr) Address {
+        return Address {
+            .sockaddr = *addr,
+        };
+    }
+
     pub fn format(self: &const Address, out_stream: var) !void {
         switch (self.sockaddr.in.family) {
             posix.AF_INET => {