-
Notifications
You must be signed in to change notification settings - Fork 171
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
Add support for sendmmsg(2) on linux #1171
base: main
Are you sure you want to change the base?
Conversation
10452dc
to
779b2b7
Compare
This comment was marked as resolved.
This comment was marked as resolved.
e6b2394
to
6534026
Compare
src/net/send_recv/msg.rs
Outdated
#[cfg(target_os = "linux")] | ||
impl<'a> MMsgHdr<'a> { | ||
/// Constructs a new message with no destination address. | ||
pub fn new(iov: &[IoSlice<'a>], control: &mut SendAncillaryBuffer<'_, '_, '_>) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you comment on why control
needs to be a mut
reference here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dumb answer is "because sendmsg
requires a mut
reference" (as does with_noaddr_msghdr
and friends). I assumed some random API modified the cmsg on send, but I don't know which one.
I think I addressed all your comments. |
src/net/send_recv/msg.rs
Outdated
iov: &[IoSlice<'a>], | ||
control: &mut SendAncillaryBuffer<'_, '_, '_>, | ||
) -> Self { | ||
with_v4_msghdr(addr, iov, control, Self::wrap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this unsound? with_v4_msghdr
allocates the V4 socket address on the stack and then passes that stack address in the msghdr
in Self::wrap
. So when we eventually call into the system call it is pointing to invalid stack memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right. Maybe SockAddrStorage
can be used for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to avoid passing the length in here, we'll need to add a RawSockAddr
type, I think, created with SockAddrV4::as_raw
etc. It'll be slightly unergonomic, as the borrow checker won't let you do this:
MMsgHdr::new_with_addr(my_v4_addr.as_raw(), ...)
Since that would create a temporary value which is dropped. But it should work fine otherwise.
Then the signature becomes:
pub fn new_with_addr(
addr: &'a RawSockAddr,
iov: &[IoSlice<'a>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
) -> Self {
// ...
}
I think that helps with the recvmmsg(2)
case, as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a RawSocketAddr
type in my latest push (it's a separate commit, so can be reviewed independently).
afe3c24
to
695e084
Compare
It wraps SockAddrStorage, but includes a length, for when a sockaddr has to be stored for a longer lifetime.
https://man7.org/linux/man-pages/man2/sendmmsg.2.html Partially addresses bytecodealliance#1156. Signed-off-by: Colin Marc <hi@colinmarc.com>
Hi, anything needed from me on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good, just a few more review comments:
@@ -107,6 +126,35 @@ impl SocketAddrAny { | |||
} | |||
} | |||
|
|||
/// A raw sockaddr and its length. | |||
#[repr(C)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this repr(C)
needed? Is there anywhere we pass the full RawSocketAddr
to an ffi call?
@@ -781,6 +826,58 @@ pub fn sendmsg_any( | |||
} | |||
} | |||
|
|||
/// `sendmsg(msghdr)`—Sends a message on a socket to a specific address. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// `sendmsg(msghdr)`—Sends a message on a socket to a specific address. | |
/// `sendmsg(msghdr)`—Sends a message on a socket to a specific raw socket address. |
target_os = "redox", | ||
target_os = "vita", | ||
target_os = "wasi" | ||
)))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cfg
attribute is unneeded because we're in the linux_raw backend here.
control: &mut SendAncillaryBuffer<'_, '_, '_>, | ||
flags: SendFlags, | ||
) -> io::Result<usize> { | ||
match addr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of matching addr
here, would it work to have the backend sendmsg_raw
and with_raw_msghdr
take an Option<&RawSocketAddr>
as well, and then in with_raw_msghdr
convert the Option
into a pointer for msg_name
using crate::utils::option_as_ptr
?
https://man7.org/linux/man-pages/man2/sendmmsg.2.html
Partially addresses #1156. I would've liked to add
recvmmsg
in the same PR, but it's actually much more complicated.