This commit is contained in:
Joshua Coles
2025-02-12 09:59:37 +00:00
parent 2d02fde6c6
commit d2909d5c17
5 changed files with 260 additions and 2 deletions
+34
View File
@@ -0,0 +1,34 @@
use std::net::{IpAddr, SocketAddr};
use tokio::net::UdpSocket;
use tracing::debug;
use socket2::{Socket, Domain, Type, Protocol};
use serde::{Deserialize, Serialize};
use crate::topology::DeviceCapabilities;
#[derive(Debug, Serialize, Deserialize)]
struct DiscoveryMessage {
#[serde(rename = "type")]
message_type: String,
node_id: String,
grpc_port: u16,
device_capabilities: DeviceCapabilities,
priority: u32,
interface_name: String,
interface_type: String,
}
async fn broadcast(address: SocketAddr) {
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
socket.set_broadcast(true).unwrap();
socket.set_reuse_address(true).unwrap();
#[cfg(not(target_os = "windows"))]
socket.set_reuse_port(true).unwrap();
socket.bind(&address.into()).unwrap();
let udp: UdpSocket = UdpSocket::from_std(socket.into()).unwrap();
//
// loop {
// udp.send_to()
// }
}
+2
View File
@@ -1,5 +1,7 @@
mod topology;
mod orchestration;
mod discovery;
mod network;
use serde::{Deserialize, Serialize};
use serde_json::Value;
+132
View File
@@ -0,0 +1,132 @@
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig};
use socket2::{Domain, Protocol, Socket, Type};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::time::Duration;
use serde::{Deserialize, Serialize};
use tokio::net::UdpSocket;
use crate::topology::DeviceCapabilities;
#[derive(Copy, Clone, Debug)]
enum InterfaceType {
ContainerVirtual,
Loopback,
Thunderbolt,
Ethernet,
WiFi,
ExternalVirtual,
Other,
}
impl InterfaceType {
fn priority(&self) -> u8 {
match self {
InterfaceType::ContainerVirtual => 7,
InterfaceType::Loopback => 6,
InterfaceType::Thunderbolt => 5,
InterfaceType::Ethernet => 4,
InterfaceType::WiFi => 3,
InterfaceType::ExternalVirtual => 1,
InterfaceType::Other => 2,
}
}
}
impl ToString for InterfaceType {
fn to_string(&self) -> String {
match self {
InterfaceType::ContainerVirtual => "Container Virtual".to_string(),
InterfaceType::Loopback => "Loopback".to_string(),
InterfaceType::Thunderbolt => "Thunderbolt".to_string(),
InterfaceType::Ethernet => "Ethernet".to_string(),
InterfaceType::WiFi => "WiFi".to_string(),
InterfaceType::ExternalVirtual => "External Virtual".to_string(),
InterfaceType::Other => "Other".to_string(),
}
}
}
struct BroadcastCreationInfo {
interface_name: String,
interface_type: InterfaceType,
bind_address: Ipv4Addr,
broadcast_address: Ipv4Addr,
}
fn get_broadcast_creation_info() -> Vec<BroadcastCreationInfo> {}
struct NodeInfo {
node_id: String,
node_port: u16,
device_capabilities: DeviceCapabilities,
}
#[derive(Debug, Serialize, Deserialize)]
struct DiscoveryMessage {
#[serde(rename = "type")]
message_type: String,
node_id: String,
grpc_port: u16,
device_capabilities: DeviceCapabilities,
priority: u8,
interface_name: String,
interface_type: String,
}
async fn listen(broadcast_creation_info: BroadcastCreationInfo, node_info: NodeInfo, broadcast_port: u16, broadcast_interval: Duration) {
let socket_addr = SocketAddr::new(
IpAddr::V4(broadcast_creation_info.bind_address),
0,
);
let socket = bind_to_address(socket_addr);
let message = serde_json::to_vec(&DiscoveryMessage {
message_type: "discovery".to_string(),
node_id: node_info.node_id,
grpc_port: node_info.node_port,
device_capabilities: node_info.device_capabilities,
priority: broadcast_creation_info.interface_type.priority(),
interface_name: broadcast_creation_info.interface_name,
interface_type: broadcast_creation_info.interface_type.to_string(),
}).unwrap();
loop {
socket.send_to(
&message,
SocketAddr::new(IpAddr::V4(broadcast_creation_info.broadcast_address), broadcast_port),
).await.unwrap();
tokio::time::sleep(broadcast_interval).await;
}
}
fn bind_to_address(address: SocketAddr) -> UdpSocket {
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
socket.set_broadcast(true).unwrap();
socket.set_reuse_address(true).unwrap();
#[cfg(not(target_os = "windows"))]
socket.set_reuse_port(true).unwrap();
socket.bind(&address.into()).unwrap();
UdpSocket::from_std(socket.into()).unwrap()
}
#[test]
fn test_interfaces() {
let raw = NetworkInterface::show().unwrap();
let names_and_addrs = raw
.iter()
.flat_map(|network_interface| {
let v4_addrs = network_interface
.addr
.iter()
.filter(|addr: &&Addr| matches!(addr, Addr::V4(..)))
.map(|addr: &Addr| (network_interface.name.clone(), *addr));
v4_addrs
})
.collect::<Vec<_>>();
}