Exemple #1
0
        public void TrySend(DhtNetwork network)
        {
            // check if stuff in queue
            if (Packets.Count == 0 ||
                Addresses.Count == 0 ||
                network.Core.TimeNow < NextTry)
            {
                return;
            }

            Attempts++;
            if (Attempts >= Addresses.Count * 2) // every address known tried twice
            {
                Attempts = 0;
                Packets.RemoveFirst();
                return;
            }

            RudpAddress target = Addresses.First.Value;

            Addresses.RemoveFirst();
            Addresses.AddLast(target);

            NextTry = network.Core.TimeNow.AddSeconds(3);

            Tuple <uint, RudpPacket> tuple = Packets.First.Value;
            RudpPacket packet = tuple.Param2;

            packet.Ident = target.Ident;

            int sentBytes = SendtoAddress(network, target, packet);

            network.Core.ServiceBandwidth[tuple.Param1].OutPerSec += sentBytes;
        }
Exemple #2
0
        public static int SendtoAddress(DhtNetwork network, RudpAddress target, RudpPacket packet)
        {
            Debug.Assert(packet.Payload != null || packet.PacketType == RudpPacketType.LightAck);

            int sentBytes = 0;

            // same code used in rudpSocket
            if (network.Core.Firewall != FirewallType.Blocked && target.LocalProxy == null)
            {
                sentBytes = network.SendPacket(target.Address, packet);
            }

            else if (target.Address.TunnelClient != null)
            {
                sentBytes = network.SendTunnelPacket(target.Address, packet);
            }

            else
            {
                packet.ToAddress = target.Address;

                TcpConnect proxy = network.TcpControl.GetProxy(target.LocalProxy);

                if (proxy != null)
                {
                    sentBytes = proxy.SendPacket(packet);
                }
                else
                {
                    sentBytes = network.TcpControl.SendRandomProxy(packet);
                }
            }

            return(sentBytes);
        }
Exemple #3
0
        void ReceiveAck(G2ReceivedPacket raw, LightClient client, RudpPacket packet)
        {
            // remove acked packet
            foreach (Tuple <uint, RudpPacket> tuple in client.Packets)
            {
                if (tuple.Param2.PeerID == packet.PeerID)
                {
                    client.Packets.Remove(tuple);
                    client.Attempts = 0;
                    break;
                }
            }

            // read ack ident and move to top
            foreach (RudpAddress address in client.Addresses)
            {
                if (address.Ident == packet.Ident)
                {
                    client.Addresses.Remove(address);
                    client.Addresses.AddFirst(address);
                    address.LastAck = Core.TimeNow;
                    break;
                }
            }

            client.NextTry = Core.TimeNow;

            // receieved ack, try to send next packet immediately
            client.TrySend(Network);
        }
Exemple #4
0
        void SendAck(RudpPacket packet)
        {
            RudpPacket ack = new RudpPacket();

            ack.TargetID     = Session.UserID;
            ack.TargetClient = Session.ClientID;
            ack.PeerID       = RemotePeerID;
            ack.PacketType   = RudpPacketType.Ack;
            ack.Sequence     = packet.Sequence;
            ack.Payload      = RudpAck.Encode(HighestSeqRecvd, (byte)(MAX_WINDOW_SIZE - RecvPacketMap.Count));
            ack.Ident        = packet.Ident;

            //Session.Log("Ack Sent, Seq " + ack.Sequence.ToString() + ", ID " + ack.PeerID.ToString() + ", highest " + HighestSeqRecvd.ToString());

            if (!AckMap.Contains(ack.Sequence))
            {
                AckMap[ack.Sequence] = true;
                AckOrder.Enqueue(ack.Sequence);
            }

            while (AckMap.Count > MAX_WINDOW_SIZE * 2)
            {
                AckMap.Remove(AckOrder.Dequeue());
            }

            SendTracked(new TrackPacket(ack));
        }
Exemple #5
0
        public void SendReliable(DhtClient client, uint service, int type, G2Packet packet, bool expedite)
        {
            if (!Clients.ContainsKey(client.RoutingID))
            {
                return;
            }

            RudpPacket comm = CreateRudpPacket(client, service, type, packet, true);

            LightClient target = Clients[client.RoutingID];

            if (expedite)
            {
                target.NextTry = Core.TimeNow;
                target.Packets.AddFirst(new Tuple <uint, RudpPacket>(service, comm));
                target.TrySend(Network);
                return;
            }

            Active[client.RoutingID] = target;

            target.Packets.AddLast(new Tuple <uint, RudpPacket>(service, comm));
            while (target.Packets.Count > 30)
            {
                //crit - log to console? Debug.Assert(false);
                target.Packets.RemoveFirst();
            }

            target.TrySend(Network);
        }
