Пример #1
0
        void OnCommandReceived(UdpBitStream buffer)
        {
            if (ParseHeader(ref buffer))
            {
                stats.CommandsReceived += 1;

                buffer.Ptr = UdpHeader.GetSize(socket);
                UdpCommandType cmd = (UdpCommandType)buffer.ReadByte(8);

                switch (cmd)
                {
                case UdpCommandType.Connect: OnCommandConnect(buffer); break;

                case UdpCommandType.Accepted: OnCommandAccepted(buffer); break;

                case UdpCommandType.Refused: OnCommandRefused(buffer); break;

                case UdpCommandType.Disconnected: OnCommandDisconnected(buffer); break;

                case UdpCommandType.Ping: OnCommandPing(buffer); break;

                default: ConnectionError(UdpConnectionError.IncorrectCommand); break;
                }
            }
        }
Пример #2
0
        internal void SendCommand(UdpCommandType cmd)
        {
            if (CheckCanSend(true) == UdpSendFailReason.None)
            {
                UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize);
                stream.WriteByte((byte)cmd, 8);

                UdpHeader header = MakeHeader(false);
                header.Pack(stream, socket);

                UdpHandle handle = MakeHandle(ref header);
                handle.Object = null;

                if (SendStream(stream, handle, false))
                {
                    // track stats
                    stats.PacketSent((uint)stream.Ptr >> 3);
                    socket.Stats.PacketSent((uint)stream.Ptr >> 3);
                }
                else
                {
                    // should we do something here?????
                }
            }
        }
Пример #3
0
        void RecvUnconnectedPacket(UdpBitStream buff, UdpEndPoint ep)
        {
            buff.Ptr = UdpHeader.GetSize(this);

            if (buff.ReadByte(8) == (byte)UdpCommandType.Connect)
            {
                if (Config.AllowIncommingConnections && ((connLookup.Count + pendingConnections.Count) < Config.ConnectionLimit || Config.ConnectionLimit == -1))
                {
                    if (Config.AutoAcceptIncommingConnections)
                    {
                        AcceptConnection(ep);
                    }
                    else
                    {
                        if (pendingConnections.Add(ep))
                        {
                            Raise(UdpEvent.PUBLIC_CONNECT_REQUEST, ep);
                        }
                    }
                }
                else
                {
                    SendRefusedCommand(ep);
                }
            }
            else
            {
                UdpLog.Debug("received invalid header byte in unconnected packet from {0}", ep.ToString());
            }
        }
Пример #4
0
        internal void SendObject(object o)
        {
            serializer.SendNext(o);

            while (serializer.HasQueuedObjects)
            {
                UdpSendFailReason reason = CheckCanSend(false);

                if (reason != UdpSendFailReason.None)
                {
                    while (serializer.HasQueuedObjects)
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason);
                    }

                    break;
                }

                UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize);
                object    obj    = serializer.NextObject();

                if (serializer.Pack(stream, ref obj))
                {
                    if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false))
                    {
                        UdpLog.Error("stream to {0} is overflowing, not sending", endpoint.ToString());
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow);
                        return;
                    }

                    UdpHeader header = MakeHeader(true);
                    header.Pack(stream, socket);

                    UdpHandle handle = MakeHandle(ref header);
                    handle.Object = obj;

                    if (SendStream(stream, handle, alwaysSendMtu))
                    {
                        // track stats
                        stats.PacketSent((uint)stream.Ptr >> 3);
                        socket.Statistics.PacketSent((uint)stream.Ptr >> 3);

                        // push object to user thread
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SENT, this, obj);
                        Log.info(this, "SendObject##UdpSocket.HeaderBitSize: " + (UdpSocket.HeaderBitSize >> 3));
                        Log.info(this, "SendObject##size: " + (stream.Ptr >> 3));
                    }
                    else
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError);
                    }
                }
                else
                {
                    socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse);
                }
            }
        }
