// Copyright 2018 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. mod msg_on_socket; use std::io::Result; use std::marker::PhantomData; use std::os::unix::io::{AsRawFd, RawFd}; use sys_util::{handle_eintr, net::UnixSeqpacket, Error as SysError, ScmSocket}; pub use crate::msg_on_socket::*; pub use msg_on_socket_derive::*; /// Create a pair of socket. Request is send in one direction while response is in the other /// direction. pub fn pair( ) -> Result<(MsgSocket, MsgSocket)> { let (sock1, sock2) = UnixSeqpacket::pair()?; let requester = MsgSocket { sock: sock1, _i: PhantomData, _o: PhantomData, }; let responder = MsgSocket { sock: sock2, _i: PhantomData, _o: PhantomData, }; Ok((requester, responder)) } /// Bidirection sock that support both send and recv. pub struct MsgSocket { sock: UnixSeqpacket, _i: PhantomData, _o: PhantomData, } impl MsgSocket { // Create a new MsgSocket. pub fn new(s: UnixSeqpacket) -> MsgSocket { MsgSocket { sock: s, _i: PhantomData, _o: PhantomData, } } } /// One direction socket that only supports sending. pub struct Sender { sock: UnixSeqpacket, _m: PhantomData, } impl Sender { /// Create a new sender sock. pub fn new(s: UnixSeqpacket) -> Sender { Sender { sock: s, _m: PhantomData, } } } /// One direction socket that only supports receiving. pub struct Receiver { sock: UnixSeqpacket, _m: PhantomData, } impl Receiver { /// Create a new receiver sock. pub fn new(s: UnixSeqpacket) -> Receiver { Receiver { sock: s, _m: PhantomData, } } } impl AsRef for MsgSocket { fn as_ref(&self) -> &UnixSeqpacket { &self.sock } } impl AsRawFd for MsgSocket { fn as_raw_fd(&self) -> RawFd { self.sock.as_raw_fd() } } impl AsRef for Sender { fn as_ref(&self) -> &UnixSeqpacket { &self.sock } } impl AsRawFd for Sender { fn as_raw_fd(&self) -> RawFd { self.sock.as_raw_fd() } } impl AsRef for Receiver { fn as_ref(&self) -> &UnixSeqpacket { &self.sock } } impl AsRawFd for Receiver { fn as_raw_fd(&self) -> RawFd { self.sock.as_raw_fd() } } /// Types that could send a message. pub trait MsgSender: AsRef { type M: MsgOnSocket; fn send(&self, msg: &Self::M) -> MsgResult<()> { let msg_size = Self::M::msg_size(); let fd_size = Self::M::max_fd_count(); let mut msg_buffer: Vec = vec![0; msg_size]; let mut fd_buffer: Vec = vec![0; fd_size]; let fd_size = msg.write_to_buffer(&mut msg_buffer, &mut fd_buffer)?; let sock: &UnixSeqpacket = self.as_ref(); if fd_size == 0 { handle_eintr!(sock.send(&msg_buffer)) .map_err(|e| MsgError::Send(SysError::new(e.raw_os_error().unwrap_or(0))))?; } else { sock.send_with_fds(&msg_buffer[..], &fd_buffer[0..fd_size]) .map_err(MsgError::Send)?; } Ok(()) } } /// Types that could receive a message. pub trait MsgReceiver: AsRef { type M: MsgOnSocket; fn recv(&self) -> MsgResult { let msg_size = Self::M::msg_size(); let fd_size = Self::M::max_fd_count(); let mut msg_buffer: Vec = vec![0; msg_size]; let mut fd_buffer: Vec = vec![0; fd_size]; let sock: &UnixSeqpacket = self.as_ref(); let (recv_msg_size, recv_fd_size) = { if fd_size == 0 { let size = sock .recv(&mut msg_buffer) .map_err(|e| MsgError::Recv(SysError::new(e.raw_os_error().unwrap_or(0))))?; (size, 0) } else { sock.recv_with_fds(&mut msg_buffer, &mut fd_buffer) .map_err(MsgError::Recv)? } }; if msg_size != recv_msg_size { return Err(MsgError::BadRecvSize { expected: msg_size, actual: recv_msg_size, }); } // Safe because fd buffer is read from socket. let (v, read_fd_size) = unsafe { Self::M::read_from_buffer(&msg_buffer[0..recv_msg_size], &fd_buffer[0..recv_fd_size])? }; if recv_fd_size != read_fd_size { return Err(MsgError::NotExpectFd); } Ok(v) } } impl MsgSender for MsgSocket { type M = I; } impl MsgReceiver for MsgSocket { type M = O; } impl MsgSender for Sender { type M = I; } impl MsgReceiver for Receiver { type M = O; }