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: 004cfd439be7
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: 2c0c1ea76a4f
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Dec 27, 2016

  1. Fix examples.

    whitequark committed Dec 27, 2016
    Copy the full SHA
    5323f88 View commit details
  2. Copy the full SHA
    2c0c1ea View commit details
Showing with 119 additions and 69 deletions.
  1. +3 −1 README.md
  2. +17 −15 examples/smoltcpserver.rs
  3. +35 −34 src/socket/tcp.rs
  4. +1 −0 src/wire/mod.rs
  5. +63 −19 src/wire/tcp.rs
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -105,9 +105,11 @@ cargo run --example smoltcpserver -- tap0

It responds to:

* pings (`ping 192.168.69.1`),
* pings (`ping 192.168.69.1`);
* UDP packets on port 6969 (`socat stdio udp4-connect:192.168.69.1:6969 <<<"abcdefg"`),
where it will respond "yo dawg" to any incoming packet;
* TCP packets on port 6969 (`socat stdio tcp4-connect:192.168.69.1:6969 <<<"abcdefg"`),
where it will respond with reversed chunks of the input indefinitely.

The buffers are only 64 bytes long, for convenience of testing resource exhaustion conditions.

32 changes: 17 additions & 15 deletions examples/smoltcpserver.rs
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ fn main() {
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
let mut tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
(tcp_socket.as_socket() : &mut TcpSocket).listen(endpoint);
(tcp_socket.as_socket() : &mut TcpSocket).listen(endpoint).unwrap();

let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
@@ -97,21 +97,23 @@ fn main() {

{
let socket: &mut TcpSocket = iface.sockets()[1].as_socket();
let data = {
let mut data = socket.recv(128).to_owned();
if data.len() > 0 {
debug!("tcp recv data: {:?}",
str::from_utf8(data.as_ref()).unwrap());
data = data.split(|&b| b == b'\n').next().unwrap().to_owned();
data.reverse();
data.extend(b"\n");
if socket.can_recv() {
let data = {
let mut data = socket.recv(128).unwrap().to_owned();
if data.len() > 0 {
debug!("tcp recv data: {:?}",
str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
data.reverse();
data.extend(b"\n");
}
data
};
if socket.can_send() && data.len() > 0 {
debug!("tcp send data: {:?}",
str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
socket.send_slice(&data[..]).unwrap();
}
data
};
if data.len() > 0 {
debug!("tcp send data: {:?}",
str::from_utf8(data.as_ref()).unwrap());
socket.send_slice(&data[..]);
}
}
}
69 changes: 35 additions & 34 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use core::fmt;
use Error;
use Managed;
use wire::{IpProtocol, IpAddress, IpEndpoint};
use wire::{TcpPacket, TcpRepr, TcpControl};
use wire::{TcpSeqNumber, TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, IpRepr, IpPayload};

/// A TCP stream ring buffer.
@@ -185,16 +185,16 @@ pub struct TcpSocket<'a> {
remote_endpoint: IpEndpoint,
/// The sequence number corresponding to the beginning of the transmit buffer.
/// I.e. an ACK(local_seq_no+n) packet removes n bytes from the transmit buffer.
local_seq_no: i32,
local_seq_no: TcpSeqNumber,
/// The sequence number corresponding to the beginning of the receive buffer.
/// I.e. userspace reading n bytes adds n to remote_seq_no.
remote_seq_no: i32,
remote_seq_no: TcpSeqNumber,
/// The last sequence number sent.
/// I.e. in an idle socket, local_seq_no+tx_buffer.len().
remote_last_seq: i32,
remote_last_seq: TcpSeqNumber,
/// The last acknowledgement number sent.
/// I.e. in an idle socket, remote_seq_no+rx_buffer.len().
remote_last_ack: i32,
remote_last_ack: TcpSeqNumber,
/// The speculative remote window size.
/// I.e. the actual remote window size minus the count of in-flight octets.
remote_win_len: usize,
@@ -218,10 +218,10 @@ impl<'a> TcpSocket<'a> {
listen_address: IpAddress::default(),
local_endpoint: IpEndpoint::default(),
remote_endpoint: IpEndpoint::default(),
local_seq_no: 0,
remote_seq_no: 0,
remote_last_seq: 0,
remote_last_ack: 0,
local_seq_no: TcpSeqNumber(0),
remote_seq_no: TcpSeqNumber(0),
remote_last_seq: TcpSeqNumber(0),
remote_last_ack: TcpSeqNumber(0),
remote_win_len: 0,
retransmit: Retransmit::new(),
tx_buffer: tx_buffer.into(),
@@ -341,7 +341,7 @@ impl<'a> TcpSocket<'a> {
if !self.can_recv() { return Err(()) }

let buffer = self.rx_buffer.dequeue(size);
self.remote_seq_no += buffer.len() as i32;
self.remote_seq_no += buffer.len();
if buffer.len() > 0 {
net_trace!("tcp:{}:{}: rx buffer: dequeueing {} octets",
self.local_endpoint, self.remote_endpoint, buffer.len());
@@ -450,9 +450,9 @@ impl<'a> TcpSocket<'a> {
// all of the control flags we sent.
_ => 0
};
let unacknowledged = self.tx_buffer.len() as i32 + control_len;
if !(ack_number - self.local_seq_no >= 0 &&
ack_number - (self.local_seq_no + unacknowledged) <= 0) {
let unacknowledged = self.tx_buffer.len() + control_len;
if !(ack_number >= self.local_seq_no &&
ack_number <= (self.local_seq_no + unacknowledged)) {
net_trace!("tcp:{}:{}: unacceptable ACK ({} not in {}..{})",
self.local_endpoint, self.remote_endpoint,
ack_number, self.local_seq_no, self.local_seq_no + unacknowledged);
@@ -468,13 +468,13 @@ impl<'a> TcpSocket<'a> {
// In all other states, segments must occupy a valid portion of the receive window.
// For now, do not try to reassemble out-of-order segments.
(_, TcpRepr { seq_number, .. }) => {
let next_remote_seq = self.remote_seq_no + self.rx_buffer.len() as i32;
if seq_number - next_remote_seq > 0 {
let next_remote_seq = self.remote_seq_no + self.rx_buffer.len();
if seq_number > next_remote_seq {
net_trace!("tcp:{}:{}: unacceptable SEQ ({} not in {}..)",
self.local_endpoint, self.remote_endpoint,
seq_number, next_remote_seq);
return Err(Error::Malformed)
} else if seq_number - next_remote_seq != 0 {
} else if seq_number != next_remote_seq {
net_trace!("tcp:{}:{}: duplicate SEQ ({} in ..{})",
self.local_endpoint, self.remote_endpoint,
seq_number, next_remote_seq);
@@ -511,7 +511,8 @@ impl<'a> TcpSocket<'a> {
}) => {
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), dst_port);
self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), src_port);
self.local_seq_no = -seq_number; // FIXME: use something more secure
// FIXME: use something more secure here
self.local_seq_no = TcpSeqNumber(-seq_number.0);
self.remote_last_seq = self.local_seq_no + 1;
self.remote_seq_no = seq_number + 1;
self.set_state(State::SynReceived);
@@ -607,7 +608,7 @@ impl<'a> TcpSocket<'a> {
// 1. the retransmit timer has expired, or...
let mut may_send = self.retransmit.check();
// 2. we've got new data in the transmit buffer.
let remote_next_seq = self.local_seq_no + self.tx_buffer.len() as i32;
let remote_next_seq = self.local_seq_no + self.tx_buffer.len();
if self.remote_last_seq != remote_next_seq {
may_send = true;
}
@@ -627,17 +628,17 @@ impl<'a> TcpSocket<'a> {
repr.payload = data;
// Speculatively shrink the remote window. This will get updated the next
// time we receive a packet.
self.remote_win_len -= data.len();
self.remote_win_len -= data.len();
// Advance the in-flight sequence number.
self.remote_last_seq += data.len() as i32;
self.remote_last_seq += data.len();
should_send = true;
}
}

_ => unreachable!()
}

let ack_number = self.remote_seq_no + self.rx_buffer.len() as i32;
let ack_number = self.remote_seq_no + self.rx_buffer.len();
if !should_send && self.remote_last_ack != ack_number {
// Acknowledge all data we have received, since it is all in order.
net_trace!("tcp:{}:{}: sending ACK",
@@ -692,25 +693,25 @@ mod test {
buffer.enqueue_slice(&b"bazhoge"[..]); // zhobarba
}

const LOCAL_IP: IpAddress = IpAddress::v4(10, 0, 0, 1);
const REMOTE_IP: IpAddress = IpAddress::v4(10, 0, 0, 2);
const LOCAL_PORT: u16 = 80;
const REMOTE_PORT: u16 = 49500;
const LOCAL_END: IpEndpoint = IpEndpoint::new(LOCAL_IP, LOCAL_PORT);
const REMOTE_END: IpEndpoint = IpEndpoint::new(REMOTE_IP, REMOTE_PORT);
const LOCAL_SEQ: i32 = 10000;
const REMOTE_SEQ: i32 = -10000;
const LOCAL_IP: IpAddress = IpAddress::v4(10, 0, 0, 1);
const REMOTE_IP: IpAddress = IpAddress::v4(10, 0, 0, 2);
const LOCAL_PORT: u16 = 80;
const REMOTE_PORT: u16 = 49500;
const LOCAL_END: IpEndpoint = IpEndpoint::new(LOCAL_IP, LOCAL_PORT);
const REMOTE_END: IpEndpoint = IpEndpoint::new(REMOTE_IP, REMOTE_PORT);
const LOCAL_SEQ: TcpSeqNumber = TcpSeqNumber(10000);
const REMOTE_SEQ: TcpSeqNumber = TcpSeqNumber(-10000);

const SEND_TEMPL: TcpRepr<'static> = TcpRepr {
src_port: REMOTE_PORT, dst_port: LOCAL_PORT,
control: TcpControl::None,
seq_number: 0, ack_number: Some(0),
seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)),
window_len: 256, payload: &[]
};
const RECV_TEMPL: TcpRepr<'static> = TcpRepr {
src_port: LOCAL_PORT, dst_port: REMOTE_PORT,
control: TcpControl::None,
seq_number: 0, ack_number: Some(0),
seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)),
window_len: 64, payload: &[]
};

@@ -917,7 +918,7 @@ mod test {
send!(s, TcpRepr {
control: TcpControl::Rst,
seq_number: REMOTE_SEQ,
ack_number: Some(1234),
ack_number: Some(TcpSeqNumber(1234)),
..SEND_TEMPL
}, Err(Error::Malformed));
assert_eq!(s.state, State::SynSent);
@@ -1005,7 +1006,7 @@ mod test {
// Already acknowledged data.
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ - 1),
ack_number: Some(TcpSeqNumber(LOCAL_SEQ.0 - 1)),
..SEND_TEMPL
}, Err(Error::Malformed));
assert_eq!(s.local_seq_no, LOCAL_SEQ + 1);
@@ -1112,7 +1113,7 @@ mod test {
#[test]
fn test_listen() {
let mut s = socket();
s.listen(IpEndpoint::new(IpAddress::default(), LOCAL_PORT));
s.listen(IpEndpoint::new(IpAddress::default(), LOCAL_PORT)).unwrap();
assert_eq!(s.state, State::Listen);
}

1 change: 1 addition & 0 deletions src/wire/mod.rs
Original file line number Diff line number Diff line change
@@ -119,6 +119,7 @@ pub use self::icmpv4::Repr as Icmpv4Repr;
pub use self::udp::Packet as UdpPacket;
pub use self::udp::Repr as UdpRepr;

pub use self::tcp::SeqNumber as TcpSeqNumber;
pub use self::tcp::Packet as TcpPacket;
pub use self::tcp::Repr as TcpRepr;
pub use self::tcp::Control as TcpControl;
Loading