| ... | ... | @@ -528,17 +528,39 @@ pub const IO_Uring = struct { |
| 528 | 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 | 545 | /// Queues (but does not submit) an SQE to perform a `recv(2)`. |
| 532 | 546 | /// Returns a pointer to the SQE. |
| 533 | 547 | pub fn recv( |
| 534 | 548 | self: *IO_Uring, |
| 535 | 549 | user_data: u64, |
| 536 | 550 | fd: os.fd_t, |
| 537 | | buffer: []u8, |
| 551 | buffer: RecvBuffer, |
| 538 | 552 | flags: u32, |
| 539 | 553 | ) !*io_uring_sqe { |
| 540 | 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 | 564 | sqe.user_data = user_data; |
| 543 | 565 | return sqe; |
| 544 | 566 | } |
| ... | ... | @@ -2014,7 +2036,7 @@ test "accept/connect/send/recv" { |
| 2014 | 2036 | |
| 2015 | 2037 | const send = try ring.send(0xeeeeeeee, client, buffer_send[0..], 0); |
| 2016 | 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 | 2040 | try testing.expectEqual(@as(u32, 2), try ring.submit()); |
| 2019 | 2041 | |
| 2020 | 2042 | const cqe_send = try ring.copy_cqe(); |
| ... | ... | @@ -2282,7 +2304,7 @@ test "accept/connect/recv/link_timeout" { |
| 2282 | 2304 | .flags = 0, |
| 2283 | 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 | 2308 | sqe_recv.flags |= linux.IOSQE_IO_LINK; |
| 2287 | 2309 | |
| 2288 | 2310 | const ts = os.linux.kernel_timespec{ .tv_sec = 0, .tv_nsec = 1000000 }; |
| ... | ... | @@ -2469,7 +2491,7 @@ test "accept/connect/recv/cancel" { |
| 2469 | 2491 | .flags = 0, |
| 2470 | 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 | 2495 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| 2474 | 2496 | |
| 2475 | 2497 | const sqe_cancel = try ring.cancel(0x99999999, 0xffffffff, 0); |