Implement the userspace side of TCP sockets.

v0.7.x
whitequark 2016-12-26 14:50:12 +00:00
parent 0e20ea9205
commit a8b4ed2deb
4 changed files with 81 additions and 14 deletions

View File

@ -106,7 +106,8 @@ cargo run --example smoltcpserver -- tap0
It responds to:
* pings (`ping 192.168.69.1`),
* UDP packets on port 6969 (`socat stdio udp4-connect:192.168.69.1:6969 <<<"abcdefg"`).
* UDP packets on port 6969 (`socat stdio udp4-connect:192.168.69.1:6969 <<<"abcdefg"`),
* TCP packets on port 6969 (`socat stdio tcp4-connect:192.168.69.1:6969 <<<"abcdefg"`),
License
-------

View File

@ -56,29 +56,42 @@ fn main() {
loop {
match iface.poll() {
Ok(()) => (),
Err(e) => debug!("error {}", e)
Err(e) => debug!("poll error: {}", e)
}
{
let udp_socket: &mut UdpSocket = iface.sockets()[0].as_socket();
let udp_client = match udp_socket.recv() {
let socket: &mut UdpSocket = iface.sockets()[0].as_socket();
let client = match socket.recv() {
Ok((endpoint, data)) => {
debug!("data {:?} from {}", data, endpoint);
debug!("udp recv data: {:?} from {}", data, endpoint);
Some(endpoint)
}
Err(Error::Exhausted) => {
None
}
Err(e) => {
debug!("error {}", e);
debug!("udp recv error: {}", e);
None
}
};
if let Some(endpoint) = udp_client {
udp_socket.send_slice(endpoint, "hihihi".as_bytes()).unwrap()
if let Some(endpoint) = client {
socket.send_slice(endpoint, b"yo dawg").unwrap()
}
}
let _tcp_socket: &mut TcpSocket = iface.sockets()[1].as_socket();
{
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: {:?}", &data[..]);
data = data.split(|&b| b == b'\n').next().unwrap().to_owned();
data.reverse();
data.extend(b"\n");
}
data
};
socket.send_slice(data.as_ref());
}
}
}

View File

@ -244,6 +244,59 @@ impl<'a> TcpSocket<'a> {
self.set_state(State::Listen);
}
/// Enqueue a sequence of octets to be sent, and return a pointer to it.
///
/// This function may return a slice smaller than the requested size in case
/// there is not enough contiguous free space in the transmit buffer, down to
/// an empty slice.
pub fn send(&mut self, size: usize) -> &mut [u8] {
let buffer = self.tx_buffer.enqueue(size);
if buffer.len() > 0 {
net_trace!("tcp:{}:{}: buffer to send {} octets",
self.local_endpoint, self.remote_endpoint, buffer.len());
}
buffer
}
/// Enqueue a sequence of octets to be sent, and fill it from a slice.
///
/// This function returns the amount of bytes actually enqueued, which is limited
/// by the amount of free space in the transmit buffer; down to zero.
///
/// See also [send](#method.send).
pub fn send_slice(&mut self, data: &[u8]) -> usize {
let buffer = self.send(data.len());
buffer.copy_from_slice(data);
buffer.len()
}
/// Dequeue a sequence of received octets, and return a pointer to it.
///
/// This function may return a slice smaller than the requested size in case
/// there are not enough octets queued in the receive buffer, down to
/// an empty slice.
pub fn recv(&mut self, size: usize) -> &[u8] {
let buffer = self.rx_buffer.dequeue(size);
self.remote_seq_no += buffer.len() as i32;
if buffer.len() > 0 {
net_trace!("tcp:{}:{}: receive {} buffered octets",
self.local_endpoint, self.remote_endpoint, buffer.len());
}
buffer
}
/// Dequeue a sequence of received octets, and fill a slice from it.
///
/// This function returns the amount of bytes actually dequeued, which is limited
/// by the amount of free space in the transmit buffer; down to zero.
///
/// See also [recv](#method.recv).
pub fn recv_slice(&mut self, data: &mut [u8]) -> usize {
let buffer = self.recv(data.len());
data[..buffer.len()].copy_from_slice(buffer);
buffer.len()
}
/// See [Socket::collect](enum.Socket.html#method.collect).
pub fn collect(&mut self, ip_repr: &IpRepr, payload: &[u8]) -> Result<(), Error> {
if ip_repr.protocol() != IpProtocol::Tcp { return Err(Error::Rejected) }

View File

@ -131,12 +131,12 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
let packet_buf = try!(self.tx_buffer.enqueue());
packet_buf.endpoint = endpoint;
packet_buf.size = size;
net_trace!("udp:{}:{}: send {} octets",
net_trace!("udp:{}:{}: buffer to send {} octets",
self.endpoint, packet_buf.endpoint, packet_buf.size);
Ok(&mut packet_buf.as_mut()[..size])
}
/// Enqueue a packete to be sent to a given remote endpoint, and fill it from a slice.
/// Enqueue a packet to be sent to a given remote endpoint, and fill it from a slice.
///
/// See also [send](#method.send).
pub fn send_slice(&mut self, endpoint: IpEndpoint, data: &[u8]) -> Result<(), Error> {
@ -150,7 +150,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
/// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
pub fn recv(&mut self) -> Result<(IpEndpoint, &[u8]), Error> {
let packet_buf = try!(self.rx_buffer.dequeue());
net_trace!("udp:{}:{}: recv {} octets",
net_trace!("udp:{}:{}: receive {} buffered octets",
self.endpoint, packet_buf.endpoint, packet_buf.size);
Ok((packet_buf.endpoint, &packet_buf.as_ref()[..packet_buf.size]))
}
@ -183,7 +183,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
packet_buf.endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port };
packet_buf.size = repr.payload.len();
packet_buf.as_mut()[..repr.payload.len()].copy_from_slice(repr.payload);
net_trace!("udp:{}:{}: collect {} octets",
net_trace!("udp:{}:{}: receiving {} octets",
self.endpoint, packet_buf.endpoint, packet_buf.size);
Ok(())
}
@ -192,7 +192,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
pub fn dispatch<F, R>(&mut self, emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
let packet_buf = try!(self.tx_buffer.dequeue());
net_trace!("udp:{}:{}: dispatch {} octets",
net_trace!("udp:{}:{}: sending {} octets",
self.endpoint, packet_buf.endpoint, packet_buf.size);
let ip_repr = IpRepr::Unspecified {
src_addr: self.endpoint.addr,