Commit 3605dd307f
Changed files (9)
lib/std/os/linux/arm-eabi.zig
@@ -648,23 +648,23 @@ pub const Flock = extern struct {
};
pub const msghdr = extern struct {
- msg_name: ?*sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec,
- msg_iovlen: i32,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
- msg_flags: i32,
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: i32,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
};
pub const msghdr_const = extern struct {
- msg_name: ?*const sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec_const,
- msg_iovlen: i32,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
- msg_flags: i32,
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: i32,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
};
pub const blksize_t = i32;
lib/std/os/linux/arm64.zig
@@ -3,8 +3,8 @@ const maxInt = std.math.maxInt;
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const sockaddr = linux.sockaddr;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const pid_t = linux.pid_t;
@@ -499,27 +499,27 @@ pub const Flock = extern struct {
};
pub const msghdr = extern struct {
- msg_name: ?*sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec,
- msg_iovlen: i32,
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: i32,
__pad1: i32 = 0,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
+ control: ?*anyopaque,
+ controllen: socklen_t,
__pad2: socklen_t = 0,
- msg_flags: i32,
+ flags: i32,
};
pub const msghdr_const = extern struct {
- msg_name: ?*const sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec_const,
- msg_iovlen: i32,
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: i32,
__pad1: i32 = 0,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
+ control: ?*anyopaque,
+ controllen: socklen_t,
__pad2: socklen_t = 0,
- msg_flags: i32,
+ flags: i32,
};
pub const blksize_t = i32;
lib/std/os/linux/i386.zig
@@ -2,8 +2,8 @@ const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const pid_t = linux.pid_t;
lib/std/os/linux/io_uring.zig
@@ -537,6 +537,36 @@ pub const IO_Uring = struct {
return sqe;
}
+ /// Queues (but does not submit) an SQE to perform a `recvmsg(2)`.
+ /// Returns a pointer to the SQE.
+ pub fn recvmsg(
+ self: *IO_Uring,
+ user_data: u64,
+ fd: os.fd_t,
+ msg: *os.msghdr,
+ flags: u32,
+ ) !*io_uring_sqe {
+ const sqe = try self.get_sqe();
+ io_uring_prep_recvmsg(sqe, fd, msg, flags);
+ sqe.user_data = user_data;
+ return sqe;
+ }
+
+ /// Queues (but does not submit) an SQE to perform a `sendmsg(2)`.
+ /// Returns a pointer to the SQE.
+ pub fn sendmsg(
+ self: *IO_Uring,
+ user_data: u64,
+ fd: os.fd_t,
+ msg: *const os.msghdr_const,
+ flags: u32,
+ ) !*io_uring_sqe {
+ const sqe = try self.get_sqe();
+ io_uring_prep_sendmsg(sqe, fd, msg, flags);
+ sqe.user_data = user_data;
+ return sqe;
+ }
+
/// Queues (but does not submit) an SQE to perform an `openat(2)`.
/// Returns a pointer to the SQE.
pub fn openat(
@@ -1237,6 +1267,26 @@ pub fn io_uring_prep_send(sqe: *io_uring_sqe, fd: os.fd_t, buffer: []const u8, f
sqe.rw_flags = flags;
}
+pub fn io_uring_prep_recvmsg(
+ sqe: *io_uring_sqe,
+ fd: os.fd_t,
+ msg: *os.msghdr,
+ flags: u32,
+) void {
+ linux.io_uring_prep_rw(.RECVMSG, sqe, fd, @ptrToInt(msg), 1, 0);
+ sqe.rw_flags = flags;
+}
+
+pub fn io_uring_prep_sendmsg(
+ sqe: *io_uring_sqe,
+ fd: os.fd_t,
+ msg: *const os.msghdr_const,
+ flags: u32,
+) void {
+ linux.io_uring_prep_rw(.SENDMSG, sqe, fd, @ptrToInt(msg), 1, 0);
+ sqe.rw_flags = flags;
+}
+
pub fn io_uring_prep_openat(
sqe: *io_uring_sqe,
fd: os.fd_t,
@@ -1908,6 +1958,88 @@ test "accept/connect/send/recv" {
try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]);
}
+test "sendmsg/recvmsg" {
+ if (builtin.os.tag != .linux) return error.SkipZigTest;
+
+ var ring = IO_Uring.init(2, 0) catch |err| switch (err) {
+ error.SystemOutdated => return error.SkipZigTest,
+ error.PermissionDenied => return error.SkipZigTest,
+ else => return err,
+ };
+ defer ring.deinit();
+
+ const address_server = try net.Address.parseIp4("127.0.0.1", 3131);
+
+ const server = try os.socket(address_server.any.family, os.SOCK.DGRAM, 0);
+ defer os.close(server);
+ try os.setsockopt(server, os.SOL.SOCKET, os.SO.REUSEPORT, &mem.toBytes(@as(c_int, 1)));
+ try os.setsockopt(server, os.SOL.SOCKET, os.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1)));
+ try os.bind(server, &address_server.any, address_server.getOsSockLen());
+
+ const client = try os.socket(address_server.any.family, os.SOCK.DGRAM, 0);
+ defer os.close(client);
+
+ const buffer_send = [_]u8{42} ** 128;
+ var iovecs_send = [_]os.iovec_const{
+ os.iovec_const{ .iov_base = &buffer_send, .iov_len = buffer_send.len },
+ };
+ const msg_send = os.msghdr_const{
+ .name = &address_server.any,
+ .namelen = address_server.getOsSockLen(),
+ .iov = &iovecs_send,
+ .iovlen = 1,
+ .control = null,
+ .controllen = 0,
+ .flags = 0,
+ };
+ const sqe_sendmsg = try ring.sendmsg(0x11111111, client, &msg_send, 0);
+ sqe_sendmsg.flags |= linux.IOSQE_IO_LINK;
+ try testing.expectEqual(linux.IORING_OP.SENDMSG, sqe_sendmsg.opcode);
+ try testing.expectEqual(client, sqe_sendmsg.fd);
+
+ var buffer_recv = [_]u8{0} ** 128;
+ var iovecs_recv = [_]os.iovec{
+ os.iovec{ .iov_base = &buffer_recv, .iov_len = buffer_recv.len },
+ };
+ var addr = [_]u8{0} ** 4;
+ var address_recv = net.Address.initIp4(addr, 0);
+ var msg_recv: os.msghdr = os.msghdr{
+ .name = &address_recv.any,
+ .namelen = address_recv.getOsSockLen(),
+ .iov = &iovecs_recv,
+ .iovlen = 1,
+ .control = null,
+ .controllen = 0,
+ .flags = 0,
+ };
+ const sqe_recvmsg = try ring.recvmsg(0x22222222, server, &msg_recv, 0);
+ try testing.expectEqual(linux.IORING_OP.RECVMSG, sqe_recvmsg.opcode);
+ try testing.expectEqual(server, sqe_recvmsg.fd);
+
+ try testing.expectEqual(@as(u32, 2), ring.sq_ready());
+ try testing.expectEqual(@as(u32, 2), try ring.submit_and_wait(2));
+ try testing.expectEqual(@as(u32, 0), ring.sq_ready());
+ try testing.expectEqual(@as(u32, 2), ring.cq_ready());
+
+ const cqe_sendmsg = try ring.copy_cqe();
+ if (cqe_sendmsg.res == -@as(i32, @enumToInt(linux.E.INVAL))) return error.SkipZigTest;
+ try testing.expectEqual(linux.io_uring_cqe{
+ .user_data = 0x11111111,
+ .res = buffer_send.len,
+ .flags = 0,
+ }, cqe_sendmsg);
+
+ const cqe_recvmsg = try ring.copy_cqe();
+ if (cqe_recvmsg.res == -@as(i32, @enumToInt(linux.E.INVAL))) return error.SkipZigTest;
+ try testing.expectEqual(linux.io_uring_cqe{
+ .user_data = 0x22222222,
+ .res = buffer_recv.len,
+ .flags = 0,
+ }, cqe_recvmsg);
+
+ try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]);
+}
+
test "timeout (after a relative time)" {
if (builtin.os.tag != .linux) return error.SkipZigTest;
lib/std/os/linux/mips.zig
@@ -2,11 +2,12 @@ const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const pid_t = linux.pid_t;
+const sockaddr = linux.sockaddr;
const timespec = linux.timespec;
pub fn syscall0(number: SYS) usize {
@@ -716,6 +717,26 @@ pub const Flock = extern struct {
__unused: [4]u8,
};
+pub const msghdr = extern struct {
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: i32,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: i32,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
+};
+
pub const blksize_t = i32;
pub const nlink_t = u32;
pub const time_t = i32;
lib/std/os/linux/powerpc.zig
@@ -2,8 +2,8 @@ const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const pid_t = linux.pid_t;
@@ -651,23 +651,23 @@ pub const Flock = extern struct {
};
pub const msghdr = extern struct {
- msg_name: ?*sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec,
- msg_iovlen: usize,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
- msg_flags: i32,
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: usize,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
};
pub const msghdr_const = extern struct {
- msg_name: ?*const sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec_const,
- msg_iovlen: usize,
- msg_control: ?*anyopaque,
- msg_controllen: socklen_t,
- msg_flags: i32,
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: usize,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: i32,
};
pub const blksize_t = i32;
lib/std/os/linux/powerpc64.zig
@@ -2,8 +2,8 @@ const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const pid_t = linux.pid_t;
@@ -626,23 +626,23 @@ pub const Flock = extern struct {
};
pub const msghdr = extern struct {
- msg_name: ?*sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec,
- msg_iovlen: usize,
- msg_control: ?*anyopaque,
- msg_controllen: usize,
- msg_flags: i32,
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: usize,
+ control: ?*anyopaque,
+ controllen: usize,
+ flags: i32,
};
pub const msghdr_const = extern struct {
- msg_name: ?*const sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec_const,
- msg_iovlen: usize,
- msg_control: ?*anyopaque,
- msg_controllen: usize,
- msg_flags: i32,
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: usize,
+ control: ?*anyopaque,
+ controllen: usize,
+ flags: i32,
};
pub const blksize_t = i64;
lib/std/os/linux/riscv64.zig
@@ -1,7 +1,12 @@
const std = @import("../../std.zig");
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
+const linux = std.os.linux;
const uid_t = std.os.linux.uid_t;
const gid_t = std.os.linux.gid_t;
const pid_t = std.os.linux.pid_t;
+const sockaddr = linux.sockaddr;
+const socklen_t = linux.socklen_t;
const timespec = std.os.linux.timespec;
pub fn syscall0(number: SYS) usize {
@@ -488,6 +493,30 @@ pub const Flock = extern struct {
__unused: [4]u8,
};
+pub const msghdr = extern struct {
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: i32,
+ __pad1: i32 = 0,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ __pad2: socklen_t = 0,
+ flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: i32,
+ __pad1: i32 = 0,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ __pad2: socklen_t = 0,
+ flags: i32,
+};
+
// The `stat` definition used by the Linux kernel.
pub const Stat = extern struct {
dev: dev_t,
lib/std/os/linux/sparc64.zig
@@ -9,8 +9,8 @@ const sigset_t = linux.sigset_t;
const linux = std.os.linux;
const sockaddr = linux.sockaddr;
const socklen_t = linux.socklen_t;
-const iovec = linux.iovec;
-const iovec_const = linux.iovec_const;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
const timespec = linux.timespec;
pub fn syscall_pipe(fd: *[2]i32) usize {
@@ -656,23 +656,23 @@ pub const Flock = extern struct {
};
pub const msghdr = extern struct {
- msg_name: ?*sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec,
- msg_iovlen: u64,
- msg_control: ?*anyopaque,
- msg_controllen: u64,
- msg_flags: i32,
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: u64,
+ control: ?*anyopaque,
+ controllen: u64,
+ flags: i32,
};
pub const msghdr_const = extern struct {
- msg_name: ?*const sockaddr,
- msg_namelen: socklen_t,
- msg_iov: [*]iovec_const,
- msg_iovlen: u64,
- msg_control: ?*anyopaque,
- msg_controllen: u64,
- msg_flags: i32,
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec_const,
+ iovlen: u64,
+ control: ?*anyopaque,
+ controllen: u64,
+ flags: i32,
};
pub const off_t = i64;