@@ -54,6 +54,9 @@ pub enum Error {
54
54
/// The provided message did not write a payload
55
55
EmptyPayload ,
56
56
57
+ /// The provided buffer was too small for the desired payload
58
+ UndersizedBuffer ,
59
+
57
60
/// The transmission queue is at capacity
58
61
AtCapacity ,
59
62
}
@@ -96,10 +99,47 @@ pub trait Message {
96
99
fn ipv6_flow_label ( & mut self ) -> u32 ;
97
100
98
101
/// 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 ;
100
103
101
104
/// 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
+ }
103
143
}
104
144
105
145
impl < 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) {
121
161
0
122
162
}
123
163
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 ( )
126
166
}
127
167
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 ( ) )
137
174
}
138
175
}
139
176
@@ -158,9 +195,24 @@ mod tests {
158
195
assert_eq ! ( message. ecn( ) , Default :: default ( ) ) ;
159
196
assert_eq ! ( message. delay( ) , Default :: default ( ) ) ;
160
197
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 ] ) ;
162
214
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 ) ;
165
217
}
166
218
}
0 commit comments