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:
Zach Reizner 2021-02-26 11:41:19 -08:00 committed by Commit Bot
parent d49bcdb081
commit 58509986c2
12 changed files with 0 additions and 2223 deletions

View file

@ -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" }

View file

@ -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"

View file

@ -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());
}
}

View file

@ -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()
}
}

View file

@ -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
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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"),
};
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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();
}