Exemplo n.º 1
0
        /// <summary>
        /// Enqueues necessary packets for a data stream
        /// </summary>
        private bool enqueueDataStream(DataStream ds, StreamState stream)
        {       //Write packets into the stream while we still have bandwidth available
            int bytesLeft = _rateThreshold - _bytesWritten;

            while (bytesLeft > 0 && ds.amountSent < ds.buffer.Length)
            {   //Prepare a data packet
                DataPacket dp = new DataPacket(stream.streamID);

                dp._bFirstPacket = (ds.amountSent == 0);
                dp.data          = ds.buffer;
                dp.offset        = ds.amountSent;

                dp.rNumber = stream.S2C_Reliable++;

                dp.MakeSerialized(this, _handler);

                ds.lastPacket = dp;             //For completion notification

                ds.amountSent += dp._dataRead;
                bytesLeft     -= dp._dataRead;

                //Add it to our list of reliable packets
                ReliableInfo ri = new ReliableInfo();

                ri.streamParent = ds;
                ri.packet       = dp;
                ri.rid          = dp.rNumber;
                ri.timeSent     = 0;

                stream.reliablePackets[dp.rNumber] = ri;
            }

            //Have we completed?
            return(!(ds.amountSent >= ds.buffer.Length));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Sends a reliable packet to the client
        /// </summary>
        public void sendReliable(PacketBase packet, Action completionCallback, int streamID)
        {       //Sync up!
            using (DdMonitor.Lock(_sync))
            {   //Get the relevant stream
                Client.StreamState stream = _streams[streamID];

                //Make sure the packet is serialized
                packet.MakeSerialized(this, _handler);

                //Is the (packet and reliable header) too large to be sent as one?
                if (4 + packet._size + _CRCLength > _C2S_UDPSize)
                {       //Add the stream packet to the reliable queue so we know
                    //when to start streaming it.
                    DataStream   ds = new DataStream();
                    ReliableInfo ri = new ReliableInfo();

                    ds.amountSent = 0;
                    ds.buffer     = packet.Data;
                    if (completionCallback != null)
                    {
                        ds.Completed += completionCallback;
                    }

                    ri.dataStream = ds;

                    //Put it in the reliable queue
                    stream.reliableQueue.Enqueue(ri);
                }
                else
                {       //Jam it in the reliable queue to be parsed
                    ReliableInfo ri = new ReliableInfo();

                    ri.packet = packet;
                    ri.rid    = -1;
                    if (completionCallback != null)
                    {
                        ri.Completed += completionCallback;
                    }

                    //Put it in the reliable queue
                    stream.reliableQueue.Enqueue(ri);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Adds any reliable packets waiting to be sent to the packet queue
        /// </summary>
        private void enqueueReliables(StreamState stream)
        {       //Check for data streams
            if (stream.reliableQueue.Count == 0)
            {
                return;
            }

            ReliableInfo ri = stream.reliableQueue.Peek();

            while (ri.dataStream != null)
            {   //If it's still streaming, then don't send any more reliables yet
                if (enqueueDataStream(ri.dataStream, stream))
                {
                    return;
                }
                else
                {
                    stream.reliableQueue.Dequeue();
                }

                //Check the next
                if (stream.reliableQueue.Count == 0)
                {
                    return;
                }

                ri = stream.reliableQueue.Peek();
            }

            //Take care of reliable packet waiting to be streamed
            ICollection <ReliableInfo> reliableBoxed = boxReliablePackets(stream.reliableQueue, stream, stream.streamID);

            //Insert them all into our reliable table
            foreach (ReliableInfo info in reliableBoxed)
            {   //Make sure the rid is correct
                if (info.rid == -1)
                {
                    Log.write(TLog.Error, "Reliable info was queued for sending with an unassigned reliable number.");
                    continue;
                }

                stream.reliablePackets[(ushort)info.rid] = info;
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Groups packets together into box packets as necessary
        /// </summary>
        public ICollection <ReliableInfo> boxReliablePackets(Queue <ReliableInfo> packetQueue, StreamState stream, int streamID)
        {       //Empty?
            if (packetQueue.Count == 0)
            {
                return(null);
            }
            //If it's just one packet, there's no need
            else if (packetQueue.Count == 1)
            {   //We need to put it in a reliable case
                Reliable     reli  = new Reliable();
                ReliableInfo rinfo = packetQueue.Dequeue();

                reli.streamID = streamID;
                reli.packet   = rinfo.packet;
                rinfo.rid     = reli.rNumber = stream.S2C_Reliable++;
                rinfo.packet  = reli;

                List <ReliableInfo> list = new List <ReliableInfo>();
                list.Add(rinfo);
                return(list);
            }

            //Go through the list, creating boxed packets as we go
            List <ReliableInfo> reliables = new List <ReliableInfo>();
            ReliableInfo        info;
            ReliableBox         box = new ReliableBox(streamID);
            int packetStartSize     = 4 /*reliable*/ + 2 /*reliable box*/ + _CRCLength;
            int currentSize         = packetStartSize;  //Header+footer size of a boxed reliable packet

            //Group our normal packets
            while (packetQueue.Count > 0 && packetQueue.Peek().dataStream == null)
            {
                ReliableInfo pInfo = packetQueue.Dequeue();

                //If the packet exceeds the max limit, send it on it's own
                if (2 + 1 + pInfo.packet.Length > byte.MaxValue)
                {       //We need to send the previous boxing packets first, as they
                    //should be in order of reliable id
                    if (box.reliables.Count > 0)
                    {
                        info     = new ReliableInfo();
                        info.rid = stream.S2C_Reliable++;

                        //Don't add a lonely box
                        if (box.reliables.Count == 1)
                        {
                            info.packet = new Reliable(box.reliables[0].packet, info.rid, streamID);
                        }
                        else
                        {       //Make sure the box is serialized
                            box.MakeSerialized(this, _handler);

                            info.packet = new Reliable(box, info.rid, streamID);
                        }

                        info.consolidateEvents(box.reliables);

                        reliables.Add(info);
                    }

                    box         = new ReliableBox(streamID);
                    currentSize = packetStartSize;

                    //Add the packet on it's own
                    Reliable reli = new Reliable();

                    reli.streamID = streamID;
                    reli.packet   = pInfo.packet;
                    pInfo.rid     = reli.rNumber = stream.S2C_Reliable++;
                    pInfo.packet  = reli;

                    reliables.Add(pInfo);
                    continue;
                }

                //Do we have space to add this packet?
                if (currentSize + pInfo.packet.Length + 1 > udpMaxSize)
                {       //There's not enough room, box up our current packet
                    info     = new ReliableInfo();
                    info.rid = stream.S2C_Reliable++;

                    //Don't add a lonely box
                    if (box.reliables.Count == 1)
                    {
                        info.packet = new Reliable(box.reliables[0].packet, info.rid, streamID);
                    }
                    else
                    {   //Make sure the box is serialized
                        box.MakeSerialized(this, _handler);

                        info.packet = new Reliable(box, info.rid, streamID);
                    }

                    info.consolidateEvents(box.reliables);

                    reliables.Add(info);

                    box         = new ReliableBox(streamID);
                    currentSize = packetStartSize;
                }

                //Add the packet to the box list
                box.reliables.Add(pInfo);
                currentSize += pInfo.packet.Length + 1;
            }

            //If the last box has more than one packet, keep it
            if (box.reliables.Count > 1)
            {
                info     = new ReliableInfo();
                info.rid = stream.S2C_Reliable++;

                //Make sure the box is serialized
                box.MakeSerialized(this, _handler);

                info.packet = new Reliable(box, info.rid, streamID);
                info.consolidateEvents(box.reliables);

                reliables.Add(info);
            }
            else if (box.reliables.Count == 1)
            {   //If it's only one packet, we don't need the box
                info        = new ReliableInfo();
                info.rid    = stream.S2C_Reliable++;
                info.packet = new Reliable(box.reliables[0].packet, info.rid, streamID);
                info.consolidateEvents(box.reliables[0]);

                reliables.Add(info);
            }

            //Boxed them all
            return(reliables);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Merges all events from a reliable infos into the class
 /// </summary>
 public void consolidateEvents(ReliableInfo reliable)
 {
     Completed += reliable.Completed;
 }