Пример #1
0
 public void Search_DoneSelf(DhtSearch search)
 {
     // if not already established (an hourly self re-search)
     if (!Established)
     {
         // a little buffer time for local nodes to send patch files
         // so we dont start sending our own huge patch files
         FireStatusChange = 10;
     }
 }
Пример #2
0
        void Search_DonePublish(DhtSearch search)
        {
            DataReq publish = (DataReq)search.Carry;

            // need to carry over componentid that wanted search also so store works

            foreach (DhtLookup node in search.LookupList)
            {
                Send_StoreReq(node.Contact, null, publish);
            }
        }
Пример #3
0
        public void CheckConnectionStatus()
        {
            // dht responsiveness is only reliable if we can accept incoming connections, other wise we might be
            // behind a NAT and in that case won't be able to receive traffic from anyone who has not sent us stuff
            bool connected = (Routing.DhtEnabled && Routing.DhtResponsive) ||
                             TcpControl.ProxyServers.Count > 0 || TcpControl.ProxyClients.Count > 0;


            if (connected == Responsive)
            {
                return;
            }

            string name = IsLookup ? "Lookup" : Core.User.Settings.Operation;

            // else set new value
            Responsive = connected;

            if (Responsive)
            {
                // done to fill up routing table down to self

                DhtSearch search = Searches.Start(Routing.LocalRoutingID + 1, "Self", Core.DhtServiceID, 0, null, null);

                if (search != null)
                {
                    search.DoneEvent       = Search_DoneSelf;
                    Routing.NextSelfSearch = Core.TimeNow.AddHours(1);
                    // at end of self search, status change count down triggered
                }

                UpdateLog("general", name + " network connected");
            }

            // network dead
            else
            {
                Established = false;

                SetLanMode(true);

                Cache.Reset();

                UpdateLog("general", name + " network disconnected");
            }

            FireStatusChangeEvent();
        }
Пример #4
0
        public void PublishNetwork(ulong target, uint service, uint datatype, byte[] data)
        {
            if (Core.InvokeRequired)
            {
                Debug.Assert(false);
            }

            string type = "Publish " + Core.GetServiceName(service);

            if (target == Core.UserID)
            {
                Network.UpdateLog("general", "Publishing " + Core.GetServiceName(service));
            }

            DataReq store = new DataReq(null, target, service, datatype, data);

            // find users closest to publish target
            if (target == Network.Local.UserID)
            {
                foreach (DhtContact closest in Network.Routing.GetCacheArea())
                {
                    Send_StoreReq(closest, null, store);
                }

                foreach (TcpConnect socket in Network.TcpControl.ProxyClients)
                {
                    Send_StoreReq(new DhtAddress(socket.RemoteIP, socket), null, store);
                }
            }
            else
            {
                DhtSearch search = Network.Searches.Start(target, type, 0, 0, null, null);

                if (search != null)
                {
                    search.DoneEvent = Search_DonePublish;
                    search.Carry     = store;
                }
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
 public void Search_DoneSelf(DhtSearch search)
 {
     // if not already established (an hourly self re-search)
     if (!Established)
     {
         // a little buffer time for local nodes to send patch files
         // so we dont start sending our own huge patch files
         FireStatusChange = 10;
     }
 }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
                }
            }
        }
Пример #9
0
        void Search_DonePublish(DhtSearch search)
        {
            DataReq publish = (DataReq)search.Carry;

            // need to carry over componentid that wanted search also so store works

            foreach (DhtLookup node in search.LookupList)
                Send_StoreReq(node.Contact, null, publish);
        }
