Skip to content

Commit ab61890

Browse files
committedDec 20, 2016
Implement TCP server sockets.
1 parent efc7bfb commit ab61890

File tree

6 files changed

+149
-29
lines changed

6 files changed

+149
-29
lines changed
 

‎examples/smoltcpserver.rs

+30-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use smoltcp::phy::{Tracer, TapInterface};
77
use smoltcp::wire::{EthernetFrame, EthernetAddress, IpAddress, IpEndpoint};
88
use smoltcp::iface::{SliceArpCache, EthernetInterface};
99
use smoltcp::socket::{UdpSocket, AsSocket, UdpSocketBuffer, UdpPacketBuffer};
10+
use smoltcp::socket::{TcpListener};
1011

1112
fn main() {
1213
let ifname = env::args().nth(1).unwrap();
@@ -15,14 +16,18 @@ fn main() {
1516
let device = Tracer::<_, EthernetFrame<&[u8]>>::new(device);
1617
let arp_cache = SliceArpCache::new(vec![Default::default(); 8]);
1718

19+
let endpoint = IpEndpoint::new(IpAddress::default(), 6969);
20+
1821
let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 2048])]);
1922
let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 2048])]);
20-
let endpoint = IpEndpoint::new(IpAddress::default(), 6969);
2123
let udp_socket = UdpSocket::new(endpoint, udp_rx_buffer, udp_tx_buffer);
2224

25+
let tcp_backlog = vec![None];
26+
let tcp_listener = TcpListener::new(endpoint, tcp_backlog);
27+
2328
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
2429
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
25-
let sockets = [udp_socket];
30+
let sockets = [udp_socket, tcp_listener];
2631
let mut iface = EthernetInterface::new(device, arp_cache,
2732
hardware_addr, protocol_addrs, sockets);
2833

@@ -32,22 +37,31 @@ fn main() {
3237
Err(e) => println!("error {}", e)
3338
}
3439

35-
let udp_socket = iface.sockets()[0].as_socket();
36-
let client = match udp_socket.recv() {
37-
Ok((endpoint, data)) => {
38-
println!("data {:?} from {}", data, endpoint);
39-
Some(endpoint)
40+
{
41+
let udp_socket: &mut UdpSocket = iface.sockets()[0].as_socket();
42+
let udp_client = match udp_socket.recv() {
43+
Ok((endpoint, data)) => {
44+
println!("data {:?} from {}", data, endpoint);
45+
Some(endpoint)
46+
}
47+
Err(Error::Exhausted) => {
48+
None
49+
}
50+
Err(e) => {
51+
println!("error {}", e);
52+
None
53+
}
54+
};
55+
if let Some(endpoint) = udp_client {
56+
udp_socket.send_slice(endpoint, "hihihi".as_bytes()).unwrap()
4057
}
41-
Err(Error::Exhausted) => {
42-
None
43-
}
44-
Err(e) => {
45-
println!("error {}", e);
46-
None
58+
}
59+
60+
{
61+
let tcp_listener: &mut TcpListener = iface.sockets()[1].as_socket();
62+
if let Some(stream) = tcp_listener.accept() {
63+
println!("client from {}", stream.remote_end())
4764
}
48-
};
49-
if let Some(endpoint) = client {
50-
udp_socket.send_slice(endpoint, "hihihi".as_bytes()).unwrap()
5165
}
5266
}
5367
}

‎src/managed.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl<'a, T: 'a + fmt::Debug + ?Sized> fmt::Debug for Managed<'a, T> {
3535
}
3636
}
3737

