commit b76316ece5f8288918bac43bc7a819133957c8e9
parent 8ffa53f262a4d612ce9a6f700c1e6a154d3ea2a1
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 18 Nov 2021 11:43:41 +0100
iobus::io_uring: add send, recv
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
M | iobus/io_uring/ops.ha | | | 86 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/iobus/io_uring/ops.ha b/iobus/io_uring/ops.ha
@@ -7,8 +7,6 @@ use rt;
use strings;
use unix::poll;
-// TODO: Seek to de-duplicate more of the SQE prep code
-
fn getsqe(bus: *bus) (*io_uring::sqe | queuefull) = {
match (io_uring::get_sqe(&bus.uring)) {
case null =>
@@ -264,3 +262,87 @@ export fn endcreate(bus: *bus, res: result) (io::file | error) = {
free(handle.cstring);
return cqe_result(res)?: io::file;
};
+
+// Flags for the [[recv]] and [[send]] family of operations. Only PEEK, OOB,
+// NOSIGNAL, and WAITALL are defined by POSIX.
+export type msgflag = enum int {
+ OOB = rt::MSG_OOB,
+ PEEK = rt::MSG_PEEK,
+ DONTROUTE = rt::MSG_DONTROUTE,
+ TRYHARD = rt::MSG_TRYHARD,
+ CTRUNC = rt::MSG_CTRUNC,
+ PROBE = rt::MSG_PROBE,
+ TRUNC = rt::MSG_TRUNC,
+ DONTWAIT = rt::MSG_DONTWAIT,
+ EOR = rt::MSG_EOR,
+ WAITALL = rt::MSG_WAITALL,
+ FIN = rt::MSG_FIN,
+ SYN = rt::MSG_SYN,
+ CONFIRM = rt::MSG_CONFIRM,
+ RST = rt::MSG_RST,
+ ERRQUEUE = rt::MSG_ERRQUEUE,
+ NOSIGNAL = rt::MSG_NOSIGNAL,
+ MORE = rt::MSG_MORE,
+ WAITFORONE = rt::MSG_WAITFORONE,
+ SENDPAGE_NOPOLICY = rt::MSG_SENDPAGE_NOPOLICY,
+ SENDPAGE_NOTLAST = rt::MSG_SENDPAGE_NOTLAST,
+ BATCH = rt::MSG_BATCH,
+ EOF = rt::MSG_EOF,
+ NO_SHARED_FRAGS = rt::MSG_NO_SHARED_FRAGS,
+ SENDPAGE_DECRYPTED = rt::MSG_SENDPAGE_DECRYPTED,
+ ZEROCOPY = rt::MSG_ZEROCOPY,
+ FASTOPEN = rt::MSG_FASTOPEN,
+ CMSG_CLOEXEC = rt::MSG_CMSG_CLOEXEC,
+};
+
+// Prepares an operation to receive data from a socket.
+export fn recv(
+ bus: *bus,
+ file: file,
+ buf: []u8,
+ flags: msgflag...
+) (handle | queuefull) = {
+ let rflags = 0;
+ for (let i = 0z; i < len(flags); i += 1) {
+ rflags |= flags[i];
+ };
+
+ let sqe = getsqe(bus)?;
+ let iflags = io_uring::flags::NONE;
+ let fd = match (file) {
+ case file: io::file =>
+ yield file: i32;
+ case file: registered_file =>
+ iflags |= io_uring::flags::FIXED_FILE;
+ yield file: i32;
+ };
+
+ io_uring::recv(sqe, fd, buf: *[*]u8, len(buf), rflags, iflags);
+ return handle { sqe = sqe, ... };
+};
+
+// Prepares an operation to send data to a socket.
+export fn send(
+ bus: *bus,
+ file: file,
+ buf: []u8,
+ flags: msgflag...
+) (handle | queuefull) = {
+ let sflags = 0;
+ for (let i = 0z; i < len(flags); i += 1) {
+ sflags |= flags[i];
+ };
+
+ let sqe = getsqe(bus)?;
+ let iflags = io_uring::flags::NONE;
+ let fd = match (file) {
+ case file: io::file =>
+ yield file: i32;
+ case file: registered_file =>
+ iflags |= io_uring::flags::FIXED_FILE;
+ yield file: i32;
+ };
+
+ io_uring::send(sqe, fd, buf: *[*]u8, len(buf), sflags, iflags);
+ return handle { sqe = sqe, ... };
+};