aboutsummaryrefslogtreecommitdiff
path: root/examples/std/src/bin/tcp_accept.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/std/src/bin/tcp_accept.rs')
-rw-r--r--examples/std/src/bin/tcp_accept.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
new file mode 100644
index 000000000..97ce77f42
--- /dev/null
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -0,0 +1,133 @@
1#![feature(type_alias_impl_trait)]
2
3use core::fmt::Write as _;
4use std::default::Default;
5
6use clap::Parser;
7use embassy_executor::{Executor, Spawner};
8use embassy_net::tcp::TcpSocket;
9use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
10use embassy_time::{Duration, Timer};
11use embedded_io::asynch::Write as _;
12use heapless::Vec;
13use log::*;
14use rand_core::{OsRng, RngCore};
15use static_cell::StaticCell;
16
17#[path = "../tuntap.rs"]
18mod tuntap;
19
20use crate::tuntap::TunTapDevice;
21
22macro_rules! singleton {
23 ($val:expr) => {{
24 type T = impl Sized;
25 static STATIC_CELL: StaticCell<T> = StaticCell::new();
26 STATIC_CELL.init_with(move || $val)
27 }};
28}
29
30#[derive(Parser)]
31#[clap(version = "1.0")]
32struct Opts {
33 /// TAP device name
34 #[clap(long, default_value = "tap0")]
35 tap: String,
36 /// use a static IP instead of DHCP
37 #[clap(long)]
38 static_ip: bool,
39}
40
41#[embassy_executor::task]
42async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! {
43 stack.run().await
44}
45
46#[derive(Default)]
47struct StrWrite(pub heapless::Vec<u8, 30>);
48
49impl core::fmt::Write for StrWrite {
50 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
51 self.0.extend_from_slice(s.as_bytes()).unwrap();
52 Ok(())
53 }
54}
55
56#[embassy_executor::task]
57async fn main_task(spawner: Spawner) {
58 let opts: Opts = Opts::parse();
59
60 // Init network device
61 let device = TunTapDevice::new(&opts.tap).unwrap();
62
63 // Choose between dhcp or static ip
64 let config = if opts.static_ip {
65 Config::Static(embassy_net::StaticConfig {
66 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
67 dns_servers: Vec::new(),
68 gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
69 })
70 } else {
71 Config::Dhcp(Default::default())
72 };
73
74 // Generate random seed
75 let mut seed = [0; 8];
76 OsRng.fill_bytes(&mut seed);
77 let seed = u64::from_le_bytes(seed);
78
79 // Init network stack
80 let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed));
81
82 // Launch network task
83 spawner.spawn(net_task(stack)).unwrap();
84
85 // Then we can use it!
86 let mut rx_buffer = [0; 4096];
87 let mut tx_buffer = [0; 4096];
88
89 loop {
90 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
91 socket.set_timeout(Some(Duration::from_secs(10)));
92 info!("Listening on TCP:9999...");
93 if let Err(_) = socket.accept(9999).await {
94 warn!("accept error");
95 continue;
96 }
97
98 info!("Accepted a connection");
99
100 // Write some quick output
101 for i in 1..=5 {
102 let mut w = StrWrite::default();
103 write!(w, "{}! ", i).unwrap();
104 let r = socket.write_all(&w.0).await;
105 if let Err(e) = r {
106 warn!("write error: {:?}", e);
107 return;
108 }
109
110 Timer::after(Duration::from_millis(500)).await;
111 }
112 info!("Closing the connection");
113 socket.abort();
114 info!("Flushing the RST out...");
115 socket.flush().await;
116 info!("Finished with the socket");
117 }
118}
119
120static EXECUTOR: StaticCell<Executor> = StaticCell::new();
121
122fn main() {
123 env_logger::builder()
124 .filter_level(log::LevelFilter::Debug)
125 .filter_module("async_io", log::LevelFilter::Info)
126 .format_timestamp_nanos()
127 .init();
128
129 let executor = EXECUTOR.init(Executor::new());
130 executor.run(|spawner| {
131 spawner.spawn(main_task(spawner)).unwrap();
132 });
133}