Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: smoltcp-rs/smoltcp
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 41f9426380b8
Choose a base ref
...
head repository: smoltcp-rs/smoltcp
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4f2c58d4f617
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Jan 14, 2017

  1. Copy the full SHA
    d7e05d1 View commit details
  2. Copy the full SHA
    6167305 View commit details
  3. Copy the full SHA
    4f2c58d View commit details
Showing with 118 additions and 17 deletions.
  1. +116 −15 src/socket/tcp.rs
  2. +2 −2 src/wire/ipv4.rs
131 changes: 116 additions & 15 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
@@ -152,7 +152,7 @@ impl fmt::Display for State {
}
}

#[derive(Debug)]
#[derive(Debug, PartialEq)]
struct Retransmit {
resend_at: u64,
delay: u64
@@ -760,9 +760,13 @@ impl<'a> TcpSocket<'a> {
};

if self.retransmit.may_send_old(timestamp) {
// The retransmit timer has expired, so assume all in-flight packets that
// have not been acknowledged are lost.
self.remote_last_seq = self.local_seq_no;
// The retransmit timer has expired, so assume all in-flight data that
// has not been acknowledged is lost.
match self.state {
// Retransmission of SYN is handled elsewhere.
State::SynReceived => (),
_ => self.remote_last_seq = self.local_seq_no
}
} else if self.retransmit.may_send_new(timestamp) {
// The retransmit timer has reset, and we can send something new.
} else {
@@ -1016,6 +1020,29 @@ mod test {
(recv(&mut $socket, $time, |repr| assert_eq!(repr, $result)));
}

macro_rules! sanity {
($socket1:expr, $socket2:expr, retransmit: $retransmit:expr) => ({
let (s1, s2) = ($socket1, $socket2);
assert_eq!(s1.state, s2.state, "state");
assert_eq!(s1.listen_address, s2.listen_address, "listen_address");
assert_eq!(s1.local_endpoint, s2.local_endpoint, "local_endpoint");
assert_eq!(s1.remote_endpoint, s2.remote_endpoint, "remote_endpoint");
assert_eq!(s1.local_seq_no, s2.local_seq_no, "local_seq_no");
assert_eq!(s1.remote_seq_no, s2.remote_seq_no, "remote_seq_no");
assert_eq!(s1.remote_last_seq, s2.remote_last_seq, "remote_last_seq");
assert_eq!(s1.remote_last_ack, s2.remote_last_ack, "remote_last_ack");
assert_eq!(s1.remote_win_len, s2.remote_win_len, "remote_win_len");
if $retransmit {
assert_eq!(s1.retransmit, s2.retransmit, "retransmit");
} else {
let retransmit = Retransmit { resend_at: 100, delay: 100 };
assert_eq!(s1.retransmit, retransmit, "retransmit (delaying)");
}
});
($socket1:expr, $socket2:expr) =>
(sanity!($socket1, $socket2, retransmit: true))
}

fn init_logger() {
extern crate log;
use std::boxed::Box;
@@ -1082,6 +1109,25 @@ mod test {
s
}

#[test]
fn test_listen_sanity() {
let mut s = socket();
s.listen(LOCAL_PORT).unwrap();
sanity!(s, socket_listen());
}

#[test]
fn test_listen_syn() {
let mut s = socket_listen();
send!(s, TcpRepr {
control: TcpControl::Syn,
seq_number: REMOTE_SEQ,
ack_number: None,
..SEND_TEMPL
});
sanity!(s, socket_syn_received());
}

#[test]
fn test_listen_syn_no_ack() {
let mut s = socket_listen();
@@ -1121,16 +1167,36 @@ mod test {
s.local_endpoint = LOCAL_END;
s.remote_endpoint = REMOTE_END;
s.local_seq_no = LOCAL_SEQ;
s.remote_seq_no = REMOTE_SEQ;
s.remote_seq_no = REMOTE_SEQ + 1;
s.remote_last_seq = LOCAL_SEQ + 1;
s.remote_win_len = 256;
s
}

#[test]
fn test_syn_received_syn_ack() {
let mut s = socket_syn_received();
recv!(s, [TcpRepr {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
..RECV_TEMPL
}]);
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
..SEND_TEMPL
});
assert_eq!(s.state, State::Established);
sanity!(s, socket_established());
}

#[test]
fn test_syn_received_rst() {
let mut s = socket_syn_received();
send!(s, TcpRepr {
control: TcpControl::Rst,
seq_number: REMOTE_SEQ,
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ),
..SEND_TEMPL
});
@@ -1206,12 +1272,9 @@ mod test {
// =========================================================================================//
fn socket_established() -> TcpSocket<'static> {
let mut s = socket_syn_received();
s.state = State::Established;
s.state = State::Established;
s.local_seq_no = LOCAL_SEQ + 1;
s.remote_seq_no = REMOTE_SEQ + 1;
s.remote_last_seq = LOCAL_SEQ + 1;
s.remote_last_ack = REMOTE_SEQ + 1;
s.remote_win_len = 128;
s
}

@@ -1350,12 +1413,13 @@ mod test {
ack_number: Some(LOCAL_SEQ + 1),
..SEND_TEMPL
});
assert_eq!(s.state, State::CloseWait);
recv!(s, [TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1 + 1),
..RECV_TEMPL
}]);
assert_eq!(s.state, State::CloseWait);
sanity!(s, socket_close_wait(), retransmit: false);
}