Пример #5
0
        UdpHandle MakeHandle(ref UdpHeader header)
        {
            UdpHandle handle = new UdpHandle();

            handle.IsObject    = header.IsObject;
            handle.ObjSequence = header.ObjSequence;
            handle.SendTime    = header.Now;
            return(handle);
        }
Пример #6
0
        void AckHandles(UdpHeader header, bool updateRtt)
        {
            while (!sendWindow.Empty)
            {
                UdpHandle handle = sendWindow.Peek();

                int seqDistance = UdpMath.SeqDistance(handle.ObjSequence, header.AckSequence, UdpHeader.SEQ_PADD);
                if (seqDistance > 0)
                {
                    break;
                }

                if (handle.IsObject)
                {
                    if (seqDistance <= -UdpSocket.AckRedundancy)
                    {
                        // track stats
                        stats.PacketLost();
                        socket.Statistics.PacketLost();

                        // handle lost
                        ObjectLost(handle.Object);
                    }
                    else
                    {
                        if ((header.AckHistory & (1UL << -seqDistance)) != 0UL)
                        {
                            // track stats
                            stats.PacketDelivered();
                            socket.Statistics.PacketDelivered();

                            // handle delivered objects
                            ObjectDelivered(handle.Object);
                        }
                        else
                        {
                            // track stats
                            stats.PacketLost();
                            socket.Statistics.PacketLost();

                            // handle
                            ObjectLost(handle.Object);
                        }
                    }
                }

                if (seqDistance == 0 && header.AckTime > 0)
                {
                    UpdatePing(recvTime, handle.SendTime, header.AckTime);
                }

                sendWindow.Dequeue();
            }
        }
Пример #7
0
        internal void SendObject(object o)
        {
            serializer.SendNext(o);

            while (serializer.HasQueuedObjects)
            {
                UdpSendFailReason reason = CheckCanSend(false);

                if (reason != UdpSendFailReason.None)
                {
                    while (serializer.HasQueuedObjects)
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason);
                    }

                    break;
                }

                UdpBitStream stream = new UdpBitStream(socket.GetWriteBuffer(), mtu, UdpHeader.GetSize(socket));
                object       obj    = serializer.NextObject();

                if (serializer.Pack(ref stream, ref obj))
                {
                    if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false))
                    {
                        UdpLog.Error("stream to {0} is overflowing, not sending", endpoint.ToString());
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow);
                        return;
                    }

                    UdpHeader header = MakeHeader(true);
                    header.Pack(new UdpBitStream(stream.Data, mtu, 0), socket);

                    UdpHandle handle = MakeHandle(ref header);
                    handle.Object = obj;

                    if (SendStream(stream, handle, alwaysSendMtu) == false)
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError);
                    }
                    else
                    {
                        stats.PacketSent();
                    }
                }
                else
                {
                    socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse);
                }
            }
        }
Пример #8
0
        UdpHeader MakeHeader(bool isObject)
        {
            UdpHeader header = new UdpHeader();

            header.IsObject    = isObject;
            header.AckHistory  = recvHistory;
            header.AckSequence = recvSequence;
            header.ObjSequence = UdpMath.SeqNext(sendSequence, UdpHeader.SEQ_MASK);
            header.Now         = socket.GetCurrentTime();

            if (recvTime > 0)
            {
                header.AckTime = (ushort)UdpMath.Clamp(header.Now - recvTime, 0, socket.Config.MaxPing);
            }

            return(header);
        }
Пример #9
0
        bool ParseHeader(ref UdpBitStream buffer)
        {
            UdpHeader header = new UdpHeader();

            header.Unpack(new UdpBitStream(buffer.Data, buffer.Length, 0), socket);

            // Assign bit size
            if (socket.Config.WritePacketBitSize)
            {
                buffer.Length = header.BitSize;
            }

            int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD);

            // we have to be within window size
            if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow)
            {
                ConnectionError(UdpConnectionError.SequenceOutOfBounds);
                return(false);
            }

            // this is an old packet
            if (seqDistance <= 0)
            {
                return(false);
            }

            // update receive history
            if (seqDistance >= socket.Config.AckRedundancy)
            {
                recvHistory = 1UL;
            }
            else
            {
                recvHistory = (recvHistory << seqDistance) | 1UL;
            }

            // update our receive stats
            recvSequence       = header.ObjSequence;
            recvSinceLastSend += 1;

            // ack sent objects
            AckHandles(header, true);

            return(true);
        }
