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

unix: Extend UpdSocket to send and receive TTL for a specific packet #82858

Closed
wants to merge 2 commits into from

Conversation

LinkTed
Copy link
Contributor

@LinkTed LinkTed commented Mar 7, 2021

Add the function recv_vectored_with_ancillary_from,
recv_vectored_with_ancillary, send_vectored_with_ancillary_to and
send_vectored_with_ancillary to UdpSocket for Unix platforms. Also add
set_recvttl and recvttl to UdpSocket to tell the kernel to receive the
TTL. Therefore, the AncillaryData enum had to be extended.

@rust-highfive
Copy link
Collaborator

r? @KodrAus

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 7, 2021
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@LinkTed LinkTed force-pushed the master branch 2 times, most recently from 062c56f to 1447222 Compare March 13, 2021 14:25
@joshtriplett
Copy link
Member

Can you force-push to fix the typo in the commit message (UpdSocket should be UdpSocket), please?

@joshtriplett
Copy link
Member

I posted comments with a few very minor issues. With those fixed, this LGTM.

@bors
Copy link
Contributor

bors commented Mar 30, 2021

☔ The latest upstream changes (presumably #83664) made this pull request unmergeable. Please resolve the merge conflicts.

@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 18, 2021
@JohnTitor
Copy link
Member

r? @joshtriplett

@bors
Copy link
Contributor

bors commented May 5, 2021

☔ The latest upstream changes (presumably #84200) made this pull request unmergeable. Please resolve the merge conflicts.

@LinkTed
Copy link
Contributor Author

LinkTed commented May 9, 2021

Hi @joshtriplett, could you approve this PR?

@camelid camelid added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 28, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 14, 2021
@LinkTed
Copy link
Contributor Author

LinkTed commented Jul 25, 2021

The job mingw-check failed! Check out the build log: (web) (plain)
Click to see the possible cause of the failure (guessed by this bot)

configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
    Finished release [optimized] target(s) in 8.34s
tidy check
tidy: Skipping binary file check, read-only filesystem
Checking which error codes lack tests...
tidy error: /checkout/library/std/src/net/udp.rs:6: platform-specific cfg: cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "emscripten",
    target_os = "freebsd",
    target_os = "linux",
    target_os = "netbsd",
    target_os = "openbsd",
))
tidy error: /checkout/library/std/src/net/udp.rs:17: platform-specific cfg: cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "emscripten",
    target_os = "freebsd",
    target_os = "linux",
    target_os = "netbsd",
    target_os = "openbsd",
))
tidy error: /checkout/library/std/src/net/udp.rs:159: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
    ))
tidy error: /checkout/library/std/src/net/udp.rs:178: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
    ))
tidy error: /checkout/library/std/src/net/udp.rs:227: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
    ))
tidy error: /checkout/library/std/src/net/udp.rs:282: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
    ))
tidy error: /checkout/library/std/src/net/udp.rs:392: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
    ))
