From 2a15f4c503803b430a16897104532edcc745aef0 Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Mon, 14 Apr 2025 22:17:43 +0200 Subject: [PATCH] save --- Cargo.lock | 33 ++++++++++++++ Cargo.toml | 7 ++- src/lib.rs | 3 +- src/main.rs | 128 ++++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 152 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a94491..a46aa2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,18 @@ dependencies = [ "defmt", ] +[[package]] +name = "dhcparse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1b7bc252945fef54ffa028dec6a3fcf7b1931968f4db476c93d0eab0d92d62" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "memchr", + "ref-cast", +] + [[package]] name = "digest" version = "0.10.7" @@ -1080,6 +1092,7 @@ dependencies = [ "cyw43-pio", "defmt", "defmt-rtt", + "dhcparse", "embassy-executor", "embassy-net", "embassy-rp", @@ -1226,6 +1239,26 @@ dependencies = [ "bitflags 2.9.0", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "regex" version = "1.11.1" diff --git a/Cargo.toml b/Cargo.toml index a1a1ad0..ec2f19e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,8 @@ embassy-net = { git = "https://github.com/embassy-rs/embassy", features = [ "defmt", "proto-ipv4", "tcp", + "udp", "dhcpv4", - # "dns", - # "icmp", - "packet-trace" ] } cyw43-pio = {git = "https://github.com/embassy-rs/embassy"} cyw43 = {git = "https://github.com/embassy-rs/embassy"} @@ -49,4 +47,5 @@ rand_core = "*" log = "*" serde-json-core = {version = "*", optional = true} -serde = {version = "*", optional = true, default-features = false, features = ["derive"]} \ No newline at end of file +serde = {version = "*", optional = true, default-features = false, features = ["derive"]} +dhcparse = {version = "*", default-features = false} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 7be1180..efefcb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,8 @@ pub async fn unwrap(res: Result) -> T { Err(e) => { error!("FATAL ERROR : {:?}", e); loop { - Timer::after_millis(0).await; + error!("FATAL ERROR : {:?}", e); + Timer::after_secs(5).await; } } } diff --git a/src/main.rs b/src/main.rs index 295e198..d80caea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,11 @@ use core::net::Ipv4Addr; use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; +use dhcparse::dhcpv4::{DhcpOption, Encode as _, MessageType, OpCode}; +use dhcparse::{dhcpv4, v4_options}; use embassy_executor::Spawner; -use embassy_net::{Config, DhcpConfig, StackResources}; +use embassy_net::udp::{PacketMetadata, UdpMetadata, UdpSocket}; +use embassy_net::{Config, DhcpConfig, IpEndpoint, StackResources}; use embassy_rp::bind_interrupts; use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Level, Output}; @@ -15,6 +18,8 @@ use embassy_rp::peripherals::USB; use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler as PioInterruptHandler, Pio}; use embassy_rp::usb::{Driver, InterruptHandler as UsbInterruptHandler}; +use embassy_time::Timer; +use heapless::Vec; use log::info; use rand_core::RngCore; use static_cell::StaticCell; @@ -88,17 +93,19 @@ async fn main(spawner: Spawner) { }); #[cfg(feature = "wifi-connect")] - let wifi_conf = unwrap(serde_json_core::from_slice::(include_bytes!("../wifi.json"))).await.0; - // Use a link-local address for communication without DHCP server - // let config = Config::dhcpv4(embassy_net::DhcpConfig::default()); - #[cfg(feature = "wifi-connect")] - let config = match wifi_conf.ip { - Some(ip) => Config::ipv4_static(embassy_net::StaticConfigV4 { - address: embassy_net::Ipv4Cidr::new(ip, 24), - dns_servers: heapless::Vec::new(), - gateway: None, - }), - None => Config::dhcpv4(DhcpConfig::default()) + let (wifi_conf, config) = { + let wifi_conf = unwrap(serde_json_core::from_slice::(include_bytes!("../wifi.json"))).await.0; + // Use a link-local address for communication without DHCP server + // let config = Config::dhcpv4(embassy_net::DhcpConfig::default()); + let config = match wifi_conf.ip { + Some(ip) => Config::ipv4_static(embassy_net::StaticConfigV4 { + address: embassy_net::Ipv4Cidr::new(ip, 24), + dns_servers: heapless::Vec::new(), + gateway: None, + }), + None => Config::dhcpv4(DhcpConfig::default()) + }; + (wifi_conf, config) }; @@ -151,8 +158,101 @@ async fn main(spawner: Spawner) { ) } - unwrap(spawner.spawn(socket::listen_task(stack, game::Team::Zero, 80))).await; - unwrap(spawner.spawn(socket::listen_task(stack, game::Team::One, 81))).await; + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + let mut res_buf = Vec::::new(); + loop { + let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + unwrap(socket.bind(67)).await; + + loop { + // loop { + // if socket.may_recv() { + // break + // } + // } + // info!("may recv"); + // Timer::after_secs(0).await; + + let (n, ep) = unwrap(socket.recv_from(&mut buf).await).await; + + // if let Ok(s) = core::str::from_utf8(&buf[..n]) { + // info!("rxd str from {}: {}", ep, s); + // } else { + // info!("rxd not str from {}: {:?}", ep, &buf[..n]); + // } + // Timer::after_secs(0).await; + + let msg = unwrap(dhcpv4::Message::new(&buf[..n])).await; + + let opts = unwrap(v4_options!(msg; MessageType required)).await; + + match opts { + dhcpv4::MessageType::DISCOVER => { + res_buf.clear(); + res_buf.push(2).unwrap(); // op + res_buf.push(1).unwrap(); // htype + res_buf.push(6).unwrap(); // hlen + res_buf.push(0).unwrap(); // hops + res_buf.extend_from_slice(&buf[4..8]).unwrap(); // xid + res_buf.extend_from_slice(&[0; 2]).unwrap(); // secs + res_buf.extend_from_slice(&buf[10..12]).unwrap(); // flags + res_buf.extend_from_slice(&[0; 4]).unwrap(); // ciaddr + res_buf.extend_from_slice(&[192, 254, 0, 12]).unwrap(); // yiaddr + res_buf.extend_from_slice(&[192, 254, 0, 2]).unwrap(); // siaddr + res_buf.extend_from_slice(&buf[24..28]).unwrap(); // giaddr + res_buf.extend_from_slice(&buf[28..44]).unwrap(); // chaddr + res_buf.extend_from_slice(&[0; 192]).unwrap(); // sname/file + res_buf.extend_from_slice(&[99, 130, 83, 99]).unwrap(); // magic cookie + // options + res_buf.extend_from_slice(&[53, 1, 2]).unwrap(); // message type + res_buf.extend_from_slice(&[1, 4, 255, 255, 255, 0]).unwrap(); // subnet mask + res_buf.extend_from_slice(&[3, 4, 192, 254, 0, 2]).unwrap(); // router + res_buf.extend_from_slice(&[6, 4, 0, 0, 0, 0]).unwrap(); // dns + res_buf.extend_from_slice(&[15, 1, 0]).unwrap(); // domain name + res_buf.extend_from_slice(&[26, 2, 0x5, 0xEA]).unwrap(); // mtu + res_buf.extend_from_slice(&[28, 4, 192, 254, 0, 255]).unwrap(); // domain name + res_buf.extend_from_slice(&[51, 4, 0, 0, 0x2, 0xBC]).unwrap(); // address lease time = 700s + res_buf.extend_from_slice(&[58, 4, 0, 0, 0x2, 0x58]).unwrap(); // renewal time = 600s + res_buf.extend_from_slice(&[59, 4, 0, 0, 0x2, 0x58]).unwrap(); // rebinding time = 600s + res_buf.extend_from_slice(&[43, 1, 0]).unwrap(); // vendor specific + let captive_portal_uri = "http://192.254.0.2:80/"; + res_buf.extend_from_slice(&[114, captive_portal_uri.len() as u8]).unwrap(); // captive portal + res_buf.extend_from_slice(captive_portal_uri.as_bytes()).unwrap(); + res_buf.extend_from_slice(&[108, 4, 0, 0, 0, 0]).unwrap(); // ipv6 only + + for o in unwrap(unwrap(dhcpv4::Message::new(&res_buf)).await.options()).await { + info!("{:?}", match o { + Err(_) => break, + Ok(o) => o + }); + } + + unwrap(socket.send_to(&res_buf, UdpMetadata { + endpoint: IpEndpoint::new(Ipv4Addr::new(193, 254, 0, 12).into(), 68), + local_address: Some(Ipv4Addr::new(192, 254, 0, 2).into()), + meta: Default::default() + }).await).await; + }, + _ => {} + } + for o in unwrap(msg.options()).await { + info!("{:?}", match o { + Err(_) => break, + Ok(o) => o + }); + } + info!("{:?}", opts); + Timer::after_secs(0).await; + // unwrap(socket.send_to(&buf[..n], ep).await).await; + } + } + + // unwrap(spawner.spawn(socket::listen_task(stack, game::Team::Zero, 80))).await; + // unwrap(spawner.spawn(socket::listen_task(stack, game::Team::One, 81))).await; } #[cfg(feature="wifi-connect")]