Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove FFI types from the public API #186

Merged
merged 2 commits into from Jan 8, 2021
Merged

Remove FFI types from the public API #186

merged 2 commits into from Jan 8, 2021

Conversation

tamird
Copy link
Contributor

@tamird tamird commented Dec 29, 2020

Extracted from #184 @Thomasdezeeuw.

Copy link
Collaborator

@Thomasdezeeuw Thomasdezeeuw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussing this in #184 (comment), I'm ok with the change.

src/sys/unix.rs Outdated
@@ -942,11 +937,13 @@ impl crate::Socket {
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
))]
pub fn device(&self) -> io::Result<Option<CString>> {
pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
use std::convert::TryInto as _;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.S: You don't need to use as _.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. I usually do this with traits to avoid bringing the trait name into the local namespace.

src/sys/unix.rs Outdated
unsafe { MaybeUninit::<[MaybeUninit<u8>; libc::IFNAMSIZ]>::uninit().assume_init() };
let mut len = buf.len() as libc::socklen_t;
unsafe { MaybeUninit::uninit().assume_init() };
let mut len = buf.len().try_into().unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave the original code. The buf initialisation is the same as MaybeUninit::uninit_array to which we should move in the future. And we know that IFNAMSIZ can't be larger than libc::socklen_t::MAX so the as usage is fine, I don't like unwrap too much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buf initialization is the same as the original code (in this PR, not in #184); I've just removed some repeated type parameters.

I agree that IFNAMSIZ in practice can't fail this conversion, but why think about it? This code is safer and should compile to the same thing.

src/sys/unix.rs Outdated
// include any null bytes.
Ok(Some(unsafe { CString::from_vec_unchecked(name) }))
let buf = &buf[..len.try_into().unwrap()];
Ok(Some(unsafe { mem::transmute::<_, &[u8]>(buf) }.into()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use transmute, it's too easy to misuse. Also let's keep the same code as in MaybeUninit::slice_assume_init_ref so we can switch to that easily once stable.

It think the following would be shortest.

// Safety: `len` bytes are writen by the OS, this includes a null
// terminator. However we don't need the null terminator.
let buf = unsafe { slice::from_raw_parts(buf.as_ptr().cast(), (len - 1) as usize) };
Ok(Some(buf.into_vec()))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len does not include a null terminator AFAIK.

Other than that, this code is the same as it would be with slice_assume_init_ref. That code would be:

let buf = &buf[..len.try_into().unwrap()];
Ok(Some(unsafe { MaybeUninit::slice_assume_init_ref(buf) }.into()))

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len does include a null terminate, I've just manually tried this patch. The test currently doesn't fail it it doesn't have permissions (mainly for the CI), but we might have to change that. I'll fiddle with this a bit more and merge this changing the signature to [u8] rather than CStr.

P.S. it requires sudo setcap cap_net_raw=ep $test_bin, something that we might have to do in the CI as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm about 95% sure that len does not include the null terminator when the name is IFNAMSIZ characters long. That is probably an edge case worth testing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a bit more manual testing. I couldn't create an interface with a name larger than 15 bytes, with IFNAMSIZ being 16.

sudo ip link add test_interface0 type bridge  # Fine.
sudo ip link add test_interface01 type bridge # Error: Attribute failed policy validation.

I also tested binding to test_interface01 with the implementation in #187 which worked.

@Thomasdezeeuw
Copy link
Collaborator

@tamird created #187 which works. I've put ignore attribute to the test as it doesn't run without the CAP_NET_RAW capability (on Linux).

@tamird
Copy link
Contributor Author

tamird commented Jan 5, 2021

@Thomasdezeeuw you should be able to push to this PR rather than working in a separate one.

@Thomasdezeeuw
Copy link
Collaborator

@tamird I didn't know I could push to some else's branch.

@Thomasdezeeuw
Copy link
Collaborator

@tamird I've pushed the changes to this branch.

tests/socket.rs Outdated Show resolved Hide resolved
tests/socket.rs Outdated
panic!(
"failing to bind to any device. \
Note that on Linux this requires the `CAP_NET_RAW` permission. \
This can be given using `sudo setcap cap_net_raw=ep $test_bin`."
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this mention whatever flag is necessary to run this test case given the ignore attribute?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it to just say "failed to bind to any device", the other info is already in the ignore attribute.

With flag do you mean --ignore passed to cargo test, or do mean another flag? If the first than I don't it's needed.

Since the test is now not run by default it doesn't make sense to allow
permission errors.

Also reduces explanation in the `panic!` calls since that's already in
the ignore attribute.
@Thomasdezeeuw Thomasdezeeuw merged commit c3babcd into rust-lang:master Jan 8, 2021
@tamird tamird deleted the better-ffi-api branch January 8, 2021 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants