1use assert_matches::assert_matches;
6use fidl_fuchsia_net::{IpAddress, SocketAddress};
7use fidl_fuchsia_net_policy_socketproxy::{
8 DnsServerList, FuchsiaNetworkInfo, FuchsiaNetworksProxy, FuchsiaNetworksRequest,
9 FuchsiaNetworksRequestStream, Network, NetworkDnsServers, NetworkInfo,
10 NetworkRegistryAddResult, NetworkRegistryRemoveResult, NetworkRegistrySetDefaultResult,
11 NetworkRegistryUpdateResult, StarnixNetworkInfo, StarnixNetworksProxy,
12};
13use fidl_fuchsia_posix_socket::OptionalUint32;
14use futures::{FutureExt as _, StreamExt as _};
15use socket_proxy::NetworkRegistryError;
16use std::future::Future;
17
18fn dns_server_list(id: u32) -> DnsServerList {
19 DnsServerList { source_network_id: Some(id), addresses: Some(vec![]), ..Default::default() }
20}
21
22fn starnix_network_info(mark: u32) -> NetworkInfo {
23 NetworkInfo::Starnix(StarnixNetworkInfo {
24 mark: Some(mark),
25 handle: Some(0),
26 ..Default::default()
27 })
28}
29
30fn starnix_network(network_id: u32) -> Network {
31 Network {
32 network_id: Some(network_id),
33 info: Some(starnix_network_info(network_id)),
34 dns_servers: Some(Default::default()),
35 ..Default::default()
36 }
37}
38
39fn fuchsia_network(network_id: u32) -> Network {
40 Network {
41 network_id: Some(network_id),
42 info: Some(NetworkInfo::Fuchsia(FuchsiaNetworkInfo { ..Default::default() })),
43 dns_servers: Some(Default::default()),
44 ..Default::default()
45 }
46}
47
48pub trait ToNetwork {
49 fn to_network(self, registry: RegistryType) -> Network;
50}
51
52pub trait ToDnsServerList {
53 fn to_dns_server_list(self) -> DnsServerList;
54}
55
56impl ToNetwork for u32 {
57 fn to_network(self, registry: RegistryType) -> Network {
58 match registry {
59 RegistryType::Starnix => starnix_network(self),
60 RegistryType::Fuchsia => fuchsia_network(self),
61 }
62 }
63}
64
65impl ToDnsServerList for u32 {
66 fn to_dns_server_list(self) -> DnsServerList {
67 dns_server_list(self)
68 }
69}
70
71pub enum RegistryType {
72 Starnix,
73 Fuchsia,
74}
75
76impl ToNetwork for (u32, Vec<IpAddress>) {
77 fn to_network(self, registry: RegistryType) -> Network {
78 let (v4, v6) = self.1.iter().fold((Vec::new(), Vec::new()), |(mut v4s, mut v6s), s| {
79 match s {
80 IpAddress::Ipv4(v4) => v4s.push(*v4),
81 IpAddress::Ipv6(v6) => v6s.push(*v6),
82 }
83 (v4s, v6s)
84 });
85 let base = match registry {
86 RegistryType::Starnix => starnix_network(self.0),
87 RegistryType::Fuchsia => fuchsia_network(self.0),
88 };
89 Network {
90 dns_servers: Some(NetworkDnsServers {
91 v4: Some(v4),
92 v6: Some(v6),
93 ..Default::default()
94 }),
95 ..base
96 }
97 }
98}
99
100impl ToDnsServerList for (u32, Vec<SocketAddress>) {
101 fn to_dns_server_list(self) -> DnsServerList {
102 DnsServerList { addresses: Some(self.1), ..dns_server_list(self.0) }
103 }
104}
105
106impl<N: ToNetwork + Clone> ToNetwork for &N {
107 fn to_network(self, registry: RegistryType) -> Network {
108 self.clone().to_network(registry)
109 }
110}
111
112impl<D: ToDnsServerList + Clone> ToDnsServerList for &D {
113 fn to_dns_server_list(self) -> DnsServerList {
114 self.clone().to_dns_server_list()
115 }
116}
117
118pub trait NetworkRegistry {
119 fn set_default(
120 &self,
121 network_id: &OptionalUint32,
122 ) -> impl Future<Output = Result<NetworkRegistrySetDefaultResult, fidl::Error>>;
123 fn add(
124 &self,
125 network: &Network,
126 ) -> impl Future<Output = Result<NetworkRegistryAddResult, fidl::Error>>;
127 fn update(
128 &self,
129 network: &Network,
130 ) -> impl Future<Output = Result<NetworkRegistryUpdateResult, fidl::Error>>;
131 fn remove(
132 &self,
133 network_id: u32,
134 ) -> impl Future<Output = Result<NetworkRegistryRemoveResult, fidl::Error>>;
135}
136
137macro_rules! impl_network_registry {
138 ($($ty:ty),*) => {
139 $(
140 impl NetworkRegistry for $ty {
141 fn set_default(
142 &self,
143 network_id: &OptionalUint32,
144 ) -> impl Future<Output = Result<NetworkRegistrySetDefaultResult, fidl::Error>> {
145 self.set_default(network_id)
146 }
147
148 fn add(
149 &self,
150 network: &Network,
151 ) -> impl Future<Output = Result<NetworkRegistryAddResult, fidl::Error>> {
152 self.add(network)
153 }
154
155 fn update(
156 &self,
157 network: &Network,
158 ) -> impl Future<Output = Result<NetworkRegistryUpdateResult, fidl::Error>> {
159 self.update(network)
160 }
161
162 fn remove(
163 &self,
164 network_id: u32,
165 ) -> impl Future<Output = Result<NetworkRegistryRemoveResult, fidl::Error>> {
166 self.remove(network_id)
167 }
168 }
169 )*
170 };
171 ($($ty:ty),*,) => { impl_network_registry!($($ty),*); };
172}
173
174impl_network_registry!(StarnixNetworksProxy, FuchsiaNetworksProxy);
175
176pub async fn respond_to_socketproxy(
177 socket_proxy_req_stream: &mut FuchsiaNetworksRequestStream,
178 result: Result<(), NetworkRegistryError>,
179) {
180 socket_proxy_req_stream
181 .next()
182 .map(|req| match req.expect("request stream ended").expect("receive request") {
183 FuchsiaNetworksRequest::SetDefault { network_id: _, responder } => {
184 let res = result.map_err(|e| {
185 assert_matches!(e, NetworkRegistryError::SetDefault(err) => {
186 return err;
187 });
188 });
189 responder.send(res).expect("respond to SetDefault");
190 }
191 FuchsiaNetworksRequest::Add { network: _, responder } => {
192 let res = result.map_err(|e| {
193 assert_matches!(e, NetworkRegistryError::Add(err) => {
194 return err;
195 });
196 });
197 responder.send(res).expect("respond to Add");
198 }
199 FuchsiaNetworksRequest::Update { network: _, responder: _ } => {
200 unreachable!("not called in tests");
201 }
202 FuchsiaNetworksRequest::Remove { network_id: _, responder } => {
203 let res = result.map_err(|e| {
204 assert_matches!(e, NetworkRegistryError::Remove(err) => {
205 return err;
206 });
207 });
208 responder.send(res).expect("respond to Remove");
209 }
210 FuchsiaNetworksRequest::CheckPresence { responder: _ } => {
211 unreachable!("not called in tests");
212 }
213 })
214 .await;
215}