protected void ackPacket(ushort seq)
        {
            OutgoingPacketSet outgoingPacketSet = ackBuffer.Find(seq);

            if (outgoingPacketSet == null)
            {
                return;
            }
            for (int i = 0; i < outgoingPacketSet.MessageIds.Count; i++)
            {
                ushort num = outgoingPacketSet.MessageIds[i];
                if (sendBuffer.Exists(num))
                {
                    sendBuffer.Find(num).writeLock = true;
                    sendBuffer.Remove(num);
                }
            }
            bool   flag = true;
            ushort num2 = oldestUnacked;

            while (num2 == sequence || PacketIO.SequenceLessThan(num2, sequence))
            {
                if (sendBuffer.Exists(num2))
                {
                    oldestUnacked = num2;
                    flag          = false;
                    break;
                }
                num2 = (ushort)(num2 + 1);
            }
            if (flag)
            {
                oldestUnacked = sequence;
            }
        }
        protected void processSendBuffer()
        {
            for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
            {
                // never send message ID >= ( oldestUnacked + bufferSize )
                if (seq >= (oldestUnacked + 256))
                {
                    break;
                }

                // for any message that hasn't been sent in the last 0.1 seconds and fits in the available space of our message packer, add it
                var packet = sendBuffer.Find(seq);
                if (packet != null)
                {
                    if (time - packet.time < 0.1)
                    {
                        continue;
                    }

                    bool packetFits = false;

                    if (packet.buffer.Length < config.FragmentThreshold)
                    {
                        packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.FragmentThreshold - Defines.MAX_PACKET_HEADER_BYTES);
                    }
                    else
                    {
                        packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.MaxPacketSize - Defines.FRAGMENT_HEADER_BYTES - Defines.MAX_PACKET_HEADER_BYTES);
                    }

                    // if the packet won't fit, flush the message packer
                    if (!packetFits)
                    {
                        flushMessagePacker();
                    }

                    packet.time = time;

                    int ptr = messagePacker.Length;
                    messagePacker.SetSize(messagePacker.Length + packet.buffer.Length);
                    messagePacker.BufferCopy(packet.buffer, 0, ptr, packet.buffer.Length);

                    tempList.Add(seq);

                    lastMessageSend = time;
                }
            }

            // if it has been 0.1 seconds since the last time we sent a message, send an empty message
            if (time - lastMessageSend >= 0.1)
            {
                sendAckPacket();
                lastMessageSend = time;
            }

            // flush any remaining messages in message packer
            flushMessagePacker();
        }