Пример #10
0
        void Search_FoundTemp(DhtSearch search, DhtAddress source, byte[] data)
        {
            object[] carry = search.Carry as object[];

            object hostArg = carry[0];
            Action<byte[], object> hostFoundEvent = carry[1] as Action<byte[], object>;
            OpCore sourceCore = carry[2] as OpCore;

            // strip temp data
            TempData temp = TempData.Decode(search.TargetID, data);

            if (temp == null)
                return;

            Action FireEvent = () => hostFoundEvent.Invoke(temp.Data, hostArg);

            // fire host event with carry vars
            if (sourceCore != null)
                sourceCore.RunInCoreAsync(FireEvent);
            else
                FireEvent.Invoke();
        }
Пример #11
0
        void Search_FoundTime(DhtSearch search, DhtAddress source, byte[] data)
        {
            OpBoard board = GetBoard(search.TargetID);

            if (data.Length < TheadSearch_ResultsSize)
                return;

            PostUID uid = PostUID.FromBytes(data, 0);
            ushort version = BitConverter.ToUInt16(data, 16);

            OpPost post = GetPost(search.TargetID, uid);

            if (post != null)
                if (post.Header.Version >= version)
                    return;

            PostSearch(search.TargetID, uid, version);
        }
Пример #12
0
        void Search_FoundThread(DhtSearch search, DhtAddress source, byte[] data)
        {
            if (data.Length < TheadSearch_ResultsSize)
                return;

            PostUID uid = PostUID.FromBytes(data, 0);
            ushort version = BitConverter.ToUInt16(data, 16);
            ushort replies = BitConverter.ToUInt16(data, 18);

            OpPost post = GetPost(search.TargetID, uid);

            if (post != null)
            {
                if (post.Replies < replies)
                {
                    post.Replies = replies;
                    UpdateGui(post);
                }

                // if we have current version, pass, else download
                if (post.Header.Version >= version)
                    return;
            }

            PostSearch(search.TargetID, uid, version);

            // if parent save replies value
            if (replies != 0)
            {
                int hash = search.TargetID.GetHashCode() ^ uid.GetHashCode();

                ushort savedReplies = 0;
                if (SavedReplyCount.SafeTryGetValue(hash, out savedReplies))
                    if (savedReplies < replies)
                        SavedReplyCount.SafeAdd(hash, replies);
            }
        }
Пример #13
0
        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;
        }
Пример #14
0
        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);
            }
        }
Пример #15
0
 void Search_Found(DhtSearch search, DhtAddress source, byte[] data)
 {
     Store_Local(new DataReq(source, search.TargetID, Service, DataType, data));
 }
Пример #16
0
        void UpdateList(DhtSearch search)
        {
            if (search.FoundValues.Count > 0)
            {
                LabelResults.Text = search.FoundValues.Count.ToString() + " Values Found, ";
            }

            if (search.FoundContact != null)
            {
                LabelResults.Text = "Found Contact(" + search.FoundContact.ClientID.ToString() + ") ";

                if (search.FoundProxy)
                    LabelResults.Text += "is a proxy";
            }

            // Dht
            // client

            foreach (DhtLookup lookup in search.LookupList)
                ListResults.Items.Add(new ListViewItem(new string[]
                    {
                        Utilities.IDtoBin(lookup.Contact.UserID),
                        lookup.Contact.ClientID.ToString()
                    }));
        }
Пример #17
0
        void Search_Found(DhtSearch search, DhtAddress source, byte[] data)
        {
            G2Header root = new G2Header(data);
            if (!G2Protocol.ReadPacket(root))
                return;

            UpdateInfo info = UpdateInfo.Decode(root); // verifies signature
            if (info == null)
                return;

            if (Core.Context.SignedUpdate == null || Core.Context.SignedUpdate.SequentialVersion < info.SequentialVersion)
            {
                Core.Context.SignedUpdate = info;
                LookupConfig.WriteUpdateInfo(Core);
            }

            // version less than what we have
            else if (Core.Context.SignedUpdate.SequentialVersion > info.SequentialVersion)
                return;

            // version remote has already loaded
            if (Core.Context.SignedUpdate.Loaded)
                return;

            // same sources will be hit as file download search progresses
            StartDownload(search.TargetID);
        }