|
@@ -7,7 +7,7 @@ use core::{cmp, fmt};
|
|
|
use {Error, Result};
|
|
|
use phy::DeviceCapabilities;
|
|
|
use wire::{IpProtocol, IpAddress, IpEndpoint, TcpSeqNumber, TcpRepr, TcpControl};
|
|
|
-use socket::{Socket, IpRepr};
|
|
|
+use socket::{Socket, SocketHandle, IpRepr};
|
|
|
use storage::{Assembler, RingBuffer};
|
|
|
|
|
|
pub type SocketBuffer<'a> = RingBuffer<'a, u8>;
|
|
@@ -169,7 +169,7 @@ impl Timer {
|
|
|
/// attempts will be reset.
|
|
|
#[derive(Debug)]
|
|
|
pub struct TcpSocket<'a> {
|
|
|
- debug_id: usize,
|
|
|
+ handle: SocketHandle,
|
|
|
state: State,
|
|
|
timer: Timer,
|
|
|
assembler: Assembler,
|
|
@@ -228,7 +228,7 @@ impl<'a> TcpSocket<'a> {
|
|
|
}
|
|
|
|
|
|
Socket::Tcp(TcpSocket {
|
|
|
- debug_id: 0,
|
|
|
+ handle: SocketHandle::EMPTY,
|
|
|
state: State::Closed,
|
|
|
timer: Timer::default(),
|
|
|
assembler: Assembler::new(rx_buffer.capacity()),
|
|
@@ -250,18 +250,15 @@ impl<'a> TcpSocket<'a> {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- /// Return the debug identifier.
|
|
|
+ /// Return the socket handle.
|
|
|
#[inline]
|
|
|
- pub fn debug_id(&self) -> usize {
|
|
|
- self.debug_id
|
|
|
+ pub fn handle(&self) -> SocketHandle {
|
|
|
+ self.handle
|
|
|
}
|
|
|
|
|
|
- /// Set the debug identifier.
|
|
|
- ///
|
|
|
- /// The debug identifier is a number printed in socket trace messages.
|
|
|
- /// It could as well be used by the user code.
|
|
|
- pub fn set_debug_id(&mut self, id: usize) {
|
|
|
- self.debug_id = id
|
|
|
+ /// Set the socket handle.
|
|
|
+ pub(in super) fn set_handle(&mut self, handle: SocketHandle) {
|
|
|
+ self.handle = handle;
|
|
|
}
|
|
|
|
|
|
/// Return the timeout duration.
|
|
@@ -585,8 +582,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
let buffer = self.tx_buffer.enqueue_many(size);
|
|
|
if buffer.len() > 0 {
|
|
|
#[cfg(any(test, feature = "verbose"))]
|
|
|
- net_trace!("[{}]{}:{}: tx buffer: enqueueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: tx buffer: enqueueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
buffer.len(), _old_length + buffer.len());
|
|
|
}
|
|
|
Ok(buffer)
|
|
@@ -608,8 +605,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
let enqueued = self.tx_buffer.enqueue_slice(data);
|
|
|
if enqueued != 0 {
|
|
|
#[cfg(any(test, feature = "verbose"))]
|
|
|
- net_trace!("[{}]{}:{}: tx buffer: enqueueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: tx buffer: enqueueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
enqueued, _old_length + enqueued);
|
|
|
}
|
|
|
Ok(enqueued)
|
|
@@ -634,8 +631,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
self.remote_seq_no += buffer.len();
|
|
|
if buffer.len() > 0 {
|
|
|
#[cfg(any(test, feature = "verbose"))]
|
|
|
- net_trace!("[{}]{}:{}: rx buffer: dequeueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: rx buffer: dequeueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
buffer.len(), _old_length - buffer.len());
|
|
|
}
|
|
|
Ok(buffer)
|
|
@@ -656,8 +653,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
self.remote_seq_no += dequeued;
|
|
|
if dequeued > 0 {
|
|
|
#[cfg(any(test, feature = "verbose"))]
|
|
|
- net_trace!("[{}]{}:{}: rx buffer: dequeueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: rx buffer: dequeueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
dequeued, _old_length - dequeued);
|
|
|
}
|
|
|
Ok(dequeued)
|
|
@@ -674,8 +671,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
let buffer = self.rx_buffer.get_allocated(0, size);
|
|
|
if buffer.len() > 0 {
|
|
|
#[cfg(any(test, feature = "verbose"))]
|
|
|
- net_trace!("[{}]{}:{}: rx buffer: peeking at {} octets",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: rx buffer: peeking at {} octets",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
buffer.len());
|
|
|
}
|
|
|
Ok(buffer)
|
|
@@ -709,12 +706,12 @@ impl<'a> TcpSocket<'a> {
|
|
|
fn set_state(&mut self, state: State) {
|
|
|
if self.state != state {
|
|
|
if self.remote_endpoint.addr.is_unspecified() {
|
|
|
- net_trace!("[{}]{}: state={}=>{}",
|
|
|
- self.debug_id, self.local_endpoint,
|
|
|
+ net_trace!("{}:{}: state={}=>{}",
|
|
|
+ self.handle, self.local_endpoint,
|
|
|
self.state, state);
|
|
|
} else {
|
|
|
- net_trace!("[{}]{}:{}: state={}=>{}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: state={}=>{}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
self.state, state);
|
|
|
}
|
|
|
}
|
|
@@ -816,17 +813,17 @@ impl<'a> TcpSocket<'a> {
|
|
|
(State::SynSent, &TcpRepr {
|
|
|
control: TcpControl::Rst, ack_number: None, ..
|
|
|
}) => {
|
|
|
- net_debug!("[{}]{}:{}: unacceptable RST (expecting RST|ACK) \
|
|
|
+ net_debug!("{}:{}:{}: unacceptable RST (expecting RST|ACK) \
|
|
|
in response to initial SYN",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
|
(State::SynSent, &TcpRepr {
|
|
|
control: TcpControl::Rst, ack_number: Some(ack_number), ..
|
|
|
}) => {
|
|
|
if ack_number != self.local_seq_no + 1 {
|
|
|
- net_debug!("[{}]{}:{}: unacceptable RST|ACK in response to initial SYN",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_debug!("{}:{}:{}: unacceptable RST|ACK in response to initial SYN",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
|
}
|
|
@@ -838,8 +835,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
(State::Listen, &TcpRepr { ack_number: Some(_), .. }) => unreachable!(),
|
|
|
// Every packet after the initial SYN must be an acknowledgement.
|
|
|
(_, &TcpRepr { ack_number: None, .. }) => {
|
|
|
- net_debug!("[{}]{}:{}: expecting an ACK",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_debug!("{}:{}:{}: expecting an ACK",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
|
// Every acknowledgement must be for transmitted but unacknowledged data.
|
|
@@ -847,16 +844,16 @@ impl<'a> TcpSocket<'a> {
|
|
|
let unacknowledged = self.tx_buffer.len() + control_len;
|
|
|
|
|
|
if ack_number < self.local_seq_no {
|
|
|
- net_debug!("[{}]{}:{}: duplicate ACK ({} not in {}...{})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_debug!("{}:{}:{}: duplicate ACK ({} not in {}...{})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
ack_number, self.local_seq_no, self.local_seq_no + unacknowledged);
|
|
|
// FIXME: implement fast retransmit
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
|
|
|
|
if ack_number > self.local_seq_no + unacknowledged {
|
|
|
- net_debug!("[{}]{}:{}: unacceptable ACK ({} not in {}...{})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_debug!("{}:{}:{}: unacceptable ACK ({} not in {}...{})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
ack_number, self.local_seq_no, self.local_seq_no + unacknowledged);
|
|
|
return Ok(Some(self.ack_reply(ip_repr, &repr)))
|
|
|
}
|
|
@@ -878,17 +875,17 @@ impl<'a> TcpSocket<'a> {
|
|
|
let segment_end = repr.seq_number + repr.segment_len();
|
|
|
|
|
|
if window_start == window_end && segment_start != segment_end {
|
|
|
- net_debug!("[{}]{}:{}: non-zero-length segment with zero receive window, \
|
|
|
+ net_debug!("{}:{}:{}: non-zero-length segment with zero receive window, \
|
|
|
will only send an ACK",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
segment_in_window = false;
|
|
|
}
|
|
|
|
|
|
if !((window_start <= segment_start && segment_start <= window_end) &&
|
|
|
(window_start <= segment_end && segment_end <= window_end)) {
|
|
|
- net_debug!("[{}]{}:{}: segment not in receive window \
|
|
|
+ net_debug!("{}:{}:{}: segment not in receive window \
|
|
|
({}..{} not intersecting {}..{}), will send challenge ACK",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
segment_start, segment_end, window_start, window_end);
|
|
|
segment_in_window = false;
|
|
|
}
|
|
@@ -924,8 +921,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
// space if all of that data is acknowledged.
|
|
|
if sent_fin && self.tx_buffer.len() + 1 == ack_len {
|
|
|
ack_len -= 1;
|
|
|
- net_trace!("[{}]{}:{}: received ACK of FIN",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: received ACK of FIN",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
ack_of_fin = true;
|
|
|
}
|
|
|
}
|
|
@@ -939,8 +936,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
|
|
|
// RSTs in SYN-RECEIVED flip the socket back to the LISTEN state.
|
|
|
(State::SynReceived, TcpControl::Rst) => {
|
|
|
- net_trace!("[{}]{}:{}: received RST",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: received RST",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
self.local_endpoint.addr = self.listen_address;
|
|
|
self.remote_endpoint = IpEndpoint::default();
|
|
|
self.set_state(State::Listen);
|
|
@@ -949,8 +946,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
|
|
|
// RSTs in any other state close the socket.
|
|
|
(_, TcpControl::Rst) => {
|
|
|
- net_trace!("[{}]{}:{}: received RST",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: received RST",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
self.set_state(State::Closed);
|
|
|
self.local_endpoint = IpEndpoint::default();
|
|
|
self.remote_endpoint = IpEndpoint::default();
|
|
@@ -959,8 +956,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
|
|
|
// SYN packets in the LISTEN state change it to SYN-RECEIVED.
|
|
|
(State::Listen, TcpControl::Syn) => {
|
|
|
- net_trace!("[{}]{}: received SYN",
|
|
|
- self.debug_id, self.local_endpoint);
|
|
|
+ net_trace!("{}:{}: received SYN",
|
|
|
+ self.handle, self.local_endpoint);
|
|
|
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
|
|
|
self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), repr.src_port);
|
|
|
// FIXME: use something more secure here
|
|
@@ -991,8 +988,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
|
|
|
// SYN|ACK packets in the SYN-SENT state change it to ESTABLISHED.
|
|
|
(State::SynSent, TcpControl::Syn) => {
|
|
|
- net_trace!("[{}]{}:{}: received SYN|ACK",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: received SYN|ACK",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
|
|
|
self.remote_seq_no = repr.seq_number + 1;
|
|
|
self.remote_last_seq = self.local_seq_no + 1;
|
|
@@ -1069,8 +1066,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
}
|
|
|
|
|
|
_ => {
|
|
|
- net_debug!("[{}]{}:{}: unexpected packet {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint, repr);
|
|
|
+ net_debug!("{}:{}:{}: unexpected packet {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint, repr);
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
|
}
|
|
@@ -1082,8 +1079,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
if ack_len > 0 {
|
|
|
// Dequeue acknowledged octets.
|
|
|
debug_assert!(self.tx_buffer.len() >= ack_len);
|
|
|
- net_trace!("[{}]{}:{}: tx buffer: dequeueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: tx buffer: dequeueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
ack_len, self.tx_buffer.len() - ack_len);
|
|
|
self.tx_buffer.dequeue_allocated(ack_len);
|
|
|
}
|
|
@@ -1104,14 +1101,14 @@ impl<'a> TcpSocket<'a> {
|
|
|
Ok(()) => {
|
|
|
debug_assert!(self.assembler.total_size() == self.rx_buffer.capacity());
|
|
|
// Place payload octets into the buffer.
|
|
|
- net_trace!("[{}]{}:{}: rx buffer: receiving {} octets at offset {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: rx buffer: receiving {} octets at offset {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
payload_len, payload_offset);
|
|
|
self.rx_buffer.write_unallocated(payload_offset, repr.payload);
|
|
|
}
|
|
|
Err(()) => {
|
|
|
- net_debug!("[{}]{}:{}: assembler: too many holes to add {} octets at offset {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_debug!("{}:{}:{}: assembler: too many holes to add {} octets at offset {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
payload_len, payload_offset);
|
|
|
return Err(Error::Dropped)
|
|
|
}
|
|
@@ -1120,16 +1117,16 @@ impl<'a> TcpSocket<'a> {
|
|
|
if let Some(contig_len) = self.assembler.remove_front() {
|
|
|
debug_assert!(self.assembler.total_size() == self.rx_buffer.capacity());
|
|
|
// Enqueue the contiguous data octets in front of the buffer.
|
|
|
- net_trace!("[{}]{}:{}: rx buffer: enqueueing {} octets (now {})",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: rx buffer: enqueueing {} octets (now {})",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
contig_len, self.rx_buffer.len() + contig_len);
|
|
|
self.rx_buffer.enqueue_unallocated(contig_len);
|
|
|
}
|
|
|
|
|
|
if !self.assembler.is_empty() {
|
|
|
// Print the ranges recorded in the assembler.
|
|
|
- net_trace!("[{}]{}:{}: assembler: {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: assembler: {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
self.assembler);
|
|
|
}
|
|
|
|
|
@@ -1204,14 +1201,14 @@ impl<'a> TcpSocket<'a> {
|
|
|
// Check if any state needs to be changed because of a timer.
|
|
|
if self.timed_out(timestamp) {
|
|
|
// If a timeout expires, we should abort the connection.
|
|
|
- net_debug!("[{}]{}:{}: timeout exceeded",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_debug!("{}:{}:{}: timeout exceeded",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
self.set_state(State::Closed);
|
|
|
} else if !self.seq_to_transmit() {
|
|
|
if let Some(retransmit_delta) = self.timer.should_retransmit(timestamp) {
|
|
|
// If a retransmit timer expired, we should resend data starting at the last ACK.
|
|
|
- net_debug!("[{}]{}:{}: retransmitting at t+{}ms",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_debug!("{}:{}:{}: retransmitting at t+{}ms",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
retransmit_delta);
|
|
|
self.remote_last_seq = self.local_seq_no;
|
|
|
}
|
|
@@ -1310,8 +1307,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
// we wait for the timer to expire.
|
|
|
State::TimeWait => {
|
|
|
if self.timer.should_close(timestamp) {
|
|
|
- net_trace!("[{}]{}:{}: TIME-WAIT timeout",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: TIME-WAIT timeout",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
self.reset();
|
|
|
return Err(Error::Exhausted)
|
|
|
}
|
|
@@ -1333,11 +1330,11 @@ impl<'a> TcpSocket<'a> {
|
|
|
|
|
|
// Trace a summary of what will be sent.
|
|
|
if is_keep_alive {
|
|
|
- net_trace!("[{}]{}:{}: sending a keep-alive",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint);
|
|
|
+ net_trace!("{}:{}:{}: sending a keep-alive",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint);
|
|
|
} else if repr.payload.len() > 0 {
|
|
|
- net_trace!("[{}]{}:{}: tx buffer: sending {} octets at offset {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: tx buffer: sending {} octets at offset {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
repr.payload.len(), self.remote_last_seq - self.local_seq_no);
|
|
|
}
|
|
|
if repr.control != TcpControl::None || repr.payload.len() == 0 {
|
|
@@ -1351,8 +1348,8 @@ impl<'a> TcpSocket<'a> {
|
|
|
(TcpControl::None, Some(_)) => "ACK",
|
|
|
_ => "<unreachable>"
|
|
|
};
|
|
|
- net_trace!("[{}]{}:{}: sending {}",
|
|
|
- self.debug_id, self.local_endpoint, self.remote_endpoint,
|
|
|
+ net_trace!("{}:{}:{}: sending {}",
|
|
|
+ self.handle, self.local_endpoint, self.remote_endpoint,
|
|
|
flags);
|
|
|
}
|
|
|
|