public Datagram() { MessageParts = new List <MessagePart>(50); Header = new DatagramHeader { isValid = true, needsBAndAs = true, //datagramSequenceNumber = datagramSequenceNumber }; _buf = new MemoryStream(new byte[1600], 0, 1600, true, true); }
private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint) { byte msgId = receiveBytes[0]; if (msgId == 0xFE) { Log.InfoFormat("A query detected from: {0}", senderEndpoint.Address); HandleQuery(receiveBytes, senderEndpoint); } else if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM) { HandleRakNetMessage(receiveBytes, senderEndpoint, msgId); } else { PlayerNetworkSession playerSession; if (!_playerSessions.TryGetValue(senderEndpoint, out playerSession)) { //Log.DebugFormat("Receive MCPE message 0x{1:x2} without session {0}", senderEndpoint.Address, msgId); //if (!_badPacketBans.ContainsKey(senderEndpoint.Address)) //{ // _badPacketBans.Add(senderEndpoint.Address, true); //} return; } Player player = playerSession.Player; if (player == null) { Log.ErrorFormat("Receive MCPE message 0x{1:x2} without player {0}. Session removed.", senderEndpoint.Address, msgId); _playerSessions.TryRemove(senderEndpoint, out playerSession); //if (!_badPacketBans.ContainsKey(senderEndpoint.Address)) //{ // _badPacketBans.Add(senderEndpoint.Address, true); //} return; } if (playerSession.Evicted) return; playerSession.LastUpdatedTime = DateTime.UtcNow; 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(); try { package.Decode(receiveBytes); } catch (Exception e) { player.Disconnect("Bad package received from client."); //if (Log.IsDebugEnabled) { Log.Warn("Bad packet " + receiveBytes[0], e); } GreylistManager.Blacklist(senderEndpoint.Address); return; } // IF reliable code below is enabled, useItem start sending doubles // for some unknown reason. //Reliability reliability = package._reliability; //if (reliability == Reliability.Reliable // || reliability == Reliability.ReliableSequenced // || reliability == Reliability.ReliableOrdered // ) { EnqueueAck(playerSession, package._datagramSequenceNumber); } DelayedProcessing(playerSession, package); package.PutPool(); } else if (header.isACK && header.isValid) { HandleAck(playerSession, receiveBytes); } else if (header.isNAK && header.isValid) { HandleNak(playerSession, receiveBytes); } else if (!header.isValid) { Log.Warn("!!!! ERROR, Invalid header !!!!!"); } } }
protected override void EncodePackage() { _buffer.Position = 0; byte[] encodedMessage = Buffer; if (Buffer == null) { encodedMessage = Messages.First().Encode(); } MessageLength = encodedMessage.Length; // Datagram header if (_datagramHeader == null) { _datagramHeader = new DatagramHeader(0x8c); } if (_splitPacketCount > 1 && _splitPacketIndex > 0) { Write((byte)0x8c); } else { Write((byte)0x84); } Write(_datagramSequenceNumber); // foreach message // Message header byte rely = (byte)_reliability; Write((byte)((rely << 5) | (_hasSplit ? Convert.ToByte("00010000", 2) : 0x00))); Write((short)(MessageLength * 8)); // length if (_reliability == Reliability.Reliable || _reliability == Reliability.ReliableOrdered || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableWithAckReceipt || _reliability == Reliability.ReliableOrderedWithAckReceipt ) { Write(_reliableMessageNumber); } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableOrdered || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrderedWithAckReceipt ) { Write(_orderingIndex); Write(_orderingChannel); } if (_hasSplit) { Write(_splitPacketCount); Write(_splitPacketId); Write(_splitPacketIndex); } // Message body Write(encodedMessage); }
protected override void DecodePackage() { Messages = new List <Package>(); _buffer.Position = 0; _datagramHeader = new DatagramHeader(ReadByte()); _datagramSequenceNumber = ReadLittle(); while (_buffer.Position != _buffer.Length) { byte flags = ReadByte(); _reliability = (Reliability)((flags & Convert.ToByte("011100000", 2)) >> 5); int hasSplitPacket = ((flags & Convert.ToByte("00010000", 2)) >> 0); short dataBitLength = ReadShort(); if (_reliability == Reliability.Reliable || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered ) { _reliableMessageNumber = ReadLittle(); } else { _reliableMessageNumber = -1; } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced ) { _sequencingIndex = ReadLittle(); } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered || _reliability == Reliability.ReliableOrderedWithAckReceipt ) { _orderingIndex = ReadLittle(); _orderingChannel = ReadByte(); // flags } else { _orderingChannel = 0; } if (hasSplitPacket != 0) { _splitPacketCount = ReadInt(); _splitPacketId = ReadShort(); _splitPacketIndex = ReadInt(); } else { _splitPacketCount = 0; } // Slurp the payload MessageLength = (int)Math.Ceiling((((double)dataBitLength) / 8)); byte[] internalBuffer = ReadBytes(MessageLength); if (hasSplitPacket != 0) { Messages.Add(new SplitPartPackage(internalBuffer[0], internalBuffer)); return; } Messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer)); if (MessageLength != internalBuffer.Length) { Debug.WriteLine("Missmatch of requested lenght, and actual read lenght"); } } }
protected override void DecodePackage() { Messages = new List <Package>(); _buffer.Position = 0; _datagramHeader = new DatagramHeader(ReadByte()); _datagramSequenceNumber = ReadLittle(); _datagramHeader.datagramSequenceNumber = _datagramSequenceNumber; while (_buffer.Position < _buffer.Length) { byte flags = ReadByte(); _reliability = (Reliability)((flags & Convert.ToByte("011100000", 2)) >> 5); _hasSplit = ((flags & Convert.ToByte("00010000", 2)) > 0); short dataBitLength = ReadShort(); if (_reliability == Reliability.Reliable || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered ) { _reliableMessageNumber = ReadLittle(); } else { _reliableMessageNumber = -1; } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced ) { _sequencingIndex = ReadLittle(); } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered || _reliability == Reliability.ReliableOrderedWithAckReceipt ) { _orderingIndex = ReadLittle(); _orderingChannel = ReadByte(); // flags } else { _orderingIndex = 0; _orderingChannel = 0; } if (_hasSplit) { _splitPacketCount = ReadInt(); _splitPacketId = ReadShort(); _splitPacketIndex = ReadInt(); } else { _splitPacketCount = -1; _splitPacketId = -1; _splitPacketIndex = -1; } // Slurp the payload MessageLength = (int)Math.Ceiling((((double)dataBitLength) / 8)); byte[] internalBuffer = ReadBytes(MessageLength); if (_hasSplit) { //Log.Debug("Recieve split\n" + HexDump(internalBuffer)); SplitPartPackage splitPartPackage = SplitPartPackage.CreateObject(); splitPartPackage.Id = internalBuffer[0]; splitPartPackage.Message = internalBuffer; Messages.Add(splitPartPackage); return; } byte id = internalBuffer[0]; if (id == 0x8e) { id = internalBuffer[1]; } Package package = PackageFactory.CreatePackage(id, internalBuffer) ?? new UnknownPackage(id, internalBuffer); package.DatagramSequenceNumber = _datagramSequenceNumber; package.ReliableMessageNumber = _reliableMessageNumber; package.OrderingChannel = _orderingChannel; package.OrderingIndex = _orderingIndex; if (!(package is McpeBatch)) { Log.Debug($"Raw: {package.DatagramSequenceNumber} {package.ReliableMessageNumber} {package.OrderingIndex} {package.GetType().Name} 0x{package.Id:x2} \n{HexDump(internalBuffer)}"); } Messages.Add(package); if (MessageLength != internalBuffer.Length) { Debug.WriteLine("Missmatch of requested lenght, and actual read lenght"); } } }
/// <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 == 0xFE) { Log.WarnFormat("A query detected from: {0}", senderEndpoint.Address); HandleQuery(receiveBytes, senderEndpoint); } else if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM) { DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes) msgId; Package message = PackageFactory.CreatePackage(msgId, receiveBytes); TraceReceive(message); switch (msgIdType) { case DefaultMessageIdTypes.ID_UNCONNECTED_PING: case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS: { UnconnectedPing incoming = (UnconnectedPing) message; //TODO: This needs to be verified with RakNet first //response.sendpingtime = msg.sendpingtime; //response.sendpongtime = DateTimeOffset.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; var packet = new UnconnectedPong { serverId = 22345, pingId = incoming.pingId /*incoming.pingId*/, serverName = string.Format(@"MCPE;{0};27;0.11.1;{1};{2}", Motd, _playerSessions.Count, 1000) }; var data = packet.Encode(); TraceSend(packet); SendData(data, senderEndpoint, new object()); break; } case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1: { OpenConnectionRequest1 incoming = (OpenConnectionRequest1) message; _isPerformanceTest = _isPerformanceTest || incoming.raknetProtocolVersion == byte.MaxValue; var packet = new OpenConnectionReply1 { serverGuid = 12345, mtuSize = incoming.mtuSize, serverHasSecurity = 0 }; var data = packet.Encode(); TraceSend(packet); SendData(data, senderEndpoint, new object()); break; } case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2: { OpenConnectionRequest2 incoming = (OpenConnectionRequest2) message; Log.WarnFormat("New connection from: {0} {1}", senderEndpoint.Address, incoming.clientUdpPort); var packet = new OpenConnectionReply2 { serverGuid = 12345, mtuSize = incoming.mtuSize, doSecurityAndHandshake = new byte[0] }; PlayerNetworkSession session = null; lock (_playerSessions) { if (_playerSessions.ContainsKey(senderEndpoint)) { PlayerNetworkSession value; _playerSessions.TryRemove(senderEndpoint, out value); value.Player.HandleDisconnectionNotification(); Log.Info("Removed ghost"); } Player player = PlayerFactory.CreatePlayer(this, senderEndpoint, _levels[_random.Next(0, _levels.Count)], incoming.mtuSize); session = new PlayerNetworkSession(player, senderEndpoint); session.LastUpdatedTime = DateTime.UtcNow; session.Mtuize = incoming.mtuSize; _playerSessions.TryAdd(senderEndpoint, session); } var data = packet.Encode(); TraceSend(packet); SendData(data, senderEndpoint, session.SyncRoot); break; } default: Log.ErrorFormat("Receive unexpected packet with ID: {0} (0x{0:x2}) from {1}", msgId, senderEndpoint.Address); break; } if (message != null) { message.PutPool(); } else { Log.ErrorFormat("Receive unexpected packet with ID: {0} (0x{0:x2}) from {1}", msgId, senderEndpoint.Address); } } 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); List<Package> messages = package.Messages; if (messages.Count == 1) { McpeBatch batch = messages.First() as McpeBatch; if (batch != null) { messages = new List<Package>(); // Get bytes byte[] payload = batch.payload; // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual package out of bytes MemoryStream destination = new MemoryStream(); defStream2.CopyTo(destination); byte[] internalBuffer = destination.ToArray(); messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer)); } } } // IF reliable code below is enabled, useItem start sending doubles // for some unknown reason. //Reliability reliability = package._reliability; //if (reliability == Reliability.Reliable // || reliability == Reliability.ReliableSequenced // || reliability == Reliability.ReliableOrdered // ) { EnqueueAck(senderEndpoint, package._datagramSequenceNumber); } PlayerNetworkSession playerSession; if (_playerSessions.TryGetValue(senderEndpoint, out playerSession)) { 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; if (!playerSession.Splits.ContainsKey(spId)) { playerSession.Splits.Add(spId, new SplitPartPackage[spCount]); } SplitPartPackage[] spPackets = playerSession.Splits[spId]; 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); } byte[] buffer = stream.ToArray(); var fullMessage = PackageFactory.CreatePackage(buffer[0], buffer) ?? new UnknownPackage(buffer[0], buffer); HandlePackage(fullMessage, playerSession); } continue; } message.Timer.Restart(); HandlePackage(message, playerSession); message.PutPool(); } } package.PutPool(); } else if (header.isACK && header.isValid) { HandleAck(receiveBytes, senderEndpoint); } else if (header.isNAK && header.isValid) { HandleNak(receiveBytes, senderEndpoint); } else if (!header.isValid) { Log.Warn("!!!! ERROR, Invalid header !!!!!"); } } }
/// <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"); } } }
/// <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"); } } }
private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint) { byte msgId = receiveBytes[0]; if (msgId == 0xFE) { Log.InfoFormat("A query detected from: {0}", senderEndpoint.Address); HandleQuery(receiveBytes, senderEndpoint); } else if (msgId <= (byte) DefaultMessageIdTypes.ID_USER_PACKET_ENUM) { HandleRakNetMessage(receiveBytes, senderEndpoint, msgId); } else { PlayerNetworkSession playerSession; if (!_playerSessions.TryGetValue(senderEndpoint, out playerSession)) { Log.DebugFormat("Receive MCPE message 0x{1:x2} without session {0}", senderEndpoint.Address, msgId); return; } Player player = playerSession.Player; if (player == null) { Log.ErrorFormat("Receive MCPE message 0x{1:x2} without player {0}. Session removed.", senderEndpoint.Address, msgId); _playerSessions.TryRemove(senderEndpoint, out playerSession); return; } if (playerSession.Evicted) return; playerSession.LastUpdatedTime = DateTime.UtcNow; 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(); try { package.Decode(receiveBytes); } catch (Exception e) { player.Disconnect("Bad package received from client."); return; } // IF reliable code below is enabled, useItem start sending doubles // for some unknown reason. //Reliability reliability = package._reliability; //if (reliability == Reliability.Reliable // || reliability == Reliability.ReliableSequenced // || reliability == Reliability.ReliableOrdered // ) { EnqueueAck(playerSession, package._datagramSequenceNumber); } List<Package> messages = package.Messages; if (messages.Count == 1) { McpeBatch batch = messages.First() as McpeBatch; if (batch != null) { batch.Source = "Client"; messages.Clear(); // Get bytes byte[] payload = batch.payload; // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual package out of bytes MemoryStream destination = new MemoryStream(); defStream2.CopyTo(destination); byte[] internalBuffer = destination.ToArray(); messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer)); } batch.PutPool(); } } DelayedProcessing(playerSession, package); package.PutPool(); } else if (header.isACK && header.isValid) { ServerInfo.NumberOfAckReceive++; HandleAck(playerSession, receiveBytes); } else if (header.isNAK && header.isValid) { ServerInfo.NumberOfNakReceive++; HandleNak(playerSession, receiveBytes); } else if (!header.isValid) { Log.Warn("!!!! ERROR, Invalid header !!!!!"); } } }
protected override void DecodePacket() { Messages = new List <Packet>(); _buffer.Position = 0; _datagramHeader = new DatagramHeader(ReadByte()); _datagramSequenceNumber = ReadLittle(); _datagramHeader.datagramSequenceNumber = _datagramSequenceNumber; _hasSplit = false; while (_buffer.Position < _buffer.Length) { if (_hasSplit) { Log.Warn("Reading second split message"); } byte flags = ReadByte(); _reliability = (Reliability)((flags & Convert.ToByte("011100000", 2)) >> 5); _hasSplit = ((flags & Convert.ToByte("00010000", 2)) > 0); short dataBitLength = ReadShort(true); if (_reliability == Reliability.Reliable || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered ) { _reliableMessageNumber = ReadLittle(); } else { _reliableMessageNumber = -1; } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced ) { _sequencingIndex = ReadLittle(); } else { _sequencingIndex = -1; } if (_reliability == Reliability.UnreliableSequenced || _reliability == Reliability.ReliableSequenced || _reliability == Reliability.ReliableOrdered || _reliability == Reliability.ReliableOrderedWithAckReceipt ) { _orderingIndex = ReadLittle(); _orderingChannel = ReadByte(); // flags } else { _orderingIndex = 0; _orderingChannel = 0; } if (_hasSplit) { _splitPacketCount = ReadInt(true); _splitPacketId = ReadShort(true); _splitPacketIndex = ReadInt(true); } else { _splitPacketCount = -1; _splitPacketId = -1; _splitPacketIndex = -1; } // Slurp the payload MessageLength = (int)Math.Ceiling((((double)dataBitLength) / 8)); byte[] internalBuffer = ReadBytes(MessageLength); if (_hasSplit) { SplitPartPacket splitPartPacket = SplitPartPacket.CreateObject(); splitPartPacket.DatagramSequenceNumber = _datagramSequenceNumber; splitPartPacket.Reliability = _reliability; splitPartPacket.ReliableMessageNumber = _reliableMessageNumber; splitPartPacket.OrderingChannel = _orderingChannel; splitPartPacket.OrderingIndex = _orderingIndex; splitPartPacket.SplitId = _splitPacketId; splitPartPacket.SplitCount = _splitPacketCount; splitPartPacket.SplitIdx = _splitPacketIndex; splitPartPacket.Id = internalBuffer[0]; splitPartPacket.Message = internalBuffer; Messages.Add(splitPartPacket); if (Log.IsDebugEnabled && _buffer.Position < _buffer.Length) { Log.Debug($"Got split message, but more to read {_buffer.Length - _buffer.Position}"); } continue; } byte id = internalBuffer[0]; Packet packet = PacketFactory.Create(id, internalBuffer, "raknet") ?? new UnknownPacket(id, internalBuffer); packet.DatagramSequenceNumber = _datagramSequenceNumber; packet.Reliability = _reliability; packet.ReliableMessageNumber = _reliableMessageNumber; packet.OrderingChannel = _orderingChannel; packet.OrderingIndex = _orderingIndex; //if (!(package is McpeBatch)) Log.Debug($"Raw: {package.DatagramSequenceNumber} {package.ReliableMessageNumber} {package.OrderingIndex} {package.GetType().Name} 0x{package.Id:x2} \n{HexDump(internalBuffer)}"); Messages.Add(packet); if (Log.IsDebugEnabled && MessageLength != internalBuffer.Length) { Log.Debug("Missmatch of requested lenght, and actual read lenght"); } } }
public void EncapsulatedHeaderTest() { DatagramHeader header = new DatagramHeader(0x8c); Assert.AreEqual(true, header.isValid); Assert.AreEqual(false, header.isACK); Assert.AreEqual(false, header.isNAK); Assert.AreEqual(false, header.isPacketPair); Assert.AreEqual(false, header.hasBAndAS); Assert.AreEqual(true, header.isContinuousSend); Assert.AreEqual(true, header.needsBAndAs); }
/// <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"); } } }