forked from smoltcp-rs/smoltcp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.rs
140 lines (120 loc) · 4.83 KB
/
client.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
mod utils;
use log::debug;
use std::collections::BTreeMap;
use std::os::unix::io::AsRawFd;
use std::str::{self, FromStr};
#[cfg(any(
feature = "proto-sixlowpan-fragmentation",
feature = "proto-ipv4-fragmentation"
))]
use smoltcp::iface::ReassemblyBuffer;
use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes, SocketSet};
use smoltcp::phy::{wait as phy_wait, Device, Medium};
use smoltcp::socket::tcp;
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
fn main() {
utils::setup_logging("");
let (mut opts, mut free) = utils::create_options();
utils::add_tuntap_options(&mut opts, &mut free);
utils::add_middleware_options(&mut opts, &mut free);
free.push("ADDRESS");
free.push("PORT");
let mut matches = utils::parse_options(&opts, free);
let device = utils::parse_tuntap_options(&mut matches);
let fd = device.as_raw_fd();
let mut device =
utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
let port = u16::from_str(&matches.free[1]).expect("invalid port format");
let neighbor_cache = NeighborCache::new();
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1500]);
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1500]);
let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
let mut ip_addrs = heapless::Vec::<IpCidr, 5>::new();
ip_addrs
.push(IpCidr::new(IpAddress::v4(192, 168, 69, 2), 24))
.unwrap();
let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
let mut routes = Routes::new();
routes.add_default_ipv4_route(default_v4_gw).unwrap();
let medium = device.capabilities().medium;
let mut builder = InterfaceBuilder::new().ip_addrs(ip_addrs).routes(routes);
#[cfg(feature = "proto-ipv4-fragmentation")]
let mut ipv4_out_packet_cache = [0u8; 1280];
#[cfg(feature = "proto-ipv4-fragmentation")]
{
let ipv4_frag_cache = ReassemblyBuffer::new(vec![], BTreeMap::new());
builder = builder
.ipv4_reassembly_buffer(ipv4_frag_cache)
.ipv4_fragmentation_buffer(&mut ipv4_out_packet_cache[..]);
}
#[cfg(feature = "proto-sixlowpan-fragmentation")]
let mut sixlowpan_out_packet_cache = [0u8; 1280];
#[cfg(feature = "proto-sixlowpan-fragmentation")]
{
let sixlowpan_frag_cache = ReassemblyBuffer::new(vec![], BTreeMap::new());
builder = builder
.sixlowpan_reassembly_buffer(sixlowpan_frag_cache)
.sixlowpan_fragmentation_buffer(&mut sixlowpan_out_packet_cache[..]);
}
if medium == Medium::Ethernet {
builder = builder
.hardware_addr(ethernet_addr.into())
.neighbor_cache(neighbor_cache);
}
let mut iface = builder.finalize(&mut device);
let mut sockets = SocketSet::new(vec![]);
let tcp_handle = sockets.add(tcp_socket);
let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
socket
.connect(iface.context(), (address, port), 49500)
.unwrap();
let mut tcp_active = false;
loop {
let timestamp = Instant::now();
match iface.poll(timestamp, &mut device, &mut sockets) {
Ok(_) => {}
Err(e) => {
debug!("poll error: {}", e);
}
}
let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
if socket.is_active() && !tcp_active {
debug!("connected");
} else if !socket.is_active() && tcp_active {
debug!("disconnected");
break;
}
tcp_active = socket.is_active();
if socket.may_recv() {
let data = socket
.recv(|data| {
let mut data = data.to_owned();
if !data.is_empty() {
debug!(
"recv data: {:?}",
str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
);
data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
data.reverse();
data.extend(b"\n");
}
(data.len(), data)
})
.unwrap();
if socket.can_send() && !data.is_empty() {
debug!(
"send data: {:?}",
str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
);
socket.send_slice(&data[..]).unwrap();
}
} else if socket.may_send() {
debug!("close");
socket.close();
}
phy_wait(fd, iface.poll_delay(timestamp, &sockets)).expect("wait error");
}
}