Beispiel #3
0
        public T Insert(ushort sequence)
        {
            if (PacketIO.SequenceLessThan(sequence, (ushort)(this.sequence - numEntries)))
            {
                return((T)null);
            }
            if (PacketIO.SequenceGreaterThan((ushort)(sequence + 1), this.sequence))
            {
                RemoveEntries(this.sequence, sequence);
                this.sequence = (ushort)(sequence + 1);
            }
            int num = (int)sequence % numEntries;

            entrySequence[num] = sequence;
            return(entryData[num]);
        }
        public T Insert(ushort sequence)
        {
            if (PacketIO.SequenceLessThan(sequence, (ushort)(this.sequence - numEntries)))
            {
                return(null);
            }

            if (PacketIO.SequenceGreaterThan((ushort)(sequence + 1), this.sequence))
            {
                RemoveEntries(this.sequence, sequence);
                this.sequence = (ushort)(sequence + 1);
            }

            int index = sequence % numEntries;

            this.entrySequence[index] = sequence;
            return(this.entryData[index]);
        }
        public override void SendMessage(byte[] buffer, int bufferPosition, int bufferLength)
        {
            int sendBufferSize = 0;

            for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
            {
                if (sendBuffer.Exists(seq))
                {
                    sendBufferSize++;
                }
            }

            if (sendBufferSize == sendBuffer.Size)
            {
                ByteBuffer tempBuff = ObjPool <ByteBuffer> .Get();

                tempBuff.SetSize(bufferLength);
                tempBuff.BufferCopy(buffer, bufferPosition, 0, bufferLength);
                messageQueue.Enqueue(tempBuff);

                return;
            }

            ushort sequence = this.sequence++;
            var    packet   = sendBuffer.Insert(sequence);

            packet.time = -1.0;

            // ensure size for header
            int varLength = getVariableLengthBytes((ushort)bufferLength);

            packet.buffer.SetSize(2 + varLength + bufferLength);

            using (var writer = ByteArrayReaderWriter.Get(packet.buffer.InternalBuffer)) {
                writer.Write(sequence);

                writeVariableLengthUShort((ushort)bufferLength, writer);
                writer.WriteBuffer(buffer, bufferPosition, bufferLength);
            }

            // signal that packet is ready to be sent
            packet.writeLock = false;
        }
        protected void ackPacket(ushort seq)
        {
            // first, map seq to message IDs and ack them
            var outgoingPacket = ackBuffer.Find(seq);

            if (outgoingPacket == null)
            {
                return;
            }

            // process messages
            for (int i = 0; i < outgoingPacket.MessageIds.Count; i++)
            {
                // remove acked message from send buffer
                ushort messageID = outgoingPacket.MessageIds[i];

                if (sendBuffer.Exists(messageID))
                {
                    sendBuffer.Find(messageID).writeLock = true;
                    sendBuffer.Remove(messageID);
                }
            }

            // update oldest unacked message
            bool allAcked = true;

            for (ushort sequence = oldestUnacked; sequence == this.sequence || PacketIO.SequenceLessThan(sequence, this.sequence); sequence++)
            {
                // if it's still in the send buffer, it hasn't been acked
                if (sendBuffer.Exists(sequence))
                {
                    oldestUnacked = sequence;
                    allAcked      = false;
                    break;
                }
            }

            if (allAcked)
            {
                oldestUnacked = this.sequence;
            }
        }
        protected void processSendBuffer()
        {
            int    num  = 0;
            ushort num2 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num2, sequence))
            {
                num++;
                num2 = (ushort)(num2 + 1);
            }
            ushort num3 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num3, sequence) && num3 < oldestUnacked + 256)
            {
                BufferedPacket bufferedPacket = sendBuffer.Find(num3);
                if (bufferedPacket != null && !bufferedPacket.writeLock && !(time - bufferedPacket.time < 0.1))
                {
                    bool flag = false;
                    if (!((bufferedPacket.buffer.Length >= config.FragmentThreshold) ? (messagePacker.Length + bufferedPacket.buffer.Length <= config.MaxPacketSize - 6 - 10) : (messagePacker.Length + bufferedPacket.buffer.Length <= config.FragmentThreshold - 10)))
                    {
                        flushMessagePacker();
                    }
                    bufferedPacket.time = time;
                    int length = messagePacker.Length;
                    messagePacker.SetSize(messagePacker.Length + bufferedPacket.buffer.Length);
                    messagePacker.BufferCopy(bufferedPacket.buffer, 0, length, bufferedPacket.buffer.Length);
                    tempList.Add(num3);
                    lastMessageSend = time;
                }
                num3 = (ushort)(num3 + 1);
            }
            if (time - lastMessageSend >= 0.1)
            {
                sendAckPacket();
                lastMessageSend = time;
            }
            flushMessagePacker();
        }
        public override void SendMessage(byte[] buffer, int bufferLength)
        {
            int    num  = 0;
            ushort num2 = oldestUnacked;

            while (PacketIO.SequenceLessThan(num2, sequence))
            {
                if (sendBuffer.Exists(num2))
                {
                    num++;
                }
                num2 = (ushort)(num2 + 1);
            }
            if (num == sendBuffer.Size)
            {
                ByteBuffer byteBuffer = ObjPool <ByteBuffer> .Get();

                byteBuffer.SetSize(bufferLength);
                byteBuffer.BufferCopy(buffer, 0, 0, bufferLength);
                messageQueue.Enqueue(byteBuffer);
            }
            else
            {
                ushort         val            = sequence++;
                BufferedPacket bufferedPacket = sendBuffer.Insert(val);
                bufferedPacket.time = -1.0;
                int variableLengthBytes = getVariableLengthBytes((ushort)bufferLength);
                bufferedPacket.buffer.SetSize(bufferLength + 2 + variableLengthBytes);
                using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(bufferedPacket.buffer.InternalBuffer))
                {
                    byteArrayReaderWriter.Write(val);
                    writeVariableLengthUShort((ushort)bufferLength, byteArrayReaderWriter);
                    byteArrayReaderWriter.WriteBuffer(buffer, bufferLength);
                }
                bufferedPacket.writeLock = false;
            }
        }
        public override void Update(double newTime)
        {
            double dt = newTime - time;

            time = newTime;
            this.packetController.Update(time);

            // see if we can pop messages off of the message queue and put them on the send queue
            if (messageQueue.Count > 0)
            {
                int sendBufferSize = 0;
                for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++)
                {
                    if (sendBuffer.Exists(seq))
                    {
                        sendBufferSize++;
                    }
                }

                if (sendBufferSize < sendBuffer.Size)
                {
                    var message = messageQueue.Dequeue();
                    SendMessage(message.InternalBuffer, 0, message.Length);
                    ObjPool <ByteBuffer> .Return(message);
                }
            }

            // update congestion mode
            {
                // conditions are bad if round-trip-time exceeds 250ms
                bool conditionsBad = (this.packetController.RTT >= 250f);

                // if conditions are bad, immediately enable congestion control and reset the congestion timer
                if (conditionsBad)
                {
                    if (this.congestionControl == false)
                    {
                        // if we're within 10 seconds of the last time we switched, double the threshold interval
                        if (time - lastCongestionSwitchTime < 10.0)
                        {
                            congestionDisableInterval = Math.Min(congestionDisableInterval * 2, 60.0);
                        }

                        lastCongestionSwitchTime = time;
                    }

                    this.congestionControl      = true;
                    this.congestionDisableTimer = 0.0;
                }

                // if we're in bad mode, and conditions are good, update the timer and see if we can disable congestion control
                if (this.congestionControl && !conditionsBad)
                {
                    this.congestionDisableTimer += dt;
                    if (this.congestionDisableTimer >= this.congestionDisableInterval)
                    {
                        this.congestionControl   = false;
                        lastCongestionSwitchTime = time;
                        congestionDisableTimer   = 0.0;
                    }
                }

                // as long as conditions are good, halve the threshold interval every 10 seconds
                if (this.congestionControl == false)
                {
                    congestionDisableTimer += dt;
                    if (congestionDisableTimer >= 10.0)
                    {
                        congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0);
                    }
                }
            }

            // if we're in congestion control mode, only send packets 10 times per second.
            // otherwise, send 30 times per second
            double flushInterval = congestionControl ? 0.1 : 0.033;

            if (time - lastBufferFlush >= flushInterval)
            {
                lastBufferFlush = time;
                processSendBuffer();
            }
        }
 public bool TestInsert(ushort sequence)
 {
     return(!PacketIO.SequenceLessThan(sequence, (ushort)(this.sequence - numEntries)));
 }
        public override void Update(double newTime)
        {
            double num = newTime - time;

            time = newTime;
            packetController.Update(time);
            if (messageQueue.Count > 0)
            {
                int    num2 = 0;
                ushort num3 = oldestUnacked;
                while (PacketIO.SequenceLessThan(num3, sequence))
                {
                    if (sendBuffer.Exists(num3))
                    {
                        num2++;
                    }
                    num3 = (ushort)(num3 + 1);
                }
                if (num2 < sendBuffer.Size)
                {
                    ByteBuffer byteBuffer = messageQueue.Dequeue();
                    SendMessage(byteBuffer.InternalBuffer, byteBuffer.Length);
                    ObjPool <ByteBuffer> .Return(byteBuffer);
                }
            }
            bool flag = packetController.RTT >= 250f;

            if (flag)
            {
                if (!congestionControl)
                {
                    if (time - lastCongestionSwitchTime < 10.0)
                    {
                        congestionDisableInterval = Math.Min(congestionDisableInterval * 2.0, 60.0);
                    }
                    lastCongestionSwitchTime = time;
                }
                congestionControl      = true;
                congestionDisableTimer = 0.0;
            }
            if (congestionControl && !flag)
            {
                congestionDisableTimer += num;
                if (congestionDisableTimer >= congestionDisableInterval)
                {
                    congestionControl        = false;
                    lastCongestionSwitchTime = time;
                    congestionDisableTimer   = 0.0;
                }
            }
            if (!congestionControl)
            {
                congestionDisableTimer += num;
                if (congestionDisableTimer >= 10.0)
                {
                    congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0);
                }
            }
            double num4 = (!congestionControl) ? 0.033 : 0.1;

            if (time - lastBufferFlush >= num4)
            {
                lastBufferFlush = time;
                processSendBuffer();
            }
        }