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: 37f565abe2cd
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: c7492b3b51e6
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Dec 18, 2016

  1. Copy the full SHA
    b56fb85 View commit details
  2. Copy the full SHA
    c7492b3 View commit details
Showing with 92 additions and 17 deletions.
  1. +3 −3 examples/smoltcpserver.rs
  2. +4 −1 src/socket/mod.rs
  3. +74 −0 src/socket/tcp.rs
  4. +11 −13 src/socket/udp.rs
6 changes: 3 additions & 3 deletions examples/smoltcpserver.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use smoltcp::Error;
use smoltcp::phy::{Tracer, TapInterface};
use smoltcp::wire::{EthernetFrame, EthernetAddress, InternetAddress, InternetEndpoint};
use smoltcp::iface::{SliceArpCache, EthernetInterface};
use smoltcp::socket::{UdpSocket, AsSocket, UdpBuffer, UdpBufferElem};
use smoltcp::socket::{UdpSocket, AsSocket, UdpBuffer, UdpPacket};

fn main() {
let ifname = env::args().nth(1).unwrap();
@@ -21,8 +21,8 @@ fn main() {
let listen_address = InternetAddress::ipv4([0, 0, 0, 0]);
let endpoint = InternetEndpoint::new(listen_address, 6969);

let udp_rx_buffer = UdpBuffer::new(vec![UdpBufferElem::new(vec![0; 2048])]);
let udp_tx_buffer = UdpBuffer::new(vec![UdpBufferElem::new(vec![0; 2048])]);
let udp_rx_buffer = UdpBuffer::new(vec![UdpPacket::new(vec![0; 2048])]);
let udp_tx_buffer = UdpBuffer::new(vec![UdpPacket::new(vec![0; 2048])]);
let udp_socket = UdpSocket::new(endpoint, udp_rx_buffer, udp_tx_buffer);

let mut sockets = [udp_socket];
5 changes: 4 additions & 1 deletion src/socket/mod.rs
Original file line number Diff line number Diff line change
@@ -14,11 +14,14 @@ use Error;
use wire::{InternetAddress as Address, InternetProtocolType as ProtocolType};

mod udp;
mod tcp;

pub use self::udp::Packet as UdpPacket;
pub use self::udp::Buffer as UdpBuffer;
pub use self::udp::BufferElem as UdpBufferElem;
pub use self::udp::UdpSocket as UdpSocket;

pub use self::tcp::Buffer as TcpBuffer;

/// A packet representation.
///
/// This interface abstracts the various types of packets layered under the IP protocol,
74 changes: 74 additions & 0 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use Managed;

/// A TCP stream ring buffer.
#[derive(Debug)]
pub struct Buffer<'a> {
storage: Managed<'a, [u8]>,
read_at: usize,
length: usize
}

impl<'a> Buffer<'a> {
/// Create a packet buffer with the given storage.
pub fn new<T>(storage: T) -> Buffer<'a>
where T: Into<Managed<'a, [u8]>> {
Buffer {
storage: storage.into(),
read_at: 0,
length: 0
}
}

/// Enqueue a slice of octets up to the given size into the buffer, and return a pointer
/// to the slice.
///
/// The returned slice may be shorter than requested, as short as an empty slice,
/// if there is not enough contiguous free space in the buffer.
pub fn enqueue(&mut self, mut size: usize) -> &mut [u8] {
let write_at = (self.read_at + self.length) % self.storage.len();
// We can't enqueue more than there is free space.
let free = self.storage.len() - self.length;
if size > free { size = free }
// We can't contiguously enqueue past the beginning of the storage.
let until_end = self.storage.len() - write_at;
if size > until_end { size = until_end }

self.length += size;
&mut self.storage[write_at..write_at + size]
}

/// Dequeue a slice of octets up to the given size from the buffer, and return a pointer
/// to the slice.
///
/// The returned slice may be shorter than requested, as short as an empty slice,
/// if there is not enough contiguous filled space in the buffer.
pub fn dequeue(&mut self, mut size: usize) -> &[u8] {
let read_at = self.read_at;
// We can't dequeue more than was queued.
if size > self.length { size = self.length }
// We can't contiguously dequeue past the end of the storage.
let until_end = self.storage.len() - self.read_at;
if size > until_end { size = until_end }

self.read_at = (self.read_at + size) % self.storage.len();
self.length -= size;
&self.storage[read_at..read_at + size]
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_buffer() {
let mut buffer = Buffer::new(vec![0; 8]); // ........
buffer.enqueue(6).copy_from_slice(b"foobar"); // foobar..
assert_eq!(buffer.dequeue(3), b"foo"); // ...bar..
buffer.enqueue(6).copy_from_slice(b"ba"); // ...barba
buffer.enqueue(4).copy_from_slice(b"zho"); // zhobarba
assert_eq!(buffer.dequeue(6), b"barba"); // zho.....
assert_eq!(buffer.dequeue(8), b"zho"); // ........
buffer.enqueue(8).copy_from_slice(b"gefug"); // ...gefug
}
}
24 changes: 11 additions & 13 deletions src/socket/udp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::borrow::BorrowMut;

use Error;
use Managed;
use wire::{InternetAddress as Address, InternetProtocolType as ProtocolType};
@@ -9,17 +7,17 @@ use socket::{Socket, PacketRepr};

/// A buffered UDP packet.
#[derive(Debug)]
pub struct BufferElem<'a> {
pub struct Packet<'a> {
endpoint: Endpoint,
size: usize,
payload: Managed<'a, [u8]>
}

