| ... | @@ -528,17 +528,39 @@ pub const IO_Uring = struct { | ... | @@ -528,17 +528,39 @@ pub const IO_Uring = struct { |
| 528 | return sqe; | 528 | return sqe; |
| 529 | } | 529 | } |
| 530 | | 530 | |
| | 531 | /// Used to select how the recv call should be handled. |
| | 532 | pub const RecvBuffer = union(enum) { |
| | 533 | /// io_uring will recv directly into this buffer |
| | 534 | buffer: []u8, |
| | 535 | |
| | 536 | /// io_uring will select a buffer that has previously been provided with `provide_buffers`. |
| | 537 | /// The buffer group referenced by `group_id` must contain at least one buffer for the recv call to work. |
| | 538 | /// `len` controls the number of bytes to read into the selected buffer. |
| | 539 | buffer_selection: struct { |
| | 540 | group_id: u16, |
| | 541 | len: usize, |
| | 542 | }, |
| | 543 | }; |
| | 544 | |
| 531 | /// Queues (but does not submit) an SQE to perform a `recv(2)`. | 545 | /// Queues (but does not submit) an SQE to perform a `recv(2)`. |
| 532 | /// Returns a pointer to the SQE. | 546 | /// Returns a pointer to the SQE. |
| 533 | pub fn recv( | 547 | pub fn recv( |
| 534 | self: *IO_Uring, | 548 | self: *IO_Uring, |
| 535 | user_data: u64, | 549 | user_data: u64, |
| 536 | fd: os.fd_t, | 550 | fd: os.fd_t, |
| 537 | buffer: []u8, | 551 | buffer: RecvBuffer, |
| 538 | flags: u32, | 552 | flags: u32, |
| 539 | ) !*io_uring_sqe { | 553 | ) !*io_uring_sqe { |
| 540 | const sqe = try self.get_sqe(); | 554 | const sqe = try self.get_sqe(); |
| 541 | io_uring_prep_recv(sqe, fd, buffer, flags); | 555 | switch (buffer) { |
| | 556 | .buffer => |slice| io_uring_prep_recv(sqe, fd, slice, flags), |
| | 557 | .buffer_selection => |selection| { |
| | 558 | io_uring_prep_rw(.RECV, sqe, fd, 0, selection.len, 0); |
| | 559 | sqe.rw_flags = flags; |
| | 560 | sqe.flags |= linux.IOSQE_BUFFER_SELECT; |
| | 561 | sqe.buf_index = selection.group_id; |
| | 562 | }, |
| | 563 | } |
| 542 | sqe.user_data = user_data; | 564 | sqe.user_data = user_data; |
| 543 | return sqe; | 565 | return sqe; |
| 544 | } | 566 | } |
| ... | @@ -2014,7 +2036,7 @@ test "accept/connect/send/recv" { | ... | @@ -2014,7 +2036,7 @@ test "accept/connect/send/recv" { |
| 2014 | | 2036 | |
| 2015 | const send = try ring.send(0xeeeeeeee, client, buffer_send[0..], 0); | 2037 | const send = try ring.send(0xeeeeeeee, client, buffer_send[0..], 0); |
| 2016 | send.flags |= linux.IOSQE_IO_LINK; | 2038 | send.flags |= linux.IOSQE_IO_LINK; |
| 2017 | _ = try ring.recv(0xffffffff, cqe_accept.res, buffer_recv[0..], 0); | 2039 | _ = try ring.recv(0xffffffff, cqe_accept.res, .{ .buffer = buffer_recv[0..] }, 0); |
| 2018 | try testing.expectEqual(@as(u32, 2), try ring.submit()); | 2040 | try testing.expectEqual(@as(u32, 2), try ring.submit()); |
| 2019 | | 2041 | |
| 2020 | const cqe_send = try ring.copy_cqe(); | 2042 | const cqe_send = try ring.copy_cqe(); |
| ... | @@ -2282,7 +2304,7 @@ test "accept/connect/recv/link_timeout" { | ... | @@ -2282,7 +2304,7 @@ test "accept/connect/recv/link_timeout" { |
| 2282 | .flags = 0, | 2304 | .flags = 0, |
| 2283 | }, cqe_connect); | 2305 | }, cqe_connect); |
| 2284 | | 2306 | |
| 2285 | const sqe_recv = try ring.recv(0xffffffff, cqe_accept.res, buffer_recv[0..], 0); | 2307 | const sqe_recv = try ring.recv(0xffffffff, cqe_accept.res, .{ .buffer = buffer_recv[0..] }, 0); |
| 2286 | sqe_recv.flags |= linux.IOSQE_IO_LINK; | 2308 | sqe_recv.flags |= linux.IOSQE_IO_LINK; |
| 2287 | | 2309 | |
| 2288 | const ts = os.linux.kernel_timespec{ .tv_sec = 0, .tv_nsec = 1000000 }; | 2310 | const ts = os.linux.kernel_timespec{ .tv_sec = 0, .tv_nsec = 1000000 }; |
| ... | @@ -2469,7 +2491,7 @@ test "accept/connect/recv/cancel" { | ... | @@ -2469,7 +2491,7 @@ test "accept/connect/recv/cancel" { |
| 2469 | .flags = 0, | 2491 | .flags = 0, |
| 2470 | }, cqe_connect); | 2492 | }, cqe_connect); |
| 2471 | | 2493 | |
| 2472 | _ = try ring.recv(0xffffffff, cqe_accept.res, buffer_recv[0..], 0); | 2494 | _ = try ring.recv(0xffffffff, cqe_accept.res, .{ .buffer = buffer_recv[0..] }, 0); |
| 2473 | try testing.expectEqual(@as(u32, 1), try ring.submit()); | 2495 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| 2474 | | 2496 | |
| 2475 | const sqe_cancel = try ring.cancel(0x99999999, 0xffffffff, 0); | 2497 | const sqe_cancel = try ring.cancel(0x99999999, 0xffffffff, 0); |