Пример #1
0
 public CachedIP(byte name, DhtContact contact, bool bootstrap)
 {
     Name = name;
     LastSeen = contact.LastSeen;
     Contact = contact;
     Bootstrap = bootstrap;
 }
Пример #2
0
        public bool Activate()
        {
            // bootstrap search from routing
            foreach (DhtContact contact in Network.Routing.Find(TargetID, 8))
            {
                Add(contact);
            }

            List <TcpConnect> sockets = null;

            // if open send search to proxied nodes just for good measure, probably helps on very small networks
            if (Core.Firewall == FirewallType.Open)
            {
                sockets = Network.TcpControl.ProxyClients;
            }

            // if natted send request to proxies for fresh nodes
            if (Core.Firewall == FirewallType.NAT)
            {
                sockets = Network.TcpControl.ProxyServers;
            }

            if (sockets != null)
            {
                foreach (TcpConnect socket in sockets)
                {
                    DhtContact contact = new DhtContact(socket, socket.RemoteIP);
                    Network.Searches.SendRequest(contact, TargetID, SearchID, Service, DataType, Parameters);

                    DhtLookup host = Add(socket.GetContact());
                    if (host != null)
                    {
                        host.Status = LookupStatus.Searching;
                    }
                }
            }

            // if blocked send proxy search request to 1 proxy, record and wait
            if (Core.Firewall == FirewallType.Blocked && !Network.UseLookupProxies)
            {
                // pick random proxy server
                if (Network.TcpControl.ProxyServers.Count == 0)
                {
                    return(false);
                }

                ProxyTcp = Network.TcpControl.ProxyServers[Core.RndGen.Next(Network.TcpControl.ProxyServers.Count)];

                Send_ProxySearchRequest();
            }

            return(true);
        }
Пример #3
0
        public void Send_Ping(DhtContact contact)
        {
            Ping ping = new Ping();

            ping.Source   = GetLocalSource();
            ping.RemoteIP = contact.IP;
            ping.Ident    = contact.Ident = (ushort)Core.RndGen.Next(ushort.MaxValue);

            // always send ping udp, tcp pings are sent manually
            int sentBytes = SendPacket(contact, ping);

            Core.ServiceBandwidth[Core.DhtServiceID].OutPerSec += sentBytes;
        }
Пример #4
0
        public DhtLookup Add(DhtContact contact)
        {
            DhtLookup added = null;

            if (contact.UserID == Network.Local.UserID && contact.ClientID == Network.Local.ClientID)
            {
                return(null);
            }

            if (Finished)            // search over
            {
                return(null);
            }

            // go through lookup list, add if closer to target
            foreach (DhtLookup lookup in LookupList)
            {
                if (contact.UserID == lookup.Contact.UserID && contact.ClientID == lookup.Contact.ClientID)
                {
                    return(lookup);
                }

                if ((contact.UserID ^ TargetID) < (lookup.Contact.UserID ^ TargetID))
                {
                    added = new DhtLookup(contact);
                    LookupList.Insert(LookupList.IndexOf(lookup), added);
                    break;
                }
            }

            if (added == null)
            {
                added = new DhtLookup(contact);
                LookupList.Add(added);
            }

            while (LookupList.Count > LOOKUP_SIZE)
            {
                LookupList.RemoveAt(LookupList.Count - 1);
            }


            // at end so we ensure this node is put into list and sent with proxy results
            if (Service == Core.DhtServiceID && contact.UserID == TargetID)
            {
                Found(contact, false);
            }

            return(added);
        }
Пример #5
0
        public bool Add(DhtContact newContact)
        {
            // duplicate already checked for in routing.add

            // check if bucket full
            if (ContactList.Count >= Routing.ContactsPerBucket)
                return false;

            // else good to go
            ContactList.Add(newContact);
            Routing.ContactMap[newContact.RoutingID] = newContact;

            return true;
        }
Пример #6
0
        public void Found(DhtContact contact, bool proxied)
        {
            FoundContact = contact;

            if (!proxied)
            {
                FinishSearch("Found");
            }

            else
            {
                FoundProxy = true;
                FinishSearch("Found Proxy");
            }
        }