Exemple #6
0
        void ReceivePong(RudpPacket pong)
        {
            if (pong.Payload != null)
            {
                uint ident = BitConverter.ToUInt32(pong.Payload, 0);

                SetPrimaryAddress(ident);
            }
        }
Exemple #7
0
        void ReceivePing(RudpPacket ping)
        {
            RudpPacket pong = new RudpPacket();

            pong.TargetID     = Session.UserID;
            pong.TargetClient = Session.ClientID;
            pong.PeerID       = RemotePeerID;
            pong.PacketType   = RudpPacketType.Pong;
            pong.Sequence     = 0;
            pong.Payload      = ping.Payload;

            SendTracked(new TrackPacket(pong));
        }
Exemple #8
0
        void ReceiveFin(RudpPacket packet)
        {
            //Session.Log("Fin Recv, Seq " + packet.Sequence.ToString() + ", ID " + packet.PeerID.ToString() + ", Reason " + packet.Payload[0].ToString());

            FinReceived = true;

            SendAck(packet);

            if (!FinSent)
            {
                RudpClose(CloseReason.YOU_CLOSED);
            }
        }
Exemple #9
0
        /*public void SendUnreliable(RudpAddress address, uint service, int type, G2Packet packet)
         * {
         *  // insecure, rudp provides this same method which is more secure, if a rudp connection is already established
         *
         *  RudpPacket wrap = CreateRudpPacket(address.Address, service, type, packet, false);
         *
         *  int sentBytes = LightClient.SendtoAddress(Core.Network, address, wrap);
         *
         *  Core.ServiceBandwidth[service].OutPerSec += sentBytes;
         * }*/

        public void ReceivePacket(G2ReceivedPacket raw, RudpPacket packet)
        {
            DhtClient client = new DhtClient(packet.SenderID, packet.SenderClient);

            if (!Clients.ContainsKey(client.RoutingID))
            {
                Clients[client.RoutingID] = new LightClient(client);
            }

            LightClient light = Clients[client.RoutingID];

            light.LastSeen = Core.TimeNow;

            // either direct, or node's proxy
            light.AddAddress(Core, new RudpAddress(raw.Source), true);

            if (raw.ReceivedTcp) // add this second so sending ack through tcp proxy is perferred
            {
                light.AddAddress(Core, new RudpAddress(raw.Source, raw.Tcp), true);
            }


            if (packet.PacketType == RudpPacketType.LightAck)
            {
                ReceiveAck(raw, light, packet);
            }

            else if (packet.PacketType == RudpPacketType.Light)
            {
                RudpLight info = new RudpLight(packet.Payload);

                if (Core.ServiceBandwidth.ContainsKey(info.Service))
                {
                    Core.ServiceBandwidth[info.Service].InPerSec += raw.Root.Data.Length;
                }

                if (Data.Contains(info.Service, info.Type))
                {
                    Data[info.Service, info.Type].Invoke(client, info.Data);
                }

                if (packet.Sequence == 1) // reliable packet
                {
                    SendAck(light, packet, info.Service);
                }
            }
        }
Exemple #10
0
        public void SendPacket(RudpPacket packet, RudpAddress target)
        {
            Debug.Assert(packet.Payload != null);

            // sending syn  to (tracked target) through (address target) udp / tcp

            /*string log = "Sending " + tracked.Packet.PacketType.ToString();
             * if (tracked.Packet.Ident != 0) log  += ", ID " + tracked.Packet.Ident.ToString();
             * log +=  " to " + Utilities.IDtoBin(tracked.Packet.TargetID).Substring(0, 10);
             * log += " target address " + target.Address.ToString();*/

            int sentBytes = 0;

            // same code used in lightComm
            if (Core.Firewall != FirewallType.Blocked && target.LocalProxy == null)
            {
                sentBytes = Network.SendPacket(target.Address, packet);
            }

            else if (target.Address.TunnelClient != null)
            {
                sentBytes = Network.SendTunnelPacket(target.Address, packet);
            }

            else
            {
                packet.ToAddress = target.Address;

                TcpConnect proxy = Network.TcpControl.GetProxy(target.LocalProxy);

                if (proxy != null)
                {
                    sentBytes = proxy.SendPacket(packet);
                }
                else
                {
                    sentBytes = Network.TcpControl.SendRandomProxy(packet);
                }

                //log += " proxied by local tcp";
            }

            Bandwidth.OutPerSec += sentBytes;

            //Session.Log(log);
        }
Exemple #11
0
        void SendSyn()
        {
            RudpPacket syn = new RudpPacket();

            lock (SendSection) // ensure queued in right order with right current seq
            {
                syn.TargetID     = Session.UserID;
                syn.TargetClient = Session.ClientID;
                syn.PeerID       = 0;
                syn.PacketType   = RudpPacketType.Syn;
                syn.Sequence     = CurrentSeq++;
                syn.Payload      = RudpSyn.Encode(1, Network.Local.UserID, Network.Local.ClientID, PeerID);

                SendPacketMap.Enqueue(new TrackPacket(syn));
            }

            ManageSendWindow();
        }
