Example #1
0
        public void SendTracked(TrackPacket tracked)
        {
            if (AddressMap.Count == 0)
            {
                return;
            }

            RudpAddress target = tracked.SpecialTarget ? tracked.Target : PrimaryAddress;

            LastSend                    = Core.TimeNow;
            tracked.TimeSent            = Core.TimeNow.Ticks;
            tracked.Target              = target;
            tracked.Packet.SenderID     = Network.Local.UserID;
            tracked.Packet.SenderClient = Network.Local.ClientID;


            if (tracked.Packet.PacketType != RudpPacketType.Syn)
            {
                SendPacket(tracked.Packet, target);
            }

            else
            {
                PrimaryAddress.Reset = true;

                foreach (RudpAddress address in AddressMap.Values)
                {
                    tracked.Packet.Ident = address.Ident;
                    tracked.Target       = address;

                    SendPacket(tracked.Packet, address);
                }
            }
        }
Example #2
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);
        }
Example #3
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();
            }
        }
Example #4
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();
        }
Example #5
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);
        }
Example #6
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();
            }
        }
Example #7
0
        public void SendTracked(TrackPacket tracked)
        {
            if (AddressMap.Count == 0)
                return;

            RudpAddress target = tracked.SpecialTarget ? tracked.Target : PrimaryAddress;

            LastSend = Core.TimeNow;
            tracked.TimeSent = Core.TimeNow.Ticks;
            tracked.Target = target;
            tracked.Packet.SenderID = Network.Local.UserID;
            tracked.Packet.SenderClient = Network.Local.ClientID;

            if (tracked.Packet.PacketType != RudpPacketType.Syn)
                SendPacket(tracked.Packet, target);

            else
            {
                PrimaryAddress.Reset = true;

                foreach (RudpAddress address in AddressMap.Values)
                {
                    tracked.Packet.Ident = address.Ident;
                    tracked.Target = address;

                    SendPacket(tracked.Packet, address);
                }
            }
        }