Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }