multicast ttl support

This commit is contained in:
Tony Garnock-Jones 2024-06-11 21:05:33 +02:00
parent b88c336714
commit 9b5f2f9e80
3 changed files with 77 additions and 39 deletions

View File

@ -4,4 +4,4 @@ sourcePort
ByteString„„„„„³ PacketOut´³rec´³lit³udp-out„´³tupleµ´³named³
targetAddr´³atom³String„„´³named³
targetPort´³atom³ SignedInteger„„´³named³body´³atom³
ByteString„„„„„³MulticastLoopback´³rec´³lit³udp-multicast-loopback„´³tupleµ´³named³enabled´³atom³Boolean„„„„„³MulticastGroupMember´³rec´³lit³udp-multicast-group-member„´³tupleµ´³named³ groupAddress´³atom³String„„´³named³groupInterface´³atom³String„„„„„„³ embeddedType€„„„„
ByteString„„„„„³ MulticastTtl´³rec´³lit³udp-multicast-ttl„´³tupleµ´³named³hopCount´³atom³ SignedInteger„„„„„³MulticastLoopback´³rec´³lit³udp-multicast-loopback„´³tupleµ´³named³enabled´³atom³Boolean„„„„„³MulticastGroupMember´³rec´³lit³udp-multicast-group-member„´³tupleµ´³named³ groupAddress´³atom³String„„´³named³groupInterface´³atom³String„„„„„„³ embeddedType€„„„„

View File

@ -13,8 +13,9 @@ Error = <udp-error @detail any> .
PacketIn = <udp-in @sourceAddr string @sourcePort int @body bytes> .
PacketOut = <udp-out @targetAddr string @targetPort int @body bytes> .
# Assertion from local application
# Assertions from local application
MulticastGroupMember = <udp-multicast-group-member @groupAddress string @groupInterface string> .
MulticastTtl = <udp-multicast-ttl @hopCount int> .
# Message from local application
MulticastLoopback = <udp-multicast-loopback @enabled bool> .

View File

@ -2,7 +2,13 @@ use std::net::SocketAddr;
use std::sync::Arc;
use preserves_schema::Codec;
use syndicate::{actor::{Account, Activation, ActorResult, AnyValue, Cap, FacetRef, LinkedTaskTermination}, dataspace::Dataspace, relay, schemas::trace, value::NestedValue};
use syndicate::{
actor::{Account, Activation, ActorResult, AnyValue, Cap, FacetRef, LinkedTaskTermination},
dataspace::Dataspace,
relay,
schemas::trace,
value::NestedValue,
};
mod schemas {
include!(concat!(env!("OUT_DIR"), "/src/schemas/mod.rs"));
@ -41,41 +47,72 @@ async fn run_udp_socket(
addr: local_addr.ip().to_string(),
port: local_addr.port().into(),
});
enclose!((sock) on_message!(t, space, language(), $p: udp::PacketOut, enclose!((sock) move |_t: &mut Activation| {
tracing::trace!(?p, "outbound packet");
let target: SocketAddr = str::parse(&format!("{}:{}", p.target_addr, p.target_port))?;
match sock.try_send_to(&p.body[..], target) {
Ok(_) => (),
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => (),
Err(e) => Err(e)?,
}
Ok(())
})));
enclose!((sock, space) during!(t, space, language(), $g: udp::MulticastGroupMember, enclose!((sock, space) move |t: &mut Activation| {
tracing::debug!(?g, "adding multicast group");
let group_address = str::parse(&g.group_address)?;
let group_interface = str::parse(&g.group_interface)?;
let mut ok = true;
if let Err(err) = sock.join_multicast_v4(group_address, group_interface) {
ok = false;
space.assert(t, language(), &udp::Error { detail: AnyValue::new(format!("{}", err)) });
}
t.on_stop(enclose!((g) move |_t| {
if ok {
tracing::debug!(?g, "removing multicast group");
sock.leave_multicast_v4(group_address, group_interface)?;
}
Ok(())
}));
Ok(())
})));
enclose!((sock, space) on_message!(t, space, language(), $l: udp::MulticastLoopback, enclose!((sock, space) move |t: &mut Activation| {
tracing::debug!(?l, "setting multicast loopback");
if let Err(err) = sock.set_multicast_loop_v4(l.enabled) {
space.assert(t, language(), &udp::Error { detail: AnyValue::new(format!("{}", err)) });
}
Ok(())
})));
enclose!(
(sock) on_message!(t, space, language(), $p: udp::PacketOut, enclose!(
(sock) move |_t: &mut Activation| {
tracing::trace!(?p, "outbound packet");
let target: SocketAddr =
str::parse(&format!("{}:{}", p.target_addr, p.target_port))?;
match sock.try_send_to(&p.body[..], target) {
Ok(_) => (),
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => (),
Err(e) => Err(e)?,
}
Ok(())
})));
enclose!(
(sock, space) during!(t, space, language(), $g: udp::MulticastGroupMember, enclose!(
(sock, space) move |t: &mut Activation| {
tracing::debug!(?g, "adding multicast group");
let group_address = str::parse(&g.group_address)?;
let group_interface = str::parse(&g.group_interface)?;
let mut ok = true;
if let Err(err) = sock.join_multicast_v4(group_address, group_interface) {
ok = false;
space.assert(t, language(), &udp::Error {
detail: AnyValue::new(format!("join_multicast_v4: {}", err)),
});
}
t.on_stop(enclose!((g) move |_t| {
if ok {
tracing::debug!(?g, "removing multicast group");
sock.leave_multicast_v4(group_address, group_interface)?;
}
Ok(())
}));
Ok(())
})));
enclose!(
(sock, space) on_message!(t, space, language(), $l: udp::MulticastLoopback, enclose!(
(sock, space) move |t: &mut Activation| {
tracing::debug!(?l, "setting multicast loopback");
if let Err(err) = sock.set_multicast_loop_v4(l.enabled) {
space.assert(t, language(), &udp::Error {
detail: AnyValue::new(format!("set_multicast_loop_v4: {}", err)),
});
}
Ok(())
})));
enclose!(
(sock, space) during!(t, space, language(), $n: udp::MulticastTtl, enclose!(
(sock, space) move |t: &mut Activation| {
tracing::debug!(?n, "setting multicast ttl");
let hop_count = match u32::try_from(&n.hop_count) {
Ok(hop_count) => hop_count,
Err(_) => {
space.assert(t, language(), &udp::Error {
detail: AnyValue::new("set_multicast_ttl_v4: bad hop count"),
});
return Ok(());
}
};
if let Err(err) = sock.set_multicast_ttl_v4(hop_count) {
space.assert(t, language(), &udp::Error {
detail: AnyValue::new(format!("set_multicast_ttl_v4: {}", err)),
});
}
Ok(())
})));
Ok(())
}));
let mut buf = [0; 65536];
@ -111,7 +148,7 @@ async fn main() -> ActorResult {
match run_udp_socket(&b, account.clone(), cause, facet.clone()).await {
Ok(()) => Ok(LinkedTaskTermination::Normal),
Err(err) => {
let err_val = AnyValue::new(format!("{}", err));
let err_val = AnyValue::new(format!("udp_io: {}", err));
facet.activate(&account, err_cause, move |t| {
b.space.assert(t, language(), &udp::Error { detail: err_val });
Ok(())