-
Notifications
You must be signed in to change notification settings - Fork 13.8k
std: sys: net: uefi: tcp: Initial TcpListener support #145339
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
base: master
Are you sure you want to change the base?
Conversation
r? @ibraheemdev rustbot has assigned @ibraheemdev. Use |
Passing this along to someone else, who hopefully has more context. r? libs |
@rustbot label +O-UEFI |
Thom is off the review rotation Also gentle ping @nicholasbishop for a review since we usually defer UEFI to you |
// The spec does not seem to state if we need to call ServiceBinding->DestroyChild for | ||
// this handle |
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 there a reference implementation that does or doesn't do this? Or a way to check whether or not the handle is valid after this call?
54d3d51
to
5459fc4
Compare
☔ The latest upstream changes (presumably #146418) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
Generally LGTM but left a few remarks
5459fc4
to
9f020a9
Compare
This comment has been minimized.
This comment has been minimized.
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 assume the waiting-on-author label isn't actually accurate?
This LGTM, with the note that if you are following some sort of reference implementation for #145339 (comment) then it would be good to mention what that is in a comment.
You should probably rebase before merge and verify that it still builds, since sys::net
has had some changes in recent weeks. Also cc @nicholasbishop if you'd like to double check this.
let completion_token = | ||
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS }; | ||
let mut listen_token = | ||
tcp4::ListenToken { completion_token, new_child_handle: crate::ptr::null_mut() }; |
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.
Should probably just import crate::ptr
, it's used a lot of places in this module and will likely wind up in more in the future. (totally optional here ofc)
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.
Added
9f020a9
to
a452682
Compare
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
So, just looked at the internals of edk2 again, and it does seem like I need to use service binding protocol to clean it up. From what I gather of the implementation of TcpServiceBindingDestroyChild, it seems like at least edk2 assumes there to be only one service binding protocol for both tcp4 and tcp6. In fact, no data from service binding protocol is passed or used to destroy the socket (other than then service binding protocol not being null). So will adjust the PR once I get time. |
a452682
to
e2521f5
Compare
I am now using the parent service binding protocol to handle in any connections accepted by TCP4. On EDK2, this is not really required, since there seems to be an assumption of a single service binding protocol for both TCP4 and TCP6. However, best to be safe. I have also refactored service binding wrapper a bit. It's best to cleanup tcp4 protcol handles in it's own drop. @rustbot ready |
Add support for binding and accepting TCP4 connections. While testing, the following network options were used with QEMU + OVMF: -nic user,hostfwd=tcp::12345-:12345 The default localhost address on qemu seems to be 10.0.2.15. UEFI spec does not seem to state that the TCP Handle returned by the Accept method has a ServiceBinding Protocol. So have made the ServiceBinding Protocol optional. Signed-off-by: Ayush Singh <[email protected]>
e2521f5
to
ba446c9
Compare
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.
Code LGTM, have a few requests for where the safety invariants live
pub(crate) fn destroy_child(&self, handle: NonNull<crate::ffi::c_void>) -> io::Result<()> { | ||
let sbp = open_protocol::<service_binding::Protocol>(self.handle, self.service_guid)?; | ||
|
||
// SAFETY: Child handle must be allocated by the current service binding protocol. | ||
let r = unsafe { ((*sbp.as_ptr()).destroy_child)(sbp.as_ptr(), handle.as_ptr()) }; | ||
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } | ||
} |
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 needs to be unsafe if the precondition of the destroy_child
call depends on the validity of handle
.
Also, is it safe to call destroy_child
with the same handle more than once?
pub(crate) struct ServiceProtocol { | ||
service_guid: r_efi::efi::Guid, | ||
handle: NonNull<crate::ffi::c_void>, | ||
child_handle: NonNull<crate::ffi::c_void>, | ||
} | ||
|
||
impl ServiceProtocol { | ||
pub(crate) fn open(service_guid: r_efi::efi::Guid) -> io::Result<Self> { | ||
/// Open a child handle on a service_binding protocol. | ||
pub(crate) fn open( | ||
service_guid: r_efi::efi::Guid, | ||
) -> io::Result<(Self, NonNull<crate::ffi::c_void>)> { |
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.
type Handle = NonNull<crate::ffi::c_void>
may be a worthwhile typedef since it's used a few times in this file and in Tcp4
fn create_child( | ||
sbp: NonNull<service_binding::Protocol>, | ||
) -> io::Result<NonNull<crate::ffi::c_void>> { |
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.
Actually I think this needs to be unsafe
too for the same reason
/// | ||
/// SAFETY: Copying ServiceProtocol is safe as long as handle is valid. For most service binding | ||
/// protocols, at least in edk2 implementations, the lifetime of these handles will be till UEFI is | ||
/// active, i.e. 'static | ||
#[derive(Clone, Copy)] | ||
pub(crate) struct ServiceProtocol { | ||
service_guid: r_efi::efi::Guid, | ||
handle: NonNull<crate::ffi::c_void>, | ||
child_handle: NonNull<crate::ffi::c_void>, | ||
} |
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 SAFETY
comment shouldn't be here since duplicating this struct doesn't do anything by itself. If the handle is expected to be valid for 'static
, this would be better expressed as an /// Invariant: ...
comment on the handle
field. Then:
- For
unsafe
calls that usehandle
, you can say they are valid by the invariant - For places where
ServiceProtocol
is constructed, you can add an// INVARIANT:
comment saying why they meet that invariant. And call out the assumption.
For most service binding protocols, at least in edk2 implementations, the lifetime of these handles will be till UEFI is active, i.e. 'static
Are there cases where a relevant handle here will disappear earlier that we need to worry about?
Add support for binding and accepting TCP4 connections.
While testing, the following network options were used with QEMU + OVMF: -nic user,hostfwd=tcp::12345-:12345
The default localhost address on qemu seems to be 10.0.2.15.
UEFI spec does not seem to state that the TCP Handle returned by the Accept method has a ServiceBinding Protocol. So have made the ServiceBinding Protocol optional.
cc @nicholasbishop