public void AddNode(NodeContact contact) { if (contact.NodeEP.AddressFamily != _currentNode.NodeEP.AddressFamily) { return; } if (_routingTable.AddContact(contact)) { Debug.Write(this.GetType().Name, "node contact added: " + contact.ToString()); ThreadPool.QueueUserWorkItem(delegate(object state) { Query(DhtRpcPacket.CreatePingPacket(_currentNode), contact); }); } }
internal bool Ping(NodeContact contact) { DhtRpcPacket response = Query(DhtRpcPacket.CreatePingPacket(_currentNode), contact); return(response != null); }
private DhtRpcPacket ProcessQuery(DhtRpcPacket query, EndPoint remoteNodeEP) { //in case of remote node querying via Tor, remoteNodeEP.Address will be loopback IP. Use the onion address from the query as remote end point if (!_currentNode.NodeEP.Equals(remoteNodeEP)) { switch (remoteNodeEP.AddressFamily) { case AddressFamily.InterNetwork: case AddressFamily.InterNetworkV6: IPAddress remoteNodeAddress = (remoteNodeEP as IPEndPoint).Address; if (IPAddress.IsLoopback(remoteNodeAddress) && (query.SourceNodeEP.AddressFamily == AddressFamily.Unspecified) && (query.SourceNodeEP as DomainEndPoint).Address.EndsWith(".onion", StringComparison.OrdinalIgnoreCase)) { AddNode(query.SourceNodeEP); //use the tor hidden end point claimed by remote node } else { AddNode(new IPEndPoint(remoteNodeAddress, query.SourceNodeEP.GetPort())); //use remote node end point as seen by connection manager and use port from query } break; default: throw new NotSupportedException(); } } Debug.Write(this.GetType().Name, "query received from: " + remoteNodeEP.ToString() + "; type: " + query.Type.ToString()); //process query switch (query.Type) { case DhtRpcType.PING: return(DhtRpcPacket.CreatePingPacket(_currentNode)); case DhtRpcType.FIND_NODE: return(DhtRpcPacket.CreateFindNodePacketResponse(_currentNode, query.NetworkId, _routingTable.GetKClosestContacts(query.NetworkId, false))); case DhtRpcType.FIND_PEERS: EndPoint[] peers = _currentNode.GetPeers(query.NetworkId); if (peers.Length == 0) { return(DhtRpcPacket.CreateFindPeersPacketResponse(_currentNode, query.NetworkId, _routingTable.GetKClosestContacts(query.NetworkId, false), peers)); } else { return(DhtRpcPacket.CreateFindPeersPacketResponse(_currentNode, query.NetworkId, new NodeContact[] { }, peers)); } case DhtRpcType.ANNOUNCE_PEER: if ((query.Peers != null) && (query.Peers.Length > 0)) { EndPoint peerEP; if (query.Peers[0].AddressFamily == AddressFamily.Unspecified) { peerEP = query.Peers[0]; } else { peerEP = new IPEndPoint((remoteNodeEP as IPEndPoint).Address, query.Peers[0].GetPort()); } _currentNode.StorePeer(query.NetworkId, peerEP); } return(DhtRpcPacket.CreateAnnouncePeerPacketResponse(_currentNode, query.NetworkId, _currentNode.GetPeers(query.NetworkId))); default: throw new Exception("Invalid DHT-RPC type."); } }