#[test]
@@ -1406,6 +1470,7 @@ mod test {
let mut s = socket_established();
s.close();
assert_eq!(s.state, State::FinWait1);
sanity!(s, socket_fin_wait_1());
}

// =========================================================================================//
@@ -1432,6 +1497,7 @@ mod test {
..SEND_TEMPL
});
assert_eq!(s.state, State::FinWait2);
sanity!(&s, socket_fin_wait_2(), retransmit: false);
}

#[test]
@@ -1450,6 +1516,7 @@ mod test {
..SEND_TEMPL
});
assert_eq!(s.state, State::Closing);
sanity!(s, socket_closing());
}

#[test]
@@ -1479,6 +1546,7 @@ mod test {
..SEND_TEMPL
});
assert_eq!(s.state, State::TimeWait);
sanity!(s, socket_time_wait(false));
}

#[test]
@@ -1513,6 +1581,7 @@ mod test {
..SEND_TEMPL
});
assert_eq!(s.state, State::TimeWait);
sanity!(s, socket_time_wait(true));
}

#[test]
@@ -1591,6 +1660,7 @@ mod test {
let mut s = socket_close_wait();
s.close();
assert_eq!(s.state, State::LastAck);
sanity!(s, socket_last_ack());
}

// =========================================================================================//
@@ -1760,6 +1830,20 @@ mod test {
recv!(s, []);
}

#[test]
fn test_fin_with_data() {
let mut s = socket_established();
s.send_slice(b"abcdef").unwrap();
s.close();
recv!(s, [TcpRepr {
control: TcpControl::Fin,
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"abcdef"[..],
..RECV_TEMPL
}])
}

// =========================================================================================//
// Tests for retransmission on packet loss.
// =========================================================================================//
@@ -1818,16 +1902,33 @@ mod test {
}

#[test]
fn test_fin_with_data() {
let mut s = socket_established();
fn test_send_data_after_syn_ack_retransmit() {
let mut s = socket_syn_received();
recv!(s, time 50, Ok(TcpRepr {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
..RECV_TEMPL
}));
recv!(s, time 150, Ok(TcpRepr { // retransmit
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
..RECV_TEMPL
}));
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
..SEND_TEMPL
});
assert_eq!(s.state(), State::Established);
s.send_slice(b"abcdef").unwrap();
s.close();
recv!(s, [TcpRepr {
control: TcpControl::Fin,
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1),
payload: &b"abcdef"[..],
..RECV_TEMPL
}])
}

}
4 changes: 2 additions & 2 deletions src/wire/ipv4.rs
Original file line number Diff line number Diff line change
@@ -480,13 +480,13 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
let (ip_repr, payload) = match Packet::new(buffer) {
Err(err) => return write!(f, "{}({})\n", indent, err),
Ok(ip_packet) => {
try!(write!(f, "{}{}\n", indent, ip_packet));
match Repr::parse(&ip_packet) {
Err(err) => return write!(f, "{}{} ({})\n", indent, ip_packet, err),
Err(_) => return Ok(()),
Ok(ip_repr) => (ip_repr, &ip_packet.payload()[..ip_repr.payload_len])
}
}
};
try!(write!(f, "{}{}\n", indent, ip_repr));

indent.increase();
match ip_repr.protocol {