public void Receive_ProxyRequest(G2ReceivedPacket packet) { ProxyReq request = ProxyReq.Decode(packet); ProxyAck ack = new ProxyAck(); ack.Source = GetLocalSource(); // check if there is space for type required if (Core.Firewall == FirewallType.Open && TcpControl.AcceptProxy(request.Type, ack.Source.UserID)) { ack.Accept = true; } else if (packet.ReceivedTcp) { packet.Tcp.CleanClose("Couldn't accept proxy request"); return; } // always send some contacts along so node can find closer proxy ack.ContactList = Routing.Find(request.SenderID, 8); // received request tcp if (packet.ReceivedUdp) { UdpControl.SendTo(packet.Source, ack); } // received request tcp else { packet.Tcp.Proxy = request.Type; packet.Tcp.SendPacket(ack); TcpControl.AddProxy(packet.Tcp); // check if a proxy needs to be disconnected now because overflow TcpControl.CheckProxies(); } }
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); } } }