refactor checkpoint

This commit is contained in:
John Smith
2022-04-16 11:18:54 -04:00
parent ddb74d993f
commit 71f7017235
23 changed files with 977 additions and 615 deletions

View File

@@ -66,6 +66,7 @@ struct NetworkUnlockedInner {
// Background processes
update_udpv4_dialinfo_task: TickTask,
update_tcpv4_dialinfo_task: TickTask,
update_wsv4_dialinfo_task: TickTask,
}
#[derive(Clone)]
@@ -107,6 +108,7 @@ impl Network {
NetworkUnlockedInner {
update_udpv4_dialinfo_task: TickTask::new(1),
update_tcpv4_dialinfo_task: TickTask::new(1),
update_wsv4_dialinfo_task: TickTask::new(1),
}
}
@@ -135,6 +137,15 @@ impl Network {
Box::pin(this2.clone().update_tcpv4_dialinfo_task_routine(l, t))
});
}
// Set ws dialinfo tick task
{
let this2 = this.clone();
this.unlocked_inner
.update_wsv4_dialinfo_task
.set_routine(move |l, t| {
Box::pin(this2.clone().update_wsv4_dialinfo_task_routine(l, t))
});
}
this
}
@@ -289,7 +300,7 @@ impl Network {
res
}
async fn send_data_to_existing_connection(
pub async fn send_data_to_existing_connection(
&self,
descriptor: ConnectionDescriptor,
data: Vec<u8>,
@@ -380,41 +391,6 @@ impl Network {
res
}
// Send data to node
// We may not have dial info for a node, but have an existing connection for it
// because an inbound connection happened first, and no FindNodeQ has happened to that
// node yet to discover its dial info. The existing connection should be tried first
// in this case.
pub async fn send_data(&self, node_ref: NodeRef, data: Vec<u8>) -> Result<(), String> {
// First try to send data to the last socket we've seen this peer on
let data = if let Some(descriptor) = node_ref.last_connection() {
match self
.clone()
.send_data_to_existing_connection(descriptor, data)
.await
.map_err(logthru_net!())?
{
None => {
return Ok(());
}
Some(d) => d,
}
} else {
data
};
// If that fails, try to make a connection or reach out to the peer via its dial info
let node_info = node_ref
.best_node_info()
.ok_or_else(|| "couldn't send data, no dial info or peer address".to_owned())?;
xxx write logic to determine if a relay needs to be used first xxx
self.send_data_to_dial_info(dial_info, data)
.await
.map_err(logthru_net!())
}
/////////////////////////////////////////////////////////////////
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
@@ -433,28 +409,33 @@ impl Network {
let protocol_config = {
let c = self.config.get();
ProtocolConfig {
udp_enabled: c.network.protocol.udp.enabled && c.capabilities.protocol_udp,
tcp_connect: c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp,
tcp_listen: c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp,
ws_connect: c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws,
ws_listen: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws,
wss_connect: c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss,
wss_listen: c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss,
inbound: ProtocolSet {
udp: c.network.protocol.udp.enabled && c.capabilities.protocol_udp,
tcp: c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp,
ws: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws,
wss: c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss,
},
outbound: ProtocolSet {
udp: c.network.protocol.udp.enabled && c.capabilities.protocol_udp,
tcp: c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp,
ws: c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws,
wss: c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss,
},
}
};
self.inner.lock().protocol_config = Some(protocol_config);
// start listeners
if protocol_config.udp_enabled {
if protocol_config.inbound.udp {
self.start_udp_listeners().await?;
}
if protocol_config.ws_listen {
if protocol_config.inbound.ws {
self.start_ws_listeners().await?;
}
if protocol_config.wss_listen {
if protocol_config.inbound.wss {
self.start_wss_listeners().await?;
}
if protocol_config.tcp_listen {
if protocol_config.inbound.tcp {
self.start_tcp_listeners().await?;
}
@@ -503,7 +484,7 @@ impl Network {
// Go through our global dialinfo and see what our best network class is
let mut network_class = NetworkClass::Invalid;
for did in inner.routing_table.global_dial_info_details() {
for did in inner.routing_table.public_dial_info_details() {
if let Some(nc) = did.network_class {
if nc < network_class {
network_class = nc;
@@ -521,6 +502,7 @@ impl Network {
protocol_config,
udp_static_public_dialinfo,
tcp_static_public_dialinfo,
ws_static_public_dialinfo,
network_class,
) = {
let inner = self.inner.lock();
@@ -529,6 +511,7 @@ impl Network {
inner.protocol_config.unwrap_or_default(),
inner.udp_static_public_dialinfo,
inner.tcp_static_public_dialinfo,
inner.ws_static_public_dialinfo,
inner.network_class.unwrap_or(NetworkClass::Invalid),
)
};
@@ -538,15 +521,15 @@ impl Network {
// If we can have public dialinfo, or we haven't figured out our network class yet,
// and we're active for UDP, we should attempt to get our public dialinfo sorted out
// and assess our network class if we haven't already
if protocol_config.udp_enabled
if protocol_config.inbound.udp
&& !udp_static_public_dialinfo
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
{
let filter = DialInfoFilter::global()
let filter = DialInfoFilter::all()
.with_protocol_type(ProtocolType::UDP)
.with_address_type(AddressType::IPV4);
let need_udpv4_dialinfo = routing_table
.first_filtered_dial_info_detail(&filter)
.first_public_filtered_dial_info_detail(&filter)
.is_none();
if need_udpv4_dialinfo {
// If we have no public UDPv4 dialinfo, then we need to run a NAT check
@@ -559,15 +542,15 @@ impl Network {
}
// Same but for TCPv4
if protocol_config.tcp_listen
if protocol_config.inbound.tcp
&& !tcp_static_public_dialinfo
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
{
let filter = DialInfoFilter::global()
let filter = DialInfoFilter::all()
.with_protocol_type(ProtocolType::TCP)
.with_address_type(AddressType::IPV4);
let need_tcpv4_dialinfo = routing_table
.first_filtered_dial_info_detail(&filter)
.first_public_filtered_dial_info_detail(&filter)
.is_none();
if need_tcpv4_dialinfo {
// If we have no public TCPv4 dialinfo, then we need to run a NAT check
@@ -579,6 +562,24 @@ impl Network {
}
}
// Same but for WSv4
if protocol_config.inbound.ws
&& !ws_static_public_dialinfo
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
{
let filter = DialInfoFilter::all()
.with_protocol_type(ProtocolType::WS)
.with_address_type(AddressType::IPV4);
let need_wsv4_dialinfo = routing_table
.first_public_filtered_dial_info_detail(&filter)
.is_none();
if need_wsv4_dialinfo {
// If we have no public TCPv4 dialinfo, then we need to run a NAT check
// ensure the singlefuture is running for this
self.unlocked_inner.update_wsv4_dialinfo_task.tick().await?;
}
}
Ok(())
}
}

View File

@@ -227,7 +227,7 @@ impl Network {
for ip_addr in ip_addrs {
let addr = SocketAddr::new(ip_addr, port);
let ldi_addrs = Self::translate_unspecified_address(&*(self.inner.lock()), &addr);
let idi_addrs = Self::translate_unspecified_address(&*(self.inner.lock()), &addr);
// see if we've already bound to this already
// if not, spawn a listener
@@ -262,9 +262,9 @@ impl Network {
));
}
// Return local dial infos we listen on
for ldi_addr in ldi_addrs {
out.push(SocketAddress::from_socket_addr(ldi_addr));
// Return interface dial infos we listen on
for idi_addr in idi_addrs {
out.push(SocketAddress::from_socket_addr(idi_addr));
}
}

View File

@@ -173,13 +173,13 @@ impl Network {
.inbound_udp_protocol_handlers
.contains_key(&addr)
{
let ldi_addrs = Self::translate_unspecified_address(&*self.inner.lock(), &addr);
let idi_addrs = Self::translate_unspecified_address(&*self.inner.lock(), &addr);
self.clone().create_udp_inbound_socket(addr).await?;
// Return local dial infos we listen on
for ldi_addr in ldi_addrs {
out.push(DialInfo::udp_from_socketaddr(ldi_addr));
// Return interface dial infos we listen on
for idi_addr in idi_addrs {
out.push(DialInfo::udp_from_socketaddr(idi_addr));
}
}
}

View File

@@ -60,9 +60,15 @@ impl Network {
.with_protocol_type(protocol_type)
.with_address_type(address_type);
routing_table
.all_filtered_dial_info_details(&filter)
.interface_dial_info_details()
.iter()
.map(|did| did.dial_info.socket_address())
.filter_map(|did| {
if did.dial_info.matches_filter(&filter) {
Some(did.dial_info.socket_address())
} else {
None
}
})
.collect()
}
@@ -130,7 +136,7 @@ impl Network {
.await
{
// Add public dial info with Server network class
routing_table.register_dial_info(
routing_table.register_public_dial_info(
external1_dial_info,
DialInfoOrigin::Discovered,
Some(NetworkClass::Server),
@@ -151,7 +157,7 @@ impl Network {
{
// Got a port mapping, let's use it
let external_mapped_dial_info = DialInfo::udp(external_mapped);
routing_table.register_dial_info(
routing_table.register_public_dial_info(
external_mapped_dial_info,
DialInfoOrigin::Mapped,
Some(NetworkClass::Mapped),
@@ -174,7 +180,7 @@ impl Network {
{
// Yes, another machine can use the dial info directly, so Full Cone
// Add public dial info with full cone NAT network class
routing_table.register_dial_info(
routing_table.register_public_dial_info(
external1_dial_info,
DialInfoOrigin::Discovered,
Some(NetworkClass::FullConeNAT),
@@ -224,14 +230,14 @@ impl Network {
.await
{
// Got a reply from a non-default port, which means we're only address restricted
routing_table.register_dial_info(
routing_table.register_public_dial_info(
external1_dial_info,
DialInfoOrigin::Discovered,
Some(NetworkClass::AddressRestrictedNAT),
);
} else {
// Didn't get a reply from a non-default port, which means we are also port restricted
routing_table.register_dial_info(
routing_table.register_public_dial_info(
external1_dial_info,
DialInfoOrigin::Discovered,
Some(NetworkClass::PortRestrictedNAT),
@@ -258,4 +264,11 @@ impl Network {
//Err("unimplemented".to_owned())
Ok(())
}
pub async fn update_wsv4_dialinfo_task_routine(self, _l: u64, _t: u64) -> Result<(), String> {
log_net!("looking for wsv4 public dial info");
// xxx
//Err("unimplemented".to_owned())
Ok(())
}
}

View File

@@ -287,22 +287,23 @@ impl Network {
"UDP: starting listeners on port {} at {:?}",
udp_port, ip_addrs
);
let dial_infos = self.create_udp_inbound_sockets(ip_addrs, udp_port).await?;
let dial_info_list = self.create_udp_inbound_sockets(ip_addrs, udp_port).await?;
let mut static_public = false;
for di in &dial_infos {
// Register local dial info only here if we specify a public address
for di in &dial_info_list {
// If the local interface address is global,
// register global dial info if no public address is specified
if public_address.is_none() && di.is_global() {
// Register global dial info if no public address is specified
routing_table.register_dial_info(
routing_table.register_public_dial_info(
di.clone(),
DialInfoOrigin::Static,
Some(NetworkClass::Server),
);
static_public = true;
} else if di.is_local() {
// Register local dial info
routing_table.register_dial_info(di.clone(), DialInfoOrigin::Static, None);
}
// Register interface dial info as well since the address is on the local interface
routing_table.register_interface_dial_info(di.clone(), DialInfoOrigin::Static);
}
// Add static public dialinfo if it's configured
@@ -315,7 +316,7 @@ impl Network {
// Add all resolved addresses as public dialinfo
for pdi_addr in &mut public_sockaddrs {
routing_table.register_dial_info(
routing_table.register_public_dial_info(
DialInfo::udp_from_socketaddr(pdi_addr),
DialInfoOrigin::Static,
Some(NetworkClass::Server),
@@ -375,22 +376,21 @@ impl Network {
let di = DialInfo::try_ws(socket_address, global_url)
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
routing_table.register_dial_info(
routing_table.register_public_dial_info(
di,
DialInfoOrigin::Static,
Some(NetworkClass::Server),
);
static_public = true;
} else if socket_address.address().is_local() {
// Build local dial info request url
let local_url = format!("ws://{}/{}", socket_address, path);
// Create local dial info
let di = DialInfo::try_ws(socket_address, local_url)
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
routing_table.register_dial_info(di, DialInfoOrigin::Static, None);
}
// Build interface dial info request url
let interface_url = format!("ws://{}/{}", socket_address, path);
// Create interface dial info
let di = DialInfo::try_ws(socket_address, interface_url)
.map_err(map_to_string)
.map_err(logthru_net!(error))?;
routing_table.register_interface_dial_info(di, DialInfoOrigin::Static);
}
// Add static public dialinfo if it's configured
@@ -410,7 +410,7 @@ impl Network {
.map_err(logthru_net!(error))?;
for gsa in global_socket_addrs {
routing_table.register_dial_info(
routing_table.register_public_dial_info(
DialInfo::try_ws(SocketAddress::from_socket_addr(gsa), url.clone())
.map_err(map_to_string)
.map_err(logthru_net!(error))?,
@@ -460,7 +460,7 @@ impl Network {
.await?;
trace!("WSS: listener started");
// NOTE: No local dial info for WSS, as there is no way to connect to a local dialinfo via TLS
// NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS
// If the hostname is specified, it is the public dialinfo via the URL. If no hostname
// is specified, then TLS won't validate, so no local dialinfo is possible.
// This is not the case with unencrypted websockets, which can be specified solely by an IP address
@@ -483,7 +483,7 @@ impl Network {
.map_err(logthru_net!(error))?;
for gsa in global_socket_addrs {
routing_table.register_dial_info(
routing_table.register_public_dial_info(
DialInfo::try_wss(SocketAddress::from_socket_addr(gsa), url.clone())
.map_err(map_to_string)
.map_err(logthru_net!(error))?,
@@ -537,19 +537,17 @@ impl Network {
for socket_address in socket_addresses {
let di = DialInfo::tcp(socket_address);
// Register local dial info only here if we specify a public address
// Register global dial info if no public address is specified
if public_address.is_none() && di.is_global() {
// Register global dial info if no public address is specified
routing_table.register_dial_info(
routing_table.register_public_dial_info(
di.clone(),
DialInfoOrigin::Static,
Some(NetworkClass::Server),
);
static_public = true;
} else if di.is_local() {
// Register local dial info
routing_table.register_dial_info(di.clone(), DialInfoOrigin::Static, None);
}
// Register interface dial info
routing_table.register_interface_dial_info(di.clone(), DialInfoOrigin::Static);
}
// Add static public dialinfo if it's configured
@@ -562,7 +560,7 @@ impl Network {
// Add all resolved addresses as public dialinfo
for pdi_addr in &mut public_sockaddrs {
routing_table.register_dial_info(
routing_table.register_public_dial_info(
DialInfo::tcp_from_socketaddr(pdi_addr),
DialInfoOrigin::Static,
None,

View File

@@ -75,7 +75,7 @@ impl Network {
res
}
async fn send_data_to_existing_connection(
pub async fn send_data_to_existing_connection(
&self,
descriptor: ConnectionDescriptor,
data: Vec<u8>,
@@ -137,31 +137,6 @@ impl Network {
res
}
pub async fn send_data(&self, node_ref: NodeRef, data: Vec<u8>) -> Result<(), String> {
// First try to send data to the last socket we've seen this peer on
let data = if let Some(descriptor) = node_ref.last_connection() {
match self
.clone()
.send_data_to_existing_connection(descriptor, data)
.await?
{
None => {
return Ok(());
}
Some(d) => d,
}
} else {
data
};
// If that fails, try to make a connection or reach out to the peer via its dial info
let dial_info = node_ref
.best_dial_info()
.ok_or_else(|| "couldn't send data, no dial info or peer address".to_owned())?;
self.send_data_to_dial_info(dial_info, data).await
}
/////////////////////////////////////////////////////////////////
pub async fn startup(&self) -> Result<(), String> {