Exemple #12
0
        RudpPacket CreateRudpPacket(DhtClient client, uint service, int type, G2Packet packet, bool reliable)
        {
            RudpPacket comm = new RudpPacket();

            comm.SenderID     = Network.Local.UserID;
            comm.SenderClient = Network.Local.ClientID;
            comm.TargetID     = client.UserID;
            comm.TargetClient = client.ClientID;
            comm.PacketType   = RudpPacketType.Light;
            comm.Payload      = RudpLight.Encode(service, type, packet.Encode(Network.Protocol));

            if (reliable)
            {
                comm.PeerID   = (ushort)Core.RndGen.Next(ushort.MaxValue); // used to ack
                comm.Sequence = 1;
            }

            return(comm);
        }
Exemple #13
0
        void SendPing(RudpAddress address)
        {
            RudpPacket ping = new RudpPacket();

            ping.TargetID     = Session.UserID;
            ping.TargetClient = Session.ClientID;
            ping.PeerID       = RemotePeerID;
            ping.PacketType   = RudpPacketType.Ping;
            ping.Sequence     = 0;
            ping.Payload      = BitConverter.GetBytes(address.Ident);

            //Session.Log("Keep Alive Sent, Seq " + alive.Sequence.ToString() + ", ID " + alive.PeerID.ToString());
            TrackPacket tracked = new TrackPacket(ping);

            tracked.Target        = address;
            tracked.SpecialTarget = true;

            SendTracked(tracked);
        }
Exemple #14
0
        void SendAck(LightClient light, RudpPacket packet, uint service)
        {
            RudpPacket comm = new RudpPacket();

            comm.SenderID     = Network.Local.UserID;
            comm.SenderClient = Network.Local.ClientID;
            comm.TargetID     = light.Client.UserID;
            comm.TargetClient = light.Client.ClientID;
            comm.PacketType   = RudpPacketType.LightAck;
            comm.PeerID       = packet.PeerID; // so remote knows which packet we're acking
            comm.Ident        = packet.Ident;  // so remote knows which address is good
            comm.Sequence     = 0;

            // send ack to first address, addresses moved to front on receive packet
            int sentBytes = LightClient.SendtoAddress(Network, light.Addresses.First.Value, comm);

            Core.ServiceBandwidth[service].OutPerSec += sentBytes;

            // on resend packet from remote we receive it through different proxy, so that address
            // is moved to the front of the list automatically and our ack takes that direction
        }
Exemple #15
0
        void ReceiveSyn(RudpPacket packet)
        {
            RudpSyn syn = new RudpSyn(packet.Payload);

            if (RemotePeerID == 0)
            {
                RemotePeerID = syn.ConnID;
            }

            //Session.Log("Syn Recv, Seq " + packet.Sequence.ToString() + ", ID " + syn.ConnID.ToString());

            SendAck(packet);             // send ack here also because peerID now set

            SynAckSent = true;

            if (SynAckSent && SynAckReceieved)
            {
                Session.Log("Connected (recv syn)");
                ChangeState(RudpState.Connected);
                SetConnected();
            }
        }
Exemple #16
0
        void StartFin(CloseReason reason)
        {
            FinPacket = new RudpPacket();

            lock (SendSection) // ensure queued in right order with right current seq
            {
                FinPacket.TargetID     = Session.UserID;
                FinPacket.TargetClient = Session.ClientID;
                FinPacket.PeerID       = RemotePeerID;
                FinPacket.PacketType   = RudpPacketType.Fin;
                FinPacket.Payload      = new byte[1] {
                    (byte)reason
                };
            }

            ChangeState(RudpState.Finishing);
            FinTimeout = 15;

            TrySendFin();

            //Session.Log("Fin Sent, Seq " + fin.Sequence.ToString() + ", ID " + fin.PeerID.ToString() + ", Reason " + reason.ToString());

            ManageSendWindow();             // immediately try to send the fin
        }
Exemple #17
0
        public void SendUnreliable(uint service, uint type, G2Packet packet)
        {
            // fast, secure, out-of-band method of sending data
            // useful for things like VOIP during a file transfer with host
            // data has got to go out asap, no matter what

            // check rudp socket is connected
            if (Status != SessionStatus.Active)
            {
                return;
            }

            // add to special rudp packet
            RudpPacket rudp = new RudpPacket();

            rudp.SenderID     = Network.Local.UserID;
            rudp.SenderClient = Network.Local.ClientID;
            rudp.TargetID     = UserID;
            rudp.TargetClient = ClientID;
            rudp.PeerID       = Comm.RemotePeerID;
            rudp.PacketType   = RudpPacketType.Unreliable;

            CommData data = new CommData(service, type, packet.Encode(Network.Protocol));

            rudp.Payload = Utilities.EncryptBytes(data.Encode(Network.Protocol), OutboundEnc.Key);

            // send
            Comm.SendPacket(rudp, Comm.PrimaryAddress);

            // stats
            Core.ServiceBandwidth[service].OutPerSec += data.Data.Length;

            PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Rudp, DirectionType.Out, Comm.PrimaryAddress.Address, rudp.Payload);

            Core.Network.LogPacket(logEntry);
        }
