mirror of
https://github.com/ziglang/zig.git
synced 2026-02-19 07:48:31 +00:00
basic tcp server working when used with netcat
This commit is contained in:
parent
acd8f6ef18
commit
cbda0fa78c
@ -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();
|
||||
}
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user