예제 #1
0
        internal NAKException(Reply reply)
        {
            var nak = Nak.ParseData(reply);

            ErrorCode   = nak.ErrorCode;
            ErrorString = nak.ErrorString;
            ExtraData   = nak.ExtraData;
        }
예제 #2
0
        /// <inheritdoc />
        public override string ToString()
        {
            if (Ack)
            {
                return("Ack");
            }

            return(Nak != null?Nak.ToString() : ReplyData?.ToString());
        }
예제 #3
0
        private void HandleNak(PlayerNetworkSession session, byte[] receiveBytes)
        {
            if (session == null)
            {
                return;
            }

            Player player = session.Player;

            if (player == null)
            {
                return;
            }

            Nak nak = Nak.CreateObject();

            nak.Decode(receiveBytes);

            int ackSeqNo   = nak.sequenceNumber.IntValue();
            int toAckSeqNo = nak.toSequenceNumber.IntValue();

            if (nak.onlyOneSequence == 1)
            {
                toAckSeqNo = ackSeqNo;
            }

            nak.PutPool();

            var queue = session.WaitingForAcksQueue;

            Log.DebugFormat("NAK from Player {0} ({5}) #{1}-{2} IsOnlyOne {3} Count={4}", player.Username, ackSeqNo, toAckSeqNo, nak.onlyOneSequence, nak.count, player.Rtt);

            for (int i = ackSeqNo; i <= toAckSeqNo; i++)
            {
                session.ErrorCount++;

                Datagram datagram;
                if (queue.TryRemove(i, out datagram))
                {
                    // RTT = RTT * 0.875 + rtt * 0.125
                    // RTTVar = RTTVar * 0.875 + abs(RTT - rtt)) * 0.125
                    // RTO = RTT + 4 * RTTVar
                    long rtt    = datagram.Timer.ElapsedMilliseconds;
                    long RTT    = player.Rtt;
                    long RTTVar = player.RttVar;

                    player.Rtt    = (long)(RTT * 0.875 + rtt * 0.125);
                    player.RttVar = (long)(RTTVar * 0.875 + Math.Abs(RTT - rtt) * 0.125);
                    player.Rto    = player.Rtt + 4 * player.RttVar + 10;                // SYNC time in the end
                    SendDatagram(session, datagram);
                }
                else
                {
                    Log.DebugFormat("NAK, no datagram #{0} to resend for {1}", i, player.Username);
                }
            }
        }
예제 #4
0
        private void HandleNak(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            PlayerNetworkSession session;

            if (!_playerSessions.TryGetValue(senderEndpoint, out session))
            {
                return;
            }

            Nak nak = Nak.CreateObject();

            nak.Decode(receiveBytes);

            int ackSeqNo   = nak.sequenceNumber.IntValue();
            int toAckSeqNo = nak.toSequenceNumber.IntValue();

            if (nak.onlyOneSequence == 1)
            {
                toAckSeqNo = ackSeqNo;
            }

            nak.PutPool();

            var queue = session.WaitingForAcksQueue;

            Log.WarnFormat("NAK from Player {0} ({5}) #{1}-{2} IsOnlyOne {3} Count={4}", session.Player.Username, ackSeqNo, toAckSeqNo, nak.onlyOneSequence, nak.count, session.Player.Rtt);

            for (int i = ackSeqNo; i <= toAckSeqNo; i++)
            {
                session.ErrorCount++;

                Datagram datagram;
                if (queue.TryRemove(i, out datagram))
                {
                    // RTT = RTT * 0.875 + rtt * 0.125
                    // RTTVar = RTTVar * 0.875 + abs(RTT - rtt)) * 0.125
                    // RTO = RTT + 4 * RTTVar
                    long rtt = datagram.Timer.ElapsedMilliseconds;
                    if (rtt > session.Player.Rto)
                    {
                        Log.WarnFormat("RTT bigger !!!!!!");
                    }
                    long RTT    = session.Player.Rtt;
                    long RTTVar = session.Player.RttVar;

                    session.Player.Rtt    = (long)(RTT * 0.875 + rtt * 0.125);
                    session.Player.RttVar = (long)(RTTVar * 0.875 + Math.Abs(RTT - rtt) * 0.125);
                    session.Player.Rto    = session.Player.Rtt + 4 * session.Player.RttVar + 10;                // SYNC time in the end

                    ThreadPool.QueueUserWorkItem(delegate(object data) { SendDatagram(senderEndpoint, (Datagram)data); }, datagram);
                }
                else
                {
                    Log.WarnFormat("No datagram #{0} to resend for {1}", i, session.Player.Username);
                }
            }
        }
