Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions library/std/src/sys/net/connection/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ pub struct TcpStream {
}

impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
let inner = tcp::Tcp::connect(addr?, None)?;
Ok(Self {
fn new(inner: tcp::Tcp) -> Self {
Self {
inner,
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
})
}
}

pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
let inner = tcp::Tcp::connect(addr?, None)?;
Ok(Self::new(inner))
}

pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
let inner = tcp::Tcp::connect(addr, Some(timeout))?;
Ok(Self {
inner,
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
})
Ok(Self::new(inner))
}

pub fn set_read_timeout(&self, t: Option<Duration>) -> io::Result<()> {
Expand Down Expand Up @@ -145,16 +145,19 @@ pub struct TcpListener {
}

impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
unsupported()
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
let inner = tcp::Tcp::bind(addr?)?;
Ok(Self { inner })
}

pub fn socket_addr(&self) -> io::Result<SocketAddr> {
unsupported()
self.inner.socket_addr()
}

pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
unsupported()
let tcp = self.inner.accept()?;
let addr = tcp.peer_addr()?;
Ok((TcpStream::new(tcp), addr))
}

pub fn duplicate(&self) -> io::Result<TcpListener> {
Expand Down
19 changes: 18 additions & 1 deletion library/std/src/sys/net/connection/uefi/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,24 @@ impl Tcp {
temp.connect(timeout)?;
Ok(Tcp::V4(temp))
}
SocketAddr::V6(_) => todo!(),
SocketAddr::V6(_) => unsupported(),
}
}

pub(crate) fn bind(addr: &SocketAddr) -> io::Result<Self> {
match addr {
SocketAddr::V4(x) => {
let temp = tcp4::Tcp4::new()?;
temp.configure(false, None, Some(x))?;
Ok(Tcp::V4(temp))
}
SocketAddr::V6(_) => unsupported(),
}
}

pub(crate) fn accept(&self) -> io::Result<Self> {
match self {
Self::V4(client) => client.accept().map(Tcp::V4),
}
}

Expand Down
43 changes: 36 additions & 7 deletions library/std/src/sys/net/connection/uefi/tcp4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) struct Tcp4 {
protocol: NonNull<tcp4::Protocol>,
flag: AtomicBool,
#[expect(dead_code)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this lint still fire?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, just tested

service_binding: helpers::ServiceProtocol,
service_binding: Option<helpers::ServiceProtocol>,
}

const DEFAULT_ADDR: efi::Ipv4Address = efi::Ipv4Address { addr: [0u8; 4] };
Expand All @@ -25,7 +25,7 @@ impl Tcp4 {
let service_binding = helpers::ServiceProtocol::open(tcp4::SERVICE_BINDING_PROTOCOL_GUID)?;
let protocol = helpers::open_protocol(service_binding.child_handle(), tcp4::PROTOCOL_GUID)?;

Ok(Self { service_binding, protocol, flag: AtomicBool::new(false) })
Ok(Self { service_binding: Some(service_binding), protocol, flag: AtomicBool::new(false) })
}

pub(crate) fn configure(
Expand All @@ -42,11 +42,13 @@ impl Tcp4 {
(DEFAULT_ADDR, 0)
};

// FIXME: Remove when passive connections with proper subnet handling are added
assert!(station_address.is_none());
let use_default_address = efi::Boolean::TRUE;
let (station_address, station_port) = (DEFAULT_ADDR, 0);
let subnet_mask = helpers::ipv4_to_r_efi(crate::net::Ipv4Addr::new(0, 0, 0, 0));
let use_default_address = station_address.is_none().into();
let (station_address, station_port) = if let Some(x) = station_address {
(helpers::ipv4_to_r_efi(*x.ip()), x.port())
} else {
(DEFAULT_ADDR, 0)
};
let subnet_mask = helpers::ipv4_to_r_efi(crate::net::Ipv4Addr::new(255, 255, 255, 0));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a breaking change? If the mask was previously 0.0.0.0 (all addresses), it seems like this may surprise some users

Worth a comment in any case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is not a breaking change. That is because the docs state the following: Not used when UseDefaultAddress is TRUE.

And previously, UseDefaultAddress was always true.


let mut config_data = tcp4::ConfigData {
type_of_service: TYPE_OF_SERVICE,
Expand Down Expand Up @@ -85,6 +87,33 @@ impl Tcp4 {
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(config_data) }
}

pub(crate) fn accept(&self) -> io::Result<Self> {
let evt = unsafe { self.create_evt() }?;
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() };

let protocol = self.protocol.as_ptr();
let r = unsafe { ((*protocol).accept)(protocol, &mut listen_token) };
if r.is_error() {
return Err(io::Error::from_raw_os_error(r.as_usize()));
}

unsafe { self.wait_or_cancel(None, &mut listen_token.completion_token) }?;

if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
} else {
let handle = NonNull::new(listen_token.new_child_handle).unwrap();
let protocol = helpers::open_protocol(handle, tcp4::PROTOCOL_GUID)?;

// The spec does not seem to state if we need to call ServiceBinding->DestroyChild for
// this handle
Comment on lines +111 to +112
Copy link
Contributor

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?

Ok(Self { service_binding: None, protocol, flag: AtomicBool::new(false) })
}
}

pub(crate) fn connect(&self, timeout: Option<Duration>) -> io::Result<()> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
Expand Down
Loading