示例#1
0
        /// <summary>
        /// Confirms that a reliable packet has been received by the client.
        /// Note that a higher rID than the lowest expected indicates that all
        /// previous reliable packets were received.
        /// </summary>
        public void confirmReliable(ushort rID, int streamID)
        {       //Great!
            using (DdMonitor.Lock(_sync))
            {   //Get the relevant stream
                Client.StreamState stream = _streams[streamID];

                //This satisfies all packets inbetween
                for (ushort i = stream.S2C_ReliableConfirmed; i <= rID; ++i)
                {       //Get our associated info
                    ReliableInfo ri;

                    if (!stream.reliablePackets.TryGetValue(i, out ri))
                    {
                        continue;
                    }

                    stream.reliablePackets.Remove(i);

                    //Part of a data stream?
                    if (ri.streamParent != null)
                    {
                        if (ri.streamParent.lastPacket == ri.packet)
                        {
                            ri.streamParent.onCompleted();
                        }
                    }
                    else
                    {
                        ri.onCompleted();
                    }
                }

                stream.S2C_ReliableConfirmed = (ushort)(rID + 1);
            }
        }
示例#2
0
        /// <summary>
        /// Allows the client to take care of anything it needs to
        /// </summary>
        public override void poll()
        {       //Sync up!
            using (DdMonitor.Lock(_sync))
            {   //Only time out server-side clients
                int now = Environment.TickCount;

                if (connectionTimeout != -1 && !_bClientConn && now - base._lastPacketRecv > connectionTimeout)
                {       //Farewell~
                    Log.write(TLog.Warning, "Client timeout: {0}", this);
                    destroy();
                    return;
                }

                if (_tickDestroy > 0 && now - _tickDestroy > 15000) //15 seconds (gives enough time to send any queued messages)
                {                                                   //Farewell~
                    Log.write(TLog.Warning, "Client timeout: {0}", this);
                    destroy();
                    return;
                }

                //Should we decay the bytes written?
                if (now - _tickLastDecay > 20)
                {
                    _bytesWritten -= _decayRate;
                    if (_bytesWritten < 0)
                    {
                        _bytesWritten = 0;
                    }
                    _tickLastDecay = now;
                }

                //Update connection stats?
                if (now - _tickLastBytesSample > 1000)
                {
                    _stats.SendSpeed    = _bytesSent;
                    _stats.ReceiveSpeed = _bytesReceived;

                    _bytesSent     = 0;
                    _bytesReceived = 0;

                    _tickLastBytesSample = now;
                }

                //Handle each stream
                for (int i = 0; i < 4; ++i)
                {
                    Client.StreamState stream = _streams[i];

                    //Queue reliable packets as necessary
                    enqueueReliables(stream);

                    //Make sure they all reach their destination
                    ensureReliable(stream);
                }

                //Box packets as necessary and send them out
                sendQueuedPackets();
            }
        }
示例#3
0
        /// <summary>
        /// Takes a note that the packet was received out of sync
        /// </summary>
        public void reportOutOfSync(PacketBase packet, ushort rID, int streamID)
        {       //Get the relevant stream
            Client.StreamState stream = _streams[streamID];

            //Keep the packet around for later
            stream.oosReliable[rID] = packet;

            //Is the last OOS packet still valid?
            if (stream.lastOOSPacket > stream.C2S_Reliable)
            {
                //Ignore the request until this OOS is honored
                return;
            }

            //Note it down as out of sync
            stream.lastOOSPacket = rID;
            stream.tickOOSPacket = Environment.TickCount;
        }
示例#4
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);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Ensures that the client is receiving all reliable packets sent
        /// </summary>
        /// <remarks>Also is the only function that sends reliable packets.</remarks>
        private void ensureReliable(Client.StreamState stream)
        {       //Compare times
            int currentTick = Environment.TickCount;

            //Do we need to send an out of sync notification?
            if (stream.lastOOSPacket > stream.C2S_Reliable &&
                currentTick - stream.tickOOSPacket > 100)
            {
                OutOfSync oos = new OutOfSync(stream.streamID);

                oos.streamID = stream.streamID;
                oos.rNumber  = stream.lastOOSPacket;
                send(oos);

                stream.tickOOSPacket = currentTick + 200;
            }

            //Do we have any bandwidth available?
            int bytesLeft = _rateThreshold - _bytesWritten;

            if (bytesLeft < 0)
            {
                return;
            }

            //We want to start with the first sent packet
            for (ushort n = stream.S2C_ReliableConfirmed; n < stream.S2C_Reliable; ++n)
            {   //Does it exist?
                ReliableInfo ri;

                if (!stream.reliablePackets.TryGetValue(n, out ri))
                {
                    continue;
                }

                //Has it been delayed too long?
                if (currentTick - ri.timeSent < 1000)
                {
                    continue;
                }

                //Resend it
                _packetQueue.Enqueue(ri.packet);

                //Was it a reattempt?
                if (ri.timeSent != 0)
                {
                    ri.attempts++;

                    //Log.write(TLog.Warning, "Reliable packet #" + ri.rid + " lost. (" + ri.attempts + ")");
                }

                ri.timeSent = Environment.TickCount;

                //Don't go over the bandwidth limit or we'll just complicate things
                bytesLeft -= ri.packet._size;
                if (bytesLeft < 0)
                {
                    break;
                }
            }
        }