예제 #5
0
		private void HandleNak(PlayerNetworkSession session, byte[] receiveBytes)
		{
			if (session == null) return;

			Player player = session.Player;
			if (player == null) return;

			Nak nak = Nak.CreateObject();
			nak.Reset();
			nak.Decode(receiveBytes);

			var queue = session.WaitingForAcksQueue;

			foreach (Tuple<int, int> range in nak.ranges)
			{
				ServerInfo.NumberOfNakReceive++;

				int start = range.Item1;
				int end = range.Item2;

				for (int i = start; i <= end; i++)
				{
					session.ErrorCount++;

					// HACK: Just to make sure we aren't getting unessecary load on the queue during heavy buffering.
					if (ServerInfo.AvailableBytes > 1000) continue;

					Datagram datagram;
					if (queue.TryGetValue(i, out datagram))
					{
						// RTT = RTT * 0.875 + rtt * 0.125
						// RTTVar = RTTVar * 0.875 + abs(RTT - rtt)) * 0.125
						// RTO = RTT + 4 * RTTVar
						long rtt = datagram.Timer.ElapsedMilliseconds;
						long RTT = player.Rtt;
						long RTTVar = player.RttVar;

						player.Rtt = (long) (RTT*0.875 + rtt*0.125);
						player.RttVar = (long) (RTTVar*0.875 + Math.Abs(RTT - rtt)*0.125);
						player.Rto = player.Rtt + 4*player.RttVar + 100; // SYNC time in the end

						//if (Log.IsDebugEnabled)
						//	Log.ErrorFormat("NAK, resending datagram #{0} for {1}, MTU: {2}", i, player.Username, session.Mtuize);

						//SendDatagram(session, datagram, false);
					}
					else
					{
						if (Log.IsDebugEnabled)
							//Log.WarnFormat("NAK, no datagram #{0} to resend for {1}", i, player.Username);
					}
				}
			}

			nak.PutPool();
		}
예제 #6
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="NakCommandBlock" /> class.
        /// </summary>
        /// <param name="error">
        ///     The error.
        /// </param>
        public NakCommandBlock(Nak error)
        {
            Cmd1 = Cmd1.Return;
            Cmd2 = (byte)Return.Nak;

            Data      = new byte[1];
            DataCount = Data.Length;

            Data[0] = (byte)(Data[0] | (1 << (int)error));
        }
예제 #7
0
        /// <summary>
        /// Send a command to alter the state of one or more outputs on a PD.
        /// </summary>
        /// <param name="connectionId">Identify the connection for communicating to the device.</param>
        /// <param name="address">Address assigned to the device.</param>
        /// <param name="outputControls">Data for one or more outputs to control.</param>
        /// <returns>Reply data that is returned after sending the command. There is the possibility of different replies can be returned from PD.</returns>
        public async Task <ReturnReplyData <OutputStatus> > OutputControl(Guid connectionId, byte address, OutputControls outputControls)
        {
            var reply = await SendCommand(connectionId,
                                          new OutputControlCommand(address, outputControls)).ConfigureAwait(false);

            return(new ReturnReplyData <OutputStatus>
            {
                Ack = reply.Type == ReplyType.Ack,
                Nak = reply.Type == ReplyType.Nak ? Nak.ParseData(reply.ExtractReplyData) : null,
                ReplyData = reply.Type == ReplyType.OutputStatusReport ? Model.ReplyData.OutputStatus.ParseData(reply.ExtractReplyData) : null
            });
        }
예제 #8
0
        /// <summary>
        /// Command that implements extended write mode to facilitate communications with an ISO 7816-4 based credential to a PD.
        /// </summary>
        /// <summary>Request to get the capabilities of the PD.</summary>
        /// <param name="connectionId">Identify the connection for communicating to the device.</param>
        /// <param name="address">Address assigned to the device.</param>
        /// <param name="extendedWrite">The extended write data.</param>
        /// <returns>Reply data that is returned after sending the command. There is the possibility of different replies can be returned from PD.</returns>
        public async Task <ReturnReplyData <ExtendedRead> > ExtendedWriteData(Guid connectionId, byte address,
                                                                              ExtendedWrite extendedWrite)
        {
            var reply = await SendCommand(connectionId,
                                          new ExtendedWriteDataCommand(address, extendedWrite)).ConfigureAwait(false);

            return(new ReturnReplyData <ExtendedRead>
            {
                Ack = reply.Type == ReplyType.Ack,
                Nak = reply.Type == ReplyType.Nak ? Nak.ParseData(reply.ExtractReplyData) : null,
                ReplyData = reply.Type == ReplyType.ExtendedRead ? ExtendedRead.ParseData(reply.ExtractReplyData) : null
            });
        }