tidy error: /checkout/library/std/src/net/udp.rs:440: platform-specific cfg: cfg(any(
        target_os = "android",
        target_os = "dragonfly",
        target_os = "emscripten",
        target_os = "freebsd",
        target_os = "linux",
        target_os = "netbsd",
        target_os = "openbsd",
* 625 error codes
* highest error code: E0783
Found 499 error codes
Found 0 error codes with no tests
Found 0 error codes with no tests
Done!
* 340 features
some tidy checks failed


command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/checkout" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "/checkout/obj/build" "16"


Build completed unsuccessfully in 0:00:10

Does somebody know how to fix this tidy error?

@the8472
Copy link
Member

the8472 commented Jul 25, 2021

Afaik platform-specific code should be in the sys (internal) or os (public) modules.

@rust-log-analyzer

This comment has been minimized.

@LinkTed
Copy link
Contributor Author

LinkTed commented Jul 25, 2021

Afaik platform-specific code should be in the sys (internal) or os (public) modules.

Did not know that, thanks.

@LinkTed LinkTed force-pushed the master branch 2 times, most recently from 8d9d6b4 to 605bf81 Compare July 26, 2021 12:36
@LinkTed
Copy link
Contributor Author

LinkTed commented Jul 27, 2021

Hi @joshtriplett,
If you have some free time, could you review my PR?

@the8472
Copy link
Member

the8472 commented Aug 11, 2021

Since josh seems busy and this concerns unstable stuff which will need some more revisions anyway I hope it's ok if I take over review. I'll go over it on the weekend.

r? @the8472

@the8472 the8472 added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Aug 11, 2021
Add the function recv_vectored_with_ancillary_from,
recv_vectored_with_ancillary, send_vectored_with_ancillary_to and
send_vectored_with_ancillary to UdpSocket for Unix platforms. Also add
set_recvttl and recvttl to UdpSocket to tell the kernel to receive the
TTL. Therefore, rename the Ancillary(Data) to UnixAncillary(Data) for
the UnixDatagram and UnixStream and also add the IpAncillary(Data) for
UdpSocket.
Copy link
Member

@the8472 the8472 left a comment

Choose a reason for hiding this comment

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

First pass, haven't reviewed everything yet.

Overall I am a bit concerned that the split into IpAncillary and UnixAncillary will lead to some duplication especially if we want to expose raw ancillary messages (parsed into header + raw data) so that other libraries can do their own decoding. Although that discussion belongs in #76915 i'm just noting that the changes here may need to be revised.

library/std/src/os/unix/net/ancillary/ip.rs Outdated Show resolved Hide resolved
/// and type `IPV6_HOPLIMIT`.
///
/// # Example
/// ```no_run
Copy link
Member

Choose a reason for hiding this comment

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

Any reason why the doc test is no_run? Obviously the receiving parts would hang if they never received data but the sending ones could send the data into a black hole.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But it would fail because of the expect("send_vectored_with_ancillary function failed").

Copy link
Member

Choose a reason for hiding this comment

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

Why would sending fail though? UDP is fire-and-forget so you can still send even if nothing is listening on the other side.
If it's failing due to the lack of ipv6 you could try 127.0.0.1 instead.

library/std/src/os/unix/net/ancillary/ip.rs Outdated Show resolved Hide resolved
///
/// The function returns `true` if there was enough space in the buffer.
/// If there was not enough space then no file descriptors was appended.
/// Technically, that means this operation adds a control message with the level `IPPROTO_IPV6`
Copy link
Member

Choose a reason for hiding this comment

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

"Technically" seems like an odd choice here (and in the comment below too). The following would probably do

This adds a control message [...]

Since this is standardized maybe link to the relevant section in RFC 3542

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Where and how to add the RFC 3542 link?

target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
))]
Copy link
Member

Choose a reason for hiding this comment

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

these additions run afoul of this rule:

//! `std/sys_common` should _not_ contain platform-specific code.

It currently isn't fully enforced by tidy, but the goal is to reduce that amount, not add more. Instead the module-reuse trick used a few times by hermit might help.

https://github.com/rust-lang/rust/blob/master/library/std/src/sys/hermit/mod.rs#L33-L38

sys_common::AsInner,
};

impl UdpSocket {
Copy link
Member

Choose a reason for hiding this comment

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

Unless I missed a policy change simply adding platform-specific methods to a cross-platform struct isn't allowed and sealed extension traits should be used instead.

self.as_inner().recvttl()
}

/// Receives data and ancillary data from socket.
Copy link
Member

Choose a reason for hiding this comment

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

ancilliary data should link to IpAncillary's docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How do I add this link?

Copy link
Member

Choose a reason for hiding this comment

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

Check the Ipv4Addr doc comments for an example.

}
}

/// A net IP Ancillary data struct.
Copy link
Member

Choose a reason for hiding this comment

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

This needs several paragraphs of text and links to external documentation (e.g. RFC 3542, cmsg manpages or posix specs)

