tcp.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{io, sync::Arc, time::Duration};
  19. use async_trait::async_trait;
  20. use futures::{
  21. future::{select, Either},
  22. pin_mut,
  23. };
  24. use futures_rustls::{TlsAcceptor, TlsStream};
  25. use smol::{
  26. lock::OnceCell,
  27. net::{SocketAddr, TcpListener as SmolTcpListener, TcpStream},
  28. Async, Timer,
  29. };
  30. use socket2::{Domain, Socket, TcpKeepalive, Type};
  31. use tracing::debug;
  32. use url::Url;
  33. use super::{PtListener, PtNegotiation, PtStream};
  34. trait SocketExt {
  35. fn enable_reuse_port(&self) -> io::Result<()>;
  36. }
  37. impl SocketExt for Socket {
  38. fn enable_reuse_port(&self) -> io::Result<()> {
  39. #[cfg(target_family = "unix")]
  40. self.set_reuse_port(true)?;
  41. // On Windows SO_REUSEPORT means the same thing as SO_REUSEADDR
  42. #[cfg(target_family = "windows")]
  43. self.set_reuse_address(true)?;
  44. Ok(())
  45. }
  46. }
  47. /// TCP Dialer implementation
  48. #[derive(Debug, Clone)]
  49. pub struct TcpDialer {
  50. /// TTL to set for opened sockets, or `None` for default.
  51. ttl: Option<u32>,
  52. }
  53. impl TcpDialer {
  54. /// Instantiate a new [`TcpDialer`] with optional TTL.
  55. pub(crate) async fn new(ttl: Option<u32>) -> io::Result<Self> {
  56. Ok(Self { ttl })
  57. }
  58. /// Internal helper function to create a TCP socket.
  59. async fn create_socket(&self, socket_addr: SocketAddr) -> io::Result<Socket> {
  60. let domain = if socket_addr.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 };
  61. let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?;
  62. if socket_addr.is_ipv6() {
  63. socket.set_only_v6(true)?;
  64. }
  65. if let Some(ttl) = self.ttl {
  66. socket.set_ttl_v4(ttl)?;
  67. }
  68. socket.set_tcp_nodelay(true)?;
  69. let keepalive = TcpKeepalive::new().with_time(Duration::from_secs(20));
  70. socket.set_tcp_keepalive(&keepalive)?;
  71. socket.enable_reuse_port()?;
  72. Ok(socket)
  73. }
  74. /// Internal dial function
  75. pub(crate) async fn do_dial(
  76. &self,
  77. socket_addr: SocketAddr,
  78. timeout: Option<Duration>,
  79. ) -> io::Result<TcpStream> {
  80. debug!(target: "net::tcp::do_dial", "Dialing {socket_addr} with TCP...");
  81. let socket = self.create_socket(socket_addr).await?;
  82. socket.set_nonblocking(true)?;
  83. // Sync start socket connect. A WouldBlock error means this
  84. // connection is in progress.
  85. match socket.connect(&socket_addr.into()) {
  86. Ok(()) => {}
  87. Err(err) if err.raw_os_error() == Some(libc::EINPROGRESS) => {}
  88. Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
  89. Err(err) => return Err(err),
  90. };
  91. let stream = Async::new_nonblocking(std::net::TcpStream::from(socket))?;
  92. // Wait until the async object becomes writable.
  93. let connect = async move {
  94. stream.writable().await?;
  95. match stream.get_ref().take_error()? {
  96. Some(err) => Err(err),
  97. None => Ok(stream),
  98. }
  99. };
  100. // If a timeout is configured, run both the connect and timeout
  101. // futures and return whatever finishes first. Otherwise wait on
  102. // the connect future.
  103. match timeout {
  104. Some(t) => {
  105. let timeout = Timer::after(t);
  106. pin_mut!(timeout);
  107. pin_mut!(connect);
  108. match select(connect, timeout).await {
  109. Either::Left((Ok(stream), _)) => Ok(TcpStream::from(stream)),
  110. Either::Left((Err(e), _)) => Err(e),
  111. Either::Right((_, _)) => Err(io::ErrorKind::TimedOut.into()),
  112. }
  113. }
  114. None => {
  115. let stream = connect.await?;
  116. Ok(TcpStream::from(stream))
  117. }
  118. }
  119. }
  120. }
  121. /// TCP Listener implementation
  122. #[derive(Debug, Clone)]
  123. pub struct TcpListener {
  124. /// Size of the listen backlog for listen sockets
  125. backlog: i32,
  126. /// When the user puts a port of 0, the OS will assign a random port.
  127. /// We get it from the listener so we know what the true endpoint is.
  128. pub port: Arc<OnceCell<u16>>,
  129. }
  130. impl TcpListener {
  131. /// Instantiate a new [`TcpListener`] with given backlog size.
  132. pub async fn new(backlog: i32) -> io::Result<Self> {
  133. Ok(Self { backlog, port: Arc::new(OnceCell::new()) })
  134. }
  135. /// Internal helper function to create a TCP socket.
  136. async fn create_socket(&self, socket_addr: SocketAddr) -> io::Result<Socket> {
  137. let domain = if socket_addr.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 };
  138. let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?;
  139. if socket_addr.is_ipv6() {
  140. socket.set_only_v6(true)?;
  141. }
  142. socket.set_tcp_nodelay(true)?;
  143. let keepalive = TcpKeepalive::new().with_time(Duration::from_secs(20));
  144. socket.set_tcp_keepalive(&keepalive)?;
  145. socket.enable_reuse_port()?;
  146. Ok(socket)
  147. }
  148. /// Internal listen function
  149. pub(crate) async fn do_listen(&self, socket_addr: SocketAddr) -> io::Result<SmolTcpListener> {
  150. let socket = self.create_socket(socket_addr).await?;
  151. socket.bind(&socket_addr.into())?;
  152. socket.listen(self.backlog)?;
  153. socket.set_nonblocking(true)?;
  154. let listener = std::net::TcpListener::from(socket);
  155. let local_port = listener.local_addr()?.port();
  156. let listener = smol::Async::<std::net::TcpListener>::try_from(listener)?;
  157. self.port.set(local_port).await.expect("fatal port already set for TcpListener");
  158. Ok(SmolTcpListener::from(listener))
  159. }
  160. }
  161. #[async_trait]
  162. impl PtListener for SmolTcpListener {
  163. async fn next(&self) -> io::Result<PtNegotiation> {
  164. let (stream, peer_addr) = match self.accept().await {
  165. Ok((s, a)) => (s, a),
  166. Err(e) => return Err(e),
  167. };
  168. let url = match Url::parse(&format!("tcp://{peer_addr}")) {
  169. Ok(v) => v,
  170. Err(e) => {
  171. return Err(io::Error::new(
  172. io::ErrorKind::InvalidData,
  173. format!("Invalid peer address '{peer_addr}': {e}"),
  174. ))
  175. }
  176. };
  177. Ok(Box::pin(async move { Ok((Box::new(stream) as Box<dyn PtStream>, url)) }))
  178. }
  179. }
  180. #[async_trait]
  181. impl PtListener for (TlsAcceptor, SmolTcpListener) {
  182. async fn next(&self) -> io::Result<PtNegotiation> {
  183. let (stream, peer_addr) = match self.1.accept().await {
  184. Ok((s, a)) => (s, a),
  185. Err(e) => return Err(e),
  186. };
  187. let url = match Url::parse(&format!("tcp+tls://{peer_addr}")) {
  188. Ok(v) => v,
  189. Err(e) => {
  190. return Err(io::Error::new(
  191. io::ErrorKind::InvalidData,
  192. format!("Invalid peer address '{peer_addr}': {e}"),
  193. ))
  194. }
  195. };
  196. let acceptor = self.0.clone();
  197. Ok(Box::pin(async move {
  198. let stream = acceptor.accept(stream).await?;
  199. Ok((Box::new(TlsStream::Server(stream)) as Box<dyn PtStream>, url))
  200. }))
  201. }
  202. }