예제 #9
0
        /// <summary>
        /// Send a  manufacture specific command to a PD.
        /// </summary>
        /// <param name="connectionId">Identify the connection for communicating to the device.</param>
        /// <param name="address">Address assigned to the device.</param>
        /// <param name="manufacturerSpecific">The manufacturer specific data.</param>
        /// <returns>Reply data that is returned after sending the command. There is the possibility of different replies can be returned from PD.</returns>
        public async Task <ReturnReplyData <ManufacturerSpecific> > ManufacturerSpecificCommand(Guid connectionId, byte address,
                                                                                                Model.CommandData.ManufacturerSpecific manufacturerSpecific)
        {
            var reply = await SendCommand(connectionId,
                                          new ManufacturerSpecificCommand(address, manufacturerSpecific)).ConfigureAwait(false);

            return(new ReturnReplyData <ManufacturerSpecific>
            {
                Ack = reply.Type == ReplyType.Ack,
                Nak = reply.Type == ReplyType.Nak ? Nak.ParseData(reply.ExtractReplyData) : null,
                ReplyData = reply.Type == ReplyType.ManufactureSpecific ? ManufacturerSpecific.ParseData(reply.ExtractReplyData) : null
            });
        }
예제 #10
0
        private void HandleNak(PlayerNetworkSession session, byte[] receiveBytes)
        {
            if (session == null)
            {
                return;
            }

            Nak nak = Nak.CreateObject();

            nak.Reset();
            nak.Decode(receiveBytes);

            var queue = session.WaitingForAcksQueue;

            foreach (Tuple <int, int> range in nak.ranges)
            {
                Interlocked.Increment(ref ServerInfo.NumberOfNakReceive);

                int start = range.Item1;
                int end   = range.Item2;

                for (int i = start; i <= end; i++)
                {
                    if (queue.TryGetValue(i, out var datagram))
                    {
                        CalculateRto(session, datagram);

                        datagram.RetransmitImmediate = true;
                    }
                    else
                    {
                        if (Log.IsDebugEnabled)
                        {
                            Log.WarnFormat("NAK, no datagram #{0} for {1}", i, session.Username);
                        }
                    }
                }
            }

            nak.PutPool();
        }
예제 #11
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            //_serverEndpoint = senderEndpoint;
            byte msgId = receiveBytes[0];

            if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes) msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null) return;

                TraceReceive(message);

                switch (msgIdType)
                {
                    case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                    {
                        //Thread.Sleep(50);
                        UnconnectedPong incoming = (UnconnectedPong) message;
                        SendOpenConnectionRequest1();

                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                    {
                        //Thread.Sleep(50);
                        OpenConnectionReply1 incoming = (OpenConnectionReply1) message;
                        if (incoming.mtuSize < _mtuSize) throw new Exception("Error:" + incoming.mtuSize);
                        SendOpenConnectionRequest2();
                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                    {
                        OpenConnectionReply2 incoming = (OpenConnectionReply2) message;
                        //Thread.Sleep(50);
                        //_mtuSize = incoming.mtuSize;
                        SendConnectionRequest();
                        break;
                    }
                    case DefaultMessageIdTypes.ID_CONNECTION_REQUEST_ACCEPTED:
                    {
                        //Thread.Sleep(50);
                        SendNewIncomingConnection();
                        var t1 = new Timer(state => SendConnectedPing(), null, 0, 5000);
                        //Thread.Sleep(50);
                        SendLogin("Client12");
                        break;
                    }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    ConnectedPackage package = ConnectedPackage.CreateObject();
                    package.Decode(receiveBytes);
                    Log.Debug(">\tReceive Datagram #" + package._datagramSequenceNumber.IntValue());

                    var messages = package.Messages;

                    //Log.Debug("Received package: #" + package._datagramSequenceNumber.IntValue());

                    Reliability reliability = package._reliability;
                    //Log.InfoFormat("Reliability: {0}", reliability);

                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        // Send ACK
                        Acks ack = new Acks();
                        ack.acks.Add(package._datagramSequenceNumber.IntValue());
                        byte[] data = ack.Encode();
                        //Log.Debug("<\tSend ACK on #" + package._datagramSequenceNumber.IntValue());
                        SendData(data, senderEndpoint);
                    }

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            SplitPartPackage splitMessage = message as SplitPartPackage;

                            int spId = package._splitPacketId;
                            int spIdx = package._splitPacketIndex;
                            int spCount = package._splitPacketCount;

                            Log.DebugFormat("Got split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);

                            if (!_splits.ContainsKey(spId))
                            {
                                _splits[spId] = new SplitPartPackage[spCount];
                            }
                            else
                            {
                                Log.WarnFormat("Resent split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);
                            }

                            SplitPartPackage[] spPackets = _splits[spId];
                            spPackets[spIdx] = splitMessage;

                            bool haveEmpty = false;
                            for (int i = 0; i < spPackets.Length; i++)
                            {
                                haveEmpty = haveEmpty || spPackets[i] == null;
                            }

                            if (!haveEmpty)
                            {
                                Log.WarnFormat("Got all {0} split packages for split ID: {1}", spCount, spId);

                                MemoryStream stream = new MemoryStream();
                                for (int i = 0; i < spPackets.Length; i++)
                                {
                                    byte[] buf = spPackets[i].Message;
                                    stream.Write(buf, 0, buf.Length);
                                }

                                try
                                {
                                    byte[] buffer = stream.ToArray();
                                    var fullMessage = PackageFactory.CreatePackage(buffer[0], buffer) ?? new UnknownPackage(buffer[0], buffer);
                                    Log.Debug("Processing split-message");
                                    HandlePackage(fullMessage, senderEndpoint);
                                    fullMessage.PutPool();
                                }
                                catch (Exception e)
                                {
                                    Log.Warn("When processing split-message", e);
                                }
                            }

                            message.PutPool();
                            return;
                        }

                        {
                            message.Timer.Restart();
                            HandlePackage(message, senderEndpoint);
                            //message.PutPool();
                        }
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);

                    Log.Warn("!!!! NAK !!!!!" + nak.sequenceNumber.IntValue());
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }
예제 #12
0
 public NakReplyEventArgs(Guid connectionId, byte address, Nak nak)
 {
     ConnectionId = connectionId;
     Address      = address;
     Nak          = nak;
 }
예제 #13
0
        internal virtual void OnReplyReceived(Reply reply)
        {
            {
                var handler = ReplyReceived;
                handler?.Invoke(this, new ReplyEventArgs {
                    Reply = reply
                });
            }

            switch (reply.Type)
            {
            case ReplyType.Nak:
            {
                var handler = NakReplyReceived;
                handler?.Invoke(this,
                                new NakReplyEventArgs(reply.ConnectionId, reply.Address, Nak.ParseData(reply)));
                break;
            }

            case ReplyType.LocalStatusReport:
            {
                var handler = LocalStatusReportReplyReceived;
                handler?.Invoke(this,
                                new LocalStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                    Model.ReplyData.LocalStatus.ParseData(reply)));
                break;
            }

            case ReplyType.InputStatusReport:
            {
                var handler = InputStatusReportReplyReceived;
                handler?.Invoke(this,
                                new InputStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                    Model.ReplyData.InputStatus.ParseData(reply)));
                break;
            }

            case ReplyType.OutputStatusReport:
            {
                var handler = OutputStatusReportReplyReceived;
                handler?.Invoke(this,
                                new OutputStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                     Model.ReplyData.OutputStatus.ParseData(reply)));
                break;
            }

            case ReplyType.ReaderStatusReport:
            {
                var handler = ReaderStatusReportReplyReceived;
                handler?.Invoke(this,
                                new ReaderStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                     Model.ReplyData.ReaderStatus.ParseData(reply)));
                break;
            }

            case ReplyType.RawReaderData:
            {
                var handler = RawCardDataReplyReceived;
                handler?.Invoke(this,
                                new RawCardDataReplyEventArgs(reply.ConnectionId, reply.Address, RawCardData.ParseData(reply)));
                break;
            }
            }
        }
