1use fidl_fuchsia_net as fnet;
13use fidl_fuchsia_posix_socket::{self as fposix_socket, OptionalUint32};
14use fuchsia_component::server::{ServiceFs, ServiceFsDir};
15use fuchsia_inspect::health::Reporter;
16use fuchsia_inspect_derive::{Inspect, WithInspect as _};
17use futures::channel::mpsc;
18use futures::lock::Mutex;
19use futures::StreamExt as _;
20use log::error;
21use std::sync::Arc;
22
23mod dns_watcher;
24mod registry;
25mod socket_provider;
26
27#[derive(Copy, Clone, Debug)]
28struct SocketMarks {
29 mark_1: OptionalUint32,
30 mark_2: OptionalUint32,
31}
32
33impl From<SocketMarks> for fnet::Marks {
34 fn from(SocketMarks { mark_1, mark_2 }: SocketMarks) -> Self {
35 let into_option_u32 = |opt| match opt {
36 OptionalUint32::Unset(fposix_socket::Empty) => None,
37 OptionalUint32::Value(val) => Some(val),
38 };
39 Self {
40 mark_1: into_option_u32(mark_1),
41 mark_2: into_option_u32(mark_2),
42 __source_breaking: fidl::marker::SourceBreaking,
43 }
44 }
45}
46
47impl SocketMarks {
48 fn has_value(&self) -> bool {
49 match (self.mark_1, self.mark_2) {
50 (OptionalUint32::Value(_), _) => true,
51 (_, OptionalUint32::Value(_)) => true,
52 _ => false,
53 }
54 }
55}
56
57impl Default for SocketMarks {
58 fn default() -> Self {
59 Self {
60 mark_1: OptionalUint32::Unset(fposix_socket::Empty),
61 mark_2: OptionalUint32::Unset(fposix_socket::Empty),
62 }
63 }
64}
65
66#[derive(Inspect)]
67struct SocketProxy {
68 registry: registry::Registry,
69 dns_watcher: dns_watcher::DnsServerWatcher,
70 socket_provider: socket_provider::SocketProvider,
71}
72
73impl SocketProxy {
74 fn new() -> Self {
75 let mark = Arc::new(Mutex::new(SocketMarks::default()));
76 let (dns_tx, dns_rx) = mpsc::channel(1);
77 Self {
78 registry: registry::Registry::new(mark.clone(), dns_tx),
79 dns_watcher: dns_watcher::DnsServerWatcher::new(Arc::new(Mutex::new(dns_rx))),
80 socket_provider: socket_provider::SocketProvider::new(mark),
81 }
82 }
83}
84
85enum IncomingService {
86 StarnixNetworks(fidl_fuchsia_netpol_socketproxy::StarnixNetworksRequestStream),
87 FuchsiaNetworks(fidl_fuchsia_netpol_socketproxy::FuchsiaNetworksRequestStream),
88 DnsServerWatcher(fidl_fuchsia_netpol_socketproxy::DnsServerWatcherRequestStream),
89 PosixSocket(fidl_fuchsia_posix_socket::ProviderRequestStream),
90 PosixSocketRaw(fidl_fuchsia_posix_socket_raw::ProviderRequestStream),
91}
92
93#[fuchsia::main(logging_tags = ["network_socket_proxy"])]
95pub async fn main() -> Result<(), anyhow::Error> {
96 fuchsia_inspect::component::health().set_starting_up();
97
98 let inspector = fuchsia_inspect::component::inspector();
99 let _inspect_server_task =
100 inspect_runtime::publish(inspector, inspect_runtime::PublishOptions::default());
101
102 let proxy = SocketProxy::new().with_inspect(inspector.root(), "root")?;
103
104 let mut fs = ServiceFs::new_local();
105 let _: &mut ServiceFsDir<'_, _> = fs
106 .dir("svc")
107 .add_fidl_service(IncomingService::StarnixNetworks)
108 .add_fidl_service(IncomingService::FuchsiaNetworks)
109 .add_fidl_service(IncomingService::DnsServerWatcher)
110 .add_fidl_service(IncomingService::PosixSocket)
111 .add_fidl_service(IncomingService::PosixSocketRaw);
112
113 let _: &mut ServiceFs<_> = fs.take_and_serve_directory_handle()?;
114
115 fuchsia_inspect::component::health().set_ok();
116
117 fs.for_each_concurrent(100, |service| async {
118 match service {
119 IncomingService::StarnixNetworks(stream) => proxy.registry.run_starnix(stream).await,
120 IncomingService::FuchsiaNetworks(stream) => proxy.registry.run_fuchsia(stream).await,
121 IncomingService::DnsServerWatcher(stream) => proxy.dns_watcher.run(stream).await,
122 IncomingService::PosixSocket(stream) => proxy.socket_provider.run(stream).await,
123 IncomingService::PosixSocketRaw(stream) => proxy.socket_provider.run_raw(stream).await,
124 }
125 .unwrap_or_else(|e| error!("{e:?}"))
126 })
127 .await;
128
129 Ok(())
130}