refactor checkpoint
This commit is contained in:
parent
ddb74d993f
commit
71f7017235
@ -50,16 +50,16 @@ def tee(prefix, infile, *files):
|
|||||||
return t
|
return t
|
||||||
|
|
||||||
|
|
||||||
def read_until_local_dial_info(proc, proto):
|
def read_until_interface_dial_info(proc, proto):
|
||||||
|
|
||||||
local_dial_info_str = b"Local Dial Info: "
|
interface_dial_info_str = b"Interface Dial Info: "
|
||||||
for ln in iter(proc.stdout.readline, ""):
|
for ln in iter(proc.stdout.readline, ""):
|
||||||
sys.stdout.buffer.write(ln)
|
sys.stdout.buffer.write(ln)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
idx = ln.find(local_dial_info_str)
|
idx = ln.find(interface_dial_info_str)
|
||||||
if idx != -1:
|
if idx != -1:
|
||||||
idx += len(local_dial_info_str)
|
idx += len(interface_dial_info_str)
|
||||||
di = ln[idx:]
|
di = ln[idx:]
|
||||||
if b"@"+bytes(proto)+b"|" in di:
|
if b"@"+bytes(proto)+b"|" in di:
|
||||||
return di.decode("utf-8").strip()
|
return di.decode("utf-8").strip()
|
||||||
@ -130,7 +130,7 @@ def main():
|
|||||||
main_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
main_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
print(">>> MAIN NODE PID={}".format(main_proc.pid))
|
print(">>> MAIN NODE PID={}".format(main_proc.pid))
|
||||||
|
|
||||||
main_di = read_until_local_dial_info(
|
main_di = read_until_interface_dial_info(
|
||||||
main_proc, bytes(args.protocol, 'utf-8'))
|
main_proc, bytes(args.protocol, 'utf-8'))
|
||||||
|
|
||||||
print(">>> MAIN DIAL INFO={}".format(main_di))
|
print(">>> MAIN DIAL INFO={}".format(main_di))
|
||||||
|
@ -107,6 +107,19 @@ struct NodeDialInfo {
|
|||||||
dialInfo @1 :DialInfo; # how to get to the node
|
dialInfo @1 :DialInfo; # how to get to the node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Signals
|
||||||
|
##############################
|
||||||
|
|
||||||
|
struct SignalInfoHolePunch {
|
||||||
|
receipt @0 :Data; # receipt to return with hole punch
|
||||||
|
nodeInfo @1 :NodeInfo; # node info of the signal sender for hole punch attempt
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SignalInfoReverseConnect {
|
||||||
|
receipt @0 :Data; # receipt to return with reverse connect
|
||||||
|
nodeInfo @1 :NodeInfo; # node info of the signal sender for reverse connect attempt
|
||||||
|
}
|
||||||
|
|
||||||
# Private Routes
|
# Private Routes
|
||||||
##############################
|
##############################
|
||||||
|
|
||||||
@ -186,10 +199,18 @@ struct NodeStatus {
|
|||||||
willValidateDialInfo @4 :Bool;
|
willValidateDialInfo @4 :Bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ProtocolSet {
|
||||||
|
udp @0 :Bool;
|
||||||
|
tcp @1 :Bool;
|
||||||
|
ws @2 :Bool;
|
||||||
|
wss @3 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo {
|
||||||
networkClass @0 :NetworkClass; # network class of this node
|
networkClass @0 :NetworkClass; # network class of this node
|
||||||
dialInfoList @1 :List(DialInfo); # dial info for this node
|
outboundProtocols @1 :ProtocolSet; # protocols that can go outbound
|
||||||
relayDialInfoList @2 :List(DialInfo); # relay dial info for this node
|
dialInfoList @2 :List(DialInfo); # inbound dial info for this node
|
||||||
|
relayPeerInfo @3 :PeerInfo; # (optional) relay peer info for this node
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SenderInfo {
|
struct SenderInfo {
|
||||||
@ -214,8 +235,7 @@ struct OperationReturnReceipt {
|
|||||||
|
|
||||||
struct OperationFindNodeQ {
|
struct OperationFindNodeQ {
|
||||||
nodeId @0 :NodeID; # node id to locate
|
nodeId @0 :NodeID; # node id to locate
|
||||||
dialInfoList @1 :List(DialInfo); # dial info for the node asking the question
|
senderNodeInfo @1 :NodeInfo; # dial info for the node asking the question
|
||||||
relayDialInfoList @2 :List(DialInfo); # relay dial info for the node asking the question
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfo {
|
struct PeerInfo {
|
||||||
@ -297,12 +317,11 @@ struct OperationFindBlockA {
|
|||||||
peers @2 :List(PeerInfo); # returned 'closer peer' information
|
peers @2 :List(PeerInfo); # returned 'closer peer' information
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OperationSignalQ {
|
struct OperationSignal {
|
||||||
data @0 :Data; # the signalling system request
|
union {
|
||||||
}
|
holePunch @0 :SignalInfoHolePunch;
|
||||||
|
reverseConnect @1 :SignalInfoReverseConnect;
|
||||||
struct OperationSignalA {
|
}
|
||||||
data @0 :Data; # the signalling system response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TunnelEndpointMode {
|
enum TunnelEndpointMode {
|
||||||
@ -318,9 +337,8 @@ enum TunnelError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TunnelEndpoint {
|
struct TunnelEndpoint {
|
||||||
nodeId @0 :NodeID; # node id
|
mode @0 :TunnelEndpointMode; # what kind of endpoint this is
|
||||||
dialInfoList @1 :List(DialInfo); # how to reach the node
|
peerInfo @1 :PeerInfo; # node id and dialinfo
|
||||||
mode @2 :TunnelEndpointMode; # what kind of endpoint this is
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FullTunnel {
|
struct FullTunnel {
|
||||||
@ -406,17 +424,15 @@ struct Operation {
|
|||||||
findBlockQ @19 :OperationFindBlockQ;
|
findBlockQ @19 :OperationFindBlockQ;
|
||||||
findBlockA @20 :OperationFindBlockA;
|
findBlockA @20 :OperationFindBlockA;
|
||||||
|
|
||||||
signalQ @21 :OperationSignalQ;
|
signal @21 :OperationSignal;
|
||||||
signalA @22 :OperationSignalA;
|
returnReceipt @22 :OperationReturnReceipt;
|
||||||
|
|
||||||
returnReceipt @23 :OperationReturnReceipt;
|
|
||||||
|
|
||||||
# Tunnel operations
|
# Tunnel operations
|
||||||
startTunnelQ @24 :OperationStartTunnelQ;
|
startTunnelQ @23 :OperationStartTunnelQ;
|
||||||
startTunnelA @25 :OperationStartTunnelA;
|
startTunnelA @24 :OperationStartTunnelA;
|
||||||
completeTunnelQ @26 :OperationCompleteTunnelQ;
|
completeTunnelQ @25 :OperationCompleteTunnelQ;
|
||||||
completeTunnelA @27 :OperationCompleteTunnelA;
|
completeTunnelA @26 :OperationCompleteTunnelA;
|
||||||
cancelTunnelQ @28 :OperationCancelTunnelQ;
|
cancelTunnelQ @27 :OperationCancelTunnelQ;
|
||||||
cancelTunnelA @29 :OperationCancelTunnelA;
|
cancelTunnelA @28 :OperationCancelTunnelA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ struct NetworkUnlockedInner {
|
|||||||
// Background processes
|
// Background processes
|
||||||
update_udpv4_dialinfo_task: TickTask,
|
update_udpv4_dialinfo_task: TickTask,
|
||||||
update_tcpv4_dialinfo_task: TickTask,
|
update_tcpv4_dialinfo_task: TickTask,
|
||||||
|
update_wsv4_dialinfo_task: TickTask,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -107,6 +108,7 @@ impl Network {
|
|||||||
NetworkUnlockedInner {
|
NetworkUnlockedInner {
|
||||||
update_udpv4_dialinfo_task: TickTask::new(1),
|
update_udpv4_dialinfo_task: TickTask::new(1),
|
||||||
update_tcpv4_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))
|
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
|
this
|
||||||
}
|
}
|
||||||
@ -289,7 +300,7 @@ impl Network {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_data_to_existing_connection(
|
pub async fn send_data_to_existing_connection(
|
||||||
&self,
|
&self,
|
||||||
descriptor: ConnectionDescriptor,
|
descriptor: ConnectionDescriptor,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
@ -380,41 +391,6 @@ impl Network {
|
|||||||
res
|
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> {
|
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
|
||||||
@ -433,28 +409,33 @@ impl Network {
|
|||||||
let protocol_config = {
|
let protocol_config = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
ProtocolConfig {
|
ProtocolConfig {
|
||||||
udp_enabled: c.network.protocol.udp.enabled && c.capabilities.protocol_udp,
|
inbound: ProtocolSet {
|
||||||
tcp_connect: c.network.protocol.tcp.connect && c.capabilities.protocol_connect_tcp,
|
udp: c.network.protocol.udp.enabled && c.capabilities.protocol_udp,
|
||||||
tcp_listen: c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp,
|
tcp: c.network.protocol.tcp.listen && c.capabilities.protocol_accept_tcp,
|
||||||
ws_connect: c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws,
|
ws: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws,
|
||||||
ws_listen: c.network.protocol.ws.listen && c.capabilities.protocol_accept_ws,
|
wss: c.network.protocol.wss.listen && c.capabilities.protocol_accept_wss,
|
||||||
wss_connect: c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss,
|
},
|
||||||
wss_listen: 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);
|
self.inner.lock().protocol_config = Some(protocol_config);
|
||||||
|
|
||||||
// start listeners
|
// start listeners
|
||||||
if protocol_config.udp_enabled {
|
if protocol_config.inbound.udp {
|
||||||
self.start_udp_listeners().await?;
|
self.start_udp_listeners().await?;
|
||||||
}
|
}
|
||||||
if protocol_config.ws_listen {
|
if protocol_config.inbound.ws {
|
||||||
self.start_ws_listeners().await?;
|
self.start_ws_listeners().await?;
|
||||||
}
|
}
|
||||||
if protocol_config.wss_listen {
|
if protocol_config.inbound.wss {
|
||||||
self.start_wss_listeners().await?;
|
self.start_wss_listeners().await?;
|
||||||
}
|
}
|
||||||
if protocol_config.tcp_listen {
|
if protocol_config.inbound.tcp {
|
||||||
self.start_tcp_listeners().await?;
|
self.start_tcp_listeners().await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +484,7 @@ impl Network {
|
|||||||
|
|
||||||
// Go through our global dialinfo and see what our best network class is
|
// Go through our global dialinfo and see what our best network class is
|
||||||
let mut network_class = NetworkClass::Invalid;
|
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 let Some(nc) = did.network_class {
|
||||||
if nc < network_class {
|
if nc < network_class {
|
||||||
network_class = nc;
|
network_class = nc;
|
||||||
@ -521,6 +502,7 @@ impl Network {
|
|||||||
protocol_config,
|
protocol_config,
|
||||||
udp_static_public_dialinfo,
|
udp_static_public_dialinfo,
|
||||||
tcp_static_public_dialinfo,
|
tcp_static_public_dialinfo,
|
||||||
|
ws_static_public_dialinfo,
|
||||||
network_class,
|
network_class,
|
||||||
) = {
|
) = {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
@ -529,6 +511,7 @@ impl Network {
|
|||||||
inner.protocol_config.unwrap_or_default(),
|
inner.protocol_config.unwrap_or_default(),
|
||||||
inner.udp_static_public_dialinfo,
|
inner.udp_static_public_dialinfo,
|
||||||
inner.tcp_static_public_dialinfo,
|
inner.tcp_static_public_dialinfo,
|
||||||
|
inner.ws_static_public_dialinfo,
|
||||||
inner.network_class.unwrap_or(NetworkClass::Invalid),
|
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,
|
// 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 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
|
// and assess our network class if we haven't already
|
||||||
if protocol_config.udp_enabled
|
if protocol_config.inbound.udp
|
||||||
&& !udp_static_public_dialinfo
|
&& !udp_static_public_dialinfo
|
||||||
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
||||||
{
|
{
|
||||||
let filter = DialInfoFilter::global()
|
let filter = DialInfoFilter::all()
|
||||||
.with_protocol_type(ProtocolType::UDP)
|
.with_protocol_type(ProtocolType::UDP)
|
||||||
.with_address_type(AddressType::IPV4);
|
.with_address_type(AddressType::IPV4);
|
||||||
let need_udpv4_dialinfo = routing_table
|
let need_udpv4_dialinfo = routing_table
|
||||||
.first_filtered_dial_info_detail(&filter)
|
.first_public_filtered_dial_info_detail(&filter)
|
||||||
.is_none();
|
.is_none();
|
||||||
if need_udpv4_dialinfo {
|
if need_udpv4_dialinfo {
|
||||||
// If we have no public UDPv4 dialinfo, then we need to run a NAT check
|
// 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
|
// Same but for TCPv4
|
||||||
if protocol_config.tcp_listen
|
if protocol_config.inbound.tcp
|
||||||
&& !tcp_static_public_dialinfo
|
&& !tcp_static_public_dialinfo
|
||||||
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
||||||
{
|
{
|
||||||
let filter = DialInfoFilter::global()
|
let filter = DialInfoFilter::all()
|
||||||
.with_protocol_type(ProtocolType::TCP)
|
.with_protocol_type(ProtocolType::TCP)
|
||||||
.with_address_type(AddressType::IPV4);
|
.with_address_type(AddressType::IPV4);
|
||||||
let need_tcpv4_dialinfo = routing_table
|
let need_tcpv4_dialinfo = routing_table
|
||||||
.first_filtered_dial_info_detail(&filter)
|
.first_public_filtered_dial_info_detail(&filter)
|
||||||
.is_none();
|
.is_none();
|
||||||
if need_tcpv4_dialinfo {
|
if need_tcpv4_dialinfo {
|
||||||
// If we have no public TCPv4 dialinfo, then we need to run a NAT check
|
// 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ impl Network {
|
|||||||
|
|
||||||
for ip_addr in ip_addrs {
|
for ip_addr in ip_addrs {
|
||||||
let addr = SocketAddr::new(ip_addr, port);
|
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
|
// see if we've already bound to this already
|
||||||
// if not, spawn a listener
|
// if not, spawn a listener
|
||||||
@ -262,9 +262,9 @@ impl Network {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return local dial infos we listen on
|
// Return interface dial infos we listen on
|
||||||
for ldi_addr in ldi_addrs {
|
for idi_addr in idi_addrs {
|
||||||
out.push(SocketAddress::from_socket_addr(ldi_addr));
|
out.push(SocketAddress::from_socket_addr(idi_addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +173,13 @@ impl Network {
|
|||||||
.inbound_udp_protocol_handlers
|
.inbound_udp_protocol_handlers
|
||||||
.contains_key(&addr)
|
.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?;
|
self.clone().create_udp_inbound_socket(addr).await?;
|
||||||
|
|
||||||
// Return local dial infos we listen on
|
// Return interface dial infos we listen on
|
||||||
for ldi_addr in ldi_addrs {
|
for idi_addr in idi_addrs {
|
||||||
out.push(DialInfo::udp_from_socketaddr(ldi_addr));
|
out.push(DialInfo::udp_from_socketaddr(idi_addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,15 @@ impl Network {
|
|||||||
.with_protocol_type(protocol_type)
|
.with_protocol_type(protocol_type)
|
||||||
.with_address_type(address_type);
|
.with_address_type(address_type);
|
||||||
routing_table
|
routing_table
|
||||||
.all_filtered_dial_info_details(&filter)
|
.interface_dial_info_details()
|
||||||
.iter()
|
.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()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +136,7 @@ impl Network {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Add public dial info with Server network class
|
// Add public dial info with Server network class
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
@ -151,7 +157,7 @@ impl Network {
|
|||||||
{
|
{
|
||||||
// Got a port mapping, let's use it
|
// Got a port mapping, let's use it
|
||||||
let external_mapped_dial_info = DialInfo::udp(external_mapped);
|
let external_mapped_dial_info = DialInfo::udp(external_mapped);
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
external_mapped_dial_info,
|
external_mapped_dial_info,
|
||||||
DialInfoOrigin::Mapped,
|
DialInfoOrigin::Mapped,
|
||||||
Some(NetworkClass::Mapped),
|
Some(NetworkClass::Mapped),
|
||||||
@ -174,7 +180,7 @@ impl Network {
|
|||||||
{
|
{
|
||||||
// Yes, another machine can use the dial info directly, so Full Cone
|
// Yes, another machine can use the dial info directly, so Full Cone
|
||||||
// Add public dial info with full cone NAT network class
|
// Add public dial info with full cone NAT network class
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
Some(NetworkClass::FullConeNAT),
|
Some(NetworkClass::FullConeNAT),
|
||||||
@ -224,14 +230,14 @@ impl Network {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Got a reply from a non-default port, which means we're only address restricted
|
// 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,
|
external1_dial_info,
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
Some(NetworkClass::AddressRestrictedNAT),
|
Some(NetworkClass::AddressRestrictedNAT),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Didn't get a reply from a non-default port, which means we are also port restricted
|
// 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,
|
external1_dial_info,
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
Some(NetworkClass::PortRestrictedNAT),
|
Some(NetworkClass::PortRestrictedNAT),
|
||||||
@ -258,4 +264,11 @@ impl Network {
|
|||||||
//Err("unimplemented".to_owned())
|
//Err("unimplemented".to_owned())
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,22 +287,23 @@ impl Network {
|
|||||||
"UDP: starting listeners on port {} at {:?}",
|
"UDP: starting listeners on port {} at {:?}",
|
||||||
udp_port, ip_addrs
|
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;
|
let mut static_public = false;
|
||||||
for di in &dial_infos {
|
for di in &dial_info_list {
|
||||||
// Register local dial info only here if we specify a public address
|
// 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() {
|
if public_address.is_none() && di.is_global() {
|
||||||
// Register global dial info if no public address is specified
|
routing_table.register_public_dial_info(
|
||||||
routing_table.register_dial_info(
|
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
|
|
||||||
static_public = true;
|
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
|
// Add static public dialinfo if it's configured
|
||||||
@ -315,7 +316,7 @@ impl Network {
|
|||||||
|
|
||||||
// Add all resolved addresses as public dialinfo
|
// Add all resolved addresses as public dialinfo
|
||||||
for pdi_addr in &mut public_sockaddrs {
|
for pdi_addr in &mut public_sockaddrs {
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
DialInfo::udp_from_socketaddr(pdi_addr),
|
DialInfo::udp_from_socketaddr(pdi_addr),
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
@ -375,22 +376,21 @@ impl Network {
|
|||||||
let di = DialInfo::try_ws(socket_address, global_url)
|
let di = DialInfo::try_ws(socket_address, global_url)
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?;
|
.map_err(logthru_net!(error))?;
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
di,
|
di,
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
static_public = true;
|
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
|
// Add static public dialinfo if it's configured
|
||||||
@ -410,7 +410,7 @@ impl Network {
|
|||||||
.map_err(logthru_net!(error))?;
|
.map_err(logthru_net!(error))?;
|
||||||
|
|
||||||
for gsa in global_socket_addrs {
|
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())
|
DialInfo::try_ws(SocketAddress::from_socket_addr(gsa), url.clone())
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?,
|
.map_err(logthru_net!(error))?,
|
||||||
@ -460,7 +460,7 @@ impl Network {
|
|||||||
.await?;
|
.await?;
|
||||||
trace!("WSS: listener started");
|
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
|
// 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.
|
// 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
|
// 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))?;
|
.map_err(logthru_net!(error))?;
|
||||||
|
|
||||||
for gsa in global_socket_addrs {
|
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())
|
DialInfo::try_wss(SocketAddress::from_socket_addr(gsa), url.clone())
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?,
|
.map_err(logthru_net!(error))?,
|
||||||
@ -537,19 +537,17 @@ impl Network {
|
|||||||
for socket_address in socket_addresses {
|
for socket_address in socket_addresses {
|
||||||
let di = DialInfo::tcp(socket_address);
|
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() {
|
if public_address.is_none() && di.is_global() {
|
||||||
// Register global dial info if no public address is specified
|
routing_table.register_public_dial_info(
|
||||||
routing_table.register_dial_info(
|
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
static_public = true;
|
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
|
// Add static public dialinfo if it's configured
|
||||||
@ -562,7 +560,7 @@ impl Network {
|
|||||||
|
|
||||||
// Add all resolved addresses as public dialinfo
|
// Add all resolved addresses as public dialinfo
|
||||||
for pdi_addr in &mut public_sockaddrs {
|
for pdi_addr in &mut public_sockaddrs {
|
||||||
routing_table.register_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
DialInfo::tcp_from_socketaddr(pdi_addr),
|
DialInfo::tcp_from_socketaddr(pdi_addr),
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
None,
|
None,
|
||||||
|
@ -75,7 +75,7 @@ impl Network {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_data_to_existing_connection(
|
pub async fn send_data_to_existing_connection(
|
||||||
&self,
|
&self,
|
||||||
descriptor: ConnectionDescriptor,
|
descriptor: ConnectionDescriptor,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
@ -137,31 +137,6 @@ impl Network {
|
|||||||
res
|
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> {
|
pub async fn startup(&self) -> Result<(), String> {
|
||||||
|
@ -17,32 +17,8 @@ pub const IPADDR_MAX_INACTIVE_DURATION_US: u64 = 300_000_000u64; // 5 minutes
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
pub struct ProtocolConfig {
|
pub struct ProtocolConfig {
|
||||||
pub udp_enabled: bool,
|
pub outbound: ProtocolSet,
|
||||||
pub tcp_connect: bool,
|
pub inbound: ProtocolSet,
|
||||||
pub tcp_listen: bool,
|
|
||||||
pub ws_connect: bool,
|
|
||||||
pub ws_listen: bool,
|
|
||||||
pub wss_connect: bool,
|
|
||||||
pub wss_listen: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProtocolConfig {
|
|
||||||
pub fn is_protocol_type_connect_enabled(&self, protocol_type: ProtocolType) -> bool {
|
|
||||||
match protocol_type {
|
|
||||||
ProtocolType::UDP => self.udp_enabled,
|
|
||||||
ProtocolType::TCP => self.tcp_connect,
|
|
||||||
ProtocolType::WS => self.ws_connect,
|
|
||||||
ProtocolType::WSS => self.wss_connect,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_protocol_type_listen_enabled(&self, protocol_type: ProtocolType) -> bool {
|
|
||||||
match protocol_type {
|
|
||||||
ProtocolType::UDP => self.udp_enabled,
|
|
||||||
ProtocolType::TCP => self.tcp_listen,
|
|
||||||
ProtocolType::WS => self.ws_listen,
|
|
||||||
ProtocolType::WSS => self.wss_listen,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Things we get when we start up and go away when we shut down
|
// Things we get when we start up and go away when we shut down
|
||||||
@ -91,6 +67,15 @@ impl Default for NetworkManagerStats {
|
|||||||
struct ClientWhitelistEntry {
|
struct ClientWhitelistEntry {
|
||||||
last_seen: u64,
|
last_seen: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mechanism required to contact another node
|
||||||
|
enum InboundMethod {
|
||||||
|
Direct, // Contact the node directly
|
||||||
|
SignalReverse, // Request via signal the node connect back directly
|
||||||
|
SignalHolePunch, // Request via signal the node negotiate a hole punch
|
||||||
|
Relay, // Must use a third party relay to reach the node
|
||||||
|
}
|
||||||
|
|
||||||
// The mutable state of the network manager
|
// The mutable state of the network manager
|
||||||
struct NetworkManagerInner {
|
struct NetworkManagerInner {
|
||||||
routing_table: Option<RoutingTable>,
|
routing_table: Option<RoutingTable>,
|
||||||
@ -476,12 +461,20 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by the RPC handler when we want to issue an RPC request or response
|
// Called by the RPC handler when we want to issue an RPC request or response
|
||||||
|
// node_ref is the direct destination to which the envelope will be sent
|
||||||
|
// If 'node_id' is specified, it can be different than node_ref.node_id()
|
||||||
|
// which will cause the envelope to be relayed
|
||||||
pub async fn send_envelope<B: AsRef<[u8]>>(
|
pub async fn send_envelope<B: AsRef<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
node_ref: NodeRef,
|
node_ref: NodeRef,
|
||||||
|
node_id: Option<DHTKey>,
|
||||||
body: B,
|
body: B,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
log_net!("sending envelope to {:?}", node_ref);
|
if let Some(node_id) = node_id {
|
||||||
|
log_net!("sending envelope to {:?} via {:?}", node_id, node_ref);
|
||||||
|
} else {
|
||||||
|
log_net!("sending envelope to {:?}", node_ref);
|
||||||
|
}
|
||||||
// Get node's min/max version and see if we can send to it
|
// Get node's min/max version and see if we can send to it
|
||||||
// and if so, get the max version we can use
|
// and if so, get the max version we can use
|
||||||
let version = if let Some((node_min, node_max)) = node_ref.operate(|e| e.min_max_version())
|
let version = if let Some((node_min, node_max)) = node_ref.operate(|e| e.min_max_version())
|
||||||
@ -503,11 +496,11 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Build the envelope to send
|
// Build the envelope to send
|
||||||
let out = self
|
let out = self
|
||||||
.build_envelope(node_ref.node_id(), version, body)
|
.build_envelope(node_id.unwrap_or_else(|| node_ref.node_id()), version, body)
|
||||||
.map_err(logthru_rpc!(error))?;
|
.map_err(logthru_rpc!(error))?;
|
||||||
|
|
||||||
// Send via relay if we have to
|
// Send the envelope via whatever means necessary
|
||||||
self.net().send_data(node_ref, out).await
|
self.send_data(node_ref, out).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the RPC handler when we want to issue an direct receipt
|
// Called by the RPC handler when we want to issue an direct receipt
|
||||||
@ -533,6 +526,203 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Figure out how to reach a node
|
||||||
|
// Node info here must be the filtered kind, with only
|
||||||
|
fn get_inbound_method(&self, node_info: &NodeInfo) -> Result<InboundMethod, String> {
|
||||||
|
// Get our network class
|
||||||
|
let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
|
||||||
|
|
||||||
|
// If we don't have a network class yet (no public dial info or haven't finished detection)
|
||||||
|
// then we just need to try to send to the best direct dial info because we won't
|
||||||
|
// know how to use relays effectively yet
|
||||||
|
if matches!(network_class, NetworkClass::Invalid) {
|
||||||
|
return Ok(InboundMethod::Direct);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the protocol of the best matching direct dial info
|
||||||
|
let protocol_type = node_info.dial_info_list.first().map(|d| d.protocol_type());
|
||||||
|
|
||||||
|
// Can the target node do inbound?
|
||||||
|
if node_info.network_class.inbound_capable() {
|
||||||
|
// Do we need to signal before going inbound?
|
||||||
|
if node_info.network_class.inbound_requires_signal() {
|
||||||
|
// Can we receive a direct reverse connection?
|
||||||
|
if network_class.inbound_capable() && !network_class.inbound_requires_signal() {
|
||||||
|
Ok(InboundMethod::SignalReverse)
|
||||||
|
}
|
||||||
|
// Is this a hole-punch capable protocol?
|
||||||
|
else if protocol_type == Some(ProtocolType::UDP) {
|
||||||
|
Ok(InboundMethod::SignalHolePunch)
|
||||||
|
}
|
||||||
|
// Otherwise we have to relay
|
||||||
|
else {
|
||||||
|
Ok(InboundMethod::Relay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Can go direct
|
||||||
|
else {
|
||||||
|
Ok(InboundMethod::Direct)
|
||||||
|
}
|
||||||
|
// If the other node is not inbound capable at all, it requires a relay
|
||||||
|
} else {
|
||||||
|
Ok(InboundMethod::Relay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a reverse connection signal and wait for the return receipt over it
|
||||||
|
// Then send the data across the new connection
|
||||||
|
pub async fn do_reverse_connect(
|
||||||
|
&self,
|
||||||
|
best_node_info: &NodeInfo,
|
||||||
|
data: Vec<u8>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
|
||||||
|
// Get relay to signal from
|
||||||
|
let relay_nr = if let Some(rpi) = best_node_info.relay_peer_info {
|
||||||
|
// Get the noderef for this inbound relay
|
||||||
|
self.routing_table().register_node_with_node_info(rpi.node_id.key, rpi.node_info)?;
|
||||||
|
} else {
|
||||||
|
// If we don't have a relay dial info that matches our protocol configuration
|
||||||
|
// then we can't send to this node!
|
||||||
|
return Err("Can't send to this relay".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the receipt timeout
|
||||||
|
let receipt_time = ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms);
|
||||||
|
|
||||||
|
// Build a return receipt for the signal
|
||||||
|
let (rcpt_data, eventual_value) = self
|
||||||
|
.generate_single_shot_receipt(receipt_time, [])
|
||||||
|
.map_err(map_error_string!())?;
|
||||||
|
|
||||||
|
// Issue the signal
|
||||||
|
let rpc = self.rpc_processor();
|
||||||
|
rpc.rpc_call_signal(dest, )
|
||||||
|
|
||||||
|
// Wait for the return receipt
|
||||||
|
match eventual_value.await {
|
||||||
|
ReceiptEvent::Returned => (),
|
||||||
|
ReceiptEvent::Expired => {
|
||||||
|
return Err("receipt was dropped before expiration".to_owned());
|
||||||
|
}
|
||||||
|
ReceiptEvent::Cancelled => {
|
||||||
|
return Err("receipt was dropped before expiration".to_owned());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// And now use the existing connection to send over
|
||||||
|
if let Some(descriptor) = node_ref.last_connection() {
|
||||||
|
match self
|
||||||
|
.net()
|
||||||
|
.send_data_to_existing_connection(descriptor, data)
|
||||||
|
.await
|
||||||
|
.map_err(logthru_net!())?
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a hole punch signal and do a negotiating ping and wait for the return receipt
|
||||||
|
// Then send the data across the new connection
|
||||||
|
pub async fn do_hole_punch(&self, best_node_info: &NodeInfo, data: Vec<u8>) -> Result<(), String> {
|
||||||
|
if let Some(relay_dial_info) = node_info.relay_dial_info_list.first() {
|
||||||
|
self.net()
|
||||||
|
.do_hole_punch(relay_dial_info.clone(), data)
|
||||||
|
.await
|
||||||
|
.map_err(logthru_net!())
|
||||||
|
} else {
|
||||||
|
// If we don't have a relay dial info that matches our protocol configuration
|
||||||
|
// then we can't send to this node!
|
||||||
|
Err("Can't send to this node yet".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send raw data to a 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.
|
||||||
|
//
|
||||||
|
// Sending to a node requires determining a NetworkClass compatible mechanism
|
||||||
|
//
|
||||||
|
pub fn send_data(&self, node_ref: NodeRef, data: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
|
let this = self.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
// 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 this
|
||||||
|
.net()
|
||||||
|
.send_data_to_existing_connection(descriptor, data)
|
||||||
|
.await
|
||||||
|
.map_err(logthru_net!())?
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we don't have last_connection, try to reach out to the peer via its dial info
|
||||||
|
let best_node_info = match node_ref
|
||||||
|
.best_node_info() {
|
||||||
|
Some(ni) => ni,
|
||||||
|
None => {
|
||||||
|
// If neither this node nor its relays would never ever be
|
||||||
|
// reachable by any of our protocols
|
||||||
|
// then we need to go through the outbound relay
|
||||||
|
if let Some(relay_node) = this.relay_node() {
|
||||||
|
// We have an outbound relay, lets use it
|
||||||
|
return this.send_data(relay_node, data).await;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We have no way to reach the node nor an outbound relay to use
|
||||||
|
return Err("Can't reach this node".to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we aren't using an outbound relay to reach this node, what inbound method do we use?
|
||||||
|
match this.get_inbound_method(&best_node_info)? {
|
||||||
|
InboundMethod::Direct => {
|
||||||
|
if let Some(dial_info) = best_node_info.dial_info_list.first() {
|
||||||
|
this.net()
|
||||||
|
.send_data_to_dial_info(dial_info.clone(), data)
|
||||||
|
.await
|
||||||
|
.map_err(logthru_net!())
|
||||||
|
} else {
|
||||||
|
// If we don't have a direct dial info that matches our protocol configuration
|
||||||
|
// then we can't send to this node!
|
||||||
|
Err("Can't send to this node yet".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InboundMethod::SignalReverse => this.do_reverse_connect(&best_node_info, data).await,
|
||||||
|
InboundMethod::SignalHolePunch => this.do_hole_punch(&best_node_info, data).await,
|
||||||
|
InboundMethod::Relay => {
|
||||||
|
if let Some(rpi) = best_node_info.relay_peer_info {
|
||||||
|
// Get the noderef for this inbound relay
|
||||||
|
let inbound_relay_noderef = this.routing_table().register_node_with_node_info(rpi.node_id.key, rpi.node_info)?;
|
||||||
|
// Send to the inbound relay
|
||||||
|
this.send_data(inbound_relay_noderef, data).await
|
||||||
|
} else {
|
||||||
|
// If we don't have a relay dial info that matches our protocol configuration
|
||||||
|
// then we can't send to this node!
|
||||||
|
Err("Can't send to this relay".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Called when a packet potentially containing an RPC envelope is received by a low-level
|
// Called when a packet potentially containing an RPC envelope is received by a low-level
|
||||||
// network protocol handler. Processes the envelope, authenticates and decrypts the RPC message
|
// network protocol handler. Processes the envelope, authenticates and decrypts the RPC message
|
||||||
// and passes it to the RPC handler
|
// and passes it to the RPC handler
|
||||||
@ -608,14 +798,7 @@ impl NetworkManager {
|
|||||||
// nodes are allowed to do this, for example PWA users
|
// nodes are allowed to do this, for example PWA users
|
||||||
|
|
||||||
let relay_nr = if self.check_client_whitelist(sender_id) {
|
let relay_nr = if self.check_client_whitelist(sender_id) {
|
||||||
// Cache the envelope information in the routing table
|
// Full relay allowed, do a full resolve_node
|
||||||
// let source_noderef = routing_table
|
|
||||||
// .register_node_with_existing_connection(envelope.get_sender_id(), descriptor, ts)
|
|
||||||
// .map_err(|e| format!("node id registration failed: {}", e))?;
|
|
||||||
// source_noderef.operate(|e| e.set_min_max_version(envelope.get_min_max_version()));
|
|
||||||
|
|
||||||
// If the sender is in the client whitelist, allow a full resolve_node,
|
|
||||||
// which effectively lets the client use our routing table
|
|
||||||
rpc.resolve_node(recipient_id).await.map_err(|e| {
|
rpc.resolve_node(recipient_id).await.map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"failed to resolve recipient node for relay, dropping outbound relayed packet...: {:?}",
|
"failed to resolve recipient node for relay, dropping outbound relayed packet...: {:?}",
|
||||||
@ -630,27 +813,16 @@ impl NetworkManager {
|
|||||||
// We should, because relays are chosen by nodes that have established connectivity and
|
// We should, because relays are chosen by nodes that have established connectivity and
|
||||||
// should be mutually in each others routing tables. The node needing the relay will be
|
// should be mutually in each others routing tables. The node needing the relay will be
|
||||||
// pinging this node regularly to keep itself in the routing table
|
// pinging this node regularly to keep itself in the routing table
|
||||||
if let Some(nr) = routing_table.lookup_node_ref(recipient_id) {
|
routing_table.lookup_node_ref(recipient_id).ok_or_else(|| {
|
||||||
// ensure we have dial_info for the entry already,
|
format!(
|
||||||
if !nr.operate(|e| e.dial_infos().is_empty()) {
|
|
||||||
nr
|
|
||||||
} else {
|
|
||||||
return Err(format!(
|
|
||||||
"Inbound relay asked for recipient with no dial info: {}",
|
|
||||||
recipient_id
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(format!(
|
|
||||||
"Inbound relay asked for recipient not in routing table: {}",
|
"Inbound relay asked for recipient not in routing table: {}",
|
||||||
recipient_id
|
recipient_id
|
||||||
));
|
)
|
||||||
}
|
})?
|
||||||
};
|
};
|
||||||
|
|
||||||
// Re-send the packet to the leased node
|
// Relay the packet to the desired destination
|
||||||
self.net()
|
self.send_data(relay_nr, data.to_vec())
|
||||||
.send_data(relay_nr, data.to_vec())
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("failed to forward envelope: {}", e))?;
|
.map_err(|e| format!("failed to forward envelope: {}", e))?;
|
||||||
// Inform caller that we dealt with the envelope, but did not process it locally
|
// Inform caller that we dealt with the envelope, but did not process it locally
|
||||||
@ -683,7 +855,7 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep relays assigned and accessible
|
// Keep relays assigned and accessible
|
||||||
async fn relay_management_task_routine(self, last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
async fn relay_management_task_routine(self, _last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
||||||
log_net!("--- network manager relay_management task");
|
log_net!("--- network manager relay_management task");
|
||||||
|
|
||||||
// Get our node's current network class and do the right thing
|
// Get our node's current network class and do the right thing
|
||||||
@ -712,9 +884,9 @@ impl NetworkManager {
|
|||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
// Register new outbound relay
|
// Register new outbound relay
|
||||||
let nr = routing_table.register_node_with_dial_info(
|
let nr = routing_table.register_node_with_node_info(
|
||||||
outbound_relay_peerinfo.node_id.key,
|
outbound_relay_peerinfo.node_id.key,
|
||||||
&outbound_relay_peerinfo.dial_infos,
|
outbound_relay_peerinfo.node_info,
|
||||||
)?;
|
)?;
|
||||||
inner.relay_node = Some(nr);
|
inner.relay_node = Some(nr);
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,10 @@ pub enum BucketEntryState {
|
|||||||
pub struct BucketEntry {
|
pub struct BucketEntry {
|
||||||
pub(super) ref_count: u32,
|
pub(super) ref_count: u32,
|
||||||
min_max_version: Option<(u8, u8)>,
|
min_max_version: Option<(u8, u8)>,
|
||||||
seen_our_dial_info: bool,
|
seen_our_node_info: bool,
|
||||||
last_connection: Option<(ConnectionDescriptor, u64)>,
|
last_connection: Option<(ConnectionDescriptor, u64)>,
|
||||||
node_info: NodeInfo,
|
node_info: NodeInfo,
|
||||||
|
local_node_info: LocalNodeInfo,
|
||||||
peer_stats: PeerStats,
|
peer_stats: PeerStats,
|
||||||
latency_stats_accounting: LatencyStatsAccounting,
|
latency_stats_accounting: LatencyStatsAccounting,
|
||||||
transfer_stats_accounting: TransferStatsAccounting,
|
transfer_stats_accounting: TransferStatsAccounting,
|
||||||
@ -49,9 +50,10 @@ impl BucketEntry {
|
|||||||
Self {
|
Self {
|
||||||
ref_count: 0,
|
ref_count: 0,
|
||||||
min_max_version: None,
|
min_max_version: None,
|
||||||
seen_our_dial_info: false,
|
seen_our_node_info: false,
|
||||||
last_connection: None,
|
last_connection: None,
|
||||||
node_info: NodeInfo::default(),
|
node_info: NodeInfo::default(),
|
||||||
|
local_node_info: LocalNodeInfo::default(),
|
||||||
latency_stats_accounting: LatencyStatsAccounting::new(),
|
latency_stats_accounting: LatencyStatsAccounting::new(),
|
||||||
transfer_stats_accounting: TransferStatsAccounting::new(),
|
transfer_stats_accounting: TransferStatsAccounting::new(),
|
||||||
peer_stats: PeerStats {
|
peer_stats: PeerStats {
|
||||||
@ -108,34 +110,20 @@ impl BucketEntry {
|
|||||||
pub fn update_node_info(&mut self, node_info: NodeInfo) {
|
pub fn update_node_info(&mut self, node_info: NodeInfo) {
|
||||||
self.node_info = node_info
|
self.node_info = node_info
|
||||||
}
|
}
|
||||||
|
pub fn update_local_node_info(&mut self, local_node_info: LocalNodeInfo) {
|
||||||
|
self.local_node_info = local_node_info
|
||||||
|
}
|
||||||
|
|
||||||
pub fn node_info(&self) -> &NodeInfo {
|
pub fn node_info(&self) -> &NodeInfo {
|
||||||
&self.node_info
|
&self.node_info
|
||||||
}
|
}
|
||||||
|
pub fn local_node_info(&self) -> &LocalNodeInfo {
|
||||||
pub fn first_filtered_node_info<F>(&self, filter: F) -> Option<NodeInfo>
|
&self.local_node_info
|
||||||
where
|
|
||||||
F: Fn(&DialInfo) -> bool,
|
|
||||||
{
|
|
||||||
let out = self.node_info.first_filtered(filter);
|
|
||||||
if out.dial_infos.is_empty() && out.relay_dial_infos.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pub fn peer_info(&self, key: DHTKey) -> PeerInfo {
|
||||||
pub fn all_filtered_node_info<F>(&self, filter: F) -> NodeInfo
|
|
||||||
where
|
|
||||||
F: Fn(&DialInfo) -> bool,
|
|
||||||
{
|
|
||||||
self.node_info.all_filtered(filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo {
|
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
node_id: NodeId::new(key),
|
node_id: NodeId::new(key),
|
||||||
node_info: self.all_filtered_node_info(|di| di.matches_peer_scope(scope)),
|
node_info: self.node_info.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,12 +161,12 @@ impl BucketEntry {
|
|||||||
self.peer_stats.status = Some(status);
|
self.peer_stats.status = Some(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_seen_our_dial_info(&mut self, seen: bool) {
|
pub fn set_seen_our_node_info(&mut self, seen: bool) {
|
||||||
self.seen_our_dial_info = seen;
|
self.seen_our_node_info = seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_seen_our_dial_info(&self) -> bool {
|
pub fn has_seen_our_node_info(&self) -> bool {
|
||||||
self.seen_our_dial_info
|
self.seen_our_node_info
|
||||||
}
|
}
|
||||||
|
|
||||||
///// stats methods
|
///// stats methods
|
||||||
|
@ -23,15 +23,15 @@ impl RoutingTable {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
pub fn debug_info_dialinfo(&self) -> String {
|
pub fn debug_info_dialinfo(&self) -> String {
|
||||||
let ldis = self.local_dial_info_details();
|
let ldis = self.interface_dial_info_details();
|
||||||
let gdis = self.global_dial_info_details();
|
let gdis = self.public_dial_info_details();
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
||||||
out += "Local Dial Info Details:\n";
|
out += "Interface Dial Info Details:\n";
|
||||||
for (n, ldi) in ldis.iter().enumerate() {
|
for (n, ldi) in ldis.iter().enumerate() {
|
||||||
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
||||||
}
|
}
|
||||||
out += "Global Dial Info Details:\n";
|
out += "Public Dial Info Details:\n";
|
||||||
for (n, gdi) in gdis.iter().enumerate() {
|
for (n, gdi) in gdis.iter().enumerate() {
|
||||||
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ impl RoutingTable {
|
|||||||
// Returns noderefs are are scoped to that address type only
|
// Returns noderefs are are scoped to that address type only
|
||||||
pub fn find_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
|
pub fn find_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
|
||||||
let dial_info_filter1 = dial_info_filter.clone();
|
let dial_info_filter1 = dial_info_filter.clone();
|
||||||
let dial_info_filter2 = dial_info_filter.clone();
|
|
||||||
self.find_fastest_nodes(
|
self.find_fastest_nodes(
|
||||||
// filter
|
// filter
|
||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
@ -21,50 +20,53 @@ impl RoutingTable {
|
|||||||
.1
|
.1
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.first_filtered_node_info(|di| di.matches_filter(&dial_info_filter1))
|
.node_info()
|
||||||
|
.first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter1))
|
||||||
.is_some()
|
.is_some()
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
// transform
|
// transform
|
||||||
|e| {
|
|e| NodeRef::new(self.clone(), *e.0, e.1.as_mut().unwrap()),
|
||||||
NodeRef::new_filtered(
|
|
||||||
self.clone(),
|
|
||||||
*e.0,
|
|
||||||
e.1.as_mut().unwrap(),
|
|
||||||
dial_info_filter2.clone(),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo {
|
pub fn get_own_peer_info(&self) -> PeerInfo {
|
||||||
let filter = DialInfoFilter::scoped(scope);
|
|
||||||
let netman = self.network_manager();
|
let netman = self.network_manager();
|
||||||
|
let enable_local_peer_scope = netman.config().get().network.enable_local_peer_scope;
|
||||||
let relay_node = netman.relay_node();
|
let relay_node = netman.relay_node();
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
node_id: NodeId::new(self.node_id()),
|
node_id: NodeId::new(self.node_id()),
|
||||||
node_info: NodeInfo {
|
node_info: NodeInfo {
|
||||||
network_class: netman.get_network_class().unwrap_or(NetworkClass::Invalid),
|
network_class: netman.get_network_class().unwrap_or(NetworkClass::Invalid),
|
||||||
dial_infos: self
|
outbound_protocols: netman.get_protocol_config().unwrap_or_default().outbound,
|
||||||
.all_filtered_dial_info_details(&filter)
|
dial_info_list: if !enable_local_peer_scope {
|
||||||
.iter()
|
self.public_dial_info_details()
|
||||||
.map(|did| did.dial_info.clone())
|
.iter()
|
||||||
.collect(),
|
.map(|did| did.dial_info.clone())
|
||||||
relay_dial_infos: relay_node
|
.collect()
|
||||||
.map(|rn| rn.node_info().dial_infos)
|
} else {
|
||||||
.unwrap_or_default(),
|
self.public_dial_info_details()
|
||||||
|
.iter()
|
||||||
|
.map(|did| did.dial_info.clone())
|
||||||
|
.chain(
|
||||||
|
self.interface_dial_info_details()
|
||||||
|
.iter()
|
||||||
|
.map(|did| did.dial_info.clone()),
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
},
|
||||||
|
relay_peer_info: relay_node.map(|rn| Box::new(rn.peer_info())),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_to_peer_info(
|
pub fn transform_to_peer_info(
|
||||||
kv: &mut (&DHTKey, Option<&mut BucketEntry>),
|
kv: &mut (&DHTKey, Option<&mut BucketEntry>),
|
||||||
scope: PeerScope,
|
|
||||||
own_peer_info: &PeerInfo,
|
own_peer_info: &PeerInfo,
|
||||||
) -> PeerInfo {
|
) -> PeerInfo {
|
||||||
match &kv.1 {
|
match &kv.1 {
|
||||||
None => own_peer_info.clone(),
|
None => own_peer_info.clone(),
|
||||||
Some(entry) => entry.get_peer_info(*kv.0, scope),
|
Some(entry) => entry.peer_info(*kv.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ struct RoutingTableInner {
|
|||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
node_id_secret: DHTKeySecret,
|
node_id_secret: DHTKeySecret,
|
||||||
buckets: Vec<Bucket>,
|
buckets: Vec<Bucket>,
|
||||||
dial_info_details: Vec<DialInfoDetail>,
|
public_dial_info_details: Vec<DialInfoDetail>,
|
||||||
|
interface_dial_info_details: Vec<DialInfoDetail>,
|
||||||
bucket_entry_count: usize,
|
bucket_entry_count: usize,
|
||||||
|
|
||||||
// Waiters
|
// Waiters
|
||||||
@ -89,7 +90,8 @@ impl RoutingTable {
|
|||||||
node_id: DHTKey::default(),
|
node_id: DHTKey::default(),
|
||||||
node_id_secret: DHTKeySecret::default(),
|
node_id_secret: DHTKeySecret::default(),
|
||||||
buckets: Vec::new(),
|
buckets: Vec::new(),
|
||||||
dial_info_details: Vec::new(),
|
public_dial_info_details: Vec::new(),
|
||||||
|
interface_dial_info_details: Vec::new(),
|
||||||
bucket_entry_count: 0,
|
bucket_entry_count: 0,
|
||||||
eventual_changed_dial_info: Eventual::new(),
|
eventual_changed_dial_info: Eventual::new(),
|
||||||
self_latency_stats_accounting: LatencyStatsAccounting::new(),
|
self_latency_stats_accounting: LatencyStatsAccounting::new(),
|
||||||
@ -163,40 +165,42 @@ impl RoutingTable {
|
|||||||
self.inner.lock().node_id_secret
|
self.inner.lock().node_id_secret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_local_dial_info(&self) -> bool {
|
pub fn has_interface_dial_info(&self) -> bool {
|
||||||
self.first_filtered_dial_info_detail(&DialInfoFilter::local())
|
!self.inner.lock().interface_dial_info_details.is_empty()
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_global_dial_info(&self) -> bool {
|
pub fn has_public_dial_info(&self) -> bool {
|
||||||
self.first_filtered_dial_info_detail(&DialInfoFilter::global())
|
!self.inner.lock().public_dial_info_details.is_empty()
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
pub fn public_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||||
self.all_filtered_dial_info_details(&DialInfoFilter::global())
|
self.inner.lock().public_dial_info_details.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
pub fn interface_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||||
self.all_filtered_dial_info_details(&DialInfoFilter::local())
|
self.inner.lock().interface_dial_info_details.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_filtered_dial_info_detail(
|
pub fn first_public_filtered_dial_info_detail(
|
||||||
&self,
|
&self,
|
||||||
filter: &DialInfoFilter,
|
filter: &DialInfoFilter,
|
||||||
) -> Option<DialInfoDetail> {
|
) -> Option<DialInfoDetail> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
for did in &inner.dial_info_details {
|
for did in &inner.public_dial_info_details {
|
||||||
if did.matches_filter(filter) {
|
if did.matches_filter(filter) {
|
||||||
return Some(did.clone());
|
return Some(did.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
pub fn all_filtered_dial_info_details(&self, filter: &DialInfoFilter) -> Vec<DialInfoDetail> {
|
|
||||||
|
pub fn all_public_filtered_dial_info_details(
|
||||||
|
&self,
|
||||||
|
filter: &DialInfoFilter,
|
||||||
|
) -> Vec<DialInfoDetail> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
for did in &inner.dial_info_details {
|
for did in &inner.public_dial_info_details {
|
||||||
if did.matches_filter(filter) {
|
if did.matches_filter(filter) {
|
||||||
ret.push(did.clone());
|
ret.push(did.clone());
|
||||||
}
|
}
|
||||||
@ -204,16 +208,48 @@ impl RoutingTable {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_dial_info(
|
pub fn first_interface_filtered_dial_info_detail(
|
||||||
|
&self,
|
||||||
|
filter: &DialInfoFilter,
|
||||||
|
) -> Option<DialInfoDetail> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
for did in &inner.interface_dial_info_details {
|
||||||
|
if did.matches_filter(filter) {
|
||||||
|
return Some(did.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_interface_filtered_dial_info_details(
|
||||||
|
&self,
|
||||||
|
filter: &DialInfoFilter,
|
||||||
|
) -> Vec<DialInfoDetail> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
for did in &inner.interface_dial_info_details {
|
||||||
|
if did.matches_filter(filter) {
|
||||||
|
ret.push(did.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_public_dial_info(
|
||||||
&self,
|
&self,
|
||||||
dial_info: DialInfo,
|
dial_info: DialInfo,
|
||||||
origin: DialInfoOrigin,
|
origin: DialInfoOrigin,
|
||||||
network_class: Option<NetworkClass>,
|
network_class: Option<NetworkClass>,
|
||||||
) {
|
) {
|
||||||
let timestamp = get_timestamp();
|
let timestamp = get_timestamp();
|
||||||
|
let enable_local_peer_scope = {
|
||||||
|
let c = self.network_manager().config().get();
|
||||||
|
c.network.enable_local_peer_scope
|
||||||
|
};
|
||||||
|
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
inner.dial_info_details.push(DialInfoDetail {
|
inner.public_dial_info_details.push(DialInfoDetail {
|
||||||
dial_info: dial_info.clone(),
|
dial_info: dial_info.clone(),
|
||||||
origin,
|
origin,
|
||||||
network_class,
|
network_class,
|
||||||
@ -222,18 +258,11 @@ impl RoutingTable {
|
|||||||
|
|
||||||
// Re-sort dial info to endure preference ordering
|
// Re-sort dial info to endure preference ordering
|
||||||
inner
|
inner
|
||||||
.dial_info_details
|
.public_dial_info_details
|
||||||
.sort_by(|a, b| a.dial_info.cmp(&b.dial_info));
|
.sort_by(|a, b| a.dial_info.cmp(&b.dial_info));
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"{}Dial Info: {}",
|
"Public Dial Info: {}",
|
||||||
if dial_info.is_local() {
|
|
||||||
"Local "
|
|
||||||
} else if dial_info.is_global() {
|
|
||||||
"Global "
|
|
||||||
} else {
|
|
||||||
"Other "
|
|
||||||
},
|
|
||||||
NodeDialInfo {
|
NodeDialInfo {
|
||||||
node_id: NodeId::new(inner.node_id),
|
node_id: NodeId::new(inner.node_id),
|
||||||
dial_info
|
dial_info
|
||||||
@ -246,9 +275,44 @@ impl RoutingTable {
|
|||||||
Self::trigger_changed_dial_info(&mut *inner);
|
Self::trigger_changed_dial_info(&mut *inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn register_interface_dial_info(&self, dial_info: DialInfo, origin: DialInfoOrigin) {
|
||||||
|
let timestamp = get_timestamp();
|
||||||
|
let enable_local_peer_scope = {
|
||||||
|
let c = self.network_manager().config().get();
|
||||||
|
c.network.enable_local_peer_scope
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
|
inner.interface_dial_info_details.push(DialInfoDetail {
|
||||||
|
dial_info: dial_info.clone(),
|
||||||
|
origin,
|
||||||
|
network_class: None,
|
||||||
|
timestamp,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-sort dial info to endure preference ordering
|
||||||
|
inner
|
||||||
|
.interface_dial_info_details
|
||||||
|
.sort_by(|a, b| a.dial_info.cmp(&b.dial_info));
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Interface Dial Info: {}",
|
||||||
|
NodeDialInfo {
|
||||||
|
node_id: NodeId::new(inner.node_id),
|
||||||
|
dial_info
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
debug!(" Origin: {:?}", origin);
|
||||||
|
|
||||||
|
Self::trigger_changed_dial_info(&mut *inner);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clear_dial_info_details(&self) {
|
pub fn clear_dial_info_details(&self) {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.dial_info_details.clear();
|
inner.public_dial_info_details.clear();
|
||||||
|
inner.interface_dial_info_details.clear();
|
||||||
Self::trigger_changed_dial_info(&mut *inner);
|
Self::trigger_changed_dial_info(&mut *inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +326,10 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_changed_dial_info(inner: &mut RoutingTableInner) {
|
fn trigger_changed_dial_info(inner: &mut RoutingTableInner) {
|
||||||
// Clear 'seen dial info' bits on routing table entries so we know to ping them
|
// Clear 'seen node info' bits on routing table entries so we know to ping them
|
||||||
for b in &mut inner.buckets {
|
for b in &mut inner.buckets {
|
||||||
for e in b.entries_mut() {
|
for e in b.entries_mut() {
|
||||||
e.1.set_seen_our_dial_info(false);
|
e.1.set_seen_our_node_info(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -608,9 +672,10 @@ impl RoutingTable {
|
|||||||
.register_node_with_node_info(
|
.register_node_with_node_info(
|
||||||
k,
|
k,
|
||||||
NodeInfo {
|
NodeInfo {
|
||||||
network_class: NetworkClass::Server,
|
network_class: NetworkClass::Server, // Bootstraps are always full servers
|
||||||
dial_infos: v,
|
outbound_protocols: ProtocolSet::default(), // Bootstraps do not participate in relaying and will not make outbound requests
|
||||||
relay_dial_infos: Default::default(),
|
dial_info_list: v, // Dial info is as specified in the bootstrap list
|
||||||
|
relay_peer_info: None, // Bootstraps never require a relay themselves
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.map_err(logthru_rtab!("Couldn't add bootstrap node: {}", k))?;
|
.map_err(logthru_rtab!("Couldn't add bootstrap node: {}", k))?;
|
||||||
|
@ -5,7 +5,6 @@ use alloc::fmt;
|
|||||||
pub struct NodeRef {
|
pub struct NodeRef {
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
dial_info_filter: DialInfoFilter,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeRef {
|
impl NodeRef {
|
||||||
@ -14,20 +13,6 @@ impl NodeRef {
|
|||||||
Self {
|
Self {
|
||||||
routing_table,
|
routing_table,
|
||||||
node_id: key,
|
node_id: key,
|
||||||
dial_info_filter: DialInfoFilter::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new_filtered(
|
|
||||||
routing_table: RoutingTable,
|
|
||||||
key: DHTKey,
|
|
||||||
entry: &mut BucketEntry,
|
|
||||||
dial_info_filter: DialInfoFilter,
|
|
||||||
) -> Self {
|
|
||||||
entry.ref_count += 1;
|
|
||||||
Self {
|
|
||||||
routing_table,
|
|
||||||
node_id: key,
|
|
||||||
dial_info_filter,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,10 +20,6 @@ impl NodeRef {
|
|||||||
self.node_id
|
self.node_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dial_info_filter(&self) -> &DialInfoFilter {
|
|
||||||
&self.dial_info_filter
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn operate<T, F>(&self, f: F) -> T
|
pub fn operate<T, F>(&self, f: F) -> T
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut BucketEntry) -> T,
|
F: FnOnce(&mut BucketEntry) -> T,
|
||||||
@ -46,52 +27,23 @@ impl NodeRef {
|
|||||||
self.routing_table.operate_on_bucket_entry(self.node_id, f)
|
self.routing_table.operate_on_bucket_entry(self.node_id, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peer_info(&self) -> PeerInfo {
|
||||||
|
self.operate(|e| e.peer_info(self.node_id()))
|
||||||
|
}
|
||||||
pub fn node_info(&self) -> NodeInfo {
|
pub fn node_info(&self) -> NodeInfo {
|
||||||
self.operate(|e| e.node_info().clone())
|
self.operate(|e| e.node_info().clone())
|
||||||
}
|
}
|
||||||
|
pub fn local_node_info(&self) -> LocalNodeInfo {
|
||||||
pub fn has_dial_info(&self) -> bool {
|
self.operate(|e| e.local_node_info().clone())
|
||||||
self.operate(|e| !e.node_info().dial_infos.is_empty())
|
|
||||||
}
|
}
|
||||||
|
pub fn has_seen_our_node_info(&self) -> bool {
|
||||||
// Returns if this node has seen and acknowledged our node's dial info yet
|
self.operate(|e| e.has_seen_our_node_info())
|
||||||
pub fn has_seen_our_dial_info(&self) -> bool {
|
|
||||||
self.operate(|e| e.has_seen_our_dial_info())
|
|
||||||
}
|
}
|
||||||
pub fn set_seen_our_dial_info(&self) {
|
pub fn set_seen_our_node_info(&self) {
|
||||||
self.operate(|e| e.set_seen_our_dial_info(true));
|
self.operate(|e| e.set_seen_our_node_info(true));
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the best node info to attempt a connection to this node
|
|
||||||
pub fn best_node_info(&self) -> Option<NodeInfo> {
|
|
||||||
let nm = self.routing_table.network_manager();
|
|
||||||
let protocol_config = nm.get_protocol_config()?;
|
|
||||||
self.operate(|e| {
|
|
||||||
e.first_filtered_node_info(|di| {
|
|
||||||
// Does it match the dial info filter
|
|
||||||
if !di.matches_filter(&self.dial_info_filter) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Filter out dial infos that don't match our protocol config
|
|
||||||
// for outbound connections. This routine filters on 'connect' settings
|
|
||||||
// to ensure we connect using only the protocols we have enabled.
|
|
||||||
protocol_config.is_protocol_type_connect_enabled(di.protocol_type())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
||||||
match self.operate(|e| e.last_connection()) {
|
self.operate(|e| e.last_connection())
|
||||||
None => None,
|
|
||||||
Some(c) => {
|
|
||||||
if !c.matches_filter(&self.dial_info_filter) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// We don't filter this out by protocol config because if a connection
|
|
||||||
// succeeded, it's allowed to persist and be used for communication
|
|
||||||
// regardless of any other configuration
|
|
||||||
Some(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,18 +55,13 @@ impl Clone for NodeRef {
|
|||||||
Self {
|
Self {
|
||||||
routing_table: self.routing_table.clone(),
|
routing_table: self.routing_table.clone(),
|
||||||
node_id: self.node_id,
|
node_id: self.node_id,
|
||||||
dial_info_filter: self.dial_info_filter.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for NodeRef {
|
impl fmt::Debug for NodeRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut out = self.node_id.encode();
|
write!(f, "{}", self.node_id.encode())
|
||||||
if !self.dial_info_filter.is_empty() {
|
|
||||||
out += &format!("{:?}", self.dial_info_filter);
|
|
||||||
}
|
|
||||||
write!(f, "{}", out)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,10 @@ mod node_status;
|
|||||||
mod nonce;
|
mod nonce;
|
||||||
mod peer_info;
|
mod peer_info;
|
||||||
mod private_safety_route;
|
mod private_safety_route;
|
||||||
|
mod protocol_set;
|
||||||
mod public_key;
|
mod public_key;
|
||||||
mod sender_info;
|
mod sender_info;
|
||||||
|
mod signal_info;
|
||||||
mod socket_address;
|
mod socket_address;
|
||||||
|
|
||||||
pub use address::*;
|
pub use address::*;
|
||||||
@ -20,6 +22,8 @@ pub use node_status::*;
|
|||||||
pub use nonce::*;
|
pub use nonce::*;
|
||||||
pub use peer_info::*;
|
pub use peer_info::*;
|
||||||
pub use private_safety_route::*;
|
pub use private_safety_route::*;
|
||||||
|
pub use protocol_set::*;
|
||||||
pub use public_key::*;
|
pub use public_key::*;
|
||||||
pub use sender_info::*;
|
pub use sender_info::*;
|
||||||
|
pub use signal_info::*;
|
||||||
pub use socket_address::*;
|
pub use socket_address::*;
|
||||||
|
@ -7,38 +7,34 @@ pub fn encode_node_info(
|
|||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
builder.set_network_class(encode_network_class(node_info.network_class));
|
builder.set_network_class(encode_network_class(node_info.network_class));
|
||||||
|
|
||||||
|
let mut ps_builder = builder.reborrow().init_outbound_protocols();
|
||||||
|
encode_protocol_set(&node_info.outbound_protocols, &mut ps_builder)?;
|
||||||
|
|
||||||
let mut dil_builder = builder.reborrow().init_dial_info_list(
|
let mut dil_builder = builder.reborrow().init_dial_info_list(
|
||||||
node_info
|
node_info
|
||||||
.dial_infos
|
.dial_info_list
|
||||||
.len()
|
.len()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(map_error_protocol!("too many dial infos in node info"))?,
|
.map_err(map_error_protocol!("too many dial infos in node info"))?,
|
||||||
);
|
);
|
||||||
|
|
||||||
for idx in 0..node_info.dial_infos.len() {
|
for idx in 0..node_info.dial_info_list.len() {
|
||||||
let mut di_builder = dil_builder.reborrow().get(idx as u32);
|
let mut di_builder = dil_builder.reborrow().get(idx as u32);
|
||||||
encode_dial_info(&node_info.dial_infos[idx], &mut di_builder)?;
|
encode_dial_info(&node_info.dial_info_list[idx], &mut di_builder)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rdil_builder = builder.reborrow().init_relay_dial_info_list(
|
if let Some(rpi) = node_info.relay_peer_info {
|
||||||
node_info
|
let mut rpi_builder = builder.reborrow().init_relay_peer_info();
|
||||||
.relay_dial_infos
|
encode_peer_info(&rpi, &mut rpi_builder)?;
|
||||||
.len()
|
|
||||||
.try_into()
|
|
||||||
.map_err(map_error_protocol!(
|
|
||||||
"too many relay dial infos in node info"
|
|
||||||
))?,
|
|
||||||
);
|
|
||||||
|
|
||||||
for idx in 0..node_info.relay_dial_infos.len() {
|
|
||||||
let mut rdi_builder = rdil_builder.reborrow().get(idx as u32);
|
|
||||||
encode_dial_info(&node_info.relay_dial_infos[idx], &mut rdi_builder)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<NodeInfo, RPCError> {
|
pub fn decode_node_info(
|
||||||
|
reader: &veilid_capnp::node_info::Reader,
|
||||||
|
allow_relay_peer_info: bool,
|
||||||
|
) -> Result<NodeInfo, RPCError> {
|
||||||
let network_class = decode_network_class(
|
let network_class = decode_network_class(
|
||||||
reader
|
reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
@ -46,37 +42,47 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
.map_err(map_error_capnp_notinschema!())?,
|
.map_err(map_error_capnp_notinschema!())?,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let outbound_protocols = decode_protocol_set(
|
||||||
|
&reader
|
||||||
|
.reborrow()
|
||||||
|
.get_outbound_protocols()
|
||||||
|
.map_err(map_error_capnp_notinschema!())?,
|
||||||
|
)?;
|
||||||
|
|
||||||
let dil_reader = reader
|
let dil_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_dial_info_list()
|
.get_dial_info_list()
|
||||||
.map_err(map_error_capnp_error!())?;
|
.map_err(map_error_capnp_error!())?;
|
||||||
let mut dial_infos = Vec::<DialInfo>::with_capacity(
|
let mut dial_info_list = Vec::<DialInfo>::with_capacity(
|
||||||
dil_reader
|
dil_reader
|
||||||
.len()
|
.len()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(map_error_protocol!("too many dial infos"))?,
|
.map_err(map_error_protocol!("too many dial infos"))?,
|
||||||
);
|
);
|
||||||
for di in dil_reader.iter() {
|
for di in dil_reader.iter() {
|
||||||
dial_infos.push(decode_dial_info(&di)?)
|
dial_info_list.push(decode_dial_info(&di)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
let rdil_reader = reader
|
let relay_peer_info = if allow_relay_peer_info {
|
||||||
.reborrow()
|
if reader.has_relay_peer_info() {
|
||||||
.get_relay_dial_info_list()
|
Some(Box::new(decode_peer_info(
|
||||||
.map_err(map_error_capnp_error!())?;
|
&reader
|
||||||
let mut relay_dial_infos = Vec::<DialInfo>::with_capacity(
|
.reborrow()
|
||||||
rdil_reader
|
.get_relay_peer_info()
|
||||||
.len()
|
.map_err(map_error_capnp_notinschema!())?,
|
||||||
.try_into()
|
false,
|
||||||
.map_err(map_error_protocol!("too many relay dial infos"))?,
|
)?))
|
||||||
);
|
} else {
|
||||||
for di in rdil_reader.iter() {
|
None
|
||||||
relay_dial_infos.push(decode_dial_info(&di)?)
|
}
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Ok(NodeInfo {
|
Ok(NodeInfo {
|
||||||
network_class,
|
network_class,
|
||||||
dial_infos,
|
outbound_protocols,
|
||||||
relay_dial_infos,
|
dial_info_list,
|
||||||
|
relay_peer_info,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,10 @@ pub fn encode_peer_info(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<PeerInfo, RPCError> {
|
pub fn decode_peer_info(
|
||||||
|
reader: &veilid_capnp::peer_info::Reader,
|
||||||
|
allow_relay_peer_info: bool,
|
||||||
|
) -> Result<PeerInfo, RPCError> {
|
||||||
let nid_reader = reader
|
let nid_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_node_id()
|
.get_node_id()
|
||||||
@ -23,7 +26,7 @@ pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<Peer
|
|||||||
.reborrow()
|
.reborrow()
|
||||||
.get_node_info()
|
.get_node_info()
|
||||||
.map_err(map_error_capnp_error!())?;
|
.map_err(map_error_capnp_error!())?;
|
||||||
let node_info = decode_node_info(&ni_reader)?;
|
let node_info = decode_node_info(&ni_reader, allow_relay_peer_info)?;
|
||||||
|
|
||||||
Ok(PeerInfo {
|
Ok(PeerInfo {
|
||||||
node_id: NodeId::new(decode_public_key(&nid_reader)),
|
node_id: NodeId::new(decode_public_key(&nid_reader)),
|
||||||
|
25
veilid-core/src/rpc_processor/coders/protocol_set.rs
Normal file
25
veilid-core/src/rpc_processor/coders/protocol_set.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::*;
|
||||||
|
use rpc_processor::*;
|
||||||
|
|
||||||
|
pub fn encode_protocol_set(
|
||||||
|
protocol_set: &ProtocolSet,
|
||||||
|
builder: &mut veilid_capnp::protocol_set::Builder,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
builder.set_udp(protocol_set.udp);
|
||||||
|
builder.set_tcp(protocol_set.tcp);
|
||||||
|
builder.set_ws(protocol_set.ws);
|
||||||
|
builder.set_wss(protocol_set.wss);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_protocol_set(
|
||||||
|
reader: &veilid_capnp::protocol_set::Reader,
|
||||||
|
) -> Result<ProtocolSet, RPCError> {
|
||||||
|
Ok(ProtocolSet {
|
||||||
|
udp: reader.reborrow().get_udp(),
|
||||||
|
tcp: reader.reborrow().get_tcp(),
|
||||||
|
ws: reader.reborrow().get_ws(),
|
||||||
|
wss: reader.reborrow().get_wss(),
|
||||||
|
})
|
||||||
|
}
|
86
veilid-core/src/rpc_processor/coders/signal_info.rs
Normal file
86
veilid-core/src/rpc_processor/coders/signal_info.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use crate::*;
|
||||||
|
use rpc_processor::*;
|
||||||
|
|
||||||
|
pub fn encode_signal_info(
|
||||||
|
signal_info: &SignalInfo,
|
||||||
|
builder: &mut veilid_capnp::operation_signal::Builder,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
match signal_info {
|
||||||
|
SignalInfo::HolePunch { receipt, node_info } => {
|
||||||
|
let mut hp_builder = builder.init_hole_punch();
|
||||||
|
let rcpt_builder =
|
||||||
|
hp_builder
|
||||||
|
.reborrow()
|
||||||
|
.init_receipt(receipt.len().try_into().map_err(map_error_protocol!(
|
||||||
|
"invalid receipt length in hole punch signal info"
|
||||||
|
))?);
|
||||||
|
rcpt_builder.copy_from_slice(receipt.as_slice());
|
||||||
|
let mut ni_builder = hp_builder.init_node_info();
|
||||||
|
encode_node_info(&node_info, &mut ni_builder)?;
|
||||||
|
}
|
||||||
|
SignalInfo::ReverseConnect { receipt, node_info } => {
|
||||||
|
let mut hp_builder = builder.init_reverse_connect();
|
||||||
|
let rcpt_builder =
|
||||||
|
hp_builder
|
||||||
|
.reborrow()
|
||||||
|
.init_receipt(receipt.len().try_into().map_err(map_error_protocol!(
|
||||||
|
"invalid receipt length in reverse connect signal info"
|
||||||
|
))?);
|
||||||
|
rcpt_builder.copy_from_slice(receipt.as_slice());
|
||||||
|
let mut ni_builder = hp_builder.init_node_info();
|
||||||
|
encode_node_info(&node_info, &mut ni_builder)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_signal_info(
|
||||||
|
reader: &veilid_capnp::operation_signal::Reader,
|
||||||
|
) -> Result<SignalInfo, RPCError> {
|
||||||
|
Ok(
|
||||||
|
match reader
|
||||||
|
.which()
|
||||||
|
.map_err(map_error_internal!("invalid signal operation"))?
|
||||||
|
{
|
||||||
|
veilid_capnp::operation_signal::HolePunch(r) => {
|
||||||
|
// Extract hole punch reader
|
||||||
|
let r = match r {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => return Err(rpc_error_internal("invalid hole punch")),
|
||||||
|
};
|
||||||
|
let receipt = r
|
||||||
|
.get_receipt()
|
||||||
|
.map_err(map_error_protocol!(
|
||||||
|
"invalid receipt in hole punch signal info"
|
||||||
|
))?
|
||||||
|
.to_vec();
|
||||||
|
let ni_reader = r.get_node_info().map_err(map_error_protocol!(
|
||||||
|
"invalid node info in hole punch signal info"
|
||||||
|
))?;
|
||||||
|
let node_info = decode_node_info(&ni_reader, true)?;
|
||||||
|
|
||||||
|
SignalInfo::HolePunch { receipt, node_info }
|
||||||
|
}
|
||||||
|
veilid_capnp::operation_signal::ReverseConnect(r) => {
|
||||||
|
// Extract reverse connect reader
|
||||||
|
let r = match r {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => return Err(rpc_error_internal("invalid reverse connect")),
|
||||||
|
};
|
||||||
|
let receipt = r
|
||||||
|
.get_receipt()
|
||||||
|
.map_err(map_error_protocol!(
|
||||||
|
"invalid receipt in reverse connect signal info"
|
||||||
|
))?
|
||||||
|
.to_vec();
|
||||||
|
let ni_reader = r.get_node_info().map_err(map_error_protocol!(
|
||||||
|
"invalid node info in reverse connect signal info"
|
||||||
|
))?;
|
||||||
|
let node_info = decode_node_info(&ni_reader, true)?;
|
||||||
|
|
||||||
|
SignalInfo::ReverseConnect { receipt, node_info }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
@ -4,10 +4,12 @@ use super::*;
|
|||||||
pub enum RPCError {
|
pub enum RPCError {
|
||||||
Timeout,
|
Timeout,
|
||||||
InvalidFormat,
|
InvalidFormat,
|
||||||
|
Unreachable(DHTKey),
|
||||||
Unimplemented(String),
|
Unimplemented(String),
|
||||||
Protocol(String),
|
Protocol(String),
|
||||||
Internal(String),
|
Internal(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rpc_error_internal<T: AsRef<str>>(x: T) -> RPCError {
|
pub fn rpc_error_internal<T: AsRef<str>>(x: T) -> RPCError {
|
||||||
error!("RPCError Internal: {}", x.as_ref());
|
error!("RPCError Internal: {}", x.as_ref());
|
||||||
RPCError::Internal(x.as_ref().to_owned())
|
RPCError::Internal(x.as_ref().to_owned())
|
||||||
@ -34,6 +36,7 @@ impl fmt::Display for RPCError {
|
|||||||
match self {
|
match self {
|
||||||
RPCError::Timeout => write!(f, "[RPCError: Timeout]"),
|
RPCError::Timeout => write!(f, "[RPCError: Timeout]"),
|
||||||
RPCError::InvalidFormat => write!(f, "[RPCError: InvalidFormat]"),
|
RPCError::InvalidFormat => write!(f, "[RPCError: InvalidFormat]"),
|
||||||
|
RPCError::Unreachable(k) => write!(f, "[RPCError: Unreachable({})]", k),
|
||||||
RPCError::Unimplemented(s) => write!(f, "[RPCError: Unimplemented({})]", s),
|
RPCError::Unimplemented(s) => write!(f, "[RPCError: Unimplemented({})]", s),
|
||||||
RPCError::Protocol(s) => write!(f, "[RPCError: Protocol({})]", s),
|
RPCError::Protocol(s) => write!(f, "[RPCError: Protocol({})]", s),
|
||||||
RPCError::Internal(s) => write!(f, "[RPCError: Internal({})]", s),
|
RPCError::Internal(s) => write!(f, "[RPCError: Internal({})]", s),
|
||||||
@ -202,37 +205,55 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let dil_reader = match fnqr.reborrow().get_dial_info_list() {
|
let sni_reader = match fnqr.reborrow().get_sender_node_info() {
|
||||||
Ok(dilr) => dilr,
|
Ok(snir) => snir,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return format!("(invalid dial info list: {})", e);
|
return format!("(invalid sender node info: {})", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let sender_node_info = match decode_node_info(&sni_reader, true) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return format!("(unable to decode node info: {})", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut dial_infos =
|
|
||||||
Vec::<DialInfo>::with_capacity(match dil_reader.len().try_into() {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
return format!("(too many dial infos: {})", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for di in dil_reader.iter() {
|
|
||||||
dial_infos.push(match decode_dial_info(&di) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
return format!("(unable to decode dial info: {})", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let node_id = decode_public_key(&nidr);
|
let node_id = decode_public_key(&nidr);
|
||||||
format!(
|
format!(
|
||||||
"FindNodeQ: node_id={} dial_infos={:?}",
|
"FindNodeQ: node_id={} sender_node_info={:#?}",
|
||||||
node_id.encode(),
|
node_id.encode(),
|
||||||
dial_infos
|
sender_node_info
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
veilid_capnp::operation::detail::FindNodeA(_) => {
|
veilid_capnp::operation::detail::FindNodeA(d) => {
|
||||||
format!("FindNodeA")
|
let fnar = match d {
|
||||||
|
Ok(fnar) => fnar,
|
||||||
|
Err(e) => {
|
||||||
|
return format!("(invalid detail: {})", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let p_reader = match fnar.reborrow().get_peers() {
|
||||||
|
Ok(pr) => pr,
|
||||||
|
Err(e) => {
|
||||||
|
return format!("(invalid sender node info: {})", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut peers = Vec::<PeerInfo>::with_capacity(match p_reader.len().try_into() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => return format!("invalid peer count: {}", e),
|
||||||
|
});
|
||||||
|
for p in p_reader.iter() {
|
||||||
|
let peer_info = match decode_peer_info(&p, true) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return format!("(unable to decode peer info: {})", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
peers.push(peer_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
format!("FindNodeA: peers={:#?}", peers)
|
||||||
}
|
}
|
||||||
veilid_capnp::operation::detail::Route(_) => {
|
veilid_capnp::operation::detail::Route(_) => {
|
||||||
format!("Route")
|
format!("Route")
|
||||||
@ -270,11 +291,8 @@ impl RPCProcessor {
|
|||||||
veilid_capnp::operation::detail::FindBlockA(_) => {
|
veilid_capnp::operation::detail::FindBlockA(_) => {
|
||||||
format!("FindBlockA")
|
format!("FindBlockA")
|
||||||
}
|
}
|
||||||
veilid_capnp::operation::detail::SignalQ(_) => {
|
veilid_capnp::operation::detail::Signal(_) => {
|
||||||
format!("SignalQ")
|
format!("Signal")
|
||||||
}
|
|
||||||
veilid_capnp::operation::detail::SignalA(_) => {
|
|
||||||
format!("SignalA")
|
|
||||||
}
|
}
|
||||||
veilid_capnp::operation::detail::ReturnReceipt(_) => {
|
veilid_capnp::operation::detail::ReturnReceipt(_) => {
|
||||||
format!("ReturnReceipt")
|
format!("ReturnReceipt")
|
||||||
|
@ -23,8 +23,10 @@ type OperationId = u64;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Destination {
|
pub enum Destination {
|
||||||
Direct(NodeRef),
|
Direct(NodeRef), // Can only be sent directly
|
||||||
PrivateRoute(PrivateRoute),
|
Normal(NodeRef), // Can be sent via relays as well as directly
|
||||||
|
Relay(NodeRef, DHTKey), // Can only be sent via a relay
|
||||||
|
PrivateRoute(PrivateRoute), // Must be encapsulated in a private route
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -131,7 +133,7 @@ struct WaitableReply {
|
|||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct InfoAnswer {
|
pub struct InfoAnswer {
|
||||||
pub latency: u64,
|
pub latency: u64,
|
||||||
pub node_info: NodeInfo,
|
pub node_status: NodeStatus,
|
||||||
pub sender_info: SenderInfo,
|
pub sender_info: SenderInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ pub struct RPCProcessorInner {
|
|||||||
pub struct RPCProcessor {
|
pub struct RPCProcessor {
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
config: VeilidConfig,
|
config: VeilidConfig,
|
||||||
default_peer_scope: PeerScope,
|
enable_local_peer_scope: bool,
|
||||||
inner: Arc<Mutex<RPCProcessorInner>>,
|
inner: Arc<Mutex<RPCProcessorInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,16 +183,11 @@ impl RPCProcessor {
|
|||||||
Self {
|
Self {
|
||||||
crypto: network_manager.crypto(),
|
crypto: network_manager.crypto(),
|
||||||
config: network_manager.config(),
|
config: network_manager.config(),
|
||||||
default_peer_scope: if !network_manager
|
enable_local_peer_scope: network_manager
|
||||||
.config()
|
.config()
|
||||||
.get()
|
.get()
|
||||||
.network
|
.network
|
||||||
.enable_local_peer_scope
|
.enable_local_peer_scope,
|
||||||
{
|
|
||||||
PeerScope::Global
|
|
||||||
} else {
|
|
||||||
PeerScope::All
|
|
||||||
},
|
|
||||||
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
|
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,16 +217,18 @@ impl RPCProcessor {
|
|||||||
fn filter_peer_scope(&self, peer_info: &PeerInfo) -> bool {
|
fn filter_peer_scope(&self, peer_info: &PeerInfo) -> bool {
|
||||||
// reject attempts to include non-public addresses in results
|
// reject attempts to include non-public addresses in results
|
||||||
if self.default_peer_scope == PeerScope::Global {
|
if self.default_peer_scope == PeerScope::Global {
|
||||||
for di in &peer_info.node_info.dial_infos {
|
for di in &peer_info.node_info.dial_info_list {
|
||||||
if !di.is_global() {
|
if !di.is_global() {
|
||||||
// non-public address causes rejection
|
// non-public address causes rejection
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for di in &peer_info.node_info.relay_dial_infos {
|
if let Some(rpi) = peer_info.node_info.relay_peer_info {
|
||||||
if !di.is_global() {
|
for di in &rpi.node_info.dial_info_list {
|
||||||
// non-public address causes rejection
|
if !di.is_global() {
|
||||||
return false;
|
// non-public address causes rejection
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,9 +276,9 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// First see if we have the node in our routing table already
|
// First see if we have the node in our routing table already
|
||||||
if let Some(nr) = routing_table.lookup_node_ref(node_id) {
|
if let Some(nr) = routing_table.lookup_node_ref(node_id) {
|
||||||
// ensure we have dial_info for the entry already,
|
// ensure we have some dial info for the entry already,
|
||||||
// if not, we should do the find_node anyway
|
// if not, we should do the find_node anyway
|
||||||
if !nr.has_dial_info() {
|
if !nr.has_any_dial_info() {
|
||||||
return Ok(nr);
|
return Ok(nr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,8 +376,8 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((rpcreader, _)) => {
|
Ok((rpcreader, _)) => {
|
||||||
// Note that we definitely received this peer info since we got a reply
|
// Note that we definitely received this node info since we got a reply
|
||||||
waitable_reply.node_ref.set_seen_our_dial_info();
|
waitable_reply.node_ref.set_seen_our_node_info();
|
||||||
|
|
||||||
// Reply received
|
// Reply received
|
||||||
let recv_ts = get_timestamp();
|
let recv_ts = get_timestamp();
|
||||||
@ -434,10 +433,20 @@ impl RPCProcessor {
|
|||||||
let out;
|
let out;
|
||||||
|
|
||||||
// To where are we sending the request
|
// To where are we sending the request
|
||||||
match dest {
|
match &dest {
|
||||||
Destination::Direct(node_ref) => {
|
Destination::Direct(node_ref) | Destination::Normal(node_ref) => {
|
||||||
// Send to a node without a private route
|
// Send to a node without a private route
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
||||||
|
// Get the actual destination node id, accounting for outbound relaying
|
||||||
|
let (node_ref, node_id) = if matches!(dest, Destination::Normal(_)) {
|
||||||
|
self.get_direct_destination(node_ref.clone())?
|
||||||
|
} else {
|
||||||
|
let node_id = node_ref.node_id();
|
||||||
|
(node_ref.clone(), node_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle the existence of safety route
|
||||||
match safety_route_spec {
|
match safety_route_spec {
|
||||||
None => {
|
None => {
|
||||||
// If no safety route is being used, and we're not sending to a private
|
// If no safety route is being used, and we're not sending to a private
|
||||||
@ -445,7 +454,7 @@ impl RPCProcessor {
|
|||||||
out = reader_to_vec(message)?;
|
out = reader_to_vec(message)?;
|
||||||
|
|
||||||
// Message goes directly to the node
|
// Message goes directly to the node
|
||||||
out_node_id = node_ref.node_id();
|
out_node_id = node_id;
|
||||||
out_noderef = Some(node_ref);
|
out_noderef = Some(node_ref);
|
||||||
hopcount = 1;
|
hopcount = 1;
|
||||||
}
|
}
|
||||||
@ -454,7 +463,7 @@ impl RPCProcessor {
|
|||||||
// but we are using a safety route, so we must create an empty private route
|
// but we are using a safety route, so we must create an empty private route
|
||||||
let mut pr_builder = ::capnp::message::Builder::new_default();
|
let mut pr_builder = ::capnp::message::Builder::new_default();
|
||||||
let private_route =
|
let private_route =
|
||||||
self.new_stub_private_route(node_ref.node_id(), &mut pr_builder)?;
|
self.new_stub_private_route(node_id, &mut pr_builder)?;
|
||||||
|
|
||||||
let message_vec = reader_to_vec(message)?;
|
let message_vec = reader_to_vec(message)?;
|
||||||
// first
|
// first
|
||||||
@ -487,7 +496,7 @@ impl RPCProcessor {
|
|||||||
None => {
|
None => {
|
||||||
// If no safety route, the first node is the first hop of the private route
|
// If no safety route, the first node is the first hop of the private route
|
||||||
hopcount = private_route.hop_count as usize;
|
hopcount = private_route.hop_count as usize;
|
||||||
let out_node_id = match private_route.hops {
|
let out_node_id = match &private_route.hops {
|
||||||
Some(rh) => rh.dial_info.node_id.key,
|
Some(rh) => rh.dial_info.node_id.key,
|
||||||
_ => return Err(rpc_error_internal("private route has no hops")),
|
_ => return Err(rpc_error_internal("private route has no hops")),
|
||||||
};
|
};
|
||||||
@ -547,7 +556,7 @@ impl RPCProcessor {
|
|||||||
let bytes = out.len() as u64;
|
let bytes = out.len() as u64;
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
.network_manager()
|
.network_manager()
|
||||||
.send_envelope(node_ref.clone(), out)
|
.send_envelope(node_ref.clone(), Some(out_node_id), out)
|
||||||
.await
|
.await
|
||||||
.map_err(logthru_rpc!(error))
|
.map_err(logthru_rpc!(error))
|
||||||
.map_err(RPCError::Internal)
|
.map_err(RPCError::Internal)
|
||||||
@ -735,7 +744,7 @@ impl RPCProcessor {
|
|||||||
// Send the reply
|
// Send the reply
|
||||||
let bytes = out.len() as u64;
|
let bytes = out.len() as u64;
|
||||||
self.network_manager()
|
self.network_manager()
|
||||||
.send_envelope(node_ref.clone(), out)
|
.send_envelope(node_ref.clone(), Some(out_node_id), out)
|
||||||
.await
|
.await
|
||||||
.map_err(RPCError::Internal)?;
|
.map_err(RPCError::Internal)?;
|
||||||
|
|
||||||
@ -762,17 +771,17 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_respond_to_sender_dial_info(
|
fn get_respond_to_sender_node_info(
|
||||||
&self,
|
&self,
|
||||||
operation: &veilid_capnp::operation::Reader,
|
operation: &veilid_capnp::operation::Reader,
|
||||||
) -> Result<Option<DialInfo>, RPCError> {
|
) -> Result<Option<NodeInfo>, RPCError> {
|
||||||
if let veilid_capnp::operation::respond_to::Sender(Ok(sender_di_reader)) = operation
|
if let veilid_capnp::operation::respond_to::Sender(Ok(sender_ni_reader)) = operation
|
||||||
.get_respond_to()
|
.get_respond_to()
|
||||||
.which()
|
.which()
|
||||||
.map_err(map_error_capnp_notinschema!())?
|
.map_err(map_error_capnp_notinschema!())?
|
||||||
{
|
{
|
||||||
// Sender DialInfo was specified, update our routing table with it
|
// Sender DialInfo was specified, update our routing table with it
|
||||||
Ok(Some(decode_dial_info(&sender_di_reader)?))
|
Ok(Some(decode_node_info(&sender_ni_reader, true)?))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -809,17 +818,17 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parse out fields
|
// Parse out fields
|
||||||
let node_info = decode_node_info(
|
let node_status = decode_node_status(
|
||||||
&iq_reader
|
&iq_reader
|
||||||
.get_node_info()
|
.get_node_status()
|
||||||
.map_err(map_error_internal!("no valid node info"))?,
|
.map_err(map_error_internal!("no valid node status"))?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// add node information for the requesting node to our routing table
|
// update node status for the requesting node to our routing table
|
||||||
if let Some(sender_nr) = rpcreader.opt_sender_nr.clone() {
|
if let Some(sender_nr) = rpcreader.opt_sender_nr.clone() {
|
||||||
// Update latest node info in routing table for the infoq sender
|
// Update latest node status in routing table for the infoq sender
|
||||||
sender_nr.operate(|e| {
|
sender_nr.operate(|e| {
|
||||||
e.update_node_info(node_info);
|
e.update_node_status(node_status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -831,10 +840,12 @@ impl RPCProcessor {
|
|||||||
respond_to.set_none(());
|
respond_to.set_none(());
|
||||||
let detail = answer.reborrow().init_detail();
|
let detail = answer.reborrow().init_detail();
|
||||||
let mut info_a = detail.init_info_a();
|
let mut info_a = detail.init_info_a();
|
||||||
// Add node info
|
|
||||||
let node_info = self.network_manager().generate_node_info();
|
// Add node status
|
||||||
let mut nib = info_a.reborrow().init_node_info();
|
let node_status = self.network_manager().generate_node_status();
|
||||||
encode_node_info(&node_info, &mut nib)?;
|
let mut nsb = info_a.reborrow().init_node_status();
|
||||||
|
encode_node_status(&node_status, &mut nsb)?;
|
||||||
|
|
||||||
// Add sender info
|
// Add sender info
|
||||||
let sender_info = self.generate_sender_info(&rpcreader);
|
let sender_info = self.generate_sender_info(&rpcreader);
|
||||||
let mut sib = info_a.reborrow().init_sender_info();
|
let mut sib = info_a.reborrow().init_sender_info();
|
||||||
@ -898,7 +909,7 @@ impl RPCProcessor {
|
|||||||
for peer in peers {
|
for peer in peers {
|
||||||
// See if this peer will validate dial info
|
// See if this peer will validate dial info
|
||||||
let will_validate_dial_info = peer.operate(|e: &mut BucketEntry| {
|
let will_validate_dial_info = peer.operate(|e: &mut BucketEntry| {
|
||||||
if let Some(ni) = &e.peer_stats().node_info {
|
if let Some(ni) = &e.peer_stats().status {
|
||||||
ni.will_validate_dial_info
|
ni.will_validate_dial_info
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
@ -980,23 +991,14 @@ impl RPCProcessor {
|
|||||||
.map_err(logthru_rpc!())?,
|
.map_err(logthru_rpc!())?,
|
||||||
);
|
);
|
||||||
|
|
||||||
// get the peerinfo/dialinfos of the requesting node
|
// get the sender NodeInfo of the requesting node
|
||||||
let dil_reader = fnq_reader
|
let sni_reader = fnq_reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_dial_info_list()
|
.get_sender_node_info()
|
||||||
.map_err(map_error_capnp_error!())?;
|
.map_err(map_error_capnp_error!())?;
|
||||||
let mut dial_infos = Vec::<DialInfo>::with_capacity(
|
|
||||||
dil_reader
|
|
||||||
.len()
|
|
||||||
.try_into()
|
|
||||||
.map_err(map_error_protocol!("too many dial infos"))?,
|
|
||||||
);
|
|
||||||
for di in dil_reader.iter() {
|
|
||||||
dial_infos.push(decode_dial_info(&di)?)
|
|
||||||
}
|
|
||||||
let peer_info = PeerInfo {
|
let peer_info = PeerInfo {
|
||||||
node_id: NodeId::new(rpcreader.header.envelope.get_sender_id()),
|
node_id: NodeId::new(rpcreader.header.envelope.get_sender_id()),
|
||||||
dial_infos,
|
node_info: decode_node_info(&sni_reader, true)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
// filter out attempts to pass non-public addresses in for peers
|
// filter out attempts to pass non-public addresses in for peers
|
||||||
@ -1007,19 +1009,17 @@ impl RPCProcessor {
|
|||||||
// add node information for the requesting node to our routing table
|
// add node information for the requesting node to our routing table
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let _requesting_node_ref = routing_table
|
let _requesting_node_ref = routing_table
|
||||||
.register_node_with_dial_info(peer_info.node_id.key, &peer_info.dial_infos)
|
.register_node_with_node_info(peer_info.node_id.key, peer_info.node_info)
|
||||||
.map_err(map_error_string!())?;
|
.map_err(map_error_string!())?;
|
||||||
|
|
||||||
// find N nodes closest to the target node in our routing table
|
// find N nodes closest to the target node in our routing table
|
||||||
let own_peer_info = routing_table.get_own_peer_info(self.default_peer_scope);
|
let own_peer_info = routing_table.get_own_peer_info();
|
||||||
let closest_nodes = routing_table.find_closest_nodes(
|
let closest_nodes = routing_table.find_closest_nodes(
|
||||||
target_node_id,
|
target_node_id,
|
||||||
// filter
|
// filter
|
||||||
None,
|
None,
|
||||||
// transform
|
// transform
|
||||||
|e| {
|
|e| RoutingTable::transform_to_peer_info(e, &own_peer_info),
|
||||||
RoutingTable::transform_to_peer_info(e, self.default_peer_scope, &own_peer_info)
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
log_rpc!(">>>> Returning {} closest peers", closest_nodes.len());
|
log_rpc!(">>>> Returning {} closest peers", closest_nodes.len());
|
||||||
|
|
||||||
@ -1076,8 +1076,8 @@ impl RPCProcessor {
|
|||||||
Err(rpc_error_unimplemented("process_find_block_q"))
|
Err(rpc_error_unimplemented("process_find_block_q"))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_signal_q(&self, _rpcreader: RPCMessageReader) -> Result<(), RPCError> {
|
async fn process_signal(&self, _rpcreader: RPCMessageReader) -> Result<(), RPCError> {
|
||||||
Err(rpc_error_unimplemented("process_signal_q"))
|
Err(rpc_error_unimplemented("process_signal"))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_return_receipt(&self, rpcreader: RPCMessageReader) -> Result<(), RPCError> {
|
async fn process_return_receipt(&self, rpcreader: RPCMessageReader) -> Result<(), RPCError> {
|
||||||
@ -1176,28 +1176,27 @@ impl RPCProcessor {
|
|||||||
veilid_capnp::operation::detail::SupplyBlockA(_) => (14u32, false),
|
veilid_capnp::operation::detail::SupplyBlockA(_) => (14u32, false),
|
||||||
veilid_capnp::operation::detail::FindBlockQ(_) => (15u32, true),
|
veilid_capnp::operation::detail::FindBlockQ(_) => (15u32, true),
|
||||||
veilid_capnp::operation::detail::FindBlockA(_) => (16u32, false),
|
veilid_capnp::operation::detail::FindBlockA(_) => (16u32, false),
|
||||||
veilid_capnp::operation::detail::SignalQ(_) => (17u32, true),
|
veilid_capnp::operation::detail::Signal(_) => (17u32, true),
|
||||||
veilid_capnp::operation::detail::SignalA(_) => (18u32, false),
|
veilid_capnp::operation::detail::ReturnReceipt(_) => (18u32, true),
|
||||||
veilid_capnp::operation::detail::ReturnReceipt(_) => (19u32, true),
|
veilid_capnp::operation::detail::StartTunnelQ(_) => (19u32, true),
|
||||||
veilid_capnp::operation::detail::StartTunnelQ(_) => (20u32, true),
|
veilid_capnp::operation::detail::StartTunnelA(_) => (20u32, false),
|
||||||
veilid_capnp::operation::detail::StartTunnelA(_) => (21u32, false),
|
veilid_capnp::operation::detail::CompleteTunnelQ(_) => (21u32, true),
|
||||||
veilid_capnp::operation::detail::CompleteTunnelQ(_) => (22u32, true),
|
veilid_capnp::operation::detail::CompleteTunnelA(_) => (22u32, false),
|
||||||
veilid_capnp::operation::detail::CompleteTunnelA(_) => (23u32, false),
|
veilid_capnp::operation::detail::CancelTunnelQ(_) => (23u32, true),
|
||||||
veilid_capnp::operation::detail::CancelTunnelQ(_) => (24u32, true),
|
veilid_capnp::operation::detail::CancelTunnelA(_) => (24u32, false),
|
||||||
veilid_capnp::operation::detail::CancelTunnelA(_) => (25u32, false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Accounting for questions we receive
|
// Accounting for questions we receive
|
||||||
if is_q {
|
if is_q {
|
||||||
// See if we have some Sender DialInfo to incorporate
|
// See if we have some Sender NodeInfo to incorporate
|
||||||
opt_sender_nr =
|
opt_sender_nr =
|
||||||
if let Some(sender_di) = self.get_respond_to_sender_dial_info(&operation)? {
|
if let Some(sender_ni) = self.get_respond_to_sender_node_info(&operation)? {
|
||||||
// Sender DialInfo was specified, update our routing table with it
|
// Sender NodeInfo was specified, update our routing table with it
|
||||||
let nr = self
|
let nr = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.update_node_with_single_dial_info(
|
.register_node_with_node_info(
|
||||||
msg.header.envelope.get_sender_id(),
|
msg.header.envelope.get_sender_id(),
|
||||||
&sender_di,
|
sender_ni,
|
||||||
)
|
)
|
||||||
.map_err(RPCError::Internal)?;
|
.map_err(RPCError::Internal)?;
|
||||||
Some(nr)
|
Some(nr)
|
||||||
@ -1251,15 +1250,14 @@ impl RPCProcessor {
|
|||||||
14 => self.process_answer(rpcreader).await, // SupplyBlockA
|
14 => self.process_answer(rpcreader).await, // SupplyBlockA
|
||||||
15 => self.process_find_block_q(rpcreader).await, // FindBlockQ
|
15 => self.process_find_block_q(rpcreader).await, // FindBlockQ
|
||||||
16 => self.process_answer(rpcreader).await, // FindBlockA
|
16 => self.process_answer(rpcreader).await, // FindBlockA
|
||||||
17 => self.process_signal_q(rpcreader).await, // SignalQ
|
17 => self.process_signal(rpcreader).await, // SignalQ
|
||||||
18 => self.process_answer(rpcreader).await, // SignalA
|
18 => self.process_return_receipt(rpcreader).await, // ReturnReceipt
|
||||||
19 => self.process_return_receipt(rpcreader).await, // ReturnReceipt
|
19 => self.process_start_tunnel_q(rpcreader).await, // StartTunnelQ
|
||||||
20 => self.process_start_tunnel_q(rpcreader).await, // StartTunnelQ
|
20 => self.process_answer(rpcreader).await, // StartTunnelA
|
||||||
21 => self.process_answer(rpcreader).await, // StartTunnelA
|
21 => self.process_complete_tunnel_q(rpcreader).await, // CompleteTunnelQ
|
||||||
22 => self.process_complete_tunnel_q(rpcreader).await, // CompleteTunnelQ
|
22 => self.process_answer(rpcreader).await, // CompleteTunnelA
|
||||||
23 => self.process_answer(rpcreader).await, // CompleteTunnelA
|
23 => self.process_cancel_tunnel_q(rpcreader).await, // CancelTunnelQ
|
||||||
24 => self.process_cancel_tunnel_q(rpcreader).await, // CancelTunnelQ
|
24 => self.process_answer(rpcreader).await, // CancelTunnelA
|
||||||
25 => self.process_answer(rpcreader).await, // CancelTunnelA
|
|
||||||
_ => panic!("must update rpc table"),
|
_ => panic!("must update rpc table"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1361,19 +1359,15 @@ impl RPCProcessor {
|
|||||||
// Gets a 'RespondTo::Sender' that contains either our dial info,
|
// Gets a 'RespondTo::Sender' that contains either our dial info,
|
||||||
// or None if the peer has seen our dial info before
|
// or None if the peer has seen our dial info before
|
||||||
pub fn get_respond_to_sender(&self, peer: NodeRef) -> RespondTo {
|
pub fn get_respond_to_sender(&self, peer: NodeRef) -> RespondTo {
|
||||||
if peer.has_seen_our_dial_info() {
|
if peer.has_seen_our_node_info() {
|
||||||
RespondTo::Sender(None)
|
RespondTo::Sender(None)
|
||||||
} else if let Some(did) = self
|
|
||||||
.routing_table()
|
|
||||||
.first_filtered_dial_info_detail(peer.dial_info_filter())
|
|
||||||
{
|
|
||||||
RespondTo::Sender(Some(did.dial_info))
|
|
||||||
} else {
|
} else {
|
||||||
RespondTo::Sender(None)
|
RespondTo::Sender(Some(self.routing_table().get_own_peer_info().node_info))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send InfoQ RPC request, receive InfoA answer
|
// Send InfoQ RPC request, receive InfoA answer
|
||||||
|
// Can be sent via relays, but not via routes
|
||||||
pub async fn rpc_call_info(self, peer: NodeRef) -> Result<InfoAnswer, RPCError> {
|
pub async fn rpc_call_info(self, peer: NodeRef) -> Result<InfoAnswer, RPCError> {
|
||||||
let info_q_msg = {
|
let info_q_msg = {
|
||||||
let mut info_q_msg = ::capnp::message::Builder::new_default();
|
let mut info_q_msg = ::capnp::message::Builder::new_default();
|
||||||
@ -1384,9 +1378,9 @@ impl RPCProcessor {
|
|||||||
.encode(&mut respond_to)?;
|
.encode(&mut respond_to)?;
|
||||||
let detail = question.reborrow().init_detail();
|
let detail = question.reborrow().init_detail();
|
||||||
let mut iqb = detail.init_info_q();
|
let mut iqb = detail.init_info_q();
|
||||||
let mut node_info_builder = iqb.reborrow().init_node_info();
|
let mut node_status_builder = iqb.reborrow().init_node_status();
|
||||||
let node_info = self.network_manager().generate_node_info();
|
let node_status = self.network_manager().generate_node_status();
|
||||||
encode_node_info(&node_info, &mut node_info_builder)?;
|
encode_node_status(&node_status, &mut node_status_builder)?;
|
||||||
|
|
||||||
info_q_msg.into_reader()
|
info_q_msg.into_reader()
|
||||||
};
|
};
|
||||||
@ -1418,13 +1412,13 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Decode node info
|
// Decode node info
|
||||||
if !info_a.has_node_info() {
|
if !info_a.has_node_status() {
|
||||||
return Err(rpc_error_internal("Missing node info"));
|
return Err(rpc_error_internal("Missing node status"));
|
||||||
}
|
}
|
||||||
let nir = info_a
|
let nsr = info_a
|
||||||
.get_node_info()
|
.get_node_status()
|
||||||
.map_err(map_error_internal!("Broken node info"))?;
|
.map_err(map_error_internal!("Broken node status"))?;
|
||||||
let node_info = decode_node_info(&nir)?;
|
let node_status = decode_node_status(&nsr)?;
|
||||||
|
|
||||||
// Decode sender info
|
// Decode sender info
|
||||||
let sender_info = if info_a.has_sender_info() {
|
let sender_info = if info_a.has_sender_info() {
|
||||||
@ -1436,21 +1430,22 @@ impl RPCProcessor {
|
|||||||
SenderInfo::default()
|
SenderInfo::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update latest node info in routing table
|
// Update latest node status in routing table
|
||||||
peer.operate(|e| {
|
peer.operate(|e| {
|
||||||
e.update_node_info(node_info.clone());
|
e.update_node_status(node_status.clone());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return the answer for anyone who may care
|
// Return the answer for anyone who may care
|
||||||
let out = InfoAnswer {
|
let out = InfoAnswer {
|
||||||
latency,
|
latency,
|
||||||
node_info,
|
node_status,
|
||||||
sender_info,
|
sender_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Can only be sent directly, not via relays or routes
|
||||||
pub async fn rpc_call_validate_dial_info(
|
pub async fn rpc_call_validate_dial_info(
|
||||||
&self,
|
&self,
|
||||||
peer: NodeRef,
|
peer: NodeRef,
|
||||||
@ -1496,7 +1491,8 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Send the validate_dial_info request
|
// Send the validate_dial_info request
|
||||||
self.request(Destination::Direct(peer.clone()), vdi_msg, None)
|
// This can only be sent directly, as relays can not validate dial info
|
||||||
|
self.request(Destination::Direct(peer), vdi_msg, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Wait for receipt
|
// Wait for receipt
|
||||||
@ -1510,6 +1506,7 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send FindNodeQ RPC request, receive FindNodeA answer
|
// Send FindNodeQ RPC request, receive FindNodeA answer
|
||||||
|
// Can be sent via all methods including relays and routes
|
||||||
pub async fn rpc_call_find_node(
|
pub async fn rpc_call_find_node(
|
||||||
self,
|
self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
@ -1528,22 +1525,10 @@ impl RPCProcessor {
|
|||||||
let mut node_id_builder = fnq.reborrow().init_node_id();
|
let mut node_id_builder = fnq.reborrow().init_node_id();
|
||||||
encode_public_key(&key, &mut node_id_builder)?;
|
encode_public_key(&key, &mut node_id_builder)?;
|
||||||
|
|
||||||
let own_peer_info = self
|
let own_peer_info = self.routing_table().get_own_peer_info();
|
||||||
.routing_table()
|
|
||||||
.get_own_peer_info(self.default_peer_scope);
|
|
||||||
|
|
||||||
let mut dil_builder = fnq.reborrow().init_dial_info_list(
|
let mut ni_builder = fnq.reborrow().init_sender_node_info();
|
||||||
own_peer_info
|
encode_node_info(&own_peer_info.node_info, &mut ni_builder)?;
|
||||||
.dial_infos
|
|
||||||
.len()
|
|
||||||
.try_into()
|
|
||||||
.map_err(map_error_internal!("too many dial infos in peer info"))?,
|
|
||||||
);
|
|
||||||
|
|
||||||
for idx in 0..own_peer_info.dial_infos.len() {
|
|
||||||
let mut di_builder = dil_builder.reborrow().get(idx as u32);
|
|
||||||
encode_dial_info(&own_peer_info.dial_infos[idx], &mut di_builder)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
find_node_q_msg.into_reader()
|
find_node_q_msg.into_reader()
|
||||||
};
|
};
|
||||||
@ -1584,7 +1569,7 @@ impl RPCProcessor {
|
|||||||
.map_err(map_error_internal!("too many peers"))?,
|
.map_err(map_error_internal!("too many peers"))?,
|
||||||
);
|
);
|
||||||
for p in peers_reader.iter() {
|
for p in peers_reader.iter() {
|
||||||
let peer_info = decode_peer_info(&p)?;
|
let peer_info = decode_peer_info(&p, true)?;
|
||||||
|
|
||||||
if !self.filter_peer_scope(&peer_info) {
|
if !self.filter_peer_scope(&peer_info) {
|
||||||
return Err(RPCError::InvalidFormat);
|
return Err(RPCError::InvalidFormat);
|
||||||
@ -1598,5 +1583,35 @@ impl RPCProcessor {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sends a unidirectional signal to a node
|
||||||
|
// Can be sent via all methods including relays and routes
|
||||||
|
pub async fn rpc_call_signal(
|
||||||
|
&self,
|
||||||
|
dest: Destination,
|
||||||
|
relay_dial_info: DialInfo,
|
||||||
|
safety_route: Option<&SafetyRouteSpec>,
|
||||||
|
signal_info: SignalInfo,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
let network_manager = self.network_manager();
|
||||||
|
//
|
||||||
|
let sig_msg = {
|
||||||
|
let mut sig_msg = ::capnp::message::Builder::new_default();
|
||||||
|
let mut question = sig_msg.init_root::<veilid_capnp::operation::Builder>();
|
||||||
|
question.set_op_id(self.get_next_op_id());
|
||||||
|
let mut respond_to = question.reborrow().init_respond_to();
|
||||||
|
respond_to.set_none(());
|
||||||
|
let detail = question.reborrow().init_detail();
|
||||||
|
let mut sig_builder = detail.init_signal();
|
||||||
|
encode_signal_info(&signal_info, &mut sig_builder)?;
|
||||||
|
|
||||||
|
sig_msg.into_reader()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the signal request
|
||||||
|
self.request(dest, sig_msg, safety_route).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// xxx do not process latency for routed messages
|
// xxx do not process latency for routed messages
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,9 @@ impl fmt::Display for VeilidAPIError {
|
|||||||
fn convert_rpc_error(x: RPCError) -> VeilidAPIError {
|
fn convert_rpc_error(x: RPCError) -> VeilidAPIError {
|
||||||
match x {
|
match x {
|
||||||
RPCError::Timeout => VeilidAPIError::Timeout,
|
RPCError::Timeout => VeilidAPIError::Timeout,
|
||||||
|
RPCError::Unreachable(n) => VeilidAPIError::NodeNotFound {
|
||||||
|
node_id: NodeId::new(n),
|
||||||
|
},
|
||||||
RPCError::Unimplemented(s) => VeilidAPIError::Unimplemented { message: s },
|
RPCError::Unimplemented(s) => VeilidAPIError::Unimplemented { message: s },
|
||||||
RPCError::Internal(s) => VeilidAPIError::Internal { message: s },
|
RPCError::Internal(s) => VeilidAPIError::Internal { message: s },
|
||||||
RPCError::Protocol(s) => VeilidAPIError::Internal { message: s },
|
RPCError::Protocol(s) => VeilidAPIError::Internal { message: s },
|
||||||
@ -324,50 +327,54 @@ pub struct NodeStatus {
|
|||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct NodeInfo {
|
pub struct NodeInfo {
|
||||||
pub network_class: NetworkClass,
|
pub network_class: NetworkClass,
|
||||||
pub dial_infos: Vec<DialInfo>,
|
pub outbound_protocols: ProtocolSet,
|
||||||
pub relay_dial_infos: Vec<DialInfo>,
|
pub dial_info_list: Vec<DialInfo>,
|
||||||
|
pub relay_peer_info: Option<Box<PeerInfo>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
|
pub struct LocalNodeInfo {
|
||||||
|
pub outbound_protocols: ProtocolSet,
|
||||||
|
pub dial_info_list: Vec<DialInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeInfo {
|
impl NodeInfo {
|
||||||
pub fn first_filtered<F>(&self, filter: F) -> NodeInfo
|
pub fn first_filtered_dial_info<F>(&self, filter: F) -> Option<DialInfo>
|
||||||
where
|
where
|
||||||
F: Fn(&DialInfo) -> bool,
|
F: Fn(&DialInfo) -> bool,
|
||||||
{
|
{
|
||||||
let mut node_info = NodeInfo::default();
|
for di in &self.dial_info_list {
|
||||||
node_info.network_class = self.network_class;
|
|
||||||
|
|
||||||
for di in &self.dial_infos {
|
|
||||||
if filter(di) {
|
if filter(di) {
|
||||||
node_info.dial_infos.push(di.clone());
|
return Some(di.clone());
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for di in &self.relay_dial_infos {
|
None
|
||||||
if filter(di) {
|
|
||||||
node_info.relay_dial_infos.push(di.clone());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node_info
|
|
||||||
}
|
}
|
||||||
pub fn all_filtered<F>(&self, filter: F) -> NodeInfo
|
|
||||||
|
pub fn all_filtered_dial_info<F>(&self, filter: F) -> Vec<DialInfo>
|
||||||
where
|
where
|
||||||
F: Fn(&DialInfo) -> bool,
|
F: Fn(&DialInfo) -> bool,
|
||||||
{
|
{
|
||||||
let mut node_info = NodeInfo::default();
|
let mut dial_info_list = Vec::new();
|
||||||
node_info.network_class = self.network_class;
|
|
||||||
|
|
||||||
for di in &self.dial_infos {
|
for di in &self.dial_info_list {
|
||||||
if filter(di) {
|
if filter(di) {
|
||||||
node_info.dial_infos.push(di.clone());
|
dial_info_list.push(di.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for di in &self.relay_dial_infos {
|
dial_info_list
|
||||||
if filter(di) {
|
}
|
||||||
node_info.relay_dial_infos.push(di.clone());
|
|
||||||
}
|
pub fn has_any_dial_info(&self) -> bool {
|
||||||
}
|
!self.dial_info_list.is_empty()
|
||||||
node_info
|
|| !self
|
||||||
|
.relay_peer_info
|
||||||
|
.map(|rpi| rpi.node_info.has_direct_dial_info())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_direct_dial_info(&self) -> bool {
|
||||||
|
!self.dial_info_list.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,6 +388,28 @@ pub enum ProtocolType {
|
|||||||
WSS,
|
WSS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
|
pub struct ProtocolSet {
|
||||||
|
pub udp: bool,
|
||||||
|
pub tcp: bool,
|
||||||
|
pub ws: bool,
|
||||||
|
pub wss: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProtocolSet {
|
||||||
|
pub fn is_protocol_type_enabled(&self, protocol_type: ProtocolType) -> bool {
|
||||||
|
match protocol_type {
|
||||||
|
ProtocolType::UDP => self.udp,
|
||||||
|
ProtocolType::TCP => self.tcp,
|
||||||
|
ProtocolType::WS => self.ws,
|
||||||
|
ProtocolType::WSS => self.wss,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn filter_dial_info(&self, di: &DialInfo) -> bool {
|
||||||
|
self.is_protocol_type_enabled(di.protocol_type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum AddressType {
|
pub enum AddressType {
|
||||||
IPV4,
|
IPV4,
|
||||||
@ -1057,7 +1086,25 @@ cfg_if! {
|
|||||||
Arc<dyn Fn(ValueKey, Vec<u8>) -> SystemPinBoxFuture<()> + Send + Sync + 'static>;
|
Arc<dyn Fn(ValueKey, Vec<u8>) -> SystemPinBoxFuture<()> + Send + Sync + 'static>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum SignalInfo {
|
||||||
|
HolePunch {
|
||||||
|
// UDP Hole Punch Request
|
||||||
|
receipt: Vec<u8>, // Receipt to be returned after the hole punch
|
||||||
|
node_info: NodeInfo, // Sender's node info
|
||||||
|
},
|
||||||
|
ReverseConnect {
|
||||||
|
// Reverse Connection Request
|
||||||
|
receipt: Vec<u8>, // Receipt to be returned by the reverse connection
|
||||||
|
node_info: NodeInfo, // Sender's node info
|
||||||
|
},
|
||||||
|
// XXX: WebRTC
|
||||||
|
// XXX: App-level signalling
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||||
pub enum TunnelMode {
|
pub enum TunnelMode {
|
||||||
Raw,
|
Raw,
|
||||||
@ -1139,14 +1186,6 @@ pub struct RoutingContextOptions {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
|
||||||
pub struct SearchDHTAnswer {
|
|
||||||
pub node_id: NodeId,
|
|
||||||
pub dial_info: Vec<DialInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
pub struct RoutingContextInner {
|
pub struct RoutingContextInner {
|
||||||
api: VeilidAPI,
|
api: VeilidAPI,
|
||||||
options: RoutingContextOptions,
|
options: RoutingContextOptions,
|
||||||
@ -1397,7 +1436,7 @@ impl VeilidAPI {
|
|||||||
.map_err(map_rpc_error!())
|
.map_err(map_rpc_error!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn search_dht(&self, node_id: NodeId) -> Result<SearchDHTAnswer, VeilidAPIError> {
|
pub async fn search_dht(&self, node_id: NodeId) -> Result<PeerInfo, VeilidAPIError> {
|
||||||
let rpc_processor = self.rpc_processor()?;
|
let rpc_processor = self.rpc_processor()?;
|
||||||
let config = self.config()?;
|
let config = self.config()?;
|
||||||
let (count, fanout, timeout) = {
|
let (count, fanout, timeout) = {
|
||||||
@ -1414,18 +1453,12 @@ impl VeilidAPI {
|
|||||||
.await
|
.await
|
||||||
.map_err(map_rpc_error!())?;
|
.map_err(map_rpc_error!())?;
|
||||||
|
|
||||||
let answer = node_ref.operate(|e| SearchDHTAnswer {
|
let answer = node_ref.peer_info();
|
||||||
node_id: NodeId::new(node_ref.node_id()),
|
|
||||||
dial_info: e.dial_infos().to_vec(),
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(answer)
|
Ok(answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn search_dht_multi(
|
pub async fn search_dht_multi(&self, node_id: NodeId) -> Result<Vec<PeerInfo>, VeilidAPIError> {
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<Vec<SearchDHTAnswer>, VeilidAPIError> {
|
|
||||||
let rpc_processor = self.rpc_processor()?;
|
let rpc_processor = self.rpc_processor()?;
|
||||||
let config = self.config()?;
|
let config = self.config()?;
|
||||||
let (count, fanout, timeout) = {
|
let (count, fanout, timeout) = {
|
||||||
@ -1442,14 +1475,7 @@ impl VeilidAPI {
|
|||||||
.await
|
.await
|
||||||
.map_err(map_rpc_error!())?;
|
.map_err(map_rpc_error!())?;
|
||||||
|
|
||||||
let mut answer = Vec::<SearchDHTAnswer>::new();
|
let answer = node_refs.iter().map(|x| x.peer_info()).collect();
|
||||||
for nr in node_refs {
|
|
||||||
let a = nr.operate(|e| SearchDHTAnswer {
|
|
||||||
node_id: NodeId::new(nr.node_id()),
|
|
||||||
dial_info: e.dial_infos().to_vec(),
|
|
||||||
});
|
|
||||||
answer.push(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(answer)
|
Ok(answer)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigHTTPS {
|
pub struct VeilidConfigHTTPS {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
@ -23,7 +23,7 @@ pub struct VeilidConfigHTTPS {
|
|||||||
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigHTTP {
|
pub struct VeilidConfigHTTP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
@ -31,13 +31,13 @@ pub struct VeilidConfigHTTP {
|
|||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigApplication {
|
pub struct VeilidConfigApplication {
|
||||||
pub https: VeilidConfigHTTPS,
|
pub https: VeilidConfigHTTPS,
|
||||||
pub http: VeilidConfigHTTP,
|
pub http: VeilidConfigHTTP,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigUDP {
|
pub struct VeilidConfigUDP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub socket_pool_size: u32,
|
pub socket_pool_size: u32,
|
||||||
@ -45,7 +45,7 @@ pub struct VeilidConfigUDP {
|
|||||||
pub public_address: Option<String>,
|
pub public_address: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigTCP {
|
pub struct VeilidConfigTCP {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -54,7 +54,7 @@ pub struct VeilidConfigTCP {
|
|||||||
pub public_address: Option<String>,
|
pub public_address: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigWS {
|
pub struct VeilidConfigWS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -64,7 +64,7 @@ pub struct VeilidConfigWS {
|
|||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigWSS {
|
pub struct VeilidConfigWSS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
@ -74,7 +74,7 @@ pub struct VeilidConfigWSS {
|
|||||||
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigProtocol {
|
pub struct VeilidConfigProtocol {
|
||||||
pub udp: VeilidConfigUDP,
|
pub udp: VeilidConfigUDP,
|
||||||
pub tcp: VeilidConfigTCP,
|
pub tcp: VeilidConfigTCP,
|
||||||
@ -82,14 +82,14 @@ pub struct VeilidConfigProtocol {
|
|||||||
pub wss: VeilidConfigWSS,
|
pub wss: VeilidConfigWSS,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigTLS {
|
pub struct VeilidConfigTLS {
|
||||||
pub certificate_path: String,
|
pub certificate_path: String,
|
||||||
pub private_key_path: String,
|
pub private_key_path: String,
|
||||||
pub connection_initial_timeout_ms: u32,
|
pub connection_initial_timeout_ms: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigDHT {
|
pub struct VeilidConfigDHT {
|
||||||
pub resolve_node_timeout_ms: Option<u32>,
|
pub resolve_node_timeout_ms: Option<u32>,
|
||||||
pub resolve_node_count: u32,
|
pub resolve_node_count: u32,
|
||||||
@ -107,7 +107,7 @@ pub struct VeilidConfigDHT {
|
|||||||
pub nearby_node_percentage: u32,
|
pub nearby_node_percentage: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigRPC {
|
pub struct VeilidConfigRPC {
|
||||||
pub concurrency: u32,
|
pub concurrency: u32,
|
||||||
pub queue_size: u32,
|
pub queue_size: u32,
|
||||||
@ -117,14 +117,14 @@ pub struct VeilidConfigRPC {
|
|||||||
pub max_route_hop_count: u8,
|
pub max_route_hop_count: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigLeases {
|
pub struct VeilidConfigLeases {
|
||||||
pub max_server_signal_leases: u32,
|
pub max_server_signal_leases: u32,
|
||||||
pub max_server_relay_leases: u32,
|
pub max_server_relay_leases: u32,
|
||||||
pub max_client_signal_leases: u32,
|
pub max_client_signal_leases: u32,
|
||||||
pub max_client_relay_leases: u32,
|
pub max_client_relay_leases: u32,
|
||||||
}
|
}
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigRoutingTable {
|
pub struct VeilidConfigRoutingTable {
|
||||||
pub limit_over_attached: u32,
|
pub limit_over_attached: u32,
|
||||||
pub limit_fully_attached: u32,
|
pub limit_fully_attached: u32,
|
||||||
@ -133,12 +133,14 @@ pub struct VeilidConfigRoutingTable {
|
|||||||
pub limit_attached_weak: u32,
|
pub limit_attached_weak: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigNetwork {
|
pub struct VeilidConfigNetwork {
|
||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
pub connection_initial_timeout_ms: u32,
|
pub connection_initial_timeout_ms: u32,
|
||||||
pub connection_inactivity_timeout_ms: u32,
|
pub connection_inactivity_timeout_ms: u32,
|
||||||
pub client_whitelist_timeout_ms: u32,
|
pub client_whitelist_timeout_ms: u32,
|
||||||
|
pub reverse_connection_receipt_time_ms: u32,
|
||||||
|
pub hole_punch_receipt_time_ms: u32,
|
||||||
pub node_id: key::DHTKey,
|
pub node_id: key::DHTKey,
|
||||||
pub node_id_secret: key::DHTKeySecret,
|
pub node_id_secret: key::DHTKeySecret,
|
||||||
pub bootstrap: Vec<String>,
|
pub bootstrap: Vec<String>,
|
||||||
@ -155,19 +157,19 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub leases: VeilidConfigLeases,
|
pub leases: VeilidConfigLeases,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigTableStore {
|
pub struct VeilidConfigTableStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigBlockStore {
|
pub struct VeilidConfigBlockStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigProtectedStore {
|
pub struct VeilidConfigProtectedStore {
|
||||||
pub allow_insecure_fallback: bool,
|
pub allow_insecure_fallback: bool,
|
||||||
pub always_use_insecure_storage: bool,
|
pub always_use_insecure_storage: bool,
|
||||||
@ -175,7 +177,7 @@ pub struct VeilidConfigProtectedStore {
|
|||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigCapabilities {
|
pub struct VeilidConfigCapabilities {
|
||||||
pub protocol_udp: bool,
|
pub protocol_udp: bool,
|
||||||
pub protocol_connect_tcp: bool,
|
pub protocol_connect_tcp: bool,
|
||||||
@ -214,7 +216,7 @@ impl Default for VeilidConfigLogLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigInner {
|
pub struct VeilidConfigInner {
|
||||||
pub program_name: String,
|
pub program_name: String,
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user