Пример #10
0
        bool ParseHeader(UdpStream stream)
        {
            // we should always start at ptr 0
            UdpAssert.Assert(stream.Ptr == 0);

            UdpHeader header = new UdpHeader();

            header.Unpack(stream, socket);

            // after unpacking the header, the pointer should be at the header size
            UdpAssert.Assert(stream.Ptr == UdpSocket.HeaderBitSize);

            int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD);

            // we have to be within window size
            if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow)
            {
                ConnectionError(UdpConnectionError.SequenceOutOfBounds);
                return(false);
            }

            // this is an old packet
            if (seqDistance <= 0)
            {
                return(false);
            }

            // update receive history
            if (seqDistance >= UdpSocket.AckRedundancy)
            {
                recvHistory = 1UL;
            }
            else
            {
                recvHistory = (recvHistory << seqDistance) | 1UL;
            }

            // update our receive stats
            recvSequence       = header.ObjSequence;
            recvSinceLastSend += 1;

            // ack sent objects
            AckHandles(header, true);

            return(true);
        }
Пример #11
0
        void SendRefusedCommand(UdpEndPoint endpoint)
        {
            UdpBitStream stream = new UdpBitStream(GetWriteBuffer(), Config.DefaultMtu, UdpHeader.GetSize(this));

            stream.WriteByte((byte)UdpCommandType.Refused, 8);

            UdpHeader header = new UdpHeader();

            header.IsObject    = false;
            header.AckHistory  = 0;
            header.AckSequence = 1;
            header.ObjSequence = 1;
            header.Now         = 0;
            header.Pack(new UdpBitStream(stream.Data, Config.DefaultMtu, 0), this);

            if (Send(endpoint, stream.Data, UdpMath.BytesRequired(stream.Ptr)) == false)
            {
                // do something here?
            }
        }
Пример #12
0
        void SendRefusedCommand(UdpEndPoint endpoint)
        {
            UdpStream stream = GetWriteStream(Config.PacketSize << 3, HeaderBitSize);

            stream.WriteByte((byte)UdpCommandType.Refused, 8);

            UdpHeader header = new UdpHeader();

            header.IsObject    = false;
            header.AckHistory  = 0;
            header.AckSequence = 1;
            header.ObjSequence = 1;
            header.Now         = 0;
            header.Pack(stream, this);

            if (Send(endpoint, stream.Data, UdpMath.BytesRequired(stream.Ptr)) == false)
            {
                // do something here?
            }
        }
Пример #13
0
        internal void SendCommand(UdpCommandType cmd)
        {
            if (CheckCanSend(true) == UdpSendFailReason.None)
            {
                UdpBitStream stream = new UdpBitStream(socket.GetWriteBuffer(), mtu, UdpHeader.GetSize(socket));
                stream.WriteByte((byte)cmd, 8);

                UdpHeader header = MakeHeader(false);
                header.Pack(new UdpBitStream(stream.Data, mtu, 0), socket);

                UdpHandle handle = MakeHandle(ref header);
                handle.Object = null;

                if (SendStream(stream, handle, false) == false)
                {
                    // do something here?
                }

                stats.CommandSent += 1;
            }
        }
Пример #14
0
        void OnObjectReceived(UdpBitStream buffer)
        {
            EnsureClientIsConnected();

            if (CheckState(UdpConnectionState.Connected) == false)
            {
                return;
            }

            if (ParseHeader(ref buffer))
            {
                object obj = null;
                buffer.Ptr = UdpHeader.GetSize(socket);

                if (serializer.Unpack(ref buffer, ref obj))
                {
                    socket.Raise(UdpEvent.PUBLIC_OBJECT_RECEIVED, this, obj);
                }

                stats.PacketReceived();
            }
        }
