blob: d234eb12f4116e1330f2fa4bcef370a91d761b46 [file] [log] [blame]
// Copyright 2019 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 {
anyhow::{Context as _, Error},
diagnostics_log::PublishOptions,
fidl::{endpoints::ClientEnd, prelude::*},
fidl_fuchsia_developer_remotecontrol as rcs,
fidl_fuchsia_overnet::{ServiceProviderRequest, ServiceProviderRequestStream},
fuchsia_async as fasync,
fuchsia_component::server::ServiceFs,
futures::channel::mpsc::unbounded,
futures::join,
futures::prelude::*,
hoist::{hoist, OvernetInstance},
remote_control::RemoteControlService,
std::rc::Rc,
std::sync::Arc,
tracing::{error, info},
};
mod args;
mod usb;
async fn exec_server() -> Result<(), Error> {
diagnostics_log::initialize(PublishOptions::default().tags(&["remote-control"]))?;
let router = overnet_core::Router::new(
overnet_core::RouterOptions::new(),
Box::new(overnet_core::SimpleSecurityContext {
node_cert: "/pkg/data/cert.crt",
node_private_key: "/pkg/data/cert.key",
root_cert: "/pkg/data/rootca.crt",
}),
)?;
let connector = {
let router = Arc::clone(&router);
move |socket| {
let router = Arc::clone(&router);
fasync::Task::spawn(async move {
match fidl::AsyncSocket::from_socket(socket) {
Ok(socket) => {
let (mut rx, mut tx) = socket.split();
let (errors_sender, errors) = unbounded();
if let Err(e) = futures::future::join(
circuit::multi_stream::multi_stream_node_connection_to_async(
router.circuit_node(),
&mut rx,
&mut tx,
true,
circuit::Quality::NETWORK,
errors_sender,
"client".to_owned(),
),
errors
.map(|e| {
tracing::warn!("A client circuit stream failed: {e:?}");
})
.collect::<()>(),
)
.map(|(result, ())| result)
.await
{
error!("Error handling Overnet link: {:?}", e);
}
}
Err(e) => error!("Could not handle incoming link socket: {:?}", e),
}
})
.detach();
}
};
let service = Rc::new(RemoteControlService::new(connector).await);
let onet_circuit_fut = {
let (s, p) = fidl::Channel::create();
let chan = fidl::AsyncChannel::from_channel(s)
.context("creating ServiceProvider async channel")?;
let stream = ServiceProviderRequestStream::from_channel(chan);
router
.register_service(rcs::RemoteControlMarker::PROTOCOL_NAME.to_owned(), ClientEnd::new(p))
.await?;
let sc = service.clone();
async move {
let fut = stream.for_each_concurrent(None, move |svc| {
let ServiceProviderRequest::ConnectToService {
chan,
info: _,
control_handle: _control_handle,
} = svc.unwrap();
let chan = fidl::AsyncChannel::from_channel(chan)
.context("failed to make async channel")
.unwrap();
sc.clone().serve_stream(rcs::RemoteControlRequestStream::from_channel(chan))
});
info!("published remote control service to overnet");
let res = fut.await;
info!("connection to overnet lost: {:?}", res);
}
};
let sc = service.clone();
let onet_fut = async move {
loop {
let sc = sc.clone();
let stream = (|| -> Result<_, Error> {
let (s, p) = fidl::Channel::create();
let chan = fidl::AsyncChannel::from_channel(s)
.context("creating ServiceProvider async channel")?;
let stream = ServiceProviderRequestStream::from_channel(chan);
hoist()
.publish_service(rcs::RemoteControlMarker::PROTOCOL_NAME, ClientEnd::new(p))?;
Ok(stream)
})();
let stream = match stream {
Ok(stream) => stream,
Err(err) => {
error!("Could not connect to overnet: {:?}", err);
break;
}
};
let fut = stream.for_each_concurrent(None, move |svc| {
let ServiceProviderRequest::ConnectToService {
chan,
info: _,
control_handle: _control_handle,
} = svc.unwrap();
let chan = fidl::AsyncChannel::from_channel(chan)
.context("failed to make async channel")
.unwrap();
sc.clone().serve_stream(rcs::RemoteControlRequestStream::from_channel(chan))
});
info!("published remote control service to overnet");
let res = fut.await;
info!("connection to overnet lost: {:?}", res);
}
};
let weak_router = Arc::downgrade(&router);
std::mem::drop(router);
let usb_fut = async move {
// TODO: Change this info! to error! Once we can return normally if USB support is disabled
// (fxbug.dev/95554)
if let Err(e) = usb::run_usb_links(weak_router.clone()).await {
info!("USB scanner failed with error {e:?}");
}
};
let sc1 = service.clone();
let mut fs = ServiceFs::new_local();
fs.dir("svc").add_fidl_service(move |req| {
fasync::Task::local(sc1.clone().serve_stream(req)).detach();
});
fs.take_and_serve_directory_handle()?;
let fidl_fut = fs.collect::<()>();
join!(fidl_fut, onet_fut, onet_circuit_fut, usb_fut);
Ok(())
}
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
let args::RemoteControl { cmd } = argh::from_env();
let res = match cmd {
args::Command::DiagnosticsBridge(_) => diagnostics_bridge::exec_server().await,
args::Command::RemoteControl(_) => exec_server().await,
};
if let Err(err) = res {
error!(%err, "Error running command");
std::process::exit(1);
}
Ok(())
}