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 Receive_Ping(G2ReceivedPacket packet) { Core.ServiceBandwidth[Core.DhtServiceID].InPerSec += packet.Root.Data.Length; Ping ping = Ping.Decode(packet); bool lanIP = Utilities.IsLocalIP(packet.Source.IP); bool validSource = (!lanIP || LanMode && lanIP); // set local IP SetLocalIP(ping.RemoteIP, packet); // check loop back if (ping.Source != null && Local.Equals(ping.Source)) { if (packet.ReceivedTcp) { packet.Tcp.CleanClose("Loopback connection"); } return; } // dont send back pong if received tunneled and no longer need to use lookup proxies // remote would only send tunneled ping if UseGlobalProxies published info on network // let our lookup address expire from remote's routing table if (packet.Tunneled && !UseLookupProxies) { return; } // setup pong reply Pong pong = new Pong(); if (ping.Source != null) { pong.Source = GetLocalSource(); } if (ping.RemoteIP != null) { pong.RemoteIP = packet.Source.IP; } if (!IsLookup && Core.Context.SignedUpdate != null && Core.Context.SignedUpdate.Loaded) { pong.Version = Core.Context.SignedUpdate.SequentialVersion; } int sentBytes = 0; // received tcp if (packet.ReceivedTcp) { if (ping.Source == null) { packet.Tcp.SendPacket(pong); return; } if (validSource) { if (ping.Source.Firewall == FirewallType.Open) { Routing.Add(new DhtContact(ping.Source, packet.Source.IP)); } // received incoming tcp means we are not firewalled if (!packet.Tcp.Outbound) { // done here to prevent setting open for loopback tcp connection Core.SetFirewallType(FirewallType.Open); pong.Source.Firewall = FirewallType.Open; } } // check if already connected if (packet.Tcp.Proxy == ProxyType.Unset && TcpControl.GetProxy(ping.Source) != null) { packet.Tcp.CleanClose("Dupelicate Connection"); return; } packet.Tcp.UserID = ping.Source.UserID; packet.Tcp.ClientID = ping.Source.ClientID; packet.Tcp.TcpPort = ping.Source.TcpPort; packet.Tcp.UdpPort = ping.Source.UdpPort; // if inbound connection, to our open host, and haven't checked fw yet if (!packet.Tcp.Outbound && ping.Source.Firewall != FirewallType.Open && !packet.Tcp.CheckedFirewall) { TcpControl.MakeOutbound(packet.Source, ping.Source.TcpPort, "check firewall"); packet.Tcp.CheckedFirewall = true; } pong.Direct = true; sentBytes = packet.Tcp.SendPacket(pong); // dont send close if proxies maxxed yet, because their id might be closer than current proxies } // ping received udp or tunneled else { if (validSource) { // received udp traffic, we must be behind a NAT at least if (Core.Firewall == FirewallType.Blocked && !packet.Tunneled) { Core.SetFirewallType(FirewallType.NAT); } Routing.TryAdd(packet, ping.Source); } // if received over lan, the port isn't set if (packet.Source.UdpPort == 0) { packet.Source.UdpPort = ping.Source.UdpPort; } // send pong sentBytes = SendPacket(packet.Source, pong); } Core.ServiceBandwidth[Core.DhtServiceID].OutPerSec += sentBytes; }