authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-08 20:08:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-08 20:08:40-04:00
logcbda0fa78c37dd84821061309469c85a2281174c
tree5fd46a2d100cba00659bfef98c5ff2483e61c812
parentacd8f6ef184c031f672fa6d6a690d831344de4b4

basic tcp server working when used with netcat


3 files changed, 44 insertions(+), 8 deletions(-)

std/event.zig+14-8
......@@ -5,11 +5,12 @@ const mem = std.mem;
55const posix = std.os.posix;
66
77pub const TcpServer = struct {
8 handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
8 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
99
1010 loop: &Loop,
1111 sockfd: i32,
1212 accept_coro: ?promise,
13 listen_address: std.net.Address,
1314
1415 waiting_for_emfile_node: PromiseNode,
1516
......@@ -28,18 +29,20 @@ pub const TcpServer = struct {
2829 .accept_coro = null,
2930 .handleRequestFn = undefined,
3031 .waiting_for_emfile_node = undefined,
32 .listen_address = undefined,
3133 };
3234 }
3335
3436 pub fn listen(self: &TcpServer, address: &const std.net.Address,
35 handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
37 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
3638 {
3739 self.handleRequestFn = handleRequestFn;
3840
3941 try std.os.posixBind(self.sockfd, &address.sockaddr);
4042 try std.os.posixListen(self.sockfd, posix.SOMAXCONN);
43 self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(self.sockfd));
4144
42 self.accept_coro = try async(self.loop.allocator) (TcpServer.handler)(self); // TODO #817
45 self.accept_coro = try async<self.loop.allocator> TcpServer.handler(self);
4346 errdefer cancel ??self.accept_coro;
4447
4548 try self.loop.addFd(self.sockfd, ??self.accept_coro);
......@@ -60,10 +63,7 @@ pub const TcpServer = struct {
6063 posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
6164 {
6265 var socket = std.os.File.openHandle(accepted_fd);
63 // TODO #817
64 _ = async(self.loop.allocator) (self.handleRequestFn)(self, accepted_addr,
65 socket) catch |err| switch (err)
66 {
66 _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
6767 error.OutOfMemory => {
6868 socket.close();
6969 continue;
......@@ -161,7 +161,7 @@ test "listen on a port, send bytes, receive bytes" {
161161
162162 const Self = this;
163163
164 async(&mem.Allocator) fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
164 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
165165 _socket: &const std.os.File) void
166166 {
167167 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
......@@ -198,5 +198,11 @@ test "listen on a port, send bytes, receive bytes" {
198198 defer server.tcp_server.deinit();
199199 try server.tcp_server.listen(addr, MyServer.handler);
200200
201 var stderr_file = try std.io.getStdErr();
202 var stderr_stream = &std.io.FileOutStream.init(&stderr_file).stream;
203 try stderr_stream.print("\nlistening at ");
204 try server.tcp_server.listen_address.format(stderr_stream);
205 try stderr_stream.print("\n");
206
201207 loop.run();
202208}
std/net.zig+6
......@@ -35,6 +35,12 @@ pub const Address = struct {
3535 };
3636 }
3737
38 pub fn initPosix(addr: &const posix.sockaddr) Address {
39 return Address {
40 .sockaddr = *addr,
41 };
42 }
43
3844 pub fn format(self: &const Address, out_stream: var) !void {
3945 switch (self.sockaddr.in.family) {
4046 posix.AF_INET => {
std/os/index.zig+24
......@@ -2229,3 +2229,27 @@ pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usiz
22292229 }
22302230 }
22312231}
2232
2233pub const PosixGetSockNameError = error {
2234 /// Insufficient resources were available in the system to perform the operation.
2235 SystemResources,
2236
2237 Unexpected,
2238};
2239
2240pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr {
2241 var addr: posix.sockaddr = undefined;
2242 var addrlen: posix.socklen_t = @sizeOf(posix.sockaddr);
2243 const rc = posix.getsockname(sockfd, &addr, &addrlen);
2244 const err = posix.getErrno(rc);
2245 switch (err) {
2246 0 => return addr,
2247 else => return unexpectedErrorPosix(err),
2248
2249 posix.EBADF => unreachable,
2250 posix.EFAULT => unreachable,
2251 posix.EINVAL => unreachable,
2252 posix.ENOTSOCK => unreachable,
2253 posix.ENOBUFS => return PosixGetSockNameError.SystemResources,
2254 }
2255}