| ... | ... | @@ -1399,15 +1399,18 @@ pub fn listen( |
| 1399 | 1399 | return sqe; |
| 1400 | 1400 | } |
| 1401 | 1401 | |
| 1402 | | fn cmd_sock( |
| 1402 | /// Prepares an cmd request for a socket. |
| 1403 | /// See: https://man7.org/linux/man-pages/man3/io_uring_prep_cmd.3.html |
| 1404 | /// Available since 6.7. |
| 1405 | pub fn cmd_sock( |
| 1403 | 1406 | self: *IoUring, |
| 1404 | 1407 | user_data: u64, |
| 1405 | 1408 | cmd_op: linux.IO_URING_SOCKET_OP, |
| 1406 | 1409 | fd: linux.fd_t, |
| 1407 | | level: u32, |
| 1408 | | optname: u32, |
| 1409 | | optval: u64, |
| 1410 | | optlen: u32, |
| 1410 | level: u32, // linux.SOL |
| 1411 | optname: u32, // linux.SO |
| 1412 | optval: u64, // pointer to the option value |
| 1413 | optlen: u32, // size of the option value |
| 1411 | 1414 | ) !*linux.io_uring_sqe { |
| 1412 | 1415 | const sqe = try self.get_sqe(); |
| 1413 | 1416 | sqe.prep_cmd_sock(cmd_op, fd, level, optname, optval, optlen); |
| ... | ... | @@ -1415,6 +1418,50 @@ fn cmd_sock( |
| 1415 | 1418 | return sqe; |
| 1416 | 1419 | } |
| 1417 | 1420 | |
| 1421 | /// Prepares set socket option for the optname argument, at the protocol |
| 1422 | /// level specified by the level argument. |
| 1423 | /// Available since 6.7.n |
| 1424 | pub fn setsockopt( |
| 1425 | self: *IoUring, |
| 1426 | user_data: u64, |
| 1427 | fd: linux.fd_t, |
| 1428 | level: u32, // linux.SOL |
| 1429 | optname: u32, // linux.SO |
| 1430 | opt: []const u8, |
| 1431 | ) !*linux.io_uring_sqe { |
| 1432 | return try self.cmd_sock( |
| 1433 | user_data, |
| 1434 | .SETSOCKOPT, |
| 1435 | fd, |
| 1436 | level, |
| 1437 | optname, |
| 1438 | @intFromPtr(opt.ptr), |
| 1439 | @intCast(opt.len), |
| 1440 | ); |
| 1441 | } |
| 1442 | |
| 1443 | /// Prepares get socket option to retrieve the value for the option specified by |
| 1444 | /// the option_name argument for the socket specified by the fd argument. |
| 1445 | /// Available since 6.7. |
| 1446 | pub fn getsockopt( |
| 1447 | self: *IoUring, |
| 1448 | user_data: u64, |
| 1449 | fd: linux.fd_t, |
| 1450 | level: u32, // linux.SOL |
| 1451 | optname: u32, // linux.SO |
| 1452 | opt: []u8, |
| 1453 | ) !*linux.io_uring_sqe { |
| 1454 | return try self.cmd_sock( |
| 1455 | user_data, |
| 1456 | .GETSOCKOPT, |
| 1457 | fd, |
| 1458 | level, |
| 1459 | optname, |
| 1460 | @intFromPtr(opt.ptr), |
| 1461 | @intCast(opt.len), |
| 1462 | ); |
| 1463 | } |
| 1464 | |
| 1418 | 1465 | pub const SubmissionQueue = struct { |
| 1419 | 1466 | head: *u32, |
| 1420 | 1467 | tail: *u32, |
| ... | ... | @@ -4391,13 +4438,10 @@ test "bind/listen/connect" { |
| 4391 | 4438 | try testing.expect(listen_fd > 2); |
| 4392 | 4439 | |
| 4393 | 4440 | // Prepare: set socket option * 2, bind, listen |
| 4394 | | var sock_opt: u32 = 1; |
| 4395 | | var sqe = try ring.cmd_sock(2, .SETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, @intFromPtr(&sock_opt), @sizeOf(u32)); |
| 4396 | | sqe.flags |= linux.IOSQE_IO_LINK; |
| 4397 | | sqe = try ring.cmd_sock(3, .SETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, @intFromPtr(&sock_opt), @sizeOf(u32)); |
| 4398 | | sqe.flags |= linux.IOSQE_IO_LINK; |
| 4399 | | sqe = try ring.bind(4, listen_fd, &addr.any, addr.getOsSockLen(), 0); |
| 4400 | | sqe.flags |= linux.IOSQE_IO_LINK; |
| 4441 | var optval: u32 = 1; |
| 4442 | (try ring.setsockopt(2, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval))).link_next(); |
| 4443 | (try ring.setsockopt(3, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, mem.asBytes(&optval))).link_next(); |
| 4444 | (try ring.bind(4, listen_fd, &addr.any, addr.getOsSockLen(), 0)).link_next(); |
| 4401 | 4445 | _ = try ring.listen(5, listen_fd, 1, 0); |
| 4402 | 4446 | // Submit 4 operations |
| 4403 | 4447 | try testing.expectEqual(4, try ring.submit()); |
| ... | ... | @@ -4409,13 +4453,13 @@ test "bind/listen/connect" { |
| 4409 | 4453 | } |
| 4410 | 4454 | |
| 4411 | 4455 | // Check that socket option is set |
| 4412 | | sock_opt = 0xff; |
| 4413 | | _ = try ring.cmd_sock(5, .GETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, @intFromPtr(&sock_opt), @sizeOf(u32)); |
| 4456 | optval = 0; |
| 4457 | _ = try ring.getsockopt(5, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval)); |
| 4414 | 4458 | try testing.expectEqual(1, try ring.submit()); |
| 4415 | 4459 | cqe = try ring.copy_cqe(); |
| 4416 | 4460 | try testing.expectEqual(5, cqe.user_data); |
| 4417 | 4461 | try testing.expectEqual(posix.E.SUCCESS, cqe.err()); |
| 4418 | | try testing.expectEqual(1, sock_opt); |
| 4462 | try testing.expectEqual(1, optval); |
| 4419 | 4463 | |
| 4420 | 4464 | // Read system assigned port into addr |
| 4421 | 4465 | var addr_len: posix.socklen_t = addr.getOsSockLen(); |
| ... | ... | @@ -4460,8 +4504,7 @@ test "bind/listen/connect" { |
| 4460 | 4504 | |
| 4461 | 4505 | // Shutdown and close all sockets |
| 4462 | 4506 | for ([_]posix.socket_t{ connect_fd, accept_fd, listen_fd }) |fd| { |
| 4463 | | var sqe = try ring.shutdown(9, fd, posix.SHUT.RDWR); |
| 4464 | | sqe.flags |= linux.IOSQE_IO_LINK; |
| 4507 | (try ring.shutdown(9, fd, posix.SHUT.RDWR)).link_next(); |
| 4465 | 4508 | _ = try ring.close(10, fd); |
| 4466 | 4509 | try testing.expectEqual(2, try ring.submit()); |
| 4467 | 4510 | for (0..2) |i| { |
| ... | ... | @@ -4477,8 +4520,7 @@ fn testSendRecv(ring: *IoUring, send_fd: posix.socket_t, recv_fd: posix.socket_t |
| 4477 | 4520 | var buffer_recv: [buffer_send.len * 2]u8 = undefined; |
| 4478 | 4521 | |
| 4479 | 4522 | // 2 sends |
| 4480 | | var sqe = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL); |
| 4481 | | sqe.flags |= linux.IOSQE_IO_LINK; |
| 4523 | _ = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL); |
| 4482 | 4524 | _ = try ring.send(2, send_fd, buffer_send, linux.MSG.WAITALL); |
| 4483 | 4525 | try testing.expectEqual(2, try ring.submit()); |
| 4484 | 4526 | for (0..2) |i| { |