usecrate::PlatformHandle; usecrate::PlatformHandleType; usecrate::INVALID_HANDLE_VALUE; #[cfg(target_os = "linux")] use audio_thread_priority::RtPriorityThreadInfo; use cubeb::ffi; use serde_derive::Deserialize; use serde_derive::Serialize; use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_int, c_uint}; use std::ptr;
// Client -> Server messages. // TODO: Callbacks should be different messages types so // ServerConn::process_msg doesn't have a catch-all case. #[derive(Debug, Serialize, Deserialize)] pubenum ServerMessage {
ClientConnect(u32),
ClientDisconnect,
// Represents a platform handle in various transitional states during serialization and remoting. // The process of serializing and remoting handles and the ownership during various states differs // between Windows and Unix. SerializableHandle changes during IPC as follows: // // 1. Created in the initial state `Owned`, with a valid `target_pid`. // 2. Ownership is transferred out for processing during IPC send, becoming `Empty` temporarily. // See `AssociateHandleForMessage::take_handle`. // - Windows: DuplicateHandle transfers the handle to the remote process. // This produces a new handle value in the local process representing the remote handle. // This value must be sent to the remote, so `AssociateHandleForMessage::set_remote_handle` // is used to transform the handle into a `SerializableValue`. // - Unix: sendmsg transfers the handle to the remote process. The handle is left `Empty`. // (Note: this occurs later, when the serialized message buffer is sent) // 3. Message containing `SerializableValue` or `Empty` (depending on handle processing in step 2) // is serialized and sent via IPC. // 4. Message received and deserialized in target process. // - Windows: `AssociateHandleForMessage::set_local_handle converts the received `SerializableValue` into `Owned`, ready for use. // - Unix: Handle (with a new value in the target process) is received out-of-band via `recvmsg` // and converted to `Owned` via `AssociateHandleForMessage::set_local_handle`. #[derive(Debug)] pubenum SerializableHandle { // Owned handle, with optional target_pid on sending side.
Owned(PlatformHandle, Option<u32>), // Transitional IPC states:
SerializableValue(PlatformHandleType), // Windows
Empty, // Unix
}
// PlatformHandle is non-Send and contains a pointer (HANDLE) on Windows. #[allow(clippy::non_send_fields_in_send_ty)] unsafeimpl Send for SerializableHandle {}
// Called on the receiving side to take ownership of the handle. pubfn take_handle(&mutself) -> PlatformHandle { match std::mem::replace(self, SerializableHandle::Empty) {
SerializableHandle::Owned(handle, target_pid) => {
assert!(target_pid.is_none());
handle
}
_ => panic!("take_handle called in invalid state"),
}
}
// Called on the sending side to take ownership of the handle for // handling platform-specific remoting. fn take_handle_for_send(&mutself) -> RemoteHandle { match std::mem::replace(self, SerializableHandle::Empty) {
SerializableHandle::Owned(handle, target_pid) => unsafe {
RemoteHandle::new(
handle.into_raw(),
target_pid.expect("target process required"),
)
},
_ => panic!("take_handle_for_send called in invalid state"),
}
}
fn get_serializable_value(&self) -> PlatformHandleType { match *self {
SerializableHandle::SerializableValue(handle) => handle,
SerializableHandle::Empty => INVALID_HANDLE_VALUE,
_ => panic!("get_remote_handle called in invalid state"),
}
}
}
// Raw handle values are serialized as i64. Additional handling external to (de)serialization is required during IPC // send/receive to convert these raw values into valid handles. impl serde::Serialize for SerializableHandle { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
S: serde::Serializer,
{ let handle = self.get_serializable_value();
serializer.serialize_i64(handle as i64)
}
}
impl<'de> serde::Deserialize<'de> for SerializableHandle { fn deserialize<D>(deserializer: D) -> Result<SerializableHandle, D::Error> where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_i64(SerializableHandleVisitor)
}
}
struct SerializableHandleVisitor; impl serde::de::Visitor<'_> for SerializableHandleVisitor { type Value = SerializableHandle;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("an integer between -2^63 and 2^63")
}
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> where
E: serde::de::Error,
{
Ok(SerializableHandle::new_serializable_value(
value as PlatformHandleType,
))
}
}
// Represents a PlatformHandle in-flight between processes. // On Unix platforms, this is just a plain owned Handle, closed on drop. // On Windows, `RemoteHandle` also retains ownership of the `target_handle` // in the `target` process. Once the handle has been successfully sent // to the remote, the sender should call `mark_sent()` to relinquish // ownership of `target_handle` in the remote. #[derive(Debug)] pubstruct RemoteHandle { pub(crate) handle: PlatformHandleType, #[cfg(windows)] pub(crate) target: u32, #[cfg(windows)] pub(crate) target_handle: Option<PlatformHandleType>,
}
#[cfg(unix)] #[allow(clippy::missing_safety_doc)] pubunsafefn take(self) -> PlatformHandleType { let h = self.handle;
std::mem::forget(self);
h
}
}
impl Drop for RemoteHandle { fn drop(&mutself) { unsafe { crate::close_platform_handle(self.handle);
} #[cfg(windows)] unsafe { iflet Some(target_handle) = self.target_handle { iflet Err(e) = crate::close_target_handle(target_handle, self.target) {
trace!("RemoteHandle failed to close target handle: {:?}", e);
}
}
}
}
}
unsafeimpl Send for RemoteHandle {}
pubtrait AssociateHandleForMessage { // True if this item has an associated handle attached for remoting. fn has_associated_handle(&self) -> bool { false
}
// Take ownership of the associated handle, leaving the item's // associated handle empty. fn take_handle(&mutself) -> RemoteHandle {
panic!("take_handle called on item without associated handle");
}
#[allow(clippy::missing_safety_doc)] // Replace an empty associated handle with a non-owning serializable value // indicating the value of the handle in the remote process. #[cfg(windows)] unsafefn set_remote_handle(&mutself, _: PlatformHandleType) {
panic!("set_remote_handle called on item without associated handle");
}
#[allow(clippy::missing_safety_doc)] // Replace a serialized associated handle value with an owned local handle. #[cfg(windows)] unsafefn set_local_handle(&mutself) {
panic!("set_local_handle called on item without associated handle");
}
#[allow(clippy::missing_safety_doc)] // Replace an empty associated handle with an owned local handle. #[cfg(unix)] unsafefn set_local_handle(&mutself, _: PlatformHandleType) {
panic!("set_local_handle called on item without associated handle");
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.