Пример #7
0
        private bool InBucket(DhtContact find)
        {
            foreach (DhtBucket bucket in BucketList)
            {
                foreach (DhtContact contact in bucket.ContactList)
                {
                    if (contact == find)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #8
0
        public bool Add(DhtContact newContact)
        {
            // duplicate already checked for in routing.add

            // check if bucket full
            if (ContactList.Count >= Routing.ContactsPerBucket)
            {
                return(false);
            }

            // else good to go
            ContactList.Add(newContact);
            Routing.ContactMap[newContact.RoutingID] = newContact;

            return(true);
        }
Пример #9
0
        private bool RemoveFromBuckets(DhtContact removed)
        {
            foreach (DhtBucket bucket in BucketList)
            {
                foreach (DhtContact contact in bucket.ContactList)
                {
                    if (contact == removed)
                    {
                        bucket.ContactList.Remove(contact);
                        return(true);
                    }
                }
            }

            NearXor.Contacts.Remove(removed);

            return(false);
        }
Пример #10
0
        private bool CheckXor(DhtContact check)
        {
            if ((LocalRoutingID ^ check.RoutingID) <= NearXor.RoutingBound)
            {
                NearXor.Contacts = Find(LocalRoutingID, NearXor.Max);

                // set bound to furthest contact in range
                if (NearXor.Contacts.Count == NearXor.Max)
                {
                    NearXor.SetBounds(LocalRoutingID ^ NearXor.Contacts[NearXor.Max - 1].RoutingID,
                                      Network.Local.UserID ^ NearXor.Contacts[NearXor.Max - 1].UserID);
                }

                return(true);
            }

            return(false);
        }
Пример #11
0
        public static new DhtContact ReadPacket(G2Header root)
        {
            // read payload
            DhtContact contact = new DhtContact();

            contact.UserID   = BitConverter.ToUInt64(root.Data, root.PayloadPos);
            contact.ClientID = BitConverter.ToUInt16(root.Data, root.PayloadPos + 8);
            contact.UdpPort  = BitConverter.ToUInt16(root.Data, root.PayloadPos + 10);
            contact.TcpPort  = BitConverter.ToUInt16(root.Data, root.PayloadPos + 12);

            // read packets
            G2Protocol.ResetPacket(root);

            G2Header child = new G2Header(root.Data);

            while (G2Protocol.ReadNextChild(root, child) == G2ReadResult.PACKET_GOOD)
            {
                if (!G2Protocol.ReadPayload(child))
                {
                    continue;
                }

                switch (child.Name)
                {
                case Packet_IP:
                    contact.IP = new IPAddress(Utilities.ExtractBytes(child.Data, child.PayloadPos, child.PayloadSize));
                    break;

                case Packet_Server:
                    contact.TunnelServer = DhtAddress.ReadPacket(child);
                    break;

                case Packet_Client:
                    contact.TunnelClient = TunnelAddress.FromBytes(child.Data, child.PayloadPos);
                    break;
                }
            }

            return(contact);
        }
Пример #12
0
 public string CreateBootstrapLink(DhtContact contact)
 {
     return CreateBootstrapLink(contact.UserID, contact.IP, contact.TcpPort, contact.UdpPort);
 }
Пример #13
0
        private void StartSearch(ulong user, uint version)
        {
            if (Core.InvokeRequired)
            {
                Core.RunInCoreAsync(delegate() { StartSearch(user, version); });
                return;
            }

            byte[] parameters = BitConverter.GetBytes(version);
            DhtSearch search = Core.Network.Searches.Start(user, Core.GetServiceName(Service), Service, DataType, parameters, Search_Found);

            if (search != null)
                search.TargetResults = 2;

            // node is in our local cache area, so not flooding by directly connecting
            if ( (!GlobalIM && Network.Routing.InCacheArea(user)) ||
                 ( GlobalIM && Core.Buddies.BuddyList.SafeContainsKey(user)) )
                foreach (ClientInfo client in Core.Locations.GetClients(user))
                    if (client.Data.TunnelClient == null)
                    {
                        Network.Searches.SendDirectRequest(new DhtAddress(client.Data.IP, client.Data.Source), user, Service, DataType, BitConverter.GetBytes(version));
                    }
                    else
                    {
                        foreach (DhtAddress server in client.Data.TunnelServers)
                        {
                            DhtContact contact = new DhtContact(client.Data.Source, client.Data.IP, client.Data.TunnelClient, server);
                            Network.Searches.SendDirectRequest(contact, user, Service, DataType, BitConverter.GetBytes(version));
                        }
                    }
        }
Пример #14
0
        public void SecondTimer()
        {
            // if not connected, cache is frozen until re-connected
            // ideally for disconnects around 10 mins, most of cache will still be valid upon reconnect
            if (!Network.Responsive)
            {
                return;
            }


            // hourly self search, even if dht not enabled so we can find closer proxies for example
            if (Core.TimeNow > NextSelfSearch)
            {
                // if behind nat this is how we ensure we are at closest proxy
                // slightly off to avoid proxy host from returning with a found
                Network.Searches.Start(LocalRoutingID + 1, "Self", Core.DhtServiceID, 0, null, null);
                NextSelfSearch = Core.TimeNow.AddHours(1);
            }

            // refresh highest lowest bucket
            if (DhtEnabled)
            {
                foreach (DhtBucket bucket in BucketList)
                {
                    // if a node has a lot of dupes logged on there will be 20 empty buckets all the way down
                    // to where clientIDs start getting split up, don't research on those

                    // if bucket not low, then it will not refresh, but once low state is triggered
                    // a re-search is almost always immediately done to bring it back up
                    if (bucket.ContactList.Count != 0 &&
                        bucket.ContactList.Count < ContactsPerBucket / 2 &&
                        Core.Firewall == FirewallType.Open &&
                        Core.TimeNow > bucket.NextRefresh)
                    {
                        // search on random id in bucket
                        Network.Searches.Start(bucket.GetRandomBucketID(), "Low Bucket", Core.DhtServiceID, 0, null, null);
                        bucket.NextRefresh = Core.TimeNow.AddMinutes(15);

                        break;
                    }
                }
            }

            /*
             *  est network size = bucket size * 2^(number of buckets - 1)
             *          est cache contacts = bucket size * number of buckets
             *          ex: net of 2M = 2^21 = 2^4 * 2^(18-1)
             *                  contacts = 16 * 18 = 288, 1 refresh per sec = ~5 mins for full cache validation
             */

            // if dhtEnabled - continually ping hosts - get oldest and ping it, remove timed out
            // if not (proxied) - passively collect hosts from server - time out non-refreshed
            // if not connected - don't remove hosts from routing

            // get youngest (freshest) and oldest contact
            DhtContact        oldest   = null;
            DhtContact        youngest = null;
            List <DhtContact> timedOut = new List <DhtContact>();
            int passiveTimeout         = ContactMap.Count + 3 * AttemptTimeout; // the timeout upper bound is the routing table size + attempt wait * 3

            foreach (DhtContact contact in ContactMap.Values)
            {
                if (youngest == null || contact.LastSeen > youngest.LastSeen)
                {
                    youngest = contact;
                }


                if (DhtEnabled)
                {
                    if (Core.TimeNow > contact.NextTry && (oldest == null || contact.LastSeen < oldest.LastSeen))
                    {
                        if (contact.Attempts < 2)
                        {
                            oldest = contact;
                        }
                        else
                        {
                            timedOut.Add(contact); // move than two tries, time out
                        }
                    }
                }

                else if (Core.TimeNow > contact.LastSeen.AddSeconds(passiveTimeout))
                {
                    timedOut.Add(contact);
                }
            }

            foreach (DhtContact contact in timedOut)
            {
                RemoveContact(contact);
            }


            // stagger cache pings, so once every second
            // find oldest can attempt, send ping, remove expired
            if (oldest != null && Core.TimeNow > oldest.NextTry)
            {
                Network.Send_Ping(oldest);

                oldest.Attempts++;

                // allow 10 (2*AttemptTimeout) unique nodes to be tried before disconnect
                // (others should be pinging us as well if connected)
                oldest.NextTry = Core.TimeNow.AddSeconds(AttemptTimeout);
            }


            // know if disconnected within 15 secs for any network size
            // find youngest, if more than 15 secs old, we are disconnected
            // in this time 15 unique contacts should have been pinged
            SetResponsive(youngest != null && youngest.LastSeen.AddSeconds(NetworkTimeout) > Core.TimeNow);
        }
Пример #15
0
 public DhtLookup(DhtContact contact)
 {
     Contact = contact;
     Status  = LookupStatus.None;
 }
Пример #16
0
        public bool Activate()
        {
            // bootstrap search from routing
            foreach(DhtContact contact in Network.Routing.Find(TargetID, 8))
                Add(contact);

            List<TcpConnect> sockets = null;

            // if open send search to proxied nodes just for good measure, probably helps on very small networks
            if (Core.Firewall == FirewallType.Open)
                sockets = Network.TcpControl.ProxyClients;

            // if natted send request to proxies for fresh nodes
            if(Core.Firewall == FirewallType.NAT)
                sockets = Network.TcpControl.ProxyServers;

            if(sockets != null)
                foreach (TcpConnect socket in sockets)
                {
                    DhtContact contact = new DhtContact(socket, socket.RemoteIP);
                    Network.Searches.SendRequest(contact, TargetID, SearchID, Service, DataType, Parameters);

                    DhtLookup host = Add(socket.GetContact());
                    if (host != null)
                        host.Status = LookupStatus.Searching;
                }

            // if blocked send proxy search request to 1 proxy, record and wait
            if (Core.Firewall == FirewallType.Blocked && !Network.UseLookupProxies)
            {
                // pick random proxy server
                if (Network.TcpControl.ProxyServers.Count == 0)
                    return false;

                ProxyTcp = Network.TcpControl.ProxyServers[Core.RndGen.Next(Network.TcpControl.ProxyServers.Count)];

                Send_ProxySearchRequest();
            }

            return true;
        }
Пример #17
0
 public void Add(DhtContact newContact)
 {
     Add(newContact, false);
 }
Пример #18
0
 public CrawlNode(DhtContact contact)
 {
     Contact  = contact;
 }
Пример #19
0
        public void AddContact(DhtContact entry)
        {
            lock (IPs)
            {
                if (IPTable.ContainsKey(entry.CacheHash()))
                {
                    entry = IPTable[entry.CacheHash()].Value; // replace entry with dupe to maintain next try info
                    IPs.Remove(entry);
                }

                // sort nodes based on last seen
                LinkedListNode<DhtContact> node = null;

                for (node = IPs.First; node != null; node = node.Next)
                    if (entry.LastSeen > node.Value.LastSeen)
                        break;

                IPTable[entry.CacheHash()] = (node != null) ? IPs.AddBefore(node, entry) : IPs.AddLast(entry);
            }
        }
Пример #20
0
        List<byte[]> Store_Replicate(DhtContact contact)
        {
            if (GlobalIM) // cache area doesnt change with network in global IM mode
                return null;

            // indicates cache area has changed, move contacts between out and in range

            // move in to out
            List<ulong> remove = new List<ulong>();

            foreach(ulong user in InRange.Keys)
                if (!Network.Routing.InCacheArea(user))
                {
                    OutofRange[user] = InRange[user];
                    remove.Add(user);
                }

            foreach (ulong key in remove)
                InRange.Remove(key);

            // move out to in
            remove.Clear();

            foreach (ulong user in OutofRange.Keys)
                if (Network.Routing.InCacheArea(user))
                {
                    InRange[user] = OutofRange[user];
                    remove.Add(user);
                }

            foreach (ulong key in remove)
                OutofRange.Remove(key);

            // invoke tags on data moving in range so all services are cached
            foreach (ulong key in remove)
                InvokeTags(key, InRange[key]);

            return null;
        }
Пример #21
0
        public void Replicate(DhtContact contact)
        {
            // dont replicate to local region until we've established our position in the dht
            if (!Network.Established)
                return;

            // when new user comes into our cache area, we send them the data we have in our high/low/xor bounds

            // replicate is only for cached area
            // for remote user stuff that loads up with client, but now out of bounds, it is
            // republished by the uniqe modifier on data

            List<PatchTag> PatchList = new List<PatchTag>();

            // get data that needs to be replicated from components
            // structure as so
            //      contact
            //          service []
            //              datatype []
            //                  patch data []

            foreach (uint service in ReplicateEvent.HandlerMap.Keys)
                foreach (uint datatype in ReplicateEvent.HandlerMap[service].Keys)
                {
                    List<byte[]> patches = ReplicateEvent.HandlerMap[service][datatype].Invoke(contact);

                    if(patches != null)
                        foreach (byte[] data in patches)
                        {
                            PatchTag patch = new PatchTag();
                            patch.Service = service;
                            patch.DataType = datatype;
                            patch.Tag = data;

                            PatchList.Add(patch);
                        }
                }

            PatchPacket packet = new PatchPacket();

            int totalSize = 0;

            foreach (PatchTag patch in PatchList)
            {
                if (patch.Tag.Length + totalSize > 1000)
                {
                    if (packet.PatchData.Count > 0)
                        Send_StoreReq(contact, contact, new DataReq(null, contact.UserID, 0, 0, packet.Encode(Network.Protocol)));

                    packet.PatchData.Clear();
                    totalSize = 0;
                }

                packet.PatchData.Add(patch);
                totalSize += patch.Tag.Length;
            }

            if (packet.PatchData.Count > 0)
                Send_StoreReq(contact, contact, new DataReq(null, contact.UserID, 0, 0, packet.Encode(Network.Protocol)));
        }
Пример #22
0
        List<byte[]> Store_Replicate(DhtContact contact)
        {
            List<byte[]> patches = new List<byte[]>();

            foreach (TempData temp in CachedData)
                if (Network.Routing.InCacheArea(temp.TargetID))
                    patches.Add(BitConverter.GetBytes(temp.TargetID));

            return patches;
        }
Пример #23
0
        List<byte[]> Store_Replicate(DhtContact contact)
        {
            List<byte[]> patches = new List<byte[]>();

            BoardMap.LockReading(delegate()
            {
                foreach (OpBoard board in BoardMap.Values)
                    if (Network.Routing.InCacheArea(board.UserID))
                    {

                        board.Posts.LockReading(delegate()
                        {
                            foreach (PostUID uid in board.Posts.Keys)
                            {
                                byte[] patch = new byte[PatchEntrySize];

                                BitConverter.GetBytes(board.UserID).CopyTo(patch, 0);

                                uid.ToBytes().CopyTo(patch, 8);
                                BitConverter.GetBytes(board.Posts[uid].Header.Version).CopyTo(patch, 24);

                                patches.Add( patch);
                            }
                        });

                    }
            });

            return patches;
        }
Пример #24
0
        public DhtLookup Add(DhtContact contact)
        {
            DhtLookup added = null;

            if (contact.UserID == Network.Local.UserID && contact.ClientID == Network.Local.ClientID)
                return null;

            if(Finished) // search over
                return null;

            // go through lookup list, add if closer to target
            foreach(DhtLookup lookup in LookupList)
            {
                if(contact.UserID == lookup.Contact.UserID && contact.ClientID == lookup.Contact.ClientID)
                    return lookup;

                if((contact.UserID ^ TargetID) < (lookup.Contact.UserID ^ TargetID))
                {
                    added = new DhtLookup(contact);
                    LookupList.Insert(LookupList.IndexOf(lookup), added);
                    break;
                }
            }

            if (added == null)
            {
                added = new DhtLookup(contact);
                LookupList.Add(added);
            }

            while (LookupList.Count > LOOKUP_SIZE)
                LookupList.RemoveAt(LookupList.Count - 1);

            // at end so we ensure this node is put into list and sent with proxy results
            if (Service == Core.DhtServiceID && contact.UserID == TargetID)
                Found(contact, false);

            return added;
        }
Пример #25
0
        List<byte[]> Store_Replicate(DhtContact contact)
        {
            List<byte[]> patches = new List<byte[]>();

            FileMap.LockReading(delegate()
            {
                foreach (OpVersionedFile vfile in FileMap.Values)
                    if (Network.Routing.InCacheArea(vfile.UserID))
                    {

                        byte[] id = BitConverter.GetBytes(vfile.UserID);
                        byte[] ver = CompactNum.GetBytes(vfile.Header.Version);

                        byte[] patch = new byte[id.Length + ver.Length];
                        id.CopyTo(patch, 0);
                        ver.CopyTo(patch, 8);

                        patches.Add(patch);
                    }
            });

            return patches;
        }
Пример #26
0
        public void Receive_SearchAck(SearchAck ack, G2ReceivedPacket packet)
        {
            DhtContact source = new DhtContact(ack.Source, packet.Source.IP);

            if( !CrawlMap.ContainsKey(source.RoutingID) )
                CrawlMap[source.RoutingID] = new CrawlNode(source);

            foreach(DhtContact contact in ack.ContactList)
                if (!CrawlMap.ContainsKey(contact.RoutingID))
                    CrawlMap[contact.RoutingID] = new CrawlNode(contact);
        }
Пример #27
0
        public void Receive_CrawlAck(CrawlAck ack, G2ReceivedPacket packet)
        {
            DhtContact source = new DhtContact(ack.Source, packet.Source.IP);

            if (!CrawlMap.ContainsKey(source.RoutingID))
                return;

            CrawlNode node = CrawlMap[source.RoutingID];

            node.Ack = ack;

            foreach(DhtContact contact in ack.ProxyServers)
                if (!CrawlMap.ContainsKey(contact.RoutingID))
                    CrawlMap[contact.RoutingID] = new CrawlNode(contact);

            foreach(DhtContact contact in ack.ProxyClients)
                if (!CrawlMap.ContainsKey(contact.RoutingID))
                {
                    CrawlNode newNode = new CrawlNode(contact);
                    newNode.Proxy = node;

                    CrawlMap[contact.RoutingID] = newNode;
                }
        }
Пример #28
0
        private void WebQueryResponse(WebCache cache, string response)
        {
            double timeout = 0;
            bool low = false;

            foreach (string line in response.Split('\n'))
            {
                // add to node cache
                if (line.StartsWith("node:"))
                {
                    string[] parts = line.Substring(5).Split('/');

                    DhtContact contact = new DhtContact(ulong.Parse(parts[0]), 0, IPAddress.Parse(parts[1]), ushort.Parse(parts[2]), ushort.Parse(parts[3]));
                    contact.LastSeen = Core.TimeNow; // set this so its put at front of list, and is the first to be attempted

                    AddContact(contact);
                }

                // for use with publishing back to cache, dont set our local IP with it in case on
                // network with LAN nodes and web cache active, dont want to reset until we find nodes on external network
                else if (line.StartsWith("remoteip:"))
                    cache.RemoteIP = IPAddress.Parse(line.Substring(9));

                // set next publish time
                else if (line.StartsWith("timeout:"))
                    timeout = double.Parse(line.Substring(8));

                else if (line.StartsWith("load:low"))
                    low = true;
            }

            cache.NextPublish = Core.TimeNow.AddMinutes(Math.Max(timeout, 15)); // dont change to min

            // if cache low auto publish to low cache so that network can be initialized
            if (low)
                new Thread(WebPublish).Start(cache);
                // more caches will be queried by the bootstrap if network not responsive
        }
Пример #29
0
 public DhtLookup(DhtContact contact)
 {
     Contact = contact;
     Status  = LookupStatus.None;
 }
Пример #30
0
 public BootstrapItem(OpCore core, DhtContact contact)
 {
     Core = core;
     Contact = contact;
 }
Пример #31
0
        private void RemoveContact(DhtContact target)
        {
            // alert app of new bounds? yes need to activate caching to new nodes in bounds as network shrinks

            bool refreshBuckets = false;
            bool refreshXor     = false;
            bool refreshHigh    = false;
            bool refreshLow     = false;


            if (ContactMap.ContainsKey(target.RoutingID))
            {
                ContactMap.Remove(target.RoutingID);
            }

            foreach (DhtBucket check in BucketList)
            {
                if (check.ContactList.Contains(target))
                {
                    refreshBuckets = check.ContactList.Remove(target) ? true : refreshBuckets;
                    break;
                }
            }

            refreshXor  = NearXor.Contacts.Remove(target) ? true : refreshXor;
            refreshHigh = NearHigh.Contacts.Remove(target) ? true : refreshHigh;
            refreshLow  = NearLow.Contacts.Remove(target) ? true : refreshLow;


            if (refreshBuckets)
            {
                CheckMerge();
            }


            // refesh lists that have been modified by getting next closest contacts
            List <DhtContact> replicate = new List <DhtContact>();

            if (refreshXor)
            {
                NearXor.Contacts = Find(LocalRoutingID, NearXor.Max);

                // set bound to furthest contact in range
                if (NearXor.Contacts.Count == NearXor.Max)
                {
                    DhtContact furthest = NearXor.Contacts[NearXor.Max - 1];

                    NearXor.SetBounds(LocalRoutingID ^ furthest.RoutingID,
                                      Network.Local.UserID ^ furthest.UserID);

                    // ensure node being replicated to hasnt already been replicated to through another list
                    if (!NearHigh.Contacts.Contains(furthest) &&
                        !NearLow.Contacts.Contains(furthest) &&
                        !replicate.Contains(furthest))
                    {
                        replicate.Add(furthest);
                    }
                }
                else
                {
                    NearXor.SetBounds(ulong.MaxValue, ulong.MaxValue);
                }
            }

            // node removed from closest, so there isnt anything in buckets closer than lower bound
            // so find node next closest to lower bound
            if (refreshLow)
            {
                DhtContact closest = null;
                ulong      bound   = NearLow.Contacts.Count > 0 ? NearLow.Contacts[0].RoutingID : LocalRoutingID;

                foreach (DhtBucket x in BucketList)
                {
                    foreach (DhtContact contact in x.ContactList)
                    {
                        if (closest == null ||
                            (closest.RoutingID < contact.RoutingID && contact.RoutingID < bound))
                        {
                            closest = contact;
                        }
                    }
                }

                if (closest != null && !NearLow.Contacts.Contains(closest))
                {
                    NearLow.Contacts.Insert(0, closest);

                    if (!NearXor.Contacts.Contains(closest) &&
                        !NearHigh.Contacts.Contains(closest) &&
                        !replicate.Contains(closest))
                    {
                        replicate.Add(closest);
                    }
                }

                if (NearLow.Contacts.Count < NearLow.Max)
                {
                    NearLow.SetBounds(0, 0);
                }
                else
                {
                    NearLow.SetBounds(NearLow.Contacts[0].RoutingID, NearLow.Contacts[0].UserID);
                }
            }

            // high - get next highest
            if (refreshHigh)
            {
                DhtContact closest = null;
                ulong      bound   = NearHigh.Contacts.Count > 0 ? NearHigh.Contacts[NearHigh.Contacts.Count - 1].RoutingID : LocalRoutingID;

                foreach (DhtBucket x in BucketList)
                {
                    foreach (DhtContact contact in x.ContactList)
                    {
                        if (closest == null ||
                            (bound < contact.RoutingID && contact.RoutingID < closest.RoutingID))
                        {
                            closest = contact;
                        }
                    }
                }

                if (closest != null && !NearHigh.Contacts.Contains(closest))
                {
                    NearHigh.Contacts.Insert(NearHigh.Contacts.Count, closest);

                    if (!NearXor.Contacts.Contains(closest) &&
                        !NearLow.Contacts.Contains(closest) &&
                        !replicate.Contains(closest))
                    {
                        replicate.Add(closest);
                    }
                }

                if (NearHigh.Contacts.Count < NearHigh.Max)
                {
                    NearHigh.SetBounds(ulong.MaxValue, ulong.MaxValue);
                }
                else
                {
                    NearHigh.SetBounds(NearHigh.Contacts[NearHigh.Contacts.Count - 1].RoutingID,
                                       NearHigh.Contacts[NearHigh.Contacts.Count - 1].UserID);
                }
            }

            foreach (DhtContact contact in replicate)
            {
                Network.Store.Replicate(contact);
            }
        }
Пример #32
0
        public void Replicate(DhtContact contact)
        {
            // dont replicate to local region until we've established our position in the dht
            if (!Network.Established)
            {
                return;
            }


            // when new user comes into our cache area, we send them the data we have in our high/low/xor bounds

            // replicate is only for cached area
            // for remote user stuff that loads up with client, but now out of bounds, it is
            // republished by the uniqe modifier on data

            List <PatchTag> PatchList = new List <PatchTag>();

            // get data that needs to be replicated from components
            // structure as so
            //      contact
            //          service []
            //              datatype []
            //                  patch data []

            foreach (uint service in ReplicateEvent.HandlerMap.Keys)
            {
                foreach (uint datatype in ReplicateEvent.HandlerMap[service].Keys)
                {
                    List <byte[]> patches = ReplicateEvent.HandlerMap[service][datatype].Invoke(contact);

                    if (patches != null)
                    {
                        foreach (byte[] data in patches)
                        {
                            PatchTag patch = new PatchTag();
                            patch.Service  = service;
                            patch.DataType = datatype;
                            patch.Tag      = data;

                            PatchList.Add(patch);
                        }
                    }
                }
            }

            PatchPacket packet = new PatchPacket();

            int totalSize = 0;

            foreach (PatchTag patch in PatchList)
            {
                if (patch.Tag.Length + totalSize > 1000)
                {
                    if (packet.PatchData.Count > 0)
                    {
                        Send_StoreReq(contact, contact, new DataReq(null, contact.UserID, 0, 0, packet.Encode(Network.Protocol)));
                    }

                    packet.PatchData.Clear();
                    totalSize = 0;
                }

                packet.PatchData.Add(patch);
                totalSize += patch.Tag.Length;
            }

            if (packet.PatchData.Count > 0)
            {
                Send_StoreReq(contact, contact, new DataReq(null, contact.UserID, 0, 0, packet.Encode(Network.Protocol)));
            }
        }
Пример #33
0
        public static new DhtContact ReadPacket(G2Header root)
        {
            // read payload
            DhtContact contact = new DhtContact();

            contact.UserID = BitConverter.ToUInt64(root.Data, root.PayloadPos);
            contact.ClientID = BitConverter.ToUInt16(root.Data, root.PayloadPos + 8);
            contact.UdpPort = BitConverter.ToUInt16(root.Data, root.PayloadPos + 10);
            contact.TcpPort = BitConverter.ToUInt16(root.Data, root.PayloadPos + 12);

            // read packets
            G2Protocol.ResetPacket(root);

            G2Header child = new G2Header(root.Data);

            while (G2Protocol.ReadNextChild(root, child) == G2ReadResult.PACKET_GOOD)
            {
                if (!G2Protocol.ReadPayload(child))
                    continue;

                switch (child.Name)
                {
                    case Packet_IP:
                        contact.IP = new IPAddress(Utilities.ExtractBytes(child.Data, child.PayloadPos, child.PayloadSize));
                        break;

                    case Packet_Server:
                        contact.TunnelServer = DhtAddress.ReadPacket(child);
                        break;

                    case Packet_Client:
                        contact.TunnelClient = TunnelAddress.FromBytes(child.Data, child.PayloadPos);
                        break;
                }
            }

            return contact;
        }
Пример #34
0
        public void RoutingUpdate(DhtContact contact)
        {
            //*** if enough nodes in local neighborhood that are untrusted then they need to figure out
            // among themselves what the deal is, because entire network could be clueless people
            // and this line of code will flood the network to aimless searches

            // find node if structure not known
            //if (StructureKnown)
            //    return;

            //OpTrust trust = GetTrust(contact.DhtID);

            //if (trust == null)
            //    Cache.Research(contact.DhtID);
        }
Пример #35
0
        public void Add(DhtContact newContact, bool pong)
        {
            if (Core.User != null && Core.User.Settings.OpAccess == AccessType.Secret)
            {
                Debug.Assert(newContact.TunnelClient == null);
            }

            if (newContact.UserID == 0)
            {
                Network.UpdateLog("Routing", "Zero add attempt");
                return;
            }

            if (newContact.UserID == Network.Local.UserID && newContact.ClientID == Network.Local.ClientID)
            {
                // happens because nodes will include ourselves in returnes to search requests
                //Network.UpdateLog("Routing", "Self add attempt");
                return;
            }

            if (newContact.ClientID == 0)
            {
                return;
            }


            // test to check if non open hosts being added to routing table through simulation
            if (Core.Sim != null && newContact.TunnelClient == null)
            {
                IPEndPoint address = new IPEndPoint(newContact.IP, newContact.UdpPort);

                if (Core.Sim.Internet.UdpEndPoints.ContainsKey(address))
                {
                    DhtNetwork checkNet = Core.Sim.Internet.UdpEndPoints[address];

                    if (checkNet.Local.UserID != newContact.UserID ||
                        checkNet.Local.ClientID != newContact.ClientID ||
                        checkNet.TcpControl.ListenPort != newContact.TcpPort ||
                        checkNet.Core.Sim.RealFirewall != FirewallType.Open)
                    {
                        throw new Exception("Routing add mismatch");
                    }
                }
            }

            // if dht enabled routing entries are set alive by pong
            // many things call add, like the location service, but don't want to falsely report being responsive
            // so only trigger dht responsive when a direct pong comes in
            if (!DhtEnabled || pong)
            {
                newContact.LastSeen = Core.TimeNow;

                if (ContactMap.ContainsKey(newContact.RoutingID))
                {
                    ContactMap[newContact.RoutingID].Alive(Core.TimeNow);
                }

                SetResponsive(true);
            }

            Network.Cache.AddContact(newContact);

            if (ContactMap.ContainsKey(newContact.RoutingID))
            {
                if (!Network.IsLookup)
                {
                    DhtContact dupe = ContactMap[newContact.RoutingID];

                    // tunnel may change from pong / location update etc.. reflect in routing
                    // once host is open and in routing, prevent it from being maliciously set back to tunneled
                    if (dupe.TunnelServer != null)
                    {
                        dupe.TunnelServer = newContact.TunnelServer;
                        dupe.TunnelClient = newContact.TunnelClient;
                    }
                }

                // dont handle dupes
                return;
            }

            // add to searches
            foreach (DhtSearch search in Network.Searches.Active)
            {
                search.Add(newContact);
            }


            AddtoBucket(newContact);

            bool replicate = false;

            // check/set xor bound, cant combine below because both need to run
            if (CheckXor(newContact))
            {
                replicate = true;
            }

            // check if should be added to high/low
            if (CheckHighLow(newContact))
            {
                replicate = true;
            }

            if (replicate)
            {
                Network.Store.Replicate(newContact);
            }

            Core.RunInGuiThread(Network.UpdateBandwidthGraph);
        }
Пример #36
0
        public void ConsoleCommand(string command)
        {
            if (command == "clear")
                ConsoleText.Clear();
            if (command == "pause")
                PauseLog = !PauseLog;

            ConsoleLog("> " + command);

            try
            {
                string[] commands = command.Split(' ');

                if(commands.Length == 0)
                    return;

                if(commands[0] == "testDht" && commands.Length == 2)
                {
                    int count = Convert.ToInt32(commands[1]);

                    for(int i = 0; i < count; i++)
                    {
                        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

                        UInt64 kid = Utilities.StrongRandUInt64(rng);

                        // create random contact
                        DhtContact contact = new DhtContact(kid, 7, new IPAddress(7), 7, 7);

                        // add to routing
                        Network.Routing.Add(contact);
                    }
                }

                if(commands[0] == "gc")
                {
                    GC.Collect();
                }

                if(commands[0] == "killtcp")
                {
                    /*ConsoleLog(TcpControl.Connections.Count.ToString() + " tcp sockets on list");

                    lock(TcpControl.Connections.SyncRoot)
                        foreach(TcpConnect connection in TcpControl.Connections)
                            connection.CleanClose("Force Disconnect");*/
                }
                if(commands[0] == "fwstatus")
                {
                    ConsoleLog("Status set to " + Firewall.ToString());
                }

                if(commands[0] == "fwset" && commands.Length > 1)
                {
                    if(commands[1] == "open")
                        SetFirewallType(FirewallType.Open);
                    if(commands[1] == "nat")
                        SetFirewallType(FirewallType.NAT);
                    if(commands[1] == "blocked")
                        SetFirewallType(FirewallType.Blocked);
                }

                if(commands[0] == "listening")
                {
                    /*ConsoleLog("Listening for TCP on port " + TcpControl.ListenPort.ToString());
                    ConsoleLog("Listening for UDP on port " + UdpControl.ListenPort.ToString());*/
                }

                if(commands[0] == "ping" && commands.Length > 0)
                {
                    //string[] addr = commands[1].Split(':');

                    //GlobalNet.Send_Ping(IPAddress.Parse(addr[0]), Convert.ToUInt16(addr[1]));
                }

                if (commands[0] == "tcptest" && commands.Length > 0)
                {
                    string[] addr = commands[1].Split(':');

                    //TcpControl.MakeOutbound(IPAddress.Parse(addr[0]), Convert.ToUInt16(addr[1]),0);
                }
            }
            catch(Exception ex)
            {
                ConsoleLog("Exception " + ex.Message);
            }
        }
Пример #37
0
        private void AddtoBucket(DhtContact newContact)
        {
            // add to buckets
            int depth = 0;
            int pos   = 1;

            List <DhtContact> moveContacts = null;

            lock (BucketList)
                foreach (DhtBucket bucket in BucketList)
                {
                    // if not the last bucket
                    if (!bucket.Last)
                    {
                        // if this is not the contacts place on tree
                        if (Utilities.GetBit(LocalRoutingID, depth) == Utilities.GetBit(newContact.RoutingID, depth))
                        {
                            depth++;
                            pos++;
                            continue;
                        }
                    }


                    // if cant add contact
                    if (!bucket.Add(newContact))
                    {
                        if (BucketList.Count > BucketLimit)
                        {
                            return;
                        }

                        // split bucket if last and try add again
                        if (bucket.Last)
                        {
                            // save contacts from bucket and reset
                            moveContacts       = bucket.ContactList;
                            bucket.ContactList = new List <DhtContact>();

                            // create new bucket
                            bucket.Last = false;
                            BucketList.Add(new DhtBucket(this, bucket.Depth + 1, true));

                            // reaching here means dhtbucket::add was never called successfully, it gets recalled after the move
                            //Network.Store.RoutingUpdate(BucketList.Count);
                            break;
                        }

                        // else contact dropped
                    }

                    break;
                }

            // split should not recurse anymore than once
            if (moveContacts != null)
            {
                foreach (DhtContact contact in moveContacts)
                {
                    AddtoBucket(contact);
                }

                AddtoBucket(newContact);
            }
        }
Пример #38
0
        public void Found(DhtContact contact, bool proxied)
        {
            FoundContact = contact;

            if( !proxied )
                FinishSearch("Found");

            else
            {
                FoundProxy = true;
                FinishSearch("Found Proxy");
            }
        }
Пример #39
0
        private bool CheckHighLow(DhtContact check)
        {
            // dont store self in high/low, buckets do that

            // we keep high/low nodes (not xor'd distance) because xor is absolute and
            // will cause a cluster of nodes to cache each other and ignore a node further away
            // then they are to each other, to ensure that far off node's stuff exists on network
            // we also set bounds high/low based on ID so node will always have someone to cache for it
            // nodes in high/low and xor ranges should mostly overlap

            // if another client of same user added, in bounds, replicate to it
            if (NearLow.RoutingBound < check.RoutingID && check.RoutingID < LocalRoutingID)
            {
                // sorted lowest to ourself
                int i = 0;
                for ( ; i < NearLow.Contacts.Count; i++)
                {
                    if (check.RoutingID < NearLow.Contacts[i].RoutingID)
                    {
                        break;
                    }
                }

                NearLow.Contacts.Insert(i, check);
                ContactMap[check.RoutingID] = check;

                if (NearLow.Contacts.Count > NearLow.Max)
                {
                    DhtContact remove = NearLow.Contacts[0];
                    NearLow.Contacts.Remove(remove);
                    if (!InBucket(remove))
                    {
                        ContactMap.Remove(remove.RoutingID);
                    }


                    NearLow.SetBounds(NearLow.Contacts[0].RoutingID, NearLow.Contacts[0].UserID);
                }

                return(true);
            }


            if (LocalRoutingID < check.RoutingID && check.RoutingID < NearHigh.RoutingBound)
            {
                // sorted ourself to highest
                int i = 0;
                for (; i < NearHigh.Contacts.Count; i++)
                {
                    if (check.RoutingID < NearHigh.Contacts[i].RoutingID)
                    {
                        break;
                    }
                }

                NearHigh.Contacts.Insert(i, check);
                ContactMap[check.RoutingID] = check;

                if (NearHigh.Contacts.Count > NearHigh.Max)
                {
                    DhtContact remove = NearHigh.Contacts[NearHigh.Contacts.Count - 1];
                    NearHigh.Contacts.Remove(remove);
                    if (!InBucket(remove))
                    {
                        ContactMap.Remove(remove.RoutingID);
                    }

                    NearHigh.SetBounds(NearHigh.Contacts[NearHigh.Contacts.Count - 1].RoutingID,
                                       NearHigh.Contacts[NearHigh.Contacts.Count - 1].UserID);
                }

                return(true);
            }

            return(false);
        }
Пример #40
0
        public void Send_Ping(DhtContact contact)
        {
            Ping ping = new Ping();
            ping.Source = GetLocalSource();
            ping.RemoteIP = contact.IP;
            ping.Ident = contact.Ident = (ushort)Core.RndGen.Next(ushort.MaxValue);

            // always send ping udp, tcp pings are sent manually
            int sentBytes = SendPacket(contact, ping);

            Core.ServiceBandwidth[Core.DhtServiceID].OutPerSec += sentBytes;
        }