├── .gitignore ├── Cargo.toml ├── README.md ├── cyclic_order ├── Cargo.toml └── src │ ├── impls.rs │ ├── lib.rs │ └── linked_list.rs ├── data_link ├── interface │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── udp_mock │ ├── Cargo.toml │ ├── src │ └── lib.rs │ └── tests │ └── two-node.rs ├── misc ├── Cargo.toml └── src │ ├── interface.rs │ ├── lib.rs │ └── state_machine.rs ├── network ├── Cargo.toml ├── src │ ├── ipv4 │ │ ├── control.rs │ │ ├── mod.rs │ │ ├── packet.rs │ │ ├── receive.rs │ │ ├── send.rs │ │ └── strategy.rs │ └── lib.rs └── tests │ └── ipv4.rs └── transport ├── brown_rip ├── Cargo.toml └── src │ ├── comm.rs │ ├── lib.rs │ ├── packet.rs │ └── periodic.rs ├── static_routing ├── Cargo.toml └── src │ └── lib.rs └── tcp ├── Cargo.toml └── src ├── access.rs ├── capability ├── c.rs ├── l.rs └── mod.rs ├── concurrent_hash_map.rs ├── connection ├── established │ ├── mod.rs │ └── tcb │ │ ├── mod.rs │ │ └── timer │ │ └── mod.rs ├── handshaking.rs ├── manager │ ├── packet_buffer.rs │ ├── recv.rs │ └── send.rs ├── mod.rs ├── packet_buf │ ├── dummy.rs │ ├── mod.rs │ ├── ring.rs │ └── vec_queue.rs ├── syn_received.rs └── timer.rs ├── lib.rs ├── listener.rs ├── packet.rs ├── receive.rs ├── ring_buf.rs ├── send.rs └── trace.rs /.gitignore: -------------------------------------------------------------------------------- 1 | reference 2 | data 3 | tools 4 | 5 | Cargo.lock 6 | /target 7 | 8 | # vim tempfiles 9 | *.swp 10 | 11 | # emacs tempfiles 12 | \#* 13 | \#*\# 14 | 15 | # misc 16 | *~ 17 | .#* 18 | 19 | # generated test data 20 | *.lnx 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | # misc prereqs 5 | "cyclic_order", 6 | "misc", 7 | 8 | # data link layer 9 | "data_link/interface", 10 | "data_link/udp_mock", 11 | 12 | # network layer 13 | "network", 14 | 15 | # transport layer (and ip routing) 16 | "transport/brown_rip", 17 | "transport/static_routing", 18 | "transport/tcp", 19 | ] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QuiltNet 2 | ================================================================================ 3 | 4 | A network stack in pure Rust designed from the ground up for both asynchronous and synchronous usage. 5 | 6 | Libraries 7 | -------------------------------------------------------------------------------- 8 | 9 | ``` 10 | / 11 | ├── cyclic_order -- Generic Code used for keeping track of out-of-order 12 | │ packets in TCP. Should be stable enough to move out of 13 | │ tree. 14 | ├── misc -- Some random crap used by everything else. 15 | ├── data_link 16 | │ ├── interface -- Presents the Interface link-layer drivers should 17 | │ │ implement to work with the Network Layer. 18 | │ └── udp_mock -- A mock link-layer driver built on UDP. (Requires 19 | │ libstd.) 20 | ├── network -- Currently Just IPv4. Should contain a interface, and 21 | │ IPv4 and Ipv6 implementations. 22 | └── transport 23 | ├── brown_rip -- A modified/simplified RIP, implemented on top of IPv4 24 | │ instead of UDP. 25 | ├── static_routing -- A dummy routing package that learns no routes -- You 26 | │ can only talk to immediate neighbors. 27 | └── tcp -- Currently incomplete. 28 | ``` 29 | -------------------------------------------------------------------------------- /cyclic_order/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "cyclic-order" 4 | version = "0.0.1" 5 | authors = [ "John Ericson " ] 6 | 7 | [lib] 8 | name = "cyclic_order" 9 | 10 | [dev-dependencies.quickcheck_macros] 11 | git = "https://github.com/BurntSushi/quickcheck" 12 | -------------------------------------------------------------------------------- /cyclic_order/src/impls.rs: -------------------------------------------------------------------------------- 1 | use std::num::UnsignedInt; 2 | 3 | use super::*; 4 | use super::CyclicOrdering::{ 5 | Clockwise, 6 | CounterClockwise, 7 | Degenerate 8 | }; 9 | 10 | impl PartialCyclicOrd for N where N: UnsignedInt + Ord 11 | { 12 | #[inline] 13 | fn is_clockwise(&self, them: &N, other: &N) -> bool 14 | { 15 | self.cyclic_cmp(them, other) == Clockwise 16 | } 17 | } 18 | 19 | impl CyclicOrd for N where N: UnsignedInt + Ord 20 | { 21 | #[inline] 22 | fn cyclic_cmp(&self, them: &N, other: &N) -> CyclicOrdering 23 | { 24 | if 25 | (self < them && them < other) || 26 | (them < other && other < self) || 27 | (other < self && self < them) 28 | { 29 | CyclicOrdering::Clockwise 30 | } 31 | else if 32 | (self > them && them > other) || 33 | (them > other && other > self) || 34 | (other > self && self > them) 35 | { 36 | CyclicOrdering::CounterClockwise 37 | } 38 | else { Degenerate } 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod partial_test { 44 | use partial_axioms::*; 45 | 46 | #[quickcheck] fn u8_cyclicity(a: u8, b: u8, c: u8) -> bool { cyclicity(&a, &b, &c) } 47 | #[quickcheck] fn u16_cyclicity(a: u16, b: u16, c: u16) -> bool { cyclicity(&a, &b, &c) } 48 | #[quickcheck] fn u32_cyclicity(a: u32, b: u32, c: u32) -> bool { cyclicity(&a, &b, &c) } 49 | #[quickcheck] fn u64_cyclicity(a: u64, b: u64, c: u64) -> bool { cyclicity(&a, &b, &c) } 50 | #[quickcheck] fn usize_cyclicity(a: usize, b: usize, c: usize) -> bool { cyclicity(&a, &b, &c) } 51 | 52 | #[quickcheck] fn u8_antisymmetry(a: u8, b: u8, c: u8) -> bool { antisymmetry(&a, &b, &c) } 53 | #[quickcheck] fn u16_antisymmetry(a: u16, b: u16, c: u16) -> bool { antisymmetry(&a, &b, &c) } 54 | #[quickcheck] fn u32_antisymmetry(a: u32, b: u32, c: u32) -> bool { antisymmetry(&a, &b, &c) } 55 | #[quickcheck] fn u64_antisymmetry(a: u64, b: u64, c: u64) -> bool { antisymmetry(&a, &b, &c) } 56 | #[quickcheck] fn usize_antisymmetry(a: usize, b: usize, c: usize) -> bool { antisymmetry(&a, &b, &c) } 57 | 58 | #[quickcheck] fn u8_transitivity(a: u8, b: u8, c: u8, d: u8) -> bool { transitivity(&a, &b, &c, &d) } 59 | #[quickcheck] fn u16_transitivity(a: u16, b: u16, c: u16, d: u16) -> bool { transitivity(&a, &b, &c, &d) } 60 | #[quickcheck] fn u32_transitivity(a: u32, b: u32, c: u32, d: u32) -> bool { transitivity(&a, &b, &c, &d) } 61 | #[quickcheck] fn u64_transitivity(a: u64, b: u64, c: u64, d: u64) -> bool { transitivity(&a, &b, &c, &d) } 62 | #[quickcheck] fn usize_transitivity(a: usize, b: usize, c: usize, d: usize) -> bool { transitivity(&a, &b, &c, &d) } 63 | } 64 | 65 | #[cfg(test)] 66 | mod total_test { 67 | use total_axioms::*; 68 | 69 | #[quickcheck] fn u8_cyclicity(a: u8, b: u8, c: u8) -> bool { cyclicity(&a, &b, &c) } 70 | #[quickcheck] fn u16_cyclicity(a: u16, b: u16, c: u16) -> bool { cyclicity(&a, &b, &c) } 71 | #[quickcheck] fn u32_cyclicity(a: u32, b: u32, c: u32) -> bool { cyclicity(&a, &b, &c) } 72 | #[quickcheck] fn u64_cyclicity(a: u64, b: u64, c: u64) -> bool { cyclicity(&a, &b, &c) } 73 | #[quickcheck] fn usize_cyclicity(a: usize, b: usize, c: usize) -> bool { cyclicity(&a, &b, &c) } 74 | 75 | #[quickcheck] fn u8_antisymmetry(a: u8, b: u8, c: u8) -> bool { antisymmetry(&a, &b, &c) } 76 | #[quickcheck] fn u16_antisymmetry(a: u16, b: u16, c: u16) -> bool { antisymmetry(&a, &b, &c) } 77 | #[quickcheck] fn u32_antisymmetry(a: u32, b: u32, c: u32) -> bool { antisymmetry(&a, &b, &c) } 78 | #[quickcheck] fn u64_antisymmetry(a: u64, b: u64, c: u64) -> bool { antisymmetry(&a, &b, &c) } 79 | #[quickcheck] fn usize_antisymmetry(a: usize, b: usize, c: usize) -> bool { antisymmetry(&a, &b, &c) } 80 | 81 | #[quickcheck] fn u8_transitivity(a: u8, b: u8, c: u8, d: u8) -> bool { transitivity(&a, &b, &c, &d) } 82 | #[quickcheck] fn u16_transitivity(a: u16, b: u16, c: u16, d: u16) -> bool { transitivity(&a, &b, &c, &d) } 83 | #[quickcheck] fn u32_transitivity(a: u32, b: u32, c: u32, d: u32) -> bool { transitivity(&a, &b, &c, &d) } 84 | #[quickcheck] fn u64_transitivity(a: u64, b: u64, c: u64, d: u64) -> bool { transitivity(&a, &b, &c, &d) } 85 | #[quickcheck] fn usize_transitivity(a: usize, b: usize, c: usize, d: usize) -> bool { transitivity(&a, &b, &c, &d) } 86 | 87 | #[quickcheck] fn u8_totality(a: u8, b: u8, c: u8) -> bool { totality(&a, &b, &c) } 88 | #[quickcheck] fn u16_totality(a: u16, b: u16, c: u16) -> bool { totality(&a, &b, &c) } 89 | #[quickcheck] fn u32_totality(a: u32, b: u32, c: u32) -> bool { totality(&a, &b, &c) } 90 | #[quickcheck] fn u64_totality(a: u64, b: u64, c: u64) -> bool { totality(&a, &b, &c) } 91 | #[quickcheck] fn usize_totality(a: usize, b: usize, c: usize) -> bool { totality(&a, &b, &c) } 92 | 93 | #[quickcheck] fn u8_super_trait_cohesion(a: u8, b: u8, c: u8) -> bool { super_trait_cohesion(&a, &b, &c) } 94 | #[quickcheck] fn u16_super_trait_cohesion(a: u16, b: u16, c: u16) -> bool { super_trait_cohesion(&a, &b, &c) } 95 | #[quickcheck] fn u32_super_trait_cohesion(a: u32, b: u32, c: u32) -> bool { super_trait_cohesion(&a, &b, &c) } 96 | #[quickcheck] fn u64_super_trait_cohesion(a: u64, b: u64, c: u64) -> bool { super_trait_cohesion(&a, &b, &c) } 97 | #[quickcheck] fn usize_super_trait_cohesion(a: usize, b: usize, c: usize) -> bool { super_trait_cohesion(&a, &b, &c) } 98 | } 99 | -------------------------------------------------------------------------------- /cyclic_order/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! See http://en.wikipedia.org/wiki/Cyclic_order 2 | 3 | #![allow(unstable)] 4 | 5 | #[cfg(test)] 6 | #[macro_use] 7 | extern crate quickcheck_macros; 8 | #[cfg(test)] 9 | extern crate quickcheck; 10 | 11 | 12 | pub mod linked_list; 13 | 14 | mod impls; 15 | 16 | #[derive(PartialEq, PartialOrd, Eq, Ord, 17 | Copy, Clone, Hash, Show)] 18 | pub enum CyclicOrdering { 19 | Clockwise, 20 | CounterClockwise, 21 | Degenerate, // a b and c are not all distinct 22 | } 23 | 24 | /// Axioms (from Wikipedia): 25 | /// 26 | /// - Cyclicity: If [a, b, c] then [b, c, a] 27 | /// - Asymmetry: If [a, b, c] then not [c, b, a] 28 | /// - Transitivity: If [a, b, c] and [a, c, d] then [a, b, d] 29 | pub trait PartialCyclicOrd 30 | { 31 | fn is_clockwise(&self, them: &Self, other: &Self) -> bool; 32 | } 33 | 34 | pub mod partial_axioms { 35 | //! implementors can test their impls easily with these 36 | 37 | use super::*; 38 | 39 | pub fn cyclicity(a: &T, b: &T, c: &T) -> bool where T: PartialCyclicOrd { 40 | a.is_clockwise(b, c) == b.is_clockwise(c, a) 41 | } 42 | 43 | pub fn antisymmetry(a: &T, b: &T, c: &T) -> bool where T: PartialCyclicOrd { 44 | !( a.is_clockwise(b, c) && c.is_clockwise(b, a) ) 45 | } 46 | 47 | pub fn transitivity(a: &T, b: &T, c: &T, d: &T) -> bool where T: PartialCyclicOrd { 48 | match (a.is_clockwise(b, c), a.is_clockwise(c, d), a.is_clockwise(b, d)) { 49 | (true, true, trans) => trans, 50 | _ => true, 51 | } 52 | } 53 | } 54 | 55 | 56 | /// Axioms (from Wikipedia): 57 | /// 58 | /// - From PartialCyclicOrder: 59 | /// - Cyclicity: If [a, b, c] then [b, c, a] 60 | /// - Asymmetry: If [a, b, c] then not [c, b, a] 61 | /// - Transitivity: If [a, b, c] and [a, c, d] then [a, b, d] 62 | /// 63 | /// - Totality: If a, b, and c are distinct, then either [a, b, c] or [c, b, a] 64 | pub trait CyclicOrd: PartialEq + PartialCyclicOrd { 65 | fn cyclic_cmp(&self, them: &Self, other: &Self) -> CyclicOrdering; 66 | } 67 | 68 | pub mod total_axioms { 69 | //! implementors can test their impls easily with these 70 | 71 | use super::*; 72 | use super::CyclicOrdering::*; 73 | 74 | pub fn cyclicity(a: &T, b: &T, c: &T) -> bool where T: CyclicOrd { 75 | a.cyclic_cmp(b, c) == b.cyclic_cmp(c, a) 76 | } 77 | 78 | pub fn antisymmetry(a: &T, b: &T, c: &T) -> bool where T: CyclicOrd { 79 | match (a.cyclic_cmp(b, c), c.cyclic_cmp(b, a)) { 80 | (Clockwise, Clockwise) => false, 81 | (CounterClockwise, CounterClockwise) => false, 82 | _ => true, 83 | } 84 | } 85 | 86 | pub fn transitivity(a: &T, b: &T, c: &T, d: &T) -> bool where T: CyclicOrd { 87 | match (a.cyclic_cmp(b, c), a.cyclic_cmp(c, d), a.cyclic_cmp(b, d)) { 88 | (Clockwise, Clockwise, trans) => trans == Clockwise, 89 | (CounterClockwise, CounterClockwise, trans) => trans == CounterClockwise, 90 | _ => true, 91 | } 92 | } 93 | 94 | pub fn totality(a: &T, b: &T, c: &T) -> bool where T: CyclicOrd { 95 | match (a.cyclic_cmp(b, c), c.cyclic_cmp(b, a)) { 96 | (Clockwise, CounterClockwise) => true, 97 | (CounterClockwise, Clockwise) => true, 98 | (Degenerate, Degenerate) => a == b || b == c || c == a, 99 | _ => false, 100 | } 101 | } 102 | 103 | pub fn super_trait_cohesion(a: &T, b: &T, c: &T) -> bool where T: CyclicOrd { 104 | match (a.cyclic_cmp(b, c), a.is_clockwise(b, c)) { 105 | (Clockwise, true) => true, 106 | (_, false) => true, 107 | _ => false, 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /cyclic_order/src/linked_list.rs: -------------------------------------------------------------------------------- 1 | use std::collections::dlist::{ 2 | DList, 3 | //ListInsertion, 4 | }; 5 | 6 | 7 | // A priority queue to store cuts of a cycle 8 | // Currently basically extension methods on DList 9 | pub trait CutQueue where T: ::CyclicOrd 10 | { 11 | fn insert_cyclic(&mut self, T); 12 | } 13 | 14 | // Does not rotate link list 15 | impl CutQueue for DList where T: ::CyclicOrd 16 | { 17 | fn insert_cyclic(&mut self, elt: T) 18 | { 19 | let mut it = self.iter_mut(); 20 | 21 | // will be used to define the cut 22 | match it.next() { 23 | None => (), // empty list, order does not matter 24 | Some(first) => loop { 25 | match it.peek_next() { 26 | None => break, 27 | Some(cur) => if 28 | first.is_clockwise(&elt, cur) || 29 | *first == elt || elt == *cur 30 | { break } 31 | } 32 | it.next(); 33 | } 34 | }; 35 | 36 | it.insert_next(elt); 37 | } 38 | } 39 | 40 | 41 | #[cfg(test)] 42 | mod test 43 | { 44 | use CyclicOrd; 45 | use CyclicOrdering::*; 46 | 47 | use super::CutQueue; 48 | use std::collections::DList; 49 | 50 | use quickcheck::TestResult; 51 | 52 | #[test] 53 | fn no_wrap() { 54 | let mut l = DList::new(); 55 | l.insert_cyclic(0u8); 56 | l.insert_cyclic(3); 57 | l.insert_cyclic(1); 58 | l.insert_cyclic(4); 59 | 60 | let mut it = l.iter().map(|x| *x); 61 | 62 | assert_eq!(it.next(), Some(0)); 63 | assert_eq!(it.next(), Some(1)); 64 | assert_eq!(it.next(), Some(3)); 65 | assert_eq!(it.next(), Some(4)); 66 | assert_eq!(it.next(), None); 67 | } 68 | 69 | #[test] 70 | fn wrap() { 71 | let mut l = DList::new(); 72 | l.insert_cyclic(5u8); 73 | l.insert_cyclic(3); 74 | l.insert_cyclic(1); 75 | l.insert_cyclic(4); 76 | l.insert_cyclic(255); 77 | l.insert_cyclic(0); 78 | 79 | let mut it = l.iter().map(|x| *x); 80 | 81 | assert_eq!(it.next(), Some(5)); 82 | assert_eq!(it.next(), Some(255)); 83 | assert_eq!(it.next(), Some(0)); 84 | assert_eq!(it.next(), Some(1)); 85 | assert_eq!(it.next(), Some(3)); 86 | assert_eq!(it.next(), Some(4)); 87 | assert_eq!(it.next(), None); 88 | } 89 | 90 | #[quickcheck] 91 | fn random_insertion(elems: Vec) -> TestResult 92 | { 93 | let mut l = DList::new(); 94 | for n in elems.iter() { 95 | l.insert_cyclic(*n); 96 | } 97 | 98 | if l.len() < 3 { return TestResult::discard(); } 99 | 100 | let mut it = l.iter(); 101 | 102 | let mut e1 = it.next().unwrap(); 103 | let mut e2 = it.next().unwrap(); 104 | let mut e3 = it.next().unwrap(); 105 | 106 | loop { 107 | if e1.cyclic_cmp(e2, e3) == CounterClockwise { 108 | return TestResult::error( 109 | format!("triple: [{}, {}, {}]",e1, e2, e3).as_slice()) 110 | }; 111 | 112 | let e4 = match it.next() { 113 | None => return TestResult::passed(), 114 | Some(e) => e, 115 | }; 116 | 117 | e1 = e2; 118 | e2 = e3; 119 | e3 = e4; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /data_link/interface/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-data-link-interface" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "interface" 10 | 11 | [dependencies] 12 | quilt-net-misc = { path = "../../misc" } 13 | -------------------------------------------------------------------------------- /data_link/interface/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(unboxed_closures)] 2 | 3 | extern crate core; 4 | 5 | extern crate misc; 6 | 7 | use core::convert::From; 8 | 9 | use misc::interface as i; 10 | 11 | 12 | // TODO: use Box<[u8]> instead of Vec 13 | pub type Packet = Vec; 14 | pub type Handler<'a> = i::Handler<'a, Packet>; 15 | 16 | #[derive(Clone, Copy, 17 | PartialEq, Eq, 18 | PartialOrd, Ord, 19 | Hash, Debug)] 20 | pub enum Error { 21 | Disabled, 22 | External(E), 23 | } 24 | 25 | impl From for Error { 26 | fn from(external: E) -> Error { 27 | Error::External(external) 28 | } 29 | } 30 | 31 | pub type Result = std::result::Result>; 32 | 33 | pub trait Interface<'a>: i::Interface { 34 | /// Send packet with specified body 35 | fn send(&self, packet: Packet) -> self::Result<(), Self::Error>; 36 | 37 | /// Update the function called on an arriving packet 38 | fn update_recv_handler<'b>(&'b self, on_recv: Handler<'a>) where 'a: 'b; 39 | 40 | //fn new(on_receive: |Vec| -> ()) -> Self; 41 | 42 | //fn stock(&mut Self, bufs: Box<[Vec]>); 43 | 44 | fn enable(&mut self); 45 | fn disable(&mut self); 46 | fn get_status(&self) -> bool; 47 | } 48 | -------------------------------------------------------------------------------- /data_link/udp_mock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-data-link-udp-mock" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "udp_mock" 10 | 11 | [dependencies] 12 | log = { version = "0.3.6", default-features = false } 13 | 14 | quilt-net-misc = { path = "../../misc" } 15 | quilt-net-data-link-interface = { path = "../interface" } 16 | 17 | [dev-dependencies] 18 | env_logger = "0.3.1" 19 | -------------------------------------------------------------------------------- /data_link/udp_mock/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(question_mark)] 2 | 3 | #[macro_use] 4 | extern crate log; 5 | 6 | extern crate misc; 7 | extern crate interface as dl; 8 | 9 | use std::collections::HashMap; 10 | use std::collections::hash_map::Entry::{Occupied, Vacant}; 11 | use std::io; 12 | use std::net::{ 13 | UdpSocket, 14 | SocketAddr, 15 | SocketAddrV4, 16 | Ipv4Addr, 17 | ToSocketAddrs, 18 | }; 19 | use std::sync::Arc; 20 | use std::sync::RwLock; 21 | use std::thread; 22 | 23 | use misc::interface as root; 24 | 25 | 26 | const RECV_BUF_SIZE: usize = 64 * 1024; 27 | 28 | type SharedHandlerMap<'a> = Arc)>>>; 30 | 31 | /// The backing listening socket / read loop for a bunch of UDP-backed mock link 32 | /// neighbors 33 | pub struct Listener<'a> { 34 | socket: UdpSocket, 35 | handlers: SharedHandlerMap<'a>, 36 | } 37 | 38 | impl Listener<'static> 39 | { 40 | pub fn new(listen_addr: A, num_threads: usize) -> io::Result> 41 | where A: ToSocketAddrs 42 | { 43 | assert!(num_threads > 0); 44 | 45 | let socket = UdpSocket::bind(listen_addr)?; 46 | 47 | let handlers: SharedHandlerMap = Arc::new(RwLock::new(HashMap::new())); 48 | 49 | for _ in 0..num_threads { 50 | let socket = socket.try_clone()?; 51 | let handlers = handlers.clone(); 52 | thread::spawn(move || { 53 | let mut buf: [u8; RECV_BUF_SIZE] = unsafe { std::mem::uninitialized() }; 54 | loop { 55 | // TODO: someway to kill task eventually 56 | match socket.recv_from(&mut buf[..]) { 57 | Err(e) => { 58 | // maybe it will work next time... 59 | debug!("OS error when trying to wait for packet: {}", e); 60 | }, 61 | Ok((len, src_addr)) => match handlers.read().unwrap().get(&src_addr) { 62 | None => continue, // drop that packet! 63 | Some(&(is_enabled, ref on_recv)) => { 64 | debug!("Received packet"); 65 | if is_enabled { 66 | debug!("Virtual Interface is enabled"); 67 | let args = buf[..len].to_vec(); 68 | (**on_recv)(args); 69 | } else { 70 | debug!("Virtual Interface is not enabled, dropping packet"); 71 | } 72 | }, 73 | } 74 | }; 75 | // ) 76 | } 77 | }); 78 | } 79 | 80 | Ok(Listener { 81 | socket: socket, 82 | handlers: handlers, 83 | }) 84 | } 85 | 86 | pub fn new_loopback(num_threads: usize) -> io::Result<(Self, SocketAddr)> { 87 | // "port 0" is wildcard (port number is dynamically assigned) 88 | let mut addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 0)); 89 | let listener = Listener::new(addr, num_threads)?; 90 | listener.socket.connect(addr)?; 91 | // resolve actual port 92 | addr = listener.socket.local_addr()?; 93 | debug!("made listener with addr: {}", addr); 94 | Ok((listener, addr)) 95 | } 96 | } 97 | 98 | impl<'a> Listener<'a> 99 | { 100 | pub fn try_clone(&self) -> io::Result> { 101 | Ok(Listener { 102 | socket: self.socket.try_clone()?, 103 | handlers: self.handlers.clone(), 104 | }) 105 | } 106 | } 107 | 108 | 109 | /// A mock link layer interface made from UDP 110 | pub struct Interface<'a> { 111 | listener: Listener<'a>, 112 | remote_addr: SocketAddr, 113 | cached_status: bool, 114 | } 115 | 116 | 117 | impl<'a> Interface<'a> { 118 | pub fn new(listener: &Listener<'a>, 119 | remote_addr: SocketAddr, 120 | on_recv: dl::Handler<'a>) -> Interface<'a> 121 | { 122 | listener.handlers.write().unwrap().insert(remote_addr, (true, on_recv)); 123 | 124 | Interface { 125 | listener: listener.try_clone().unwrap(), 126 | remote_addr: remote_addr, 127 | cached_status: true, 128 | } 129 | } 130 | } 131 | 132 | impl<'a> root::Interface for Interface<'a> { 133 | type Error = io::Error; 134 | } 135 | 136 | impl<'a> dl::Interface<'a> for Interface<'a> { 137 | fn send(&self, packet: dl::Packet) -> dl::Result<(), Self::Error> { 138 | if self.cached_status == false { 139 | Err(dl::Error::Disabled)?; 140 | } 141 | let sent = self.listener 142 | .socket.try_clone()? 143 | .send_to(&packet[..], self.remote_addr)?; 144 | if sent != packet.len() { 145 | return Err(From::from(io::Error::new( 146 | io::ErrorKind::WriteZero, 147 | "The packet could not be sent in whole"))); 148 | } else { 149 | Ok(()) 150 | } 151 | } 152 | 153 | fn update_recv_handler<'b>(&'b self, on_recv: dl::Handler<'a>) 154 | where 'a: 'b 155 | { 156 | self.listener.handlers.write().unwrap() 157 | .insert(self.remote_addr, (true, on_recv)); 158 | } 159 | 160 | fn enable(&mut self) { 161 | let mut map = self.listener.handlers.write().unwrap(); 162 | self.cached_status = true; 163 | match map.entry(self.remote_addr) { 164 | Vacant(_) => panic!("udp mock interface should already have entry in table"), 165 | Occupied(mut entry) => { 166 | entry.get_mut().0 = true; 167 | }, 168 | } 169 | } 170 | 171 | fn disable(&mut self) { 172 | let mut map = self.listener.handlers.write().unwrap(); 173 | self.cached_status = false; 174 | match map.entry(self.remote_addr) { 175 | Vacant(_) => panic!("udp mock interface should already have entry in table"), 176 | Occupied(mut entry) => { 177 | entry.get_mut().0 = false; 178 | }, 179 | } 180 | } 181 | 182 | fn get_status(&self) -> bool { 183 | self.cached_status 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /data_link/udp_mock/tests/two-node.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_syntax)] 2 | 3 | #[macro_use] 4 | extern crate log; 5 | extern crate env_logger; 6 | 7 | extern crate misc; 8 | extern crate interface as dl; 9 | extern crate udp_mock; 10 | 11 | use std::io; 12 | 13 | use std::sync::{Arc, Barrier}; 14 | use std::str::from_utf8; 15 | use std::string::String; 16 | use std::str::FromStr; 17 | 18 | use misc::SenderClosure; 19 | use udp_mock::*; 20 | 21 | 22 | fn talk_to_self_channel_helper(num_threads: usize) { 23 | use std::sync::mpsc::*; 24 | 25 | let (l1, a1) = Listener::new_loopback(num_threads).unwrap(); 26 | let (l2, a2) = Listener::new_loopback(num_threads).unwrap(); 27 | 28 | let (tx1, rx1) = channel::<(dl::Packet,)>(); 29 | let (tx2, rx2) = channel::<(dl::Packet,)>(); 30 | 31 | const M1: &'static str = "Hey Josh!"; 32 | const M2: &'static str = "Hey Cody!"; 33 | 34 | let interface1 = Interface::new(&l1, a2, box SenderClosure::new(tx1)); 35 | let interface2 = Interface::new(&l2, a1, box SenderClosure::new(tx2)); 36 | 37 | dl::Interface::send(&interface1, String::from_str(M2).unwrap().into()).unwrap(); 38 | dl::Interface::send(&interface2, String::from_str(M1).unwrap().into()).unwrap(); 39 | 40 | let (packet_1,) = rx1.recv().unwrap(); 41 | assert_eq!(packet_1.as_slice(), M1.as_bytes()); 42 | debug!("Got the first packet"); 43 | 44 | let (packet_2,) = rx2.recv().unwrap(); 45 | assert_eq!(packet_2.as_slice(), M2.as_bytes()); 46 | debug!("Got the second packet"); 47 | } 48 | 49 | #[test] 50 | fn talk_to_self_channel() { 51 | talk_to_self_channel_helper(1); 52 | } 53 | #[test] 54 | fn talk_to_self_channel_parallel() { 55 | talk_to_self_channel_helper(4); 56 | } 57 | 58 | fn talk_to_self_callback_helper(num_threads: usize) { 59 | fn mk_callback(barrier: Arc, msg: &'static str) -> dl::Handler { 60 | box move |packet: dl::Packet| { 61 | debug!("got packet: {}", from_utf8(packet.as_slice()).unwrap()); 62 | debug!("matching against: {}", msg); 63 | assert_eq!(packet.as_slice(), msg.as_bytes()); 64 | barrier.wait(); 65 | } 66 | } 67 | 68 | let barrier = Arc::new(Barrier::new(3)); 69 | 70 | let (l1, a1) = Listener::new_loopback(num_threads).unwrap(); 71 | let (l2, a2) = Listener::new_loopback(num_threads).unwrap(); 72 | 73 | const M1: &'static str = "Hey Josh!"; 74 | const M2: &'static str = "Hey Cody!"; 75 | 76 | let interface1 = Interface::new(&l1, a2, mk_callback(barrier.clone(), M1)); 77 | let interface2 = Interface::new(&l2, a1, mk_callback(barrier.clone(), M2)); 78 | 79 | dl::Interface::send(&interface1, String::from_str(M2).unwrap().into()).unwrap(); 80 | dl::Interface::send(&interface2, String::from_str(M1).unwrap().into()).unwrap(); 81 | 82 | barrier.wait(); 83 | } 84 | 85 | #[test] 86 | fn talk_to_self_callback() { 87 | talk_to_self_callback_helper(1); 88 | } 89 | 90 | #[test] 91 | fn talk_to_self_callback_parallel() { 92 | talk_to_self_callback_helper(4); 93 | } 94 | 95 | #[test] 96 | fn disable_then_cant_send() { 97 | 98 | fn inner() -> io::Result<()> { 99 | let (l, a) = Listener::new_loopback(1).unwrap(); 100 | let mut i = Interface::new(&l, a, box |_| {}); 101 | 102 | dl::Interface::disable(&mut i); 103 | 104 | match dl::Interface::send(&i, Vec::new()).unwrap_err() { 105 | dl::Error::Disabled => (), 106 | _ => panic!("was not disabled") 107 | } 108 | 109 | Ok(()) 110 | } 111 | inner().unwrap(); 112 | } 113 | -------------------------------------------------------------------------------- /misc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-misc" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "misc" 10 | 11 | [dependencies] 12 | log = { version = "0.3.6", default-features = false } 13 | -------------------------------------------------------------------------------- /misc/src/interface.rs: -------------------------------------------------------------------------------- 1 | // TODO: real network card may consolidate multiple packets per interrupt. 2 | pub type Handler<'a, Packet> = Box; 3 | 4 | pub trait Interface { 5 | type Error; 6 | } 7 | -------------------------------------------------------------------------------- /misc/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(unboxed_closures, fn_traits)] 2 | 3 | extern crate core; 4 | 5 | #[macro_use] 6 | extern crate log; 7 | 8 | pub mod interface; 9 | pub mod state_machine; 10 | 11 | use core::ops::FnMut; 12 | 13 | use std::sync::mpsc::Sender; 14 | use std::sync::Mutex; 15 | 16 | pub struct LockedClosure { 17 | pub closure: Mutex 18 | } 19 | 20 | impl FnOnce for LockedClosure where F: FnMut + Send { 21 | type Output = >::Output; 22 | 23 | extern "rust-call" fn call_once(mut self, args: Args) -> Self::Output { 24 | self.call_mut(args) 25 | } 26 | 27 | } 28 | 29 | impl FnMut for LockedClosure where F: FnMut + Send { 30 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { 31 | self.closure.get_mut().unwrap().call_mut(args) 32 | } 33 | } 34 | 35 | 36 | impl Fn for LockedClosure where F: FnMut + Send { 37 | extern "rust-call" fn call(&self, args: Args) -> Self::Output { 38 | self.closure.lock().unwrap().call_mut(args) 39 | } 40 | } 41 | 42 | // TODO: get rid of mutex 43 | pub struct SenderClosure { 44 | pub sender: Mutex> 45 | } 46 | 47 | impl SenderClosure { 48 | pub fn new(sender: Sender) -> SenderClosure { 49 | SenderClosure { sender: Mutex::new(sender) } 50 | } 51 | } 52 | 53 | impl FnOnce for SenderClosure { 54 | type Output = (); 55 | 56 | extern "rust-call" fn call_once(mut self, args: T) -> () { 57 | self.call_mut(args); 58 | } 59 | } 60 | 61 | impl FnMut for SenderClosure { 62 | extern "rust-call" fn call_mut(&mut self, args: T) -> () { 63 | debug!("SenderClosure called without lock!"); 64 | self.sender.get_mut().unwrap().send(args).unwrap(); 65 | } 66 | } 67 | 68 | impl Fn for SenderClosure { 69 | extern "rust-call" fn call(&self, args: T) -> () { 70 | debug!("SenderClosure called with lock!"); 71 | self.sender.lock().unwrap().send(args).unwrap(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /misc/src/state_machine.rs: -------------------------------------------------------------------------------- 1 | pub enum Next { 2 | Terminate, 3 | Continue(Transitions), 4 | } 5 | 6 | pub type Transitions = for<'a> fn(&'a mut State, Input) -> Next; 7 | 8 | pub struct StateMachine { 9 | state: State, 10 | transitions: Transitions 11 | } 12 | 13 | impl StateMachine { 14 | 15 | pub fn new(initial_state: S, 16 | initial_transitions: Transitions) 17 | -> StateMachine 18 | { 19 | StateMachine { 20 | state: initial_state, 21 | transitions: initial_transitions, 22 | } 23 | } 24 | 25 | // returns false if terminating 26 | pub fn next(&mut self, input: I) -> bool { 27 | match (self.transitions)(&mut self.state, input) { 28 | Next::Terminate => false, 29 | Next::Continue(new_ts) => { 30 | self.transitions = new_ts; 31 | true 32 | }, 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /network/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-network" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "network" 10 | 11 | [dependencies] 12 | bitflags = "0.7" 13 | log = { version = "0.3.6", default-features = false } 14 | 15 | quilt-net-misc = { path = "../misc" } 16 | quilt-net-data-link-interface = { path = "../data_link/interface" } 17 | 18 | [dev-dependencies] 19 | env_logger = "0.3.1" 20 | 21 | quilt-net-data-link-udp-mock = { path = "../data_link/udp_mock" } 22 | quilt-net-transport-static-routing = { path = "../transport/static_routing" } 23 | -------------------------------------------------------------------------------- /network/src/ipv4/control.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | use super::strategy; 3 | 4 | 5 | /// Enables the given interface 6 | pub fn up<'a, A, E>(ip_state: &super::State<'a, A, E>, interface: usize) 7 | -> Result<(), ()> 8 | where A: strategy::RoutingTable<'a> + 'a, 9 | E: Debug + 'a 10 | { 11 | // no UFCS to make this concise 12 | match ip_state.get_interface(interface) { 13 | None => return Err(()), 14 | Some(x) => x.interface.write().unwrap().enable(), 15 | }; 16 | Ok(()) 17 | } 18 | 19 | /// Disables the given interface 20 | pub fn down<'a, A, E>(ip_state: &super::State<'a, A, E>, interface: usize) 21 | -> Result<(), ()> 22 | where A: strategy::RoutingTable<'a> + 'a, 23 | E: Debug + 'a 24 | { 25 | match ip_state.get_interface(interface) { 26 | None => return Err(()), 27 | Some(x) => x.interface.write().unwrap().disable(), 28 | }; 29 | Ok(()) 30 | } 31 | 32 | pub fn register_protocol_handler 33 | <'a, 'st: 'a, A, E> 34 | (ip_state: &'a super::State<'st, A, E>, 35 | proto_number: u8, 36 | handler: super::Handler<'st>) 37 | where A: strategy::RoutingTable<'st> 38 | { 39 | ip_state.protocol_handlers.write().unwrap()[proto_number as usize].push(handler); 40 | } 41 | -------------------------------------------------------------------------------- /network/src/ipv4/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::hash_map::HashMap; 2 | use std::fmt; 3 | use std::str::FromStr; 4 | use std::sync::{Arc, RwLock}; 5 | 6 | use data_link::interface as dl; 7 | 8 | use self::strategy::RoutingTable; 9 | 10 | pub mod control; 11 | pub mod packet; 12 | pub mod send; 13 | pub mod receive; 14 | pub mod strategy; 15 | 16 | 17 | #[derive(PartialEq, PartialOrd, Eq, Ord, 18 | Copy, Clone, Hash, Debug)] 19 | pub struct Addr(pub [u8; 4]); 20 | 21 | 22 | impl fmt::Display for Addr { 23 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 24 | let [a0, a1, a2, a3] = self.0; 25 | write!(f, "{}.{}.{}.{}", a0, a1, a2, a3) 26 | } 27 | } 28 | 29 | impl FromStr for Addr { 30 | type Err = (); 31 | 32 | fn from_str(s: &str) -> Result { 33 | let mut quad: [Result; 4] = [Err(()); 4]; 34 | let iter = s.trim().split('.').map(FromStr::from_str).map(|r| r.map_err(|_| ())); 35 | 36 | for (mut ptr, val) in quad.iter_mut().zip(iter) 37 | { 38 | *ptr = val; 39 | } 40 | 41 | let [a0, a1, a2, a3] = quad; 42 | 43 | Ok(Addr([a0?, a1?, a2?, a3?])) 44 | } 45 | } 46 | 47 | 48 | #[inline] 49 | pub fn parse_addr(&[a, b, c, d]: &[u8; 4]) -> Addr { 50 | Addr([a, b, c, d]) 51 | } 52 | 53 | #[inline] 54 | pub fn parse_addr_unsafe(b: &[u8]) -> Addr { 55 | Addr([b[0], b[1], b[2], b[3]]) 56 | } 57 | 58 | // TODO: remove 59 | #[inline] 60 | pub fn write_addr(Addr(slice): Addr) -> [u8; 4] { 61 | slice 62 | } 63 | 64 | 65 | 66 | // key: adjacent ip (next hop) 67 | // value: index to InterfaceRow (see below) 68 | pub type InterfaceTable = HashMap; 69 | 70 | pub struct InterfaceRow<'a, E> { 71 | pub local_ip: Addr, 72 | pub interface: RwLock + Send + Sync + 'a>>, 73 | } 74 | 75 | // TODO: use Box<[u8]> instead of Vec 76 | // TODO: real network card may consolidate multiple packets per interrupt 77 | pub type Handler<'a> = super::misc::interface::Handler<'a, packet::V>; 78 | 79 | pub type ProtocolTable<'a> = Vec>>; 80 | 81 | pub struct State<'a, A, E> where A: RoutingTable<'a> + 'a 82 | { 83 | pub interfaces: Vec>, 84 | pub neighbors: InterfaceTable, 85 | pub routes: A, 86 | pub protocol_handlers: RwLock>, 87 | // Identification counter? increased with each packet sent out, 88 | // used in Identification header for fragmentation purposes 89 | } 90 | 91 | impl<'a, RT, DE> State<'a, RT, DE> 92 | where RT: RoutingTable<'a> + 'a, 93 | DE: fmt::Debug + 'a 94 | 95 | { 96 | pub fn new(interfaces: Vec>, 97 | neighbors: InterfaceTable) 98 | -> Arc> 99 | { 100 | let routes: RT = RoutingTable::init(neighbors.keys().map(|x| *x)); 101 | 102 | let state: Arc> = Arc::new(State { 103 | routes: routes, 104 | neighbors: neighbors, 105 | interfaces: interfaces, 106 | // handlers are not clonable, so the nice ways of doing this do not work 107 | protocol_handlers: RwLock::new(vec![ 108 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 109 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 110 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 111 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 112 | 113 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 114 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 115 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 116 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 117 | 118 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 119 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 120 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 121 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 122 | 123 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 124 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 125 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 126 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 127 | 128 | 129 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 130 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 131 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 132 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 133 | 134 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 135 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 136 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 137 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 138 | 139 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 140 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 141 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 142 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 143 | 144 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 145 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 146 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], 147 | vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![]]), 148 | }); 149 | 150 | for &InterfaceRow { ref interface, .. } in state.interfaces.iter() { 151 | use self::receive::make_receive_callback; 152 | interface.write().unwrap() 153 | .update_recv_handler(make_receive_callback::(state.clone())); 154 | } 155 | 156 | RoutingTable::monitor(state.clone()); 157 | 158 | state 159 | } 160 | 161 | /// Returns dl::Interface struct for the requested interface 162 | pub fn get_interface(&self, interface_ix: usize) 163 | -> Option<&InterfaceRow<'a, DE>> 164 | { 165 | self.interfaces.as_slice().get(interface_ix) 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /network/src/ipv4/packet.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::mem::transmute; 3 | //use std::num::Int; 4 | use std::vec::Vec; 5 | 6 | use super::Addr; 7 | use super::parse_addr_unsafe; 8 | use super::write_addr; 9 | 10 | #[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Debug)] 11 | pub struct V { buf: Vec } 12 | 13 | #[derive(PartialEq, PartialOrd, Eq, Ord)]//, Debug)] 14 | pub struct A { buf: [u8] } 15 | 16 | 17 | impl V { 18 | pub fn new(buf: Vec) -> V { 19 | V { buf: buf } 20 | } 21 | 22 | /// NOT CHECKSUMED! 23 | fn new_with_header(ip: Addr, 24 | protocol: u8, 25 | expected_body_size: Option) -> V 26 | { 27 | let mut buf: Vec = Vec::with_capacity(MIN_HDR_LEN_8S as usize 28 | + expected_body_size.unwrap_or(0) as usize); 29 | unsafe { buf.set_len(MIN_HDR_LEN_8S as usize); } 30 | let mut packet = V::new(buf); 31 | { 32 | let s = packet.borrow_mut(); 33 | const SENTINAL8: u8 = 0b_1000_0001; 34 | const SENTINAL16: u16 = 0b_1100_1000_0000_0011; 35 | const SENTINAL32: u32 = 0b_1110_0000_0000_0000_0000_0000_0000_0111; 36 | *(s.cast_h_mut()) = Header { 37 | version_ihl: SENTINAL8, // SET LATER 38 | ///////////////////////////////////// Internet header length 39 | type_of_service: SENTINAL8, // SET LATER 40 | total_length: SENTINAL16, // DO NOT SET 41 | identification: SENTINAL16, 42 | flags_fragment_offset: SENTINAL16, // SET LATER 43 | ///////////////////////////////////// Fragment Offset 44 | time_to_live: 128, 45 | protocol: protocol, 46 | header_checksum: SENTINAL16, // DO NOT SET 47 | source_address: SENTINAL32, // DO NOT SET 48 | destination_address: SENTINAL32, // SET LATER 49 | }; 50 | s.set_version(4); 51 | s.set_header_length(MIN_HDR_LEN_32S); 52 | s.set_type_of_service(Precedence::Routine, ServiceFlags::empty()); 53 | s.set_flags_fragment_offset(DONT_FRAGMENT, 0); 54 | s.set_destination(ip); 55 | } 56 | packet 57 | } 58 | 59 | pub fn new_with_builder 60 | 61 | (ip: Addr, 62 | protocol: u8, 63 | expected_body_size: Option, 64 | builder: F) 65 | -> Result<(Accum, V), Err> 66 | where F: for<'a> FnOnce(&'a mut V) -> Result 67 | { 68 | let mut packet = V::new_with_header(ip, protocol, expected_body_size); 69 | 70 | let accum = try!(builder(&mut packet)); 71 | 72 | let len = packet.borrow().as_slice().len() as u16; 73 | 74 | // once the new error handling libs land 75 | // this can be return Err(...) instead 76 | assert!(len > MIN_HDR_LEN_8S); 77 | 78 | // now fix header and checksum 79 | { 80 | let s = packet.borrow_mut(); 81 | s.cast_h_mut().total_length = len.to_be(); 82 | s.update_checksum(); 83 | } 84 | Ok((accum, packet)) 85 | } 86 | 87 | pub fn as_vec(&self) -> &Vec { &self.buf } 88 | 89 | pub fn as_mut_vec(&mut self) -> &mut Vec { &mut self.buf } 90 | 91 | pub fn to_vec(self) -> Vec { self.buf } 92 | 93 | pub fn borrow(&self) -> &A { unsafe { transmute(self.buf.as_slice()) } } 94 | 95 | pub fn borrow_mut(&mut self) -> &mut A { unsafe { transmute(self.buf.as_mut_slice()) } } 96 | } 97 | 98 | pub const MIN_HDR_LEN_1S: u32 = MIN_HDR_LEN_32S as u32 * 32; 99 | pub const MIN_HDR_LEN_8S: u16 = MIN_HDR_LEN_32S as u16 * 4; 100 | pub const MIN_HDR_LEN_16S: u16 = MIN_HDR_LEN_32S as u16 * 2; 101 | pub const MIN_HDR_LEN_32S: u8 = 5; 102 | 103 | /// From RFC 791 104 | /// 105 | /// 0 1 2 3 106 | /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 107 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 108 | /// |Version| IHL |Type of Service| Total Length | 109 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 110 | /// | Identification |Flags| Fragment Offset | 111 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 112 | /// | Time to Live | Protocol | Header Checksum | 113 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 114 | /// | Source Address | 115 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 116 | /// | Destination Address | 117 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 118 | /// | Options | Padding | 119 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 120 | 121 | #[repr(packed)] 122 | #[derive(PartialEq, PartialOrd, Eq, Ord, 123 | Copy, Clone, Hash, Debug)] 124 | pub struct Header { 125 | pub version_ihl: u8, // IP version (= 4) 126 | /////////////////////////////////// Internet header length 127 | pub type_of_service: u8, // Type of service 128 | pub total_length: u16, // Total length in octets 129 | pub identification: u16, // Identification 130 | pub flags_fragment_offset: u16, // 3-bits Flags 131 | /////////////////////////////////// Fragment Offset 132 | pub time_to_live: u8, // Time To Live 133 | pub protocol: u8, // Protocol 134 | pub header_checksum: u16, // Checksum 135 | pub source_address: u32, // Source Address 136 | pub destination_address: u32, // Destination Address 137 | } 138 | 139 | 140 | #[repr(u8)] 141 | #[derive(PartialEq, PartialOrd, Eq, Ord, 142 | Copy, Clone, Hash, Debug)] 143 | pub enum Precedence { 144 | NetworkControl = 0b_111_00000, 145 | InternetworkControl = 0b_110_00000, 146 | CriticEpc = 0b_101_00000, 147 | FlashOverride = 0b_100_00000, 148 | Flash = 0b_011_00000, 149 | Immediate = 0b_010_00000, 150 | Priority = 0b_001_00000, 151 | Routine = 0b_000_00000, 152 | } 153 | 154 | 155 | bitflags! { 156 | pub flags ServiceFlags: u8 { 157 | const LOW_DELAY = 0b000_100_00, 158 | const HIGH_THROUGHPUT = 0b000_010_00, 159 | const HIGH_RELIABILTY = 0b000_001_00, 160 | } 161 | } 162 | 163 | bitflags! { 164 | pub flags IpFlags: u16 { 165 | const DONT_FRAGMENT = 0b010_00000_00000000, 166 | const MORE_FRAGMENTS = 0b001_00000_00000000, 167 | } 168 | } 169 | 170 | 171 | struct CastHelper { 172 | header: Header, 173 | _rest: [u8], // used to make it a DST 174 | } 175 | 176 | impl A { 177 | 178 | pub fn as_slice(&self) -> &[u8] { 179 | unsafe { transmute(self) } 180 | } 181 | 182 | pub fn as_mut_slice(&mut self) -> &mut [u8] { 183 | unsafe { transmute(self) } 184 | } 185 | 186 | pub fn cast_h(&self) -> &Header { 187 | & unsafe { transmute::<_,&CastHelper>(self) }.header 188 | } 189 | 190 | pub fn cast_h_mut(&mut self) -> &mut Header { 191 | &mut unsafe { transmute::<_,&mut CastHelper>(self) }.header 192 | } 193 | 194 | 195 | pub fn new(buf: &[u8]) -> &A { 196 | unsafe { transmute(buf) } 197 | } 198 | 199 | pub fn new_mut(buf: &mut [u8]) -> &mut A { 200 | unsafe { transmute(buf) } 201 | } 202 | 203 | 204 | 205 | pub fn get_version(&self) -> u8 { self.buf[0] >> 4 } 206 | pub fn set_version(&mut self, v: u8) { 207 | const MASK: u8 = 0b1111_0000; 208 | assert!(v & MASK == 0); 209 | self.buf[0] &= !MASK; // clear lower bits 210 | self.buf[0] |= v << 4; 211 | } 212 | 213 | pub fn get_header_length(&self) -> u8 { self.buf[0] & 0b0000_1111 } 214 | pub fn set_header_length(&mut self, hl: u8) { 215 | const MASK: u8 = 0b1111_0000; 216 | assert!(hl & MASK == 0); 217 | self.buf[0] &= MASK; // clear lower bits 218 | self.buf[0] |= hl; 219 | } 220 | 221 | pub fn hdr_bytes(&self) -> usize { self.get_header_length() as usize * 4 } 222 | 223 | pub fn get_total_length(& self) -> u16 { u16::from_be(self.cast_h() .total_length) } 224 | pub fn set_total_length(&mut self, v: u16) { self.cast_h_mut().total_length = v.to_be(); } 225 | 226 | 227 | pub fn get_type_of_service(&self) -> (Precedence, ServiceFlags) { 228 | const MASK: u8 = 0b111_00000; 229 | let tos = self.cast_h().type_of_service; 230 | ( unsafe { ::std::mem::transmute(tos & MASK) }, 231 | ServiceFlags { bits: tos & !MASK } ) 232 | } 233 | pub fn set_type_of_service(&mut self, prec: Precedence, flags: ServiceFlags) { 234 | self.cast_h_mut().type_of_service = prec as u8 | flags.bits; 235 | } 236 | 237 | 238 | pub fn get_identification(& self) -> u16 { u16::from_be(self.cast_h() .identification) } 239 | pub fn set_identification(&mut self, v: u16) { self.cast_h_mut().identification = v.to_be(); } 240 | 241 | 242 | pub fn get_flags_fragment_offset(&self) -> (IpFlags, u16) { 243 | let ffo = u16::from_be(self.cast_h().flags_fragment_offset); 244 | const MASK: u16 = 0b111_00000_00000000; 245 | ( unsafe { ::std::mem::transmute(ffo & MASK) }, 246 | ffo & !MASK) 247 | } 248 | pub fn set_flags_fragment_offset(&mut self, flags: IpFlags, offset: u16) { 249 | assert!(0 == (offset & 0b111_00000_00000000)); 250 | self.cast_h_mut().flags_fragment_offset = (flags.bits | offset).to_be(); 251 | } 252 | 253 | 254 | pub fn get_time_to_live(& self) -> u8 { self.cast_h() .time_to_live } 255 | pub fn set_time_to_live(&mut self, v: u8) { self.cast_h_mut().time_to_live = v; } 256 | 257 | pub fn get_protocol(& self) -> u8 { self.cast_h() .protocol } 258 | pub fn set_protocol(&mut self, v: u8) { self.cast_h_mut().protocol = v; } 259 | 260 | pub fn get_header_checksum(& self) -> u16 { u16::from_be(self.cast_h() .header_checksum) } 261 | pub fn set_header_checksum(&mut self, v: u16) { self.cast_h_mut().header_checksum = v.to_be(); } 262 | 263 | pub fn get_source(&self) -> Addr { parse_addr_unsafe(&self.buf[12..16]) } 264 | pub fn set_source(&mut self, a: Addr) { 265 | // TODO: report assign slices lack of doing anything 266 | let [a, b, c, d] = write_addr(a); 267 | self.buf[12] = a; 268 | self.buf[13] = b; 269 | self.buf[14] = c; 270 | self.buf[15] = d; 271 | } 272 | 273 | pub fn get_destination(&self) -> Addr { parse_addr_unsafe(&self.buf[16..20]) } 274 | pub fn set_destination(&mut self, a: Addr) { 275 | let [a, b, c, d] = write_addr(a); 276 | self.buf[16] = a; 277 | self.buf[17] = b; 278 | self.buf[18] = c; 279 | self.buf[19] = d; 280 | } 281 | 282 | // Eh, todo. Iterator over IpOptions? 283 | //pub fn options(&self) -> ... { } 284 | 285 | pub fn get_payload(&self) -> &[u8] { 286 | if self.get_total_length() as usize > self.buf.len() { 287 | &self.buf[self.hdr_bytes() as usize..] 288 | } else { 289 | &self.buf[self.hdr_bytes() as usize..self.get_total_length() as usize] 290 | } 291 | } 292 | 293 | pub fn get_payload_mut(&mut self) -> &mut [u8] { 294 | let start = self.hdr_bytes() as usize; 295 | if self.get_total_length() as usize > self.buf.len() { 296 | &mut self.buf[start..] 297 | } else { 298 | let end = self.get_total_length() as usize; 299 | &mut self.buf[start..end] 300 | } 301 | } 302 | 303 | /// returns native endian 304 | pub fn make_header_checksum(&self) -> u16 { 305 | let u16s: &[u16] = unsafe { cast_slice(&self.as_slice()[..self.as_slice().len() & !1]) }; 306 | 307 | // TODO: Factor out singleton iterator 308 | let temp: [u16; 1] = [0]; // for checkum field itself 309 | 310 | // [..12] to make sure body is excluded, 311 | // and also because length might be incorrect from transmute 312 | let iter = u16s[0..5].iter() 313 | .chain(temp.iter()) 314 | .chain(u16s[6..(self.hdr_bytes() / 2)].iter()); 315 | 316 | make_checksum(iter.map(|x| u16::from_be(*x))) 317 | } 318 | 319 | pub fn update_checksum(&mut self) { 320 | let cs = self.make_header_checksum(); 321 | self.set_header_checksum(cs); 322 | } 323 | } 324 | 325 | impl fmt::Display for A { 326 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 327 | write!(f, 328 | "Ip | ver {} | {} | Tos {} | Len {} |\n | FId {} | off {} |\n | ttl {} | proto {} | sum {} |\n | Src {} | Dst {} |", 329 | self.get_version(), 330 | self.get_header_length(), 331 | self.cast_h().type_of_service, 332 | self.get_total_length(), 333 | 334 | self.get_identification(), 335 | self.get_flags_fragment_offset().1, 336 | 337 | self.get_time_to_live(), 338 | self.get_protocol(), 339 | self.get_header_checksum(), 340 | 341 | self.get_source(), 342 | self.get_destination()) 343 | } 344 | } 345 | 346 | impl fmt::Display for V { 347 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 348 | self.borrow().fmt(f) 349 | } 350 | } 351 | 352 | #[derive(PartialEq, PartialOrd, Eq, Ord, 353 | Copy, Clone, Hash, Debug)] 354 | /// Where there are two fields: expected, then got. 355 | pub enum BadPacket { 356 | TooShort(usize), // header cannot fit 357 | 358 | BadVersion(u8), // isn't 4 359 | BadPacketLength(usize, u16), // not what it really is 360 | 361 | HeaderTooLong(usize, usize), // header declared shorter than min or longer than body 362 | HeaderTooShort(usize), // header declared shorter than min or longer than body 363 | 364 | BadChecksum(u16, u16), 365 | BadOptions, 366 | } 367 | 368 | 369 | pub fn validate(buf: &[u8]) -> Result<(), BadPacket> 370 | { 371 | // have to check this first to avoid out-of-bounds panic on version check 372 | if buf.len() < 1 { 373 | return Err(BadPacket::TooShort(buf.len())) 374 | } 375 | 376 | let packet = A::new(buf); 377 | 378 | // try to do this early as possible in case is other type of packet 379 | if packet.get_version() != 4 { 380 | return Err(BadPacket::BadVersion(packet.get_version())) 381 | }; 382 | 383 | // then this so other header indexing doesn't panic 384 | if packet.as_slice().len() != packet.get_total_length() as usize { 385 | return Err(BadPacket::BadPacketLength(packet.as_slice().len(), 386 | packet.get_total_length())) 387 | }; 388 | 389 | 390 | if packet.hdr_bytes() > packet.as_slice().len() 391 | { 392 | return Err(BadPacket::HeaderTooLong(packet.hdr_bytes(), 393 | packet.as_slice().len())) 394 | }; 395 | if packet.hdr_bytes() < MIN_HDR_LEN_8S as usize 396 | { 397 | return Err(BadPacket::HeaderTooShort(packet.hdr_bytes())) 398 | }; 399 | 400 | { 401 | let expected = packet.make_header_checksum(); 402 | let got = packet.get_header_checksum(); 403 | if expected != got 404 | { 405 | return Err(BadPacket::BadChecksum(expected, got)); 406 | } 407 | }; 408 | 409 | Ok(()) 410 | } 411 | 412 | /// assumes and returns native byte order 413 | pub fn make_checksum(iter: I) -> u16 414 | where I: Iterator 415 | { 416 | let mut sum = iter 417 | .map(|x| x as u32) 418 | .fold(0, |old, cur| old + cur); 419 | 420 | debug!("Untruncated checksum is: {:032b}", sum); 421 | 422 | while sum >> 16 != 0 { 423 | sum = (sum & 0x0000FFFF) + (sum >> 16); 424 | } 425 | 426 | // align debug messages 427 | debug!("Truncated checksum is: {:032b}", sum); 428 | 429 | !(sum as u16) 430 | } 431 | 432 | /// Adjusts len 433 | pub unsafe fn cast_slice(src: &[T]) -> &[U] 434 | { 435 | use core::mem::size_of; 436 | use core::slice; 437 | 438 | assert_eq!(0, src.len() % size_of::()); 439 | 440 | slice::from_raw_parts(src.as_ptr() as _, src.len() / size_of::()) 441 | } 442 | -------------------------------------------------------------------------------- /network/src/ipv4/receive.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | use std::sync::Arc; 3 | 4 | use super::{ 5 | packet, 6 | strategy, 7 | send 8 | }; 9 | 10 | use data_link::interface as dl; 11 | 12 | /// Called upon receipt of an IP packet: 13 | /// If packet is destined for this node, deliver it to appropriate handlers 14 | /// If packet is destined elsewhere, fix packet headers and forward 15 | fn receive<'a, A, E>(state: &super::State<'a, A, E>, buf: Vec) 16 | where A: strategy::RoutingTable<'a> + 'a, 17 | E: Debug 18 | { 19 | debug!("Received packet."); 20 | let packet = match packet::validate(buf.as_slice()) { 21 | Ok(_) => packet::V::new(buf), 22 | Err(e) => { 23 | debug!("dropping incomming packet because {:?}", e); 24 | return; 25 | }, 26 | }; 27 | 28 | debug!("packet header:\n{}", packet.borrow()); 29 | 30 | if is_packet_dst_local(state, &packet) { 31 | debug!("Packet is local! {}", packet); 32 | // local handling 33 | let handlers = &state.protocol_handlers.read().unwrap() 34 | [packet.borrow().get_protocol() as usize]; 35 | // If there are no handlers (vector is empty), the packet is just dropped 36 | // TODO: factor out this clone-until-last-time pattern 37 | let mut iter = handlers.iter().peekable(); 38 | while let Some(ref handler) = iter.next() { 39 | if iter.peek().is_none() { 40 | handler(packet); 41 | break; 42 | } else { 43 | handler(packet.clone()); 44 | } 45 | } 46 | /* 47 | match iter.next() { 48 | None => (), 49 | Some(mut handler) => loop { 50 | match iter.next() { 51 | None => { 52 | // no clone needed! 53 | (&**handler).call((packet,)); 54 | break; 55 | } 56 | Some(h_next) => { 57 | (&**handler).call((packet.clone(),)); 58 | handler = h_next; 59 | } 60 | } 61 | } 62 | }*/ 63 | } else { 64 | debug!("packet is not local! {}", packet); 65 | // handle errors just for logging purposes 66 | match forward(state, packet) { 67 | Ok(_) => (), 68 | Err(e) => debug!("packet could not be fowarded because {:?}", e), 69 | }; 70 | } 71 | } 72 | 73 | /// Forwards a packet back into the network after rewriting its headers 74 | /// Result status is whether packet was able to be forwarded 75 | fn forward<'a, A, E>(state: &super::State<'a, A, E>, mut packet: packet::V) -> send::Result<(), E> 76 | where A: strategy::RoutingTable<'a> + 'a 77 | { 78 | { // Decrement TTL 79 | let ttl = packet.borrow().get_time_to_live() - 1; 80 | if ttl == 0 { return Ok(()); } 81 | packet.borrow_mut().set_time_to_live(ttl); 82 | } 83 | { // Update checksum 84 | packet.borrow_mut().update_checksum(); 85 | } 86 | let row = try!(send::resolve_route( 87 | state, 88 | packet.borrow_mut().get_destination())); 89 | // Do NOT update src address 90 | try!(send::send_manual(row, packet)); 91 | Ok(()) 92 | } 93 | 94 | /// Determine whether packet is destined for this node 95 | fn is_packet_dst_local<'a, A, E>(state: &super::State<'a, A, E>, packet: &packet::V) -> bool 96 | where A: strategy::RoutingTable<'a> + 'a 97 | { 98 | let dst = packet.borrow().get_destination(); 99 | 100 | // TODO: factor out is_neighbor_addr and is_our_addr 101 | state.interfaces.iter() 102 | .any(|&super::InterfaceRow { local_ip, .. }| local_ip == dst) 103 | } 104 | 105 | pub fn make_receive_callback<'a, A, E>(state: Arc>) -> dl::Handler 106 | where A: strategy::RoutingTable<'a> + Send + 'a, 107 | E: Debug + 'a 108 | { 109 | let state = state.clone(); 110 | box move |packet: dl::Packet | { 111 | receive(&*state, packet); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /network/src/ipv4/send.rs: -------------------------------------------------------------------------------- 1 | use std::result; 2 | use std::convert::From; 3 | 4 | use super::{ 5 | packet, 6 | strategy, 7 | }; 8 | 9 | use data_link::interface as dl; 10 | 11 | 12 | #[derive(PartialEq, Eq, Clone, Debug)] 13 | pub enum Error { 14 | NoRoute, 15 | BadPacket(packet::BadPacket), 16 | External(dl::Error), 17 | } 18 | 19 | impl From> for Error { 20 | fn from(e: dl::Error) -> Error { 21 | Error::External(e) 22 | } 23 | } 24 | 25 | pub type Result = ::core::result::Result>; 26 | 27 | 28 | pub fn send 29 | <'st, 'a, A, DE, E, F, G> 30 | (state: &'st super::State<'a, A, DE>, 31 | dst: super::Addr, 32 | protocol: u8, 33 | expected_body_size: Option, 34 | builder: F, 35 | // TODO: make this take a &'st mut packet::A someday 36 | awkward: G) 37 | -> result::Result<(), E> 38 | where A: strategy::RoutingTable<'a> + 'a, 39 | DE: 'a, 40 | E: From>, 41 | F: for<'b> FnOnce(&'b mut packet::V) -> result::Result<(), E> + 'st, 42 | G: for<'b> FnOnce(&'b mut packet::V) -> result::Result<(), E> + 'st, 43 | { 44 | let closure //: for<'p> |&'p mut packet::V| -> 45 | = move |packet: &mut packet::V| -> result::Result<&'st super::InterfaceRow<'a, DE>, E> { 46 | try!(builder(packet)); 47 | debug!("client built packet: {}", packet); 48 | 49 | let row = try!(resolve_route(state, dst)); 50 | packet.borrow_mut().set_source(row.local_ip); 51 | 52 | // TCP needs to hook in here for checksum of "virtual header" 53 | // awkward layer violation is awkward 54 | try!(awkward(packet)); 55 | 56 | Ok(row) 57 | }; 58 | 59 | let (row, packet) = try!(packet::V::new_with_builder::, _>( 60 | dst, 61 | protocol, 62 | expected_body_size, 63 | closure)); 64 | 65 | // final try to do from_error 66 | try!(send_manual(row, packet).map_err(|e| Error::External(e))); 67 | Ok(()) 68 | } 69 | 70 | 71 | /// looks up route for interface and packet src address 72 | pub fn resolve_route<'a, 'st, A, E>(state: &'st super::State<'a, A, E>, 73 | dst: super::Addr) 74 | -> self::Result<&'st super::InterfaceRow<'a, E>, E> 75 | where A: strategy::RoutingTable<'a> + 'a, 76 | 'a: 'st 77 | { 78 | match state.routes.lookup(dst) { 79 | None => Err(self::Error::NoRoute), 80 | Some(next_hop) => { // Send packet to next hop towards destination 81 | debug!("Found route through {}", next_hop); 82 | match state.neighbors.get(&next_hop) { 83 | None => panic!("IP: Route's next hop is not a neighbor!"), 84 | // Tell interface to send packet bytes 85 | Some(index) => Ok(&state.interfaces[*index]) 86 | } 87 | } 88 | } 89 | } 90 | 91 | 92 | /// For anybody that wants to do their own routing 93 | /// and set their own checksum 94 | pub fn send_manual( 95 | row: &super::InterfaceRow, 96 | packet: packet::V) 97 | -> dl::Result<(), E> 98 | { 99 | let &super::InterfaceRow { ref interface, .. } = row; 100 | // need to let here because send consumes packet 101 | let dst = packet.borrow().get_destination(); 102 | try!(interface.write().unwrap().send(packet.to_vec())); 103 | debug!("sent packet to {}", dst); 104 | Ok(()) 105 | } 106 | -------------------------------------------------------------------------------- /network/src/ipv4/strategy.rs: -------------------------------------------------------------------------------- 1 | use std::option::Option; 2 | use std::sync::Arc; 3 | 4 | 5 | pub trait RoutingTable<'a>: Send + Sync + Sized { 6 | 7 | // initialized with the neighbor IPs 8 | fn init(i: I) -> Self where I: Iterator; 9 | 10 | fn lookup(&self, super::Addr) -> Option; 11 | 12 | fn monitor(state: Arc>) -> (); 13 | 14 | fn dump(&self); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /network/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(unboxed_closures)] 2 | #![feature(slice_patterns)] 3 | #![feature(box_syntax)] 4 | #![feature(question_mark)] 5 | 6 | extern crate core; 7 | 8 | #[macro_use] 9 | extern crate log; 10 | #[macro_use] 11 | extern crate bitflags; 12 | 13 | #[macro_use] 14 | extern crate misc; 15 | 16 | mod data_link { 17 | pub extern crate interface; 18 | } 19 | 20 | pub mod ipv4; 21 | -------------------------------------------------------------------------------- /network/tests/ipv4.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_syntax)] 2 | 3 | mod net { 4 | pub extern crate misc; 5 | 6 | pub mod data_link { 7 | pub extern crate interface; 8 | pub extern crate udp_mock; 9 | } 10 | 11 | pub extern crate network; 12 | 13 | pub mod transport { 14 | //pub extern crate brown_rip; 15 | pub extern crate static_routing; 16 | } 17 | } 18 | 19 | use std::fmt; 20 | use std::str::from_utf8; 21 | use std::sync::{Arc, Barrier, RwLock}; 22 | 23 | #[macro_use] 24 | extern crate log; 25 | 26 | use net::data_link::udp_mock::*; 27 | use net::network::ipv4; 28 | use net::network::ipv4::*; 29 | use net::network::ipv4::strategy::RoutingTable; 30 | use net::transport::static_routing::StaticTable; 31 | 32 | pub fn make_ip_to_wait 33 | <'st, R, E> 34 | (interfaces: Vec>, 35 | neighbors: InterfaceTable, 36 | msg: &'st str, 37 | barrier: Arc) 38 | -> Arc> 39 | where R: strategy::RoutingTable<'st> + 'st, 40 | E: fmt::Debug + 'st 41 | 42 | { 43 | let state = ipv4::State::<'st, R, E>::new(interfaces, neighbors); 44 | control::register_protocol_handler::(&*state, 8, box move |packet| { 45 | debug!("got packet: {}", from_utf8(packet.borrow().get_payload()).unwrap()); 46 | debug!("matching against: {}", msg); 47 | assert_eq!(packet.borrow().get_payload(), msg.as_bytes()); 48 | barrier.wait(); 49 | }); 50 | state 51 | } 52 | 53 | fn sending 54 | <'st, R, E> 55 | (state: &ipv4::State<'st, R, E>, 56 | dst: ipv4::Addr, 57 | msg: &'static str) 58 | -> Result<(), ipv4::send::Error> 59 | where R: RoutingTable<'st>, 60 | E: 'st 61 | { 62 | let buf: &[u8] = msg.as_bytes(); 63 | send::send( 64 | state, 65 | dst, 66 | 8, 67 | Some(buf.len() as u16), 68 | | packet | { 69 | packet.as_mut_vec().extend_from_slice(buf); 70 | Ok(()) 71 | }, 72 | |_| Ok(()) ) 73 | } 74 | 75 | macro_rules! map( 76 | { $($key:expr => $value:expr),+ } => { 77 | { 78 | let mut m = ::std::collections::HashMap::new(); 79 | $( 80 | m.insert($key, $value); 81 | )+ 82 | m 83 | } 84 | }; 85 | ); 86 | 87 | #[test] 88 | fn direct_two_nodes() { 89 | static NUM_THREADS: usize = 1; 90 | 91 | let barrier = Arc::new(Barrier::new(3)); 92 | 93 | let (l1, da1) = Listener::new_loopback(NUM_THREADS).unwrap(); 94 | let (l2, da2) = Listener::new_loopback(NUM_THREADS).unwrap(); 95 | 96 | let di1 = Interface::new(&l1, da2, box |_|()); 97 | let di2 = Interface::new(&l2, da1, box |_|()); 98 | 99 | let ia1 = ipv4::Addr([1,1,1,1]); 100 | let ia2 = ipv4::Addr([2,2,2,2]); 101 | 102 | const M1: &'static str = "Hey Node 1!"; 103 | const M2: &'static str = "Hey Node 2!"; 104 | 105 | let i1 = make_ip_to_wait::( 106 | vec![InterfaceRow { local_ip: ia1, interface: RwLock::new(box di1) }], 107 | map!{ia2 => 0}, 108 | M1, 109 | barrier.clone()); 110 | 111 | let i2 = make_ip_to_wait::( 112 | vec![InterfaceRow { local_ip: ia2, interface: RwLock::new(box di2) }], 113 | map!{ia1 => 0}, 114 | M2, 115 | barrier.clone()); 116 | 117 | sending(&*i1, ia2, M2).unwrap(); 118 | sending(&*i2, ia1, M1).unwrap(); 119 | 120 | barrier.wait(); 121 | } 122 | -------------------------------------------------------------------------------- /transport/brown_rip/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-transport-brown-rip" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "brown_rip" 10 | 11 | [dependencies.log] 12 | version = "0.3.6" 13 | 14 | [dependencies.time] 15 | url = "http://github.com/rust-lang/time" 16 | 17 | [dependencies.quilt-net-misc] 18 | path = "../../misc" 19 | 20 | [dependencies.quilt-net-network] 21 | path = "../../network" 22 | -------------------------------------------------------------------------------- /transport/brown_rip/src/comm.rs: -------------------------------------------------------------------------------- 1 | use std::io::IoResult; 2 | use std::sync::Arc; 3 | use std::option::None; 4 | 5 | use network::ipv4::{ 6 | mod, 7 | control, 8 | send, 9 | 10 | InterfaceRow, 11 | InterfaceTable, 12 | }; 13 | 14 | use super::{RIP_INFINITY, RipTable, RipRow}; 15 | use super::packet::{mod, Packet}; 16 | 17 | 18 | fn handle(state: &ipv4::State, packet: ipv4::packet::V) -> IoResult<()> { 19 | let neighbor_addr = packet.borrow().get_source(); 20 | //let interface_addr = packet.borrow().get_destination(); 21 | let data = packet.borrow().get_payload(); 22 | 23 | match state.neighbors.get(&neighbor_addr) { 24 | None => debug!("Odd, got packet from non-neighbor: {}", neighbor_addr), 25 | _ => (), 26 | }; 27 | 28 | match packet::parse(data) { 29 | Ok(Packet::Request) => { 30 | debug!("Got request from {}", neighbor_addr); 31 | 32 | // TODO: factor out singleton iterator 33 | { 34 | let single = [neighbor_addr]; 35 | let unlocked = state.routes.map.write(); 36 | let factory = || unlocked.iter().map(|(a,r)| (*a,r)); // the whole table 37 | 38 | try!(propagate(factory, 39 | single.iter().map(|x| *x), // just who issued the request 40 | &state.neighbors, 41 | state.interfaces.as_slice())); 42 | } 43 | 44 | // TODO factor out empty iterator 45 | let empty: [packet::Entry, ..0] = []; 46 | let empty_iter = empty.as_slice().iter().map(|x| *x); 47 | 48 | try!(update(state, neighbor_addr, empty_iter)); 49 | }, 50 | Ok(Packet::Response(entries)) => { 51 | debug!("Got response from {}", neighbor_addr); 52 | try!(update(state, neighbor_addr, entries)); 53 | }, 54 | _ => debug!("invalid packet received: {}", data), 55 | } 56 | Ok(()) 57 | } 58 | 59 | /// Registers protocol handler for incomming RIP packets. 60 | pub fn register(state: &Arc>) { 61 | let handler = { 62 | let state = state.clone(); 63 | box move |&: packet: ipv4::packet::V | { 64 | handle(&*state, packet).ok().expect("Failure handling incomming IP Packet"); 65 | } 66 | }; 67 | 68 | control::register_protocol_handler( 69 | &**state, 70 | super::RIP_PROTOCOL, 71 | handler) 72 | } 73 | 74 | 75 | /// This method is the sole method of sending a "response" packet. 76 | /// 77 | /// The `key_rows` are written to packets, one per each interface / neighbor. Entries learned about 78 | /// from the neighbor in question will be "poisoned" accordingly. This is fine for the case of 79 | /// sending expired packets to other nodes, as the cost field would be infinite anyways. 80 | /// 81 | /// Note that unlike the normal send method, this does not take any locks. It purposely asks for 82 | /// certain fields of IpState, rather than the structure as a whole, to prevent itself from taking 83 | /// any locks. 84 | pub fn propagate<'a, I, J>(route_subset: ||:'a -> I, 85 | mut neighbor_subset: J, 86 | neighbors: &'a InterfaceTable, 87 | interfaces: &'a [InterfaceRow]) 88 | -> IoResult<()> 89 | where I: Iterator<(ipv4::Addr, &'a RipRow)>, 90 | J: Iterator 91 | { 92 | for neighbor_ip in neighbor_subset 93 | { 94 | debug!("trying to propagate to: {}", neighbor_ip); 95 | 96 | let interface_row = match neighbors.get(&neighbor_ip) { 97 | None => panic!("Can't propagate to non-neighbor: {}", neighbor_ip), 98 | Some(&index) => &interfaces[index], 99 | }; 100 | 101 | let entry_builder = |(route_dst, row): (ipv4::Addr, &'a RipRow)| packet::Entry { 102 | address: route_dst, 103 | cost: if row.next_hop == neighbor_ip { 104 | //poison 105 | RIP_INFINITY 106 | } else { 107 | row.cost 108 | } as u32 109 | }; 110 | 111 | let mut entries_iter = route_subset().map(entry_builder).peekable(); 112 | 113 | while !entries_iter.is_empty() { 114 | 115 | let f = |packet: &mut ipv4::packet::V| { 116 | // needs to be set here to `new_with_builder` sets the correct checksum. 117 | packet.borrow_mut().set_source(interface_row.local_ip); 118 | packet::write_response(&mut entries_iter)(packet.as_mut_vec()) 119 | }; 120 | 121 | let (_, packet) = try!(ipv4::packet::V::new_with_builder( 122 | neighbor_ip, 123 | super::RIP_PROTOCOL, 124 | None, 125 | f)); 126 | match send::send_manual(interface_row, packet) { 127 | Ok(_) => (), 128 | Err(e) => debug!("could not propigate to {}, because {}", neighbor_ip, e), 129 | }; 130 | } 131 | } 132 | Ok(()) 133 | } 134 | 135 | 136 | /// Go through a bunch of entries, update the table, propigate changes 137 | fn update(state: &ipv4::State, 138 | neighbor_addr: ipv4::Addr, 139 | entries_but_neighbor_itself: I) 140 | -> IoResult<()> 141 | where I: Iterator 142 | { 143 | // TODO: factor out singleton iterator 144 | // "cons on" neighbor who just responded 145 | let scratch = [packet::Entry { cost: 0, address: neighbor_addr }]; 146 | let mut entries = scratch.as_slice().iter().map(|x| *x).chain(entries_but_neighbor_itself); 147 | 148 | let mut updated_entries = ::std::collections::hash_map::HashMap::new(); 149 | 150 | for packet::Entry { mut cost, address: dst } in entries { 151 | use std::collections::hash_map::{Occupied, Vacant}; 152 | 153 | // hmm, thoughput or latency? 154 | let mut unlocked = state.routes.map.write(); 155 | 156 | if cost > RIP_INFINITY as u32 { 157 | debug!("received bad cost grater than infinity: {}", cost); 158 | }; 159 | if cost < RIP_INFINITY as u32 { cost += 1; }; // bump cost unless infinite 160 | 161 | debug!("can go to {} with cost {} via {}", dst, cost, neighbor_addr); 162 | 163 | let mk_new_row = || { 164 | RipRow { 165 | time_added: ::time::get_time(), 166 | next_hop: neighbor_addr, 167 | cost: cost as u8, 168 | } 169 | }; 170 | 171 | match unlocked.entry(dst) { 172 | Vacant(entry) => { 173 | if cost < RIP_INFINITY as u32 { // no point spending memory on dead routes 174 | let r = mk_new_row(); 175 | updated_entries.insert(dst, r); 176 | entry.set(r.clone()); 177 | } 178 | }, 179 | Occupied(e) => { 180 | let old = e.into_mut(); 181 | 182 | let no_worse = cost <= old.cost as u32; 183 | let update = neighbor_addr == old.next_hop; 184 | let dead_route = cost >= RIP_INFINITY as u32; 185 | let to_self = state.interfaces.iter() 186 | .any(|&InterfaceRow { local_ip, .. }| local_ip == dst); 187 | 188 | // accept update from neighbor, or better route 189 | // don't bother switching what sort of dead route it is 190 | // don't bother accepting route to self 191 | if (update || (no_worse && !dead_route)) && !to_self 192 | { 193 | let new = mk_new_row(); 194 | debug!("route to {} changed from ({}, {}) to ({}, {})", 195 | dst, old.cost, old.next_hop, new.cost, new.next_hop); 196 | 197 | // only propigate updates that effect cost 198 | // nobody cares about our next hop 199 | // routes renews (i.e. only timestamp changed) are only propigated via periodic updates 200 | if new.cost != old.cost { 201 | updated_entries.insert(dst, new); 202 | } 203 | 204 | *old = new; 205 | } 206 | }, 207 | }; 208 | }; 209 | 210 | // just those keys which were updated 211 | let factory = || updated_entries.iter().map(|(a,r)| (*a,r)); 212 | 213 | try!(propagate(factory, 214 | state.neighbors.keys().map(|x| *x), // tell everyone 215 | &state.neighbors, 216 | state.interfaces.as_slice())); 217 | Ok(()) 218 | } 219 | -------------------------------------------------------------------------------- /transport/brown_rip/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(unboxed_closures)] 2 | #![feature(phase)] 3 | 4 | // for tests 5 | #![feature(globs)] 6 | 7 | #[cfg(not(ndebug))] 8 | #[phase(plugin, link)] 9 | extern crate log; 10 | 11 | #[phase(plugin, link)] 12 | extern crate misc; 13 | extern crate time; 14 | extern crate network; 15 | 16 | use std::collections::HashMap; 17 | use std::sync::{Arc, RWLock}; 18 | 19 | use time::{Timespec, get_time}; 20 | 21 | use network::ipv4; 22 | use network::ipv4::strategy::RoutingTable; 23 | 24 | mod comm; 25 | mod periodic; 26 | mod packet; 27 | 28 | const RIP_INFINITY: u8 = 16; 29 | const RIP_MAX_ENTRIES: u16 = 64; 30 | const RIP_PROTOCOL: u8 = 200; 31 | 32 | #[deriving(Show, Clone)] 33 | pub struct RipRow { 34 | // the next hop is always the same node that told your about the route 35 | pub next_hop: ipv4::Addr, // which neighbor to we send the packet too 36 | pub time_added: Timespec, // Relative to 1970 37 | pub cost: u8, // How many hops 38 | } 39 | 40 | pub struct RipTable { 41 | // key: ipv4:: we want to reach, NOT our interface's IP 42 | map: RWLock>, 43 | } 44 | 45 | impl RoutingTable for RipTable { 46 | 47 | fn lookup(&self, ip: ipv4::Addr) -> Option { 48 | self.map.read().get(&ip).and_then( |table| { 49 | Some(table.next_hop) 50 | }) 51 | } 52 | 53 | fn init(elements: I) -> RipTable where I: Iterator { 54 | let cur_time = get_time(); 55 | // don't need 56 | let routes_iter = elements.map( 57 | |neighbor_addr| 58 | // src is our interface IP, seems like a fine IP to use for the learned-from field 59 | (neighbor_addr, RipRow { 60 | time_added: cur_time, 61 | next_hop: neighbor_addr, 62 | cost: 1, 63 | })); 64 | RipTable { map: RWLock::new(FromIterator::from_iter(routes_iter)) } 65 | } 66 | 67 | fn monitor(state: Arc>) -> () { 68 | debug!("In use"); 69 | comm::register(&state); 70 | periodic::spawn_updater(state.clone()); 71 | periodic::spawn_garbage_collector(state); 72 | } 73 | 74 | fn dump(&self) { 75 | for dst in self.map.read().keys() { 76 | let RipRow { cost, next_hop, time_added } = self.map.read().deref()[*dst]; 77 | println!("{} - {} -> {} [learned at: {} ]", 78 | dst, cost, next_hop, time_added); 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /transport/brown_rip/src/packet.rs: -------------------------------------------------------------------------------- 1 | use std::io::{ 2 | BufReader, 3 | BufWriter, 4 | MemWriter, 5 | SeekSet, 6 | 7 | IoError, 8 | IoResult, 9 | }; 10 | use std::mem::{transmute, size_of}; 11 | 12 | use network::ipv4; 13 | 14 | use super::RIP_MAX_ENTRIES; 15 | 16 | #[deriving(PartialEq, Eq, Clone, Show)] 17 | #[repr(packed)] 18 | pub struct Entry { 19 | pub cost: u32, 20 | pub address: ipv4::Addr, 21 | } 22 | 23 | #[deriving(PartialEq, PartialOrd, Eq, Ord, 24 | Clone, Show)] 25 | #[repr(u16)] 26 | #[repr(packed)] 27 | pub enum Packet { 28 | Request, 29 | Response(Arr), 30 | } 31 | 32 | pub fn parse<'a>(buf: &'a [u8]) -> Result>, ()> { 33 | parse_helper(buf).map_err(|_| ()) 34 | } 35 | 36 | pub type Entries<'a> = EntryIter>; 37 | 38 | struct EntryIter(R); 39 | 40 | impl EntryIter where R: Reader { 41 | 42 | fn next_helper(&mut self) -> IoResult { 43 | let &EntryIter(ref mut r) = self; 44 | let cost = try!(r.read_be_u32()); 45 | let mut addr_buf: [u8, ..4] = [0, 0, 0, 0]; 46 | try!(r.read(addr_buf.as_mut_slice())); 47 | let address = ipv4::parse_addr(&addr_buf); 48 | Ok(Entry { cost: cost, address: address }) 49 | } 50 | } 51 | 52 | impl Iterator for EntryIter where R: Reader 53 | { 54 | fn next(&mut self) -> Option { 55 | self.next_helper().ok() 56 | } 57 | } 58 | 59 | #[inline] 60 | fn parse_helper<'a>(buf: &'a [u8]) -> IoResult>> 61 | { 62 | let mut r = BufReader::new(buf); 63 | match try!(r.read_be_u16()) { 64 | 1 => Ok(Packet::Request), 65 | 2 => { 66 | let count = try!(r.read_be_u16()); 67 | // ought to be static 68 | let hdr_len: uint = size_of::() * 2; 69 | let body_len: uint = size_of::() * 2 * count as uint; 70 | 71 | match buf.len().cmp(&(body_len + hdr_len)) { 72 | Less => return Err(IoError::last_error()), // some random error 73 | Greater => debug!("packet was too large"), 74 | Equal => (), 75 | } 76 | 77 | Ok(Packet::Response(EntryIter(r))) 78 | }, 79 | _ => Err(IoError::last_error()), // some random error 80 | } 81 | } 82 | 83 | pub fn write_request(vec: &Vec) -> IoResult<()> 84 | { 85 | // MemWriter is just a newtype 86 | let m: &mut MemWriter = unsafe { transmute(vec) }; 87 | try!(m.write_be_u16(1)); 88 | try!(m.write_be_u16(0)); 89 | Ok(()) 90 | } 91 | 92 | // iterator must yield at least one entry, or assertion will fall 93 | pub fn write_response<'a, I>(entries_iter: &'a mut I) 94 | -> proc(&mut Vec):'a -> IoResult<()> 95 | where I: Iterator 96 | { 97 | proc(vec) 98 | { 99 | let entries_iter = entries_iter; 100 | let thus_far = vec.len(); 101 | let mut count: u16 = 0; 102 | { 103 | // MemWriter is just a newtype 104 | let m: &mut MemWriter = unsafe { transmute(&*vec) }; 105 | try!(m.write_be_u16(2)); 106 | try!(m.write_be_u16(0x_FF_FF)); // place holder 107 | 108 | // this seems overly manual, except I need to remember number of times I 109 | // loop 110 | while count < RIP_MAX_ENTRIES { 111 | let Entry { cost, address } = match entries_iter.next() { 112 | Some(e) => e, 113 | None => break, 114 | }; 115 | count += 1; 116 | try!(m.write_be_u32(cost)); 117 | try!(m.write(&ipv4::write_addr(address))); 118 | } 119 | assert!(count > 0); // we don't want to send empty response packets 120 | } 121 | { 122 | let mut b = BufWriter::new(vec.as_mut_slice()); 123 | try!(b.seek((thus_far + size_of::()) as i64, SeekSet)); 124 | debug!("fixing count ({}) when writing entries_iter", count); 125 | try!(b.write_be_u16(count)); 126 | } 127 | Ok(()) 128 | } 129 | } 130 | 131 | #[cfg(test)] 132 | mod test { 133 | use super::*; 134 | 135 | use std::io::net::ip::{IpAddr, Ipv4Addr}; 136 | use std::io::{ 137 | BufReader, 138 | BufWriter, 139 | MemWriter, 140 | SeekSet, 141 | 142 | IoError, 143 | IoResult, 144 | }; 145 | 146 | #[test] 147 | fn parse_invalid() { 148 | assert!(parse(&[0]).is_err()); 149 | assert!(parse(&[1]).is_err()); 150 | assert!(parse(&[2]).is_err()); 151 | 152 | assert!(parse(&[0,0]).is_err()); 153 | assert!(parse(&[1,0]).is_err()); 154 | assert!(parse(&[2,0]).is_err()); 155 | 156 | assert!(parse(&[0,0]).is_err()); 157 | assert!(parse(&[1,0,0]).is_err()); 158 | assert!(parse(&[2,0,0,0]).is_err()); 159 | 160 | assert!(parse(&[1,1,0]).is_err()); 161 | assert!(parse(&[2,1,0,0]).is_err()); 162 | } 163 | 164 | #[test] 165 | fn parse_request() { 166 | assert_eq!(parse(&[0,1]), Ok(Request)); 167 | } 168 | 169 | #[test] 170 | fn parse_response() { 171 | let empty: [Entry, ..0] = []; 172 | assert_eq!(parse(&[0,2,0,0]), Ok(Response(empty.as_slice()))); 173 | } 174 | 175 | #[test] 176 | fn write_request() { 177 | let msg: &[u8] = &[0,1,0,0]; 178 | let vec = Vec::new(); 179 | super::write_request(&vec).unwrap(); 180 | assert_eq!(vec.as_slice(), msg); 181 | } 182 | 183 | #[test] 184 | fn write_response() { 185 | { 186 | let empty: [Entry, ..0] = []; 187 | let msg: &[u8] = &[0,2,0,0]; 188 | 189 | let vec = Vec::new(); 190 | write(Response(empty.iter().map(|x| *x)))(&vec).unwrap(); 191 | assert_eq!(vec.as_slice(), msg); 192 | } 193 | { 194 | let entries = [Entry { cost: 5, address: ipv4::write_addr(Ipv4Addr(1,2,3,4)) }, 195 | Entry { cost: 16, address: ipv4::write_addr(Ipv4Addr(5,4,3,2)) }]; 196 | let msg: &[u8] = &[0,2,0,2, 197 | 0,0,0,5, 1,2,3,4, 198 | 0,0,0,16, 5,4,3,2]; 199 | 200 | let vec = Vec::new(); 201 | super::write_responce(Response(entries.iter().map(|x| *x)))(&vec).unwrap(); 202 | assert_eq!(vec.as_slice(), msg); 203 | } 204 | } 205 | 206 | } 207 | -------------------------------------------------------------------------------- /transport/brown_rip/src/periodic.rs: -------------------------------------------------------------------------------- 1 | use std::io::Timer; 2 | use std::sync::Arc; 3 | use std::time::Duration; 4 | 5 | use time::{Timespec, get_time}; 6 | 7 | use network::ipv4; 8 | 9 | use super::{RIP_INFINITY, RipRow, RipTable}; 10 | use super::comm::propagate; 11 | 12 | 13 | const UPDATE_PERIOD: i64 = 5; 14 | const EXPIRATION_PERIOD: i64 = 12; 15 | 16 | 17 | pub fn spawn_updater(state: Arc>) { 18 | spawn(proc() { 19 | let mut timer = Timer::new().unwrap(); 20 | let periodic = timer.periodic(Duration::seconds(UPDATE_PERIOD)); 21 | loop { 22 | debug!("periodic update"); 23 | periodic.recv(); 24 | update(&*state); 25 | } 26 | }) 27 | } 28 | 29 | fn update(state: &ipv4::State) { 30 | let unlocked = state.routes.map.read(); 31 | // propegate the whole damn table! 32 | let factory = || unlocked.iter().map(|(a,r)| (*a,r)); 33 | 34 | // ignore errors, for now 35 | let _ = propagate(factory, 36 | state.neighbors.keys().map(|x| *x), // tell everyone 37 | &state.neighbors, 38 | state.interfaces.as_slice()); 39 | } 40 | 41 | pub fn spawn_garbage_collector(state: Arc>) { 42 | spawn(proc() { 43 | let mut timer = Timer::new().unwrap(); 44 | // half the expiration period to ensure nothing lives too long 45 | let periodic = timer.periodic(Duration::seconds(EXPIRATION_PERIOD / 2)); 46 | loop { 47 | debug!("Periodic gc"); 48 | periodic.recv(); 49 | collector_garbage(&*state); 50 | } 51 | }) 52 | } 53 | 54 | fn collector_garbage(state: &ipv4::State) { 55 | let cur_time = get_time(); 56 | 57 | let mut bad_keys: Vec = Vec::new(); 58 | { // naked block to make sure lock is released 59 | let mut bad_rows: Vec<&RipRow> = Vec::new(); 60 | 61 | let mut table = state.routes.map.write(); 62 | for (dst, row) in table.iter_mut() { 63 | let deadline = Timespec { 64 | sec: row.time_added.sec + EXPIRATION_PERIOD, 65 | ..row.time_added 66 | }; 67 | // allowed to forget neighbors, though the neighbor -> interface map 68 | // will remember them 69 | if row.cost == RIP_INFINITY || deadline <= cur_time 70 | { 71 | row.cost = RIP_INFINITY; // dead rows shall be poisonsed 72 | bad_keys.push(*dst); 73 | bad_rows.push(row); 74 | } 75 | } 76 | 77 | let zip_iter_factory = || bad_keys.iter() 78 | .map(|x| *x) 79 | .zip(bad_rows.iter().map(|x| *x)); 80 | 81 | // ignore errors, for now 82 | let _ = propagate(zip_iter_factory, 83 | state.neighbors.keys().map(|x| *x), // all neighbors 84 | &state.neighbors, 85 | state.interfaces.as_slice()); 86 | } 87 | 88 | for k in bad_keys.into_iter() { 89 | // lock is reaquired 90 | let mut table = state.routes.map.write(); 91 | table.remove(&k); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /transport/static_routing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-transport-static-routing" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "static_routing" 10 | 11 | [dependencies] 12 | log = { version = "0.3.6", default-features = false } 13 | 14 | quilt-net-misc = { path = "../../misc" } 15 | quilt-net-network = { path = "../../network" } 16 | -------------------------------------------------------------------------------- /transport/static_routing/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | #[macro_use] 5 | extern crate misc; 6 | 7 | extern crate network; 8 | 9 | use std::collections::HashMap; 10 | use std::sync::{Arc, RwLock}; 11 | 12 | use network::ipv4; 13 | use network::ipv4::strategy::RoutingTable; 14 | 15 | #[derive(Debug)] 16 | pub struct StaticTable { 17 | // key: Ip we want to reach, NOT our interface's IP 18 | // value: Ip of neighbor we want to send to 19 | map: RwLock>, 20 | } 21 | 22 | impl<'a> RoutingTable<'a> for StaticTable { 23 | 24 | fn lookup(&self, ip: ipv4::Addr) -> Option { 25 | self.map.read().unwrap().get(&ip).map(|x| *x) 26 | } 27 | 28 | fn init(elements: I) -> StaticTable where I: Iterator { 29 | // make I <-> I, the ID map 30 | let routes_iter = elements.map(|neighbor_ip| (neighbor_ip, neighbor_ip)); 31 | StaticTable { map: RwLock::new(routes_iter.collect()) } 32 | } 33 | 34 | fn monitor(_state: Arc>) -> () { 35 | debug!("In use"); 36 | } 37 | 38 | fn dump(&self) { 39 | for vip in self.map.read().unwrap().keys() { 40 | let next_hop = self.map.read().unwrap()[vip]; 41 | info!("{} -> {}", vip, next_hop); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /transport/tcp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "quilt-net-transport-tcp" 4 | version = "0.0.1" 5 | authors = [ "Anson Rosenthal " 6 | , "John Ericson " ] 7 | 8 | [lib] 9 | name = "tcp" 10 | 11 | [dependencies] 12 | time = { url = "http://github.com/rust-lang/time" } 13 | 14 | quilt-net-misc = { path = "../../misc" } 15 | quilt-net-network = { path = "../../network" } 16 | cyclic-order = { path = "../../cyclic_order" } 17 | 18 | [dev-dependencies] 19 | quickcheck_macros = { git = "https://github.com/BurntSushi/quickcheck" } 20 | -------------------------------------------------------------------------------- /transport/tcp/src/access.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::hash_map::{Occupied, Vacant}; 3 | use std::io::net::ip::Port; 4 | use std::sync::{ 5 | RWLock, 6 | RWLockReadGuard, 7 | RWLockWriteGuard, 8 | }; 9 | 10 | use listener::Listener; 11 | use connection::Connection; 12 | 13 | use send; 14 | 15 | #[inline] 16 | pub fn get_per_port 17 | <'s> 18 | (tcp_table: &'s RWLockReadGuard<'s, ::Table>, 19 | local_port: Port) 20 | -> Result<&'s::PerPort, ()> 21 | { 22 | match tcp_table.get(&local_port) { 23 | Some(st) => Ok(st), 24 | None => Err(()) 25 | } 26 | } 27 | 28 | #[inline] 29 | pub fn reserve_per_port_mut 30 | <'s> 31 | (tcp_table: &'s mut RWLockWriteGuard<'s, ::Table>, 32 | local_port: Port) 33 | -> &'s mut ::PerPort 34 | { 35 | match tcp_table.entry(local_port) { 36 | Vacant(entry) => entry.set(::PerPort { // allocate blank 37 | listener: RWLock::new(Listener::Closed), 38 | connections: RWLock::new(HashMap::new()), 39 | }), 40 | Occupied(entry) => entry.into_mut(), 41 | } 42 | } 43 | 44 | #[inline] 45 | pub fn reserve_connection_mut 46 | <'s> 47 | (subtable: &'s mut RWLockWriteGuard<'s, ::SubTable>, 48 | foreign_addr: ::ConAddr) 49 | -> &'s mut RWLock 50 | { 51 | match subtable.entry(foreign_addr) { 52 | Vacant(entry) => entry.set(RWLock::new(Connection::Closed)), 53 | Occupied(entry) => entry.into_mut(), 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /transport/tcp/src/capability/c.rs: -------------------------------------------------------------------------------- 1 | use std::io::net::ip::Port; 2 | use std::io::{ 3 | Reader, 4 | Writer, 5 | IoResult, 6 | IoError, 7 | IoErrorKind 8 | }; 9 | 10 | use std::sync::{Arc, Weak, Mutex, RWLock}; 11 | use std::comm::{ 12 | Sender, 13 | Receiver, 14 | }; 15 | 16 | use network::ipv4; 17 | use network::ipv4::strategy::RoutingTable; 18 | 19 | use connection::{ 20 | mod, 21 | Connection, 22 | }; 23 | use listener; 24 | use send; 25 | 26 | use super::{l, L}; 27 | 28 | 29 | /// Capability that gives synchronous access to a Connection 30 | // TODO: not too great that ipv4::State's routing strategy is leaking this far. 31 | pub struct C 32 | where A: RoutingTable 33 | { 34 | state: Arc<::State>, 35 | 36 | con: Weak>, 37 | can_read: Receiver<()>, 38 | can_write: Receiver<()>, 39 | } 40 | 41 | impl C 42 | where A: RoutingTable 43 | { 44 | pub fn connect(state: &Arc<::State>, 45 | us: Port, 46 | them: ::ConAddr) 47 | -> send::Result> 48 | { 49 | let (handler, rd_rx, wt_rx) = make_con_handler(); 50 | 51 | let con = try!(connection::handshaking::Handshaking::new( 52 | state, us, None, them, 53 | false, false, None, None, handler)); 54 | 55 | Ok(new(state, con, rd_rx, wt_rx)) 56 | } 57 | 58 | /// Convenience wrapper. If you always are going to do non-blocking, use the 59 | /// async API instead. 60 | /// 61 | /// `None` means no connection / closed. `Some(n)` is n number of bytes read. 62 | pub fn read_nonblock(&mut self, buf: &mut [u8]) -> Result 63 | { 64 | debug!("trying to do a non-blocking read"); 65 | let arc = match self.con.upgrade() { 66 | Some(a) => a, 67 | None => return Err(()), 68 | }; 69 | 70 | let mut lock = arc.write(); 71 | let mut est = match &mut *lock { 72 | &Connection::Established(ref mut est) => est, 73 | _ => return Err(()), 74 | }; 75 | Ok(est.read(&*self.state, buf)) 76 | } 77 | 78 | // Returns (send, receive) window sizes for this connection 79 | pub fn get_window(&self) -> ((u32, u16), (u32, u16)) { 80 | self.con.upgrade().unwrap().read().deref().get_window() 81 | } 82 | } 83 | 84 | const EOF: IoError = IoError { 85 | kind: IoErrorKind::EndOfFile, 86 | desc: "TCP connection is apparently closed!", 87 | detail: None, 88 | }; 89 | 90 | impl Reader for C 91 | where A: RoutingTable 92 | { 93 | fn read(&mut self, mut buf: &mut [u8]) -> IoResult 94 | { 95 | let num_requested = buf.len(); 96 | debug!("trying to do a blocking read"); 97 | let arc = match self.con.upgrade() { 98 | Some(l) => l, 99 | None => return Err(EOF), 100 | }; 101 | 102 | let mut total_read = 0; 103 | 104 | loop { 105 | { 106 | let mut lock = arc.write(); 107 | let mut est = match &mut *lock { 108 | &Connection::Established(ref mut est) => est, 109 | _ if total_read == 0 => return Err(EOF), 110 | _ => return Ok(total_read), // semi-success: next call will EOF 111 | }; 112 | //debug!("reading from est"); 113 | let n = est.read(&*self.state, buf); 114 | //debug!("tcb read {} bytes", n); 115 | { 116 | // TODO report this annoying situation 117 | let temp1 = buf; 118 | let temp2 = temp1[mut n..]; 119 | buf = temp2; 120 | } 121 | total_read += n; 122 | //debug!("total read so far is {}", total_read); 123 | //debug!("buf is {}", buf); 124 | if total_read == num_requested { return Ok(total_read) }; // success 125 | assert!(total_read < num_requested); 126 | }; 127 | // block, after letting go of lock 128 | self.can_read.recv(); 129 | } 130 | } 131 | } 132 | 133 | 134 | impl Writer for C 135 | where A: RoutingTable 136 | { 137 | fn write(&mut self, mut buf: &[u8]) -> IoResult<()> 138 | { 139 | debug!("trying to do a blocking write"); 140 | let arc = match self.con.upgrade() { 141 | Some(l) => l, 142 | None => return Err(EOF), 143 | }; 144 | 145 | loop { 146 | { 147 | let mut lock = arc.write(); 148 | let mut est = match &mut *lock { 149 | &Connection::Established(ref mut est) => est, 150 | _ => return Err(EOF), 151 | }; 152 | let n = est.write(&*self.state, buf); 153 | buf = buf[n..]; 154 | if buf.len() == 0 { return Ok(()) }; 155 | }; 156 | // block, after letting go of lock 157 | self.can_write.recv(); 158 | } 159 | } 160 | } 161 | 162 | 163 | pub fn new(state: &Arc<::State>, 164 | con: Weak>, 165 | rd_rx: Receiver<()>, 166 | wt_rx: Receiver<()>) 167 | -> C 168 | where A: RoutingTable 169 | { 170 | // block on first CanRead---to signify that connection is established 171 | rd_rx.recv(); 172 | 173 | C { 174 | state: state.clone(), 175 | 176 | con: con, 177 | can_read: rd_rx, 178 | can_write: wt_rx, 179 | } 180 | } 181 | 182 | pub fn make_con_handler() -> (connection::established::Handler, Receiver<()>, Receiver<()>) 183 | { 184 | use connection::established::Established; 185 | use connection::established::Situation; 186 | 187 | 188 | let (rd_tx, rd_rx) = channel::<()>(); 189 | let (wt_tx, wt_rx) = channel::<()>(); 190 | 191 | let handler = { 192 | // TODO: this mutex is not necessary 193 | let rd = Mutex::new(rd_tx); 194 | let wt = Mutex::new(wt_tx); 195 | box move |&mut: est: Established, situ: Situation| { 196 | debug!("in C-Capability Handler"); 197 | match situ { 198 | Situation::CanRead => rd.lock().send(()), 199 | Situation::CanWrite => wt.lock().send(()), 200 | }; 201 | Connection::Established(est) 202 | } 203 | }; 204 | (handler, rd_rx, wt_rx) 205 | } 206 | 207 | /* 208 | impl fmt::Show for Capability 209 | where A: RoutingTable { 210 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 211 | } 212 | } 213 | */ 214 | -------------------------------------------------------------------------------- /transport/tcp/src/capability/l.rs: -------------------------------------------------------------------------------- 1 | use std::io::net::ip::Port; 2 | use std::sync::{Arc, Weak, Mutex}; 3 | use std::comm::{ 4 | Sender, 5 | Receiver, 6 | }; 7 | 8 | use network::ipv4; 9 | use network::ipv4::strategy::RoutingTable; 10 | 11 | use connection::{ 12 | mod, 13 | Connection, 14 | }; 15 | use listener; 16 | use send; 17 | 18 | use super::{c, C}; 19 | 20 | 21 | /// Capability that gives synchronous access to a Listener 22 | // TODO: not too great that ipv4::State's routing strategy is leaking this far. 23 | pub struct L 24 | where A: RoutingTable 25 | { 26 | us: Port, 27 | weak: Weak<::PerPort>, 28 | 29 | state: Arc<::State>, 30 | requests: Receiver 31 | } 32 | 33 | impl L 34 | where A: RoutingTable 35 | { 36 | pub fn listen(state: &Arc<::State>, 37 | us: Port) 38 | -> send::Result> 39 | { 40 | let (tx, rx) = channel::(); 41 | 42 | let handler = { 43 | // TODO: this mutex is not necessary 44 | let request = Mutex::new(tx); 45 | box move |&mut: us: ::ConAddr, them: ::ConAddr, call | { 46 | debug!("in L-Capability Handler"); 47 | request.lock().send((us, them, call)); 48 | true // keep on listening 49 | } 50 | }; 51 | 52 | let weak = try!(::listener::passive_new::( 53 | &**state, 54 | handler, 55 | us)); 56 | 57 | Ok(self::L { 58 | us: us, 59 | weak: weak, 60 | 61 | state: state.clone(), 62 | requests: rx, 63 | }) 64 | } 65 | 66 | pub fn accept(&self) -> send::Result> { 67 | debug!("Accept called on capability {}", self.us); 68 | // get info and black-box function to actually make the connection 69 | let (_, _, mk_con) = self.requests.recv(); 70 | // make handler and receives to interact with connection 71 | let (handler, rd_rx, wt_rx) = c::make_con_handler(); 72 | // make connection with handler 73 | let weak_ref = try!(mk_con.call_once((handler,))); 74 | // make connection capability with weak ref to handler 75 | Ok(c::new(&self.state, weak_ref, rd_rx, wt_rx)) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /transport/tcp/src/capability/mod.rs: -------------------------------------------------------------------------------- 1 | /// A TCP Capability is mostly analogous to a (TCP) Socket on 2 | /// Unix. This library wraps the more low-level core implementation to 3 | /// provide a "blocking", synchronous interface. 4 | /// 5 | /// While in the core interface connections and listeners need to be 6 | /// explicitly closed, that would be undesirable burden on the users 7 | /// of this implementation. Once all capabilities are dropped, nobody 8 | /// will be able to access the underlying connection without using the 9 | /// core interface. Therefore, once they are all dropped the 10 | /// connection will be automatically closed. If you don't like that, 11 | /// use the core interface. 12 | 13 | 14 | // TODO: clonable capabilities 15 | 16 | 17 | pub use self::l::L; 18 | pub use self::c::C; 19 | 20 | mod l; 21 | mod c; 22 | -------------------------------------------------------------------------------- /transport/tcp/src/concurrent_hash_map.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::BorrowFrom; 2 | use std::collections::HashMap; 3 | use std::collections::hash_map::{Entry, Occupied, Vacant}; 4 | use std::fmt; 5 | use std::default::Default; 6 | use std::hash::{ 7 | Hash, 8 | Hasher, 9 | RandomSipHasher 10 | }; 11 | use std::sync::{ 12 | Arc, 13 | Weak, 14 | RWLock 15 | }; 16 | 17 | /// This is a very shitty concurrent hash map that will do for now 18 | pub struct ConcurrentHashMap(RWLock, H>>); 19 | 20 | impl ConcurrentHashMap 21 | where K: Send + Sync + Hash + Eq + fmt::Show, 22 | V: Send + Sync + fmt::Show, 23 | { 24 | pub fn new() -> ConcurrentHashMap 25 | { 26 | ConcurrentHashMap(RWLock::new(HashMap::new())) 27 | } 28 | } 29 | 30 | impl ConcurrentHashMap 31 | where K: Send + Sync + Eq + Hash + fmt::Show, 32 | V: Send + Sync + fmt::Show, 33 | H: Send + Sync + Hasher, 34 | { 35 | pub fn get(&self, k: &Q) -> Option> 36 | where Q: Hash + Eq + BorrowFrom 37 | { 38 | self.0.read().get(k).map(|v| v.clone()) 39 | } 40 | 41 | //fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> 42 | //{ 43 | // 44 | //} 45 | 46 | pub fn get_or_init(&self, 47 | k: K, 48 | init: || -> V) 49 | -> Arc 50 | { 51 | // Upside, might avoid write lock. Downside, first come first SUCKER 52 | match self.get(&k) { 53 | Some(v) => return v.clone(), 54 | _ => (), 55 | } 56 | 57 | match self.0.write().entry(k) { 58 | Vacant(entry) => { 59 | let arc = entry.set(Arc::new(init())); 60 | arc.clone() 61 | } 62 | Occupied(entry) => entry.into_mut().clone(), 63 | } 64 | } 65 | 66 | pub fn dump(&self) { 67 | let mut ix = 0u; 68 | for (k, v) in self.0.read().iter() { 69 | println!("[{}] {}: {}", ix, k, v); 70 | ix += 1; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/established/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::hash_map::{Occupied, Vacant}; 3 | use std::io::net::ip::Port; 4 | use std::sync::{Arc,RWLock, Weak}; 5 | use std::time::duration::Duration; 6 | 7 | use network::ipv4; 8 | use network::ipv4::strategy::RoutingTable; 9 | 10 | use packet::{mod, TcpPacket}; 11 | use send::{mod, Error,}; 12 | 13 | use super::Connection; 14 | use self::tcb::TCB; 15 | use self::tcb::timer; 16 | 17 | 18 | pub mod tcb; 19 | 20 | 21 | pub enum Situation { 22 | CanRead, 23 | CanWrite, 24 | } 25 | 26 | pub type Handler = 27 | Box + Send + Sync + 'static>; 28 | 29 | // especially must be private because we cheat on whether the fields exist 30 | pub struct Established { 31 | us: ::ConAddr, 32 | them: ::ConAddr, 33 | 34 | handler: Handler, 35 | tcb: TCB, 36 | } 37 | 38 | impl super::State for Established 39 | { 40 | fn next(self, 41 | state: &::State, 42 | packet: TcpPacket) 43 | -> Connection 44 | where A: RoutingTable 45 | { 46 | match self.next_raii(state, packet) 47 | { 48 | Ok(con) => con, 49 | Err(_) => Connection::Closed, 50 | } 51 | } 52 | 53 | fn close(self, _state: &::State) -> Connection 54 | where A: RoutingTable 55 | { 56 | debug!("TODO: close for established"); 57 | Connection::Established(self) 58 | } 59 | 60 | fn checkup(mut self, 61 | state: &::State, 62 | interval: &mut Duration) 63 | -> (Connection, bool) 64 | where A: RoutingTable 65 | { 66 | debug!("TODO: checkup for established"); 67 | 68 | tcb::timer::on_timeout(&mut self, state, interval); 69 | 70 | // false == don't kill timer thread 71 | (Connection::Established(self), false) 72 | } 73 | } 74 | 75 | impl Established 76 | { 77 | fn next_raii(mut self, 78 | state: &::State, 79 | packet: TcpPacket) 80 | -> send::Result 81 | where A: RoutingTable 82 | { 83 | let us = (packet.get_dst_addr(), packet.get_dst_port()); 84 | let them = (packet.get_src_addr(), packet.get_src_port()); 85 | 86 | assert_eq!(self.us, us); 87 | assert_eq!(self.them, them); 88 | 89 | debug!("TCB bout to recv!"); 90 | let (r, w) = self.tcb.recv(packet); 91 | debug!("TCB recv yielded (r:{}, w:{})", r, w); 92 | 93 | let self2 = if r { 94 | self.invoke_handler(Situation::CanRead) 95 | } else { 96 | Connection::Established(self) 97 | }; 98 | 99 | let self3 = match self2 { 100 | Connection::Established(est) => if w { 101 | est.invoke_handler(Situation::CanWrite) 102 | } else { 103 | Connection::Established(est) 104 | }, 105 | _ => self2, 106 | }; 107 | 108 | 109 | // TODO Check if control packet -> transition to close 110 | 111 | // TODO 112 | // Handle as received data: 113 | // If enitrely outside window, discard 114 | // If we can add to window, do this 115 | // If this means application can read more, signal by calling CanRead 116 | 117 | // self.tcb.recv(_packet, CanRead); 118 | 119 | // stay established 120 | Ok(self3) 121 | } 122 | 123 | 124 | pub fn invoke_handler(mut self, situ: Situation) -> Connection 125 | { 126 | use std::mem::swap; 127 | 128 | debug!("Established connection is invoking its handler"); 129 | let mut handler: Handler = box move |&mut: _, _| { 130 | debug!("I am a dummy closure used by swap, don't call me!!!"); 131 | panic!(); 132 | }; 133 | 134 | // 1st swap 135 | swap(&mut self.handler, &mut handler); 136 | 137 | let mut con: Connection = handler.call_mut((self, situ)); 138 | 139 | match con { 140 | // 2nd swap 141 | Connection::Established(ref mut e) => swap(&mut e.handler, &mut handler), 142 | _ => (), 143 | }; 144 | 145 | con 146 | } 147 | 148 | pub fn new(state: &::State, 149 | us: ::ConAddr, 150 | them: ::ConAddr, 151 | our_isn: u32, 152 | their_isn: u32, 153 | their_wnd: u16, 154 | handler: Handler) 155 | -> Connection 156 | where A: RoutingTable 157 | { 158 | debug!("Established connection on our addr {} to server {}", us, them); 159 | let est = Established { 160 | us: us, 161 | them: them, 162 | handler: handler, 163 | tcb: TCB::new(our_isn, their_isn, their_wnd) 164 | }; 165 | 166 | // first CanRead let's them know connection was made 167 | est.invoke_handler(Situation::CanRead) 168 | } 169 | 170 | /// non-blocking, returns how much was written to caller's buffer 171 | pub fn read(&mut self, 172 | state: &::State, 173 | buf: &mut [u8]) 174 | -> uint 175 | where A: RoutingTable 176 | { 177 | debug!("trying to do a non-blocking read: est"); 178 | self.tcb.read(buf) 179 | } 180 | 181 | /// non-blocking, returns how much was read from caller's buffer 182 | pub fn write(&mut self, 183 | state: &::State, 184 | buf: &[u8]) 185 | -> uint 186 | where A: RoutingTable 187 | { 188 | debug!("trying to do a non-blocking write"); 189 | self.tcb.send(buf, state, self.us, self.them) 190 | } 191 | 192 | pub fn get_window(&self) -> ((u32, u16), (u32, u16)) { 193 | self.tcb.get_window() 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/established/tcb/mod.rs: -------------------------------------------------------------------------------- 1 | use std::io::BufWriter; 2 | use std::cmp; 3 | 4 | use network::ipv4::strategy::RoutingTable; 5 | use network::ipv4::Addr; 6 | 7 | use packet::{mod, TcpPacket}; 8 | use send; 9 | 10 | use connection::packet_buf::{ 11 | BestPacketBuf, 12 | PacketBuf, 13 | // PacketBufIter, 14 | get_next_write_seq, 15 | }; 16 | use self::timer::RetransmitData; 17 | //use super::manager::recv::RecvMgr; 18 | //use super::manager::send::SendMgr; 19 | 20 | 21 | pub mod timer; 22 | 23 | 24 | pub const TCP_MSS : u16 = 536u16; 25 | pub const TCP_BUF_SIZE : u16 = ((1u32 << 16u) - 1u32) as u16; 26 | pub const TCP_RECV_WND_INIT : u16 = TCP_BUF_SIZE; 27 | pub const TCP_MAX_RETRIES : uint = 5u; 28 | 29 | #[deriving(Show)] 30 | pub struct TcbState { 31 | pub recv_WND: u16, // Recv Window Size 32 | pub send_WND: u16, // Send Window Size 33 | //pub send_UP: u32, // send urgent pointer 34 | pub send_WL1: u32, // Seq number for last window update 35 | pub send_WL2: u32, // Ack number for last window update 36 | } 37 | 38 | impl TcbState 39 | { 40 | 41 | //TODO: initialize all these variables from handshake!!! 42 | pub fn new(our_isn: u32, their_isn: u32, their_wnd: u16) -> TcbState { 43 | TcbState { 44 | recv_WND: TCP_RECV_WND_INIT, 45 | send_WND: their_wnd, //INIT: get from what they tell us 46 | send_WL1: their_isn, //they should be acking what we send and vice-versa 47 | send_WL2: our_isn, 48 | } 49 | } 50 | } 51 | 52 | 53 | /// Encapsulates all connection state and data structures 54 | pub struct TCB { 55 | read: BestPacketBuf, 56 | write: BestPacketBuf, 57 | 58 | // Buffers 59 | //recv_mgr : RecvMgr, 60 | //send_mgr : SendMgr, 61 | state: TcbState, 62 | transmit_data: RetransmitData, 63 | } 64 | 65 | impl TCB 66 | { 67 | pub fn new(our_isn: u32, their_isn: u32, their_wnd: u16) -> TCB { 68 | TCB { 69 | read : PacketBuf::new(their_isn), 70 | write : PacketBuf::new(our_isn), 71 | state : TcbState::new(our_isn, their_isn, their_wnd), 72 | transmit_data: RetransmitData::new(), 73 | } 74 | } 75 | 76 | // ******** TCP Module API ***********************************// 77 | 78 | // Returns the socket's (send, receive) windows 79 | pub fn get_window(&self) -> ((u32, u16), (u32, u16)) { 80 | ((self.write.get_next_consume_seq(), self.state.send_WND), (self.read.get_next_consume_seq(), self.state.recv_WND)) 81 | } 82 | 83 | /// Receive logic for TCP packet 84 | pub fn recv(&mut self, packet: TcpPacket) -> (bool, bool) 85 | { 86 | let mut can_read = false; 87 | let mut can_write = false; 88 | // Validate (ACK, SEQ in appropriate intervals) 89 | // Is duplicate? -> trash TODO: quick duplicate detection 90 | if self.validate_packet_state(&packet) { 91 | 92 | debug!("Valid state for packet SEQ:{}, LEN:{}", packet.get_seq_num(), packet.get_body_len()); 93 | let seg_SEQ = packet.get_seq_num(); 94 | let seg_WND = packet.get_window_size(); 95 | 96 | // If ACK 97 | if let Some(seg_ACK) = packet.get_ack_num() { 98 | debug!("is ACK packet"); 99 | // If ACKing new data 100 | // FIXME: is this covered in validate_packet_state()? 101 | 102 | if mod_in_interval(self.write.get_next_consume_seq(), 103 | get_next_write_seq(&self.write), 104 | seg_ACK) 105 | { 106 | debug!("ACKing new data"); 107 | 108 | let una = self.write.get_next_consume_seq(); 109 | 110 | // UPDATE TIMER STATE 111 | // (NEED X LEVELS of these if you have X max retransmission limit) 112 | // if seg_ACK <= last_retransmitted 113 | // don't care 114 | // elif seg_ACK <= send.NXT 115 | // RTT_last = now() - last_transmit_time() 116 | // else: 117 | // This is an invalid ACK.... 118 | 119 | self.transmit_data.update_rtt_from_ack(seg_ACK); 120 | 121 | 122 | // Fast-forward our retransmission queue up to the ACK 123 | let _= self.write.consume_iter() 124 | .zip(::std::iter::count(una, 1)) 125 | .take_while(|&(_, n): &(u8, u32) | n != seg_ACK) 126 | .last(); 127 | 128 | // -> if (send_WL1 < SEG.SEQ) or (send_WL1 == SEG.SEQ && send_WL2 <= SEG.ACK) 129 | if (self.state.send_WL1 < seg_SEQ) || 130 | (self.state.send_WL1 == seg_SEQ && self.mod_leq(self.state.send_WL2, seg_ACK)) 131 | { 132 | self.state.send_WND = seg_WND; 133 | self.state.send_WL1 = seg_SEQ; 134 | self.state.send_WL2 = seg_ACK; 135 | } else { 136 | debug!("valid packet with shrinking ACK?"); 137 | // -> else 138 | // -> don't care 139 | } 140 | // We have more space to write into now 141 | can_write = true; 142 | // | OR start timer to buffer ACKS to only annouce the highest ACK instead of notifying X 143 | // times 144 | } 145 | } 146 | 147 | { 148 | let old_recv_next = get_next_write_seq(&self.read); 149 | 150 | // add packet to buffer 151 | { 152 | // need to let, because packet will be moved 153 | let seq = packet.get_seq_num(); 154 | let offset = packet.get_payload_offset(); 155 | self.read.add_vec(seq, packet.to_vec(), offset); 156 | } 157 | 158 | let recv_next = get_next_write_seq(&self.read); 159 | //debug!("read buf head changed from {} to {}", old_recv_next, recv_next); 160 | 161 | if old_recv_next != recv_next // != cause wrap arounds 162 | { 163 | can_read = true; 164 | } 165 | 166 | // ->TODO Will require method in RecvMgr that can iterate over first contiguous block from RCV.NXT 167 | // - and do things at each packet (copy to buf), optionally deleting from queue once consumed 168 | 169 | // -> Send ACK TODO: efficient way of ACKing - single ACK value at any time, should just update 170 | // ACK number in timer 171 | } 172 | } 173 | else 174 | { 175 | debug!("Invalid Packet ::State: TCB: {}, SEG:", self.state, 176 | packet.get_ack_num(), 177 | packet.get_seq_num()); 178 | } 179 | (can_read, can_write) 180 | } 181 | 182 | //TODO 183 | fn validate_packet_state(&self, packet: &TcpPacket) -> bool { 184 | true 185 | } 186 | 187 | #[inline] 188 | /// Returns the receive window: the number of bytes in the receive buffer that are not reserved 189 | /// by unconsumed, sequentially ordered data 190 | /*fn get_rcv_window(&self) -> u16 { 191 | self.recv_mgr.size - (self.state.recv_NXT - self.recv_mgr.usr_NXT) as u16 192 | }*/ 193 | 194 | /// Send logic for TCP Packets 195 | 196 | // ********* Userland API ************************************// 197 | 198 | /// Read as many bytes as we can into buf from received TCP data 199 | /// until we get to n bytes, starting from the next unconsumed 200 | /// sequence number. 201 | /// 202 | /// Returns the number of bytes read 203 | pub fn read(&mut self, buf: &mut [u8]) -> uint { 204 | // debug!("tcb read called, buf is {}", self.read); 205 | 206 | // Get CONSUMING iter over bytes queued for reading 207 | let mut bytes_to_read = self.read.consume_iter().take(buf.len()).peekable(); 208 | debug!("got consuming iterator"); 209 | 210 | let mut ctr = 0u; 211 | let mut writer = BufWriter::new(buf); 212 | 213 | // Read as many bytes as we can to fill user's buf 214 | debug!("reading from consuming iterator"); 215 | for b in bytes_to_read { 216 | writer.write_u8(b); 217 | ctr += 1; 218 | } 219 | debug!("done reading from sonsuming iterator"); 220 | 221 | // Our receive window just widened by ctr bytes 222 | self.state.recv_WND += ctr as u16; 223 | 224 | ctr 225 | } 226 | 227 | 228 | /// Write as many bytes as we can into our TCP send buffer 229 | /// from buf, starting with `start` 230 | /// 231 | /// Returning the number of bytes we were able to successfully write 232 | /// NOTE: this is less than n when 233 | /// n > (SND.UNA + SND.WND ) - SND.NXT 234 | pub fn send(&mut self, buf: &[u8], 235 | state: &::State, 236 | us: ::ConAddr, 237 | them: ::ConAddr) -> uint 238 | where A: RoutingTable 239 | { 240 | //debug!("TCB state: {}", self.state); 241 | //debug!("User on <{}<{}> send data: {}", us, them, buf); 242 | 243 | let send_nxt = get_next_write_seq(&self.write); 244 | 245 | let bytes_written = self.write.add_slice(send_nxt, buf); 246 | 247 | self.transmit_data.update_with_interval(get_next_write_seq(&self.write)); 248 | 249 | //TODO: will this SEQ num state get moved into PacketBuf? 250 | //debug!("SendBuf: {}", self.write); 251 | //debug!("{} bytes written", bytes_written); 252 | 253 | self.flush_transmit_queue(state, us, them); 254 | 255 | bytes_written as uint 256 | } 257 | 258 | //Iterate through bytes to be sent, packaging them into packets and sending them off 259 | pub fn flush_transmit_queue(&mut self, 260 | state: &::State, 261 | us: ::ConAddr, 262 | them: ::ConAddr) -> send::Result<()> 263 | where A: RoutingTable 264 | { 265 | debug!("<{},{}> Flushing Transmission Queue", us, them); 266 | 267 | // UPDATE TIMER DATA 268 | // if new data, push another entry onto queue with now() as time 269 | // pop entry w/ MAX_RETRIES retries off 270 | 271 | // Send all the bytes we have up to the current send window 272 | let mut bytes_to_send = self.write.iter().take(self.state.send_WND as uint).peekable(); 273 | 274 | let cur_recv_nxt = get_next_write_seq(&self.read); 275 | 276 | let mut ctr = self.write.get_next_consume_seq(); 277 | // Until we run out of bytes 278 | while !bytes_to_send.is_empty() { 279 | 280 | // Make a packet builder 281 | let builder: for<'p> |&'p mut TcpPacket| -> send::Result<()> = |packet| { 282 | 283 | // Set Packet Header Params 284 | packet.set_ack_num(cur_recv_nxt); 285 | packet.set_seq_num(ctr); 286 | packet.set_window_size(self.state.recv_WND); 287 | 288 | // Counter for bytes added to payload 289 | { 290 | let mut v = packet.as_mut_vec(); 291 | 292 | // Add up to MSS bytes to this packet 293 | for _ in range(0u, TCP_MSS as uint) { 294 | match bytes_to_send.next() { 295 | Some(b) => { 296 | v.push(b); 297 | ctr += 1; 298 | }, 299 | None => { 300 | debug!("less than MSS packet cause there is nothing else to send"); 301 | break 302 | } 303 | } 304 | } 305 | }; 306 | 307 | //TODO Update sent record for timers 308 | 309 | Ok(()) 310 | }; 311 | 312 | try!(send::send(&*state.ip, 313 | Some(us.0), 314 | us.1, 315 | them, 316 | Some(TCP_MSS), 317 | |x| x, 318 | builder)); 319 | } 320 | Ok(()) 321 | } 322 | 323 | fn mod_leq(&self, n: u32, m: u32) -> bool { 324 | n <= m || (n - m > (1 << 16)) 325 | } 326 | } 327 | 328 | // Checks if n in (s, e] (mod 2^32) 329 | // TODO: should be in utils or something? 330 | #[inline] 331 | pub fn mod_in_interval(s: u32, e: u32, n: u32) -> bool { 332 | if e < s { 333 | 334 | // interval is wrapped around 335 | s <= n || n <= e 336 | } else { 337 | 338 | // Plain old interval 339 | s <= n && n <= e 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/established/tcb/timer/mod.rs: -------------------------------------------------------------------------------- 1 | use time; 2 | use std::sync::{Arc, Weak, RWLock}; 3 | use std::io::Timer; 4 | use std::time::duration::Duration; 5 | use std::collections::ring_buf::RingBuf; 6 | 7 | use network::ipv4; 8 | use network::ipv4::strategy::RoutingTable; 9 | 10 | use connection::Connection; 11 | use connection::established::Established; 12 | use connection::established::tcb::{TCB,TCP_MAX_RETRIES}; 13 | 14 | pub const TCP_RTT_INIT : uint = 2_000u; // 2 seconds 15 | 16 | #[deriving(Send)] 17 | pub struct TransmissionEntry { 18 | 19 | // Sequence number of LAST byte in this block 20 | pub seq_num: u32, 21 | 22 | // Number of times the highest sequence number in this block has been transmitted 23 | pub num_tries: uint, 24 | 25 | // Timestamp in ns of the first transmission of the highest seq number in block 26 | pub ts_first: i64, 27 | } 28 | 29 | #[deriving(Send)] 30 | pub struct RetransmitData { 31 | 32 | // Estimate of RTT in ms 33 | rtt_estimate: uint, 34 | 35 | // Queue of (seq#, #tries, timestamp of 1st transmission) triples 36 | transmission_intervals: RingBuf, 37 | } 38 | 39 | impl RetransmitData { 40 | pub fn new() -> RetransmitData { 41 | 42 | // Create bounded queue for intervals, plus one spot for insertions before deletions 43 | let mut buf = RingBuf::new(); 44 | buf.reserve_exact(TCP_MAX_RETRIES + 1); 45 | 46 | RetransmitData { 47 | rtt_estimate: TCP_RTT_INIT, 48 | transmission_intervals: buf, 49 | } 50 | } 51 | 52 | // Adds a new interval to the queue, popping off one of it is now expired 53 | pub fn update_with_interval(&mut self, seq_num: u32) -> Option { 54 | 55 | // Check to see if oldest entry is expired 56 | let pop_back = match self.transmission_intervals.back() { 57 | None => false, 58 | Some(te) => te.num_tries == TCP_MAX_RETRIES 59 | }; 60 | 61 | // If so, pop it and return 62 | let back = if pop_back { self.transmission_intervals.pop_back() } else { None }; 63 | 64 | // Add new interval to front of queue 65 | self.transmission_intervals.push( TransmissionEntry { 66 | seq_num: seq_num, 67 | num_tries: 0u, 68 | ts_first: now_millis(), 69 | }); 70 | 71 | back 72 | } 73 | 74 | pub fn get_rtt_estimate(&mut self) -> uint { 75 | self.rtt_estimate 76 | } 77 | 78 | pub fn update_rtt_from_ack(&mut self, ack_num: u32) { 79 | 80 | // No update if we have no unACKed data 81 | if self.transmission_intervals.is_empty() { return; } 82 | 83 | // Get most recently sent sequence number 84 | let front = self.transmission_intervals.front().unwrap(); 85 | 86 | let mut update = false; 87 | 88 | // If we haven't retransmitted it 89 | if front.num_tries <= 1 { 90 | 91 | // if there is more than 1 interval around, is the ACK necessarily for this interval? 92 | if self.transmission_intervals.len() > 1 { 93 | if ack_num > self.transmission_intervals[1].seq_num { 94 | update = true; 95 | } 96 | // ACK must be for this interval 97 | } else { 98 | update = true; 99 | } 100 | } 101 | 102 | // Update estimate of RTT since we are seeing new ACK of non-retransmitted data 103 | self.rtt_estimate = calc_rtt(front.ts_first, now_millis()) 104 | 105 | } 106 | } 107 | 108 | //TODO: smooth using ALPHA 109 | fn calc_rtt(t_sent: i64, t_recv: i64) -> uint { 110 | (t_recv - t_sent) as uint 111 | } 112 | 113 | // Hopefully returns timestamp of now in milliseconds 114 | fn now_millis() -> i64 { 115 | let ts = time::get_time(); 116 | ts.sec * 1000 + (ts.nsec / 1000) as i64 117 | } 118 | 119 | pub fn on_timeout(est: &mut Established, 120 | state: &::State, 121 | interval: &mut Duration) 122 | where A: RoutingTable 123 | { 124 | let mut tcb = &mut est.tcb; 125 | 126 | *interval = Duration::milliseconds(tcb.transmit_data.get_rtt_estimate() as i64); 127 | 128 | match tcb.flush_transmit_queue(state, est.us, est.them) { 129 | Ok(_) => (), 130 | Err(_) => debug!("failure during timeout action, ok"), 131 | }; 132 | } 133 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/handshaking.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::hash_map::{Occupied, Vacant}; 3 | use std::default::Default; 4 | use std::io::net::ip::Port; 5 | use std::sync::{Arc, Weak, RWLock}; 6 | use std::rand::{task_rng, Rng}; 7 | use std::time::duration::Duration; 8 | 9 | use network::ipv4; 10 | use network::ipv4::strategy::RoutingTable; 11 | 12 | use packet::{mod, TcpPacket}; 13 | use send::{mod, Error,}; 14 | 15 | use super::Connection; 16 | use super::established::{ 17 | mod, 18 | tcb, 19 | Established, 20 | Situation, 21 | }; 22 | 23 | pub struct Handshaking { 24 | us: Port, 25 | our_ip: Option, 26 | them: ::ConAddr, 27 | 28 | want: bool, // do we want to we want to receive an ACK? 29 | owe: bool, // ought we to send them an ACK, if the situation arises? 30 | ackd_before: bool, 31 | synd_before: bool, 32 | 33 | our_number: u32, 34 | their_number: Option, 35 | their_wnd: Option, 36 | future_handler: established::Handler, 37 | } 38 | 39 | impl super::State for Handshaking 40 | { 41 | fn next(self, 42 | state: &::State, 43 | packet: TcpPacket) 44 | -> Connection 45 | where A: RoutingTable 46 | { 47 | match self.next_raii(state, packet) 48 | { 49 | Ok(con) => con, 50 | Err(_) => Connection::Closed, 51 | } 52 | } 53 | 54 | fn close(self, _state: &::State) -> Connection 55 | { 56 | if self.ackd_before { 57 | debug!("TODO: goto fin wait 1"); 58 | Connection::Handshaking(self) 59 | } else { // can close immediately 60 | Connection::Closed 61 | } 62 | } 63 | 64 | fn checkup(self, 65 | state: &::State, 66 | interval: &mut Duration) 67 | -> (Connection, bool) 68 | { 69 | debug!("TODO: checkup for handshaking"); 70 | // false == don't kill timer thread 71 | (Connection::Handshaking(self), false) 72 | } 73 | } 74 | 75 | 76 | 77 | impl Handshaking 78 | { 79 | fn next_raii(mut self, 80 | state: &::State, 81 | packet: TcpPacket) 82 | -> send::Result 83 | where A: RoutingTable 84 | { 85 | let us = (packet.get_dst_addr(), packet.get_dst_port()); 86 | let them = (packet.get_src_addr(), packet.get_src_port()); 87 | 88 | match self.our_ip { 89 | Some(ip) => assert_eq!(ip, us.0), 90 | None => self.our_ip = Some(us.0), 91 | }; 92 | assert_eq!(self.them, them); 93 | 94 | debug!("{} to {} pre packet: want {}, owe {}", them, us, self.want, self.owe); 95 | 96 | if packet.flags().contains(packet::ACK) { 97 | self.want = false; 98 | //FIXME: should we verify the ACK# accompanying this? 99 | self.their_wnd = Some(packet.get_window_size()); 100 | } 101 | 102 | if packet.flags().contains(packet::SYN) { 103 | self.owe = true; 104 | self.their_number = Some(packet.get_seq_num()); // TODO: should check this 105 | self.their_wnd = Some(packet.get_window_size()); 106 | } 107 | 108 | debug!("{} to {} post packet: want {}, owe {}", them, us, self.want, self.owe); 109 | 110 | try!(self.send(state, us.1, them)); 111 | 112 | Ok(if (self.want || self.owe) == false { 113 | debug!("{} to {} free!!!!", them, us); 114 | // Become established 115 | Established::new(state, 116 | (self.our_ip.unwrap(), self.us), 117 | self.them, 118 | self.our_number, 119 | self.their_number.unwrap(), 120 | self.their_wnd.unwrap(), 121 | self.future_handler) 122 | } else { 123 | debug!("{} to {} not free", them, us); 124 | Connection::Handshaking(self) 125 | }) 126 | } 127 | 128 | // Only takes State arc because we are temporarily doing one timeout 129 | // thread / connection Do not propigate this arc further 130 | pub fn new(state: &Arc<::State>, 131 | us: Port, 132 | our_ip: Option, 133 | them: ::ConAddr, 134 | 135 | want: bool, 136 | owe: bool, 137 | their_number: Option, 138 | their_wnd: Option, 139 | future_handler: established::Handler) 140 | -> send::Result>> 141 | where A: RoutingTable 142 | { 143 | let per_port = ::PerPort::get_or_init(&state.tcp, us); 144 | let conn = Connection::get_or_init(&*per_port, them); 145 | { 146 | let mut lock = conn.write(); 147 | match *lock { 148 | Connection::Closed => (), 149 | _ => return Err(Error::PortOrTripleReserved), 150 | }; 151 | debug!("Confirmed no existing connection on our port {} to server {}", us, them); 152 | 153 | let mut potential = Handshaking { 154 | us: us, 155 | our_ip: our_ip, 156 | them: them, 157 | 158 | want: want, 159 | owe: owe, 160 | ackd_before: false, 161 | synd_before: false, 162 | our_number: Handshaking::generate_isn(), 163 | their_number: their_number, 164 | their_wnd: their_wnd, 165 | future_handler: future_handler, 166 | }; 167 | 168 | try!(potential.send(&**state, us, them)); 169 | 170 | // don't bother really reserving port until at least the first 171 | // message was sent; 172 | *lock = super::Connection::Handshaking(potential); 173 | } 174 | // make sure this is after letting go of locks 175 | super::timer::start_timer(state, &conn); 176 | Ok(conn.downgrade()) 177 | } 178 | 179 | 180 | 181 | fn send(&mut self, 182 | state: &::State, 183 | us: Port, // already expects specific port 184 | them: ::ConAddr) 185 | -> send::Result<()> 186 | where A: RoutingTable 187 | { 188 | let our_ip = self.our_ip; 189 | 190 | debug!("{} to {} pre send: want {}, owe {}", them, us, self.want, self.owe); 191 | 192 | { 193 | let builder: for<'p> |&'p mut packet::TcpPacket| -> send::Result<()> = |packet| 194 | { 195 | // Set SEQ to our ISN 196 | packet.set_seq_num(self.our_number); 197 | // Set Window Size 198 | packet.set_window_size(tcb::TCP_RECV_WND_INIT); 199 | // gotta SYN them at least once for double handshake 200 | if ! self.synd_before { 201 | debug!("{} will SYN {}", us, them); 202 | packet.flags_mut().insert(packet::SYN); 203 | 204 | self.want = true; 205 | self.synd_before = true; 206 | } 207 | // if we owe them an ACK 208 | if self.owe { 209 | debug!("{} will ACK {}", us, them); 210 | 211 | // will also set ACK flag 212 | packet.set_ack_num( 213 | self.their_number 214 | .expect("Should have number to ACK if they want us to ACK")); 215 | 216 | self.owe = false; 217 | self.ackd_before = true; 218 | } 219 | Ok(()) 220 | }; 221 | 222 | 223 | try!(send::send(&*state.ip, 224 | our_ip, // to ensure routes don't fuck us 225 | us, 226 | them, 227 | Some(0), 228 | |x| x, 229 | builder)); 230 | } 231 | 232 | debug!("{} to {} post send: want {}, owe {}", them, us, self.want, self.owe); 233 | 234 | debug!("Attempt handshake with {} on our port {}", them, us); 235 | Ok(()) 236 | } 237 | 238 | 239 | /// Generates a pseudorandom u32 - used to set ISN 240 | fn generate_isn() -> u32 { 241 | let mut rng = task_rng(); 242 | rng.gen::() 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/manager/packet_buffer.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | use std::io::BufWriter; 3 | use std::fmt; 4 | use std::cmp; 5 | 6 | use super::super::tcb::{TCP_BUF_SIZE, TcbState, mod_in_interval}; 7 | 8 | #[deriving(Show, Eq, PartialEq)] 9 | struct BufEntry { 10 | pub seq: u32, 11 | 12 | // Index within data corresponding to above sequence # 13 | pub hdr_offset: u32, 14 | 15 | // Index within data at which consumption should start 16 | pub consume_offset: u32, 17 | pub data: Vec 18 | } 19 | 20 | // Holds (Seq#, Header Offset, Data) for pakcets in packet queue 21 | impl BufEntry { 22 | 23 | fn len(&self) -> u32 { 24 | self.data.len() - hdr_offset 25 | } 26 | 27 | //TODO: mod?? 28 | pub fn covers(&self, other: &BufEntry) -> bool { 29 | self.contains(other.seq) && self.contains(other.seq + other.len()) 30 | } 31 | 32 | pub fn contains(&self, seq: u32) -> bool { 33 | self.seq <= seq && self.seq + self.len() >= seq 34 | } 35 | 36 | pub fn slice_until_seq(&self, seq: u32) -> &[u8] { 37 | self.data[self.get_cur_ix()..cmp::min(self.len(), get_ix(seq))] 38 | } 39 | 40 | fn get_end_seq(&self) -> u32 { 41 | self.seq + self.len() 42 | } 43 | 44 | fn get_cur_ix(&self) -> uint { 45 | self.hdr_offset + self.consume_offset 46 | } 47 | 48 | fn get_ix(&self, seq: u32) -> uint { 49 | assert!(self.contains(seq)); 50 | self.hdr_offset + (seq - self.seq) 51 | } 52 | } 53 | 54 | #[deriving(Show)] 55 | pub struct RecvMgr { 56 | 57 | // Queue of received packets whose data has not been consumed yet 58 | packets: Vec, 59 | 60 | // Offset to start reading from within the first packet on the queue 61 | packet_offset: u32, 62 | 63 | // Next sequence number that the user will consume 64 | pub usr_NXT: u32, 65 | 66 | // Virtual size of buffer 67 | pub size: u16, 68 | } 69 | 70 | 71 | /// The Data Structure that provides functionality to iterate in-order through data 72 | /// sent or received in pieces that may not have been in order 73 | impl RecvMgr { 74 | 75 | //****** Methods Kernel Calls *********// 76 | pub fn new(&self) -> RecvMgr { 77 | RecvMgr { 78 | packets: vec!(), 79 | packet_offset: 0u32, 80 | usr_XT: 0u32, 81 | size: TCP_BUF_SIZE, 82 | } 83 | } 84 | 85 | 86 | // Adds packet to receive queue 87 | // TODO: return boolean to tell us whether usr_NXT is overlapped, so we can notify canRead? 88 | #[inline] 89 | pub fn add_packet(&mut self, seq: u32, offset: u32, data: Vec) { 90 | let entry = BufEntry { 91 | seq: seq, 92 | hdr_offset: offset, 93 | data: data 94 | }; 95 | match self.find_ix(entry) { 96 | None => (), 97 | Some(ix) => self.packets.insert(ix, entry) 98 | } 99 | } 100 | 101 | 102 | // TODO: Binary search using OrdSlicePrelude 103 | // Finds index where given entry belongs in sorted sequence if it is not a duplicate 104 | fn find_ix(&self, entry: &BufEntry) -> Option { 105 | for (ix, e) in self.packets.iter().enumerate() { 106 | if e.seq > entry.seq { 107 | Some(ix) 108 | } else if e.seq == entry.seq { 109 | if !e.covers(entry) { 110 | Some(ix) 111 | } else { 112 | None 113 | } 114 | } 115 | } 116 | //Just push 117 | Some(self.packets.len()) 118 | } 119 | 120 | pub fn iter_to(&self, seq: u32) -> Iterator<&[u8]> { 121 | NonConsumingIterator { 122 | buf: self, 123 | until: seq, 124 | cur_ix: 0u, 125 | next_seq: buf.consume_NXT, 126 | } 127 | } 128 | 129 | pub fn consume_to(&mut self, seq: u32) -> Iterator<&[u8]> { 130 | ConsumingIterator { 131 | buf: self, 132 | until: seq, 133 | next_seq: buf.consume_NXT, 134 | } 135 | } 136 | 137 | pub fn iter_all(&self) -> Iterator> { 138 | self.packets.iter().map( |entry| entry.data) 139 | } 140 | 141 | } 142 | 143 | 144 | impl Iterator<&[u8]> for ConsumingIterator { 145 | // Call to next: 146 | // - Checks first packet to see if it is contiguous 147 | // - if so 148 | // - read as much as we need, if whole packet, pop it 149 | fn next(&mut self) -> Option<&[u8]> { 150 | 151 | // Short-circuit if goal already met 152 | if self.until <= next_seq { 153 | None 154 | } 155 | 156 | let mut destroy = false; 157 | let mut result = None; 158 | match self.buf.packets { 159 | [] => (), 160 | [first, ..] => { 161 | 162 | // Packet is contiguous w/ previous 163 | if first.contains(self.next_seq) { 164 | 165 | // Packet contains all the data we need 166 | if first.contains(self.until) { 167 | 168 | result = Some(first.slice_to_seq(self.until)); 169 | } else { 170 | result = Some(first.slice_to_seq(self.until)); 171 | destroy = true; 172 | } 173 | } else { 174 | None 175 | } 176 | } 177 | } 178 | 179 | self.next_seq = self.until; 180 | if destroy { 181 | self.buf.packets.remove(0); 182 | } 183 | result 184 | } 185 | } 186 | 187 | impl Iterator<&[u8]> for NonConsumingIterator { 188 | // A Call to next does: 189 | // - Looks at the current Vec (by self.cur_ix and 190 | fn next(&mut self) -> Option<&[u8]> { 191 | match self.buf.packets[self] { 192 | [] => None, 193 | [first, ..] => { 194 | if !first.contains(self.until) { 195 | 196 | } else { 197 | } 198 | } 199 | } 200 | } 201 | } 202 | 203 | 204 | /* 205 | //****** Userland API *******// 206 | /// Blocking read 207 | /// TODO: mutate TCB state? 208 | pub fn read(&mut self, buf: &mut [u8], n: uint) -> uint { 209 | 210 | let mut bufw = BufWriter::new(buf); 211 | let mut bytes_read = 0u; 212 | let mut more_contiguous = true; 213 | 214 | // Read through packets, copying into user's buf, until we have read n bytes 215 | // or we run out of contiguous data 216 | while bytes_read < n && more_contiguous { 217 | let (packet_read, more_contiguous, to_pop) = self.read_top(&mut bufw, n - bytes_read); 218 | 219 | // Pop off this packet if it was consumed 220 | if to_pop { 221 | self.packets.pop(); 222 | } 223 | 224 | bytes_read += packet_read as uint; 225 | self.usr_NXT += packet_read; 226 | } 227 | bytes_read 228 | } 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | // Tries to copy n bytes from next packet in receive queue 240 | // Pops packet off queue if fully consumed 241 | // Resets self.packet_offset appropriately 242 | fn read_top(&mut self, bufw: &mut BufWriter, n: uint) -> (u32, bool, bool) { 243 | match self.packets.top() { 244 | None => (0, false, false), 245 | Some(next_packet) => { 246 | 247 | let seg_SEQ = next_packet.get_seq_num(); 248 | let seg_LEN = next_packet.get_body_len(); 249 | 250 | // Packet is next in order 251 | if mod_in_interval(seg_SEQ, seg_LEN, self.usr_NXT) { 252 | 253 | if seg_LEN as u32 - self.packet_offset > n as u32 { 254 | 255 | bufw.write(next_packet.get_payload()[self.packet_offset as uint..self.packet_offset as uint + n]); 256 | self.packet_offset += n as u32; 257 | 258 | // Read n bytes, may have additional data, didn't consume this packet entirely 259 | return (n as u32, true, false) 260 | } else { 261 | 262 | let rest : u32 = seg_LEN as u32 - self.packet_offset; 263 | 264 | // Read until end of packet 265 | bufw.write(next_packet.get_payload()[self.packet_offset as uint..(self.packet_offset + rest) as uint]); 266 | 267 | // Reset packet offset 268 | self.packet_offset = 0u32; 269 | 270 | // We may have more contiguous data, read again to find out 271 | return (rest, true, true) 272 | } 273 | 274 | // This packet arrived out of order 275 | } else { 276 | return (0, false, false) 277 | } 278 | } 279 | } 280 | } 281 | 282 | /// Returns sequence number of last byte of contiguous block of data starting at usr_NXT 283 | /// NOTE: could pop off all intermediate packets and put them in a user-dedicated buffer 284 | /// -> This would make additions faster in the case of a lazy user who never reads 285 | /// TODO: use the iterator abstraction we should use for the above 286 | pub fn shift_nxt(&mut self) -> u32 { 287 | 0u32 288 | } 289 | 290 | /// Returns a new RecvMgr, complete with: 291 | /// - An empty priority queue, ready to sort TcpPackets based on beginning sequence number 292 | /// - Pointer to the next sequence number the user will consume, starting at 0 293 | pub fn new() -> RecvMgr { 294 | RecvMgr { 295 | packets: BinaryHeap::new(), 296 | packet_offset: 0, 297 | usr_NXT: 0u32, 298 | size: TCP_BUF_SIZE, 299 | } 300 | } 301 | 302 | } 303 | 304 | /// Pretty Print Impl for BinaryHeap for debug 305 | impl fmt::Show for BinaryHeap { 306 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 307 | write!(f, "RecvQueue: {}", self.clone().into_sorted_vec()) 308 | } 309 | } 310 | */ 311 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/manager/recv.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | use std::io::BufWriter; 3 | use std::fmt; 4 | 5 | use packet::{TcpPacket, ACK, SYN}; 6 | use super::super::tcb::{TCP_BUF_SIZE, TcbState, mod_in_interval}; 7 | 8 | #[deriving(Show)] 9 | pub struct RecvMgr { 10 | 11 | // Queue of received packets whose data has not been consumed yet 12 | packets: BinaryHeap, 13 | 14 | // Offset to start reading from within the first packet on the queue 15 | packet_offset: u32, 16 | 17 | // Next sequence number that the user will consume 18 | pub usr_NXT: u32, 19 | 20 | // Virtual size of buffer 21 | pub size: u16, 22 | } 23 | 24 | impl RecvMgr { 25 | 26 | //****** Methods Kernel Calls// 27 | 28 | // Adds packet to receive queue 29 | // TODO: return boolean to tell us whether usr_NXT is overlapped, so we can notify canRead? 30 | #[inline] 31 | pub fn add_packet(&mut self, packet: TcpPacket) { 32 | self.packets.push(packet); 33 | } 34 | 35 | //****** Userland API *******// 36 | /// Blocking read 37 | /// TODO: mutate TCB state? 38 | pub fn read(&mut self, buf: &mut [u8], n: uint) -> uint { 39 | 40 | let mut bufw = BufWriter::new(buf); 41 | let mut bytes_read = 0u; 42 | let mut more_contiguous = true; 43 | 44 | // Read through packets, copying into user's buf, until we have read n bytes 45 | // or we run out of contiguous data 46 | while bytes_read < n && more_contiguous { 47 | let (packet_read, more_contiguous, to_pop) = self.read_top(&mut bufw, n - bytes_read); 48 | 49 | // Pop off this packet if it was consumed 50 | if to_pop { 51 | self.packets.pop(); 52 | } 53 | 54 | bytes_read += packet_read as uint; 55 | self.usr_NXT += packet_read; 56 | } 57 | bytes_read 58 | } 59 | 60 | // Tries to copy n bytes from next packet in receive queue 61 | // Pops packet off queue if fully consumed 62 | // Resets self.packet_offset appropriately 63 | fn read_top(&mut self, bufw: &mut BufWriter, n: uint) -> (u32, bool, bool) { 64 | match self.packets.top() { 65 | None => (0, false, false), 66 | Some(next_packet) => { 67 | 68 | let seg_SEQ = next_packet.get_seq_num(); 69 | let seg_LEN = next_packet.get_body_len(); 70 | 71 | // Packet is next in order 72 | if mod_in_interval(seg_SEQ, seg_LEN, self.usr_NXT) { 73 | 74 | if seg_LEN as u32 - self.packet_offset > n as u32 { 75 | 76 | bufw.write(next_packet.get_payload()[self.packet_offset as uint..self.packet_offset as uint + n]); 77 | self.packet_offset += n as u32; 78 | 79 | // Read n bytes, may have additional data, didn't consume this packet entirely 80 | return (n as u32, true, false) 81 | } else { 82 | 83 | let rest : u32 = seg_LEN as u32 - self.packet_offset; 84 | 85 | // Read until end of packet 86 | bufw.write(next_packet.get_payload()[self.packet_offset as uint..(self.packet_offset + rest) as uint]); 87 | 88 | // Reset packet offset 89 | self.packet_offset = 0u32; 90 | 91 | // We may have more contiguous data, read again to find out 92 | return (rest, true, true) 93 | } 94 | 95 | // This packet arrived out of order 96 | } else { 97 | return (0, false, false) 98 | } 99 | } 100 | } 101 | } 102 | 103 | /// Returns sequence number of last byte of contiguous block of data starting at usr_NXT 104 | /// NOTE: could pop off all intermediate packets and put them in a user-dedicated buffer 105 | /// -> This would make additions faster in the case of a lazy user who never reads 106 | /// TODO: use the iterator abstraction we should use for the above 107 | pub fn shift_nxt(&mut self) -> u32 { 108 | 0u32 109 | } 110 | 111 | /// Returns a new RecvMgr, complete with: 112 | /// - An empty priority queue, ready to sort TcpPackets based on beginning sequence number 113 | /// - Pointer to the next sequence number the user will consume, starting at 0 114 | pub fn new() -> RecvMgr { 115 | RecvMgr { 116 | packets: BinaryHeap::new(), 117 | packet_offset: 0, 118 | usr_NXT: 0u32, 119 | size: TCP_BUF_SIZE, 120 | } 121 | } 122 | 123 | } 124 | 125 | /// Pretty Print Impl for BinaryHeap for debug 126 | impl fmt::Show for BinaryHeap { 127 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 128 | write!(f, "RecvQueue: {}", self.clone().into_sorted_vec()) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/manager/send.rs: -------------------------------------------------------------------------------- 1 | 2 | pub struct SendMgr; 3 | 4 | //TODO: all the things 5 | impl SendMgr { 6 | pub fn new() -> SendMgr { 7 | SendMgr 8 | } 9 | 10 | pub fn send(&self, buf: &[u8], start: u32, n: uint) -> uint { 11 | //TODO: 12 | return 0u; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/mod.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use std::collections::HashMap; 4 | use std::collections::hash_map::{Occupied, Vacant}; 5 | use std::default::Default; 6 | use std::io::net::ip::Port; 7 | use std::io::Timer; 8 | use std::sync::{ 9 | Arc, 10 | RWLock, 11 | RWLockReadGuard, 12 | RWLockWriteGuard, 13 | }; 14 | use std::time::duration::Duration; 15 | 16 | use network::ipv4; 17 | use network::ipv4::strategy::RoutingTable; 18 | 19 | use Table; 20 | use packet::TcpPacket; 21 | 22 | mod packet_buf; 23 | mod timer; 24 | 25 | pub mod handshaking; 26 | pub mod established; 27 | 28 | 29 | pub enum Connection { 30 | Closed, 31 | Handshaking(handshaking::Handshaking), 32 | Established(established::Established), 33 | } 34 | 35 | impl Default for Connection 36 | { 37 | fn default() -> Connection { 38 | Connection::Closed 39 | } 40 | } 41 | 42 | impl Connection { 43 | pub fn get_or_init(per_port: &::PerPort, them: ::ConAddr) -> Arc> 44 | { 45 | per_port.connections.get_or_init(them, 46 | || RWLock::new(Default::default())) 47 | } 48 | 49 | pub fn get_window(&self) -> ((u32, u16), (u32, u16)) { 50 | match self { 51 | &Connection::Closed => ((0, 0), (0, 0)), 52 | &Connection::Handshaking(_) => ((0,0), (0, 0)), 53 | &Connection::Established(ref est) => est.get_window() 54 | } 55 | } 56 | } 57 | 58 | impl fmt::Show for Connection { 59 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 60 | match self { 61 | &Connection::Closed => write!(f, "CLOSED"), 62 | &Connection::Handshaking(ref h) => write!(f, "HANDSHAKING[TODO]"), 63 | &Connection::Established(ref e) => write!(f, "ESTABLISHED"), 64 | } 65 | } 66 | } 67 | 68 | pub trait State { 69 | fn next(self, &::State, TcpPacket) -> Connection 70 | where A: RoutingTable; 71 | 72 | fn close(self, &::State) -> Connection 73 | where A: RoutingTable; 74 | 75 | fn checkup(self, &::State, &mut Duration) -> (Connection, bool) 76 | where A: RoutingTable; 77 | } 78 | 79 | pub fn trans(e: &mut Connection, s: &::State, p: TcpPacket) 80 | where A: RoutingTable 81 | { 82 | use std::mem::swap; 83 | 84 | let mut blank: Connection = Connection::Closed; 85 | 86 | // safe to "close" it without another connection moving in because we have lock 87 | swap(e, &mut blank); 88 | 89 | *e = match blank { 90 | Connection::Closed => Connection::Closed, 91 | Connection::Handshaking(c) => c.next(s, p), 92 | Connection::Established(c) => c.next(s, p), 93 | } 94 | } 95 | 96 | pub fn close(e: &mut Connection, s: &::State) where A: RoutingTable 97 | { 98 | use std::mem::swap; 99 | 100 | let mut blank: Connection = Connection::Closed; 101 | 102 | // safe to "close" it without another connection moving in because we have lock 103 | swap(e, &mut blank); 104 | 105 | *e = match blank { 106 | Connection::Closed => Connection::Closed, 107 | Connection::Handshaking(c) => c.close(s), 108 | Connection::Established(c) => c.close(s), 109 | } 110 | } 111 | 112 | pub fn checkup(e: &mut Connection, 113 | s: &::State, 114 | interval: &mut Duration) 115 | -> bool 116 | where A: RoutingTable 117 | { 118 | use std::mem::swap; 119 | 120 | let mut blank: Connection = Connection::Closed; 121 | 122 | // safe to "close" it without another connection moving in because we have lock 123 | swap(e, &mut blank); 124 | 125 | let (new_con, stop) = match blank { 126 | Connection::Closed => (Connection::Closed, true), 127 | Connection::Handshaking(c) => c.checkup(s, interval), 128 | Connection::Established(c) => c.checkup(s, interval), 129 | }; 130 | *e = new_con; 131 | 132 | stop 133 | } 134 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/packet_buf/dummy.rs: -------------------------------------------------------------------------------- 1 | use std::slice::Items; 2 | use std::iter::Map; 3 | 4 | 5 | pub struct PacketBuf { 6 | dumb: [u8, ..2], 7 | } 8 | 9 | 10 | impl super::PacketBuf for PacketBuf 11 | { 12 | fn new(_init_seq_num: u32) -> PacketBuf { 13 | PacketBuf { dumb: [0, 0] } 14 | } 15 | 16 | fn add_vec(&mut self, _seq_num: u32, _vec: Vec, _start_off: uint) -> u32 { 0 } 17 | fn add_slice(&mut self, _seq_num: u32, _buf: &[u8]) -> u32 { 0 } 18 | 19 | fn get_next_consume_seq(&self) -> u32 { 0 } 20 | } 21 | 22 | 23 | type ViewC<'a> = Map<'a, &'a u8, u8, Items<'a, u8>>; 24 | type ConsumeC<'a> = Map<'a, &'a u8, u8, Items<'a, u8>>; 25 | 26 | 27 | //impl<'a> super::PacketBufIter<'a> for PacketBuf 28 | impl<'a> PacketBuf 29 | { 30 | //type View = ViewC<'a>; 31 | //type Consume = ConsumeC<'a>; 32 | 33 | pub fn iter(&'a self) -> ViewC<'a> { 34 | self.dumb.iter().map(|x| *x) 35 | } 36 | 37 | pub fn consume_iter(&'a mut self) -> ConsumeC<'a> { 38 | self.dumb.iter().map(|x| *x) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/packet_buf/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod dummy; 2 | pub mod ring; 3 | pub mod vec_queue; 4 | 5 | pub type BestPacketBuf = vec_queue::PacketBuf; 6 | 7 | pub trait PacketBuf 8 | { 9 | fn new(init_seq_num: u32) -> Self; 10 | 11 | /// Returns the number of bytes from the payload that now exist in 12 | /// the buffer 13 | /// 14 | /// In particular, the bytes could have been added as a result of 15 | /// this call, or they could have already existed in the buffer 16 | #[inline] 17 | fn add_vec (&mut self, seq_num: u32, vec: Vec, start_off: uint) -> u32; 18 | 19 | /// Return value as the same semantics as `add_vec` 20 | #[inline] 21 | fn add_slice(&mut self, seq_num: u32, buf: &[u8]) -> u32; 22 | 23 | fn get_next_consume_seq(&self) -> u32; 24 | } 25 | /* 26 | pub trait PacketBufIter<'a>: PacketBuf 27 | { 28 | type View: Iterator; 29 | type Consume: Iterator; 30 | 31 | fn iter (&'a self) -> >::View; 32 | fn consume_iter(&'a mut self) -> >::Consume; 33 | } 34 | */ 35 | 36 | 37 | // TODO: make derived method in PacketBufIter 38 | 39 | // TODO: cap at tail seq + 2^31 ? 40 | 41 | /// seq number for the head of continuous data 42 | pub fn get_next_write_seq(b: &BestPacketBuf) -> u32 43 | { 44 | let tail = b.get_next_consume_seq(); 45 | 46 | // number of continuous bytes 47 | // make sure not to consume 48 | let delta = b.iter().count(); 49 | 50 | tail + delta as u32 51 | } 52 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/packet_buf/ring.rs: -------------------------------------------------------------------------------- 1 | use std::slice::Items; 2 | use std::cmp; 3 | use std::iter::{Map, Scan}; 4 | 5 | use ring_buf::{mod, RingBuf}; 6 | 7 | 8 | #[deriving(Show)] 9 | pub struct PacketBuf { 10 | tail_seq: u32, 11 | ring: RingBuf, 12 | } 13 | 14 | 15 | impl super::PacketBuf for PacketBuf 16 | { 17 | fn new(init_seq_num: u32) -> PacketBuf { 18 | PacketBuf { 19 | tail_seq: init_seq_num, 20 | ring: RingBuf::new(1 << 14), // used to be 2^14 21 | } 22 | } 23 | 24 | fn get_next_consume_seq(&self) -> u32 { self.tail_seq } 25 | 26 | fn add_vec(&mut self, seq_num: u32, vec: Vec, start_off: uint) -> u32 { 27 | self.add_slice(seq_num, vec.as_slice()[start_off..]) 28 | } 29 | 30 | fn add_slice(&mut self, seq_num: u32, buf: &[u8]) -> u32 31 | { 32 | let delta: i64 = 33 | (seq_num as i64) - 34 | ((self.tail_seq + self.ring.readable_len() as u32) as i64); 35 | debug!("delta: {}", delta); 36 | 37 | if delta == 0 38 | { 39 | let bytes_fit = cmp::min(self.ring.writable_len(), buf.len()); 40 | 41 | self.ring.write(buf[..bytes_fit]) as u32 42 | } 43 | else if // overlaps, but is not completely contained 44 | (delta < 0) && 45 | (buf.len() - (-delta) as uint) < self.ring.writable_len() && 46 | ((-delta) as uint) < buf.len() 47 | { 48 | debug!("overlaps"); 49 | self.ring.write(buf[-delta as uint..]) as u32 50 | } 51 | else // out of order or redundant/contained 52 | { debug!("not writing anything"); 0 } 53 | } 54 | } 55 | 56 | 57 | type ViewC<'a> = ring_buf::View<'a>; 58 | type ConsumeC<'a> = Scan<'a, u8, u8, ring_buf::Consume<'a>, &'a mut u32>; 59 | 60 | 61 | //impl<'a> PacketBufIter<'a> for PacketBuf 62 | impl<'a> PacketBuf 63 | { 64 | //type View = ViewC<'a>; 65 | //type Consume = ConsumeC<'a>; 66 | 67 | #[inline] 68 | pub fn iter(&'a self) -> ViewC<'a> { 69 | self.ring.iter() 70 | } 71 | 72 | #[inline] 73 | pub fn consume_iter(&'a mut self) -> ConsumeC<'a> { 74 | 75 | // TODO close over len instead 76 | let inc: |&mut &mut u32, u8|:'a -> Option = |ptr, b| { 77 | **ptr = **ptr + 1; // wrap around is inplicit 78 | Some(b) 79 | }; 80 | 81 | self.ring.consume_iter() 82 | .scan(&mut self.tail_seq, inc) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/packet_buf/vec_queue.rs: -------------------------------------------------------------------------------- 1 | extern crate cyclic_order; 2 | 3 | use std::cmp; 4 | use std::collections::dlist; 5 | use std::collections::DList; 6 | use std::slice; 7 | use std::iter::{ 8 | mod, 9 | Chain, 10 | Counter, 11 | Filter, 12 | FilterMap, 13 | FlatMap, 14 | Map, 15 | Rev, 16 | Scan, 17 | Skip, 18 | SkipWhile, 19 | Peekable, 20 | TakeWhile, 21 | Zip, 22 | }; 23 | use std::num::Int; 24 | 25 | use self::cyclic_order::{CyclicOrd, PartialCyclicOrd}; 26 | use self::cyclic_order::CyclicOrdering::*; 27 | use self::cyclic_order::linked_list::{mod, CutQueue}; 28 | 29 | #[deriving(PartialEq, Eq, Show)] 30 | struct Tagged { 31 | seq: u32, 32 | offset: uint, 33 | buf: Vec, 34 | } 35 | 36 | impl PartialCyclicOrd for Tagged { 37 | fn is_clockwise(&self, them: &Tagged, other: &Tagged) -> bool { 38 | self.cyclic_cmp(them, other) == Clockwise 39 | } 40 | } 41 | 42 | 43 | impl CyclicOrd for Tagged 44 | { 45 | fn cyclic_cmp(&self, them: &Tagged, other: &Tagged) -> cyclic_order::CyclicOrdering { 46 | match self.tail().cyclic_cmp(&them.tail(), &other.tail()) { 47 | Degenerate => self.head().cyclic_cmp(&them.head(), &other.head()), 48 | otherwise => otherwise 49 | } 50 | } 51 | } 52 | 53 | 54 | impl Tagged 55 | { 56 | #[inline] 57 | fn new(seq_num: u32, vec: Vec, start_off: uint) -> Tagged 58 | { 59 | let u32_max: u32 = Int::max_value(); 60 | 61 | let node = Tagged { 62 | seq: seq_num, 63 | offset: start_off, 64 | buf: vec, 65 | }; 66 | 67 | assert!(start_off < node.len()); 68 | assert!((node.len() - start_off) < u32_max as uint); 69 | 70 | node 71 | } 72 | 73 | #[inline] 74 | fn len(&self) -> uint 75 | { 76 | self.buf.len() - self.offset 77 | } 78 | 79 | #[inline] 80 | fn head(&self) -> u32 81 | { 82 | self.seq + (self.len() - self.offset) as u32 83 | } 84 | 85 | #[inline] 86 | fn tail(&self) -> u32 87 | { 88 | self.seq 89 | } 90 | } 91 | 92 | impl ::std::slice::AsSlice for Tagged 93 | { 94 | #[inline] 95 | fn as_slice<'a>(&'a self) -> &'a [u8] 96 | { 97 | self.buf.as_slice()[self.offset..] 98 | } 99 | } 100 | 101 | mod tagged_test { 102 | /* 103 | use super::cylic_order::{partial_axioms, total_axioms}; 104 | 105 | #[quickcheck] 106 | fn partial_cyclicity(a: Tagged, b: Tagged, c: Tagged) -> bool { 107 | partial_axioms::cyclicity(&a, &b, &c) 108 | } 109 | 110 | #[quickcheck] 111 | fn partial_antisymmetry(a: Tagged, b: Tagged, c: Tagged) -> bool { 112 | partial_axioms::antisymmetry(&a, &b, &c) 113 | } 114 | 115 | #[quickcheck] 116 | fn partial_transitivity(a: Tagged, b: Tagged, c: Tagged, d: Tagged) -> bool { 117 | partial_axioms::transitivity(&a, &b, &c, &d) 118 | } 119 | 120 | 121 | #[quickcheck] 122 | fn total_cyclicity(a: Tagged, b: Tagged, c: Tagged) -> bool { 123 | total_axioms::cyclicity(&a, &b, &c) 124 | } 125 | 126 | #[quickcheck] 127 | fn total_antisymmetry(a: Tagged, b: Tagged, c: Tagged) -> bool { 128 | total_axioms::antisymmetry(&a, &b, &c) 129 | } 130 | 131 | #[quickcheck] 132 | fn total_transitivity(a: Tagged, b: Tagged, c: Tagged, d: Tagged) -> bool { 133 | total_axioms::transitivity(&a, &b, &c, &d) 134 | } 135 | 136 | #[quickcheck] 137 | fn total_totality(a: Tagged, b: Tagged, c: Tagged) -> bool { 138 | total_axioms::totality(&a, &b, &c) 139 | } 140 | 141 | #[quickcheck] 142 | fn super_trait_cohesion(a: Tagged, b: Tagged, c: Tagged) -> bool { 143 | total_axioms::super_trait_cohesion(&a, &b, &c) 144 | } 145 | */ 146 | } 147 | 148 | 149 | 150 | 151 | #[deriving(Show)] 152 | pub struct PacketBuf { 153 | tail_seq: u32, 154 | data: DList, 155 | } 156 | 157 | 158 | impl super::PacketBuf for PacketBuf 159 | { 160 | fn new(init_seq_num: u32) -> PacketBuf { 161 | PacketBuf { 162 | tail_seq: init_seq_num, 163 | data: DList::new(), 164 | } 165 | } 166 | 167 | fn get_next_consume_seq(&self) -> u32 { self.tail_seq } 168 | 169 | fn add_slice(&mut self, seq_num: u32, buf: &[u8]) -> u32 170 | { 171 | self.add_vec(seq_num, buf.to_vec(), 0) 172 | } 173 | 174 | fn add_vec(&mut self, seq_num: u32, vec: Vec, start_off: uint) -> u32 175 | { 176 | let node = Tagged::new(seq_num, vec, start_off); 177 | let ret = node.head() - node.tail(); // always accept everything! 178 | self.data.insert_cyclic(node); 179 | ret 180 | } 181 | } 182 | 183 | 184 | // TODO: reuse code between the two iterators 185 | 186 | pub struct ViewIter<'a> { 187 | expected_seq: u32, 188 | tagged_iter: Peekable<&'a Tagged, dlist::Items<'a, Tagged>>, 189 | } 190 | 191 | impl<'a> Iterator for ViewIter<'a> 192 | { 193 | #[inline] 194 | fn next(&mut self) -> Option 195 | { 196 | loop { 197 | { 198 | let next = match self.tagged_iter.peek() { 199 | None => return None, 200 | Some(s) => s, 201 | }; 202 | 203 | if 204 | self.expected_seq == next.tail() || 205 | next.tail().is_clockwise(&self.expected_seq, &next.head()) 206 | { 207 | let tagged = next; 208 | 209 | let ret = Some(tagged.as_slice()[(self.expected_seq - tagged.tail()) as uint]); 210 | self.expected_seq += 1; 211 | 212 | return ret; 213 | } 214 | }; 215 | 216 | let _ = self.tagged_iter.next(); 217 | } 218 | } 219 | } 220 | 221 | pub struct ConsumeIter<'a>(&'a mut PacketBuf); 222 | 223 | impl<'a> Iterator for ConsumeIter<'a> 224 | { 225 | #[inline] 226 | fn next(&mut self) -> Option 227 | { 228 | loop { 229 | { 230 | let next = match self.0.data.front() { 231 | None => return None, 232 | Some(s) => s, 233 | }; 234 | 235 | if 236 | self.0.tail_seq == next.tail() || 237 | next.tail().is_clockwise(&self.0.tail_seq, &next.head()) 238 | { 239 | let tagged = next; 240 | 241 | let ret = Some(tagged.as_slice()[(self.0.tail_seq - tagged.tail()) as uint]); 242 | self.0.tail_seq += 1; 243 | 244 | return ret; 245 | } 246 | }; 247 | 248 | let _ = self.0.data.pop_front(); 249 | } 250 | } 251 | } 252 | 253 | impl<'a> PacketBuf 254 | { 255 | // TODO: make it not iterator through all the vecs every time 256 | #[inline] 257 | pub fn iter(&'a self) -> ViewIter<'a> 258 | { 259 | ViewIter { 260 | expected_seq: self.tail_seq, 261 | tagged_iter: self.data.iter().peekable(), 262 | } 263 | } 264 | 265 | // TODO: make it not iterator through all the vecs every time 266 | #[inline] 267 | pub fn consume_iter(&'a mut self) -> ConsumeIter<'a> 268 | { 269 | ConsumeIter(self) 270 | } 271 | } 272 | 273 | #[cfg(test)] 274 | mod test 275 | { 276 | use std::num::Int; 277 | 278 | use super::super::PacketBuf as PacketBuf_T; 279 | //use super::PacketBuf; 280 | use super::*; 281 | 282 | #[test] 283 | fn iter_empty() { 284 | let vb: PacketBuf = PacketBuf_T::new(0); 285 | let mut iter = vb.iter(); 286 | assert_eq!(iter.next(), None); 287 | } 288 | 289 | #[test] 290 | fn one_buf() { 291 | let mut vb: PacketBuf = PacketBuf_T::new(0); 292 | 293 | vb.add_slice(0, [1,5,4,3].as_slice()); 294 | 295 | let mut iter = vb.iter(); 296 | 297 | assert_eq!(iter.next(), Some(1)); 298 | assert_eq!(iter.next(), Some(5)); 299 | assert_eq!(iter.next(), Some(4)); 300 | assert_eq!(iter.next(), Some(3)); 301 | assert_eq!(iter.next(), None); 302 | } 303 | 304 | #[test] 305 | fn many_buf() { 306 | let mut vb: PacketBuf = PacketBuf_T::new(0); 307 | 308 | vb.add_slice(0, [1].as_slice()); 309 | vb.add_slice(1, [3,2].as_slice()); 310 | vb.add_slice(3, [6,5].as_slice()); 311 | 312 | let mut iter = vb.iter(); 313 | 314 | assert_eq!(iter.next(), Some(1)); 315 | assert_eq!(iter.next(), Some(3)); 316 | assert_eq!(iter.next(), Some(2)); 317 | assert_eq!(iter.next(), Some(6)); 318 | assert_eq!(iter.next(), Some(5)); 319 | assert_eq!(iter.next(), None); 320 | } 321 | 322 | #[test] 323 | fn overlapping_buf() { 324 | let mut vb: PacketBuf = PacketBuf_T::new(0); 325 | 326 | vb.add_slice(0, [1,3,2,4].as_slice()); 327 | vb.add_slice(2, [2,4,3,5].as_slice()); 328 | vb.add_slice(4, [3,5,4,6].as_slice()); 329 | 330 | let mut iter = vb.iter(); 331 | 332 | assert_eq!(iter.next(), Some(1)); 333 | assert_eq!(iter.next(), Some(3)); 334 | assert_eq!(iter.next(), Some(2)); 335 | assert_eq!(iter.next(), Some(4)); 336 | assert_eq!(iter.next(), Some(3)); 337 | assert_eq!(iter.next(), Some(5)); 338 | assert_eq!(iter.next(), Some(4)); 339 | assert_eq!(iter.next(), Some(6)); 340 | assert_eq!(iter.next(), None); 341 | } 342 | 343 | #[test] 344 | fn wrapping_buf() { 345 | let u32_max: u32 = Int::max_value(); 346 | 347 | let mut vb: PacketBuf = PacketBuf_T::new(u32_max - 3); 348 | 349 | vb.add_slice(u32_max - 3, [1,3,2,4].as_slice()); 350 | vb.add_slice(u32_max - 1, [2,4,3,5].as_slice()); 351 | vb.add_slice(u32_max + 1, [3,5,4,6].as_slice()); 352 | 353 | let mut iter = vb.iter(); 354 | 355 | assert_eq!(iter.next(), Some(1)); 356 | assert_eq!(iter.next(), Some(3)); 357 | assert_eq!(iter.next(), Some(2)); 358 | assert_eq!(iter.next(), Some(4)); 359 | assert_eq!(iter.next(), Some(3)); 360 | assert_eq!(iter.next(), Some(5)); 361 | assert_eq!(iter.next(), Some(4)); 362 | assert_eq!(iter.next(), Some(6)); 363 | assert_eq!(iter.next(), None); 364 | } 365 | 366 | #[test] 367 | fn mut_iter() { 368 | let u32_max: u32 = Int::max_value(); 369 | 370 | let mut vb: PacketBuf = PacketBuf_T::new(u32_max - 3); 371 | 372 | vb.add_slice(u32_max - 3, [1,3,2,4].as_slice()); 373 | vb.add_slice(u32_max - 1, [2,4,3,5].as_slice()); 374 | vb.add_slice(u32_max + 1, [3,5,4,6].as_slice()); 375 | 376 | { 377 | let mut iter = vb.consume_iter(); 378 | 379 | assert_eq!(iter.next(), Some(1)); 380 | assert_eq!(iter.next(), Some(3)); 381 | assert_eq!(iter.next(), Some(2)); 382 | assert_eq!(iter.next(), Some(4)); 383 | } 384 | { 385 | let mut iter = vb.consume_iter(); 386 | assert_eq!(iter.next(), Some(3)); 387 | assert_eq!(iter.next(), Some(5)); 388 | assert_eq!(iter.next(), Some(4)); 389 | assert_eq!(iter.next(), Some(6)); 390 | assert_eq!(iter.next(), None); 391 | } 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/syn_received.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::hash_map::{Occupied, Vacant}; 3 | use std::default::Default; 4 | use std::io::net::ip::Port; 5 | use std::sync::RWLock; 6 | 7 | use misc::interface::{Fn, /* Handler */}; 8 | 9 | use network::ipv4; 10 | use network::ipv4::strategy::RoutingTable; 11 | 12 | use packet::{mod, TcpPacket}; 13 | use send::{mod, Error,}; 14 | use super::Connection; 15 | 16 | use connection::established::{ 17 | mod, 18 | Established, 19 | Situation, 20 | }; 21 | 22 | pub struct SynReceived { 23 | init_seq_num: u32, 24 | future_handler: established::Handler, 25 | } 26 | 27 | impl super::State for SynReceived 28 | { 29 | fn next(self, 30 | state: &::State, 31 | packet: TcpPacket) 32 | -> Connection 33 | where A: RoutingTable 34 | { 35 | match self.next_raii(state, packet) 36 | { 37 | Ok(con) => con, 38 | Err(_) => Connection::Closed, 39 | } 40 | } 41 | } 42 | 43 | 44 | 45 | impl SynReceived 46 | { 47 | fn next_raii(self, 48 | _state: &::State, 49 | packet: TcpPacket) 50 | -> send::Result 51 | where A: RoutingTable 52 | { 53 | let us = (packet.get_dst_addr(), packet.get_dst_port()); 54 | let them = (packet.get_src_addr(), packet.get_src_port()); 55 | 56 | if !packet.flags().contains(packet::ACK) 57 | { 58 | debug!("Listener on {} got non-ack packet from {}. Make a friendship just to wreck it client?", 59 | us.1, them); 60 | return Err(Error::BadHandshake) 61 | }; 62 | debug!("Done 3/3 handshake with {} on {}", them, us); 63 | 64 | // Become established 65 | Ok(Established::new(us, 66 | them, 67 | self.future_handler)) 68 | } 69 | 70 | 71 | 72 | pub fn passive_new(state: &::State, 73 | us: ::ConAddr, // already expects specific port 74 | them: ::ConAddr, 75 | init_seq_no: u32, 76 | handler: established::Handler) 77 | where A: RoutingTable 78 | { 79 | let per_port = ::PerPort::get_or_init(&state.tcp, us.1); 80 | let conn = per_port.connections.get_or_init(them, 81 | || RWLock::new(Default::default())); 82 | 83 | let mut lock = conn.write(); 84 | match *lock { 85 | Connection::Closed => (), 86 | _ => panic!("Packet should never reach listener if connection exists"), 87 | }; 88 | 89 | match handshake_2(state, us, them) { 90 | Err(_) => (), 91 | Ok(con) => *lock = SynReceived::raw_new(init_seq_no, handler), 92 | }; 93 | } 94 | 95 | /// Used to implement double connect, otherwise use `passive_new` 96 | pub fn raw_new(init_seq_no: u32, 97 | handler: established::Handler) 98 | -> Connection 99 | { 100 | Connection::SynReceived(SynReceived { 101 | init_seq_num: init_seq_no, 102 | future_handler: handler, 103 | }) 104 | } 105 | } 106 | 107 | 108 | 109 | fn handshake_2(state: &::State, 110 | us: ::ConAddr, // already expects specific port 111 | them: ::ConAddr) 112 | -> send::Result<()> 113 | where A: RoutingTable 114 | { 115 | // TODO: Report ICE if this signature is removed 116 | let builder: for<'p> |&'p mut packet::TcpPacket| -> send::Result<()> = |packet| { 117 | use packet::{SYN, ACK}; 118 | *packet.flags_mut() = SYN | ACK; 119 | Ok(()) 120 | }; 121 | 122 | // TODO: Should we keep track of a failure to respond? 123 | try!(send::send(&*state.ip, 124 | Some(us.0), 125 | us.1, 126 | them, 127 | Some(0), 128 | |x| x, 129 | builder)); 130 | 131 | debug!("Attempt 2/3 handshake with {} on our port {}", them, us.1); 132 | Ok(()) 133 | } 134 | -------------------------------------------------------------------------------- /transport/tcp/src/connection/timer.rs: -------------------------------------------------------------------------------- 1 | use time; 2 | use std::sync::{Arc, Weak, RWLock}; 3 | use std::io::Timer; 4 | use std::time::duration::Duration; 5 | 6 | 7 | use network::ipv4; 8 | use network::ipv4::strategy::RoutingTable; 9 | 10 | 11 | pub fn start_timer(state: &Arc<::State>, 12 | weak: &Arc>) 13 | where A: RoutingTable 14 | { 15 | let state_weak = state.clone().downgrade(); 16 | let con_weak = weak.clone().downgrade(); 17 | 18 | spawn(proc() { 19 | let mut interval = Duration::milliseconds(0); 20 | let mut timer = Timer::new().unwrap(); 21 | 22 | loop { 23 | let oneshot = timer.oneshot(interval); 24 | oneshot.recv(); 25 | debug!("Timer firing"); 26 | 27 | let (state, mut con) = match (state_weak.upgrade(), con_weak.upgrade()) { 28 | (Some(state), Some(arc)) => (state, arc), 29 | _ => break, 30 | }; 31 | 32 | if super::checkup(&mut *con.write(), &*state, &mut interval) { 33 | break; 34 | } 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /transport/tcp/src/lib.rs: -------------------------------------------------------------------------------- 1 | // in the short run these are not important 2 | #![allow(unused_imports)] 3 | #![allow(dead_code)] 4 | 5 | #![feature(if_let)] 6 | //#![feature(associated_types)] 7 | #![feature(default_type_params)] 8 | #![feature(unboxed_closures)] // still broken 9 | #![feature(slicing_syntax)] 10 | #![feature(tuple_indexing)] 11 | #![feature(phase)] 12 | 13 | // for tests 14 | #![feature(globs)] 15 | 16 | #[cfg(not(ndebug))] 17 | #[phase(plugin, link)] 18 | extern crate log; 19 | 20 | #[phase(plugin, link)] 21 | extern crate misc; 22 | extern crate time; 23 | extern crate network; 24 | 25 | use std::fmt; 26 | use std::collections::HashMap; 27 | use std::default::Default; 28 | use std::io::net::ip::Port; 29 | use std::sync::{Arc, RWLock}; 30 | 31 | use time::{Timespec, get_time}; 32 | 33 | use network::ipv4; 34 | use network::ipv4::strategy::RoutingTable; 35 | 36 | use concurrent_hash_map::ConcurrentHashMap; 37 | use listener::Listener; 38 | use connection::Connection; 39 | 40 | mod packet; 41 | mod concurrent_hash_map; 42 | mod ring_buf; 43 | 44 | mod send; 45 | mod receive; 46 | 47 | mod trace; 48 | 49 | pub mod listener; 50 | pub mod connection; 51 | 52 | pub mod capability; 53 | 54 | 55 | pub const PROTOCOL: u8 = 6; 56 | 57 | /// Address of one end of a connection 58 | pub type ConAddr = (ipv4::Addr, Port); 59 | 60 | /// Closed state and memory usage: 61 | /// 62 | /// We keep track of closed connections/listeners inside the `Connection` and 63 | /// `Listener` structs, rather than with the existence of such structs. The 64 | /// reason for this is to free /all/ memory associated with a connection 65 | /// requires getting a lock on entire tables to evict the entries -- an 66 | /// synchronization affecting other connections. Putting the `Option` outside 67 | /// the `RWLock` for the listener instills the same semantics for consistency 68 | /// (and similar performance either way). 69 | /// 70 | /// The memory associated with connections and listeners shall instead be 71 | /// collected periodically, minimizing the aforementioned write-locking of the 72 | /// whole-map locks. 73 | /// 74 | /// A concurrent map that provided RW-synchronization to the /entries/ in the 75 | /// map (as opposed to the values) would enable the presence of an entry to 76 | /// indicate open/closed state of the connection. 77 | /// 78 | /// 79 | /// Concurrency Model: 80 | /// 81 | /// Like the rest of this implementation, callbacks are used in order to give 82 | /// the library user the maximum flexibility over the scheduling model. This 83 | /// means it is important that the tables have `Arc`s and not `Weak`s so 84 | /// that the connection persists between callback invocations. 85 | 86 | pub type Table = ConcurrentHashMap; 87 | 88 | pub struct State where A: RoutingTable { 89 | tcp: Table, 90 | pub ip: Arc>, // not TCP's responsibility to hide this 91 | } 92 | 93 | impl State where A: RoutingTable 94 | { 95 | pub fn init_and_register(ip: Arc>) -> Arc> 96 | { 97 | let ptr = Arc::new(State { 98 | ip: ip, 99 | tcp: ConcurrentHashMap::new(), 100 | }); 101 | receive::register(&ptr); 102 | ptr 103 | } 104 | 105 | pub fn dump_tcp(&self) { 106 | println!("Sockets:"); 107 | self.tcp.dump(); 108 | } 109 | } 110 | 111 | pub type SubTable = ConcurrentHashMap>; 112 | 113 | impl fmt::Show for RWLock { 114 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 115 | write!(f, "RW<{}>", self.read().deref()) 116 | } 117 | } 118 | 119 | impl fmt::Show for RWLock> { 120 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 121 | write!(f, "RW<{}>", self.read().deref()) 122 | } 123 | } 124 | 125 | pub struct PerPort { 126 | listener: RWLock>, 127 | connections: SubTable, 128 | } 129 | 130 | 131 | 132 | impl Default for PerPort 133 | { 134 | fn default() -> PerPort { 135 | PerPort { 136 | listener: RWLock::new(Default::default()), 137 | connections: ConcurrentHashMap::new(), 138 | } 139 | } 140 | } 141 | 142 | impl PerPort 143 | { 144 | pub fn get_or_init(tcp: &Table, us: Port) -> Arc 145 | { 146 | tcp.get_or_init( 147 | us, 148 | || Default::default()) 149 | } 150 | } 151 | 152 | impl fmt::Show for PerPort { 153 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 154 | write!(f, "Listener: {}, Cnx:TODO", self.listener) //, self.connections) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /transport/tcp/src/listener.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::collections::HashMap; 3 | use std::collections::hash_map::{Occupied, Vacant}; 4 | use std::io::net::ip::Port; 5 | use std::sync::{Arc, Weak, RWLock}; 6 | 7 | use network::ipv4; 8 | use network::ipv4::strategy::RoutingTable; 9 | 10 | use Table; 11 | use packet::{mod, TcpPacket}; 12 | use send::{mod, Error,}; 13 | 14 | use connection::Connection; 15 | use connection::handshaking::Handshaking; 16 | use connection::established::{ 17 | mod, 18 | Established, 19 | }; 20 | 21 | pub type ConnectionFun = Box< 22 | FnOnce<(established::Handler,), 23 | (send::Result>>)> 24 | + Send + Sync + 'static>; 25 | 26 | pub type ConnectionAttemptMessage = (::ConAddr, // us 27 | ::ConAddr, // them 28 | ConnectionFun); 29 | 30 | pub type OnConnectionAttempt = Box< 31 | FnMut 32 | + Send + Sync + 'static>; 33 | 34 | 35 | pub struct Listener { 36 | us: Port, 37 | handler: OnConnectionAttempt, 38 | } 39 | 40 | impl Listener 41 | { 42 | fn handle(&mut self, 43 | state: &Arc<::State>, 44 | packet: TcpPacket) 45 | -> bool 46 | where A: RoutingTable 47 | { 48 | let us = (packet.get_dst_addr(), packet.get_dst_port()); 49 | let them = (packet.get_src_addr(), packet.get_src_port()); 50 | 51 | assert_eq!(self.us, us.1); 52 | 53 | if !( packet.flags().contains(packet::SYN) && ! packet.flags().contains(packet::ACK) ) 54 | { 55 | debug!("Listener on {} got non-syn or ack packet from {}. This is not how you make an introduction....", 56 | us.1, them); 57 | return true; 58 | }; 59 | 60 | if packet.get_payload().len() != 0 { 61 | debug!("Listener on {} got non-empty packet from {}. Slow down, we just met....", us.1, them); 62 | return true; 63 | }; 64 | 65 | debug!("Done with 1/3 handshake with {} on our port {}", them, us.1); 66 | 67 | let con_maker: ConnectionFun = { 68 | let seq_num = packet.get_seq_num(); 69 | let state = state.clone().downgrade(); 70 | let wnd = packet.get_window_size(); 71 | box move |: handler | { 72 | let state = match state.upgrade() { 73 | None => return Err(Error::BadHandshake), // I suppose IP dissapearing is a bad handshake? 74 | Some(s) => s, 75 | }; 76 | Handshaking::new(&state, us.1, Some(us.0), them, 77 | false, true, Some(seq_num), Some(wnd), handler) 78 | } 79 | }; 80 | self.handler.call_mut((us, them, con_maker)) 81 | } 82 | } 83 | 84 | pub fn trans(listener: &mut Option, 85 | state: &Arc<::State>, 86 | packet: TcpPacket) 87 | where A: RoutingTable 88 | { 89 | use std::mem::swap; 90 | 91 | let mut blank: Option= None; 92 | 93 | swap(listener, &mut blank); 94 | 95 | *listener = match blank { 96 | None => { 97 | debug!("Sorry, no l to receive this packet"); 98 | None 99 | }, 100 | Some(mut l) => { 101 | debug!("Listener found!"); 102 | if l.handle(state, packet) { 103 | Some(l) 104 | } else { 105 | None 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | pub fn passive_new(state: &::State, 113 | handler: OnConnectionAttempt, 114 | local_port: Port) 115 | -> send::Result> 116 | where A: RoutingTable 117 | { 118 | let per_port = ::PerPort::get_or_init(&state.tcp, local_port); 119 | let mut lock = per_port.listener.write(); // get listener read lock 120 | 121 | *lock = match *lock { 122 | None => Some(Listener { us: local_port, handler: handler }), 123 | _ => { 124 | debug!("Oh no, listener already exists here"); 125 | return Err(Error::PortOrTripleReserved); 126 | }, 127 | }; 128 | 129 | Ok(per_port.clone().downgrade()) 130 | } 131 | 132 | impl fmt::Show for Listener { 133 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 134 | write!(f, "LISTENER: <{}>", self.us) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /transport/tcp/src/packet.rs: -------------------------------------------------------------------------------- 1 | use std::io::{ 2 | BufReader, 3 | BufWriter, 4 | MemWriter, 5 | SeekSet, 6 | 7 | IoError, 8 | IoResult, 9 | }; 10 | use std::mem::{transmute, size_of}; 11 | use std::num::Int; 12 | use std::fmt; 13 | 14 | use network::ipv4::Addr; 15 | use network::ipv4::packet; 16 | 17 | // Length of TCP header in bytes 18 | pub const TCP_HDR_LEN: uint = 20; 19 | 20 | #[deriving(PartialEq, Eq, Clone)] 21 | pub struct TcpPacket { 22 | ip: packet::V 23 | } 24 | 25 | #[deriving(PartialEq, PartialOrd, Eq, Ord, 26 | Clone, Show)] 27 | // TODO: I just copied this from IP, feel free to add or remove error cases Anson. 28 | /// Where there are two fields: expected, then got. 29 | pub enum BadPacket { 30 | TooShort(uint), // header cannot fit 31 | 32 | HeaderTooLong(uint, uint), // header declared shorter than min or longer than body 33 | HeaderTooShort(uint), // header declared shorter than min or longer than body 34 | 35 | BadChecksum(u16, u16), 36 | BadOptions, 37 | } 38 | 39 | bitflags! { 40 | #[deriving(Show)] 41 | flags Flags: u8 { 42 | const URG = 0b_00_100000, 43 | const ACK = 0b_00_010000, 44 | const PSH = 0b_00_001000, 45 | const RST = 0b_00_000100, 46 | const SYN = 0b_00_000010, 47 | const FIN = 0b_00_000001, 48 | } 49 | } 50 | 51 | impl TcpPacket { 52 | 53 | pub fn new(ip_packet: packet::V) -> TcpPacket { 54 | TcpPacket { ip: ip_packet } 55 | } 56 | 57 | pub fn hack(ip_packet: &packet::V) -> &TcpPacket { 58 | unsafe {transmute(ip_packet) } 59 | } 60 | 61 | pub fn hack_mut(ip_packet: &mut packet::V) -> &mut TcpPacket { 62 | unsafe {transmute(ip_packet) } 63 | } 64 | 65 | pub fn validate(ip: packet::V) -> Result 66 | { 67 | // have to check this first to avoid out-of-bounds panic on version check 68 | if ip.borrow().get_total_length() < TCP_HDR_LEN as u16 + packet::MIN_HDR_LEN_8S { 69 | return Err(BadPacket::TooShort(ip.borrow().get_total_length() as uint)) 70 | } 71 | 72 | let packet = TcpPacket::new(ip); 73 | 74 | // this should be true as long as IP does it's job and our CODE is correct 75 | // therefore is assert, not check 76 | assert_eq!(packet.ip.borrow().get_total_length() as uint - packet.ip.borrow().hdr_bytes() as uint, 77 | packet.get_tcp().len()); 78 | 79 | let hdr_len = packet.get_hdr_size() as uint * 4; 80 | 81 | if hdr_len > packet.get_tcp().len() 82 | { 83 | return Err(BadPacket::HeaderTooLong(hdr_len, 84 | packet.get_tcp().len())) 85 | }; 86 | if hdr_len < TCP_HDR_LEN as uint 87 | { 88 | return Err(BadPacket::HeaderTooShort(hdr_len)) 89 | }; 90 | 91 | { 92 | let expected = packet.make_header_checksum(); 93 | let got = packet.get_checksum(); 94 | if expected != got 95 | { 96 | return Err(BadPacket::BadChecksum(expected, got)); 97 | } 98 | }; 99 | 100 | Ok(packet) 101 | } 102 | 103 | pub fn as_vec(&self) -> &Vec { 104 | self.ip.as_vec() 105 | } 106 | 107 | pub fn as_mut_vec(&mut self) -> &mut Vec { 108 | self.ip.as_mut_vec() 109 | } 110 | 111 | pub fn to_vec(self) -> Vec { 112 | self.ip.to_vec() 113 | } 114 | 115 | /// Returns slice containing TCP packet 116 | fn get_tcp(&self) -> &[u8] { 117 | self.ip.borrow().get_payload() 118 | } 119 | 120 | /// Returns mutable slice containing TCP packet body 121 | fn get_tcp_mut(&mut self) -> &mut [u8] { 122 | self.ip.borrow_mut().get_payload_mut() 123 | } 124 | 125 | /// Returns immutable slice containing TCP packet header 126 | /// NOTE: assumes no TCP options 127 | fn tcp_hdr(&self) -> &[u8] { 128 | self.get_tcp()[..TCP_HDR_LEN] 129 | } 130 | 131 | /// Returns mutable slice containing TCP packet header 132 | /// NOTE: assumes no TCP options 133 | fn tcp_hdr_mut(&mut self) -> &mut [u8] { 134 | self.get_tcp_mut()[mut ..TCP_HDR_LEN] 135 | } 136 | 137 | /// Returns length of the TCP body 138 | pub fn get_body_len(&self) -> u32 { 139 | (self.get_tcp().len() - TCP_HDR_LEN) as u32 140 | } 141 | 142 | // 4-tuple info 143 | pub fn get_src_addr(&self) -> Addr { 144 | self.ip.borrow().get_source() 145 | } 146 | pub fn get_src_port(&self) -> u16 { 147 | BufReader::new(self.tcp_hdr()[0..2]).read_be_u16().unwrap() 148 | } 149 | pub fn set_src_port(&mut self, port: u16) { 150 | BufWriter::new(self.tcp_hdr_mut()[mut 0..2]).write_be_u16(port).unwrap(); 151 | } 152 | pub fn get_dst_addr(&self) -> Addr { 153 | self.ip.borrow().get_destination() 154 | } 155 | pub fn get_dst_port(&self) -> u16 { 156 | BufReader::new(self.tcp_hdr()[2..4]).read_be_u16().unwrap() 157 | } 158 | pub fn set_dst_port(&mut self, port: u16) { 159 | BufWriter::new(self.tcp_hdr_mut()[mut 2..4]).write_be_u16(port).unwrap(); 160 | } 161 | 162 | // Control Flags 163 | pub fn flags(&self) -> Flags { 164 | const MASK: u8 = 0b_00_111111; 165 | Flags { bits: self.tcp_hdr()[13] & MASK } 166 | } 167 | pub fn flags_mut(&mut self) -> &mut Flags{ 168 | unsafe { transmute(&mut self.tcp_hdr_mut()[13]) } 169 | } 170 | 171 | 172 | // Recv Window size 173 | pub fn get_window_size(&self) -> u16 { 174 | BufReader::new(self.tcp_hdr()[14..16]).read_be_u16().unwrap() 175 | } 176 | pub fn set_window_size(&mut self, window_size: u16) { 177 | BufWriter::new(self.tcp_hdr_mut()[mut 14..16]).write_be_u16(window_size) 178 | .unwrap(); 179 | } 180 | 181 | // AKA data offset: 4 bytes 182 | pub fn get_hdr_size(&self) -> u8 { 183 | (self.tcp_hdr()[12] >> 4) as u8 184 | } 185 | // FIXME: way to ensure this always gets called 186 | pub fn set_hdr_size(&mut self, size: u8) { 187 | self.tcp_hdr_mut()[12] = size << 4; 188 | } 189 | 190 | // Sequence Number Ops 191 | pub fn get_seq_num(&self) -> u32 { 192 | // assert!(self.is_seq()) 193 | BufReader::new(self.tcp_hdr()[4..8]).read_be_u32().unwrap() 194 | } 195 | pub fn set_seq_num(&mut self, seq_num: u32) { 196 | BufWriter::new(self.tcp_hdr_mut()[mut 4..8]).write_be_u32(seq_num) 197 | .unwrap(); 198 | } 199 | 200 | // Acknowledgement Number Ops 201 | pub fn get_ack_num(&self) -> Option { 202 | if self.flags().contains(ACK) { 203 | Some(BufReader::new(self.tcp_hdr()[8..12]).read_be_u32().unwrap()) 204 | } else { 205 | None 206 | } 207 | } 208 | pub fn set_ack_num(&mut self, ack_num: u32) { 209 | self.flags_mut().insert(ACK); 210 | BufWriter::new(self.tcp_hdr_mut()[mut 8..12]).write_be_u32(ack_num) 211 | .unwrap(); 212 | } 213 | 214 | // Checksum Ops 215 | pub fn get_checksum(&self) -> u16 { 216 | BufReader::new(self.tcp_hdr()[16..18]).read_be_u16().unwrap() 217 | } 218 | pub fn set_checksum(&mut self, checksum: u16) { 219 | BufWriter::new(self.tcp_hdr_mut()[mut 16..18]).write_be_u16(checksum) 220 | .unwrap(); 221 | } 222 | 223 | /// Returns TCP payload as slice 224 | pub fn get_payload(&self) -> &[u8] { 225 | self.get_tcp()[TCP_HDR_LEN..] 226 | } 227 | 228 | pub fn get_payload_offset(&self) -> uint { 229 | self.ip.borrow().hdr_bytes() as uint + TCP_HDR_LEN 230 | } 231 | 232 | /// Returns TCP payload as mut slice 233 | pub fn get_mut_payload(&mut self) -> &mut[u8] { 234 | self.get_tcp_mut()[mut TCP_HDR_LEN..] 235 | } 236 | 237 | /// returns native endian 238 | pub fn make_header_checksum(&self) -> u16 239 | { 240 | // +--------+--------+--------+--------+ 241 | // | Source Address | 242 | // +--------+--------+--------+--------+ 243 | // | Destination Address | 244 | // +--------+--------+--------+--------+ 245 | // | zero | PTCL | TCP Length | 246 | // +--------+--------+--------+--------+ 247 | 248 | let len_tcp_bytes = self.get_tcp().len(); 249 | 250 | // the WHOLE IP PACKET 251 | let bytes: &[u8] = self.ip.borrow().as_slice(); 252 | let words: &[u16] = unsafe { packet::cast_slice(bytes[..bytes.len() & !1]) }; 253 | 254 | // src and dest 255 | let pseudo1: &[u16] = words[6..10]; 256 | debug!("done magic number index 1"); 257 | 258 | let pseudo2: [u16, ..2] = [ 259 | (self.ip.borrow().get_protocol() as u16).to_be(), 260 | (self.get_tcp().len() as u16).to_be(), // tcp_len 261 | ]; 262 | 263 | // TODO: Factor out singleton iterator 264 | let zero_checksum_or_last_byte: [u16, ..1] = [ 265 | if len_tcp_bytes % 2 == 0 { 266 | debug!("no magic number index 2 needed"); 267 | 0 268 | } else { // compensate for last byte 269 | let n = bytes[bytes.len() - 1] as u16; 270 | debug!("done magic number index 2"); 271 | n 272 | }.to_be(), 273 | ]; 274 | 275 | let tcp_words = words[packet::MIN_HDR_LEN_16S as uint..]; 276 | 277 | let real1 = tcp_words[..8]; 278 | debug!("done magic number index 3"); 279 | let real2 = tcp_words[9..]; 280 | debug!("done magic number index 4"); 281 | 282 | let iter = real1.iter() 283 | .chain(zero_checksum_or_last_byte.iter()) 284 | .chain(real2.iter()) 285 | .chain(pseudo1.iter()) 286 | .chain(pseudo2.iter()); 287 | 288 | packet::make_checksum(iter.map(|x| Int::from_be(*x))) 289 | } 290 | 291 | pub fn update_checksum(&mut self) { 292 | let cs = self.make_header_checksum(); 293 | self.set_checksum(cs); 294 | } 295 | } 296 | 297 | // For purposes of sorting by sequence number 298 | impl Ord for TcpPacket { 299 | fn cmp(&self, other: &TcpPacket) -> Ordering { 300 | self.get_seq_num().cmp(&other.get_seq_num()) 301 | } 302 | } 303 | 304 | impl PartialOrd for TcpPacket { 305 | fn partial_cmp(&self, other: &TcpPacket) -> Option { 306 | Some(self.cmp(other)) 307 | } 308 | } 309 | 310 | impl fmt::Show for TcpPacket { 311 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 312 | write!(f, "TCP: [Flags:{}] , |srcPort {}|dstPort {}|\n|Seq# {}|\n|Ack# {}|\n|offset {}|ACK {}|SYN {}|FIN {}|window {}|\n|checksum {}|\n{}", self.tcp_hdr()[13], 313 | self.get_src_addr(), self.get_dst_addr(), 314 | self.get_src_port(), self.get_dst_port(), 315 | self.get_seq_num(), 316 | self.get_ack_num(), 317 | self.get_hdr_size(), 318 | self.flags().contains(ACK), self.flags().contains(SYN), self.flags().contains(FIN), 319 | self.get_window_size(), 320 | self.get_checksum(), 321 | self.get_payload()) 322 | } 323 | } 324 | 325 | 326 | #[cfg(test)] 327 | mod test { 328 | use super::*; 329 | 330 | #[test] 331 | fn byte(){ 332 | let b = [1u8]; // 0x1 == 1 333 | //assert_eq!(get_multibyte(&b, 0, 1), 1i); 334 | } 335 | 336 | #[test] 337 | fn short(){ 338 | let b = [1u8, 255u8]; // 0x1_11111111 == 511 339 | //assert_eq!(get_multibyte(&b, 0, 1), 1i); 340 | //assert_eq!(get_multibyte(&b, 0, 2), 511i); 341 | } 342 | 343 | #[test] 344 | fn u32(){ 345 | let b = [10u8, 112u8, 1u8, 123u8]; // 0x00001010_01110000_00000001_01111011 == 511 346 | //assert_eq!(get_multibyte(&b, 0, 1), 10i); 347 | //assert_eq!(get_multibyte(&b, 0, 2), 2672i); 348 | //assert_eq!(get_multibyte(&b, 0, 3), 684033i); 349 | //assert_eq!(get_multibyte(&b, 0, 4), 175112571); 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /transport/tcp/src/receive.rs: -------------------------------------------------------------------------------- 1 | use std::io::{ 2 | IoError, 3 | IoResult, 4 | }; 5 | use std::sync::Arc; 6 | 7 | use network::ipv4::{ 8 | mod, 9 | control, 10 | send, 11 | }; 12 | use network::ipv4::strategy::RoutingTable; 13 | 14 | use super::packet::TcpPacket; 15 | 16 | use trace; 17 | 18 | fn handle(state: &Arc<::State>, 19 | packet: ipv4::packet::V) 20 | where A: RoutingTable 21 | { 22 | let packet = match TcpPacket::validate(packet) { 23 | Ok(p) => p, 24 | Err(e) => { 25 | debug!("TCP packet invalid because {}", e); 26 | return; 27 | }, 28 | }; 29 | 30 | trace::log_trace(&packet, true); 31 | debug!("Got TCP Packet: {}", &packet); 32 | 33 | let dst_port = packet.get_dst_port(); 34 | 35 | let sub_table = match state.tcp.get(&dst_port) { 36 | Some(p) => p, 37 | None => { 38 | debug!("no sub-table--definitely no listener or connection to handle this") 39 | return; 40 | }, 41 | }; 42 | 43 | let src_info = (packet.get_src_addr(), 44 | packet.get_src_port()); 45 | 46 | match sub_table.connections.get(&src_info) { 47 | Some(connection) => { 48 | debug!("existing connection found to handle this! (might be closed)"); 49 | super::connection::trans( 50 | &mut *connection.write(), 51 | &**state, 52 | packet) 53 | }, 54 | None => { 55 | debug!("no existing connection, let's see if we have a listener"); 56 | super::listener::trans( 57 | &mut *sub_table.listener.write(), 58 | state, 59 | packet) 60 | }, 61 | } 62 | } 63 | 64 | /// Registers protocol handler for incomming RIP packets. 65 | pub fn register(state: &Arc>) 66 | where A: RoutingTable 67 | { 68 | control::register_protocol_handler( 69 | &*state.ip, 70 | super::PROTOCOL, 71 | { 72 | let state = state.clone(); 73 | box move | packet: ipv4::packet::V | { 74 | handle(&state, packet); 75 | } 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /transport/tcp/src/ring_buf.rs: -------------------------------------------------------------------------------- 1 | use std::cmp; 2 | use std::slice::bytes::copy_memory; 3 | use std::slice::Items; 4 | use std::iter::{Chain, Map, Scan}; 5 | 6 | #[deriving(Show)] 7 | pub struct RingBuf { 8 | tail: uint, // Back of unconsumed, valid data -- oldest byte written 9 | head: uint, // Front of unconsumed, valid data -- next byte to write 10 | data: Vec, 11 | } 12 | // head == tail is declared to be empty 13 | 14 | 15 | impl RingBuf 16 | { 17 | // Returns new Ring Buffer of given (fixed) size 18 | pub fn new(size: uint) -> RingBuf { 19 | RingBuf { 20 | tail: 0, 21 | head: 0, 22 | data: Vec::from_fn(size + 1, |_| 0), 23 | } 24 | } 25 | 26 | #[inline] 27 | fn check_invariants(&self) { 28 | // always at least one byte in ring buf 29 | assert!(self.data.len() > 0); 30 | // head and tail always point to a valid byte 31 | assert!(self.tail < self.data.len()); 32 | assert!(self.head < self.data.len()); 33 | 34 | // always at least one empty byte -- but you can't use it 35 | assert!(self.readable_len() < self.data.len()); 36 | } 37 | 38 | 39 | #[inline] 40 | pub fn writable_len(&self) -> uint 41 | { 42 | self.check_invariants(); 43 | self.data.len() - self.readable_len() - 1 44 | } 45 | 46 | /// The number of readable/valid bytes 47 | #[inline] 48 | pub fn readable_len(&self) -> uint 49 | { 50 | if self.tail <= self.head { 51 | self.head - self.tail 52 | } else { 53 | self.data.len() - self.tail + self.head 54 | } 55 | } 56 | 57 | // Reads as many bytes as possible into buf, returns number of bytes read 58 | pub fn read(&mut self, buf: &mut [u8]) -> uint 59 | { 60 | self.check_invariants(); 61 | 62 | // Number of bytes we're going to copy 63 | let n = cmp::min(self.readable_len(), buf.len()); 64 | debug!("read: n: {}, ws: {}", n, self.readable_len()); 65 | 66 | // Head of slice we're reading from, wrapped around 67 | let read_head = (self.tail + n) % self.data.len(); 68 | 69 | // If we need to wrap around 70 | if self.tail > read_head 71 | { 72 | let first_slice_len = self.data.len() - self.tail; 73 | 74 | // read until end of vec into first slice of buf 75 | copy_memory(buf[mut ..first_slice_len], self.data[self.tail..]); 76 | 77 | // read from start until head into second slice of buf 78 | copy_memory(buf[mut first_slice_len..n], self.data[0..read_head]); 79 | } 80 | else 81 | { 82 | // Copy straight until head 83 | copy_memory(buf, self.data[self.tail..read_head]); 84 | } 85 | 86 | // Move tail to reflect consumption 87 | self.tail = read_head; 88 | 89 | // Return # bytes read 90 | self.check_invariants(); 91 | n 92 | } 93 | 94 | // Writes as many bytes as possible from buf, returns number of bytes written 95 | pub fn write(&mut self, buf: &[u8]) -> uint 96 | { 97 | self.check_invariants(); 98 | 99 | let len = self.data.len(); 100 | 101 | // Number of bytes we're going to copy 102 | // NOTE: subtract 1 to avoid writing full array - we can't disambiguate full/empty! 103 | let n = cmp::min(self.writable_len(), buf.len()); 104 | //println!("write: n: {}, ws: {}", n, self.readable_len()); 105 | 106 | 107 | // Head of slice we're writing into, wrapped around 108 | let write_head = (self.head + n) % len; 109 | 110 | // If we need to wrap around 111 | if self.tail > write_head 112 | { 113 | let first_slice_len = len - self.head; 114 | 115 | // read until end of vec into first slice of buf 116 | copy_memory(self.data[mut self.head..len], buf[0..first_slice_len]); 117 | 118 | // read from start until head into second slice of buf 119 | copy_memory(self.data[mut ..write_head], buf[first_slice_len..n] ); 120 | } 121 | else 122 | { 123 | // Copy straight until head 124 | copy_memory(self.data[mut self.head..write_head], buf); 125 | } 126 | 127 | // Move head to front of newly written data 128 | self.head = write_head; 129 | 130 | // Return # bytes read 131 | self.check_invariants(); 132 | n 133 | } 134 | } 135 | 136 | impl<'a> RingBuf 137 | { 138 | #[inline] 139 | pub fn iter<'a>(&'a self) -> View<'a> 140 | { 141 | raw_make_iter(&self.data, self.head, self.tail) 142 | } 143 | 144 | #[inline] 145 | pub fn consume_iter<'a>(&'a mut self) -> Consume<'a> 146 | { 147 | let len: uint = self.data.len(); 148 | 149 | // TODO close over len instead 150 | let inc: |&mut (&mut uint, uint), u8|:'a -> Option = |st, b| { 151 | *st.0 = (*st.0 + 1) % st.1; 152 | Some(b) 153 | }; 154 | 155 | raw_make_iter(&self.data, self.head, self.tail) 156 | .scan((&mut self.tail, len), inc) 157 | } 158 | } 159 | 160 | 161 | pub type View<'a> = Map<'a, &'a u8, u8, Chain, Items<'a, u8>>>; 162 | pub type Consume<'a> = Scan<'a, u8, u8, View<'a>, (&'a mut uint, uint)>; 163 | 164 | 165 | // for finer-grain borrowing 166 | #[inline] 167 | fn raw_make_iter<'a>(data: &'a Vec, 168 | head: uint, 169 | tail: uint) -> View<'a> 170 | { 171 | if head < tail 172 | { 173 | // we need to wrap around 174 | data[tail..] 175 | .iter() 176 | .chain(data[..head].iter()) 177 | } 178 | else 179 | { 180 | // continuous (including empty) 181 | 182 | // we need to chain so that the types are the same 183 | data[tail..head] 184 | .iter() 185 | .chain(data[head..head].iter()) 186 | } 187 | .map(|x| *x) 188 | } 189 | 190 | 191 | #[cfg(test)] 192 | mod test 193 | { 194 | use super::RingBuf; 195 | 196 | #[test] 197 | fn empty_readable_lens() { 198 | let mut ring = RingBuf::new(0); 199 | assert_eq!(ring.readable_len(), 0); 200 | } 201 | 202 | #[test] 203 | fn single_valid_byte() { 204 | let mut ring = RingBuf::new(1); 205 | assert_eq!(ring.write([1].as_slice()), 1); 206 | assert_eq!(ring.readable_len(), 1); 207 | } 208 | 209 | #[test] 210 | fn simple(){ 211 | let mut ring = RingBuf::new(10); 212 | let mut buf = [0u8, 0u8]; 213 | assert_eq!(ring.write([1, 1].as_slice()), 2); 214 | println!("after write: {}", ring); 215 | assert_eq!(ring.read(buf.as_mut_slice()), 2); 216 | println!("after read: {}", ring); 217 | assert_eq!(buf, [1,1]); 218 | } 219 | 220 | #[test] 221 | fn slightly_more_complex(){ 222 | let mut ring = RingBuf::new(10); 223 | ring.head = 8; 224 | ring.tail = 8; 225 | let mut buf = [0u8, 0u8, 0u8, 0u8, 0u8]; 226 | assert_eq!(ring.write([1, 1, 2, 3, 4].as_slice()), 5); 227 | println!("after write: {}", ring); 228 | assert_eq!(ring.read(buf.as_mut_slice()), 5); 229 | println!("after read: {}", ring); 230 | assert_eq!(buf, [1,1, 2, 3, 4]); 231 | } 232 | 233 | #[test] 234 | fn wrap(){ 235 | let mut ring = RingBuf::new(4); 236 | let mut buf = [0u8,0u8,0u8,0u8]; 237 | assert_eq!(ring.write([1,2,3].as_slice()), 3); 238 | println!("After write1: {}", ring); 239 | assert_eq!(ring.read(buf.as_mut_slice()), 3); 240 | println!("After read1: {}", ring); 241 | assert_eq!(buf, [1, 2, 3, 0]); 242 | 243 | assert_eq!(ring.write([4, 5, 6, 7].as_slice()), 4); 244 | println!("After write2: {}", ring); 245 | assert_eq!(ring.read(buf.as_mut_slice()), 4); 246 | println!("After read2: {}", ring); 247 | println!("buf: {}", buf.as_slice()); 248 | assert_eq!(buf, [4, 5, 6, 7]) 249 | } 250 | 251 | #[test] 252 | fn simple_non_consuming() { 253 | let mut ring = RingBuf::new(4); 254 | 255 | assert_eq!(ring.write([1,2,3,4].as_slice()), 4); 256 | 257 | assert_eq!(ring.tail, 0); 258 | assert_eq!(ring.head, 4); 259 | assert_eq!(ring.readable_len(), 4); 260 | 261 | ring.check_invariants(); 262 | 263 | let mut iter = ring.iter(); 264 | 265 | assert_eq!(iter.next(), Some(1)); 266 | assert_eq!(iter.next(), Some(2)); 267 | assert_eq!(iter.next(), Some(3)); 268 | assert_eq!(iter.next(), Some(4)); 269 | assert_eq!(iter.next(), None); 270 | 271 | ring.check_invariants(); 272 | 273 | assert_eq!(ring.tail, 0); 274 | assert_eq!(ring.head, 4); 275 | assert_eq!(ring.readable_len(), 4); 276 | } 277 | 278 | #[test] 279 | fn simple_consuming() { 280 | let mut ring = RingBuf::new(4); 281 | assert_eq!(ring.write([1,2,3,4].as_slice()), 4); 282 | 283 | assert_eq!(ring.tail, 0); 284 | assert_eq!(ring.head, 4); 285 | assert_eq!(ring.readable_len(), 4); 286 | 287 | ring.check_invariants(); 288 | 289 | { 290 | let mut iter = ring.consume_iter(); 291 | 292 | assert_eq!(iter.next(), Some(1)); 293 | assert_eq!(iter.next(), Some(2)); 294 | assert_eq!(iter.next(), Some(3)); 295 | assert_eq!(iter.next(), Some(4)); 296 | assert_eq!(iter.next(), None); 297 | } 298 | 299 | ring.check_invariants(); 300 | 301 | assert_eq!(ring.tail, 4); 302 | assert_eq!(ring.head, 4); 303 | assert_eq!(ring.readable_len(), 0); 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /transport/tcp/src/send.rs: -------------------------------------------------------------------------------- 1 | use std::result; 2 | use std::io::net::ip::Port; 3 | use std::error::FromError; 4 | 5 | use network::ipv4::{ 6 | mod, 7 | send, 8 | strategy, 9 | }; 10 | 11 | use packet; 12 | use trace; 13 | 14 | #[deriving(PartialEq, Eq, Clone, Show)] 15 | pub enum Error { 16 | PortOrTripleReserved, 17 | ListenerAlreadyExists, 18 | RouteBrokeConnection, // new route has different src IP so we are fucked 19 | BadHandshake, 20 | External(send::Error), 21 | } 22 | 23 | pub type Result = ::std::result::Result; 24 | 25 | impl FromError for Error { 26 | fn from_error(e: ipv4::send::Error) -> Error { 27 | Error::External(e) 28 | } 29 | } 30 | 31 | pub fn send 32 | <'ip, 'clos, A, E> 33 | (ip_state: &'ip ipv4::State, 34 | //connection: &'tcp Connection, 35 | src_addr: Option, 36 | src_port: Port, 37 | dst: super::ConAddr, 38 | expected_body_size: Option, 39 | upcaster: |self::Error| -> E, 40 | builder: for<'a> |&'a mut packet::TcpPacket|:'clos -> result::Result<(), E>) 41 | -> result::Result<(), E> 42 | where A: strategy::RoutingTable, 43 | E: FromError, 44 | { 45 | let tcp_builder: for<'p> |&'p mut ipv4::packet::V| -> result::Result<(), E> = | packet | 46 | { 47 | // make room for TCP header 48 | let new_len = packet.as_vec().len() + packet::TCP_HDR_LEN; 49 | unsafe { packet.as_mut_vec().set_len(new_len) }; 50 | 51 | let packet = packet::TcpPacket::hack_mut(packet); 52 | 53 | packet.set_src_port(src_port); 54 | packet.set_dst_port(dst.1); 55 | packet.set_hdr_size((packet::TCP_HDR_LEN / 4) as u8); // # 32-bit words in header 56 | 57 | builder(packet) 58 | }; 59 | 60 | let awkward_checksum_fixer: for<'p> |&'p mut ipv4::packet::V| -> result::Result<(), E> = | packet | 61 | { 62 | // Log the sending of this packet 63 | trace::log_trace(packet::TcpPacket::hack(packet), false); 64 | 65 | let packet = packet::TcpPacket::hack_mut(packet); 66 | 67 | match src_addr { 68 | Some(addr) => if addr != packet.get_src_addr() { 69 | return Err(upcaster(Error::RouteBrokeConnection)) 70 | }, 71 | _ => () 72 | }; 73 | 74 | packet.update_checksum(); 75 | Ok(()) 76 | }; 77 | 78 | try!(send::send::( 79 | ip_state, 80 | dst.0, 81 | super::PROTOCOL, 82 | Some(packet::TCP_HDR_LEN as u16 + expected_body_size.unwrap_or(0)), 83 | tcp_builder, 84 | awkward_checksum_fixer)); 85 | 86 | Ok(()) 87 | } 88 | -------------------------------------------------------------------------------- /transport/tcp/src/trace.rs: -------------------------------------------------------------------------------- 1 | use time; 2 | use std::sync::Arc; 3 | 4 | use network::ipv4::{mod, control, send}; 5 | use packet::TcpPacket; 6 | 7 | static RECV_STR : &'static str = "RECV"; 8 | static SEND_STR : &'static str = "SEND"; 9 | 10 | pub fn log_trace(tcp_packet: &TcpPacket, is_recv: bool) { 11 | let action = if is_recv { RECV_STR } else { SEND_STR }; 12 | info!("[TRACE][{}][ns:{}][seq:{}][ack:{}][len:{}][flags:{}][data:{}]", 13 | action, 14 | (time::now_utc().tm_sec as u64) * 100_000_000u64 + time::now_utc().tm_nsec as u64, 15 | tcp_packet.get_seq_num(), 16 | tcp_packet.get_ack_num(), 17 | tcp_packet.get_body_len(), 18 | tcp_packet.flags(), 19 | match ::std::str::from_utf8(tcp_packet.get_payload()) { 20 | None => "binary data, probz too big", 21 | Some(s) => s 22 | }); 23 | } 24 | --------------------------------------------------------------------------------