blob: d0622a6b92f33b85575b41f98e1757dca412acce [file]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use assert_matches::assert_matches;
use fidl_fuchsia_net::IpAddress;
use fidl_fuchsia_net_policy_socketproxy::{
FuchsiaNetworkInfo, FuchsiaNetworksProxy, FuchsiaNetworksRequest, FuchsiaNetworksRequestStream,
Network, NetworkDnsServers, NetworkInfo, NetworkRegistryAddResult, NetworkRegistryRemoveResult,
NetworkRegistrySetDefaultResult, NetworkRegistryUpdateResult, StarnixNetworkInfo,
StarnixNetworksProxy,
};
use fidl_fuchsia_posix_socket::OptionalUint32;
use futures::{FutureExt as _, StreamExt as _};
use socket_proxy::NetworkRegistryError;
use std::future::Future;
fn starnix_network_info(mark: u32) -> NetworkInfo {
NetworkInfo::Starnix(StarnixNetworkInfo {
mark: Some(mark),
handle: Some(0),
..Default::default()
})
}
fn starnix_network(network_id: u32) -> Network {
Network {
network_id: Some(network_id),
info: Some(starnix_network_info(network_id)),
dns_servers: Some(Default::default()),
..Default::default()
}
}
fn fuchsia_network(network_id: u32) -> Network {
Network {
network_id: Some(network_id),
info: Some(NetworkInfo::Fuchsia(FuchsiaNetworkInfo { ..Default::default() })),
dns_servers: Some(Default::default()),
..Default::default()
}
}
pub trait ToNetwork {
fn to_network(self, registry: RegistryType) -> Network;
}
impl ToNetwork for u32 {
fn to_network(self, registry: RegistryType) -> Network {
match registry {
RegistryType::Starnix => starnix_network(self),
RegistryType::Fuchsia => fuchsia_network(self),
}
}
}
pub enum RegistryType {
Starnix,
Fuchsia,
}
impl ToNetwork for (u32, Vec<IpAddress>) {
fn to_network(self, registry: RegistryType) -> Network {
let (v4, v6) = self.1.iter().fold((Vec::new(), Vec::new()), |(mut v4s, mut v6s), s| {
match s {
IpAddress::Ipv4(v4) => v4s.push(*v4),
IpAddress::Ipv6(v6) => v6s.push(*v6),
}
(v4s, v6s)
});
let base = match registry {
RegistryType::Starnix => starnix_network(self.0),
RegistryType::Fuchsia => fuchsia_network(self.0),
};
Network {
dns_servers: Some(NetworkDnsServers {
v4: Some(v4),
v6: Some(v6),
..Default::default()
}),
..base
}
}
}
impl<N: ToNetwork + Clone> ToNetwork for &N {
fn to_network(self, registry: RegistryType) -> Network {
self.clone().to_network(registry)
}
}
pub trait NetworkRegistry {
fn set_default(
&self,
network_id: &OptionalUint32,
) -> impl Future<Output = Result<NetworkRegistrySetDefaultResult, fidl::Error>>;
fn add(
&self,
network: &Network,
) -> impl Future<Output = Result<NetworkRegistryAddResult, fidl::Error>>;
fn update(
&self,
network: &Network,
) -> impl Future<Output = Result<NetworkRegistryUpdateResult, fidl::Error>>;
fn remove(
&self,
network_id: u32,
) -> impl Future<Output = Result<NetworkRegistryRemoveResult, fidl::Error>>;
}
macro_rules! impl_network_registry {
($($ty:ty),*) => {
$(
impl NetworkRegistry for $ty {
fn set_default(
&self,
network_id: &OptionalUint32,
) -> impl Future<Output = Result<NetworkRegistrySetDefaultResult, fidl::Error>> {
self.set_default(network_id)
}
fn add(
&self,
network: &Network,
) -> impl Future<Output = Result<NetworkRegistryAddResult, fidl::Error>> {
self.add(network)
}
fn update(
&self,
network: &Network,
) -> impl Future<Output = Result<NetworkRegistryUpdateResult, fidl::Error>> {
self.update(network)
}
fn remove(
&self,
network_id: u32,
) -> impl Future<Output = Result<NetworkRegistryRemoveResult, fidl::Error>> {
self.remove(network_id)
}
}
)*
};
($($ty:ty),*,) => { impl_network_registry!($($ty),*); };
}
impl_network_registry!(StarnixNetworksProxy, FuchsiaNetworksProxy);
pub async fn respond_to_socketproxy(
socket_proxy_req_stream: &mut FuchsiaNetworksRequestStream,
result: Result<(), NetworkRegistryError>,
) {
socket_proxy_req_stream
.next()
.map(|req| match req.expect("request stream ended").expect("receive request") {
FuchsiaNetworksRequest::SetDefault { network_id: _, responder } => {
let res = result.map_err(|e| {
assert_matches!(e, NetworkRegistryError::SetDefault(err) => {
return err;
});
});
responder.send(res).expect("respond to SetDefault");
}
FuchsiaNetworksRequest::Add { network: _, responder } => {
let res = result.map_err(|e| {
assert_matches!(e, NetworkRegistryError::Add(err) => {
return err;
});
});
responder.send(res).expect("respond to Add");
}
FuchsiaNetworksRequest::Update { network: _, responder: _ } => {
unreachable!("not called in tests");
}
FuchsiaNetworksRequest::Remove { network_id: _, responder } => {
let res = result.map_err(|e| {
assert_matches!(e, NetworkRegistryError::Remove(err) => {
return err;
});
});
responder.send(res).expect("respond to Remove");
}
})
.await;
}