• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use pinweaver_storage::{
2     current::{StorageInterface, StorageRequest, StorageResponse},
3     util::{DeserializeExact, ForwardTipcSerialize},
4 };
5 use std::sync::{Arc, Mutex, MutexGuard};
6 use tipc::{Handle, TipcError, UnbufferedService};
7 use trusty_std::alloc::FallibleVec;
8 use trusty_sys::Error;
9 
10 type Response = DeserializeExact<StorageResponse>;
11 const MAX_MESSAGE_SIZE: usize = <Response as tipc::Deserialize>::MAX_SERIALIZED_SIZE;
12 
13 /// The service that initializes the given `StorageClient` upon connection.
14 ///
15 /// This is a tipc server: the storage daemon running in Android connects to
16 /// this service, acting as a tipc client. The connection remains open while
17 /// the main service sends commands to the storage daemon through the
18 /// `StorageClient`.
19 pub(crate) struct StorageClientService {
20     client: Arc<StorageClient>,
21 }
22 
23 impl StorageClientService {
new(client: Arc<StorageClient>) -> Self24     pub fn new(client: Arc<StorageClient>) -> Self {
25         Self { client }
26     }
27 }
28 
29 impl UnbufferedService for StorageClientService {
30     type Connection = ();
31 
32     /// Stores the connection handle for later use.
on_connect( &self, _port: &tipc::PortCfg, handle: &tipc::Handle, _peer: &tipc::Uuid, ) -> tipc::Result<tipc::ConnectResult<Self::Connection>>33     fn on_connect(
34         &self,
35         _port: &tipc::PortCfg,
36         handle: &tipc::Handle,
37         _peer: &tipc::Uuid,
38     ) -> tipc::Result<tipc::ConnectResult<Self::Connection>> {
39         self.client.set_server_handle(handle)?;
40         Ok(tipc::ConnectResult::Accept(()))
41     }
42 
43     /// Not used, as the storage daemon acts as a server.
on_message( &self, _connection: &Self::Connection, _handle: &tipc::Handle, _buffer: &mut [u8], ) -> tipc::Result<tipc::MessageResult>44     fn on_message(
45         &self,
46         _connection: &Self::Connection,
47         _handle: &tipc::Handle,
48         _buffer: &mut [u8],
49     ) -> tipc::Result<tipc::MessageResult> {
50         Ok(tipc::MessageResult::MaintainConnection)
51     }
52 
on_disconnect(&self, _connection: &Self::Connection)53     fn on_disconnect(&self, _connection: &Self::Connection) {
54         log::error!("Storage client disconnected");
55         self.client.clear_server_handle();
56     }
57 }
58 
59 #[derive(Default)]
60 pub(crate) struct StorageClient {
61     /// Initialized by the [`StorageClientService`].
62     server_handle: Mutex<Option<Handle>>,
63 }
64 
65 impl StorageClient {
66     /// Locks the mutex or returns an error.
lock(&self) -> tipc::Result<MutexGuard<'_, Option<Handle>>>67     fn lock(&self) -> tipc::Result<MutexGuard<'_, Option<Handle>>> {
68         self.server_handle.lock().map_err(|_| TipcError::SystemError(Error::BadState))
69     }
70 
71     /// Sets the server handle for this storage client.
72     ///
73     /// Clones the handle to send messages, if a storage daemon hasn't already connected.
set_server_handle(&self, handle: &Handle) -> tipc::Result<()>74     pub fn set_server_handle(&self, handle: &Handle) -> tipc::Result<()> {
75         match &mut *self.lock()? {
76             Some(_) => Err(TipcError::SystemError(Error::AlreadyExists)),
77             server_handle @ None => {
78                 *server_handle = Some(handle.try_clone()?);
79                 Ok(())
80             }
81         }
82     }
83 
84     /// Clears the current server handle for this storage client.
85     ///
86     /// Ignores whether there is currently a handle set.
clear_server_handle(&self)87     pub fn clear_server_handle(&self) {
88         if let Ok(mut handle) = self.lock() {
89             *handle = None;
90         }
91     }
92 }
93 
94 impl StorageInterface for StorageClient {
95     type Error = tipc::TipcError;
96 
request(&self, request: &StorageRequest) -> tipc::Result<StorageResponse>97     fn request(&self, request: &StorageRequest) -> tipc::Result<StorageResponse> {
98         let guard = self.lock()?;
99         let handle = guard.as_ref().ok_or(TipcError::SystemError(Error::NotReady))?;
100         handle.send(&ForwardTipcSerialize(request))?;
101         let mut buf: Vec<u8> = FallibleVec::try_with_capacity(MAX_MESSAGE_SIZE)?;
102         buf.resize(MAX_MESSAGE_SIZE, 0);
103         let response: Response = handle.recv(&mut buf)?;
104         Ok(response.0)
105     }
106 }
107