void Receive_Pong(G2ReceivedPacket packet) { Core.ServiceBandwidth[Core.DhtServiceID].InPerSec += packet.Root.Data.Length; Pong pong = Pong.Decode(packet); SetLocalIP(pong.RemoteIP, packet); bool lanIP = Utilities.IsLocalIP(packet.Source.IP); bool validSource = (!lanIP || LanMode && lanIP); // check if remote has a newer version cached if (!IsLookup && pong.Version != 0 && Core.Update != null) { if (Core.Context.SignedUpdate == null || !Core.Context.SignedUpdate.Loaded || Core.Context.SignedUpdate.SequentialVersion < pong.Version) { // ota update disabled for now //Core.Update.NewVersion(pong.Version, pong.Source.UserID); } } // if received tcp if (packet.ReceivedTcp) { // if regular interval pong if (pong.Source == null) { // keep routing entry fresh so connect state remains if (validSource && packet.Tcp.Proxy == ProxyType.Server) { Routing.Add(new DhtContact(packet.Tcp, packet.Tcp.RemoteIP), true); } } // else connect pong with source info else { // usually a proxied pong from somewhere else to keep our routing fresh if (validSource && pong.Source.Firewall == FirewallType.Open) { Routing.Add(new DhtContact(pong.Source, packet.Source.IP), true); } // pong's direct flag ensures that tcp connection info (especially client ID) is not set with // information from a pong routed through the remote host, but from the host we're directly connected to if (pong.Direct) { packet.Tcp.UserID = pong.Source.UserID; packet.Tcp.ClientID = pong.Source.ClientID; packet.Tcp.TcpPort = pong.Source.TcpPort; packet.Tcp.UdpPort = pong.Source.UdpPort; // if firewalled if (packet.Tcp.Outbound && packet.Tcp.Proxy == ProxyType.Unset) { if (Core.Firewall != FirewallType.Open && TcpControl.AcceptProxy(ProxyType.Server, pong.Source.UserID)) { // send proxy request ProxyReq request = new ProxyReq(); request.SenderID = Local.UserID; request.Type = (Core.Firewall == FirewallType.Blocked) ? ProxyType.ClientBlocked : ProxyType.ClientNAT; packet.Tcp.SendPacket(request); } // else ping/pong done, end connect else { packet.Tcp.CleanClose("Not in need of a proxy"); } } } } } // pong received udp or tunneled else { if (validSource) { if (Core.Firewall == FirewallType.Blocked && !packet.Tunneled) { Core.SetFirewallType(FirewallType.NAT); } // add to routing // on startup, especially in sim everyone starts blocked so pong source firewall is not set right, but still needs to go into routing Routing.TryAdd(packet, pong.Source, true); } // send bootstrap request for nodes if network not responsive // do tcp connect because if 2 nodes on network then one needs to find out they're open if (!Responsive) { Searches.SendRequest(packet.Source, Local.UserID, 0, Core.DhtServiceID, 0, null); if (!packet.Tunneled) // ip isnt set correctly on tunneled, and if tunneled then lookup active and host tested anyways { TcpControl.MakeOutbound(packet.Source, pong.Source.TcpPort, "pong bootstrap"); } } // forward to proxied nodes, so that their routing tables are up to date, so they can publish easily if (Core.Firewall == FirewallType.Open) { pong.FromAddress = packet.Source; pong.RemoteIP = null; pong.Direct = false; foreach (TcpConnect connection in TcpControl.ProxyClients) { connection.SendPacket(pong); } } } }