basic tcp server working when used with netcat

This commit is contained in:
Andrew Kelley 2018-04-08 20:08:40 -04:00
parent acd8f6ef18
commit cbda0fa78c
3 changed files with 44 additions and 8 deletions

View File

@ -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();
}

View File

@ -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 => {

View File

@ -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,
}
}