public async Task ProcessGetProvidersMessage_HasCloserPeers() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { dht.RoutingTable.Add(other); Cid cid = "zBunRGrmCGokA1oMESGGTfrtcMFsVA8aEtcNzM54akPWXF97uXCqTjF3GZ9v8YzxHrG66J8QhtPFWwZebRZ2zeUEELu67"; var request = new DhtMessage { Type = MessageType.GetProviders, Key = cid.Hash.ToArray() }; var response = dht.ProcessGetProviders(request, new DhtMessage()); Assert.AreNotEqual(0, response.CloserPeers.Length); } finally { await dht.StopAsync(); } }
public async Task ProcessGetProvidersMessage_HasProvider() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { swarm.RegisterPeer(other); Cid cid = "zBunRGrmCGokA1oMESGGTfrtcMFsVA8aEtcNzM54akPWXF97uXCqTjF3GZ9v8YzxHrG66J8QhtPFWwZebRZ2zeUEELu67"; dht.ContentRouter.Add(cid, other.Id); var request = new DhtMessage { Type = MessageType.GetProviders, Key = cid.Hash.ToArray() }; var response = dht.ProcessGetProviders(request, new DhtMessage()); Assert.AreEqual(1, response.ProviderPeers.Length); response.ProviderPeers[0].TryToPeer(out var found); Assert.AreEqual(other, found); Assert.AreNotEqual(0, found.Addresses.Count()); } finally { await dht.StopAsync(); } }
public async Task ProcessFindNodeMessage_NoOtherPeers() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { var request = new DhtMessage { Type = MessageType.FindNode, Key = new MultiHash("QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h").ToArray() }; var response = dht.ProcessFindNode(request, new DhtMessage()); Assert.AreEqual(0, response.CloserPeers.Length); } finally { await dht.StopAsync(); } }
public async Task ProcessFindNodeMessage_BadNodeId() { var swarm = new SwarmService { LocalPeer = self }; swarm.RegisterPeerAddress("/ip4/127.0.0.1/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1a"); swarm.RegisterPeerAddress("/ip4/127.0.0.2/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1b"); swarm.RegisterPeerAddress("/ip4/127.0.0.3/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1c"); swarm.RegisterPeerAddress("/ip4/127.0.0.4/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1d"); swarm.RegisterPeerAddress("/ip4/127.0.0.5/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1e"); var dht = new DhtService { SwarmService = swarm, CloserPeerCount = 3 }; await dht.StartAsync(); try { dht.RoutingTable.Add(other); var request = new DhtMessage { Type = MessageType.FindNode, Key = new byte[] { 0xFF, 1, 2, 3 } }; var response = dht.ProcessFindNode(request, new DhtMessage()); Assert.AreEqual(3, response.CloserPeers.Length); } finally { await dht.StopAsync(); } }
public async Task ProcessFindNodeMessage_InSwarm() { var swarmA = new SwarmService { LocalPeer = self }; var swarmB = swarmA.RegisterPeerAddress( "/ip4/127.0.0.1/tcp/4001/ipfs/QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h"); var dht = new DhtService { SwarmService = swarmA }; await dht.StartAsync(); try { dht.RoutingTable.Add(swarmB); var request = new DhtMessage { Type = MessageType.FindNode, Key = swarmB.Id.ToArray() }; var response = dht.ProcessFindNode(request, new DhtMessage()); Assert.AreEqual(1, response.CloserPeers.Length); var ok = response.CloserPeers[0].TryToPeer(out var found); Assert.IsTrue(ok); Assert.AreEqual(swarmB, found); CollectionAssert.AreEqual( swarmB.Addresses.Select(a => a.WithoutPeerId()).ToArray(), found.Addresses.Select(a => a.WithoutPeerId()).ToArray()); } finally { await dht.StopAsync(); } }
public Task <SendQueryEventArgs> SendAsync(DhtMessage message, Node node) { var tcs = new TaskCompletionSource <SendQueryEventArgs> (); EnqueueSend(message, node, tcs); return(tcs.Task); }
private void SendMessage(DhtMessage message, IPEndPoint endpoint) { lastSent = DateTime.Now; byte[] buffer = message.Encode(); listener.Send(buffer, endpoint); RaiseMessageSent(endpoint, message); }
public async Task ProcessFindNodeMessage_Self() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { var request = new DhtMessage { Type = MessageType.FindNode, Key = self.Id.ToArray() }; var response = dht.ProcessFindNode(request, new DhtMessage()); Assert.AreEqual(1, response.CloserPeers.Length); var ok = response.CloserPeers[0].TryToPeer(out var found); Assert.IsTrue(ok); Assert.AreEqual(self, found); } finally { await dht.StopAsync(); } }
public async Task ProcessFindNodeMessage_InRoutingTable() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { dht.RoutingTable.Add(other); var request = new DhtMessage { Type = MessageType.FindNode, Key = other.Id.ToArray() }; var response = dht.ProcessFindNode(request, new DhtMessage()); Assert.AreEqual(1, response.CloserPeers.Length); var ok = response.CloserPeers[0].TryToPeer(out var found); Assert.IsTrue(ok); Assert.AreEqual(other, found); CollectionAssert.AreEqual(other.Addresses.ToArray(), found.Addresses.Select(a => a.WithoutPeerId()).ToArray()); } finally { await dht.StopAsync(); } }
internal void EnqueueSend(DhtMessage message, IPEndPoint endpoint) { //if (endpoint.Address.Equals(IPAddress.Any) || IPAddress.IsLoopback(endpoint.Address)) // return; lock (_locker) { if (message.TransactionId == null) { if (message is ResponseBase) { throw new ArgumentException("Message must have a transaction id"); } do { message.TransactionId = TransactionId.NextId(); } while (MessageFactory.IsRegistered(message.TransactionId)); } // We need to be able to cancel a query message if we time out waiting for a response QueryBase queryMessage = message as QueryBase; if (queryMessage != null) { MessageFactory.RegisterSend(queryMessage); } _sendQueue.Enqueue(new SendDetails(endpoint, message)); } }
private async Task ProcessMsgData() { while (running) { if (!_recvMessageQueue.TryTake(out DhtData dhtData)) { await Task.Delay(1000); continue; } try { var dic = (Dictionary <string, object>)BEncoder.Decode(dhtData.Data); var msg = new DhtMessage(dic); switch (msg.MesageType) { case MessageType.Request: var item = new Tuple <DhtMessage, IPEndPoint>(msg, dhtData.RemoteEndPoint); _requestQueue.TryAdd(item); break; case MessageType.Response: if (msg.MessageId.Length != 2) { continue; } var remotePoint = dhtData.RemoteEndPoint; var responseNode = new DhtNode() { NodeId = (byte[])msg.Data["id"], Host = remotePoint.Address, Port = (ushort)remotePoint.Port }; var flag = await MessageMap.RequireRegisteredInfoAsync(msg, responseNode); if (!flag) { continue; } _responseQueue.TryAdd(new Tuple <DhtMessage, DhtNode>(msg, responseNode), 10); break; } } catch (Exception ex) { if (ex is DecodeException) { filterPeers.Add(dhtData.RemoteEndPoint.ToInt64()); continue; } _logger.Error($"ErrorData:{BitConverter.ToString(dhtData.Data)}", ex); var response = new DhtMessage { MesageType = MessageType.Exception, MessageId = new byte[] { 0, 0 } }; response.Errors.Add(202); response.Errors.Add("Server Error:" + ex.Message); _sendMessageQueue.TryAdd(new Tuple <DhtMessage, DhtNode>(response, new DhtNode(dhtData.RemoteEndPoint))); } } }
public void Send(DhtMessage msg, IPEndPoint endpoint) { if (msg is FindNodeResponse && MessageLoop.GetWaitSendCount() > MaxSendQueue) { return; } MessageLoop.EnqueueSend(msg, endpoint); }
public SendDetails(Node node, IPEndPoint destination, DhtMessage message, TaskCompletionSource <SendQueryEventArgs> tcs) { CompletionSource = tcs; Destination = destination; Node = node; Message = message; SentAt = null; }
public SendDetails(Node?node, IPEndPoint destination, DhtMessage message, TaskCompletionSource <SendQueryEventArgs>?tcs) { CompletionSource = tcs; Destination = destination; Node = node; Message = message; SentAt = new ValueStopwatch(); }
private void RaiseMessageReceived(IPEndPoint endPoint, DhtMessage message) { EventHandler <MessageEventArgs> h = ReceivedMessage; if (h != null) { h(this, new MessageEventArgs(endPoint, message)); } }
private void RaiseMessageSent(IPEndPoint endpoint, DhtMessage query) { EventHandler <MessageEventArgs> h = SentMessage; if (h != null) { h(this, new MessageEventArgs(endpoint, query)); } }
private void ReceiveMessage() { if (_receiveQueue.Count == 0) { return; } KeyValuePair <IPEndPoint, DhtMessage> receive = _receiveQueue.Dequeue(); DhtMessage message = receive.Value; IPEndPoint source = receive.Key; for (int i = 0; i < _waitingResponse.Count; i++) { if (_waitingResponse[i].Message.TransactionId.Equals(message.TransactionId)) { _waitingResponse.RemoveAt(i--); } } //DHT.NET: We don't want to add these to the routing table as their ID is 0 if (message.GetType() == typeof(ErrorMessage)) { return; } try { Node node = _engine.RoutingTable.FindNode(message.Id); // What do i do with a null node? if (node == null) { node = new Node(message.Id, source); _engine.RoutingTable.Add(node); } node.Seen(); message.Handle(_engine, node); ResponseBase response = message as ResponseBase; if (response != null) { QuerySent?.Invoke(this, new SendQueryEventArgs(node.EndPoint, response.Query, response)); } } catch (DHTMessageException ex) { Logger.Log("Incoming message barfed: {0}", ex); // Normal operation (FIXME: do i need to send a response error message?) } catch (Exception ex) { Logger.Log("Handle Error for message: {0}", ex); EnqueueSend(new ErrorMessage(ErrorCode.GenericError, "Misshandle received message!"), source); } }
public void Send(DhtMessage msg, IPEndPoint endpoint) { if (msg.TransactionId == null) { if (msg is ResponseMessage) { //throw new ArgumentException("Message must have a transaction id"); } msg.TransactionId = TransactionId.NextId(); } var buffer = msg.Encode(); udpSocketListener.Send(buffer, endpoint); }
private bool SendMsg(CommandType command, IDictionary <string, object> data, DhtNode node) { var msg = new DhtMessage { CommandType = command, MesageType = MessageType.Request, Data = new SortedDictionary <string, object>(data) }; msg.Data.Add("id", GetNeighborNodeId(node.NodeId)); var dhtItem = new Tuple <DhtMessage, DhtNode>(msg, node); return(msg.CommandType == CommandType.Get_Peers ? _sendMessageQueue.TryAdd(dhtItem, EnqueueWaitTime) : _sendMessageQueue.TryAdd(dhtItem)); }
void ReceiveMessage() { KeyValuePair <IPEndPoint, DhtMessage> receive = ReceiveQueue.Dequeue(); DhtMessage message = receive.Value; IPEndPoint source = receive.Key; var query = default(SendDetails); try { Node node = Engine.RoutingTable.FindNode(message.Id); if (node == null) { node = new Node(message.Id, source); Engine.RoutingTable.Add(node); } // If we have received a ResponseMessage corresponding to a query we sent, we should // remove it from our list before handling it as that could cause an exception to be // thrown. if (message is ResponseMessage || message is ErrorMessage) { if (!WaitingResponse.TryGetValue(message.TransactionId, out query)) { return; } WaitingResponse.Remove(message.TransactionId); } node.Seen(); if (message is ResponseMessage response) { response.Handle(Engine, node); query.CompletionSource?.TrySetResult(new SendQueryEventArgs(node, node.EndPoint, (QueryMessage)query.Message, response)); RaiseMessageSent(node, node.EndPoint, (QueryMessage)query.Message, response); } else if (message is ErrorMessage error) { query.CompletionSource?.TrySetResult(new SendQueryEventArgs(node, node.EndPoint, (QueryMessage)query.Message, error)); RaiseMessageSent(node, node.EndPoint, (QueryMessage)query.Message, error); } } catch (MessageException) { var error = new ErrorMessage(message.TransactionId, ErrorCode.GenericError, "Unexpected error responding to the message"); query.CompletionSource?.TrySetResult(new SendQueryEventArgs(query.Node, query.Destination, (QueryMessage)query.Message, error)); } catch (Exception) { var error = new ErrorMessage(message.TransactionId, ErrorCode.GenericError, "Unexpected exception responding to the message"); query.CompletionSource?.TrySetResult(new SendQueryEventArgs(query.Node, query.Destination, (QueryMessage)query.Message, error)); EnqueueSend(error, null, source); } }
public async Task ProcessAddProviderMessage() { var swarm = new SwarmService { LocalPeer = self }; var dht = new DhtService { SwarmService = swarm }; await dht.StartAsync(); try { Cid cid = "zBunRGrmCGokA1oMESGGTfrtcMFsVA8aEtcNzM54akPWXF97uXCqTjF3GZ9v8YzxHrG66J8QhtPFWwZebRZ2zeUEELu67"; var request = new DhtMessage { Type = MessageType.AddProvider, Key = cid.Hash.ToArray(), ProviderPeers = new[] { new DhtPeerMessage { Id = other.Id.ToArray(), Addresses = other.Addresses.Select(a => a.ToArray()).ToArray() } } }; var response = dht.ProcessAddProvider(other, request, new DhtMessage()); Assert.IsNull(response); var providers = dht.ContentRouter.Get(cid).ToArray(); Assert.AreEqual(1, providers.Length); Assert.AreEqual(other.Id, providers[0]); var provider = swarm.KnownPeers.Single(p => p == other); Assert.AreNotEqual(0, provider.Addresses.Count()); } finally { await dht.StopAsync(); } }
internal void EnqueueSend(DhtMessage message, Node node, IPEndPoint endpoint, TaskCompletionSource <SendQueryEventArgs> tcs = null) { if (message.TransactionId == null) { if (message is ResponseMessage) { throw new ArgumentException("Message must have a transaction id"); } do { message.TransactionId = TransactionId.NextId(); } while (DhtMessageFactory.IsRegistered(message.TransactionId)); } // We need to be able to cancel a query message if we time out waiting for a response if (message is QueryMessage) { DhtMessageFactory.RegisterSend((QueryMessage)message); } SendQueue.Enqueue(new SendDetails(node, endpoint, message, tcs)); }
private void ReceiveMessage() { if (receiveQueue.Count == 0) { return; } KeyValuePair <IPEndPoint, DhtMessage> receive; lock (locker) { receive = receiveQueue.Dequeue(); } DhtMessage m = receive.Value; IPEndPoint source = receive.Key; if (m == null || source == null) { return; } try { if (m is QueryMessage) { m.Handle(engine, new Node(m.Id, source)); } else if (m is ErrorMessage) { RaiseOnError(((ErrorMessage)m).ErrorList.ToString()); } RaiseMessageReceived(source, m); } catch (Exception ex) { RaiseOnError(string.Format("Handle Error for message: {0}", ex)); Debug.WriteLine(ex); } }
public void EnqueueSend(DhtMessage message, IPEndPoint endpoint) { lock (locker) { if (message.TransactionId == null) { if (message is ResponseMessage) { throw new ArgumentException("Message must have a transaction id"); } //do //{ message.TransactionId = TransactionId.NextId(); //} while (MessageFactory.IsRegistered(message.TransactionId)); } // We need to be able to cancel a query message if we time out waiting for a response //if (message is QueryMessage) // MessageFactory.RegisterSend((QueryMessage)message); sendQueue.Enqueue(new SendDetails(endpoint, message)); } }
public SendDetails(IPEndPoint destination, DhtMessage message) { Destination = destination; Message = message; SentAt = DateTime.MinValue; }
internal void EnqueueSend(DhtMessage message, Node node) { EnqueueSend(message, node.EndPoint); }
private void CompactNode(byte[] buffer, int offset) { DhtMessage.Write(buffer, offset, id.Bytes); CompactPort(buffer, offset + 20); }
public void RaiseMessageReceived(DhtMessage message, IPEndPoint endpoint) => MessageReceived?.Invoke(message.Encode(), endpoint);
private void Compare(DhtMessage m, string expected) { byte[] b = m.Encode(); Assert.AreEqual(Encoding.UTF8.GetString(b), expected); }
internal void EnqueueSend(DhtMessage message, Node node, TaskCompletionSource <SendQueryEventArgs> tcs = null) { EnqueueSend(message, node, node.EndPoint, tcs); }