public CachedIP(byte name, DhtContact contact, bool bootstrap) { Name = name; LastSeen = contact.LastSeen; Contact = contact; Bootstrap = bootstrap; }
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); }
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; }
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); }
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; }
public void Found(DhtContact contact, bool proxied) { FoundContact = contact; if (!proxied) { FinishSearch("Found"); } else { FoundProxy = true; FinishSearch("Found Proxy"); } }
private bool InBucket(DhtContact find) { foreach (DhtBucket bucket in BucketList) { foreach (DhtContact contact in bucket.ContactList) { if (contact == find) { return(true); } } } return(false); }
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); }
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); }
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); }
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); }
public string CreateBootstrapLink(DhtContact contact) { return CreateBootstrapLink(contact.UserID, contact.IP, contact.TcpPort, contact.UdpPort); }
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)); } } }
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); }
public DhtLookup(DhtContact contact) { Contact = contact; Status = LookupStatus.None; }
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; }
public void Add(DhtContact newContact) { Add(newContact, false); }
public CrawlNode(DhtContact contact) { Contact = contact; }
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); } }
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; }
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))); }
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; }
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; }
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; }
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; }
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); }
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; } }
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 }
public BootstrapItem(OpCore core, DhtContact contact) { Core = core; Contact = contact; }
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); } }
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))); } }
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; }
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); }
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); }
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); } }
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); } }
public void Found(DhtContact contact, bool proxied) { FoundContact = contact; if( !proxied ) FinishSearch("Found"); else { FoundProxy = true; FinishSearch("Found Proxy"); } }
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); }