Browse Source

Reimplement {RawSocket,TapInterface}::receive correctly.

whitequark 7 years ago
parent
commit
f239e36bf3
3 changed files with 38 additions and 28 deletions
  1. 3 0
      examples/tcpdump.rs
  2. 17 10
      src/phy/raw_socket.rs
  3. 18 18
      src/phy/tap_interface.rs

+ 3 - 0
examples/tcpdump.rs

@@ -1,6 +1,8 @@
 extern crate smoltcp;
 
 use std::env;
+use std::os::unix::io::AsRawFd;
+use smoltcp::phy::wait as phy_wait;
 use smoltcp::phy::{Device, RxToken, RawSocket};
 use smoltcp::wire::{PrettyPrinter, EthernetFrame};
 
@@ -8,6 +10,7 @@ fn main() {
     let ifname = env::args().nth(1).unwrap();
     let mut socket = RawSocket::new(ifname.as_ref()).unwrap();
     loop {
+        phy_wait(socket.as_raw_fd(), None).unwrap();
         let (rx_token, _) = socket.receive().unwrap();
         rx_token.consume(/*timestamp = */ 0, |buffer| {
             print!("{}", PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &buffer));

+ 17 - 10
src/phy/raw_socket.rs

@@ -1,4 +1,5 @@
 use std::cell::RefCell;
+use std::vec::Vec;
 use std::rc::Rc;
 use std::io;
 use std::os::unix::io::{RawFd, AsRawFd};
@@ -47,9 +48,20 @@ impl<'a> Device<'a> for RawSocket {
     }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let rx = RxToken { lower: self.lower.clone(), mtu: self.mtu };
-        let tx = TxToken { lower: self.lower.clone() };
-        Some((rx, tx))
+        let mut lower = self.lower.borrow_mut();
+        let mut buffer = vec![0; self.mtu];
+        match lower.recv(&mut buffer[..]) {
+            Ok(size) => {
+                buffer.resize(size, 0);
+                let rx = RxToken { buffer };
+                let tx = TxToken { lower: self.lower.clone() };
+                Some((rx, tx))
+            }
+            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
+                None
+            }
+            Err(err) => panic!("{}", err)
+        }
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
@@ -61,17 +73,12 @@ impl<'a> Device<'a> for RawSocket {
 
 #[doc(hidden)]
 pub struct RxToken {
-    lower:  Rc<RefCell<sys::RawSocketDesc>>,
-    mtu:    usize,
+    buffer: Vec<u8>
 }
 
 impl phy::RxToken for RxToken {
     fn consume<R, F: FnOnce(&[u8]) -> Result<R>>(self, _timestamp: u64, f: F) -> Result<R> {
-        let mut lower = self.lower.borrow_mut();
-        let mut buffer = vec![0; self.mtu];
-        let size = lower.recv(&mut buffer[..]).unwrap();
-        buffer.resize(size, 0);
-        f(&mut buffer)
+        f(&self.buffer[..])
     }
 }
 

+ 18 - 18
src/phy/tap_interface.rs

@@ -1,9 +1,10 @@
 use std::cell::RefCell;
+use std::vec::Vec;
 use std::rc::Rc;
 use std::io;
 use std::os::unix::io::{RawFd, AsRawFd};
 
-use {Error, Result};
+use Result;
 use phy::{self, sys, DeviceCapabilities, Device};
 
 /// A virtual Ethernet interface.
@@ -48,9 +49,20 @@ impl<'a> Device<'a> for TapInterface {
     }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let rx = RxToken { lower: self.lower.clone(), mtu: self.mtu };
-        let tx = TxToken { lower: self.lower.clone(), };
-        Some((rx, tx))
+        let mut lower = self.lower.borrow_mut();
+        let mut buffer = vec![0; self.mtu];
+        match lower.recv(&mut buffer[..]) {
+            Ok(size) => {
+                buffer.resize(size, 0);
+                let rx = RxToken { buffer };
+                let tx = TxToken { lower: self.lower.clone() };
+                Some((rx, tx))
+            }
+            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
+                None
+            }
+            Err(err) => panic!("{}", err)
+        }
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
@@ -62,26 +74,14 @@ impl<'a> Device<'a> for TapInterface {
 
 #[doc(hidden)]
 pub struct RxToken {
-    lower: Rc<RefCell<sys::TapInterfaceDesc>>,
-    mtu:   usize,
+    buffer: Vec<u8>
 }
 
 impl phy::RxToken for RxToken {
     fn consume<R, F>(self, _timestamp: u64, f: F) -> Result<R>
         where F: FnOnce(&[u8]) -> Result<R>
     {
-        let mut lower = self.lower.borrow_mut();
-        let mut buffer = vec![0; self.mtu];
-        match lower.recv(&mut buffer[..]) {
-            Ok(size) => {
-                buffer.resize(size, 0);
-                f(&buffer)
-            }
-            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
-                Err(Error::Exhausted)
-            }
-            Err(err) => panic!("{}", err)
-        }
+        f(&self.buffer[..])
     }
 }