library/std/src/os/unix/net/tests.rs Outdated Show resolved Hide resolved
@LinkTed
Copy link
Contributor Author

LinkTed commented Aug 21, 2021

First pass, haven't reviewed everything yet.

Overall I am a bit concerned that the split into IpAncillary and UnixAncillary will lead to some duplication especially if we want to expose raw ancillary messages (parsed into header + raw data) so that other libraries can do their own decoding. Although that discussion belongs in #76915 i'm just noting that the changes here may need to be revised.

This was suggested here. I think we should keep IpAncillary and UnixAncillary because a Unix socket does not have a TTL. I try to avoid code duplication as much as possible.

If other libraries should use their own decoding, then we have to define the interface.

Extend UdpSocket to send and receive hop-limit.
@the8472
Copy link
Member

the8472 commented Aug 22, 2021

First pass, haven't reviewed everything yet.
Overall I am a bit concerned that the split into IpAncillary and UnixAncillary will lead to some duplication especially if we want to expose raw ancillary messages (parsed into header + raw data) so that other libraries can do their own decoding. Although that discussion belongs in #76915 i'm just noting that the changes here may need to be revised.

This was suggested here. I think we should keep IpAncillary and UnixAncillary because a Unix socket does not have a TTL. I try to avoid code duplication as much as possible.

If other libraries should use their own decoding, then we have to define the interface.

Having separate enums makes sense. But do we need separate ancillary types and all those setters too?

Imo it would make more sense to align more closely with native concept of arbitrary messages. Some of those happen to be of types known to the standard library but not all of them.

I think it could look roughly look like this:

trait AncillaryMessage {
   fn to_raw(&self) -> (c_int, c_int, &[u8]);

   // and some unsafe helper methods do the memcpy to custom types properly
}

struct RawAncillaryMessage {
   // I'm not 100% sure, but I think for raw accessors to platform-specific values using `c_int` should be fine.
   fn from_raw(level: c_int, type: c_int, body: &[u8]) -> Self;
}

impl AncillaryMessage for RawAncillaryMessage {
  ...
}

impl AncillaryMessage for IpAncillaryData {
  ...
}

impl TryFrom<RawAncillaryMessage> for IpAncillaryData {
  ...
}

impl SocketAncillary {
  pub fn addMessage(&mut self, impl AncillaryMessage) {
     ...
  }

  pub fn getMessages(&self) -> impl Iterator<Item = RawAncillaryMessage> {
     ...
  }
}

Then you could add any kind of message and iterator over any kind of message and then try_into() each message into IpAncillaryData and ignore those out that the standard library doesn't know or process them yourself by accessing the raw data.

If you pass in a UnixAncillaryData into an inet socket then the send will fail with an error, so it's not something we need to guard against. The separation of the enums would only exist as a weak separation so that users of try_into() would have fewer enum variants to deal with as long as they use the correct one for the socket.

#[doc(cfg(any(target_os = "android", target_os = "linux",)))]
#[cfg(any(doc, target_os = "android", target_os = "linux",))]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>);
Copy link
Member

Choose a reason for hiding this comment

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

If these structs are linux-specific they should be moved to os::linux, or are there any other unix platforms that support this too and they're just not implemented yet? There's #88025 which looks similar and yet different, I haven't checked if they can be unified.

@bors
Copy link
Contributor

bors commented Aug 23, 2021

☔ The latest upstream changes (presumably #88265) made this pull request unmergeable. Please resolve the merge conflicts.

@the8472 the8472 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 5, 2021
@JohnCSimon
Copy link
Member

@LinkTed
Ping from triage - can you please address the merge conflicts?

@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 19, 2021
@JohnCSimon
Copy link
Member

@LinkTed
I'm closing this PR is inactive, please feel free to reopen when you're ready to continue and address the comments and merge conflicts.
@rustbot label: +S-inactive

@rustbot rustbot added the S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. label Nov 8, 2021
@JohnCSimon JohnCSimon closed this Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.