38-
impl<'a, 'b: 'a, T: 'b + ?Sized> From<&'b mut T> for Managed<'b, T> {
39-
fn from(value: &'b mut T) -> Self {
38+
impl<'a, T: 'a + ?Sized> From<&'a mut T> for Managed<'a, T> {
39+
fn from(value: &'a mut T) -> Self {
4040
Managed::Borrowed(value)
4141
}
4242
}

‎src/socket/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub use self::udp::SocketBuffer as UdpSocketBuffer;
2121
pub use self::udp::UdpSocket as UdpSocket;
2222

2323
pub use self::tcp::SocketBuffer as TcpSocketBuffer;
24+
pub use self::tcp::Incoming as TcpIncoming;
25+
pub use self::tcp::Listener as TcpListener;
2426

2527
/// A packet representation.
2628
///
@@ -49,6 +51,7 @@ pub trait PacketRepr {
4951
/// since the lower layers treat the packet as an opaque octet sequence.
5052
pub enum Socket<'a, 'b: 'a> {
5153
Udp(UdpSocket<'a, 'b>),
54+
TcpServer(TcpListener<'a>),
5255
#[doc(hidden)]
5356
__Nonexhaustive
5457
}
@@ -67,6 +70,8 @@ impl<'a, 'b> Socket<'a, 'b> {
6770
match self {
6871
&mut Socket::Udp(ref mut socket) =>
6972
socket.collect(src_addr, dst_addr, protocol, payload),
73+
&mut Socket::TcpServer(ref mut socket) =>
74+
socket.collect(src_addr, dst_addr, protocol, payload),
7075
&mut Socket::__Nonexhaustive => unreachable!()
7176
}
7277
}
@@ -84,6 +89,8 @@ impl<'a, 'b> Socket<'a, 'b> {
8489
match self {
8590
&mut Socket::Udp(ref mut socket) =>
8691
socket.dispatch(f),
92+
&mut Socket::TcpServer(_) =>
93+
Err(Error::Exhausted),
8794
&mut Socket::__Nonexhaustive => unreachable!()
8895
}
8996
}
@@ -105,3 +112,12 @@ impl<'a, 'b> AsSocket<UdpSocket<'a, 'b>> for Socket<'a, 'b> {
105112
}
106113
}
107114
}
115+
116+
impl<'a, 'b> AsSocket<TcpListener<'a>> for Socket<'a, 'b> {
117+
fn as_socket(&mut self) -> &mut TcpListener<'a> {
118+
match self {
119+
&mut Socket::TcpServer(ref mut socket) => socket,
120+
_ => panic!(".as_socket::<TcpListener> called on wrong socket type")
121+
}
122+
}
123+
}

‎src/socket/tcp.rs

+90
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
use Error;
12
use Managed;
3+
use wire::{IpProtocol, IpAddress, IpEndpoint};
4+
use wire::{TcpPacket, TcpRepr, TcpControl};
5+
use socket::{Socket};
26

37
/// A TCP stream ring buffer.
48
#[derive(Debug)]
@@ -56,6 +60,92 @@ impl<'a> SocketBuffer<'a> {
5660
}
5761
}
5862

