blob: fd7e52da443a8b3ae2b475934ae71e9b95165979 [file] [log] [blame]
use crate::devices::BindingId;
use crate::eventloop::{Event, EventLoop};
use failure::Error;
use fidl_fuchsia_posix_socket as psocket;
use fuchsia_async as fasync;
use fuchsia_zircon::{self as zx, prelude::HandleBased};
use futures::channel::mpsc;
use futures::{TryFutureExt, TryStreamExt};
use log::error;
use net_types::ip::{AddrSubnet, AddrSubnetEither, IpAddr, IpVersion, Subnet, SubnetEither};
use std::sync::{Arc, Mutex};
pub struct SocketControlWorker {
events: psocket::ControlRequestStream,
inner: Arc<Mutex<SocketControlWorkerInner>>,
}
#[derive(Debug)]
pub struct SocketControlWorkerInner {
local_socket: zx::Socket,
peer_socket: zx::Socket,
info: SocketControlInfo,
}
#[derive(Debug)]
pub enum SocketControlInfo {
Unbound(UnboundSocket),
Bound(SocketWorker),
}
#[derive(Debug)]
pub struct UnboundSocket {
net_proto: IpVersion, // TODO(wesleyac): Pull into type?
trans_proto: TransProto, // TODO(wesleyac): Pull into type?
nonblock: bool,
}
#[derive(Debug)]
pub enum TransProto {
UDP,
TCP,
}
impl SocketControlWorker {
pub fn new(
events: psocket::ControlRequestStream,
net_proto: IpVersion,
trans_proto: TransProto,
nonblock: bool,
) -> Result<Self, ()> {
let sockopt = match trans_proto {
TransProto::UDP => zx::SocketOpts::DATAGRAM,
TransProto::TCP => zx::SocketOpts::STREAM,
};
let (local_socket, peer_socket) = zx::Socket::create(sockopt).map_err(|_| ())?;
Ok(Self {
events,
inner: Arc::new(Mutex::new(SocketControlWorkerInner {
local_socket,
peer_socket,
info: SocketControlInfo::Unbound(UnboundSocket {
net_proto,
trans_proto,
nonblock,
}),
})),
})
}
pub fn spawn(mut self, sender: mpsc::UnboundedSender<Event>) {
fasync::spawn_local(
async move {
while let Some(evt) = await!(self.events.try_next())? {
sender.unbounded_send(Event::FidlSocketControlEvent((
Arc::clone(&self.inner),
evt,
)));
}
Ok(())
}
.unwrap_or_else(|e: Error| error!("{:?}", e)),
);
}
}
impl SocketControlWorkerInner {
pub fn handle_request(&mut self, event_loop: &mut EventLoop, req: psocket::ControlRequest) {
match req {
psocket::ControlRequest::Clone { .. } => {}
psocket::ControlRequest::Close { .. } => {}
psocket::ControlRequest::Describe { responder } => {
let peer = self.peer_socket.duplicate_handle(zx::Rights::SAME_RIGHTS);
if let Ok(peer) = peer {
let mut info =
fidl_fuchsia_io::NodeInfo::Socket(fidl_fuchsia_io::Socket { socket: peer });
responder.send(&mut info);
}
// If the call to duplicate_handle fails, we have no choice but to drop the
// responder and close the channel, since Describe must be infallible.
}
psocket::ControlRequest::Sync { .. } => {}
psocket::ControlRequest::GetAttr { .. } => {}
psocket::ControlRequest::SetAttr { .. } => {}
psocket::ControlRequest::Ioctl { .. } => {}
psocket::ControlRequest::Bind { .. } => {}
psocket::ControlRequest::Connect { .. } => {}
psocket::ControlRequest::Listen { .. } => {}
psocket::ControlRequest::Accept { .. } => {}
psocket::ControlRequest::GetSockName { .. } => {}
psocket::ControlRequest::GetPeerName { .. } => {}
psocket::ControlRequest::SetSockOpt { .. } => {}
psocket::ControlRequest::GetSockOpt { .. } => {}
psocket::ControlRequest::IoctlPosix { .. } => {}
}
}
}
#[derive(Debug)]
pub struct SocketWorker {
address: IpAddr,
port: u16,
nic: BindingId,
trans_proto: TransProto,
}
impl SocketWorker {
pub fn spawn(mut self) {
unimplemented!()
}
}