public void Received(byte[] data) { if (!CheckVerify()) { _session.Send(PacketFactory.CreateError("not verification")); _session.Close(); return; } var package = PacketFactory.Create(data); _packetHandler.HandlePacket(package); }
void TcpClient_Received(object sender, SocketEventArgs e) { try { LastActiveTime = DateTime.Now; var packet = PacketFactory.Create(e.Data); switch (packet.Version) { case 2: Packet2Handler(packet as Packet); break; } } catch (Exception ex) { logger.Error("ClientBase DataReceived error:{0}", ex); } }
public override void Flush() { if (Closed) { throw new InvalidOperationException("Stream is closed"); } if (Buf.Length > VBANPacket <T> .MaxSize) { throw new InvalidOperationException($"Buffer is too large, must be smaller than {VBANPacket<T>.MaxSize}"); } VBANPacket <T> packet = PacketFactory.Create(); packet.Data = Buf.Bytes; byte[] x; _client.Send(x = packet.Bytes, x.Length, IpEndPoint); Buf = new UnfinishedByteArray(VBANPacket <T> .MaxSize, true); }
public override void Flush() { if (Closed) { throw new InvalidOperationException("Stream is closed"); } if (Buf.Length > VBANPacket <T> .MaxSize) { throw new InvalidOperationException( $"Buffer is too large, must be smaller than {VBANPacket<T>.MaxSize}"); } var packet = PacketFactory.Create(); packet.AttachData(Buf); byte[] x = packet; _client.Send(x, x.Length, IpEndPoint); Buf = new ByteArray(); }
private void SetupRequest(Request request) { switch (Context.ServiceContract.ConcurrencyMode) { case ConcurrencyMode.Single: case ConcurrencyMode.Reentrant: { var response = Response(request); var respPack = PacketFactory.Create(response); Session.Send(respPack); } break; case ConcurrencyMode.Multiple: ThreadPool.QueueUserWorkItem(obj => { var response = Response(request); var packet = PacketFactory.Create(response); Session.Send(packet); }, null); break; } }
private void HandleSplitMessage(PlayerNetworkSession playerSession, SplitPartPacket splitMessage) { int spId = splitMessage.SplitId; int spIdx = splitMessage.SplitIdx; int spCount = splitMessage.SplitCount; Int24 sequenceNumber = splitMessage.DatagramSequenceNumber; Reliability reliability = splitMessage.Reliability; Int24 reliableMessageNumber = splitMessage.ReliableMessageNumber; Int24 orderingIndex = splitMessage.OrderingIndex; byte orderingChannel = splitMessage.OrderingChannel; SplitPartPacket[] spPackets; bool haveEmpty = false; // Need sync for this part since they come very fast, and very close in time. // If no synk, will often detect complete message two times (or more). lock (playerSession.Splits) { if (!playerSession.Splits.ContainsKey(spId)) { playerSession.Splits.TryAdd(spId, new SplitPartPacket[spCount]); } spPackets = playerSession.Splits[spId]; if (spPackets[spIdx] != null) { Log.Debug("Already had splitpart (resent). Ignore this part."); return; } spPackets[spIdx] = splitMessage; for (int i = 0; i < spPackets.Length; i++) { haveEmpty = haveEmpty || spPackets[i] == null; } } if (!haveEmpty) { Log.DebugFormat("Got all {0} split packets for split ID: {1}", spCount, spId); SplitPartPacket[] waste; playerSession.Splits.TryRemove(spId, out waste); using (MemoryStream stream = MemoryStreamManager.GetStream()) { for (int i = 0; i < spPackets.Length; i++) { SplitPartPacket splitPartPacket = spPackets[i]; byte[] buf = splitPartPacket.Message; if (buf == null) { Log.Error("Expected bytes in splitpart, but got none"); continue; } stream.Write(buf, 0, buf.Length); splitPartPacket.PutPool(); } byte[] buffer = stream.ToArray(); try { ConnectedPacket newPacket = ConnectedPacket.CreateObject(); newPacket._datagramSequenceNumber = sequenceNumber; newPacket._reliability = reliability; newPacket._reliableMessageNumber = reliableMessageNumber; newPacket._orderingIndex = orderingIndex; newPacket._orderingChannel = (byte)orderingChannel; newPacket._hasSplit = false; Packet fullMessage = PacketFactory.Create(buffer[0], buffer, "raknet") ?? new UnknownPacket(buffer[0], buffer); fullMessage.DatagramSequenceNumber = sequenceNumber; fullMessage.Reliability = reliability; fullMessage.ReliableMessageNumber = reliableMessageNumber; fullMessage.OrderingIndex = orderingIndex; fullMessage.OrderingChannel = orderingChannel; newPacket.Messages = new List <Packet>(); newPacket.Messages.Add(fullMessage); Log.Debug( $"Assembled split packet {newPacket._reliability} message #{newPacket._reliableMessageNumber}, Chan: #{newPacket._orderingChannel}, OrdIdx: #{newPacket._orderingIndex}"); HandleConnectedPacket(playerSession, newPacket); newPacket.PutPool(); } catch (Exception e) { Log.Error("Error during split message parsing", e); if (Log.IsDebugEnabled) { Log.Debug($"0x{buffer[0]:x2}\n{Packet.HexDump(buffer)}"); } playerSession.Disconnect("Bad packet received from client.", false); } } } }
private void HandleRakNetMessage(byte[] receiveBytes, IPEndPoint senderEndpoint, byte msgId) { DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId; // Increase fast, decrease slow on 1s ticks. if (ServerInfo.NumberOfPlayers < ServerInfo.PlayerSessions.Count) { ServerInfo.NumberOfPlayers = ServerInfo.PlayerSessions.Count; } // Shortcut to reply fast, and no parsing if (msgIdType == DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1) { if (!GreylistManager.AcceptConnection(senderEndpoint.Address)) { var noFree = NoFreeIncomingConnections.CreateObject(); var bytes = noFree.Encode(); noFree.PutPool(); TraceSend(noFree); SendData(bytes, senderEndpoint); Interlocked.Increment(ref ServerInfo.NumberOfDeniedConnectionRequestsPerSecond); return; } } Packet message = null; try { try { message = PacketFactory.Create(msgId, receiveBytes, "raknet"); } catch (Exception) { message = null; } if (message == null) { GreylistManager.Blacklist(senderEndpoint.Address); Log.ErrorFormat("Receive bad packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId); return; } TraceReceive(message); switch (msgIdType) { case DefaultMessageIdTypes.ID_UNCONNECTED_PING: case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS: { HandleRakNetMessage(senderEndpoint, (UnconnectedPing)message); break; } case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1: { HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest1)message); break; } case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2: { HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest2)message); break; } default: GreylistManager.Blacklist(senderEndpoint.Address); if (Log.IsInfoEnabled) { Log.ErrorFormat("Receive unexpected packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId); } break; } } finally { if (message != null) { message.PutPool(); } } }
internal void HandlePacket(Packet message, PlayerNetworkSession playerSession) { //SignalTick(); try { if (message == null) { return; } if (typeof(UnknownPacket) == message.GetType()) { UnknownPacket packet = (UnknownPacket)message; if (Log.IsDebugEnabled) { Log.Warn($"Received unknown packet 0x{message.Id:X2}\n{Packet.HexDump(packet.Message)}"); } message.PutPool(); return; } if (typeof(McpeWrapper) == message.GetType()) { McpeWrapper batch = (McpeWrapper)message; var messages = new List <Packet>(); // Get bytes byte[] payload = batch.payload; if (playerSession.CryptoContext != null && playerSession.CryptoContext.UseEncryption) { payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext); } // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Expected 0x78 0x9C 0x{message.Id:X2}\n{Packet.HexDump(batch.payload)}"); } if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Decrypted 0x{message.Id:X2}\n{Packet.HexDump(payload)}"); } throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var deflateStream = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual packet out of bytes using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream()) { deflateStream.CopyTo(destination); destination.Position = 0; while (destination.Position < destination.Length) { int len = (int)VarInt.ReadUInt32(destination); long pos = destination.Position; int id = (int)VarInt.ReadUInt32(destination); len = (int)(len - (destination.Position - pos)); // calculate len of buffer after varint byte[] internalBuffer = new byte[len]; destination.Read(internalBuffer, 0, len); //if (Log.IsDebugEnabled) // Log.Debug($"0x{internalBuffer[0]:x2}\n{Packet.HexDump(internalBuffer)}"); try { messages.Add(PacketFactory.Create((byte)id, internalBuffer, "mcpe") ?? new UnknownPacket((byte)id, internalBuffer)); } catch (Exception e) { if (Log.IsDebugEnabled) { Log.Warn($"Error parsing packet 0x{message.Id:X2}\n{Packet.HexDump(internalBuffer)}"); } throw; } } if (destination.Length > destination.Position) { throw new Exception("Have more data"); } } } foreach (var msg in messages) { // Temp fix for performance, take 1. var interact = msg as McpeInteract; if (interact?.actionId == 4 && interact.targetRuntimeEntityId == 0) { continue; } msg.DatagramSequenceNumber = batch.DatagramSequenceNumber; msg.Reliability = batch.Reliability; msg.ReliableMessageNumber = batch.ReliableMessageNumber; msg.OrderingChannel = batch.OrderingChannel; msg.OrderingIndex = batch.OrderingIndex; HandlePacket(msg, playerSession); } message.PutPool(); return; } MiNetServer.TraceReceive(message); if (CryptoContext != null && CryptoContext.UseEncryption) { MiNetServer.FastThreadPool.QueueUserWorkItem(() => { HandlePacket(MessageHandler, message as Packet); message.PutPool(); }); } else { HandlePacket(MessageHandler, message); message.PutPool(); } } catch (Exception e) { Log.Error("Packet handling", e); throw; } }
private IPacket PrivateReadPacket() { IPacket p = null; switch (SocketModeRx) { case Mode.Ascii: { p = new SshIdentification(pr.ReadLine().ToByteArray()); break; } case Mode.PlainText: { ServerSequence++; int packetLength = pr.ReadInt32(); byte paddingLength = pr.ReadByte(); var payload = pr.ReadBytes(packetLength - paddingLength - 1); pr.ReadBytes(paddingLength); p = PacketFactory.Create(session, payload); break; } case Mode.CipherText: { if (Decryptor == null) { session.KexProcessor.Wait(); } int packetLength = pr.ReadInt32(); byte paddingLength = pr.ReadByte(); var payload = pr.ReadBytes(packetLength - paddingLength - 1); var padding = pr.ReadBytes(paddingLength); var hmac = DecryptorMac; hmac.WriteUInt32(ServerSequence++); hmac.WriteInt32(packetLength); hmac.Write(paddingLength); hmac.Write(payload); hmac.Write(padding); if (rxCompressionEnabled || (rxCompressionEnabled = IsRxCompressionEnabled())) { if (RxZlibTransform == null) { RxZlibTransform = new ZlibTransform(CompressionMode.Decompress); } var length = RxZlibTransform.TransformBlock(payload, 0, payload.Length, zlibRxBuffer, 0); Debug.WriteLine(string.Format("Compression In: In: {0}; Out: {1}; TotalIn: {2}; TotalOut: {3}; TotalRatio: {4}", payload.Length, length, RxZlibTransform.TotalIn, RxZlibTransform.TotalOut, RxZlibTransform.Ratio)); payload = new byte[length]; Buffer.BlockCopy(zlibRxBuffer, 0, payload, 0, length); } // mac isn't encrypted, read directly from network stream byte[] mac = new byte[hmac.BlockSize]; st.Read(mac, 0, hmac.BlockSize); if (!hmac.IsMatch(mac)) { throw new CryptographicException("MAC couldn't be verified!"); } hmac.Reset(); p = PacketFactory.Create(session, payload); break; } } if (p.Code == MessageCode.SSH_MSG_IDENTIFICATION) { SocketModeRx = Mode.PlainText; } if (p.Code == MessageCode.SSH_MSG_NEWKEYS) { SocketModeRx = Mode.CipherText; } return(p); }
internal void HandleOfflineRakMessage(ReadOnlyMemory <byte> receiveBytes, IPEndPoint senderEndpoint) { byte messageId = receiveBytes.Span[0]; var messageType = (DefaultMessageIdTypes)messageId; // Increase fast, decrease slow on 1s ticks. if (_connectionInfo.NumberOfPlayers < _connectionInfo.RakSessions.Count) { _connectionInfo.NumberOfPlayers = _connectionInfo.RakSessions.Count; } // Shortcut to reply fast, and no parsing if (messageType == DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1) { if (!_greyListManager.AcceptConnection(senderEndpoint.Address)) { var noFree = NoFreeIncomingConnections.CreateObject(); var bytes = noFree.Encode(); TraceSend(noFree); noFree.PutPool(); _sender.SendData(bytes, senderEndpoint); Interlocked.Increment(ref _connectionInfo.NumberOfDeniedConnectionRequestsPerSecond); return; } } Packet message = null; try { try { message = PacketFactory.Create(messageId, receiveBytes, "raknet"); } catch (Exception) { message = null; } if (message == null) { _greyListManager.Blacklist(senderEndpoint.Address); Log.Error($"Receive bad packet with ID: {messageId} (0x{messageId:x2}) {messageType} from {senderEndpoint.Address}"); return; } TraceReceive(Log, message); switch (messageType) { case DefaultMessageIdTypes.ID_NO_FREE_INCOMING_CONNECTIONS: // Stop this client connection _connection.Stop(); break; case DefaultMessageIdTypes.ID_UNCONNECTED_PING: case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS: HandleRakNetMessage(senderEndpoint, (UnconnectedPing)message); break; case DefaultMessageIdTypes.ID_UNCONNECTED_PONG: HandleRakNetMessage(senderEndpoint, (UnconnectedPong)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1: HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest1)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1: HandleRakNetMessage(senderEndpoint, (OpenConnectionReply1)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2: HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest2)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2: HandleRakNetMessage(senderEndpoint, (OpenConnectionReply2)message); break; default: _greyListManager.Blacklist(senderEndpoint.Address); if (Log.IsInfoEnabled) { Log.Error($"Receive unexpected packet with ID: {messageId} (0x{messageId:x2}) {messageType} from {senderEndpoint.Address}"); } break; } } finally { message?.PutPool(); } }
internal void HandleOfflineRakMessage(ReadOnlyMemory <byte> receiveBytes, IPEndPoint senderEndpoint) { byte messageId = receiveBytes.Span[0]; var messageType = (DefaultMessageIdTypes)messageId; // Increase fast, decrease slow on 1s ticks. //if (_connectionInfo.NumberOfPlayers < _connectionInfo.RakSessions.Count) _connectionInfo.NumberOfPlayers = _connectionInfo.RakSessions.Count; Packet message = null; try { try { message = PacketFactory.Create(messageId, receiveBytes, "raknet"); } catch (Exception) { message = null; } if (message == null) { Log.Error($"Receive bad packet with ID: {messageId} (0x{messageId:x2}) {messageType} from {senderEndpoint.Address}"); return; } // TraceReceive(Log, message); switch (messageType) { case DefaultMessageIdTypes.ID_NO_FREE_INCOMING_CONNECTIONS: // Stop this client connection _connection.Stop(); break; case DefaultMessageIdTypes.ID_UNCONNECTED_PING: case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS: HandleRakNetMessage(senderEndpoint, (UnconnectedPing)message); break; case DefaultMessageIdTypes.ID_UNCONNECTED_PONG: HandleRakNetMessage(senderEndpoint, (UnconnectedPong)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1: //HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest1) message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_1: HandleRakNetMessage(senderEndpoint, (OpenConnectionReply1)message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2: //HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest2) message); break; case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REPLY_2: HandleRakNetMessage(senderEndpoint, (OpenConnectionReply2)message); break; default: if (Log.IsInfoEnabled) { Log.Error($"Receive unexpected packet with ID: {messageId} (0x{messageId:x2}) {messageType} from {senderEndpoint.Address}"); } break; } } finally { message?.PutPool(); } }
public void HandlePacket(Packet message) { if (message is McpeWrapper wrapper) { var messages = new List <Packet>(); // Get bytes to process ReadOnlyMemory <byte> payload = wrapper.payload; // Decrypt bytes if (CryptoContext != null && CryptoContext.UseEncryption) { // This call copies the entire buffer, but what can we do? It is kind of compensated by not // creating a new buffer when parsing the packet (only a mem-slice) payload = CryptoUtils.Decrypt(payload, CryptoContext); } // Decompress bytes var stream = new MemoryStreamReader(payload.Slice(0, payload.Length - 4)); // slice away adler if (stream.ReadByte() != 0x78) { if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Expected 0x78 0x9C 0x{wrapper.Id:X2}\n{Packet.HexDump(wrapper.payload)}"); } if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Decrypted 0x{wrapper.Id:X2}\n{Packet.HexDump(payload)}"); } throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var deflateStream = new DeflateStream(stream, CompressionMode.Decompress, false)) { using var s = new MemoryStream(); deflateStream.CopyTo(s); s.Position = 0; int count = 0; // Get actual packet out of bytes while (s.Position < s.Length) { count++; uint len = VarInt.ReadUInt32(s); ReadOnlyMemory <byte> internalBuffer = s.GetBuffer().AsMemory((int)s.Position, (int)len); s.Position += len; int id = internalBuffer.Span[0]; //if (Log.IsDebugEnabled) // Log.Debug($"0x{internalBuffer[0]:x2}\n{Packet.HexDump(internalBuffer)}"); try { messages.Add(PacketFactory.Create((byte)id, internalBuffer, "mcpe") ?? new UnknownPacket((byte)id, internalBuffer)); } catch (Exception) { if (Log.IsDebugEnabled) { Log.Warn($"Error parsing bedrock message #{count} id={id}\n{Packet.HexDump(internalBuffer)}"); } //throw; return; // Exit, but don't crash. } } if (s.Length > s.Position) { throw new Exception("Have more data"); } } foreach (Packet msg in messages) { // Temp fix for performance, take 1. //var interact = msg as McpeInteract; //if (interact?.actionId == 4 && interact.targetRuntimeEntityId == 0) continue; msg.ReliabilityHeader = new ReliabilityHeader() { Reliability = wrapper.ReliabilityHeader.Reliability, ReliableMessageNumber = wrapper.ReliabilityHeader.ReliableMessageNumber, OrderingChannel = wrapper.ReliabilityHeader.OrderingChannel, OrderingIndex = wrapper.ReliabilityHeader.OrderingIndex, }; RakOfflineHandler.TraceReceive(Log, msg); try { HandleCustomPacket(msg); } catch (Exception e) { Log.Warn($"Bedrock message handler error", e); } } wrapper.PutPool(); } else if (message is UnknownPacket unknownPacket) { if (Log.IsDebugEnabled) { Log.Warn($"Received unknown packet 0x{unknownPacket.Id:X2}\n{Packet.HexDump(unknownPacket.Message)}"); } unknownPacket.PutPool(); } else { Log.Error($"Unhandled packet: {message.GetType().Name} 0x{message.Id:X2} for user: {_session.Username}, IP {_session.EndPoint.Address}"); if (Log.IsDebugEnabled) { Log.Warn($"Unknown packet 0x{message.Id:X2}\n{Packet.HexDump(message.Bytes)}"); } } }
protected override void DecodePacket() { _reader.Position = 0; Header = new InternalDatagramHeader(ReadByte()); Header.DatagramSequenceNumber = ReadLittle(); // End datagram, online packet starts Messages = new List <Packet>(); while (!_reader.Eof) { byte flags = ReadByte(); var header = new ReliabilityHeader(); header.Reliability = (Reliability)((flags & 0b011100000) >> 5); header.HasSplit = (flags & 0b00010000) > 0; short dataBitLength = ReadShort(true); switch (header.Reliability) { case Reliability.Reliable: case Reliability.ReliableSequenced: case Reliability.ReliableOrdered: header.ReliableMessageNumber = ReadLittle(); break; } switch (header.Reliability) { case Reliability.UnreliableSequenced: case Reliability.ReliableSequenced: header.SequencingIndex = ReadLittle(); break; } switch (header.Reliability) { case Reliability.UnreliableSequenced: case Reliability.ReliableSequenced: case Reliability.ReliableOrdered: case Reliability.ReliableOrderedWithAckReceipt: header.OrderingIndex = ReadLittle(); header.OrderingChannel = ReadByte(); // flags break; } if (header.HasSplit) { header.PartCount = ReadInt(true); header.PartId = ReadShort(true); header.PartIndex = ReadInt(true); } // Slurp the payload int messageLength = (int)Math.Ceiling((((double)dataBitLength) / 8)); ReadOnlyMemory <byte> internalBuffer = Slice(messageLength); if (internalBuffer.Length != messageLength) { Log.Error($"Didn't get expected length {internalBuffer.Length}"); } if (internalBuffer.Length == 0) { continue; //Log.Error($"Read length {internalBuffer.Length}, expected {messageLength}"); } if (messageLength == 0) { continue; } //if(header.Reliability != Reliability.ReliableOrdered) Log.Error($"Parsing message {internalBuffer.Span[0]} with reliability={header.Reliability}"); if (header.HasSplit) { var splitPartPacket = SplitPartPacket.CreateObject(); splitPartPacket.ReliabilityHeader = header; splitPartPacket.Id = internalBuffer.Span[0]; splitPartPacket.Message = internalBuffer; Messages.Add(splitPartPacket); if (Log.IsDebugEnabled && _reader.Position < _reader.Length) { Log.Debug($"Got split message, but more to read {_reader.Length - _reader.Position}"); } } else { byte id = internalBuffer.Span[0]; Packet packet = PacketFactory.Create(id, internalBuffer, "raknet") ?? new UnknownPacket(id, internalBuffer.ToArray()); packet.ReliabilityHeader = header; Messages.Add(packet); } if (Log.IsDebugEnabled && messageLength != internalBuffer.Length) { Log.Debug("Mismatch of requested length, and actual read length"); } } }
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 HandlePacket(Packet message) { if (message is McpeWrapper wrapper) { var messages = new LinkedList <Packet>(); // Get bytes to process var payload = wrapper.payload.ToArray(); // Decrypt bytes if (CryptoContext != null && CryptoContext.UseEncryption) { FirstEncryptedPacketWaitHandle.Set(); payload = CryptoUtils.Decrypt(payload, CryptoContext); _hasEncrypted = true; } //var stream = new MemoryStreamReader(payload); using (var deflateStream = new DeflateStream(new MemoryStream(payload), System.IO.Compression.CompressionMode.Decompress, false)) { using var s = new MemoryStream(); deflateStream.CopyTo(s); s.Position = 0; int count = 0; // Get actual packet out of bytes while (s.Position < s.Length) { count++; uint len = VarInt.ReadUInt32(s); long pos = s.Position; ReadOnlyMemory <byte> internalBuffer = s.GetBuffer().AsMemory((int)s.Position, (int)len); int id = VarInt.ReadInt32(s); Packet packet = null; try { packet = PacketFactory.Create((byte)id, internalBuffer, "mcpe") ?? new UnknownPacket((byte)id, internalBuffer); //Hack for some servers that screw up the order. // if (packet is McpePlayerList) // { // messages.AddFirst(packet); // } // else { messages.AddLast(packet); } //var a = 0x91; } catch (Exception e) { Log.Warn(e, $"Error parsing bedrock message #{count} id={id}\n{Packet.HexDump(internalBuffer)}"); //throw; return; // Exit, but don't crash. } s.Position = pos + len; } if (s.Length > s.Position) { throw new Exception("Have more data"); } } //var msgs = messages.ToArray(); //messages.Clear(); foreach (Packet msg in messages) { msg.ReliabilityHeader = new ReliabilityHeader() { Reliability = wrapper.ReliabilityHeader.Reliability, ReliableMessageNumber = wrapper.ReliabilityHeader.ReliableMessageNumber, OrderingChannel = wrapper.ReliabilityHeader.OrderingChannel, OrderingIndex = wrapper.ReliabilityHeader.OrderingIndex, SequencingIndex = wrapper.ReliabilityHeader.SequencingIndex }; try { HandleGamePacket(msg); } catch (Exception e) { Log.Warn(e, $"Bedrock message handler error"); } } wrapper.PutPool(); } else if (message is UnknownPacket unknownPacket) { if (Log.IsDebugEnabled) { Log.Warn($"Received unknown packet 0x{unknownPacket.Id:X2}\n{Packet.HexDump(unknownPacket.Message)}"); } unknownPacket.PutPool(); } else { Log.Error($"Unhandled packet: {message.GetType().Name} 0x{message.Id:X2} for user: {_session.Username}, IP {_session.EndPoint.Address}"); if (Log.IsDebugEnabled) { Log.Warn($"Unknown packet 0x{message.Id:X2}\n{Packet.HexDump(message.Bytes)}"); } } }
private void Parse() { ParsedPacket = PacketFactory.Create(_bits); Consumed = ParsedPacket.Consumed; }