コード例 #1
0
        private static IEnumerable <Contact> LoadBootstrapData()
        {
            foreach (var line in File.ReadAllLines("Bootstrap.txt").OmitComments("#", "//"))
            {
                UdpContact udpC = null;

                try
                {
                    string[] split = line.Split(' ');
                    Guid     a     = Guid.Parse(split[0]);
                    Guid     b     = Guid.Parse(split[1]);
                    Guid     c     = Guid.Parse(split[2]);
                    Guid     d     = Guid.Parse(split[3]);

                    Identifier512 id = new Identifier512(a, b, c, d);

                    IPAddress ip   = IPAddress.Parse(split[4]);
                    int       port = Int32.Parse(split[5]);

                    udpC = new UdpContact(id, networkId, ip, port);

                    Console.WriteLine("Loaded bootstrap contact " + udpC);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception parsing bootstrap file: " + e);
                }

                if (udpC != null)
                {
                    yield return(udpC);
                }
            }
        }
コード例 #2
0
        static void Main(string[] args)
        {
            myDomainMappings = ReadDomainMappings("MyDomainMappings.txt");
            ReadSettings(ref dnsport, ref peerport);

            dnsServer = new DnsServer(new Dictionary <string, DomainMapping>()
            {
                { "hellequin.p2p", new DomainMapping()
                  {
                      Address = IPAddress.Parse("78.105.97.103"), Name = "hellequin.p2p", TimeToLive = TimeSpan.FromSeconds(1234)
                  } }
            });
            dnsServer.Start();

            Identifier512 myId = Identifier512.NewIdentifier();

            routingTable = new DistributedRoutingTable(Identifier512.NewIdentifier(), (a) => new UdpContact(a.LocalIdentifier, networkId, LocalIp, peerport), networkId, new Configuration());

            UdpContact.InitialiseUdp(routingTable, peerport);

            Console.WriteLine("Bootstrapping DHT");
            routingTable.Bootstrap(LoadBootstrapData());

            Console.WriteLine("Bootstrap finished");
            Console.WriteLine("There are " + routingTable.ContactCount + " Contacts");

            Console.WriteLine("Press any key to close");
            Console.ReadLine();

            UdpContact.Stop();
        }
コード例 #3
0
        /// <summary>
        /// Finds the closest contact in the network. Does several round trips to the network
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns>an IEnumerable&lt;contact&gt; in order of distance from the target. Can be cast into a GetClosestNodes.ClosestResults</contact></returns>
        public IEnumerable <Contact> GetClosestContacts(Identifier512 target, Func <Contact, bool> terminate = null)
        {
            MinMaxHeap <Contact> heap = new MinMaxHeap <Contact>(new ContactComparer(target), contacts.ClosestNodes(target).Take(RoutingTable.Configuration.LookupConcurrency));

            HashSet <Identifier512> contacted = new HashSet <Identifier512>();

            contacted.Add(RoutingTable.LocalIdentifier);

            int iterations = 0;
            HashSet <Contact> uniqueDiscoveries;

            do
            {
                iterations++;

                uniqueDiscoveries = new HashSet <Contact>(                                                      //hashet means we only get each result once
                    heap                                                                                        //from the set of results we know about
                    .Where(c => !contacted.Contains(c.Identifier))                                              //which we have not already contacted
                    .SelectMany(c =>
                {
                    try { return(RemoteGetClosest(RoutingTable.LocalContact, c, target, RoutingTable.Configuration.LookupConcurrency, RoutingTable.Configuration.LookupTimeout)); }
                    catch (TimeoutException) { return(null); }
                })                                                                                          //select the closest ones they know about
                    .Where(n => n != null)
                    .Where(r => !heap.Contains(r)));                                                        //remove the results we already know about

                //Make the system aware of these potentially new nodes
                foreach (var c in uniqueDiscoveries)
                {
                    contacts.Update(c);
                }

                //make sure we never contact these nodes again
                contacted.UnionWith(heap.Select(a => a.Identifier));

                //add the new results
                heap.AddMany(uniqueDiscoveries);

                while (heap.Count > RoutingTable.Configuration.LookupConcurrency)
                {
                    heap.RemoveMax();
                }

                if (terminate != null)
                {
                    if (uniqueDiscoveries.Where(a => terminate(a)).FirstOrDefault() != null)
                    {
                        break;
                    }
                }
            }while (uniqueDiscoveries.Count != 0 && heap.Minimum.Identifier != target);

            return(new ClosestResults(heap, iterations));
            //while (heap.Count > 0)
            //    yield return heap.RemoveMin();
        }
コード例 #4
0
        /// <summary>
        /// Create a new DistributedRoutingTable
        /// </summary>
        /// <param name="localIdentifier">The identifier of this node, or null to autogenerate one</param>
        /// <param name="createLocalContact">A factory function which creates a contact for this table</param>
        /// <param name="networkId">the ID of the network this routing table is part of</param>
        /// <param name="configuration">The configuration of this node</param>
        public DistributedRoutingTable(Identifier512 localIdentifier, Func <DistributedRoutingTable, Contact> createLocalContact, Guid networkId, Configuration configuration)
        {
            LocalIdentifier = localIdentifier != null ? localIdentifier : Identifier512.NewIdentifier();
            NetworkId       = networkId;
            Configuration   = configuration;
            LocalContact    = createLocalContact(this);

            contacts = new ContactCollection(this);

            //Register internal consumers
            RegisterConsumer(MessageCallback = new Callback());
            RegisterConsumer(getClosest      = new GetClosestNodes(contacts, MessageCallback));
        }