Exemple #18
0
        public ListViewItem PackettoItem(PacketLogEntry logEntry)
        {
            // hash, protocol, direction, address, type, size
            string hash     = Utilities.BytestoHex(sha.ComputeHash(logEntry.Data), 0, 2, false);
            string protocol = logEntry.Protocol.ToString();

            // Network - Search / Search Req / Store ... - Component

            // Comm - Data / Ack / Syn

            // Rudp - Type - Component

            string name = "?";

            G2Header root = new G2Header(logEntry.Data);

            if (G2Protocol.ReadPacket(root))
            {
                if (logEntry.Protocol == TransportProtocol.Rudp)
                {
                    name = TransportProtocol.Rudp.ToString() + " - ";

                    name += GetVariableName(typeof(CommPacket), root.Name);

                    if (root.Name == CommPacket.Data)
                    {
                        CommData data = CommData.Decode(root);

                        name += " - " + Network.Core.GetServiceName(data.Service);
                    }
                }
                else
                {
                    name = GetVariableName(typeof(RootPacket), root.Name) + " - ";

                    if (root.Name == RootPacket.Comm)
                    {
                        RudpPacket commPacket = RudpPacket.Decode(root);

                        name += GetVariableName(typeof(RudpPacketType), commPacket.PacketType);
                    }

                    if (root.Name == RootPacket.Network)
                    {
                        NetworkPacket netPacket = NetworkPacket.Decode(root);

                        G2Header internalRoot = new G2Header(netPacket.InternalData);
                        if (G2Protocol.ReadPacket(internalRoot))
                        {
                            name += GetVariableName(typeof(NetworkPacket), internalRoot.Name);

                            uint             id   = 0;
                            G2ReceivedPacket wrap = new G2ReceivedPacket();
                            wrap.Root = internalRoot;

                            // search request / search acks / stores have component types
                            if (internalRoot.Name == NetworkPacket.SearchRequest)
                            {
                                SearchReq req = SearchReq.Decode(wrap);
                                id = req.Service;
                            }

                            if (internalRoot.Name == NetworkPacket.SearchAck)
                            {
                                SearchAck ack = SearchAck.Decode(wrap);
                                id = ack.Service;
                            }

                            if (internalRoot.Name == NetworkPacket.StoreRequest)
                            {
                                StoreReq store = StoreReq.Decode(wrap);
                                id = store.Service;
                            }

                            if (id != 0)
                            {
                                name += " - " + Network.Core.GetServiceName(id); // GetVariableName(typeof(ServiceID), id);
                            }
                        }
                    }
                }
            }

            string time = logEntry.Time.ToString("HH:mm:ss:ff");

            string address = (logEntry.Address == null) ? "Broadcast" : logEntry.Address.ToString();

            return(new PacketListViewItem(logEntry, new string[] { time, protocol, address, name, logEntry.Data.Length.ToString(), hash }, logEntry.Direction == DirectionType.In));
        }
