Ejemplo n.º 1
0
        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);
                    }
                }
            }
        }