@@ -54,6 +54,9 @@ pub enum Error {
5454 /// The provided message did not write a payload
5555 EmptyPayload ,
5656
57+ /// The provided buffer was too small for the desired payload
58+ UndersizedBuffer ,
59+
5760 /// The transmission queue is at capacity
5861 AtCapacity ,
5962}
@@ -96,10 +99,47 @@ pub trait Message {
9699 fn ipv6_flow_label ( & mut self ) -> u32 ;
97100
98101 /// Returns true if the packet can be used in a GSO packet
99- fn can_gso ( & self ) -> bool ;
102+ fn can_gso ( & self , segment_len : usize ) -> bool ;
100103
101104 /// Writes the payload of the message to an output buffer
102- fn write_payload ( & mut self , buffer : & mut [ u8 ] , gso_offset : usize ) -> usize ;
105+ fn write_payload ( & mut self , buffer : PayloadBuffer , gso_offset : usize ) -> Result < usize , Error > ;
106+ }
107+
108+ #[ derive( Debug ) ]
109+ pub struct PayloadBuffer < ' a > ( & ' a mut [ u8 ] ) ;
110+
111+ impl < ' a > PayloadBuffer < ' a > {
112+ #[ inline]
113+ pub fn new ( bytes : & ' a mut [ u8 ] ) -> Self {
114+ Self ( bytes)
115+ }
116+
117+ /// # Safety
118+ ///
119+ /// This function should only be used in the case that the writer has its own safety checks in place
120+ #[ inline]
121+ pub unsafe fn into_mut_slice ( self ) -> & ' a mut [ u8 ] {
122+ self . 0
123+ }
124+
125+ #[ track_caller]
126+ #[ inline]
127+ pub fn write ( & mut self , bytes : & [ u8 ] ) -> Result < usize , Error > {
128+ if bytes. is_empty ( ) {
129+ return Err ( Error :: EmptyPayload ) ;
130+ }
131+
132+ if let Some ( buffer) = self . 0 . get_mut ( 0 ..bytes. len ( ) ) {
133+ buffer. copy_from_slice ( bytes) ;
134+ Ok ( bytes. len ( ) )
135+ } else {
136+ debug_assert ! (
137+ false ,
138+ "tried to write more bytes than was available in the buffer"
139+ ) ;
140+ Err ( Error :: UndersizedBuffer )
141+ }
142+ }
103143}
104144
105145impl < Handle : path:: Handle , Payload : AsRef < [ u8 ] > > Message for ( Handle , Payload ) {
@@ -121,19 +161,16 @@ impl<Handle: path::Handle, Payload: AsRef<[u8]>> Message for (Handle, Payload) {
121161 0
122162 }
123163
124- fn can_gso ( & self ) -> bool {
125- true
164+ fn can_gso ( & self , segment_len : usize ) -> bool {
165+ segment_len >= self . 1 . as_ref ( ) . len ( )
126166 }
127167
128- fn write_payload ( & mut self , buffer : & mut [ u8 ] , _gso_offset : usize ) -> usize {
129- let payload = self . 1 . as_ref ( ) ;
130- let len = payload. len ( ) ;
131- if let Some ( buffer) = buffer. get_mut ( ..len) {
132- buffer. copy_from_slice ( payload) ;
133- len
134- } else {
135- 0
136- }
168+ fn write_payload (
169+ & mut self ,
170+ mut buffer : PayloadBuffer ,
171+ _gso_offset : usize ,
172+ ) -> Result < usize , Error > {
173+ buffer. write ( self . 1 . as_ref ( ) )
137174 }
138175}
139176
@@ -158,9 +195,24 @@ mod tests {
158195 assert_eq ! ( message. ecn( ) , Default :: default ( ) ) ;
159196 assert_eq ! ( message. delay( ) , Default :: default ( ) ) ;
160197 assert_eq ! ( message. ipv6_flow_label( ) , 0 ) ;
161- assert_eq ! ( message. write_payload( & mut buffer[ ..] , 0 ) , 3 ) ;
198+ assert_eq ! (
199+ message. write_payload( PayloadBuffer :: new( & mut buffer[ ..] ) , 0 ) ,
200+ Ok ( 3 )
201+ ) ;
202+ }
203+
204+ #[ test]
205+ #[ should_panic]
206+ fn message_tuple_undersized_test ( ) {
207+ let remote_address = SocketAddressV4 :: new ( [ 127 , 0 , 0 , 1 ] , 80 ) . into ( ) ;
208+ let local_address = SocketAddressV4 :: new ( [ 192 , 168 , 0 , 1 ] , 3000 ) . into ( ) ;
209+ let tuple = path:: Tuple {
210+ remote_address,
211+ local_address,
212+ } ;
213+ let mut message = ( tuple, [ 1u8 , 2 , 3 ] ) ;
162214
163- // assert an empty buffer doesn't panic
164- assert_eq ! ( message. write_payload( & mut [ ] [ ..] , 0 ) , 0 ) ;
215+ // assert an undersized buffer panics in debug
216+ let _ = message. write_payload ( PayloadBuffer :: new ( & mut [ ] [ ..] ) , 0 ) ;
165217 }
166218}
0 commit comments