63+
/// A description of incoming TCP connection.
64+
#[derive(Debug)]
65+
pub struct Incoming {
66+
local_end: IpEndpoint,
67+
remote_end: IpEndpoint,
68+
seq_number: u32
69+
}
70+
71+
impl Incoming {
72+
/// Return the local endpoint.
73+
pub fn local_end(&self) -> IpEndpoint {
74+
self.local_end
75+
}
76+
77+
/// Return the remote endpoint.
78+
pub fn remote_end(&self) -> IpEndpoint {
79+
self.remote_end
80+
}
81+
}
82+
83+
/// A Transmission Control Protocol server socket.
84+
#[derive(Debug)]
85+
pub struct Listener<'a> {
86+
endpoint: IpEndpoint,
87+
backlog: Managed<'a, [Option<Incoming>]>,
88+
accept_at: usize,
89+
length: usize
90+
}
91+
92+
impl<'a> Listener<'a> {
93+
/// Create a server socket with the given backlog.
94+
pub fn new<T>(endpoint: IpEndpoint, backlog: T) -> Socket<'a, 'static>
95+
where T: Into<Managed<'a, [Option<Incoming>]>> {
96+
Socket::TcpServer(Listener {
97+
endpoint: endpoint,
98+
backlog: backlog.into(),
99+
accept_at: 0,
100+
length: 0
101+
})
102+
}
103+
104+
/// Accept a connection from this server socket,
105+
pub fn accept(&mut self) -> Option<Incoming> {
106+
if self.length == 0 { return None }
107+
108+
let accept_at = self.accept_at;
109+
self.accept_at = (self.accept_at + 1) % self.backlog.len();
110+
self.length -= 1;
111+
112+
self.backlog[accept_at].take()
113+
}
114+
115+
/// See [Socket::collect](enum.Socket.html#method.collect).
116+
pub fn collect(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress,
117+
protocol: IpProtocol, payload: &[u8])
118+
-> Result<(), Error> {
119+
if protocol != IpProtocol::Tcp { return Err(Error::Rejected) }
120+
121+
let packet = try!(TcpPacket::new(payload));
122+
let repr = try!(TcpRepr::parse(&packet, src_addr, dst_addr));
123+
124+
if repr.dst_port != self.endpoint.port { return Err(Error::Rejected) }
125+
if !self.endpoint.addr.is_unspecified() {
126+
if self.endpoint.addr != *dst_addr { return Err(Error::Rejected) }
127+
}
128+
129+
match (repr.control, repr.ack_number) {
130+
(TcpControl::Syn, None) => {
131+
if self.length == self.backlog.len() { return Err(Error::Exhausted) }
132+
133+
let inject_at = (self.accept_at + self.length) % self.backlog.len();
134+
self.length += 1;
135+
136+
assert!(self.backlog[inject_at].is_none());
137+
self.backlog[inject_at] = Some(Incoming {
138+
local_end: IpEndpoint::new(*dst_addr, repr.dst_port),
139+
remote_end: IpEndpoint::new(*src_addr, repr.src_port),
140+
seq_number: repr.seq_number
141+
});
142+
Ok(())
143+
}
144+
_ => Err(Error::Rejected)
145+
}
146+
}
147+
}
148+
59149
#[cfg(test)]
60150
mod test {
61151
use super::*;

‎src/socket/udp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<'a> PacketBuffer<'a> {
1717
pub fn new<T>(payload: T) -> PacketBuffer<'a>
1818
where T: Into<Managed<'a, [u8]>> {
1919
PacketBuffer {
20-
endpoint: IpEndpoint::INVALID,
20+
endpoint: IpEndpoint::UNSPECIFIED,
2121
size: 0,
2222
payload: payload.into()
2323
}

‎src/wire/ip.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ impl fmt::Display for Protocol {
2525
/// An internetworking address.
2626
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
2727
pub enum Address {
28-
/// An invalid address.
28+
/// An unspecified address.
2929
/// May be used as a placeholder for storage where the address is not assigned yet.
30-
Invalid,
30+
Unspecified,
3131
/// An IPv4 address.
3232
Ipv4(Ipv4Address)
3333
}
@@ -41,23 +41,23 @@ impl Address {
4141
/// Query whether the address is a valid unicast address.
4242
pub fn is_unicast(&self) -> bool {
4343
match self {
44-
&Address::Invalid => false,
45-
&Address::Ipv4(addr) => addr.is_unicast()
44+
&Address::Unspecified => false,
45+
&Address::Ipv4(addr) => addr.is_unicast()
4646
}
4747
}
4848

4949
/// Query whether the address falls into the "unspecified" range.
5050
pub fn is_unspecified(&self) -> bool {
5151
match self {
52-
&Address::Invalid => false,
53-
&Address::Ipv4(addr) => addr.is_unspecified()
52+
&Address::Unspecified => true,
53+
&Address::Ipv4(addr) => addr.is_unspecified()
5454
}
5555
}
5656
}
5757

5858
impl Default for Address {
5959
fn default() -> Address {
60-
Address::Invalid
60+
Address::Unspecified
6161
}
6262
}
6363

@@ -70,8 +70,8 @@ impl From<Ipv4Address> for Address {
7070
impl fmt::Display for Address {
7171
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7272
match self {
73-
&Address::Invalid => write!(f, "(invalid)"),
74-
&Address::Ipv4(addr) => write!(f, "{}", addr)
73+
&Address::Unspecified => write!(f, "*"),
74+
&Address::Ipv4(addr) => write!(f, "{}", addr)
7575
}
7676
}
7777
}
@@ -84,7 +84,7 @@ pub struct Endpoint {
8484
}
8585

8686
impl Endpoint {
87-
pub const INVALID: Endpoint = Endpoint { addr: Address::Invalid, port: 0 };
87+
pub const UNSPECIFIED: Endpoint = Endpoint { addr: Address::Unspecified, port: 0 };
8888

8989
/// Create an endpoint address from given address and port.
9090
pub fn new(addr: Address, port: u16) -> Endpoint {

0 commit comments

Comments
 (0)
Please sign in to comment.