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