Skip to main content

netget/server/ethernet_ip/
mod.rs

1pub mod actions;
2pub mod codec;
3use crate::protocol::SpawnContext;
4use anyhow::{ensure, Result};
5use std::{net::SocketAddr, sync::Arc};
6pub async fn spawn(ctx: SpawnContext) -> Result<SocketAddr> {
7    let types = ctx
8        .startup_params
9        .as_ref()
10        .map(|p| p.get_optional_array("attribute_types"))
11        .transpose()?
12        .flatten()
13        .cloned()
14        .unwrap_or_default();
15    ensure!(types.len() <= 128, "at most 128 attribute schemas");
16    for t in &types {
17        let mut a = t.clone();
18        a["type"] = serde_json::json!("ethernet_ip_get");
19        codec::validate(&a)?;
20    }
21    // Acquire both sockets before starting any task. A UDP port conflict must not leave
22    // the TCP adapter alive after startup fails.
23    let listener =
24        crate::server::socket_helpers::create_reusable_tcp_listener(ctx.legacy_listen_addr())
25            .await?;
26    let addr = listener.local_addr()?;
27    let socket = tokio::net::UdpSocket::bind(addr).await?;
28    let schemas = types.clone();
29    let addr = crate::server::ics_support::spawn_accept_bounded(
30        ctx.clone(),
31        Arc::new(actions::EthernetIpProtocol),
32        move || {
33            let mut device = codec::Device::default();
34            device.types = schemas.clone();
35            device
36        },
37        &actions::EVENTS,
38        listener,
39    )
40    .await?;
41    let state = ctx.state.clone();
42    let sid = ctx.server_id;
43    state
44        .spawn_server_task(sid, async move {
45            let mut buf = [0; codec::MAX_FRAME + 1];
46            while let Ok((n, peer)) = socket.recv_from(&mut buf).await {
47                if n == 24
48                    && buf[0..4] == [0x63, 0, 0, 0]
49                    && buf[4..12] == [0; 8]
50                    && buf[20..24] == [0; 4]
51                {
52                    let mut context = [0; 8];
53                    context.copy_from_slice(&buf[12..20]);
54                    let response = codec::encapsulate(0x63, 0, context, 0, &codec::identity(addr));
55                    let _ = socket.send_to(&response, peer).await;
56                }
57            }
58        })
59        .await;
60    Ok(addr)
61}