@@ -106,6 +106,8 @@ impl<'a> Into<SocketBuffer<'a>> for Managed<'a, [u8]> {
106
106
}
107
107
}
108
108
109
+ /// The state of a TCP socket, according to [RFC 793][rfc793].
110
+ /// [rfc793]: https://tools.ietf.org/html/rfc793
109
111
#[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
110
112
pub enum State {
111
113
Closed ,
@@ -160,7 +162,12 @@ impl Retransmit {
160
162
}
161
163
}
162
164
163
- /// A Transmission Control Protocol data stream.
165
+ /// A Transmission Control Protocol socket.
166
+ ///
167
+ /// A TCP socket may passively listen for connections or actively connect to another endpoint.
168
+ /// Note that, for listening sockets, there is no "backlog"; to be able to simultaneously
169
+ /// accept several connections, as many sockets must be allocated, or any new connection
170
+ /// attempts will be reset.
164
171
#[ derive( Debug ) ]
165
172
pub struct TcpSocket < ' a > {
166
173
/// State of the socket.
@@ -222,12 +229,6 @@ impl<'a> TcpSocket<'a> {
222
229
} )
223
230
}
224
231
225
- /// Return the connection state.
226
- #[ inline( always) ]
227
- pub fn state ( & self ) -> State {
228
- self . state
229
- }
230
-
231
232
/// Return the local endpoint.
232
233
#[ inline( always) ]
233
234
pub fn local_endpoint ( & self ) -> IpEndpoint {
@@ -240,44 +241,80 @@ impl<'a> TcpSocket<'a> {
240
241
self . remote_endpoint
241
242
}
242
243
243
- fn set_state ( & mut self , state : State ) {
244
- if self . state != state {
245
- if self . remote_endpoint . addr . is_unspecified ( ) {
246
- net_trace ! ( "tcp:{}: state={}→{}" ,
247
- self . local_endpoint, self . state, state) ;
248
- } else {
249
- net_trace ! ( "tcp:{}:{}: state={}→{}" ,
250
- self . local_endpoint, self . remote_endpoint, self . state, state) ;
251
- }
252
- }
253
- self . state = state
254
- }
255
-
256
244
/// Start listening on the given endpoint.
257
245
///
258
- /// # Panics
259
- /// This function will panic if the socket is not in the CLOSED state.
260
- pub fn listen ( & mut self , endpoint : IpEndpoint ) {
261
- assert ! ( self . state == State :: Closed ) ;
246
+ /// This function returns an error if the socket was open; see [is_open](#method.is_open).
247
+ pub fn listen ( & mut self , endpoint : IpEndpoint ) -> Result < ( ) , ( ) > {
248
+ if self . is_open ( ) { return Err ( ( ) ) }
262
249
263
250
self . listen_address = endpoint. addr ;
264
251
self . local_endpoint = endpoint;
265
252
self . remote_endpoint = IpEndpoint :: default ( ) ;
266
253
self . set_state ( State :: Listen ) ;
254
+ Ok ( ( ) )
255
+ }
256
+
257
+ /// Return whether the connection is open.
258
+ ///
259
+ /// This function returns true if the socket will process incoming or dispatch outgoing
260
+ /// packets. Note that this does not mean that it is possible to send or receive data through
261
+ /// the socket; for that, use [can_send](#method.can_send) or [can_recv](#method.can_recv).
262
+ pub fn is_open ( & self ) -> bool {
263
+ match self . state {
264
+ State :: Closed => false ,
265
+ State :: TimeWait => false ,
266
+ _ => true
267
+ }
268
+ }
269
+
270
+ /// Return whether the transmit half of the full-duplex connection is open.
271
+ ///
272
+ /// This function returns true if it's possible to send data and have it arrive
273
+ /// to the remote endpoint. However, it does not make any guarantees about the state
274
+ /// of the transmit buffer, and even if it returns true, [send](#method.send) may
275
+ /// not be able to enqueue any octets.
276
+ pub fn can_send ( & self ) -> bool {
277
+ match self . state {
278
+ State :: Established => true ,
279
+ // In CLOSE_WAIT, the remote endpoint has closed our receive half of the connection
280
+ // but we still can transmit indefinitely.
281
+ State :: CloseWait => true ,
282
+ _ => false
283
+ }
284
+ }
285
+
286
+ /// Return whether the receive half of the full-duplex connection is open.
287
+ ///
288
+ /// This function returns true if it's possible to receive data from the remote endpoint.
289
+ /// It will return true while there is data in the receive buffer, and if there isn't,
290
+ /// as long as the remote endpoint has not closed the connection.
291
+ pub fn can_recv ( & self ) -> bool {
292
+ match self . state {
293
+ State :: Established => true ,
294
+ // In FIN_WAIT_1/2, we have closed our transmit half of the connection but
295
+ // we still can receive indefinitely.
296
+ State :: FinWait1 | State :: FinWait2 => true ,
297
+ _ => false
298
+ }
267
299
}
268
300
269
301
/// Enqueue a sequence of octets to be sent, and return a pointer to it.
270
302
///
271
303
/// This function may return a slice smaller than the requested size in case
272
304
/// there is not enough contiguous free space in the transmit buffer, down to
273
305
/// an empty slice.
274
- pub fn send ( & mut self , size : usize ) -> & mut [ u8 ] {
306
+ ///
307
+ /// This function returns an error if the transmit half of the connection is not open;
308
+ /// see [can_send](#method.can_send).
309
+ pub fn send ( & mut self , size : usize ) -> Result < & mut [ u8 ] , ( ) > {
310
+ if !self . can_send ( ) { return Err ( ( ) ) }
311
+
275
312
let buffer = self . tx_buffer . enqueue ( size) ;
276
313
if buffer. len ( ) > 0 {
277
314
net_trace ! ( "tcp:{}:{}: tx buffer: enqueueing {} octets" ,
278
315
self . local_endpoint, self . remote_endpoint, buffer. len( ) ) ;
279
316
}
280
- buffer
317
+ Ok ( buffer)
281
318
}
282
319
283
320
/// Enqueue a sequence of octets to be sent, and fill it from a slice.
@@ -286,26 +323,30 @@ impl<'a> TcpSocket<'a> {
286
323
/// by the amount of free space in the transmit buffer; down to zero.
287
324
///
288
325
/// See also [send](#method.send).
289
- pub fn send_slice ( & mut self , data : & [ u8 ] ) -> usize {
290
- let buffer = self . send ( data. len ( ) ) ;
326
+ pub fn send_slice ( & mut self , data : & [ u8 ] ) -> Result < usize , ( ) > {
327
+ let buffer = try! ( self . send ( data. len ( ) ) ) ;
291
328
let data = & data[ ..buffer. len ( ) ] ;
292
329
buffer. copy_from_slice ( data) ;
293
- buffer. len ( )
330
+ Ok ( buffer. len ( ) )
294
331
}
295
332
296
333
/// Dequeue a sequence of received octets, and return a pointer to it.
297
334
///
298
335
/// This function may return a slice smaller than the requested size in case
299
336
/// there are not enough octets queued in the receive buffer, down to
300
337
/// an empty slice.
301
- pub fn recv ( & mut self , size : usize ) -> & [ u8 ] {
338
+ pub fn recv ( & mut self , size : usize ) -> Result < & [ u8 ] , ( ) > {
339
+ // We may have received some data inside the initial SYN ("TCP Fast Open"),
340
+ // but until the connection is fully open we refuse to dequeue any data.
341
+ if !self . can_recv ( ) { return Err ( ( ) ) }
342
+
302
343
let buffer = self . rx_buffer . dequeue ( size) ;
303
344
self . remote_seq_no += buffer. len ( ) as i32 ;
304
345
if buffer. len ( ) > 0 {
305
346
net_trace ! ( "tcp:{}:{}: rx buffer: dequeueing {} octets" ,
306
347
self . local_endpoint, self . remote_endpoint, buffer. len( ) ) ;
307
348
}
308
- buffer
349
+ Ok ( buffer)
309
350
}
310
351
311
352
/// Dequeue a sequence of received octets, and fill a slice from it.
@@ -314,15 +355,35 @@ impl<'a> TcpSocket<'a> {
314
355
/// by the amount of free space in the transmit buffer; down to zero.
315
356
///
316
357
/// See also [recv](#method.recv).
317
- pub fn recv_slice ( & mut self , data : & mut [ u8 ] ) -> usize {
318
- let buffer = self . recv ( data. len ( ) ) ;
358
+ pub fn recv_slice ( & mut self , data : & mut [ u8 ] ) -> Result < usize , ( ) > {
359
+ let buffer = try! ( self . recv ( data. len ( ) ) ) ;
319
360
let data = & mut data[ ..buffer. len ( ) ] ;
320
361
data. copy_from_slice ( buffer) ;
321
- buffer. len ( )
362
+ Ok ( buffer. len ( ) )
363
+ }
364
+
365
+ /// Return the connection state.
366
+ ///
367
+ /// This function is provided for debugging.
368
+ pub fn state ( & self ) -> State {
369
+ self . state
370
+ }
371
+
372
+ fn set_state ( & mut self , state : State ) {
373
+ if self . state != state {
374
+ if self . remote_endpoint . addr . is_unspecified ( ) {
375
+ net_trace ! ( "tcp:{}: state={}→{}" ,
376
+ self . local_endpoint, self . state, state) ;
377
+ } else {
378
+ net_trace ! ( "tcp:{}:{}: state={}→{}" ,
379
+ self . local_endpoint, self . remote_endpoint, self . state, state) ;
380
+ }
381
+ }
382
+ self . state = state
322
383
}
323
384
324
- /// See [Socket::collect ](enum.Socket.html#method.collect ).
325
- pub fn collect ( & mut self , ip_repr : & IpRepr , payload : & [ u8 ] ) -> Result < ( ) , Error > {
385
+ /// See [Socket::process ](enum.Socket.html#method.process ).
386
+ pub fn process ( & mut self , ip_repr : & IpRepr , payload : & [ u8 ] ) -> Result < ( ) , Error > {
326
387
if ip_repr. protocol ( ) != IpProtocol :: Tcp { return Err ( Error :: Rejected ) }
327
388
328
389
let packet = try!( TcpPacket :: new ( payload) ) ;
@@ -663,7 +724,7 @@ mod test {
663
724
dst_addr : LOCAL_IP ,
664
725
protocol : IpProtocol :: Tcp
665
726
} ;
666
- socket. collect ( & ip_repr, & packet. into_inner ( ) [ ..] )
727
+ socket. process ( & ip_repr, & packet. into_inner ( ) [ ..] )
667
728
}
668
729
669
730
fn recv < F > ( socket : & mut TcpSocket , mut f : F )
0 commit comments