Skip to content

Commit ec2c22e

Browse files
authored
Add setsockopt (#320)
* Add setsockopt * Add tests for SetSockOpt opcode
1 parent 2c9010a commit ec2c22e

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

io-uring-test/src/tests/net.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,11 +1494,64 @@ pub fn test_socket<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
14941494
assert_eq!(cqes.len(), 1);
14951495
assert_eq!(cqes[0].user_data(), 42);
14961496
assert!(cqes[0].result() >= 0);
1497-
assert!(cqes[0].result() != plain_fd);
1497+
let io_uring_socket = unsafe { Socket::from_raw_fd(cqes[0].result()) };
1498+
assert!(io_uring_socket.as_raw_fd() != plain_fd);
14981499
assert_eq!(cqes[0].flags(), 0);
14991500

1501+
// Try a setsockopt.
1502+
{
1503+
let mut optval: libc::c_int = 0;
1504+
let mut optval_size: libc::socklen_t = std::mem::size_of_val(&optval) as libc::socklen_t;
1505+
// Get value before.
1506+
let ret = unsafe {
1507+
libc::getsockopt(
1508+
io_uring_socket.as_raw_fd(),
1509+
libc::SOL_SOCKET,
1510+
libc::SO_REUSEADDR,
1511+
&mut optval as *mut _ as *mut libc::c_void,
1512+
&mut optval_size as *mut _ as *mut libc::socklen_t,
1513+
)
1514+
};
1515+
assert_eq!(ret, 0);
1516+
assert_eq!(optval, 0);
1517+
1518+
// Set value.
1519+
optval = 1;
1520+
let op = io_uring::opcode::SetSockOpt::new(
1521+
io_uring::types::Fd(io_uring_socket.as_raw_fd()),
1522+
libc::SOL_SOCKET as u32,
1523+
libc::SO_REUSEADDR as u32,
1524+
&optval as *const _ as *const libc::c_void,
1525+
std::mem::size_of_val(&optval) as libc::socklen_t,
1526+
)
1527+
.build()
1528+
.user_data(1234);
1529+
unsafe {
1530+
ring.submission().push(&op.into()).expect("queue is full");
1531+
}
1532+
ring.submit_and_wait(1)?;
1533+
let cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
1534+
assert_eq!(cqes.len(), 1);
1535+
assert_eq!(cqes[0].user_data(), 1234);
1536+
assert_eq!(cqes[0].result(), 0);
1537+
assert_eq!(cqes[0].flags(), 0);
1538+
1539+
// Check value actually set.
1540+
optval = 0;
1541+
let ret = unsafe {
1542+
libc::getsockopt(
1543+
io_uring_socket.as_raw_fd(),
1544+
libc::SOL_SOCKET,
1545+
libc::SO_REUSEADDR,
1546+
&mut optval as *mut _ as *mut libc::c_void,
1547+
&mut optval_size as *mut _ as *mut libc::socklen_t,
1548+
)
1549+
};
1550+
assert_eq!(ret, 0);
1551+
assert_eq!(optval, 1);
1552+
}
1553+
15001554
// Close both sockets, to avoid leaking FDs.
1501-
let io_uring_socket = unsafe { Socket::from_raw_fd(cqes[0].result()) };
15021555
drop(plain_socket);
15031556
drop(io_uring_socket);
15041557

src/opcode.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,36 @@ opcode! {
641641
}
642642
}
643643

644+
opcode! {
645+
/// Set a socket option.
646+
pub struct SetSockOpt {
647+
fd: { impl sealed::UseFixed },
648+
level: { u32 },
649+
optname: { u32 },
650+
optval: { *const libc::c_void },
651+
optlen: { u32 },
652+
;;
653+
flags: u32 = 0
654+
}
655+
656+
pub const CODE = sys::IORING_OP_URING_CMD;
657+
658+
pub fn build(self) -> Entry {
659+
let SetSockOpt { fd, level, optname, optval, optlen, flags } = self;
660+
let mut sqe = sqe_zeroed();
661+
sqe.opcode = Self::CODE;
662+
assign_fd!(sqe.fd = fd);
663+
sqe.__bindgen_anon_1.__bindgen_anon_1.cmd_op = sys::SOCKET_URING_OP_SETSOCKOPT;
664+
665+
sqe.__bindgen_anon_2.__bindgen_anon_1.level = level;
666+
sqe.__bindgen_anon_2.__bindgen_anon_1.optname = optname;
667+
sqe.__bindgen_anon_3.uring_cmd_flags = flags;
668+
sqe.__bindgen_anon_5.optlen = optlen;
669+
unsafe { *sqe.__bindgen_anon_6.optval.as_mut() = optval as u64 };
670+
Entry(sqe)
671+
}
672+
}
673+
644674
opcode! {
645675
/// Attempt to cancel an already issued request.
646676
pub struct AsyncCancel {

0 commit comments

Comments
 (0)