use super::{
fd::{tcp, Flags},
Protocol, Socket, TransportFeatures,
};
use crate::msg::{addr::Addr, cmsg};
use core::task::{Context, Poll};
use s2n_quic_core::{inet::ExplicitCongestionNotification, ready};
use std::{
io::{self, IoSlice, IoSliceMut},
net::SocketAddr,
};
use tokio::{io::Interest, net::TcpStream};
impl Socket for TcpStream {
#[inline]
fn local_addr(&self) -> io::Result<SocketAddr> {
(*self).local_addr()
}
#[inline]
fn protocol(&self) -> Protocol {
Protocol::Tcp
}
#[inline]
fn features(&self) -> TransportFeatures {
TransportFeatures::TCP
}
#[inline]
fn poll_peek_len(&self, cx: &mut Context) -> Poll<io::Result<usize>> {
loop {
ready!(self.poll_read_ready(cx))?;
let res = self.try_io(Interest::READABLE, || tcp::peek(self));
match res {
Ok(len) => return Ok(len).into(),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {
continue;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(err) => return Err(err).into(),
}
}
}
#[inline]
fn poll_recv(
&self,
cx: &mut Context,
_addr: &mut Addr,
cmsg: &mut cmsg::Receiver,
buffer: &mut [IoSliceMut],
) -> Poll<io::Result<usize>> {
loop {
ready!(self.poll_read_ready(cx))?;
let flags = Flags::default();
let res = self.try_io(Interest::READABLE, || tcp::recv(self, buffer, flags));
match res {
Ok(len) => {
cmsg.set_ecn(ExplicitCongestionNotification::NotEct);
cmsg.set_segment_len(0);
return Ok(len).into();
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {
continue;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(err) => return Err(err).into(),
}
}
}
#[inline]
fn try_send(
&self,
_addr: &Addr,
_ecn: ExplicitCongestionNotification,
buffer: &[IoSlice],
) -> io::Result<usize> {
loop {
match tcp::send(self, buffer) {
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {
continue;
}
res => return res,
}
}
}
#[inline]
fn poll_send(
&self,
cx: &mut Context,
_addr: &Addr,
_ecn: ExplicitCongestionNotification,
buffer: &[IoSlice],
) -> Poll<io::Result<usize>> {
loop {
ready!(self.poll_write_ready(cx))?;
let res = self.try_io(Interest::WRITABLE, || tcp::send(self, buffer));
match res {
Ok(len) => return Ok(len).into(),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {
continue;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(err) => return Err(err).into(),
}
}
}
#[inline]
fn send_finish(&self) -> io::Result<()> {
Ok(())
}
}