Created
November 8, 2018 15:47
-
-
Save povilasb/d4c51405eea2494d8a50c0d4b8fb6a45 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[cfg(target_os = "linux")] | |
#[test] | |
fn keep_alive() { | |
let mut evloop = Core::new().unwrap(); | |
let network = Network::new(&evloop.handle()); | |
let network_handle = network.handle(); | |
let (server_addr_tx, server_addr_rx) = oneshot::channel(); | |
let (plug_client, mut plug_server) = IpPlug::new_pair(); | |
let plug_client = plug_client.map(move |packet| { | |
println!("[client] rx: {:?}", packet); | |
packet | |
}).into_ip_plug(&network_handle); | |
let mut syn_received = false; | |
let mut ack_received = false; | |
let plug_server = plug_server.filter(move |packet| { | |
println!("[server] rx: {:?}", packet); | |
// Drop all incoming packets to server after TCP connection was established. So keepalive | |
// packets comming from client will be dropped and client won't receive further ACKs | |
let allow_packet = !(syn_received && ack_received); | |
syn_received |= packet.to_ipv4_packet().and_then(|p| p.to_tcp_packet()) | |
.and_then(|p| Some(p.is_syn())).unwrap_or(false); | |
ack_received |= packet.to_ipv4_packet().and_then(|p| p.to_tcp_packet()) | |
.and_then(|p| Some(p.is_ack())).unwrap_or(false); | |
allow_packet | |
}).into_ip_plug(&network_handle); | |
let server_ip = Ipv4Addr::random_global(); | |
let spawn_server = netsim::device::MachineBuilder::new() | |
.add_ip_iface( | |
netsim::iface::IpIfaceBuilder::new() | |
.ipv4_addr(server_ip, 0) | |
.ipv4_route(Ipv4Route::new(Ipv4Range::global(), None)), | |
plug_server, | |
).spawn(&network_handle, move || { | |
println!("[server] ip = {}", server_ip); | |
let bind_addr = SocketAddr::V4(SocketAddrV4::new(server_ip, 0)); | |
let listener = unwrap!(TcpListener::bind(bind_addr)); | |
let server_addr = unwrap!(listener.local_addr()); | |
let _ = server_addr_tx.send(server_addr); | |
let (mut client_sock, _client_addr) = unwrap!(listener.accept()); | |
println!("[server] new client: {}", _client_addr); | |
let mut buf = [0; 4096]; | |
let res = client_sock.read(&mut buf); | |
assert!(res.is_err()); | |
}); | |
let spawn_client = netsim::device::MachineBuilder::new() | |
.add_ip_iface( | |
netsim::iface::IpIfaceBuilder::new() | |
.ipv4_addr(Ipv4Addr::random_global(), 0) | |
.ipv4_route(Ipv4Route::new(Ipv4Range::global(), None)), | |
plug_client, | |
).spawn(&network_handle, move || { | |
const SOCKET1_TOKEN: Token = Token(0); | |
let evloop = unwrap!(Poll::new()); | |
let server_addr = unwrap!(server_addr_rx.wait()); | |
let mut sock1 = unwrap!(TcpSock::connect(&server_addr)); | |
unwrap!(evloop.register(&sock1, SOCKET1_TOKEN, Ready::writable() | Ready::readable(), PollOpt::edge(),)); | |
let mut events = Events::with_capacity(16); | |
'event_loop: loop { | |
unwrap!(evloop.poll(&mut events, None)); | |
for ev in events.iter() { | |
use std::time::Duration; | |
match ev.token() { | |
SOCKET1_TOKEN => { | |
let res: Result<Option<Vec<u8>>, SocketError> = sock1.read(); | |
println!("[client] bytes read {:?}", unwrap!(res)); | |
} | |
_ => panic!("Unexpected event"), | |
} | |
} | |
} | |
}); | |
unwrap!(evloop.run(spawn_server.join(spawn_client))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment