diff options
Diffstat (limited to 'std')
| -rw-r--r-- | std/event/tcp.zig | 50 | ||||
| -rw-r--r-- | std/os/index.zig | 4 | ||||
| -rw-r--r-- | std/os/linux/index.zig | 10 |
3 files changed, 59 insertions, 5 deletions
diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 5715e46a62..c1e6e891cd 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -110,13 +110,61 @@ pub const Server = struct { } }; +pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 { + const sockfd = try std.os.posixSocket( + posix.AF_UNIX, + posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, + 0, + ); + errdefer std.os.close(sockfd); + + var sock_addr = posix.sockaddr{ + .un = posix.sockaddr_un{ + .family = posix.AF_UNIX, + .path = undefined, + }, + }; + + if (path.len > @typeOf(sock_addr.un.path).len) return error.NameTooLong; + mem.copy(u8, sock_addr.un.path[0..], path); + const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len); + try std.os.posixConnectAsync(sockfd, &sock_addr, size); + try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); + try std.os.posixGetSockOptConnectError(sockfd); + + return sockfd; +} + +pub async fn socketRead(loop: *std.event.Loop, fd: i32, buffer: []u8) !void { + while (true) { + return std.os.posixRead(fd, buffer) catch |err| switch (err) { + error.WouldBlock => { + try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLIN); + continue; + }, + else => return err, + }; + } +} +pub async fn socketWrite(loop: *std.event.Loop, fd: i32, buffer: []const u8) !void { + while (true) { + return std.os.posixWrite(fd, buffer) catch |err| switch (err) { + error.WouldBlock => { + try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLOUT); + continue; + }, + else => return err, + }; + } +} + pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File { var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733 const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp); errdefer std.os.close(sockfd); - try std.os.posixConnectAsync(sockfd, &address.os_addr); + try std.os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in)); try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); try std.os.posixGetSockOptConnectError(sockfd); diff --git a/std/os/index.zig b/std/os/index.zig index d86ab119df..1ce9bd7278 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -2677,9 +2677,9 @@ pub fn posixConnect(sockfd: i32, sockaddr: *const posix.sockaddr) PosixConnectEr /// Same as posixConnect except it is for blocking socket file descriptors. /// It expects to receive EINPROGRESS. -pub fn posixConnectAsync(sockfd: i32, sockaddr: *const posix.sockaddr) PosixConnectError!void { +pub fn posixConnectAsync(sockfd: i32, sockaddr: *const c_void, len: u32) PosixConnectError!void { while (true) { - const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr)); + const rc = posix.connect(sockfd, sockaddr, len); const err = posix.getErrno(rc); switch (err) { 0, posix.EINPROGRESS => return, diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig index c369921e14..6323c89dda 100644 --- a/std/os/linux/index.zig +++ b/std/os/linux/index.zig @@ -1094,6 +1094,7 @@ pub const in_port_t = u16; pub const sa_family_t = u16; pub const socklen_t = u32; +/// This intentionally only has ip4 and ip6 pub const sockaddr = extern union { in: sockaddr_in, in6: sockaddr_in6, @@ -1114,6 +1115,11 @@ pub const sockaddr_in6 = extern struct { scope_id: u32, }; +pub const sockaddr_un = extern struct { + family: sa_family_t, + path: [108]u8, +}; + pub const iovec = extern struct { iov_base: [*]u8, iov_len: usize, @@ -1148,8 +1154,8 @@ pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize { return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags); } -pub fn connect(fd: i32, addr: *const sockaddr, len: socklen_t) usize { - return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len)); +pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { + return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len); } pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { |
