Exemplo n.º 1
0
        // Return if there is more to come.
        public static bool ProcessLanesSend(LaneSetup setup, Lane[] lanes, DateTime now, Send[] output, out uint numOut)
        {
            numOut = 0;
            for (int i = 0; i < lanes.Length; i++)
            {
                Lane lane  = lanes[i];
                int  holes = 0;
                for (int j = 0; j < lane.OutCount; j++)
                {
                    if (lane.Out[j].Source == null)
                    {
                        holes++;
                        continue;
                    }
                    if (lane.Out[j].SendTime <= now)
                    {
                        lane.Stats.SendCount++;
                        lane.Out[j].SendCount++;
                        if (lane.Out[j].SendCount > 1)
                        {
                            lane.Stats.SendResends++;
                        }

                        uint resendMsAdd = lane.Out[j].SendCount * lane.Out[j].SendCount * lane.ResendMs;
                        if (resendMsAdd > 5000)
                        {
                            resendMsAdd = 5000;
                        }

                        lane.Out[j].SendTime = lane.Out[j].SendTime.AddMilliseconds(resendMsAdd);

                        Bitstream.Buffer tmp = setup.Factory.GetBuffer(setup.MaxPacketSize);
                        tmp.bytepos = setup.ReservedHeaderBytes;

                        Bitstream.PutBits(tmp, 1, lane.Out[j].Reliable ? 1u : 0u);
                        Bitstream.PutCompressedUint(tmp, lane.Out[j].SeqId);

                        if (lane.Out[j].Reliable)
                        {
                            Bitstream.PutBits(tmp, 1, lane.Out[j].IsFinalPiece ? 1u : 0u);

                            // flush out a max number of acks or all.
                            int wrote = 0;
                            for (int k = 0; k < lane.AckCount && k < 4; k++)
                            {
                                Bitstream.PutCompressedUint(tmp, lane.Acks[k]);
                                wrote++;
                            }
                            Bitstream.PutCompressedUint(tmp, 0);
                            for (int k = 0; k < (int)lane.AckCount - wrote; k++)
                            {
                                lane.Acks[k] = lane.Acks[k + wrote];
                            }
                            lane.AckCount = (ushort)(lane.AckCount - wrote);
                        }

                        Bitstream.SyncByte(tmp);

                        uint   begin = lane.Out[j].Begin;
                        uint   end   = lane.Out[j].End;
                        uint   ofs   = tmp.bytepos;
                        byte[] src   = lane.Out[j].Source.buf;
                        byte[] dst   = tmp.buf;
                        for (uint k = begin; k != end; k++)
                        {
                            dst[ofs++] = src[k];
                        }
                        tmp.bytepos           = 0;
                        tmp.bitpos            = 0;
                        tmp.bytesize          = ofs;
                        tmp.bitsize           = 0;
                        output[numOut].Data   = tmp;
                        output[numOut].Lane   = lane;
                        lane.Stats.SendBytes += ofs;
                        if (++numOut == output.Length)
                        {
                            return(true);
                        }
                    }
                }

                if (holes > 0 && holes >= lane.OutCount / 4)
                {
                    ushort write = 0;
                    for (uint j = 0; j < lane.OutCount; j++)
                    {
                        if (lane.Out[j].Source != null)
                        {
                            if (write != j)
                            {
                                lane.Out[write] = lane.Out[j];
                            }
                            ++write;
                        }
                    }
                    lane.OutCount = write;
                }
            }

            // Unsent acks
            for (int i = 0; i < lanes.Length; i++)
            {
                Lane lane = lanes[i];
                if (lane.AckCount > 0)
                {
                    Bitstream.Buffer tmp = setup.Factory.GetBuffer(setup.MaxPacketSize);
                    tmp.bytepos = setup.ReservedHeaderBytes;
                    Bitstream.PutBits(tmp, 1, 1);                     // reliable
                    Bitstream.PutCompressedUint(tmp, 0);              // ack only
                    Bitstream.PutBits(tmp, 1, 1);                     // final

                    for (int k = 0; k < lane.AckCount; k++)
                    {
                        Bitstream.PutCompressedUint(tmp, lane.Acks[k]);
                    }

                    Bitstream.PutCompressedUint(tmp, 0);
                    lane.AckCount = 0;
                    Bitstream.SyncByte(tmp);
                    tmp.Flip();
                    output[numOut].Data = tmp;
                    output[numOut].Lane = lane;

                    lane.Stats.SendCount++;
                    lane.Stats.SendAckOnly++;
                    lane.Stats.SendBytes += tmp.bytesize;

                    if (++numOut == output.Length)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 2
0
        // Will hold the buffers until they are sent
        public static void ScheduleSend(LaneSetup setup, DateTime now, ToSend[] tosend, uint count)
        {
            for (uint i = 0; i < count; i++)
            {
                Lane lane = tosend[i].Lane;

                if (!tosend[i].Reliable)
                {
                    uint target = (uint)lane.Out.Length;
                    if (lane.OutCount == lane.Out.Length)
                    {
                        for (uint k = 0; k < lane.Out.Length; k++)
                        {
                            if (lane.Out[k].Source == null)
                            {
                                target = k;
                                break;
                            }
                        }
                    }
                    else
                    {
                        target = lane.OutCount++;
                    }

                    if (target == lane.Out.Length)
                    {
                        // Dropped
                        continue;
                    }

                    if (tosend[i].CanKeepData)
                    {
                        lane.Out[target].Source = tosend[i].Data;
                    }
                    else
                    {
                        lane.Out[target].Source = setup.Factory.GetBuffer(tosend[i].Data.bytesize);
                        Bitstream.Insert(lane.Out[target].Source, tosend[i].Data);
                        Bitstream.SyncByte(lane.Out[target].Source);
                        lane.Out[target].Source.Flip();
                    }

                    lane.Out[target].Source.userdata = 1;                     // refcount

                    lane.Out[target].Begin           = 0;
                    lane.Out[target].End             = tosend[i].Data.bytesize;
                    lane.Out[target].IsFinalPiece    = true;
                    lane.Out[target].SendTime        = now;
                    lane.Out[target].InitialSendTime = now;
                    lane.Out[target].SendCount       = 0;
                    lane.Out[target].SeqId           = ++lane.OutgoingSeqUnreliable;
                    lane.Out[target].Reliable        = false;
                }
                else
                {
                    uint   segmentSize = setup.MaxPacketSize - 32 - setup.ReservedHeaderBytes;
                    uint   numSegments = (uint)(((tosend[i].Data.bytesize - tosend[i].Data.bytepos) + segmentSize - 1) / segmentSize);
                    uint[] outSlots    = new uint[256];
                    if (numSegments == 0 || numSegments > outSlots.Length)
                    {
                        continue;
                    }

                    uint write = 0;
                    for (uint k = 0; k < lane.OutCount; k++)
                    {
                        if (lane.Out[k].Source == null)
                        {
                            outSlots[write++] = k;
                            if (write == numSegments)
                            {
                                break;
                            }
                        }
                    }

                    uint left = numSegments - write;
                    if ((lane.Out.Length - lane.OutCount) < left)
                    {
                        // no room.
                        continue;
                    }

                    for (uint k = 0; k < left; k++)
                    {
                        outSlots[write++] = lane.OutCount++;
                    }

                    Bitstream.Buffer source = tosend[i].Data;
                    if (!tosend[i].CanKeepData)
                    {
                        source = setup.Factory.GetBuffer(tosend[i].Data.bytesize);
                        Bitstream.Insert(source, tosend[i].Data);
                        source.Flip();
                    }

                    source.userdata = 0;
                    uint RangeBegin = 0;
                    for (uint k = 0; k < numSegments; k++)
                    {
                        uint bytesLeft = source.bytesize - RangeBegin;
                        if (bytesLeft == 0)
                        {
                            Console.WriteLine("ERROR: bytesLeft=0!");
                            continue;
                        }
                        uint toWrite = bytesLeft < segmentSize ? bytesLeft : segmentSize;
                        uint slot    = outSlots[k];
                        source.userdata++;
                        lane.Out[slot].Source          = source;
                        lane.Out[slot].Begin           = RangeBegin;
                        lane.Out[slot].End             = RangeBegin + toWrite;
                        lane.Out[slot].IsFinalPiece    = k == (numSegments - 1);
                        lane.Out[slot].SendTime        = now;
                        lane.Out[slot].InitialSendTime = now;
                        lane.Out[slot].SendCount       = 0;
                        lane.Out[slot].Reliable        = true;
                        lane.Out[slot].SeqId           = ++lane.OutgoingSeqReliable;
                        RangeBegin = RangeBegin + toWrite;
                    }
                }
            }
        }
Exemplo n.º 3
0
        // This will start reading from the buffers and modify the incoming array.
        public static void HandleIncomingPackets(LaneSetup setup, Incoming[] packets, uint packetsCount)
        {
            // Zero pass make own buffers.
            for (uint i = 0; i < packetsCount; i++)
            {
                if (!packets[i].CanKeepData)
                {
                    Bitstream.Buffer tmp  = packets[i].Packet;
                    Bitstream.Buffer copy = setup.Factory.GetBuffer((uint)tmp.buf.Length);
                    Bitstream.Insert(copy, tmp);
                    copy.Flip();
                    packets[i].Packet = copy;
                }
            }

            // First pass extract.
            for (uint i = 0; i < packetsCount; i++)
            {
                Bitstream.Buffer tmp  = packets[i].Packet;
                Lane             lane = packets[i].Lane;
                lane.Stats.RecvCount++;
                lane.Stats.RecvBytes += tmp.BitsLeft() / 8;

                bool reliable = Bitstream.ReadBits(tmp, 1) == 1;
                uint seq      = Bitstream.ReadCompressedUint(tmp);
                packets[i].Internal.Seq        = seq;
                packets[i].Internal.IsReliable = reliable;

                if (seq == 0)
                {
                    lane.Stats.RecvAckOnly++;
                }

                if (reliable)
                {
                    packets[i].Internal.IsFinalPiece = Bitstream.ReadBits(tmp, 1) == 1;

                    if (!packets[i].Internal.IsFinalPiece)
                    {
                        lane.Stats.RecvNonFinal++;
                    }

                    if (seq != 0)
                    {
                        if (lane.AckCount < lane.Acks.Length)
                        {
                            lane.Acks[lane.AckCount++] = seq;
                        }
                    }

                    while (true)
                    {
                        uint seqAck = Bitstream.ReadCompressedUint(tmp);
                        if (seqAck != 0)
                        {
                            for (int j = 0; j != lane.OutCount; j++)
                            {
                                if (lane.Out[j].SeqId == seqAck)
                                {
                                    double msLag = (packets[i].ArrivalTime - lane.Out[j].InitialSendTime).TotalMilliseconds;
                                    if (msLag > 0)
                                    {
                                        uint ms = (uint)msLag;
                                        if (ms < lane.LagMsMin || lane.LagMsMin == 0)
                                        {
                                            if (ms >= setup.MinResendTimeMs)
                                            {
                                                lane.LagMsMin = ms;
                                                lane.ResendMs = 2 * ms;
                                            }
                                        }
                                    }

                                    if (lane.Out[j].Source != null)
                                    {
                                        if (--lane.Out[j].Source.userdata == 0)
                                        {
                                            setup.Factory.ReturnBuffer(lane.Out[j].Source);
                                        }
                                        lane.Out[j].Source = null;
                                    }
                                }
                            }
                            continue;
                        }
                        break;
                    }
                }
                else
                {
                    packets[i].Internal.IsFinalPiece = true;
                }

                Bitstream.SyncByte(tmp);
            }

            // Unreliable packets, these are placed in the out queue after reading out the sequence and mode.
            for (int i = 0; i < packets.Length; i++)
            {
                if (packets[i].Internal.IsReliable || packets[i].Internal.Seq == 0)
                {
                    continue;
                }
                Lane lane = packets[i].Lane;
                if (lane.DoneHead - lane.DoneTail != lane.Done.Length)
                {
                    uint head = lane.DoneHead % (uint)lane.Done.Length;
                    lane.Done[head].Data           = packets[i].Packet;
                    lane.Done[head].Reliable       = false;
                    lane.Done[head].SeqId          = packets[i].Internal.Seq;
                    lane.Done[head].ArrivalTime    = packets[i].ArrivalTime;
                    lane.Done[head].CompletionTime = packets[i].ArrivalTime;
                    lane.Done[head].Lane           = lane;
                    lane.DoneHead = lane.DoneHead + 1;
                }
            }

            // Handle reliable. These go straight
            for (int i = 0; i < packets.Length; i++)
            {
                if (!packets[i].Internal.IsReliable || packets[i].Internal.Seq == 0)
                {
                    continue;
                }

                Lane lane = packets[i].Lane;

                if (packets[i].Internal.Seq <= lane.ReliableSeq)
                {
                    lane.Stats.RecvDupes++;
                    continue;
                }

                // If packet arrives a second time, ignore.
                uint numProgress = (uint)lane.Progress.Length;
                bool hadit       = false;
                for (uint p = lane.ProgressTail; p != lane.ProgressHead; p++)
                {
                    uint idx = p % numProgress;
                    if (lane.Progress[idx].SeqId == packets[i].Internal.Seq)
                    {
                        hadit = true;
                        break;
                    }
                }

                if (hadit)
                {
                    // Already got the packet for this sequence id.
                    lane.Stats.RecvDupes++;
                    continue;
                }

                if (lane.ProgressHead - lane.ProgressTail != lane.Progress.Length)
                {
                    uint head = lane.ProgressHead % (uint)lane.Progress.Length;
                    lane.Progress[head].Data         = packets[i].Packet;
                    lane.Progress[head].IsFinalPiece = packets[i].Internal.IsFinalPiece;
                    lane.Progress[head].ArrivalTime  = packets[i].ArrivalTime;
                    lane.Progress[head].SeqId        = packets[i].Internal.Seq;
                    lane.ProgressHead = lane.ProgressHead + 1;
                }
            }
        }