Exemple #19
0
        public void ReceivePacket(G2ReceivedPacket packet)
        {
            // Network packet
            if (packet.Root.Name == RootPacket.Network)
            {
                NetworkPacket netPacket = NetworkPacket.Decode(packet.Root);

                G2ReceivedPacket embedded = new G2ReceivedPacket();
                embedded.Tcp             = packet.Tcp;
                embedded.Source          = packet.Source;
                embedded.Source.UserID   = netPacket.SourceID;
                embedded.Source.ClientID = netPacket.ClientID;
                embedded.Root            = new G2Header(netPacket.InternalData);

                // from - received from proxy server
                if (netPacket.FromAddress != null)
                {
                    if (packet.ReceivedUdp)
                    {
                        throw new Exception("From tag set on packet received udp");
                    }
                    if (packet.Tcp.Proxy != ProxyType.Server)
                    {
                        throw new Exception("From tag (" + netPacket.FromAddress.ToString() + ") set on packet not received from server (" + packet.Tcp.ToString() + ")");
                    }

                    embedded.Source = new DhtContact(netPacket.FromAddress);
                }

                // to - received from proxied node, and not for us
                if (netPacket.ToAddress != null &&
                    !(netPacket.ToAddress.UserID == Local.UserID && netPacket.ToAddress.ClientID == Local.ClientID))
                {
                    if (packet.ReceivedUdp)
                    {
                        throw new Exception("To tag set on packet received udp");
                    }
                    if (packet.Tcp.Proxy == ProxyType.Server || packet.Tcp.Proxy == ProxyType.Unset)
                    {
                        throw new Exception("To tag set on packet received from server");
                    }

                    DhtAddress address = netPacket.ToAddress;
                    netPacket.ToAddress = null;

                    TcpConnect direct = TcpControl.GetProxy(address);

                    if (direct != null)
                    {
                        direct.SendPacket(netPacket);
                    }
                    else
                    {
                        UdpControl.SendTo(address, netPacket);
                    }

                    return;
                }

                // process
                if (G2Protocol.ReadPacket(embedded.Root))
                {
                    ReceiveNetworkPacket(embedded);
                }
            }

            // Tunnel Packet
            else if (packet.Root.Name == RootPacket.Tunnel)
            {
                // can only tunnel over lookup network
                if (!IsLookup)
                {
                    return;
                }

                PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.In, packet.Source, packet.Root.Data);
                LogPacket(logEntry);

                TunnelPacket tunnel = TunnelPacket.Decode(packet.Root);

                // handle locally
                if (tunnel.Target.Equals(Local))
                {
                    Core.Context.Cores.LockReading(delegate()
                    {
                        foreach (OpCore core in Core.Context.Cores)
                        {
                            if (core.TunnelID == tunnel.Target.TunnelID)
                            {
                                core.Network.ReceiveTunnelPacket(packet, tunnel);
                            }
                        }
                    });
                }
                else if (tunnel.TargetServer != null)
                {
                    TcpConnect direct = TcpControl.GetProxy(tunnel.Target);

                    // if directly connected add from and forwared
                    if (direct != null)
                    {
                        direct.SendPacket(tunnel);
                    }

                    // only forward udp if received over tcp from a proxied host
                    else if (tunnel.TargetServer != null && packet.ReceivedTcp && packet.Tcp.Proxy != ProxyType.Server)
                    {
                        UdpControl.SendTo(tunnel.TargetServer, tunnel);
                    }
                }
            }

            // Communication Packet
            else if (packet.Root.Name == RootPacket.Comm)
            {
                RudpPacket commPacket = RudpPacket.Decode(packet);

                // received direct
                packet.Source.UserID   = commPacket.SenderID;
                packet.Source.ClientID = commPacket.SenderClient;

                // remote node is proxied
                if (commPacket.RemoteProxy != null)
                {
                    packet.Source = new DhtContact(commPacket.RemoteProxy);
                }

                // For local host
                if (commPacket.TargetID == Local.UserID && commPacket.TargetClient == Local.ClientID)
                {
                    ReceiveCommPacket(packet, commPacket);
                    return;
                }

                // Also Forward to appropriate node
                TcpConnect socket = TcpControl.GetProxy(commPacket.TargetID, commPacket.TargetClient);

                if (socket != null)
                {
                    // forward to proxied node - strip TO flag, add from address
                    commPacket.ToAddress   = null;
                    commPacket.RemoteProxy = packet.Source; // if remote proxy is null, then we are setting this to the packet's original source

                    socket.SendPacket(commPacket);
                    return;
                }

                // received from a proxied node, forward udp
                if (packet.ReceivedTcp && commPacket.ToAddress != null)
                {
                    DhtAddress target = commPacket.ToAddress;

                    commPacket.ToAddress   = null; // strip TO flag
                    commPacket.RemoteProxy = new DhtAddress(Core.LocalIP, GetLocalSource());

                    UdpControl.SendTo(target, commPacket);
                }
            }
        }
Exemple #20
0
        void ManageRecvWindow()
        {
            bool dataReceived = false;

            lock (RecvPacketMap)
            {
                ArrayList removeList = new ArrayList();

                foreach (byte seq in RecvPacketMap.Keys)
                {
                    RudpPacket packet = RecvPacketMap[seq];

                    // deal with reading in order at 0xFF to zero boundry
                    if (NextSeq > 0xFF - 25 && packet.Sequence < 25)
                    {
                        continue;
                    }

                    if (packet.Sequence != NextSeq)
                    {
                        break;
                    }

                    if (packet.PacketType == RudpPacketType.Syn)
                    {
                        ReceiveSyn(packet);
                    }

                    else if (packet.PacketType == RudpPacketType.Data)
                    {
                        // if local is closing connection, dump pending data so we can get to the fin packet and process it
                        if (State != RudpState.Finishing)
                        {
                            dataReceived = true;
                            break;
                        }
                    }

                    else if (packet.PacketType == RudpPacketType.Fin)
                    {
                        ReceiveFin(packet);
                    }

                    HighestSeqRecvd = packet.Sequence;

                    removeList.Add(packet.Sequence);

                    NextSeq++;
                }


                foreach (byte seq in removeList)
                {
                    RecvPacketMap.Remove(seq);
                }
            }

            // if data waiting to be read
            // dont let data receive if still connecting (getting ahead of ourselves) need successful ack return path before we recv data
            if (State == RudpState.Connected && (RecvBuffLength > 0 || dataReceived))
            {
                Session.OnReceive();
            }
        }
