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); } } } }
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"); } } }