redox/schemes/ethernetd/src/resource.rs
Jeremy Soller 224c43f761 Orbital (#16)
* Port previous ethernet scheme

* Add ipd

* Fix initfs rebuilds, use QEMU user networking addresses in ipd

* Add tcp/udp, netutils, dns, and network config

* Add fsync to network driver

* Add dns, router, subnet by default

* Fix e1000 driver. Make ethernet and IP non-blocking to avoid deadlocks

* Add orbital server, WIP

* Add futex

* Add orbutils and orbital

* Update libstd, orbutils, and orbital
Move ANSI key encoding to vesad

* Add orbital assets

* Update orbital

* Update to add login manager

* Add blocking primitives, block for most things except waitpid, update orbital

* Wait in waitpid and IRQ, improvements for other waits

* Fevent in root scheme

* WIP: Switch to using fevent

* Reorganize

* Event based e1000d driver

* Superuser-only access to some network schemes, display, and disk

* Superuser root and irq schemes

* Fix orbital
2016-10-13 17:21:42 -06:00

98 lines
2.8 KiB
Rust

use std::{cmp, mem};
use resource_scheme::Resource;
use syscall;
use syscall::error::*;
use common::{n16, MacAddr, EthernetIIHeader, EthernetII};
/// A ethernet resource
pub struct EthernetResource {
/// The network
pub network: usize,
/// The data
pub data: Vec<u8>,
/// The MAC addresss
pub peer_addr: MacAddr,
/// The ethernet type
pub ethertype: u16,
}
impl Resource for EthernetResource {
fn dup(&self) -> Result<Box<Self>> {
let network = try!(syscall::dup(self.network));
Ok(Box::new(EthernetResource {
network: network,
data: self.data.clone(),
peer_addr: self.peer_addr,
ethertype: self.ethertype,
}))
}
fn path(&self, buf: &mut [u8]) -> Result<usize> {
let path_string = format!("ethernet:{}/{:X}", self.peer_addr.to_string(), self.ethertype);
let path = path_string.as_bytes();
for (b, p) in buf.iter_mut().zip(path.iter()) {
*b = *p;
}
Ok(cmp::min(buf.len(), path.len()))
}
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if !self.data.is_empty() {
let mut data: Vec<u8> = Vec::new();
mem::swap(&mut self.data, &mut data);
for (b, d) in buf.iter_mut().zip(data.iter()) {
*b = *d;
}
return Ok(cmp::min(buf.len(), data.len()));
}
let mut bytes = [0; 65536];
let count = try!(syscall::read(self.network, &mut bytes));
if let Some(frame) = EthernetII::from_bytes(&bytes[..count]) {
if frame.header.ethertype.get() == self.ethertype {
for (b, d) in buf.iter_mut().zip(frame.data.iter()) {
*b = *d;
}
return Ok(cmp::min(buf.len(), frame.data.len()));
}
}
Ok(0)
}
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let data = Vec::from(buf);
match syscall::write(self.network, &EthernetII {
header: EthernetIIHeader {
src: MacAddr { bytes: [0x50, 0x51, 0x52, 0x53, 0x54, 0x55] },
dst: self.peer_addr,
ethertype: n16::new(self.ethertype),
},
data: data,
}
.to_bytes()) {
Ok(_) => Ok(buf.len()),
Err(err) => Err(err),
}
}
fn sync(&mut self) -> Result<usize> {
syscall::fsync(self.network)
}
}
impl Drop for EthernetResource {
fn drop(&mut self) {
let _ = syscall::close(self.network);
}
}