Пример #15
0
        void AckHandles(UdpHeader header, bool updateRtt)
        {
            while (!sendWindow.Empty)
            {
                UdpHandle handle = sendWindow.Peek();

                int seqDistance = UdpMath.SeqDistance(handle.ObjSequence, header.AckSequence, UdpHeader.SEQ_PADD);
                if (seqDistance > 0)
                {
                    break;
                }

                if (handle.IsObject)
                {
                    if (seqDistance <= -socket.Config.AckRedundancy)
                    {
                        ObjectLost(handle.Object);
                    }

                    if ((header.AckHistory & (1UL << -seqDistance)) != 0UL)
                    {
                        ObjectDelivered(handle.Object);
                    }
                    else
                    {
                        ObjectLost(handle.Object);
                    }
                }

                if (seqDistance == 0 && header.AckTime > 0)
                {
                    UpdatePing(recvTime, handle.SendTime, header.AckTime);
                }

                sendWindow.Dequeue();
            }
        }
Пример #16
0
        bool ParseHeader(ref UdpBitStream buffer)
        {
            UdpHeader header = new UdpHeader();
            header.Unpack(new UdpBitStream(buffer.Data, buffer.Length, 0), socket);

            // Assign bit size
            if (socket.Config.WritePacketBitSize) {
                buffer.Length = header.BitSize;
            }

            int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD);

            // we have to be within window size
            if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) {
                ConnectionError(UdpConnectionError.SequenceOutOfBounds);
                return false;
            }

            // this is an old packet
            if (seqDistance <= 0)
                return false;

            // update receive history
            if (seqDistance >= socket.Config.AckRedundancy) {
                recvHistory = 1UL;
            } else {
                recvHistory = (recvHistory << seqDistance) | 1UL;
            }

            // update our receive stats
            recvSequence = header.ObjSequence;
            recvSinceLastSend += 1;

            // ack sent objects
            AckHandles(header, true);

            return true;
        }
Пример #17
0
        UdpHeader MakeHeader(bool isObject)
        {
            UdpHeader header = new UdpHeader();
            header.IsObject = isObject;
            header.AckHistory = recvHistory;
            header.AckSequence = recvSequence;
            header.ObjSequence = UdpMath.SeqNext(sendSequence, UdpHeader.SEQ_MASK);
            header.Now = socket.GetCurrentTime();

            if (recvTime > 0)
                header.AckTime = (ushort) UdpMath.Clamp(header.Now - recvTime, 0, socket.Config.MaxPing);

            return header;
        }
Пример #18
0
 UdpHandle MakeHandle(ref UdpHeader header)
 {
     UdpHandle handle = new UdpHandle();
     handle.IsObject = header.IsObject;
     handle.ObjSequence = header.ObjSequence;
     handle.SendTime = header.Now;
     return handle;
 }
Пример #19
0
        void AckHandles(UdpHeader header, bool updateRtt)
        {
            while (!sendWindow.Empty) {
                UdpHandle handle = sendWindow.Peek();

                int seqDistance = UdpMath.SeqDistance(handle.ObjSequence, header.AckSequence, UdpHeader.SEQ_PADD);
                if (seqDistance > 0) {
                    break;
                }

                if (handle.IsObject) {
                    if (seqDistance <= -socket.Config.AckRedundancy) {
                        ObjectLost(handle.Object);
                    }

                    if ((header.AckHistory & (1UL << -seqDistance)) != 0UL) {
                        ObjectDelivered(handle.Object);
                    } else {
                        ObjectLost(handle.Object);
                    }
                }

                if (seqDistance == 0 && header.AckTime > 0) {
                    UpdatePing(recvTime, handle.SendTime, header.AckTime);
                }

                sendWindow.Dequeue();
            }
        }