blob: fee643f8b5666d805ca1e4a70de8fe0223cd99a6 [file] [log] [blame]
Andrew Walbran1072cc02022-05-23 14:47:58 +00001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::errors::GetServiceError;
16use android_system_virtualizationservice::{
17 aidl::android::system::virtualizationservice::IVirtualMachine::IVirtualMachine,
18};
19use binder::unstable_api::{new_spibinder, AIBinder};
20use log::warn;
21use std::os::{raw, unix::io::IntoRawFd};
22
23pub struct VsockFactory<'a> {
24 vm: &'a dyn IVirtualMachine,
25 port: u32,
26}
27
28impl<'a> VsockFactory<'a> {
29 pub fn new(vm: &'a dyn IVirtualMachine, port: u32) -> Self {
30 Self { vm, port }
31 }
32
33 pub fn connect_rpc_client(&mut self) -> Result<binder::SpIBinder, GetServiceError> {
34 let param = self.as_void_ptr();
35
36 unsafe {
37 // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and
38 // the ownership can be safely taken by new_spibinder.
39 // RpcPreconnectedClient does not take ownership of param, only passing it to
40 // request_fd.
41 let binder =
42 binder_rpc_unstable_bindgen::RpcPreconnectedClient(Some(Self::request_fd), param)
43 as *mut AIBinder;
44 new_spibinder(binder).ok_or(GetServiceError::ConnectionFailed)
45 }
46 }
47
48 fn as_void_ptr(&mut self) -> *mut raw::c_void {
49 self as *mut _ as *mut raw::c_void
50 }
51
52 fn new_vsock_fd(&self) -> i32 {
53 match self.vm.connectVsock(self.port as i32) {
54 Ok(vsock) => {
55 // Ownership of the fd is transferred to binder
56 vsock.into_raw_fd()
57 }
58 Err(e) => {
59 warn!("Vsock connection failed: {}", e);
60 -1
61 }
62 }
63 }
64
65 unsafe extern "C" fn request_fd(param: *mut raw::c_void) -> raw::c_int {
66 // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
67 // VsockFactory, with param taking the value returned by as_void_ptr (so a properly aligned
68 // non-null pointer to an initialized instance).
69 let vsock_factory = param as *mut Self;
70 vsock_factory.as_ref().unwrap().new_vsock_fd()
71 }
72}