Documentation run on schemes/ipd. (#18)
* Documentation run on schemes/ipd. * Update main.rs * Update resource.rs
This commit is contained in:
parent
3634afe549
commit
35696f4169
|
@ -1,5 +1,24 @@
|
||||||
#![feature(rand)]
|
#![feature(rand)]
|
||||||
|
|
||||||
|
//! Implementation of the IP Scheme as a userland driver.
|
||||||
|
//!
|
||||||
|
//! # Role
|
||||||
|
//!
|
||||||
|
//! See https://en.wikipedia.org/wiki/Internet_Protocol for more details about the
|
||||||
|
//! IP protocol. Clients will often prefer using either higher-level protocols TCP
|
||||||
|
//! or UDP, both of which are built upon IP.
|
||||||
|
//!
|
||||||
|
//! # URL Syntax
|
||||||
|
//!
|
||||||
|
//! To open a IP connection, use `ip:[host]/protocol`.
|
||||||
|
//!
|
||||||
|
//! * If `host` is specified, it must be an ipv4 number (e.g. `192.168.0.1`)
|
||||||
|
//! and the connection may be used immediately to send/receive data.
|
||||||
|
//! * If `host` is omitted, this connectino will wait for a distant peer to
|
||||||
|
//! connect.
|
||||||
|
//! * The `protocol` is the hex-based number of the ip protocol
|
||||||
|
//! (see http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).
|
||||||
|
|
||||||
extern crate netutils;
|
extern crate netutils;
|
||||||
extern crate resource_scheme;
|
extern crate resource_scheme;
|
||||||
extern crate syscall;
|
extern crate syscall;
|
||||||
|
|
|
@ -5,22 +5,48 @@ use resource_scheme::Resource;
|
||||||
use syscall;
|
use syscall;
|
||||||
use syscall::error::*;
|
use syscall::error::*;
|
||||||
|
|
||||||
/// A IP (internet protocole) resource
|
/// A IP (internet protocol) resource.
|
||||||
|
///
|
||||||
|
/// Each instance represents a connection (~ a IP socket).
|
||||||
pub struct IpResource {
|
pub struct IpResource {
|
||||||
|
/// Link to the underlying device (typically, an Ethernet card).
|
||||||
pub link: usize,
|
pub link: usize,
|
||||||
pub data: Vec<u8>,
|
|
||||||
|
/// If this connection was opened waiting for a peer (i.e. `ip:/protocol`),
|
||||||
|
/// the data received when the peer actually connected. Otherwise, empty.
|
||||||
|
/// Emptied during the first call to `read()`.
|
||||||
|
pub init_data: Vec<u8>,
|
||||||
|
|
||||||
|
/// The IP address of the host (i.e. this machine).
|
||||||
pub host_addr: Ipv4Addr,
|
pub host_addr: Ipv4Addr,
|
||||||
|
|
||||||
|
/// The IP address of the peer (i.e. the other machine).
|
||||||
pub peer_addr: Ipv4Addr,
|
pub peer_addr: Ipv4Addr,
|
||||||
|
|
||||||
|
/// The IP protocol used by this connection. See
|
||||||
|
/// http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
|
||||||
|
/// for the list of valid protocols.
|
||||||
pub proto: u8,
|
pub proto: u8,
|
||||||
|
|
||||||
|
/// The id of the next packet being sent.
|
||||||
|
/// See https://en.wikipedia.org/wiki/IPv4#Identification .
|
||||||
pub id: u16,
|
pub id: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for IpResource {
|
impl Resource for IpResource {
|
||||||
|
/// Duplicate the connection.
|
||||||
|
///
|
||||||
|
/// This duplicates both `self.link` and `self.init_data`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Fails if the `link` to the underlying device cannot be
|
||||||
|
/// duplicated.
|
||||||
fn dup(&self) -> Result<Box<Self>> {
|
fn dup(&self) -> Result<Box<Self>> {
|
||||||
let link = try!(syscall::dup(self.link));
|
let link = try!(syscall::dup(self.link));
|
||||||
Ok(Box::new(IpResource {
|
Ok(Box::new(IpResource {
|
||||||
link: link,
|
link: link,
|
||||||
data: self.data.clone(),
|
init_data: self.init_data.clone(),
|
||||||
host_addr: self.host_addr,
|
host_addr: self.host_addr,
|
||||||
peer_addr: self.peer_addr,
|
peer_addr: self.peer_addr,
|
||||||
proto: self.proto,
|
proto: self.proto,
|
||||||
|
@ -28,6 +54,12 @@ impl Resource for IpResource {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current path, as `ip:peer/protocol`, where `peer`
|
||||||
|
/// is the IPv4 address of the peer and `protocol` is the hex-based
|
||||||
|
/// number of the IP protocol used.
|
||||||
|
///
|
||||||
|
/// Note that the `peer` is specified even if the connection was initially
|
||||||
|
/// created as `ip:/protocol`.
|
||||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let path_string = format!("ip:{}/{:X}", self.peer_addr.to_string(), self.proto);
|
let path_string = format!("ip:{}/{:X}", self.peer_addr.to_string(), self.proto);
|
||||||
let path = path_string.as_bytes();
|
let path = path_string.as_bytes();
|
||||||
|
@ -39,10 +71,21 @@ impl Resource for IpResource {
|
||||||
Ok(cmp::min(buf.len(), path.len()))
|
Ok(cmp::min(buf.len(), path.len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read data from the device.
|
||||||
|
///
|
||||||
|
/// If some data has already been made available during the establishment
|
||||||
|
/// of the connection, this data is (entirely) read during the first call
|
||||||
|
/// to `read()`, without attempting to actually read from the device. This
|
||||||
|
/// can happen only if the connection was waiting for a remote peer to connect, i.e.
|
||||||
|
/// with a url `ip:/protocol`, without host.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Fails if the call to `syscall::read()` fails for this device.
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||||
if !self.data.is_empty() {
|
if !self.init_data.is_empty() {
|
||||||
let mut data: Vec<u8> = Vec::new();
|
let mut data: Vec<u8> = Vec::new();
|
||||||
mem::swap(&mut self.data, &mut data);
|
mem::swap(&mut self.init_data, &mut data);
|
||||||
|
|
||||||
for (b, d) in buf.iter_mut().zip(data.iter()) {
|
for (b, d) in buf.iter_mut().zip(data.iter()) {
|
||||||
*b = *d;
|
*b = *d;
|
||||||
|
@ -69,6 +112,11 @@ impl Resource for IpResource {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send data to the peer.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Fails if the call to `syscall::write()` fails for this device.
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||||
let ip_data = Vec::from(buf);
|
let ip_data = Vec::from(buf);
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
||||||
if let Ok(link) = syscall::open(&format!("ethernet:{}/800", &route_mac.to_string()), O_RDWR) {
|
if let Ok(link) = syscall::open(&format!("ethernet:{}/800", &route_mac.to_string()), O_RDWR) {
|
||||||
return Ok(Box::new(IpResource {
|
return Ok(Box::new(IpResource {
|
||||||
link: link,
|
link: link,
|
||||||
data: Vec::new(),
|
init_data: Vec::new(),
|
||||||
host_addr: ip_addr,
|
host_addr: ip_addr,
|
||||||
peer_addr: peer_addr,
|
peer_addr: peer_addr,
|
||||||
proto: proto,
|
proto: proto,
|
||||||
|
@ -127,6 +127,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
||||||
} else {
|
} else {
|
||||||
while let Ok(link) = syscall::open("ethernet:/800", O_RDWR) {
|
while let Ok(link) = syscall::open("ethernet:/800", O_RDWR) {
|
||||||
let mut bytes = [0; 65536];
|
let mut bytes = [0; 65536];
|
||||||
|
// FIXME: Blocking call?
|
||||||
match syscall::read(link, &mut bytes) {
|
match syscall::read(link, &mut bytes) {
|
||||||
Ok(count) => {
|
Ok(count) => {
|
||||||
if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
|
if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
|
||||||
|
@ -134,7 +135,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
||||||
(packet.header.dst.equals(ip_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) {
|
(packet.header.dst.equals(ip_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) {
|
||||||
return Ok(Box::new(IpResource {
|
return Ok(Box::new(IpResource {
|
||||||
link: link,
|
link: link,
|
||||||
data: packet.data,
|
init_data: packet.data,
|
||||||
host_addr: ip_addr,
|
host_addr: ip_addr,
|
||||||
peer_addr: packet.header.src,
|
peer_addr: packet.header.src,
|
||||||
proto: proto,
|
proto: proto,
|
||||||
|
|
Loading…
Reference in a new issue