impl<'a> BufferElem<'a> {
impl<'a> Packet<'a> {
/// Create a buffered packet.
pub fn new<T>(payload: T) -> BufferElem<'a>
pub fn new<T>(payload: T) -> Packet<'a>
where T: Into<Managed<'a, [u8]>> {
BufferElem {
Packet {
endpoint: Endpoint::INVALID,
size: 0,
payload: payload.into()
@@ -35,18 +33,18 @@ impl<'a> BufferElem<'a> {
}
}

/// An UDP packet buffer.
/// An UDP packet ring buffer.
#[derive(Debug)]
pub struct Buffer<'a, 'b: 'a> {
storage: Managed<'a, [BufferElem<'b>]>,
storage: Managed<'a, [Packet<'b>]>,
read_at: usize,
length: usize
}

impl<'a, 'b> Buffer<'a, 'b> {
/// Create a packet buffer with the given storage.
pub fn new<T>(storage: T) -> Buffer<'a, 'b>
where T: Into<Managed<'a, [BufferElem<'b>]>> {
where T: Into<Managed<'a, [Packet<'b>]>> {
let mut storage = storage.into();
for elem in storage.iter_mut() {
elem.endpoint = Default::default();
@@ -78,20 +76,20 @@ impl<'a, 'b> Buffer<'a, 'b> {

/// Enqueue an element into the buffer, and return a pointer to it, or return
/// `Err(Error::Exhausted)` if the buffer is full.
pub fn enqueue(&mut self) -> Result<&mut BufferElem<'b>, Error> {
pub fn enqueue(&mut self) -> Result<&mut Packet<'b>, Error> {
if self.full() {
Err(Error::Exhausted)
} else {
let index = self.mask(self.read_at + self.length);
let result = &mut self.storage.borrow_mut()[index];
let result = &mut self.storage[index];
self.length += 1;
Ok(result)
}
}

/// Dequeue an element from the buffer, and return a pointer to it, or return
/// `Err(Error::Exhausted)` if the buffer is empty.
pub fn dequeue(&mut self) -> Result<&BufferElem<'b>, Error> {
pub fn dequeue(&mut self) -> Result<&Packet<'b>, Error> {
if self.empty() {
Err(Error::Exhausted)
} else {
@@ -221,7 +219,7 @@ mod test {
pub fn test_buffer() {
let mut storage = vec![];
for _ in 0..5 {
storage.push(BufferElem::new(vec![0]))
storage.push(Packet::new(vec![0]))
}
let mut buffer = Buffer::new(&mut storage[..]);