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); } } }
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); } }