Exemple #21
0
        void ManageSendWindow()
        {
            ArrayList retransmit = new ArrayList();

            int rtt         = AvgLatency.GetAverage();
            int outstanding = 0;

            lock (SendSection)
            {
                // iter through send window
                foreach (TrackPacket packet in SendPacketMap)
                {
                    if (packet.Acked)
                    {
                        continue;
                    }

                    else if (packet.TimeSent == 0)
                    {
                        retransmit.Add(packet);
                    }

                    // connecting so must be a syn packet
                    else if (State == RudpState.Connecting)
                    {
                        if (packet.TimeEllapsed(Core) > 1000 * 2) // dont combine with above cause then next else if would always run
                        {
                            retransmit.Add(packet);
                        }
                    }

                    // send packets that havent been sent yet, and ones that need to be retransmitted
                    else if (packet.TimeEllapsed(Core) > rtt * 2)
                    {
                        retransmit.Add(packet);
                    }

                    // mark as outstanding
                    else
                    {
                        outstanding++;
                    }
                }
            }

            // re-transmit packets
            foreach (TrackPacket track in retransmit)
            {
                if (outstanding < SendWindowSize)
                {
                    //Session.Log("Re-Send ID " + track.Packet.PeerID.ToString() +
                    //            ", Type " + track.Packet.Type.ToString() +
                    //            ", Seq " + track.Packet.Sequence.ToString() + ", Retries " + track.Retries.ToString() +
                    //            ", Passed " + track.TimeEllapsed().ToString() + " ms");

                    track.Retries++;
                    ReTransmits++;

                    SendTracked(track);

                    outstanding++;
                }
                else
                {
                    break;
                }
            }


            lock (SendSection)
            {
                // send number of packets so that outstanding equals window size
                while (outstanding < SendWindowSize && SendBuffLength > 0 && SendPacketMap.Count < MAX_WINDOW_SIZE)
                {
                    int buffLen = (SendBuffLength > CHUNK_SIZE) ? CHUNK_SIZE : SendBuffLength;

                    RudpPacket data = new RudpPacket();
                    data.TargetID     = Session.UserID;
                    data.TargetClient = Session.ClientID;
                    data.PeerID       = RemotePeerID;
                    data.PacketType   = RudpPacketType.Data;
                    data.Sequence     = CurrentSeq++;
                    data.Payload      = Utilities.ExtractBytes(SendBuff, 0, buffLen);


                    // move next data on deck for next send
                    if (SendBuffLength > buffLen)
                    {
                        Buffer.BlockCopy(SendBuff, buffLen, SendBuff, 0, SendBuffLength - buffLen);
                    }
                    SendBuffLength -= buffLen;

                    TrackPacket track = new TrackPacket(data);
                    SendPacketMap.Enqueue(track);

                    //Session.Log("Data Sent, Seq " + data.Sequence.ToString() + ", ID " + data.PeerID.ToString() + ", Size " + buffLen.ToString());

                    SendTracked(track);

                    outstanding++;
                }
            }

            // if we can take more data call onsend
            if (SendBuffLength == 0 && RudpSendBlock)
            {
                //Session.Log("OnSend Called");
                RudpSendBlock = false;
                Session.OnSend();
            }
        }
Exemple #22
0
        public void ReceiveCommPacket(G2ReceivedPacket raw, RudpPacket packet)
        {
            try
            {
                if (packet.PacketType == RudpPacketType.Light ||
                    packet.PacketType == RudpPacketType.LightAck)
                {
                    LightComm.ReceivePacket(raw, packet);
                    return;
                }

                // if a socket already set up
                lock (RudpControl.SocketMap)
                    if (RudpControl.SocketMap.ContainsKey(packet.PeerID))
                    {
                        RudpControl.SocketMap[packet.PeerID].RudpReceive(raw, packet, IsLookup);
                        return;
                    }

                // if starting new session
                if (packet.PacketType != RudpPacketType.Syn)
                {
                    return;
                }

                RudpSyn syn = new RudpSyn(packet.Payload);

                // prevent connection from self
                if (syn.SenderID == Local.UserID && syn.ClientID == Local.ClientID)
                {
                    return;
                }


                // find connecting session with same or unknown client id
                ulong id = syn.SenderID ^ syn.ClientID;

                if (RudpControl.SessionMap.ContainsKey(id))
                {
                    RudpSession session = RudpControl.SessionMap[id];

                    // if session id zero or matches forward
                    if ((session.Comm.State == RudpState.Connecting && session.Comm.RemotePeerID == 0) ||
                        (session.Comm.State != RudpState.Closed && session.Comm.RemotePeerID == syn.ConnID)) // duplicate syn
                    {
                        session.Comm.RudpReceive(raw, packet, IsLookup);
                        return;
                    }

                    else if (session.Comm.State == RudpState.Finishing)
                    {
                        RudpControl.RemoveSession(session);
                        // remove session, allow new one to be created
                    }
                    else
                    {
                        return;
                    }
                }

                // if clientid not in session, create new session
                RudpSession newSession = new RudpSession(RudpControl, syn.SenderID, syn.ClientID, true);

                RudpControl.SessionMap[id] = newSession;

                // send ack before sending our own syn (connect)
                // ack tells remote which address is good so that our syn's ack comes back quickly
                newSession.Comm.RudpReceive(raw, packet, IsLookup);

                newSession.Connect();


                UpdateLog("RUDP", "Inbound session accepted to ClientID " + syn.ClientID.ToString());
            }
            catch (Exception ex)
            {
                UpdateLog("Exception", "DhtNetwork::ReceiveCommPacket: " + ex.Message);
            }
        }
