public void Search_DoneSelf(DhtSearch search) { // if not already established (an hourly self re-search) if (!Established) { // a little buffer time for local nodes to send patch files // so we dont start sending our own huge patch files FireStatusChange = 10; } }
void Search_DonePublish(DhtSearch search) { DataReq publish = (DataReq)search.Carry; // need to carry over componentid that wanted search also so store works foreach (DhtLookup node in search.LookupList) { Send_StoreReq(node.Contact, null, publish); } }
public void CheckConnectionStatus() { // dht responsiveness is only reliable if we can accept incoming connections, other wise we might be // behind a NAT and in that case won't be able to receive traffic from anyone who has not sent us stuff bool connected = (Routing.DhtEnabled && Routing.DhtResponsive) || TcpControl.ProxyServers.Count > 0 || TcpControl.ProxyClients.Count > 0; if (connected == Responsive) { return; } string name = IsLookup ? "Lookup" : Core.User.Settings.Operation; // else set new value Responsive = connected; if (Responsive) { // done to fill up routing table down to self DhtSearch search = Searches.Start(Routing.LocalRoutingID + 1, "Self", Core.DhtServiceID, 0, null, null); if (search != null) { search.DoneEvent = Search_DoneSelf; Routing.NextSelfSearch = Core.TimeNow.AddHours(1); // at end of self search, status change count down triggered } UpdateLog("general", name + " network connected"); } // network dead else { Established = false; SetLanMode(true); Cache.Reset(); UpdateLog("general", name + " network disconnected"); } FireStatusChangeEvent(); }
public void PublishNetwork(ulong target, uint service, uint datatype, byte[] data) { if (Core.InvokeRequired) { Debug.Assert(false); } string type = "Publish " + Core.GetServiceName(service); if (target == Core.UserID) { Network.UpdateLog("general", "Publishing " + Core.GetServiceName(service)); } DataReq store = new DataReq(null, target, service, datatype, data); // find users closest to publish target if (target == Network.Local.UserID) { foreach (DhtContact closest in Network.Routing.GetCacheArea()) { Send_StoreReq(closest, null, store); } foreach (TcpConnect socket in Network.TcpControl.ProxyClients) { Send_StoreReq(new DhtAddress(socket.RemoteIP, socket), null, store); } } else { DhtSearch search = Network.Searches.Start(target, type, 0, 0, null, null); if (search != null) { search.DoneEvent = Search_DonePublish; search.Carry = store; } } }
public DhtSearch Start(ulong key, string name, uint service, uint datatype, byte[] parameters, Action <DhtSearch, DhtAddress, byte[]> found) { if (Core.InvokeRequired) { Debug.Assert(false); } // transfer componenent does its own duplicate checks // also there can exist multiple transfers with with same trar if (Core.Transfers == null || service != Core.Transfers.ServiceID) { foreach (DhtSearch pending in Pending) { if (pending.TargetID == key && pending.Service == service && Utilities.MemCompare(parameters, pending.Parameters)) { return(null); } } foreach (DhtSearch active in Active) { if (active.TargetID == key && active.Service == service && Utilities.MemCompare(parameters, active.Parameters)) { return(null); } } } DhtSearch search = new DhtSearch(this, key, name, service, datatype); search.FoundEvent = found; search.Parameters = parameters; search.Log("Pending"); Pending.Add(search); return(search); }
public void SecondTimer() { // get active search count int searchCount = 0; lock (Active) foreach (DhtSearch search in Active) { if (search.ProxyTcp == null || search.ProxyTcp.Proxy == ProxyType.Server) { searchCount++; } } // if pending searches if (Network.Responsive) // only move from pending to active if network responsive { while (searchCount < MAX_SEARCHES && Pending.Count > 0) { DhtSearch move = Pending[0]; searchCount++; // do here to get out of loop if (move.Activate()) { move.Log("Active"); Active.Add(move); Pending.Remove(move); } } } // pulse active searches List <DhtSearch> removeList = new List <DhtSearch>(); lock (Active) foreach (DhtSearch search in Active) { if (search.Finished) { removeList.Add(search); } else { search.SecondTimer(); } } // remove finished searches foreach (DhtSearch search in removeList) { if (Active.Contains(search)) { lock (Active) Active.Remove(search); } if (Pending.Contains(search)) { lock (Pending) Pending.Remove(search); } string log = "Finished"; if (search.FoundValues.Count > 0) { log += ", " + search.FoundValues.Count.ToString() + " Values Found"; } if (search.FinishReason != null) { log += ", " + search.FinishReason; } search.Log(log); } }
public void ReceiveRequest(G2ReceivedPacket packet) { SearchReq request = SearchReq.Decode(packet); // loopback if (Network.Local.Equals(request.Source)) { return; } if (Core.ServiceBandwidth.ContainsKey(request.Service)) { Core.ServiceBandwidth[request.Service].InPerSec += packet.Root.Data.Length; } if (packet.ReceivedTcp && request.SearchID != 0) { // request from blocked node if (packet.Tcp.Proxy == ProxyType.ClientBlocked) { int proxySearches = 0; lock (Active) foreach (DhtSearch search in Active) { if (search.ProxyTcp == packet.Tcp) { proxySearches++; if (request.EndProxySearch && search.SearchID == request.SearchID) { search.FinishSearch("Proxied node finished search"); return; } } } if (proxySearches < MAX_SEARCHES) { DhtSearch search = new DhtSearch(this, request.TargetID, "Proxy", request.Service, request.DataType); search.Parameters = request.Parameters; search.ProxyTcp = packet.Tcp; search.SearchID = request.SearchID; search.Activate(); Active.Add(search); search.Log("Active - Proxy Search"); } // continue processing request and send local results } // request from proxy server if (packet.Tcp.Proxy == ProxyType.Server && request.EndProxySearch) { lock (Active) foreach (DhtSearch search in Active) { if (search.SearchID == request.SearchID) { if (!search.Finished) { search.FinishSearch("Server finished search"); } } } } } if (request.Source.Firewall == FirewallType.Open) { Routing.Add(new DhtContact(request.Source, packet.Source.IP)); } // forward to proxied nodes foreach (TcpConnect socket in Network.TcpControl.ProxyClients) { // prevents incoming udp from proxy and being forwarded to same host tcp if (socket != packet.Tcp && !(packet.Source.UserID == socket.UserID && packet.Source.ClientID == socket.ClientID)) { request.FromAddress = packet.Source; socket.SendPacket(request); } } // send ack bool sendNoResults = (request.SearchID != 0 || request.Service == Core.DhtServiceID) && (packet.ReceivedUdp || packet.Tunneled); SearchAck ack = new SearchAck(); ack.Source = Network.GetLocalSource(); ack.SearchID = request.SearchID; ack.Service = request.Service; // search for connected proxy if (Network.TcpControl.ProxyMap.Values.Any(p => p.UserID == request.TargetID)) { ack.Proxied = true; } // only send nodes from proxy server routing table if (request.Nodes && (packet.ReceivedUdp || packet.Tunneled)) { ack.ContactList = Routing.Find(request.TargetID, 8); } // dont send an ack if behind a proxy server and no results if (!SearchEvent.Contains(request.Service, request.DataType)) { if (sendNoResults) { SendAck(packet, request, ack); } } else { List <byte[]> results = new List <byte[]>(); SearchEvent[request.Service, request.DataType].Invoke(request.TargetID, request.Parameters, results); // if nothing found, still send ack with closer contacts if (results == null || results.Count == 0) { if (sendNoResults) { SendAck(packet, request, ack); } return; } // if a direct search if (request.SearchID == 0) { foreach (byte[] value in results) { Network.Store.Send_StoreReq(packet.Source, packet.Tcp, new DataReq(null, request.TargetID, request.Service, request.DataType, value)); } return; } // else send normal search results int totalSize = 0; foreach (byte[] data in results) { if (data.Length + totalSize > 1200) { SendAck(packet, request, ack); ack.ValueList.Clear(); ack.ContactList.Clear(); // dont send twice totalSize = 0; } ack.ValueList.Add(data); totalSize += data.Length; } if (totalSize > 0) { SendAck(packet, request, ack); } } }
void Search_DonePublish(DhtSearch search) { DataReq publish = (DataReq)search.Carry; // need to carry over componentid that wanted search also so store works foreach (DhtLookup node in search.LookupList) Send_StoreReq(node.Contact, null, publish); }
void Search_FoundTemp(DhtSearch search, DhtAddress source, byte[] data) { object[] carry = search.Carry as object[]; object hostArg = carry[0]; Action<byte[], object> hostFoundEvent = carry[1] as Action<byte[], object>; OpCore sourceCore = carry[2] as OpCore; // strip temp data TempData temp = TempData.Decode(search.TargetID, data); if (temp == null) return; Action FireEvent = () => hostFoundEvent.Invoke(temp.Data, hostArg); // fire host event with carry vars if (sourceCore != null) sourceCore.RunInCoreAsync(FireEvent); else FireEvent.Invoke(); }
void Search_FoundTime(DhtSearch search, DhtAddress source, byte[] data) { OpBoard board = GetBoard(search.TargetID); if (data.Length < TheadSearch_ResultsSize) return; PostUID uid = PostUID.FromBytes(data, 0); ushort version = BitConverter.ToUInt16(data, 16); OpPost post = GetPost(search.TargetID, uid); if (post != null) if (post.Header.Version >= version) return; PostSearch(search.TargetID, uid, version); }
void Search_FoundThread(DhtSearch search, DhtAddress source, byte[] data) { if (data.Length < TheadSearch_ResultsSize) return; PostUID uid = PostUID.FromBytes(data, 0); ushort version = BitConverter.ToUInt16(data, 16); ushort replies = BitConverter.ToUInt16(data, 18); OpPost post = GetPost(search.TargetID, uid); if (post != null) { if (post.Replies < replies) { post.Replies = replies; UpdateGui(post); } // if we have current version, pass, else download if (post.Header.Version >= version) return; } PostSearch(search.TargetID, uid, version); // if parent save replies value if (replies != 0) { int hash = search.TargetID.GetHashCode() ^ uid.GetHashCode(); ushort savedReplies = 0; if (SavedReplyCount.SafeTryGetValue(hash, out savedReplies)) if (savedReplies < replies) SavedReplyCount.SafeAdd(hash, replies); } }
public DhtSearch Start(ulong key, string name, uint service, uint datatype, byte[] parameters, Action<DhtSearch, DhtAddress, byte[]> found) { if (Core.InvokeRequired) Debug.Assert(false); // transfer componenent does its own duplicate checks // also there can exist multiple transfers with with same trar if (Core.Transfers == null || service != Core.Transfers.ServiceID) { foreach (DhtSearch pending in Pending) if (pending.TargetID == key && pending.Service == service && Utilities.MemCompare(parameters, pending.Parameters)) return null; foreach (DhtSearch active in Active) if (active.TargetID == key && active.Service == service && Utilities.MemCompare(parameters, active.Parameters)) return null; } DhtSearch search = new DhtSearch(this, key, name, service, datatype); search.FoundEvent = found; search.Parameters = parameters; search.Log("Pending"); Pending.Add(search); return search; }
public void ReceiveRequest(G2ReceivedPacket packet) { SearchReq request = SearchReq.Decode(packet); // loopback if (Network.Local.Equals(request.Source)) return; if (Core.ServiceBandwidth.ContainsKey(request.Service)) Core.ServiceBandwidth[request.Service].InPerSec += packet.Root.Data.Length; if (packet.ReceivedTcp && request.SearchID != 0) { // request from blocked node if (packet.Tcp.Proxy == ProxyType.ClientBlocked) { int proxySearches = 0; lock (Active) foreach (DhtSearch search in Active) if (search.ProxyTcp == packet.Tcp) { proxySearches++; if (request.EndProxySearch && search.SearchID == request.SearchID) { search.FinishSearch("Proxied node finished search"); return; } } if (proxySearches < MAX_SEARCHES) { DhtSearch search = new DhtSearch(this, request.TargetID, "Proxy", request.Service, request.DataType); search.Parameters = request.Parameters; search.ProxyTcp = packet.Tcp; search.SearchID = request.SearchID; search.Activate(); Active.Add(search); search.Log("Active - Proxy Search"); } // continue processing request and send local results } // request from proxy server if (packet.Tcp.Proxy == ProxyType.Server && request.EndProxySearch) { lock (Active) foreach (DhtSearch search in Active) if (search.SearchID == request.SearchID) if( !search.Finished ) search.FinishSearch("Server finished search"); } } if (request.Source.Firewall == FirewallType.Open) Routing.Add(new DhtContact(request.Source, packet.Source.IP)); // forward to proxied nodes foreach (TcpConnect socket in Network.TcpControl.ProxyClients) // prevents incoming udp from proxy and being forwarded to same host tcp if(socket != packet.Tcp && !(packet.Source.UserID == socket.UserID && packet.Source.ClientID == socket.ClientID)) { request.FromAddress = packet.Source; socket.SendPacket(request); } // send ack bool sendNoResults = (request.SearchID != 0 || request.Service == Core.DhtServiceID) && (packet.ReceivedUdp || packet.Tunneled); SearchAck ack = new SearchAck(); ack.Source = Network.GetLocalSource(); ack.SearchID = request.SearchID; ack.Service = request.Service; // search for connected proxy if (Network.TcpControl.ProxyMap.Values.Any(p => p.UserID == request.TargetID)) ack.Proxied = true; // only send nodes from proxy server routing table if (request.Nodes && (packet.ReceivedUdp || packet.Tunneled)) ack.ContactList = Routing.Find(request.TargetID, 8); // dont send an ack if behind a proxy server and no results if (!SearchEvent.Contains(request.Service, request.DataType)) { if (sendNoResults) SendAck(packet, request, ack); } else { List<byte[]> results = new List<byte[]>(); SearchEvent[request.Service, request.DataType].Invoke(request.TargetID, request.Parameters, results); // if nothing found, still send ack with closer contacts if (results == null || results.Count == 0) { if (sendNoResults) SendAck(packet, request, ack); return; } // if a direct search if (request.SearchID == 0) { foreach(byte[] value in results) Network.Store.Send_StoreReq(packet.Source, packet.Tcp, new DataReq(null, request.TargetID, request.Service, request.DataType, value)); return; } // else send normal search results int totalSize = 0; foreach (byte[] data in results) { if (data.Length + totalSize > 1200) { SendAck(packet, request, ack); ack.ValueList.Clear(); ack.ContactList.Clear(); // dont send twice totalSize = 0; } ack.ValueList.Add(data); totalSize += data.Length; } if(totalSize > 0) SendAck(packet, request, ack); } }
void Search_Found(DhtSearch search, DhtAddress source, byte[] data) { Store_Local(new DataReq(source, search.TargetID, Service, DataType, data)); }
void UpdateList(DhtSearch search) { if (search.FoundValues.Count > 0) { LabelResults.Text = search.FoundValues.Count.ToString() + " Values Found, "; } if (search.FoundContact != null) { LabelResults.Text = "Found Contact(" + search.FoundContact.ClientID.ToString() + ") "; if (search.FoundProxy) LabelResults.Text += "is a proxy"; } // Dht // client foreach (DhtLookup lookup in search.LookupList) ListResults.Items.Add(new ListViewItem(new string[] { Utilities.IDtoBin(lookup.Contact.UserID), lookup.Contact.ClientID.ToString() })); }
void Search_Found(DhtSearch search, DhtAddress source, byte[] data) { G2Header root = new G2Header(data); if (!G2Protocol.ReadPacket(root)) return; UpdateInfo info = UpdateInfo.Decode(root); // verifies signature if (info == null) return; if (Core.Context.SignedUpdate == null || Core.Context.SignedUpdate.SequentialVersion < info.SequentialVersion) { Core.Context.SignedUpdate = info; LookupConfig.WriteUpdateInfo(Core); } // version less than what we have else if (Core.Context.SignedUpdate.SequentialVersion > info.SequentialVersion) return; // version remote has already loaded if (Core.Context.SignedUpdate.Loaded) return; // same sources will be hit as file download search progresses StartDownload(search.TargetID); }