Exemple #1
0
        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();
            }
        }
Exemple #2
0
        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();
            }
        }
Exemple #3
0
        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();
            }
        }
Exemple #4
0
        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();
            }
        }
Exemple #5
0
        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();
            }
        }
Exemple #6
0
        public Task <SendQueryEventArgs> SendAsync(DhtMessage message, Node node)
        {
            var tcs = new TaskCompletionSource <SendQueryEventArgs> ();

            EnqueueSend(message, node, tcs);
            return(tcs.Task);
        }
Exemple #7
0
 private void SendMessage(DhtMessage message, IPEndPoint endpoint)
 {
     lastSent = DateTime.Now;
     byte[] buffer = message.Encode();
     listener.Send(buffer, endpoint);
     RaiseMessageSent(endpoint, message);
 }
Exemple #8
0
        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();
            }
        }
Exemple #9
0
        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();
            }
        }
Exemple #10
0
        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));
            }
        }
Exemple #11
0
        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)));
                }
            }
        }
Exemple #12
0
 public void Send(DhtMessage msg, IPEndPoint endpoint)
 {
     if (msg is FindNodeResponse && MessageLoop.GetWaitSendCount() > MaxSendQueue)
     {
         return;
     }
     MessageLoop.EnqueueSend(msg, endpoint);
 }
Exemple #13
0
 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();
 }
Exemple #15
0
        private void RaiseMessageReceived(IPEndPoint endPoint, DhtMessage message)
        {
            EventHandler <MessageEventArgs> h = ReceivedMessage;

            if (h != null)
            {
                h(this, new MessageEventArgs(endPoint, message));
            }
        }
Exemple #16
0
        private void RaiseMessageSent(IPEndPoint endpoint, DhtMessage query)
        {
            EventHandler <MessageEventArgs> h = SentMessage;

            if (h != null)
            {
                h(this, new MessageEventArgs(endpoint, query));
            }
        }
Exemple #17
0
        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);
            }
        }
Exemple #18
0
        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);
        }
Exemple #19
0
        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));
        }
Exemple #20
0
        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);
            }
        }
Exemple #21
0
        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();
            }
        }
Exemple #22
0
        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));
        }
Exemple #23
0
        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);
            }
        }
Exemple #24
0
        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));
            }
        }
Exemple #25
0
 public SendDetails(IPEndPoint destination, DhtMessage message)
 {
     Destination = destination;
     Message     = message;
     SentAt      = DateTime.MinValue;
 }
Exemple #26
0
 internal void EnqueueSend(DhtMessage message, Node node)
 {
     EnqueueSend(message, node.EndPoint);
 }
Exemple #27
0
 private void CompactNode(byte[] buffer, int offset)
 {
     DhtMessage.Write(buffer, offset, id.Bytes);
     CompactPort(buffer, offset + 20);
 }
Exemple #28
0
 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);
 }
Exemple #30
0
 internal void EnqueueSend(DhtMessage message, Node node, TaskCompletionSource <SendQueryEventArgs> tcs = null)
 {
     EnqueueSend(message, node, node.EndPoint, tcs);
 }