mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-06 02:25:23 +00:00
msg_socket: removed
Now that msg_socket is no longer used anywhere, remove the code so that nobody else starts to use it. Use serde and tube instead. TEST=run_tests BUG=b:176847362 Change-Id: Ibe68b47b444830a921d6ba98798dfc163447d31b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2722915 Tested-by: kokoro <noreply+kokoro@google.com> Auto-Submit: Zach Reizner <zachr@chromium.org> Commit-Queue: Zach Reizner <zachr@chromium.org> Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
This commit is contained in:
parent
d49bcdb081
commit
58509986c2
12 changed files with 0 additions and 2223 deletions
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "msg_socket"
|
||||
version = "0.1.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cros_async = { path = "../cros_async" }
|
||||
data_model = { path = "../data_model" }
|
||||
futures = "*"
|
||||
libc = "*"
|
||||
msg_on_socket_derive = { path = "msg_on_socket_derive" }
|
||||
base = { path = "../base" }
|
||||
sync = { path = "../sync" }
|
|
@ -1,15 +0,0 @@
|
|||
[package]
|
||||
name = "msg_on_socket_derive"
|
||||
version = "0.1.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
base = "*"
|
||||
proc-macro2 = "^1"
|
||||
quote = "^1"
|
||||
syn = "^1"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
path = "msg_on_socket_derive.rs"
|
|
@ -1,911 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#![recursion_limit = "256"]
|
||||
extern crate proc_macro;
|
||||
|
||||
use std::vec::Vec;
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, Ident, Index, Member, Meta,
|
||||
NestedMeta, Type,
|
||||
};
|
||||
|
||||
/// The function that derives the recursive implementation for struct or enum.
|
||||
#[proc_macro_derive(MsgOnSocket, attributes(msg_on_socket))]
|
||||
pub fn msg_on_socket_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let impl_for_input = socket_msg_impl(input);
|
||||
impl_for_input.into()
|
||||
}
|
||||
|
||||
fn socket_msg_impl(input: DeriveInput) -> TokenStream {
|
||||
if !input.generics.params.is_empty() {
|
||||
return quote! {
|
||||
compile_error!("derive(SocketMsg) does not support generic parameters");
|
||||
};
|
||||
}
|
||||
match input.data {
|
||||
Data::Struct(ds) => {
|
||||
if is_named_struct(&ds) {
|
||||
impl_for_named_struct(input.ident, ds)
|
||||
} else {
|
||||
impl_for_tuple_struct(input.ident, ds)
|
||||
}
|
||||
}
|
||||
Data::Enum(de) => impl_for_enum(input.ident, de),
|
||||
_ => quote! {
|
||||
compile_error!("derive(SocketMsg) only support struct and enum");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn is_named_struct(ds: &DataStruct) -> bool {
|
||||
matches!(&ds.fields, Fields::Named(_f))
|
||||
}
|
||||
|
||||
/************************** Named Struct Impls ********************************************/
|
||||
|
||||
struct StructField {
|
||||
member: Member,
|
||||
ty: Type,
|
||||
skipped: bool,
|
||||
}
|
||||
|
||||
fn impl_for_named_struct(name: Ident, ds: DataStruct) -> TokenStream {
|
||||
let fields = get_struct_fields(ds);
|
||||
let uses_fd_impl = define_uses_fd_for_struct(&fields);
|
||||
let buffer_sizes_impls = define_buffer_size_for_struct(&fields);
|
||||
|
||||
let read_buffer = define_read_buffer_for_struct(&name, &fields);
|
||||
let write_buffer = define_write_buffer_for_struct(&name, &fields);
|
||||
quote! {
|
||||
impl msg_socket::MsgOnSocket for #name {
|
||||
#uses_fd_impl
|
||||
#buffer_sizes_impls
|
||||
#read_buffer
|
||||
#write_buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flatten struct fields.
|
||||
fn get_struct_fields(ds: DataStruct) -> Vec<StructField> {
|
||||
let fields = match ds.fields {
|
||||
Fields::Named(fields_named) => fields_named.named,
|
||||
_ => {
|
||||
panic!("Struct must have named fields");
|
||||
}
|
||||
};
|
||||
let mut vec = Vec::new();
|
||||
for field in fields {
|
||||
let member = match field.ident {
|
||||
Some(ident) => Member::Named(ident),
|
||||
None => panic!("Unknown Error."),
|
||||
};
|
||||
let ty = field.ty;
|
||||
let mut skipped = false;
|
||||
for attr in field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path.is_ident("msg_on_socket"))
|
||||
{
|
||||
match attr.parse_meta().unwrap() {
|
||||
Meta::List(meta) => {
|
||||
for nested in meta.nested {
|
||||
match nested {
|
||||
NestedMeta::Meta(Meta::Path(ref meta_path))
|
||||
if meta_path.is_ident("skip") =>
|
||||
{
|
||||
skipped = true;
|
||||
}
|
||||
_ => panic!("unrecognized attribute meta `{}`", quote! { #nested }),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("unrecognized attribute `{}`", quote! { #attr }),
|
||||
}
|
||||
}
|
||||
vec.push(StructField {
|
||||
member,
|
||||
ty,
|
||||
skipped,
|
||||
});
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
fn define_uses_fd_for_struct(fields: &[StructField]) -> TokenStream {
|
||||
let field_types: Vec<_> = fields
|
||||
.iter()
|
||||
.filter(|f| !f.skipped)
|
||||
.map(|f| &f.ty)
|
||||
.collect();
|
||||
|
||||
if field_types.is_empty() {
|
||||
return quote!();
|
||||
}
|
||||
|
||||
quote! {
|
||||
fn uses_descriptor() -> bool {
|
||||
#(<#field_types>::uses_descriptor())||*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_buffer_size_for_struct(fields: &[StructField]) -> TokenStream {
|
||||
let (msg_size, fd_count) = get_fields_buffer_size_sum(fields);
|
||||
quote! {
|
||||
fn msg_size(&self) -> usize {
|
||||
#msg_size
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
#fd_count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_read_buffer_for_struct(_name: &Ident, fields: &[StructField]) -> TokenStream {
|
||||
let mut read_fields = Vec::new();
|
||||
let mut init_fields = Vec::new();
|
||||
for field in fields {
|
||||
let ident = match &field.member {
|
||||
Member::Named(ident) => ident,
|
||||
Member::Unnamed(_) => unreachable!(),
|
||||
};
|
||||
let name = ident.clone();
|
||||
if field.skipped {
|
||||
let ty = &field.ty;
|
||||
init_fields.push(quote! {
|
||||
#name: <#ty>::default()
|
||||
});
|
||||
continue;
|
||||
}
|
||||
let read_field = read_from_buffer_and_move_offset(&ident, &field.ty);
|
||||
read_fields.push(read_field);
|
||||
init_fields.push(quote!(#name));
|
||||
}
|
||||
quote! {
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#read_fields)*
|
||||
Ok((
|
||||
Self {
|
||||
#(#init_fields),*
|
||||
},
|
||||
__fd_offset
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_write_buffer_for_struct(_name: &Ident, fields: &[StructField]) -> TokenStream {
|
||||
let mut write_fields = Vec::new();
|
||||
for field in fields {
|
||||
if field.skipped {
|
||||
continue;
|
||||
}
|
||||
let ident = match &field.member {
|
||||
Member::Named(ident) => ident,
|
||||
Member::Unnamed(_) => unreachable!(),
|
||||
};
|
||||
let write_field = write_to_buffer_and_move_offset(&ident);
|
||||
write_fields.push(write_field);
|
||||
}
|
||||
quote! {
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#write_fields)*
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************** Enum Impls ********************************************/
|
||||
fn impl_for_enum(name: Ident, de: DataEnum) -> TokenStream {
|
||||
let uses_fd_impl = define_uses_fd_for_enum(&de);
|
||||
let buffer_sizes_impls = define_buffer_size_for_enum(&name, &de);
|
||||
let read_buffer = define_read_buffer_for_enum(&name, &de);
|
||||
let write_buffer = define_write_buffer_for_enum(&name, &de);
|
||||
quote! {
|
||||
impl msg_socket::MsgOnSocket for #name {
|
||||
#uses_fd_impl
|
||||
#buffer_sizes_impls
|
||||
#read_buffer
|
||||
#write_buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_uses_fd_for_enum(de: &DataEnum) -> TokenStream {
|
||||
let mut variant_field_types = Vec::new();
|
||||
for variant in &de.variants {
|
||||
for variant_field_ty in variant.fields.iter().map(|f| &f.ty) {
|
||||
variant_field_types.push(variant_field_ty);
|
||||
}
|
||||
}
|
||||
|
||||
if variant_field_types.is_empty() {
|
||||
return quote!();
|
||||
}
|
||||
|
||||
quote! {
|
||||
fn uses_descriptor() -> bool {
|
||||
#(<#variant_field_types>::uses_descriptor())||*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_buffer_size_for_enum(name: &Ident, de: &DataEnum) -> TokenStream {
|
||||
let mut msg_size_match_variants = Vec::new();
|
||||
let mut fd_count_match_variants = Vec::new();
|
||||
|
||||
for variant in &de.variants {
|
||||
let variant_name = &variant.ident;
|
||||
match &variant.fields {
|
||||
Fields::Named(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
for field in &fields.named {
|
||||
tmp_names.push(field.ident.clone().unwrap());
|
||||
}
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name { #(#tmp_names),* } => #(#tmp_names.msg_size())+*,
|
||||
};
|
||||
msg_size_match_variants.push(v);
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name { #(#tmp_names),* } => #(#tmp_names.descriptor_count())+*,
|
||||
};
|
||||
fd_count_match_variants.push(v);
|
||||
}
|
||||
Fields::Unnamed(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
for idx in 0..fields.unnamed.len() {
|
||||
let tmp_name = format!("enum_field{}", idx);
|
||||
let tmp_name = Ident::new(&tmp_name, Span::call_site());
|
||||
tmp_names.push(tmp_name.clone());
|
||||
}
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name(#(#tmp_names),*) => #(#tmp_names.msg_size())+*,
|
||||
};
|
||||
msg_size_match_variants.push(v);
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name(#(#tmp_names),*) => #(#tmp_names.descriptor_count())+*,
|
||||
};
|
||||
fd_count_match_variants.push(v);
|
||||
}
|
||||
Fields::Unit => {
|
||||
let v = quote! {
|
||||
#name::#variant_name => 0,
|
||||
};
|
||||
msg_size_match_variants.push(v.clone());
|
||||
fd_count_match_variants.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
fn msg_size(&self) -> usize {
|
||||
1 + match self {
|
||||
#(#msg_size_match_variants)*
|
||||
}
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
match self {
|
||||
#(#fd_count_match_variants)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_read_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream {
|
||||
let mut match_variants = Vec::new();
|
||||
let de = de.clone();
|
||||
for (idx, variant) in de.variants.iter().enumerate() {
|
||||
let idx = idx as u8;
|
||||
let variant_name = &variant.ident;
|
||||
match &variant.fields {
|
||||
Fields::Named(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
let mut read_tmps = Vec::new();
|
||||
for f in &fields.named {
|
||||
tmp_names.push(f.ident.clone());
|
||||
let read_tmp =
|
||||
read_from_buffer_and_move_offset(f.ident.as_ref().unwrap(), &f.ty);
|
||||
read_tmps.push(read_tmp);
|
||||
}
|
||||
let v = quote! {
|
||||
#idx => {
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#read_tmps)*
|
||||
Ok((#name::#variant_name { #(#tmp_names),* }, __fd_offset))
|
||||
}
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
Fields::Unnamed(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
let mut read_tmps = Vec::new();
|
||||
for (idx, field) in fields.unnamed.iter().enumerate() {
|
||||
let tmp_name = format_ident!("enum_field{}", idx);
|
||||
tmp_names.push(tmp_name.clone());
|
||||
let read_tmp = read_from_buffer_and_move_offset(&tmp_name, &field.ty);
|
||||
read_tmps.push(read_tmp);
|
||||
}
|
||||
|
||||
let v = quote! {
|
||||
#idx => {
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#read_tmps)*
|
||||
Ok((#name::#variant_name( #(#tmp_names),*), __fd_offset))
|
||||
}
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
Fields::Unit => {
|
||||
let v = quote! {
|
||||
#idx => Ok((#name::#variant_name, 0)),
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
quote! {
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let v = buffer.get(0).ok_or(msg_socket::MsgError::WrongMsgBufferSize)?;
|
||||
match v {
|
||||
#(#match_variants)*
|
||||
_ => Err(msg_socket::MsgError::InvalidType),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_write_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream {
|
||||
let mut match_variants = Vec::new();
|
||||
let de = de.clone();
|
||||
for (idx, variant) in de.variants.iter().enumerate() {
|
||||
let idx = idx as u8;
|
||||
let variant_name = &variant.ident;
|
||||
match &variant.fields {
|
||||
Fields::Named(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
let mut write_tmps = Vec::new();
|
||||
for f in &fields.named {
|
||||
tmp_names.push(f.ident.clone().unwrap());
|
||||
let write_tmp =
|
||||
enum_write_to_buffer_and_move_offset(&f.ident.as_ref().unwrap());
|
||||
write_tmps.push(write_tmp);
|
||||
}
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name { #(#tmp_names),* } => {
|
||||
buffer[0] = #idx;
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#write_tmps)*
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
Fields::Unnamed(fields) => {
|
||||
let mut tmp_names = Vec::new();
|
||||
let mut write_tmps = Vec::new();
|
||||
for idx in 0..fields.unnamed.len() {
|
||||
let tmp_name = format_ident!("enum_field{}", idx);
|
||||
tmp_names.push(tmp_name.clone());
|
||||
let write_tmp = enum_write_to_buffer_and_move_offset(&tmp_name);
|
||||
write_tmps.push(write_tmp);
|
||||
}
|
||||
|
||||
let v = quote! {
|
||||
#name::#variant_name(#(#tmp_names),*) => {
|
||||
buffer[0] = #idx;
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#write_tmps)*
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
Fields::Unit => {
|
||||
let v = quote! {
|
||||
#name::#variant_name => {
|
||||
buffer[0] = #idx;
|
||||
Ok(0)
|
||||
}
|
||||
};
|
||||
match_variants.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
if buffer.is_empty() {
|
||||
return Err(msg_socket::MsgError::WrongMsgBufferSize)
|
||||
}
|
||||
match self {
|
||||
#(#match_variants)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_write_to_buffer_and_move_offset(name: &Ident) -> TokenStream {
|
||||
quote! {
|
||||
let o = #name.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += #name.msg_size();
|
||||
__fd_offset += o;
|
||||
}
|
||||
}
|
||||
|
||||
/************************** Tuple Impls ********************************************/
|
||||
fn impl_for_tuple_struct(name: Ident, ds: DataStruct) -> TokenStream {
|
||||
let fields = get_tuple_fields(ds);
|
||||
|
||||
let uses_fd_impl = define_uses_fd_for_tuples(&fields);
|
||||
let buffer_sizes_impls = define_buffer_size_for_struct(&fields);
|
||||
let read_buffer = define_read_buffer_for_tuples(&name, &fields);
|
||||
let write_buffer = define_write_buffer_for_tuples(&name, &fields);
|
||||
quote! {
|
||||
impl msg_socket::MsgOnSocket for #name {
|
||||
#uses_fd_impl
|
||||
#buffer_sizes_impls
|
||||
#read_buffer
|
||||
#write_buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_tuple_fields(ds: DataStruct) -> Vec<StructField> {
|
||||
let mut field_idents = Vec::new();
|
||||
let fields = match ds.fields {
|
||||
Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed,
|
||||
_ => {
|
||||
panic!("Tuple struct must have unnamed fields.");
|
||||
}
|
||||
};
|
||||
for (idx, field) in fields.iter().enumerate() {
|
||||
let member = Member::Unnamed(Index::from(idx));
|
||||
let ty = field.ty.clone();
|
||||
field_idents.push(StructField {
|
||||
member,
|
||||
ty,
|
||||
skipped: false,
|
||||
});
|
||||
}
|
||||
field_idents
|
||||
}
|
||||
|
||||
fn define_uses_fd_for_tuples(fields: &[StructField]) -> TokenStream {
|
||||
if fields.is_empty() {
|
||||
return quote!();
|
||||
}
|
||||
|
||||
let field_types = fields.iter().map(|f| &f.ty);
|
||||
quote! {
|
||||
fn uses_descriptor() -> bool {
|
||||
#(<#field_types>::uses_descriptor())||*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_read_buffer_for_tuples(name: &Ident, fields: &[StructField]) -> TokenStream {
|
||||
let mut read_fields = Vec::new();
|
||||
let mut init_fields = Vec::new();
|
||||
for (idx, field) in fields.iter().enumerate() {
|
||||
let tmp_name = format!("tuple_tmp{}", idx);
|
||||
let tmp_name = Ident::new(&tmp_name, Span::call_site());
|
||||
let read_field = read_from_buffer_and_move_offset(&tmp_name, &field.ty);
|
||||
read_fields.push(read_field);
|
||||
init_fields.push(quote!(#tmp_name));
|
||||
}
|
||||
|
||||
quote! {
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
#(#read_fields)*
|
||||
Ok((
|
||||
#name (
|
||||
#(#init_fields),*
|
||||
),
|
||||
__fd_offset
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_write_buffer_for_tuples(name: &Ident, fields: &[StructField]) -> TokenStream {
|
||||
let mut write_fields = Vec::new();
|
||||
let mut tmp_names = Vec::new();
|
||||
for idx in 0..fields.len() {
|
||||
let tmp_name = format_ident!("tuple_tmp{}", idx);
|
||||
let write_field = enum_write_to_buffer_and_move_offset(&tmp_name);
|
||||
write_fields.push(write_field);
|
||||
tmp_names.push(tmp_name);
|
||||
}
|
||||
quote! {
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let #name( #(#tmp_names),* ) = self;
|
||||
#(#write_fields)*
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
/************************** Helpers ********************************************/
|
||||
fn get_fields_buffer_size_sum(fields: &[StructField]) -> (TokenStream, TokenStream) {
|
||||
let fields: Vec<_> = fields
|
||||
.iter()
|
||||
.filter(|f| !f.skipped)
|
||||
.map(|f| &f.member)
|
||||
.collect();
|
||||
if !fields.is_empty() {
|
||||
(
|
||||
quote! {
|
||||
#( self.#fields.msg_size() as usize )+*
|
||||
},
|
||||
quote! {
|
||||
#( self.#fields.descriptor_count() as usize )+*
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(quote!(0), quote!(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_from_buffer_and_move_offset(name: &Ident, ty: &Type) -> TokenStream {
|
||||
quote! {
|
||||
let t = <#ty>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let #name = t.0;
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_buffer_and_move_offset(name: &Ident) -> TokenStream {
|
||||
quote! {
|
||||
let o = self.#name.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += self.#name.msg_size();
|
||||
__fd_offset += o;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::socket_msg_impl;
|
||||
use quote::quote;
|
||||
use syn::{parse_quote, DeriveInput};
|
||||
|
||||
#[test]
|
||||
fn end_to_end_struct_test() {
|
||||
let input: DeriveInput = parse_quote! {
|
||||
struct MyMsg {
|
||||
a: u8,
|
||||
b: RawDescriptor,
|
||||
c: u32,
|
||||
}
|
||||
};
|
||||
|
||||
let expected = quote! {
|
||||
impl msg_socket::MsgOnSocket for MyMsg {
|
||||
fn uses_descriptor() -> bool {
|
||||
<u8>::uses_descriptor()
|
||||
|| <RawDescriptor>::uses_descriptor()
|
||||
|| <u32>::uses_descriptor()
|
||||
}
|
||||
fn msg_size(&self) -> usize {
|
||||
self.a.msg_size() as usize
|
||||
+ self.b.msg_size() as usize
|
||||
+ self.c.msg_size() as usize
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
self.a.descriptor_count() as usize
|
||||
+ self.b.descriptor_count() as usize
|
||||
+ self.c.descriptor_count() as usize
|
||||
}
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let a = t.0;
|
||||
let t = <RawDescriptor>::read_from_buffer(
|
||||
&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let b = t.0;
|
||||
let t = <u32>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let c = t.0;
|
||||
Ok((Self { a, b, c }, __fd_offset))
|
||||
}
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let o = self
|
||||
.a
|
||||
.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += self.a.msg_size();
|
||||
__fd_offset += o;
|
||||
let o = self
|
||||
.b
|
||||
.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += self.b.msg_size();
|
||||
__fd_offset += o;
|
||||
let o = self
|
||||
.c
|
||||
.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += self.c.msg_size();
|
||||
__fd_offset += o;
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn end_to_end_tuple_struct_test() {
|
||||
let input: DeriveInput = parse_quote! {
|
||||
struct MyMsg(u8, u32, File);
|
||||
};
|
||||
|
||||
let expected = quote! {
|
||||
impl msg_socket::MsgOnSocket for MyMsg {
|
||||
fn uses_descriptor() -> bool {
|
||||
<u8>::uses_descriptor() || <u32>::uses_descriptor() || <File>::uses_descriptor()
|
||||
}
|
||||
fn msg_size(&self) -> usize {
|
||||
self.0.msg_size() as usize
|
||||
+ self.1.msg_size() as usize + self.2.msg_size() as usize
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
self.0.descriptor_count() as usize
|
||||
+ self.1.descriptor_count() as usize
|
||||
+ self.2.descriptor_count() as usize
|
||||
}
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let tuple_tmp0 = t.0;
|
||||
let t = <u32>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let tuple_tmp1 = t.0;
|
||||
let t = <File>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let tuple_tmp2 = t.0;
|
||||
Ok((MyMsg(tuple_tmp0, tuple_tmp1, tuple_tmp2), __fd_offset))
|
||||
}
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let MyMsg(tuple_tmp0, tuple_tmp1, tuple_tmp2) = self;
|
||||
let o = tuple_tmp0.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += tuple_tmp0.msg_size();
|
||||
__fd_offset += o;
|
||||
let o = tuple_tmp1.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += tuple_tmp1.msg_size();
|
||||
__fd_offset += o;
|
||||
let o = tuple_tmp2.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += tuple_tmp2.msg_size();
|
||||
__fd_offset += o;
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn end_to_end_enum_test() {
|
||||
let input: DeriveInput = parse_quote! {
|
||||
enum MyMsg {
|
||||
A(u8),
|
||||
B,
|
||||
C {
|
||||
f0: u8,
|
||||
f1: RawDescriptor,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let expected = quote! {
|
||||
impl msg_socket::MsgOnSocket for MyMsg {
|
||||
fn uses_descriptor() -> bool {
|
||||
<u8>::uses_descriptor()
|
||||
|| <u8>::uses_descriptor()
|
||||
|| <RawDescriptor>::uses_descriptor()
|
||||
}
|
||||
fn msg_size(&self) -> usize {
|
||||
1 + match self {
|
||||
MyMsg::A(enum_field0) => enum_field0.msg_size(),
|
||||
MyMsg::B => 0,
|
||||
MyMsg::C { f0, f1 } => f0.msg_size() + f1.msg_size(),
|
||||
}
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
match self {
|
||||
MyMsg::A(enum_field0) => enum_field0.descriptor_count(),
|
||||
MyMsg::B => 0,
|
||||
MyMsg::C { f0, f1 } => f0.descriptor_count() + f1.descriptor_count(),
|
||||
}
|
||||
}
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let v = buffer
|
||||
.get(0)
|
||||
.ok_or(msg_socket::MsgError::WrongMsgBufferSize)?;
|
||||
match v {
|
||||
0u8 => {
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let enum_field0 = t.0;
|
||||
Ok((MyMsg::A(enum_field0), __fd_offset))
|
||||
}
|
||||
1u8 => Ok((MyMsg::B, 0)),
|
||||
2u8 => {
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let f0 = t.0;
|
||||
let t = <RawDescriptor>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
|
||||
__offset += t.0.msg_size();
|
||||
__fd_offset += t.1;
|
||||
let f1 = t.0;
|
||||
Ok((MyMsg::C { f0, f1 }, __fd_offset))
|
||||
}
|
||||
_ => Err(msg_socket::MsgError::InvalidType),
|
||||
}
|
||||
}
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
if buffer.is_empty() {
|
||||
return Err(msg_socket::MsgError::WrongMsgBufferSize)
|
||||
}
|
||||
match self {
|
||||
MyMsg::A(enum_field0) => {
|
||||
buffer[0] = 0u8;
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let o = enum_field0
|
||||
.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += enum_field0.msg_size();
|
||||
__fd_offset += o;
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
MyMsg::B => {
|
||||
buffer[0] = 1u8;
|
||||
Ok(0)
|
||||
}
|
||||
MyMsg::C { f0, f1 } => {
|
||||
buffer[0] = 2u8;
|
||||
let mut __offset = 1usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
let o = f0.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += f0.msg_size();
|
||||
__fd_offset += o;
|
||||
let o = f1.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
|
||||
__offset += f1.msg_size();
|
||||
__fd_offset += o;
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn end_to_end_struct_skip_test() {
|
||||
let input: DeriveInput = parse_quote! {
|
||||
struct MyMsg {
|
||||
#[msg_on_socket(skip)]
|
||||
a: u8,
|
||||
}
|
||||
};
|
||||
|
||||
let expected = quote! {
|
||||
impl msg_socket::MsgOnSocket for MyMsg {
|
||||
fn msg_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
0
|
||||
}
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
) -> msg_socket::MsgResult<(Self, usize)> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
Ok((Self { a: <u8>::default() }, __fd_offset))
|
||||
}
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> msg_socket::MsgResult<usize> {
|
||||
let mut __offset = 0usize;
|
||||
let mut __fd_offset = 0usize;
|
||||
Ok(__fd_offset)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
|
||||
}
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
// 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;
|
||||
mod serializable_descriptors;
|
||||
|
||||
use std::io::{IoSlice, Result};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use base::{
|
||||
handle_eintr, net::UnixSeqpacket, AsRawDescriptor, Error as SysError, RawDescriptor, ScmSocket,
|
||||
UnsyncMarker,
|
||||
};
|
||||
use cros_async::{Executor, IoSourceExt};
|
||||
|
||||
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<Request: MsgOnSocket, Response: MsgOnSocket>(
|
||||
) -> Result<(MsgSocket<Request, Response>, MsgSocket<Response, Request>)> {
|
||||
let (sock1, sock2) = UnixSeqpacket::pair()?;
|
||||
let requester = MsgSocket::new(sock1);
|
||||
let responder = MsgSocket::new(sock2);
|
||||
Ok((requester, responder))
|
||||
}
|
||||
|
||||
/// Bidirection sock that support both send and recv.
|
||||
pub struct MsgSocket<I: MsgOnSocket, O: MsgOnSocket> {
|
||||
sock: UnixSeqpacket,
|
||||
_i: PhantomData<I>,
|
||||
_o: PhantomData<O>,
|
||||
_unsync_marker: UnsyncMarker,
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> MsgSocket<I, O> {
|
||||
// Create a new MsgSocket.
|
||||
pub fn new(s: UnixSeqpacket) -> MsgSocket<I, O> {
|
||||
MsgSocket {
|
||||
sock: s,
|
||||
_i: PhantomData,
|
||||
_o: PhantomData,
|
||||
_unsync_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an async receiver that implements `futures::Stream`.
|
||||
pub fn async_receiver(&self, ex: &Executor) -> MsgResult<AsyncReceiver<I, O>> {
|
||||
AsyncReceiver::new(self, ex)
|
||||
}
|
||||
}
|
||||
|
||||
/// One direction socket that only supports sending.
|
||||
pub struct Sender<M: MsgOnSocket> {
|
||||
sock: UnixSeqpacket,
|
||||
_m: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> Sender<M> {
|
||||
/// Create a new sender sock.
|
||||
pub fn new(s: UnixSeqpacket) -> Sender<M> {
|
||||
Sender {
|
||||
sock: s,
|
||||
_m: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One direction socket that only supports receiving.
|
||||
pub struct Receiver<M: MsgOnSocket> {
|
||||
sock: UnixSeqpacket,
|
||||
_m: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> Receiver<M> {
|
||||
/// Create a new receiver sock.
|
||||
pub fn new(s: UnixSeqpacket) -> Receiver<M> {
|
||||
Receiver {
|
||||
sock: s,
|
||||
_m: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> AsRef<UnixSeqpacket> for MsgSocket<I, O> {
|
||||
fn as_ref(&self) -> &UnixSeqpacket {
|
||||
&self.sock
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> AsRawDescriptor for MsgSocket<I, O> {
|
||||
fn as_raw_descriptor(&self) -> RawDescriptor {
|
||||
self.sock.as_raw_descriptor()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> AsRawDescriptor for &MsgSocket<I, O> {
|
||||
fn as_raw_descriptor(&self) -> RawDescriptor {
|
||||
self.sock.as_raw_descriptor()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> AsRef<UnixSeqpacket> for Sender<M> {
|
||||
fn as_ref(&self) -> &UnixSeqpacket {
|
||||
&self.sock
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> AsRawDescriptor for Sender<M> {
|
||||
fn as_raw_descriptor(&self) -> RawDescriptor {
|
||||
self.sock.as_raw_descriptor()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> AsRef<UnixSeqpacket> for Receiver<M> {
|
||||
fn as_ref(&self) -> &UnixSeqpacket {
|
||||
&self.sock
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MsgOnSocket> AsRawDescriptor for Receiver<M> {
|
||||
fn as_raw_descriptor(&self) -> RawDescriptor {
|
||||
self.sock.as_raw_descriptor()
|
||||
}
|
||||
}
|
||||
|
||||
/// Types that could send a message.
|
||||
pub trait MsgSender: AsRef<UnixSeqpacket> {
|
||||
type M: MsgOnSocket;
|
||||
fn send(&self, msg: &Self::M) -> MsgResult<()> {
|
||||
let msg_size = msg.msg_size();
|
||||
let descriptor_size = msg.descriptor_count();
|
||||
let mut msg_buffer: Vec<u8> = vec![0; msg_size];
|
||||
let mut descriptor_buffer: Vec<RawDescriptor> = vec![0; descriptor_size];
|
||||
|
||||
let descriptor_size = msg.write_to_buffer(&mut msg_buffer, &mut descriptor_buffer)?;
|
||||
let sock: &UnixSeqpacket = self.as_ref();
|
||||
if descriptor_size == 0 {
|
||||
handle_eintr!(sock.send(&msg_buffer))
|
||||
.map_err(|e| MsgError::Send(SysError::new(e.raw_os_error().unwrap_or(0))))?;
|
||||
} else {
|
||||
let ioslice = IoSlice::new(&msg_buffer[..]);
|
||||
sock.send_with_fds(&[ioslice], &descriptor_buffer[0..descriptor_size])
|
||||
.map_err(MsgError::Send)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Types that could receive a message.
|
||||
pub trait MsgReceiver: AsRef<UnixSeqpacket> {
|
||||
type M: MsgOnSocket;
|
||||
fn recv(&self) -> MsgResult<Self::M> {
|
||||
let sock: &UnixSeqpacket = self.as_ref();
|
||||
|
||||
let (msg_buffer, descriptor_buffer) = {
|
||||
if Self::M::uses_descriptor() {
|
||||
sock.recv_as_vec_with_fds()
|
||||
.map_err(|e| MsgError::Recv(SysError::new(e.raw_os_error().unwrap_or(0))))?
|
||||
} else {
|
||||
(
|
||||
sock.recv_as_vec().map_err(|e| {
|
||||
MsgError::Recv(SysError::new(e.raw_os_error().unwrap_or(0)))
|
||||
})?,
|
||||
vec![],
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if msg_buffer.is_empty() && Self::M::fixed_size() != Some(0) {
|
||||
return Err(MsgError::RecvZero);
|
||||
}
|
||||
|
||||
if let Some(fixed_size) = Self::M::fixed_size() {
|
||||
if fixed_size != msg_buffer.len() {
|
||||
return Err(MsgError::BadRecvSize {
|
||||
expected: fixed_size,
|
||||
actual: msg_buffer.len(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Safe because fd buffer is read from socket.
|
||||
let (v, read_descriptor_size) =
|
||||
unsafe { Self::M::read_from_buffer(&msg_buffer, &descriptor_buffer)? };
|
||||
if descriptor_buffer.len() != read_descriptor_size {
|
||||
return Err(MsgError::NotExpectDescriptor);
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> MsgSender for MsgSocket<I, O> {
|
||||
type M = I;
|
||||
}
|
||||
impl<I: MsgOnSocket, O: MsgOnSocket> MsgReceiver for MsgSocket<I, O> {
|
||||
type M = O;
|
||||
}
|
||||
|
||||
impl<I: MsgOnSocket> MsgSender for Sender<I> {
|
||||
type M = I;
|
||||
}
|
||||
impl<O: MsgOnSocket> MsgReceiver for Receiver<O> {
|
||||
type M = O;
|
||||
}
|
||||
|
||||
/// Asynchronous adaptor for `MsgSocket`.
|
||||
pub struct AsyncReceiver<'m, I: MsgOnSocket, O: MsgOnSocket> {
|
||||
// This weirdness is because we can't directly implement IntoAsync for &MsgSocket because there
|
||||
// is no AsRawFd impl for references.
|
||||
inner: &'m MsgSocket<I, O>,
|
||||
sock: Box<dyn IoSourceExt<&'m UnixSeqpacket> + 'm>,
|
||||
}
|
||||
|
||||
impl<'m, I: MsgOnSocket, O: MsgOnSocket> AsyncReceiver<'m, I, O> {
|
||||
fn new(msg_socket: &'m MsgSocket<I, O>, ex: &Executor) -> MsgResult<Self> {
|
||||
let sock = ex
|
||||
.async_from(&msg_socket.sock)
|
||||
.map_err(MsgError::CreateAsync)?;
|
||||
Ok(AsyncReceiver {
|
||||
inner: msg_socket,
|
||||
sock,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn next(&mut self) -> MsgResult<O> {
|
||||
self.sock.wait_readable().await.unwrap();
|
||||
self.inner.recv()
|
||||
}
|
||||
}
|
|
@ -1,438 +0,0 @@
|
|||
// 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 slice;
|
||||
mod tuple;
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use std::mem::{size_of, transmute_copy, MaybeUninit};
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base::{Error as SysError, RawDescriptor};
|
||||
use data_model::*;
|
||||
use slice::{slice_read_helper, slice_write_helper};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// An error during transaction or serialization/deserialization.
|
||||
pub enum MsgError {
|
||||
/// Error while creating an async socket.
|
||||
CreateAsync(cros_async::AsyncError),
|
||||
/// Error while sending a request or response.
|
||||
Send(SysError),
|
||||
/// Error while receiving a request or response.
|
||||
Recv(SysError),
|
||||
/// The type of a received request or response is unknown.
|
||||
InvalidType,
|
||||
/// There was not the expected amount of data when receiving a message. The inner
|
||||
/// value is how much data is expected and how much data was actually received.
|
||||
BadRecvSize { expected: usize, actual: usize },
|
||||
/// There was no data received when the socket `recv`-ed.
|
||||
RecvZero,
|
||||
/// There was no associated file descriptor received for a request that expected it.
|
||||
ExpectDescriptor,
|
||||
/// There was some associated file descriptor received but not used when deserialize.
|
||||
NotExpectDescriptor,
|
||||
/// Failed to set flags on the file descriptor.
|
||||
SettingDescriptorFlags(SysError),
|
||||
/// Trying to serialize/deserialize, but fd buffer size is too small. This typically happens
|
||||
/// when max_fd_count() returns a value that is too small.
|
||||
WrongDescriptorBufferSize,
|
||||
/// Trying to serialize/deserialize, but msg buffer size is too small. This typically happens
|
||||
/// when msg_size() returns a value that is too small.
|
||||
WrongMsgBufferSize,
|
||||
}
|
||||
|
||||
pub type MsgResult<T> = result::Result<T, MsgError>;
|
||||
|
||||
impl Display for MsgError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::MsgError::*;
|
||||
|
||||
match self {
|
||||
CreateAsync(e) => write!(f, "failed to create an async socket: {}", e),
|
||||
Send(e) => write!(f, "failed to send request or response: {}", e),
|
||||
Recv(e) => write!(f, "failed to receive request or response: {}", e),
|
||||
InvalidType => write!(f, "invalid type"),
|
||||
BadRecvSize { expected, actual } => write!(
|
||||
f,
|
||||
"wrong amount of data received; expected {} bytes; got {} bytes",
|
||||
expected, actual
|
||||
),
|
||||
RecvZero => write!(f, "received zero data"),
|
||||
ExpectDescriptor => write!(f, "missing associated file descriptor for request"),
|
||||
NotExpectDescriptor => write!(f, "unexpected file descriptor is unused"),
|
||||
SettingDescriptorFlags(e) => {
|
||||
write!(f, "failed setting flags on the message descriptor: {}", e)
|
||||
}
|
||||
WrongDescriptorBufferSize => write!(f, "descriptor buffer size too small"),
|
||||
WrongMsgBufferSize => write!(f, "msg buffer size too small"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A msg that could be serialized to and deserialize from array in little endian.
|
||||
///
|
||||
/// For structs, we always have fixed size of bytes and fixed count of fds.
|
||||
/// For enums, the size needed might be different for each variant.
|
||||
///
|
||||
/// e.g.
|
||||
/// ```
|
||||
/// use base::RawDescriptor;
|
||||
/// enum Message {
|
||||
/// VariantA(u8),
|
||||
/// VariantB(u32, RawDescriptor),
|
||||
/// VariantC,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For variant A, we need 1 byte to store its inner value.
|
||||
/// For variant B, we need 4 bytes and 1 RawDescriptor to store its inner value.
|
||||
/// For variant C, we need 0 bytes to store its inner value.
|
||||
/// When we serialize Message to (buffer, fd_buffer), we always use fixed number of bytes in
|
||||
/// the buffer. Unused buffer bytes will be padded with zero.
|
||||
/// However, for fd_buffer, we could not do the same thing. Otherwise, we are essentially sending
|
||||
/// fd 0 through the socket.
|
||||
/// Thus, read/write functions always the return correct count of fds in this variant. There will be
|
||||
/// no padding in fd_buffer.
|
||||
pub trait MsgOnSocket: Sized {
|
||||
// `true` if this structure can potentially serialize descriptors.
|
||||
fn uses_descriptor() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
// Returns `Some(size)` if this structure always has a fixed size.
|
||||
fn fixed_size() -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Size of message in bytes.
|
||||
fn msg_size(&self) -> usize {
|
||||
Self::fixed_size().unwrap()
|
||||
}
|
||||
|
||||
/// Number of FDs in this message. This must be overridden if `uses_descriptor()` returns true.
|
||||
fn descriptor_count(&self) -> usize {
|
||||
assert!(!Self::uses_descriptor());
|
||||
0
|
||||
}
|
||||
/// Returns (self, fd read count).
|
||||
/// This function is safe only when:
|
||||
/// 0. fds contains valid fds, received from socket, serialized by Self::write_to_buffer.
|
||||
/// 1. For enum, fds contains correct fd layout of the particular variant.
|
||||
/// 2. write_to_buffer is implemented correctly(put valid fds into the buffer, has no padding,
|
||||
/// return correct count).
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)>;
|
||||
|
||||
/// Serialize self to buffers.
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawDescriptor]) -> MsgResult<usize>;
|
||||
}
|
||||
|
||||
impl MsgOnSocket for SysError {
|
||||
fn fixed_size() -> Option<usize> {
|
||||
Some(size_of::<u32>())
|
||||
}
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
let (v, size) = u32::read_from_buffer(buffer, fds)?;
|
||||
Ok((SysError::new(v as i32), size))
|
||||
}
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
let v = self.errno() as u32;
|
||||
v.write_to_buffer(buffer, fds)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MsgOnSocket> MsgOnSocket for Option<T> {
|
||||
fn uses_descriptor() -> bool {
|
||||
T::uses_descriptor()
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
match self {
|
||||
Some(v) => v.msg_size() + 1,
|
||||
None => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
match self {
|
||||
Some(v) => v.descriptor_count(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
match buffer[0] {
|
||||
0 => Ok((None, 0)),
|
||||
1 => {
|
||||
let (inner, len) = T::read_from_buffer(&buffer[1..], fds)?;
|
||||
Ok((Some(inner), len))
|
||||
}
|
||||
_ => Err(MsgError::InvalidType),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
match self {
|
||||
None => {
|
||||
buffer[0] = 0;
|
||||
Ok(0)
|
||||
}
|
||||
Some(inner) => {
|
||||
buffer[0] = 1;
|
||||
inner.write_to_buffer(&mut buffer[1..], fds)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MsgOnSocket> MsgOnSocket for Arc<T> {
|
||||
fn uses_descriptor() -> bool {
|
||||
T::uses_descriptor()
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
(**self).msg_size()
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
(**self).descriptor_count()
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
T::read_from_buffer(buffer, fds).map(|(v, count)| (Arc::new(v), count))
|
||||
}
|
||||
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
(**self).write_to_buffer(buffer, fds)
|
||||
}
|
||||
}
|
||||
|
||||
impl MsgOnSocket for () {
|
||||
fn fixed_size() -> Option<usize> {
|
||||
Some(0)
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(_buffer: &[u8], _fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
Ok(((), 0))
|
||||
}
|
||||
|
||||
fn write_to_buffer(&self, _buffer: &mut [u8], _fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
// usize could be different sizes on different targets. We always use u64.
|
||||
impl MsgOnSocket for usize {
|
||||
fn msg_size(&self) -> usize {
|
||||
size_of::<u64>()
|
||||
}
|
||||
unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
if buffer.len() < size_of::<u64>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
let t = u64::from_le_bytes(slice_to_array(buffer));
|
||||
Ok((t as usize, 0))
|
||||
}
|
||||
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
if buffer.len() < size_of::<u64>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
let t: Le64 = (*self as u64).into();
|
||||
buffer[0..self.msg_size()].copy_from_slice(t.as_slice());
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode bool as a u8 of value 0 or 1
|
||||
impl MsgOnSocket for bool {
|
||||
fn msg_size(&self) -> usize {
|
||||
size_of::<u8>()
|
||||
}
|
||||
unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
if buffer.len() < size_of::<u8>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
let t: u8 = buffer[0];
|
||||
match t {
|
||||
0 => Ok((false, 0)),
|
||||
1 => Ok((true, 0)),
|
||||
_ => Err(MsgError::InvalidType),
|
||||
}
|
||||
}
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
if buffer.len() < size_of::<u8>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
buffer[0] = *self as u8;
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! le_impl {
|
||||
($type:ident, $native_type:ident) => {
|
||||
impl MsgOnSocket for $type {
|
||||
fn fixed_size() -> Option<usize> {
|
||||
Some(size_of::<$native_type>())
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(
|
||||
buffer: &[u8],
|
||||
_fds: &[RawDescriptor],
|
||||
) -> MsgResult<(Self, usize)> {
|
||||
if buffer.len() < size_of::<$native_type>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
let t = $native_type::from_le_bytes(slice_to_array(buffer));
|
||||
Ok((t.into(), 0))
|
||||
}
|
||||
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
_fds: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
if buffer.len() < size_of::<$native_type>() {
|
||||
return Err(MsgError::WrongMsgBufferSize);
|
||||
}
|
||||
let t: $native_type = self.clone().into();
|
||||
buffer[0..self.msg_size()].copy_from_slice(&t.to_le_bytes());
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
le_impl!(u8, u8);
|
||||
le_impl!(u16, u16);
|
||||
le_impl!(u32, u32);
|
||||
le_impl!(u64, u64);
|
||||
|
||||
le_impl!(Le16, u16);
|
||||
le_impl!(Le32, u32);
|
||||
le_impl!(Le64, u64);
|
||||
|
||||
fn simple_read<T: MsgOnSocket>(buffer: &[u8], offset: &mut usize) -> MsgResult<T> {
|
||||
assert!(!T::uses_descriptor());
|
||||
// Safety for T::read_from_buffer depends on the given FDs being valid, but we pass no FDs.
|
||||
let (v, _) = unsafe { T::read_from_buffer(&buffer[*offset..], &[])? };
|
||||
*offset += v.msg_size();
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn simple_write<T: MsgOnSocket>(v: T, buffer: &mut [u8], offset: &mut usize) -> MsgResult<()> {
|
||||
assert!(!T::uses_descriptor());
|
||||
v.write_to_buffer(&mut buffer[*offset..], &mut [])?;
|
||||
*offset += v.msg_size();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Converts a slice into an array of fixed size inferred from by the return value. Panics if the
|
||||
// slice is too small, but will tolerate slices that are too large.
|
||||
fn slice_to_array<T, O>(s: &[T]) -> O
|
||||
where
|
||||
T: Copy,
|
||||
O: Default + AsMut<[T]>,
|
||||
{
|
||||
let mut o = O::default();
|
||||
let o_slice = o.as_mut();
|
||||
let len = o_slice.len();
|
||||
o_slice.copy_from_slice(&s[..len]);
|
||||
o
|
||||
}
|
||||
|
||||
macro_rules! array_impls {
|
||||
($N:expr, $t: ident $($ts:ident)*)
|
||||
=> {
|
||||
impl<T: MsgOnSocket + Clone> MsgOnSocket for [T; $N] {
|
||||
fn uses_descriptor() -> bool {
|
||||
T::uses_descriptor()
|
||||
}
|
||||
|
||||
fn fixed_size() -> Option<usize> {
|
||||
Some(T::fixed_size()? * $N)
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
match T::fixed_size() {
|
||||
Some(s) => s * $N,
|
||||
None => self.iter().map(|i| i.msg_size()).sum::<usize>() + size_of::<u64>() * $N
|
||||
}
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
if T::uses_descriptor() {
|
||||
self.iter().map(|i| i.descriptor_count()).sum()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor])
|
||||
-> MsgResult<(Self, usize)> {
|
||||
// Taken from the canonical example of initializing an array, the `assume_init` can
|
||||
// be assumed safe because the array elements (`MaybeUninit<T>` in this case)
|
||||
// themselves don't require initializing.
|
||||
let mut msgs: [MaybeUninit<T>; $N] = MaybeUninit::uninit().assume_init();
|
||||
|
||||
let fd_count = slice_read_helper(buffer, fds, &mut msgs)?;
|
||||
|
||||
// Also taken from the canonical example, we initialized every member of the array
|
||||
// in the first loop of this function, so it is safe to `transmute_copy` the array
|
||||
// of `MaybeUninit` data to plain data. Although `transmute`, which checks the
|
||||
// types' sizes, would have been preferred in this code, the compiler complains with
|
||||
// "cannot transmute between types of different sizes, or dependently-sized types."
|
||||
// Because this function operates on generic data, the type is "dependently-sized"
|
||||
// and so the compiler will not check that the size of the input and output match.
|
||||
// See this issue for details: https://github.com/rust-lang/rust/issues/61956
|
||||
Ok((transmute_copy::<_, [T; $N]>(&msgs), fd_count))
|
||||
}
|
||||
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
slice_write_helper(self, buffer, fds)
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod $t {
|
||||
use super::MsgOnSocket;
|
||||
|
||||
#[test]
|
||||
fn read_write_option_array() {
|
||||
type ArrayType = [Option<u32>; $N];
|
||||
let array = [Some($N); $N];
|
||||
let mut buffer = vec![0; array.msg_size()];
|
||||
array.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_array = unsafe { ArrayType::read_from_buffer(&buffer, &[]) }.unwrap().0;
|
||||
|
||||
assert!(array.iter().eq(read_array.iter()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_fixed() {
|
||||
type ArrayType = [u32; $N];
|
||||
let mut buffer = vec![0; <ArrayType>::fixed_size().unwrap()];
|
||||
let array = [$N as u32; $N];
|
||||
array.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_array = unsafe { ArrayType::read_from_buffer(&buffer, &[]) }.unwrap().0;
|
||||
|
||||
assert!(array.iter().eq(read_array.iter()));
|
||||
}
|
||||
}
|
||||
array_impls!(($N - 1), $($ts)*);
|
||||
};
|
||||
{$N:expr, } => {};
|
||||
}
|
||||
|
||||
array_impls! {
|
||||
64, tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 tmp7 tmp8 tmp9 tmp10 tmp11 tmp12 tmp13 tmp14 tmp15 tmp16
|
||||
tmp17 tmp18 tmp19 tmp20 tmp21 tmp22 tmp23 tmp24 tmp25 tmp26 tmp27 tmp28 tmp29 tmp30 tmp31
|
||||
tmp32 tmp33 tmp34 tmp35 tmp36 tmp37 tmp38 tmp39 tmp40 tmp41 tmp42 tmp43 tmp44 tmp45 tmp46
|
||||
tmp47 tmp48 tmp49 tmp50 tmp51 tmp52 tmp53 tmp54 tmp55 tmp56 tmp57 tmp58 tmp59 tmp60 tmp61
|
||||
tmp62 tmp63 tmp64
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
use base::RawDescriptor;
|
||||
use std::mem::{size_of, ManuallyDrop, MaybeUninit};
|
||||
use std::ptr::drop_in_place;
|
||||
|
||||
use crate::{MsgOnSocket, MsgResult};
|
||||
|
||||
use super::{simple_read, simple_write};
|
||||
|
||||
/// Helper used by the types that read a slice of homegenously typed data.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function has the same safety requirements as `T::read_from_buffer`, with the additional
|
||||
/// requirements that the `msgs` are only used on success of this function
|
||||
pub unsafe fn slice_read_helper<T: MsgOnSocket>(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
msgs: &mut [MaybeUninit<T>],
|
||||
) -> MsgResult<usize> {
|
||||
let mut offset = 0usize;
|
||||
let mut fd_offset = 0usize;
|
||||
|
||||
// In case of an error, we need to keep track of how many elements got initialized.
|
||||
// In order to perform the necessary drops, the below loop is executed in a closure
|
||||
// to capture errors without returning.
|
||||
let mut last_index = 0;
|
||||
let res = (|| {
|
||||
for msg in &mut msgs[..] {
|
||||
let element_size = match T::fixed_size() {
|
||||
Some(s) => s,
|
||||
None => simple_read::<u64>(buffer, &mut offset)? as usize,
|
||||
};
|
||||
// Assuming the unsafe caller gave valid FDs, this call should be safe.
|
||||
let (m, fd_size) = T::read_from_buffer(&buffer[offset..], &fds[fd_offset..])?;
|
||||
*msg = MaybeUninit::new(m);
|
||||
offset += element_size;
|
||||
fd_offset += fd_size;
|
||||
last_index += 1;
|
||||
}
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
// Because `MaybeUninit` will not automatically call drops, we have to drop the
|
||||
// partially initialized array manually in the case of an error.
|
||||
if let Err(e) = res {
|
||||
for msg in &mut msgs[..last_index] {
|
||||
// The call to `as_mut_ptr()` turns the `MaybeUninit` element of the array
|
||||
// into a pointer, which can be used with `drop_in_place` to call the
|
||||
// destructor without moving the element, which is impossible. This is safe
|
||||
// because `last_index` prevents this loop from traversing into the
|
||||
// uninitialized parts of the array.
|
||||
drop_in_place(msg.as_mut_ptr());
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(fd_offset)
|
||||
}
|
||||
|
||||
/// Helper used by the types that write a slice of homegenously typed data.
|
||||
pub fn slice_write_helper<T: MsgOnSocket>(
|
||||
msgs: &[T],
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
let mut offset = 0usize;
|
||||
let mut fd_offset = 0usize;
|
||||
for msg in msgs {
|
||||
let element_size = match T::fixed_size() {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
let element_size = msg.msg_size();
|
||||
simple_write(element_size as u64, buffer, &mut offset)?;
|
||||
element_size as usize
|
||||
}
|
||||
};
|
||||
let fd_size = msg.write_to_buffer(&mut buffer[offset..], &mut fds[fd_offset..])?;
|
||||
offset += element_size;
|
||||
fd_offset += fd_size;
|
||||
}
|
||||
|
||||
Ok(fd_offset)
|
||||
}
|
||||
|
||||
impl<T: MsgOnSocket> MsgOnSocket for Vec<T> {
|
||||
fn uses_descriptor() -> bool {
|
||||
T::uses_descriptor()
|
||||
}
|
||||
|
||||
fn fixed_size() -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
let vec_size = match T::fixed_size() {
|
||||
Some(s) => s * self.len(),
|
||||
None => self.iter().map(|i| i.msg_size() + size_of::<u64>()).sum(),
|
||||
};
|
||||
size_of::<u64>() + vec_size
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
if T::uses_descriptor() {
|
||||
self.iter().map(|i| i.descriptor_count()).sum()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
let mut offset = 0;
|
||||
let len = simple_read::<u64>(buffer, &mut offset)? as usize;
|
||||
let mut msgs: Vec<MaybeUninit<T>> = Vec::with_capacity(len);
|
||||
msgs.set_len(len);
|
||||
let fd_count = slice_read_helper(&buffer[offset..], fds, &mut msgs)?;
|
||||
let mut msgs = ManuallyDrop::new(msgs);
|
||||
Ok((
|
||||
Vec::from_raw_parts(msgs.as_mut_ptr() as *mut T, msgs.len(), msgs.capacity()),
|
||||
fd_count,
|
||||
))
|
||||
}
|
||||
|
||||
fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawDescriptor]) -> MsgResult<usize> {
|
||||
let mut offset = 0;
|
||||
simple_write(self.len() as u64, buffer, &mut offset)?;
|
||||
slice_write_helper(self, &mut buffer[offset..], fds)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn read_write_1_fixed() {
|
||||
let vec = vec![1u32];
|
||||
let mut buffer = vec![0; vec.msg_size()];
|
||||
vec.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_vec = unsafe { <Vec<u32>>::read_from_buffer(&buffer, &[]) }
|
||||
.unwrap()
|
||||
.0;
|
||||
|
||||
assert_eq!(vec, read_vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_8_fixed() {
|
||||
let vec = vec![1u16, 1, 3, 5, 8, 13, 21, 34];
|
||||
let mut buffer = vec![0; vec.msg_size()];
|
||||
vec.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_vec = unsafe { <Vec<u16>>::read_from_buffer(&buffer, &[]) }
|
||||
.unwrap()
|
||||
.0;
|
||||
assert_eq!(vec, read_vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_1() {
|
||||
let vec = vec![Some(1u64)];
|
||||
let mut buffer = vec![0; vec.msg_size()];
|
||||
println!("{:?}", vec.msg_size());
|
||||
vec.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_vec = unsafe { <Vec<_>>::read_from_buffer(&buffer, &[]) }
|
||||
.unwrap()
|
||||
.0;
|
||||
|
||||
assert_eq!(vec, read_vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_4() {
|
||||
let vec = vec![Some(12u16), Some(0), None, None];
|
||||
let mut buffer = vec![0; vec.msg_size()];
|
||||
vec.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_vec = unsafe { <Vec<_>>::read_from_buffer(&buffer, &[]) }
|
||||
.unwrap()
|
||||
.0;
|
||||
|
||||
assert_eq!(vec, read_vec);
|
||||
}
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
use base::RawDescriptor;
|
||||
use std::mem::size_of;
|
||||
|
||||
use crate::{MsgOnSocket, MsgResult};
|
||||
|
||||
use super::{simple_read, simple_write};
|
||||
|
||||
// Returns the size of one part of a tuple.
|
||||
fn tuple_size_helper<T: MsgOnSocket>(v: &T) -> usize {
|
||||
T::fixed_size().unwrap_or_else(|| v.msg_size() + size_of::<u64>())
|
||||
}
|
||||
|
||||
unsafe fn tuple_read_helper<T: MsgOnSocket>(
|
||||
buffer: &[u8],
|
||||
fds: &[RawDescriptor],
|
||||
buffer_index: &mut usize,
|
||||
fd_index: &mut usize,
|
||||
) -> MsgResult<T> {
|
||||
let end = match T::fixed_size() {
|
||||
Some(_) => buffer.len(),
|
||||
None => {
|
||||
let len = simple_read::<u64>(buffer, buffer_index)? as usize;
|
||||
*buffer_index + len
|
||||
}
|
||||
};
|
||||
let (v, fd_read) = T::read_from_buffer(&buffer[*buffer_index..end], &fds[*fd_index..])?;
|
||||
*buffer_index += v.msg_size();
|
||||
*fd_index += fd_read;
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn tuple_write_helper<T: MsgOnSocket>(
|
||||
v: &T,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
buffer_index: &mut usize,
|
||||
fd_index: &mut usize,
|
||||
) -> MsgResult<()> {
|
||||
let end = match T::fixed_size() {
|
||||
Some(_) => buffer.len(),
|
||||
None => {
|
||||
let len = v.msg_size();
|
||||
simple_write(len as u64, buffer, buffer_index)?;
|
||||
*buffer_index + len
|
||||
}
|
||||
};
|
||||
let fd_written = v.write_to_buffer(&mut buffer[*buffer_index..end], &mut fds[*fd_index..])?;
|
||||
*buffer_index += v.msg_size();
|
||||
*fd_index += fd_written;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
() => {};
|
||||
($t: ident) => {
|
||||
#[allow(unused_variables, non_snake_case)]
|
||||
impl<$t: MsgOnSocket> MsgOnSocket for ($t,) {
|
||||
fn uses_descriptor() -> bool {
|
||||
$t::uses_descriptor()
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
self.0.descriptor_count()
|
||||
}
|
||||
|
||||
fn fixed_size() -> Option<usize> {
|
||||
$t::fixed_size()
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
self.0.msg_size()
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
let (t, s) = $t::read_from_buffer(buffer, fds)?;
|
||||
Ok(((t,), s))
|
||||
}
|
||||
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
self.0.write_to_buffer(buffer, fds)
|
||||
}
|
||||
}
|
||||
};
|
||||
($t: ident, $($ts:ident),*) => {
|
||||
#[allow(unused_variables, non_snake_case)]
|
||||
impl<$t: MsgOnSocket $(, $ts: MsgOnSocket)*> MsgOnSocket for ($t$(, $ts)*) {
|
||||
fn uses_descriptor() -> bool {
|
||||
$t::uses_descriptor() $(|| $ts::uses_descriptor())*
|
||||
}
|
||||
|
||||
fn descriptor_count(&self) -> usize {
|
||||
if Self::uses_descriptor() {
|
||||
return 0;
|
||||
}
|
||||
let ($t $(,$ts)*) = self;
|
||||
$t.descriptor_count() $(+ $ts.descriptor_count())*
|
||||
}
|
||||
|
||||
fn fixed_size() -> Option<usize> {
|
||||
// Returns None if any element is not fixed size.
|
||||
Some($t::fixed_size()? $(+ $ts::fixed_size()?)*)
|
||||
}
|
||||
|
||||
fn msg_size(&self) -> usize {
|
||||
if let Some(size) = Self::fixed_size() {
|
||||
return size
|
||||
}
|
||||
|
||||
let ($t $(,$ts)*) = self;
|
||||
tuple_size_helper($t) $(+ tuple_size_helper($ts))*
|
||||
}
|
||||
|
||||
unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawDescriptor]) -> MsgResult<(Self, usize)> {
|
||||
let mut buffer_index = 0;
|
||||
let mut fd_index = 0;
|
||||
Ok((
|
||||
(
|
||||
tuple_read_helper(buffer, fds, &mut buffer_index, &mut fd_index)?,
|
||||
$({
|
||||
// Dummy let used to trigger the correct number of iterations.
|
||||
let $ts = ();
|
||||
tuple_read_helper(buffer, fds, &mut buffer_index, &mut fd_index)?
|
||||
},)*
|
||||
),
|
||||
fd_index
|
||||
))
|
||||
}
|
||||
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
buffer: &mut [u8],
|
||||
fds: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
let mut buffer_index = 0;
|
||||
let mut fd_index = 0;
|
||||
let ($t $(,$ts)*) = self;
|
||||
tuple_write_helper($t, buffer, fds, &mut buffer_index, &mut fd_index)?;
|
||||
$(
|
||||
tuple_write_helper($ts, buffer, fds, &mut buffer_index, &mut fd_index)?;
|
||||
)*
|
||||
Ok(fd_index)
|
||||
}
|
||||
}
|
||||
tuple_impls!{ $($ts),* }
|
||||
}
|
||||
}
|
||||
|
||||
// Imlpement tuple for up to 8 elements.
|
||||
tuple_impls! { A, B, C, D, E, F, G, H }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn read_write_1_fixed() {
|
||||
let tuple = (1,);
|
||||
let mut buffer = vec![0; tuple.msg_size()];
|
||||
tuple.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_tuple = unsafe { <(u32,)>::read_from_buffer(&buffer, &[]) }
|
||||
.unwrap()
|
||||
.0;
|
||||
|
||||
assert_eq!(tuple, read_tuple);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_8_fixed() {
|
||||
let tuple = (1u32, 2u8, 3u16, 4u64, 5u32, 6u16, 7u8, 8u8);
|
||||
let mut buffer = vec![0; tuple.msg_size()];
|
||||
tuple.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_tuple = unsafe { <_>::read_from_buffer(&buffer, &[]) }.unwrap().0;
|
||||
|
||||
assert_eq!(tuple, read_tuple);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_1() {
|
||||
let tuple = (Some(1u64),);
|
||||
let mut buffer = vec![0; tuple.msg_size()];
|
||||
tuple.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_tuple = unsafe { <_>::read_from_buffer(&buffer, &[]) }.unwrap().0;
|
||||
|
||||
assert_eq!(tuple, read_tuple);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_write_4() {
|
||||
let tuple = (Some(12u16), Some(false), None::<u8>, None::<u64>);
|
||||
let mut buffer = vec![0; tuple.msg_size()];
|
||||
println!("{:?}", tuple.msg_size());
|
||||
tuple.write_to_buffer(&mut buffer, &mut []).unwrap();
|
||||
let read_tuple = unsafe { <_>::read_from_buffer(&buffer, &[]) }.unwrap().0;
|
||||
|
||||
assert_eq!(tuple, read_tuple);
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
use crate::msg_on_socket::{MsgError, MsgOnSocket, MsgResult};
|
||||
use base::{AsRawDescriptor, Event, FromRawDescriptor, RawDescriptor};
|
||||
use std::fs::File;
|
||||
use std::net::{TcpListener, TcpStream, UdpSocket};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
|
||||
|
||||
macro_rules! rawdescriptor_impl {
|
||||
($type:ident) => {
|
||||
impl MsgOnSocket for $type {
|
||||
fn uses_descriptor() -> bool {
|
||||
true
|
||||
}
|
||||
fn msg_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
unsafe fn read_from_buffer(
|
||||
_buffer: &[u8],
|
||||
descriptors: &[RawDescriptor],
|
||||
) -> MsgResult<(Self, usize)> {
|
||||
if descriptors.len() < 1 {
|
||||
return Err(MsgError::ExpectDescriptor);
|
||||
}
|
||||
Ok(($type::from_raw_descriptor(descriptors[0]), 1))
|
||||
}
|
||||
fn write_to_buffer(
|
||||
&self,
|
||||
_buffer: &mut [u8],
|
||||
descriptors: &mut [RawDescriptor],
|
||||
) -> MsgResult<usize> {
|
||||
if descriptors.is_empty() {
|
||||
return Err(MsgError::WrongDescriptorBufferSize);
|
||||
}
|
||||
descriptors[0] = self.as_raw_descriptor();
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
rawdescriptor_impl!(Event);
|
||||
rawdescriptor_impl!(File);
|
||||
|
||||
macro_rules! rawfd_impl {
|
||||
($type:ident) => {
|
||||
impl MsgOnSocket for $type {
|
||||
fn uses_descriptor() -> bool {
|
||||
true
|
||||
}
|
||||
fn msg_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn descriptor_count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
unsafe fn read_from_buffer(_buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
|
||||
if fds.len() < 1 {
|
||||
return Err(MsgError::ExpectDescriptor);
|
||||
}
|
||||
Ok(($type::from_raw_fd(fds[0]), 1))
|
||||
}
|
||||
fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
|
||||
if fds.is_empty() {
|
||||
return Err(MsgError::WrongDescriptorBufferSize);
|
||||
}
|
||||
fds[0] = self.as_raw_fd();
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
rawfd_impl!(UnixStream);
|
||||
rawfd_impl!(TcpStream);
|
||||
rawfd_impl!(TcpListener);
|
||||
rawfd_impl!(UdpSocket);
|
||||
rawfd_impl!(UnixListener);
|
||||
rawfd_impl!(UnixDatagram);
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
use base::{Event, RawDescriptor};
|
||||
|
||||
use msg_socket::*;
|
||||
|
||||
#[derive(MsgOnSocket)]
|
||||
struct DummyRequest {}
|
||||
|
||||
#[derive(MsgOnSocket)]
|
||||
enum Response {
|
||||
A(u8),
|
||||
B,
|
||||
C(u32, Event),
|
||||
D([u8; 4]),
|
||||
E { f0: u8, f1: u32 },
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sock_send_recv_enum() {
|
||||
let (req, res) = pair::<DummyRequest, Response>().unwrap();
|
||||
let e0 = Event::new().unwrap();
|
||||
let e1 = e0.try_clone().unwrap();
|
||||
res.send(&Response::C(0xf0f0, e0)).unwrap();
|
||||
let r = req.recv().unwrap();
|
||||
match r {
|
||||
Response::C(v, efd) => {
|
||||
assert_eq!(v, 0xf0f0);
|
||||
efd.write(0x0f0f).unwrap();
|
||||
}
|
||||
_ => panic!("wrong type"),
|
||||
};
|
||||
assert_eq!(e1.read().unwrap(), 0x0f0f);
|
||||
|
||||
res.send(&Response::B).unwrap();
|
||||
match req.recv().unwrap() {
|
||||
Response::B => {}
|
||||
_ => panic!("Wrong enum type"),
|
||||
};
|
||||
|
||||
res.send(&Response::A(0x3)).unwrap();
|
||||
match req.recv().unwrap() {
|
||||
Response::A(v) => assert_eq!(v, 0x3),
|
||||
_ => panic!("Wrong enum type"),
|
||||
};
|
||||
|
||||
res.send(&Response::D([0, 1, 2, 3])).unwrap();
|
||||
match req.recv().unwrap() {
|
||||
Response::D(v) => assert_eq!(v, [0, 1, 2, 3]),
|
||||
_ => panic!("Wrong enum type"),
|
||||
};
|
||||
|
||||
res.send(&Response::E {
|
||||
f0: 0x12,
|
||||
f1: 0x0f0f,
|
||||
})
|
||||
.unwrap();
|
||||
match req.recv().unwrap() {
|
||||
Response::E { f0, f1 } => {
|
||||
assert_eq!(f0, 0x12);
|
||||
assert_eq!(f1, 0x0f0f);
|
||||
}
|
||||
_ => panic!("Wrong enum type"),
|
||||
};
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
use base::{Event, RawDescriptor};
|
||||
|
||||
use msg_socket::*;
|
||||
|
||||
#[derive(MsgOnSocket)]
|
||||
struct Request {
|
||||
field0: u8,
|
||||
field1: Event,
|
||||
field2: u32,
|
||||
field3: bool,
|
||||
}
|
||||
|
||||
#[derive(MsgOnSocket)]
|
||||
struct DummyResponse {}
|
||||
|
||||
#[test]
|
||||
fn sock_send_recv_struct() {
|
||||
let (req, res) = pair::<Request, DummyResponse>().unwrap();
|
||||
let e0 = Event::new().unwrap();
|
||||
let e1 = e0.try_clone().unwrap();
|
||||
req.send(&Request {
|
||||
field0: 2,
|
||||
field1: e0,
|
||||
field2: 0xf0f0,
|
||||
field3: true,
|
||||
})
|
||||
.unwrap();
|
||||
let r = res.recv().unwrap();
|
||||
assert_eq!(r.field0, 2);
|
||||
assert_eq!(r.field2, 0xf0f0);
|
||||
assert_eq!(r.field3, true);
|
||||
r.field1.write(0x0f0f).unwrap();
|
||||
assert_eq!(e1.read().unwrap(), 0x0f0f);
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
use base::{Event, RawDescriptor};
|
||||
use msg_socket::*;
|
||||
|
||||
#[derive(MsgOnSocket)]
|
||||
struct Message(u8, u16, Event);
|
||||
|
||||
#[test]
|
||||
fn sock_send_recv_tuple() {
|
||||
let (req, res) = pair::<Message, Message>().unwrap();
|
||||
let e0 = Event::new().unwrap();
|
||||
let e1 = e0.try_clone().unwrap();
|
||||
req.send(&Message(1, 0x12, e0)).unwrap();
|
||||
let r = res.recv().unwrap();
|
||||
assert_eq!(r.0, 1);
|
||||
assert_eq!(r.1, 0x12);
|
||||
r.2.write(0x0f0f).unwrap();
|
||||
assert_eq!(e1.read().unwrap(), 0x0f0f);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// 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.
|
||||
|
||||
use msg_socket::*;
|
||||
|
||||
#[test]
|
||||
fn sock_send_recv_unit() {
|
||||
let (req, res) = pair::<(), ()>().unwrap();
|
||||
req.send(&()).unwrap();
|
||||
let _ = res.recv().unwrap();
|
||||
}
|
Loading…
Reference in a new issue