Skip to content

Commit e984db0

Browse files
committed
fix(net): CMsgBuilder get buffer reference only
1 parent baac3f1 commit e984db0

File tree

2 files changed

+62
-73
lines changed

2 files changed

+62
-73
lines changed

compio-net/src/cmsg/mod.rs

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::marker::PhantomData;
22

3-
use compio_buf::{IoBuf, IoBufMut};
4-
53
cfg_if::cfg_if! {
64
if #[cfg(windows)] {
75
#[path = "windows.rs"]
@@ -31,9 +29,9 @@ impl<'a> CMsgIter<'a> {
3129
/// # Safety
3230
///
3331
/// The buffer should contain valid control messages.
34-
pub unsafe fn new<B: IoBuf>(buffer: &'a B) -> Self {
32+
pub unsafe fn new(buffer: &'a [u8]) -> Self {
3533
Self {
36-
inner: sys::CMsgIter::new(buffer.as_buf_ptr(), buffer.buf_len()),
34+
inner: sys::CMsgIter::new(buffer.as_ptr(), buffer.len()),
3735
_p: PhantomData,
3836
}
3937
}
@@ -52,59 +50,53 @@ impl<'a> Iterator for CMsgIter<'a> {
5250
}
5351

5452
/// Helper to construct control message.
55-
pub struct CMsgBuilder<B> {
53+
pub struct CMsgBuilder<'a> {
5654
inner: sys::CMsgIter,
57-
buffer: B,
5855
len: usize,
56+
_p: PhantomData<&'a mut ()>,
5957
}
6058

61-
impl<B> CMsgBuilder<B> {
62-
/// Finishes building, returns the buffer and the length of the control
63-
/// message.
64-
pub fn build(self) -> (B, usize) {
65-
(self.buffer, self.len)
59+
impl<'a> CMsgBuilder<'a> {
60+
/// Create [`CMsgBuilder`] with the given buffer. The buffer will be zeroed
61+
/// on creation.
62+
///
63+
/// # Panics
64+
///
65+
/// This function will panic if the buffer is too short or not properly
66+
/// aligned.
67+
pub fn new(buffer: &'a mut [u8]) -> Self {
68+
buffer.fill(0);
69+
Self {
70+
inner: sys::CMsgIter::new(buffer.as_ptr(), buffer.len()),
71+
len: 0,
72+
_p: PhantomData,
73+
}
74+
}
75+
76+
/// Finishes building, returns length of the control message.
77+
pub fn finish(self) -> usize {
78+
self.len
6679
}
6780

6881
/// Try to append a control message entry into the buffer. If the buffer
6982
/// does not have enough space or is not properly aligned with the value
7083
/// type, returns `None`.
71-
///
72-
/// # Safety
73-
///
74-
/// TODO: This function may be safe? Given that the buffer is zeroed,
75-
/// properly aligned and has enough space, safety conditions of all unsafe
76-
/// functions involved are satisfied, except for `CMSG_*`/`wsa_cmsg_*`, as
77-
/// their safety are not documented.
78-
pub unsafe fn try_push<T>(&mut self, level: i32, ty: i32, value: T) -> Option<()> {
84+
pub fn try_push<T>(&mut self, level: i32, ty: i32, value: T) -> Option<()> {
7985
if !self.inner.is_aligned::<T>() || !self.inner.is_space_enough::<T>() {
8086
return None;
8187
}
8288

83-
let mut cmsg = self.inner.current_mut()?;
84-
cmsg.set_level(level);
85-
cmsg.set_ty(ty);
86-
cmsg.set_data(value);
87-
88-
self.inner.next();
89-
self.len += sys::space_of::<T>();
90-
Some(())
91-
}
92-
}
89+
// SAFETY: the buffer is zeroed and the pointer is valid and aligned
90+
unsafe {
91+
let mut cmsg = self.inner.current_mut()?;
92+
cmsg.set_level(level);
93+
cmsg.set_ty(ty);
94+
cmsg.set_data(value);
9395

94-
impl<B: IoBufMut> CMsgBuilder<B> {
95-
/// Create [`CMsgBuilder`] with the given buffer. The buffer will be zeroed
96-
/// on creation.
97-
///
98-
/// # Panics
99-
///
100-
/// This function will panic if the buffer is too short or not properly
101-
/// aligned.
102-
pub fn new(mut buffer: B) -> Self {
103-
buffer.as_mut_slice().fill(std::mem::MaybeUninit::zeroed());
104-
Self {
105-
inner: sys::CMsgIter::new(buffer.as_buf_mut_ptr(), buffer.buf_len()),
106-
buffer,
107-
len: 0,
96+
self.inner.next();
97+
self.len += sys::space_of::<T>();
10898
}
99+
100+
Some(())
109101
}
110102
}

compio-net/tests/cmsg.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,45 @@ use compio_net::{CMsgBuilder, CMsgIter};
33

44
#[test]
55
fn test_cmsg() {
6-
let buf = vec![0u8; 64];
7-
let mut builder = CMsgBuilder::new(buf);
6+
let mut buf = [0u8; 64];
7+
let mut builder = CMsgBuilder::new(&mut buf);
88

9-
unsafe {
10-
builder.try_push(0, 0, ()).unwrap(); // 16 / 12
11-
builder.try_push(1, 1, u32::MAX).unwrap(); // 16 + 4 + 4 / 12 + 4
12-
builder.try_push(2, 2, i64::MIN).unwrap(); // 16 + 8 / 12 + 8
13-
}
14-
let (buf, len) = builder.build();
9+
builder.try_push(0, 0, ()).unwrap(); // 16 / 12
10+
builder.try_push(1, 1, u32::MAX).unwrap(); // 16 + 4 + 4 / 12 + 4
11+
builder.try_push(2, 2, i64::MIN).unwrap(); // 16 + 8 / 12 + 8
12+
let len = builder.finish();
1513
assert!(len == 64 || len == 48);
1614

17-
let buf = buf.slice(..len);
18-
let mut iter = unsafe { CMsgIter::new(&buf) };
15+
unsafe {
16+
let buf = buf.slice(..len);
17+
let mut iter = CMsgIter::new(&buf);
1918

20-
let cmsg = iter.next().unwrap();
21-
assert_eq!(
22-
(cmsg.level(), cmsg.ty(), unsafe { cmsg.data::<()>() }),
23-
(0, 0, &())
24-
);
25-
let cmsg = iter.next().unwrap();
26-
assert_eq!(
27-
(cmsg.level(), cmsg.ty(), unsafe { cmsg.data::<u32>() }),
28-
(1, 1, &u32::MAX)
29-
);
30-
let cmsg = iter.next().unwrap();
31-
assert_eq!(
32-
(cmsg.level(), cmsg.ty(), unsafe { cmsg.data::<i64>() }),
33-
(2, 2, &i64::MIN)
34-
);
35-
assert!(iter.next().is_none());
19+
let cmsg = iter.next().unwrap();
20+
assert_eq!((cmsg.level(), cmsg.ty(), cmsg.data::<()>()), (0, 0, &()));
21+
let cmsg = iter.next().unwrap();
22+
assert_eq!(
23+
(cmsg.level(), cmsg.ty(), cmsg.data::<u32>()),
24+
(1, 1, &u32::MAX)
25+
);
26+
let cmsg = iter.next().unwrap();
27+
assert_eq!(
28+
(cmsg.level(), cmsg.ty(), cmsg.data::<i64>()),
29+
(2, 2, &i64::MIN)
30+
);
31+
assert!(iter.next().is_none());
32+
}
3633
}
3734

3835
#[test]
3936
#[should_panic]
4037
fn invalid_buffer_length() {
41-
let buf = vec![0u8; 1];
42-
CMsgBuilder::new(buf);
38+
let mut buf = [0u8; 1];
39+
CMsgBuilder::new(&mut buf);
4340
}
4441

4542
#[test]
4643
#[should_panic]
4744
fn invalid_buffer_alignment() {
48-
let buf = vec![0u8; 64];
49-
CMsgBuilder::new(buf.slice(1..));
45+
let mut buf = [0u8; 64];
46+
CMsgBuilder::new(&mut buf[1..]);
5047
}

0 commit comments

Comments
 (0)