Exemple #23
0
 public TrackPacket(RudpPacket packet)
 {
     Packet = packet;
 }
Exemple #24
0
        public int Receive(byte[] buff, int buffOffset, int buffLen)
        {
            if (RecvBuffLength > buffLen)
            {
                return(FinishReceive(buff, buffOffset, buffLen));
            }

            lock (RecvPacketMap)
            {
                ArrayList removeList = new ArrayList();

                // copy data from packets
                // while next element of map equals next in sequence
                foreach (byte seq in RecvPacketMap.Keys) // read keys because they are sorted
                {
                    RudpPacket packet = RecvPacketMap[seq];

                    // deal with reading in order at 0xFF to zero boundry
                    if (NextSeq > 0xFF - 25 && packet.Sequence < 25)
                    {
                        continue;
                    }

                    if (packet.Sequence != NextSeq)
                    {
                        break;
                    }

                    if (packet.PacketType == RudpPacketType.Data)
                    {
                        int dataSize = packet.Payload.Length;

                        if (dataSize > MAX_CHUNK_SIZE)
                        {
                            Session.Log("Too Large Packet Received Size " + packet.Payload.Length + ", Type Data");
                            RudpClose(CloseReason.LARGE_PACKET);
                            return(-1);
                        }

                        // copy data
                        packet.Payload.CopyTo(RecvBuff, RecvBuffLength);
                        RecvBuffLength += packet.Payload.Length;

                        //Session.Log("Data Recv, Seq " + packet.Sequence.ToString() + ", ID " + packet.PeerID.ToString());
                    }
                    else
                    {
                        break;
                    }

                    HighestSeqRecvd = packet.Sequence;

                    removeList.Add(packet.Sequence);

                    NextSeq++;

                    if (RecvBuffLength > buffLen)
                    {
                        break;
                    }
                }

                foreach (byte seq in removeList)
                {
                    RecvPacketMap.Remove(seq);
                }
            }

            //Log("Reliable Receive " + NumtoStr(copysize) + ", " + NumtoStr(m_RecvBuffLength) + " left");

            return(FinishReceive(buff, buffOffset, buffLen));
        }