コード例 #5
0
        /// <summary>
        /// Returns an enumeration of all nodes in ascending order of distance from the given identifier
        /// </summary>
        /// <param name="identifier">The identifier.</param>
        /// <returns></returns>
        public IEnumerable <Contact> ClosestNodes(Identifier512 identifier)
        {
            int mid = Identifier512.CommonPrefixLength(identifier, LocalIdentifier);

            if (mid != 512)
            {
                foreach (var contact in buckets[mid].OrderWithComparer(new ContactComparer(identifier)))
                {
                    yield return(contact);
                }
            }

            //loop through buckets, moving up and down from mid concatenating the two buckets either side of mid and returning them in order of distance
            List <Contact> contacts = new List <Contact>();
            bool           moreLow  = true;
            bool           moreHigh = true;

            for (int i = 1; moreHigh || moreLow; i++)
            {
                int indexHigh = mid + i;
                int indexLow  = mid - i;

                contacts.Clear();

                if (indexHigh >= buckets.Length)
                {
                    moreHigh = false;
                }
                else
                {
                    contacts.AddRange(buckets[indexHigh]);
                }

                if (indexLow < 0)
                {
                    moreLow = false;
                }
                else
                {
                    contacts.AddRange(buckets[indexLow]);
                }

                foreach (var contact in contacts.OrderWithComparer(new ContactComparer(identifier)))
                {
                    yield return(contact);
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Gets the closest nodes the remote contact has to a given contact
        /// </summary>
        /// <param name="local">The local contact</param>
        /// <param name="remote">The remote node to ask</param>
        /// <param name="target">The target to search for</param>
        /// <param name="limit">The limit of items to return</param>
        /// <param name="timeout">The maximum time to wait</param>
        /// <returns>a collection of contacts in order of distance from the target, or null if timed out</returns>
        public IEnumerable <Contact> RemoteGetClosest(Contact local, Contact remote, Identifier512 target, int limit, int timeout)
        {
            var            token   = callback.AllocateToken();
            RequestMessage request = new RequestMessage(token.Id, target, limit);

            using (MemoryStream mStream = new MemoryStream())
            {
                Serializer.Serialize <RequestMessage>(mStream, request);
                remote.Send(local, ConsumerId, mStream.ToArray());
            }

            if (!token.Wait(timeout))
            {
                throw new TimeoutException();
            }

            callback.FreeToken(token);

            return(DecodeResponse(token.Response));
        }
コード例 #7
0
        /// <summary>
        /// Moves the specified contact to the top of the most recently used queue
        /// </summary>
        /// <param name="source">The source.</param>
        internal void Update(Contact source)
        {
            if (Configuration.UpdateRoutingTable)
            {
                if (source == null)
                {
                    return;
                }
                if (source.Identifier == LocalIdentifier)
                {
                    return;
                }
                if (source.NetworkId != NetworkId)
                {
                    throw new ArgumentException("Network Id of contact and ContactCollection must be the same");
                }

                buckets[Identifier512.CommonPrefixLength(source.Identifier, LocalIdentifier)].Update(source);
            }
        }
コード例 #8
0
        private static UdpContact ReadContact(BinaryReader reader)
        {
            int idBytesLength = IPAddress.NetworkToHostOrder(reader.ReadInt32());

            byte[]        idBytes = reader.ReadBytes(idBytesLength);
            Identifier512 id      = new Identifier512(idBytes);

            int netIdBytesLength = IPAddress.NetworkToHostOrder(reader.ReadInt32());

            byte[] netIdBytes = reader.ReadBytes(netIdBytesLength);
            Guid   netId      = new Guid(netIdBytes);

            int port = IPAddress.NetworkToHostOrder(reader.ReadInt32());

            int addrBytesLength = IPAddress.NetworkToHostOrder(reader.ReadInt32());

            byte[]    addrBytes = reader.ReadBytes(addrBytesLength);
            IPAddress address   = new IPAddress(addrBytes);

            return(new UdpContact(id, netId, address, port));
        }
コード例 #9
0
        private static void ReadSettings(ref int dnsport, ref int peerport)
        {
            foreach (var line in File.ReadAllLines("Settings.txt").OmitComments("#", "//").Select(a => a.ToLowerInvariant().Replace(" ", "").Replace("\t", "").Split('=')))
            {
                switch (line[0])
                {
                case "dnsport": dnsport = Int32.Parse(line[1]); break;

                case "peerport": peerport = Int32.Parse(line[1]); break;

                case "localip": LocalIp = IPAddress.Parse(line[1]); break;

                case "networkid": networkId = Guid.Parse(line[1]); break;

                case "routingidentifier":
                    var s = line[1].Split(',');
                    routingIdentifier = new Identifier512(Guid.Parse(s[0]), Guid.Parse(s[1]), Guid.Parse(s[2]), Guid.Parse(s[3]));
                    break;

                default: Console.WriteLine("Unknown setting " + line[0]); break;
                }
            }
        }
コード例 #10
0
 public RequestMessage(long callbackId, Identifier512 target, int limit)
 {
     CallbackId = callbackId;
     Target     = target;
     Limit      = limit;
 }
コード例 #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Contact"/> class.
 /// </summary>
 /// <param name="identifier">The identifier of the DistributedRoutingTable this contact represents</param>
 /// <param name="networkId">The network id.</param>
 public Contact(Identifier512 identifier, Guid networkId)
 {
     Identifier     = identifier;
     networkIdBytes = networkId.ToByteArray();
 }
コード例 #12
0
 public UdpContact(Identifier512 id, Guid networkId, IPAddress ip, int port)
     : base(id, networkId)
 {
     Ip   = ip;
     Port = port;
 }
コード例 #13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ContactComparer"/> class.
 /// </summary>
 /// <param name="target">The target.</param>
 public ContactComparer(Identifier512 target)
 {
     comparer = new IdentifierComparer(target);
 }