private static List <MessagePart> CreateMessageParts(Packet message, int mtuSize, RakSession session) { Memory <byte> encodedMessage = message.Encode(); if (encodedMessage.IsEmpty) { return(new List <MessagePart>(0)); } if (message.IsMcpe) { Log.Error($"Got bedrock message in unexpected place {message.GetType().Name}"); } int maxPayloadSizeNoSplit = mtuSize - 28 - GetHeaderSize(message.ReliabilityHeader, false); bool split = encodedMessage.Length >= maxPayloadSizeNoSplit; List <(int @from, int length)> splits = ArraySplit(encodedMessage.Length, mtuSize - RakOfflineHandler.UdpHeaderSize - 4 /*datagram header*/ - GetHeaderSize(message.ReliabilityHeader, split)); int count = splits.Count; if (count == 0) { Log.Warn("Got zero parts back from split"); } if (count <= 1) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = message.ReliabilityHeader.Reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = message.ReliabilityHeader.OrderingIndex; messagePart.ReliabilityHeader.HasSplit = false; messagePart.Buffer = encodedMessage; return(new List <MessagePart>(1) { messagePart }); } // Stupid but scared to change it .. remove the -100 when i feel "safe" if (session.SplitPartId > short.MaxValue - 100) { Interlocked.CompareExchange(ref session.SplitPartId, 0, short.MaxValue); } int index = 0; short splitId = (short)Interlocked.Increment(ref session.SplitPartId); var messageParts = new List <MessagePart>(count); foreach ((int from, int length)span in splits) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = message.ReliabilityHeader.Reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = message.ReliabilityHeader.OrderingIndex; messagePart.ReliabilityHeader.HasSplit = count > 1; messagePart.ReliabilityHeader.PartCount = count; messagePart.ReliabilityHeader.PartId = splitId; messagePart.ReliabilityHeader.PartIndex = index++; messagePart.Buffer = encodedMessage.Slice(span.@from, span.length); messageParts.Add(messagePart); } return(messageParts); }
private static List <MessagePart> CreateMessageParts(Packet message, int mtuSize, Reliability reliability, RakSession session) { Memory <byte> encodedMessage = message.Encode(); if (encodedMessage.IsEmpty) { return(new List <MessagePart>(0)); } // All MCPE messages goes into a compressed (and possible encrypted) wrapper. // Note that McpeWrapper itself is a RakNet level message. bool isWrapper = message is McpeWrapper; if (message.IsMcpe) { var wrapper = McpeWrapper.CreateObject(); wrapper.payload = Compression.Compress(encodedMessage, true, encodedMessage.Length > 1000 ? CompressionLevel.Fastest : CompressionLevel.NoCompression); encodedMessage = wrapper.Encode(); wrapper.PutPool(); isWrapper = true; } // Should probably only force for McpeWrapper, not the other messages (RakNet) if (!(message is ConnectedPong) && !(message is DetectLostConnections)) { reliability = Reliability.ReliableOrdered; } int orderingIndex = 0; lock (session.EncodeSync) { CryptoContext cryptoContext = session.CryptoContext; if (!message.ForceClear && cryptoContext != null && session.CryptoContext.UseEncryption && isWrapper) { var wrapper = McpeWrapper.CreateObject(); wrapper.payload = CryptoUtils.Encrypt(encodedMessage.Slice(1), cryptoContext); encodedMessage = wrapper.Encode(); wrapper.PutPool(); } if (reliability == Reliability.ReliableOrdered) { orderingIndex = Interlocked.Increment(ref session.OrderingIndex); } } List <(int @from, int length)> splits = ArraySplit(encodedMessage.Length, mtuSize - 100); int count = splits.Count; if (count == 0) { Log.Warn("Got zero parts back from split"); } if (count <= 1) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = orderingIndex; messagePart.ReliabilityHeader.HasSplit = false; messagePart.Buffer = encodedMessage; return(new List <MessagePart>(1) { messagePart }); } // Stupid but scared to change it .. remove the -100 when i feel "safe" if (session.SplitPartId > short.MaxValue - 100) { Interlocked.CompareExchange(ref session.SplitPartId, 0, short.MaxValue); } int index = 0; short splitId = (short)Interlocked.Increment(ref session.SplitPartId); var messageParts = new List <MessagePart>(count); foreach ((int from, int length)span in splits) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = orderingIndex; messagePart.ReliabilityHeader.HasSplit = count > 1; messagePart.ReliabilityHeader.PartCount = count; messagePart.ReliabilityHeader.PartId = splitId; messagePart.ReliabilityHeader.PartIndex = index++; messagePart.Buffer = encodedMessage.Slice(span.@from, span.length); messageParts.Add(messagePart); } return(messageParts); }