blob: 8dbf822cf85afc23473bb5c7161e1a33139f6492 [file] [log] [blame]
// Copyright 2018 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.
//! Main process for Fuchsia builds - uses fidl rather than stdin / stdout
#![deny(warnings)]
use {
failure::{Error, ResultExt},
fidl::endpoints::ServiceMarker,
fidl_fuchsia_xi::JsonMarker,
fuchsia_app::server::ServicesServer,
fuchsia_async as fasync,
fuchsia_zircon::{AsHandleRef, Signals, Socket, Status, Time},
futures::{TryFutureExt, future},
std::{
io,
sync::Arc,
thread,
},
xi_core_lib::XiCore,
xi_rpc::RpcLoop,
};
#[allow(deprecated)]
use fidl_fuchsia_xi::{Json, JsonImpl};
// TODO: this should be moved into fuchsia_zircon.
pub struct BlockingSocket(Arc<Socket>);
impl io::Read for BlockingSocket {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let wait_sigs = Signals::SOCKET_READABLE | Signals::SOCKET_PEER_CLOSED;
let signals = self.0.wait_handle(wait_sigs, Time::INFINITE)?;
if signals.contains(Signals::SOCKET_PEER_CLOSED) {
return Ok(0);
}
self.0.read(buf).or_else(|status|
if status == Status::PEER_CLOSED {
Ok(0)
} else {
Err(status.into())
}
)
}
}
impl io::Write for BlockingSocket {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf).map_err(Into::into)
// TODO: handle case where socket is full (wait and retry)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn editor_main(sock: Socket) {
eprintln!("editor_main");
let mut state = XiCore::new();
let arc_sock = Arc::new(sock);
let my_in = io::BufReader::new(BlockingSocket(arc_sock.clone()));
let my_out = BlockingSocket(arc_sock);
let mut rpc_looper = RpcLoop::new(my_out);
let _ = rpc_looper.mainloop(|| my_in, &mut state);
}
#[allow(deprecated)]
fn spawn_json_server(chan: fasync::Channel) {
fasync::spawn(
JsonImpl {
state: (),
on_open: |_, _| future::ready(()),
connect_socket: |_state, socket, _controller| {
eprintln!("connect_socket");
let _ = thread::spawn(move || editor_main(socket));
future::ready(())
}
}
.serve(chan)
.unwrap_or_else(|e| eprintln!("error running xi Json server {:?}", e)))
}
fn main() {
if let Err(e) = main_xi() {
eprintln!("xi-core: Error: {:?}", e);
}
}
fn main_xi() -> Result<(), Error> {
let mut executor = fasync::Executor::new().context("unable to create executor")?;
let server = ServicesServer::new()
.add_service((JsonMarker::NAME, spawn_json_server))
.start()
.map_err(|e| e.context("error starting service server"))?;
let n_threads = 2;
executor.run(server, n_threads)
}