Skip to content

Commit 3f38c78

Browse files
Replace the macro in libp2p-tcp with a generic, inner implementation
To avoid code duplication, a generic inner implementation is used that does all of the heavy lifting. To abstract over the individual types, we create traits that are private to the module. Consumers of the crate shouldn't be concerned with this because a) none of the generic types are exported b) there are no type parameters in public interfaces
1 parent 2ea459d commit 3f38c78

File tree

6 files changed

+926
-636
lines changed

6 files changed

+926
-636
lines changed

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
//! [`Keypair`]: identity::Keypair
142142
//! [`PublicKey`]: identity::PublicKey
143143
//! [`Future`]: futures::Future
144-
//! [`TcpConfig`]: tcp::TcpConfig
144+
//! [`TcpConfig`]: tcp::async_std::TcpConfig
145145
//! [`NetworkBehaviour`]: swarm::NetworkBehaviour
146146
//! [`StreamMuxer`]: core::muxing::StreamMuxer
147147
//! [`Yamux`]: yamux::Yamux
@@ -282,7 +282,7 @@ struct CommonTransport {
282282
}
283283

284284
#[cfg(all(not(any(target_os = "emscripten", target_os = "unknown")), feature = "libp2p-websocket"))]
285-
type InnerImplementation = core::transport::OrTransport<dns::DnsConfig<tcp::TcpConfig>, websocket::WsConfig<dns::DnsConfig<tcp::TcpConfig>>>;
285+
type InnerImplementation = core::transport::OrTransport<dns::DnsConfig<tcp::async_std::TcpConfig>, websocket::WsConfig<dns::DnsConfig<tcp::async_std::TcpConfig>>>;
286286
#[cfg(all(not(any(target_os = "emscripten", target_os = "unknown")), not(feature = "libp2p-websocket")))]
287287
type InnerImplementation = dns::DnsConfig<tcp::TcpConfig>;
288288
#[cfg(any(target_os = "emscripten", target_os = "unknown"))]
@@ -297,7 +297,7 @@ impl CommonTransport {
297297
/// Initializes the `CommonTransport`.
298298
#[cfg(not(any(target_os = "emscripten", target_os = "unknown")))]
299299
pub fn new() -> io::Result<CommonTransport> {
300-
let tcp = tcp::TcpConfig::new().nodelay(true);
300+
let tcp = tcp::async_std::TcpConfig::new().nodelay(true);
301301
let transport = dns::DnsConfig::new(tcp)?;
302302
#[cfg(feature = "libp2p-websocket")]
303303
let transport = {

transports/tcp/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ipnet = "2.0.0"
1818
libp2p-core = { version = "0.16.0", path = "../../core" }
1919
log = "0.4.1"
2020
tokio = { version = "0.2", default-features = false, features = ["tcp"], optional = true }
21+
async-trait = "0.1"
2122

2223
[features]
2324
default = ["async-std"]

transports/tcp/src/async_std.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use crate::internal::{self, TcpListener, TcpStream, TcpTransStream};
2+
use futures::{AsyncRead, AsyncWrite};
3+
use libp2p_core::{transport::TransportError, Multiaddr, Transport};
4+
use std::{
5+
io,
6+
net::SocketAddr,
7+
pin::Pin,
8+
task::{Context, Poll},
9+
};
10+
11+
type AsyncStdConfig = internal::TcpConfig<async_std::net::TcpListener>;
12+
13+
/// Represents the configuration for a TCP/IP transport capability for libp2p.
14+
///
15+
/// This implementation uses the network futures from async_std.
16+
#[derive(Debug, Clone, Default)]
17+
pub struct TcpConfig {
18+
inner: AsyncStdConfig,
19+
}
20+
21+
impl TcpConfig {
22+
/// Creates a new configuration object for TCP/IP.
23+
pub fn new() -> Self {
24+
Self {
25+
inner: AsyncStdConfig::new(),
26+
}
27+
}
28+
29+
/// Sets the TTL to set for opened sockets.
30+
pub fn ttl(mut self, value: u32) -> Self {
31+
self.inner.ttl = Some(value);
32+
self
33+
}
34+
35+
/// Sets the `TCP_NODELAY` to set for opened sockets.
36+
pub fn nodelay(mut self, value: bool) -> Self {
37+
self.inner.nodelay = Some(value);
38+
self
39+
}
40+
}
41+
42+
impl Transport for TcpConfig {
43+
type Output = <AsyncStdConfig as Transport>::Output;
44+
type Error = <AsyncStdConfig as Transport>::Error;
45+
type Listener = <AsyncStdConfig as Transport>::Listener;
46+
type ListenerUpgrade = <AsyncStdConfig as Transport>::ListenerUpgrade;
47+
type Dial = <AsyncStdConfig as Transport>::Dial;
48+
49+
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
50+
self.inner.listen_on(addr)
51+
}
52+
53+
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
54+
self.inner.dial(addr)
55+
}
56+
}
57+
58+
#[async_trait::async_trait]
59+
impl TcpListener for async_std::net::TcpListener {
60+
type TcpStream = async_std::net::TcpStream;
61+
62+
async fn bind(addrs: &SocketAddr) -> io::Result<async_std::net::TcpListener> {
63+
async_std::net::TcpListener::bind(addrs).await
64+
}
65+
66+
async fn accept(&mut self) -> io::Result<(async_std::net::TcpStream, SocketAddr)> {
67+
async_std::net::TcpListener::accept(self).await
68+
}
69+
70+
fn local_addr(&self) -> io::Result<SocketAddr> {
71+
async_std::net::TcpListener::local_addr(self)
72+
}
73+
}
74+
75+
impl AsyncRead for TcpTransStream<async_std::net::TcpStream> {
76+
fn poll_read(
77+
mut self: Pin<&mut Self>,
78+
cx: &mut Context,
79+
buf: &mut [u8],
80+
) -> Poll<Result<usize, io::Error>> {
81+
AsyncRead::poll_read(Pin::new(&mut self.inner), cx, buf)
82+
}
83+
}
84+
85+
impl AsyncWrite for TcpTransStream<async_std::net::TcpStream> {
86+
fn poll_write(
87+
mut self: Pin<&mut Self>,
88+
cx: &mut Context,
89+
buf: &[u8],
90+
) -> Poll<Result<usize, io::Error>> {
91+
AsyncWrite::poll_write(Pin::new(&mut self.inner), cx, buf)
92+
}
93+
94+
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
95+
AsyncWrite::poll_flush(Pin::new(&mut self.inner), cx)
96+
}
97+
98+
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
99+
AsyncWrite::poll_close(Pin::new(&mut self.inner), cx)
100+
}
101+
}
102+
103+
#[async_trait::async_trait]
104+
impl TcpStream for async_std::net::TcpStream {
105+
async fn connect(addrs: &SocketAddr) -> io::Result<Self> {
106+
async_std::net::TcpStream::connect(addrs).await
107+
}
108+
fn set_ttl(&self, ttl: u32) -> io::Result<()> {
109+
async_std::net::TcpStream::set_ttl(self, ttl)
110+
}
111+
fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
112+
async_std::net::TcpStream::set_nodelay(self, nodelay)
113+
}
114+
fn peer_addr(&self) -> io::Result<SocketAddr> {
115+
async_std::net::TcpStream::peer_addr(self)
116+
}
117+
fn local_addr(&self) -> io::Result<SocketAddr> {
118+
async_std::net::TcpStream::local_addr(self)
119+
}
120+
}

0 commit comments

Comments
 (0)