Skip to content

Commit

Permalink
feat(network): allow using raw sockets
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed May 4, 2024
1 parent 1a150d4 commit ade68d3
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 17 deletions.
4 changes: 2 additions & 2 deletions network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ pub use dht::{
};
pub use network::{
ActivePeers, Connection, KnownPeerHandle, KnownPeers, KnownPeersError, Network, NetworkBuilder,
NetworkConfig, Peer, PeerBannedError, QuicConfig, RecvStream, SendStream, WeakActivePeers,
WeakKnownPeerHandle, WeakNetwork,
NetworkConfig, Peer, PeerBannedError, QuicConfig, RecvStream, SendStream, ToSocket,
WeakActivePeers, WeakKnownPeerHandle, WeakNetwork,
};
pub use types::{
service_datagram_fn, service_message_fn, service_query_fn, Address, BoxCloneService,
Expand Down
67 changes: 52 additions & 15 deletions network/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,11 @@ impl<T1> NetworkBuilder<(T1, ())> {
}

impl NetworkBuilder {
pub fn build<T: ToSocketAddrs, S>(self, bind_address: T, service: S) -> Result<Network>
pub fn build<T: ToSocket, S>(self, bind_address: T, service: S) -> Result<Network>
where
S: Send + Sync + Clone + 'static,
S: Service<ServiceRequest, QueryResponse = Response>,
{
use socket2::{Domain, Protocol, Socket, Type};

let config = self.optional_fields.config.unwrap_or_default();
let quic_config = config.quic.clone().unwrap_or_default();
let (service_name, private_key) = self.mandatory_fields;
Expand All @@ -98,18 +96,7 @@ impl NetworkBuilder {
.with_transport_config(quic_config.make_transport_config())
.build()?;

let socket = 'socket: {
let mut err = anyhow::anyhow!("no addresses to bind to");
for addr in bind_address.to_socket_addrs()? {
let s = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?;
if let Err(e) = s.bind(&socket2::SockAddr::from(addr)) {
err = e.into();
} else {
break 'socket s;
}
}
return Err(err);
};
let socket = bind_address.to_socket().map(socket2::Socket::from)?;

if let Some(send_buffer_size) = quic_config.socket_send_buffer_size {
if let Err(e) = socket.set_send_buffer_size(send_buffer_size) {
Expand Down Expand Up @@ -339,6 +326,56 @@ impl Drop for NetworkInner {
}
}

pub trait ToSocket {
fn to_socket(self) -> Result<std::net::UdpSocket>;
}

impl ToSocket for std::net::UdpSocket {
fn to_socket(self) -> Result<std::net::UdpSocket> {
Ok(self)
}
}

macro_rules! impl_to_socket_for_addr {
($($ty:ty),*$(,)?) => {$(
impl ToSocket for $ty {
fn to_socket(self) -> Result<std::net::UdpSocket> {
bind_socket_to_addr(self)
}
}
)*};
}

impl_to_socket_for_addr! {
SocketAddr,
std::net::SocketAddrV4,
std::net::SocketAddrV6,
(std::net::IpAddr, u16),
(std::net::Ipv4Addr, u16),
(std::net::Ipv6Addr, u16),
(&str, u16),
(String, u16),
&str,
String,
&[SocketAddr],
Address,
}

fn bind_socket_to_addr<T: ToSocketAddrs>(bind_address: T) -> Result<std::net::UdpSocket> {
use socket2::{Domain, Protocol, Socket, Type};

let mut err = anyhow::anyhow!("no addresses to bind to");
for addr in bind_address.to_socket_addrs()? {
let s = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?;
if let Err(e) = s.bind(&socket2::SockAddr::from(addr)) {
err = e.into();
} else {
return Ok(s.into());
}
}
return Err(err);
}

#[derive(thiserror::Error, Debug)]
#[error("network has been shutdown")]
struct NetworkShutdownError;
Expand Down

0 comments on commit ade68d3

Please sign in to comment.