Exemple #25
0
        public void RudpReceive(G2ReceivedPacket raw, RudpPacket packet, bool global)
        {
            // check if packet meant for another socket
            if (packet.PeerID != 0 && packet.PeerID != PeerID)
            {
                return;
            }

            // check for errors
            string error = null;

            if (packet.Sequence > HighestSeqRecvd && State == RudpState.Closed)            // accept only packets that came before the fin
            {
                error = "Packet Received while in Close State ID " + packet.PeerID.ToString() + ", Type " + packet.PacketType.ToString();
            }

            else if (packet.Payload.Length > 4096)
            {
                error = "Too Large Packet Received Size " + packet.Payload.Length.ToString() + ", Type " + packet.PacketType.ToString();
                RudpClose(CloseReason.LARGE_PACKET);
            }

            if (error != null)
            {
                Session.Log(error);
                return;
            }

            Bandwidth.InPerSec += raw.Root.Data.Length;

            // add proxied and direct addresses
            // proxied first because that packet has highest chance of being received, no need for retry
            // also allows quick udp hole punching
            if (raw.ReceivedTcp)
            {
                AddAddress(new RudpAddress(raw.Source, raw.Tcp));
            }

            AddAddress(new RudpAddress(raw.Source));   // either direct node, or node's proxy

            // received syn, ident 5, from 1001 over tcp

            /*string log = "Received " + packet.PacketType.ToString();
             * if (packet.Ident != 0) log += " ID:" + packet.Ident.ToString();
             * log += " from " + raw.Source.ToString();
             *
             * if (raw.Tcp != null)
             *  log += " tcp";
             * else
             *  log += " udp";
             * Session.Log(log);*/

            if (packet.PacketType == RudpPacketType.Unreliable)
            {
                Session.UnreliableReceive(packet.Payload);
                return;
            }

            // try to clear up bufffer, helps if full, better than calling this on each return statement
            ManageRecvWindow();

            // if ACK, PING, or PONG
            if (packet.PacketType == RudpPacketType.Ack || packet.PacketType == RudpPacketType.Ping || packet.PacketType == RudpPacketType.Pong)
            {
                if (packet.PacketType == RudpPacketType.Ack)
                {
                    ReceiveAck(packet);
                }

                if (packet.PacketType == RudpPacketType.Ping)
                {
                    ReceivePing(packet);
                }

                if (packet.PacketType == RudpPacketType.Pong)
                {
                    ReceivePong(packet);
                }

                return;
            }

            // if SYN, DATA or FIN packet

            // stop acking so remote host catches up
            if (packet.Sequence > HighestSeqRecvd + MAX_WINDOW_SIZE || RecvPacketMap.Count > MAX_WINDOW_SIZE)
            {
                //Session.Log("Error Packet Overflow");
                return;
            }

            // Send Ack - cant combine if statements doesnt work
            if (AckMap.Contains(packet.Sequence))
            {
                //Session.Log("Error Packet Seq " + packet.Sequence.ToString() + " Already Received");
                SendAck(packet);
                return;
            }

            // insert into recv map
            lock (RecvPacketMap)
            {
                RecvPacketMap[packet.Sequence] = packet;
            }

            ManageRecvWindow();

            // ack down here so highest received is iterated, syns send own acks
            if (packet.PacketType != RudpPacketType.Syn)
            {
                SendAck(packet);
            }
        }
Exemple #26
0
        void ReceiveAck(RudpPacket packet)
        {
            int latency = 0;
            int retries = -1;

            // find original packet that was sent
            TrackPacket sent = null;

            lock (SendSection)
            {
                foreach (TrackPacket tracked in SendPacketMap)
                {
                    if (tracked.Packet.Sequence == packet.Sequence)
                    {
                        sent = tracked;
                        break;
                    }
                }
            }

            // mark packet as acked
            if (sent != null)
            {
                sent.Target.LastAck = Core.TimeNow;

                // connect handshake
                if (State == RudpState.Connecting && sent.Packet.PacketType == RudpPacketType.Syn)
                {
                    SynAckReceieved = true;

                    SetPrimaryAddress(packet.Ident);

                    if (SynAckSent && SynAckReceieved)
                    {
                        Session.Log("Connected (recv ack)");
                        ChangeState(RudpState.Connected);
                        SetConnected();

                        // if data packets received before final connection ack, process them now
                        ManageRecvWindow();
                    }
                }

                if (!sent.Acked)
                {
                    InOrderAcks++;

                    if (sent.Retries == 0)
                    {
                        latency = (int)sent.TimeEllapsed(Core);
                        latency = latency < 5 ? 5 : latency;
                        AvgLatency.Input(latency);
                        AvgLatency.Next();
                    }
                }

                retries = sent.Retries;

                sent.Acked = true;
            }

            RudpAck ack = new RudpAck(packet.Payload);

            //Session.Log("Ack Recv, Seq " + packet.Sequence.ToString() + ", ID " + packet.PeerID.ToString() + ", highest " + ack.Start.ToString() + ", retries " + retries.ToString() + ", latency " + latency.ToString());

            lock (SendSection)
            {
                // ack possibly un-acked packets
                foreach (TrackPacket tracked in SendPacketMap)
                {
                    // ack if start past the zero boundry with sequences behind
                    if (tracked.Packet.Sequence > 0xFF - 25 && ack.Start < 25)
                    {
                        tracked.Acked = true;
                    }

                    // break start before boundry and sequences ahead are not recvd/acked yet
                    if (ack.Start > 0xFF - 25 && tracked.Packet.Sequence < 25)
                    {
                        break;
                    }

                    // normal acking procedure
                    else if (ack.Start >= tracked.Packet.Sequence)
                    {
                        tracked.Acked = true;
                    }

                    else
                    {
                        break;
                    }
                }

                // remove acked, only remove packets from front
                while (SendPacketMap.Count > 0 && SendPacketMap.Peek().Acked)
                {
                    // calculate receive speed of remote host by rate they ack
                    AvgBytesSent.Input(SendPacketMap.Peek().Packet.Payload.Length);

                    SendPacketMap.Dequeue();
                    PacketsCompleted++;
                }
            }

            // increase window if packets removed from beginning of buffer
            //if(packetsRemoved && SendWindowSize < 25)
            //  SendWindowSize++;


            ManageSendWindow();
        }