예제 #14
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            byte msgId = receiveBytes[0];

            if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes) msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null) return;

                TraceReceive(message);

                switch (msgIdType)
                {
                    case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                    {
                        UnconnectedPong incoming = (UnconnectedPong) message;
                        HaveServer = true;
                        SendOpenConnectionRequest1();

                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                    {
                        OpenConnectionReply1 incoming = (OpenConnectionReply1) message;
                        _mtuSize = incoming.mtuSize;
                        //if (incoming.mtuSize < _mtuSize) throw new Exception("Error:" + incoming.mtuSize);
                        SendOpenConnectionRequest2();
                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                    {
                        OpenConnectionReply2 incoming = (OpenConnectionReply2) message;
                        //_mtuSize = incoming.mtuSize;
                        SendConnectionRequest();
                        break;
                    }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    //ConnectedPackage package = ConnectedPackage.CreateObject();
                    ConnectedPackage package = new ConnectedPackage();
                    package.Decode(receiveBytes);
                    header = package._datagramHeader;
                    //Log.Debug($"> Datagram #{header.datagramSequenceNumber}, {package._hasSplit}, {package._splitPacketId}, {package._reliability}, {package._reliableMessageNumber}, {package._sequencingIndex}, {package._orderingChannel}, {package._orderingIndex}");

                    var messages = package.Messages;

                    //Reliability reliability = package._reliability;
                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        if (header.datagramSequenceNumber == 1000)
                        {
                            Log.Error("Datagram 1000 ignored");
                        }
                        else
                        {
                            // Send ACK
                            Acks ack = new Acks();
                            ack.acks.Add(package._datagramSequenceNumber.IntValue());
                            byte[] data = ack.Encode();
                            //Log.Info("Send ACK #" + package._datagramSequenceNumber.IntValue());
                            SendData(data, senderEndpoint);
                        }
                    }

                    //if (LoginSent) return; //HACK

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            lock (Session.SyncRoot)
                            {
                                HandleSplitMessage(Session, package, (SplitPartPackage) message);
                            }

                            continue;
                        }

                        message.Timer.Restart();
                        HandlePackage(message);
                        message.PutPool();
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }
예제 #15
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            byte msgId = receiveBytes[0];

            if (msgId <= (byte)DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null)
                {
                    return;
                }

                TraceReceive(message);

                switch (msgIdType)
                {
                case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                {
                    UnconnectedPong incoming = (UnconnectedPong)message;
                    HaveServer = true;
                    SendOpenConnectionRequest1();

                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                {
                    OpenConnectionReply1 incoming = (OpenConnectionReply1)message;
                    _mtuSize = incoming.mtuSize;
                    //if (incoming.mtuSize < _mtuSize) throw new Exception("Error:" + incoming.mtuSize);
                    SendOpenConnectionRequest2();
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                {
                    OpenConnectionReply2 incoming = (OpenConnectionReply2)message;
                    //_mtuSize = incoming.mtuSize;
                    SendConnectionRequest();
                    break;
                }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    //ConnectedPackage package = ConnectedPackage.CreateObject();
                    ConnectedPackage package = new ConnectedPackage();
                    package.Decode(receiveBytes);
                    header = package._datagramHeader;
                    //Log.Debug(">\tReceive Datagram #" + package._datagramSequenceNumber.IntValue());
                    Log.Debug($"> Datagram #{header.datagramSequenceNumber}, {package._hasSplit}, {package._splitPacketId}, {package._reliability}, {package._reliableMessageNumber}, {package._sequencingIndex}, {package._orderingChannel}, {package._orderingIndex}");

                    var messages = package.Messages;

                    //Reliability reliability = package._reliability;
                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        if (header.datagramSequenceNumber == 1000)
                        {
                            Log.Error("Datagram 1000 ignored");
                        }
                        else
                        {
                            // Send ACK
                            Acks ack = new Acks();
                            ack.acks.Add(package._datagramSequenceNumber.IntValue());
                            byte[] data = ack.Encode();
                            //Log.Info("Send ACK #" + package._datagramSequenceNumber.IntValue());
                            SendData(data, senderEndpoint);
                        }
                    }

                    //if (LoginSent) return; //HACK

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            lock (Session.SyncRoot)
                            {
                                HandleSplitMessage(Session, package, (SplitPartPackage)message);
                            }

                            continue;
                        }

                        message.Timer.Restart();
                        HandlePackage(message);
                        message.PutPool();
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }
예제 #16
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            byte msgId = receiveBytes[0];

            //Log.DebugFormat("Recieve {0} 0x{0:x2} len: {1}", msgId, receiveBytes.Length);

            if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes) msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null) return;

                TraceReceive(message);

                switch (msgIdType)
                {
                    case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                    {
                        UnconnectedPong incoming = (UnconnectedPong) message;
                        SendOpenConnectionRequest1();

                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                    {
                        OpenConnectionReply1 incoming = (OpenConnectionReply1) message;
                        _mtuSize = incoming.mtuSize;
                        //if (incoming.mtuSize < _mtuSize) throw new Exception("Error:" + incoming.mtuSize);
                        SendOpenConnectionRequest2();
                        break;
                    }
                    case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                    {
                        OpenConnectionReply2 incoming = (OpenConnectionReply2) message;
                        //_mtuSize = incoming.mtuSize;
                        SendConnectionRequest();
                        break;
                    }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    //ConnectedPackage package = ConnectedPackage.CreateObject();
                    ConnectedPackage package = new ConnectedPackage();
                    package.Decode(receiveBytes);
                    //Log.Debug(">\tReceive Datagram #" + package._datagramSequenceNumber.IntValue());

                    var messages = package.Messages;

                    //Reliability reliability = package._reliability;
                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        // Send ACK
                        Acks ack = new Acks();
                        ack.acks.Add(package._datagramSequenceNumber.IntValue());
                        byte[] data = ack.Encode();
                        //Log.Info("Send ACK #" + package._datagramSequenceNumber.IntValue());
                        SendData(data, senderEndpoint);
                    }

                    //if (LoginSent) return; //HACK

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            lock (Session.SyncRoot)
                            {
                                var splits = Session.Splits;
                                SplitPartPackage splitMessage = message as SplitPartPackage;

                                int spId = package._splitPacketId;
                                int spIdx = package._splitPacketIndex;
                                int spCount = package._splitPacketCount;

                                Log.DebugFormat("Got split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);

                                if (!splits.ContainsKey(spId))
                                {
                                    splits.Add(spId, new SplitPartPackage[spCount]);
                                }

                                SplitPartPackage[] spPackets = splits[spId];
                                if (spIdx < 0 || spIdx >= spPackets.Length)
                                {
                                    Log.DebugFormat("Unexpeted split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);
                                    continue;
                                }

                                if (splitMessage.Message == null)
                                {
                                    Log.DebugFormat("Empty split package");
                                    continue;
                                }

                                spPackets[spIdx] = splitMessage;

                                bool haveEmpty = false;
                                for (int i = 0; i < spPackets.Length; i++)
                                {
                                    haveEmpty = haveEmpty || spPackets[i] == null;
                                }

                                if (!haveEmpty)
                                {
                                    Log.DebugFormat("Got all {0} split packages for split ID: {1}", spCount, spId);

                                    MemoryStream stream = new MemoryStream();
                                    for (int i = 0; i < spPackets.Length; i++)
                                    {
                                        byte[] buf = spPackets[i].Message;
                                        stream.Write(buf, 0, buf.Length);
                                    }

                                    try
                                    {
                                        byte[] buffer = stream.ToArray();
                                        Log.DebugFormat("Processing split-message 0x{1:x2}, lenght={0}", buffer.Length, buffer[0]);
                                        Package fullMessage = PackageFactory.CreatePackage(buffer[0], buffer) ?? new UnknownPackage(buffer[0], buffer);
                                        HandlePackage(fullMessage, senderEndpoint);
                                        fullMessage.PutPool();
                                        continue;
                                    }
                                    catch (Exception e)
                                    {
                                        Log.Error("When processing split-message", e);
                                    }
                                }

                                message.PutPool();
                                continue;
                            }
                        }
                        else
                        {
                            message.Timer.Restart();
                            HandlePackage(message, senderEndpoint);
                            message.PutPool();
                        }
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }
예제 #17
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            byte msgId = receiveBytes[0];

            //Log.DebugFormat("Recieve {0} 0x{0:x2} len: {1}", msgId, receiveBytes.Length);

            if (msgId <= (byte)DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null)
                {
                    return;
                }

                TraceReceive(message);

                switch (msgIdType)
                {
                case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                {
                    UnconnectedPong incoming = (UnconnectedPong)message;
                    SendOpenConnectionRequest1();

                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                {
                    OpenConnectionReply1 incoming = (OpenConnectionReply1)message;
                    _mtuSize = incoming.mtuSize;
                    //if (incoming.mtuSize < _mtuSize) throw new Exception("Error:" + incoming.mtuSize);
                    SendOpenConnectionRequest2();
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                {
                    OpenConnectionReply2 incoming = (OpenConnectionReply2)message;
                    //_mtuSize = incoming.mtuSize;
                    SendConnectionRequest();
                    break;
                }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    //ConnectedPackage package = ConnectedPackage.CreateObject();
                    ConnectedPackage package = new ConnectedPackage();
                    package.Decode(receiveBytes);
                    //Log.Debug(">\tReceive Datagram #" + package._datagramSequenceNumber.IntValue());

                    var messages = package.Messages;

                    //Reliability reliability = package._reliability;
                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        // Send ACK
                        Acks ack = new Acks();
                        ack.acks.Add(package._datagramSequenceNumber.IntValue());
                        byte[] data = ack.Encode();
                        //Log.Info("Send ACK #" + package._datagramSequenceNumber.IntValue());
                        SendData(data, senderEndpoint);
                    }

                    //if (LoginSent) return; //HACK

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            lock (Session.SyncRoot)
                            {
                                var splits = Session.Splits;
                                SplitPartPackage splitMessage = message as SplitPartPackage;

                                int spId    = package._splitPacketId;
                                int spIdx   = package._splitPacketIndex;
                                int spCount = package._splitPacketCount;

                                Log.DebugFormat("Got split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);

                                if (!splits.ContainsKey(spId))
                                {
                                    splits.Add(spId, new SplitPartPackage[spCount]);
                                }

                                SplitPartPackage[] spPackets = splits[spId];
                                if (spIdx < 0 || spIdx >= spPackets.Length)
                                {
                                    Log.DebugFormat("Unexpeted split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);
                                    continue;
                                }

                                if (splitMessage.Message == null)
                                {
                                    Log.DebugFormat("Empty split package");
                                    continue;
                                }

                                spPackets[spIdx] = splitMessage;

                                bool haveEmpty = false;
                                for (int i = 0; i < spPackets.Length; i++)
                                {
                                    haveEmpty = haveEmpty || spPackets[i] == null;
                                }

                                if (!haveEmpty)
                                {
                                    Log.DebugFormat("Got all {0} split packages for split ID: {1}", spCount, spId);

                                    MemoryStream stream = new MemoryStream();
                                    for (int i = 0; i < spPackets.Length; i++)
                                    {
                                        byte[] buf = spPackets[i].Message;
                                        stream.Write(buf, 0, buf.Length);
                                    }

                                    try
                                    {
                                        byte[] buffer = stream.ToArray();
                                        Log.DebugFormat("Processing split-message 0x{1:x2}, lenght={0}", buffer.Length, buffer[0]);
                                        Package fullMessage = PackageFactory.CreatePackage(buffer[0], buffer) ?? new UnknownPackage(buffer[0], buffer);
                                        HandlePackage(fullMessage, senderEndpoint);
                                        fullMessage.PutPool();
                                        continue;
                                    }
                                    catch (Exception e)
                                    {
                                        Log.Error("When processing split-message", e);
                                    }
                                }

                                message.PutPool();
                                continue;
                            }
                        }
                        else
                        {
                            message.Timer.Restart();
                            HandlePackage(message, senderEndpoint);
                            message.PutPool();
                        }
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);

                    Log.Warn("!!!! NAK !!!!!" + nak.sequenceNumber.IntValue());
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }
예제 #18
0
        internal virtual void OnReplyReceived(Reply reply)
        {
            {
                var handler = ReplyReceived;
                handler?.Invoke(this, new ReplyEventArgs {
                    Reply = reply
                });
            }

            switch (reply.Type)
            {
            case ReplyType.Nak:
            {
                var handler = NakReplyReceived;
                handler?.Invoke(this,
                                new NakReplyEventArgs(reply.ConnectionId, reply.Address,
                                                      Nak.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.LocalStatusReport:
            {
                var handler = LocalStatusReportReplyReceived;
                handler?.Invoke(this,
                                new LocalStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                    Model.ReplyData.LocalStatus.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.InputStatusReport:
            {
                var handler = InputStatusReportReplyReceived;
                handler?.Invoke(this,
                                new InputStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                    Model.ReplyData.InputStatus.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.OutputStatusReport:
            {
                var handler = OutputStatusReportReplyReceived;
                handler?.Invoke(this,
                                new OutputStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                     Model.ReplyData.OutputStatus.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.ReaderStatusReport:
            {
                var handler = ReaderStatusReportReplyReceived;
                handler?.Invoke(this,
                                new ReaderStatusReportReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                     Model.ReplyData.ReaderStatus.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.RawReaderData:
            {
                var handler = RawCardDataReplyReceived;
                handler?.Invoke(this,
                                new RawCardDataReplyEventArgs(reply.ConnectionId, reply.Address,
                                                              RawCardData.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.ManufactureSpecific:
            {
                var handler = ManufacturerSpecificReplyReceived;
                handler?.Invoke(this,
                                new ManufacturerSpecificReplyEventArgs(reply.ConnectionId, reply.Address,
                                                                       ManufacturerSpecific.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.ExtendedRead:
            {
                var handler = ExtendedReadReplyReceived;
                handler?.Invoke(this,
                                new ExtendedReadReplyEventArgs(reply.ConnectionId, reply.Address,
                                                               ExtendedRead.ParseData(reply.ExtractReplyData)));
                break;
            }

            case ReplyType.PIVData:
            {
                var handler = PIVDataReplyReceived;
                handler?.Invoke(this,
                                new PIVDataReplyEventArgs(reply.ConnectionId, reply.Address,
                                                          PIVData.ParseData(reply.ExtractReplyData)));
                break;
            }
            }
        }
예제 #19
0
        private void HandleNak(PlayerNetworkSession session, byte[] receiveBytes)
        {
            if (session == null)
            {
                return;
            }

            Nak nak = Nak.CreateObject();

            nak.Reset();
            nak.Decode(receiveBytes);

            var queue = session.WaitingForAcksQueue;

            foreach (Tuple <int, int> range in nak.ranges)
            {
                Interlocked.Increment(ref ServerInfo.NumberOfNakReceive);

                int start = range.Item1;
                int end   = range.Item2;

                for (int i = start; i <= end; i++)
                {
                    session.ErrorCount++;

                    // HACK: Just to make sure we aren't getting unessecary load on the queue during heavy buffering.
                    //if (ServerInfo.AvailableBytes > 1000) continue;

                    Datagram datagram;
                    //if (queue.TryRemove(i, out datagram))
                    if (!session.Evicted && queue.TryRemove(i, out datagram))
                    {
                        // RTT = RTT * 0.875 + rtt * 0.125
                        // RTTVar = RTTVar * 0.875 + abs(RTT - rtt)) * 0.125
                        // RTO = RTT + 4 * RTTVar
                        long rtt    = datagram.Timer.ElapsedMilliseconds;
                        long RTT    = session.Rtt;
                        long RTTVar = session.RttVar;

                        session.Rtt    = (long)(RTT * 0.875 + rtt * 0.125);
                        session.RttVar = (long)(RTTVar * 0.875 + Math.Abs(RTT - rtt) * 0.125);
                        session.Rto    = session.Rtt + 4 * session.RttVar + 100;                    // SYNC time in the end

                        FastThreadPool.QueueUserWorkItem(delegate
                        {
                            var dgram = (Datagram)datagram;
                            if (Log.IsDebugEnabled)
                            {
                                Log.WarnFormat("NAK, resent datagram #{0} for {1}", dgram.Header.datagramSequenceNumber, session.Username);
                            }
                            SendDatagram(session, dgram);
                            Interlocked.Increment(ref ServerInfo.NumberOfResends);
                        });
                    }
                    else
                    {
                        if (Log.IsDebugEnabled)
                        {
                            Log.WarnFormat("NAK, no datagram #{0} for {1}", i, session.Username);
                        }
                    }
                }
            }

            nak.PutPool();
        }
예제 #20
0
        /// <summary>
        ///     Processes a message.
        /// </summary>
        /// <param name="receiveBytes">The received bytes.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        /// <exception cref="System.Exception">Receive ERROR, NAK in wrong place</exception>
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            //_serverEndpoint = senderEndpoint;
            byte msgId = receiveBytes[0];

            if (msgId <= (byte)DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId;

                Package message = PackageFactory.CreatePackage(msgId, receiveBytes);

                if (message == null)
                {
                    return;
                }

                TraceReceive(message);

                switch (msgIdType)
                {
                case DefaultMessageIdTypes.ID_UNCONNECTED_PONG:
                {
                    //Thread.Sleep(50);
                    UnconnectedPong incoming = (UnconnectedPong)message;
                    SendOpenConnectionRequest1();

                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1:
                {
                    //Thread.Sleep(50);
                    OpenConnectionReply1 incoming = (OpenConnectionReply1)message;
                    if (incoming.mtuSize < _mtuSize)
                    {
                        throw new Exception("Error:" + incoming.mtuSize);
                    }
                    SendOpenConnectionRequest2();
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2:
                {
                    OpenConnectionReply2 incoming = (OpenConnectionReply2)message;
                    //Thread.Sleep(50);
                    //_mtuSize = incoming.mtuSize;
                    SendConnectionRequest();
                    break;
                }

                case DefaultMessageIdTypes.ID_CONNECTION_REQUEST_ACCEPTED:
                {
                    //Thread.Sleep(50);
                    SendNewIncomingConnection();
                    var t1 = new Timer(state => SendConnectedPing(), null, 0, 5000);
                    //Thread.Sleep(50);
                    SendLogin("Client12");
                    break;
                }
                }
            }
            else
            {
                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    ConnectedPackage package = ConnectedPackage.CreateObject();
                    package.Decode(receiveBytes);
                    Log.Debug(">\tReceive Datagram #" + package._datagramSequenceNumber.IntValue());

                    var messages = package.Messages;

                    //Log.Debug("Received package: #" + package._datagramSequenceNumber.IntValue());

                    Reliability reliability = package._reliability;
                    //Log.InfoFormat("Reliability: {0}", reliability);

                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        // Send ACK
                        Acks ack = new Acks();
                        ack.acks.Add(package._datagramSequenceNumber.IntValue());
                        byte[] data = ack.Encode();
                        //Log.Debug("<\tSend ACK on #" + package._datagramSequenceNumber.IntValue());
                        SendData(data, senderEndpoint);
                    }

                    foreach (var message in messages)
                    {
                        if (message is SplitPartPackage)
                        {
                            SplitPartPackage splitMessage = message as SplitPartPackage;

                            int spId    = package._splitPacketId;
                            int spIdx   = package._splitPacketIndex;
                            int spCount = package._splitPacketCount;

                            Log.DebugFormat("Got split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);

                            if (!_splits.ContainsKey(spId))
                            {
                                _splits[spId] = new SplitPartPackage[spCount];
                            }
                            else
                            {
                                Log.WarnFormat("Resent split package {2} (of {0}) for split ID: {1}", spCount, spId, spIdx);
                            }

                            SplitPartPackage[] spPackets = _splits[spId];
                            spPackets[spIdx] = splitMessage;

                            bool haveEmpty = false;
                            for (int i = 0; i < spPackets.Length; i++)
                            {
                                haveEmpty = haveEmpty || spPackets[i] == null;
                            }

                            if (!haveEmpty)
                            {
                                Log.WarnFormat("Got all {0} split packages for split ID: {1}", spCount, spId);

                                MemoryStream stream = new MemoryStream();
                                for (int i = 0; i < spPackets.Length; i++)
                                {
                                    byte[] buf = spPackets[i].Message;
                                    stream.Write(buf, 0, buf.Length);
                                }

                                try
                                {
                                    byte[] buffer      = stream.ToArray();
                                    var    fullMessage = PackageFactory.CreatePackage(buffer[0], buffer) ?? new UnknownPackage(buffer[0], buffer);
                                    Log.Debug("Processing split-message");
                                    HandlePackage(fullMessage, senderEndpoint);
                                    fullMessage.PutPool();
                                }
                                catch (Exception e)
                                {
                                    Log.Warn("When processing split-message", e);
                                }
                            }

                            message.PutPool();
                            return;
                        }

                        {
                            message.Timer.Restart();
                            HandlePackage(message, senderEndpoint);
                            //message.PutPool();
                        }
                    }

                    //package.PutPool();
                }
                else if (header.isPacketPair)
                {
                    Log.Warn("header.isPacketPair");
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(receiveBytes, senderEndpoint);
                }
                else if (header.isNAK && header.isValid)
                {
                    Nak nak = new Nak();
                    nak.Decode(receiveBytes);

                    Log.Warn("!!!! NAK !!!!!" + nak.sequenceNumber.IntValue());
                    HandleNak(receiveBytes, senderEndpoint);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
                else
                {
                    Log.Warn("!! WHAT THE F");
                }
            }
        }