Exemple #1
0
        public static IEnumerable <Datagram> CreateDatagrams(Packet message, int mtuSize, RaknetSession session)
        {
            Log.Warn($"CreateDatagrams single message");
            Datagram datagram = CreateObject();

            List <MessagePart> messageParts = CreateMessageParts(message, mtuSize, session);

            foreach (MessagePart messagePart in messageParts)
            {
                if (!datagram.TryAddMessagePart(messagePart, mtuSize))
                {
                    yield return(datagram);

                    datagram = CreateObject();
                    if (datagram.MessageParts.Count != 0)
                    {
                        throw new Exception("Excepted no message parts in new message");
                    }

                    if (!datagram.TryAddMessagePart(messagePart, mtuSize))
                    {
                        string error = $"Message part too big for a single datagram. Size: {messagePart.Encode().Length}, MTU: {mtuSize}";
                        Log.Error(error);
                        throw new Exception(error);
                    }
                }
            }

            yield return(datagram);
        }
Exemple #2
0
        private static List <MessagePart> CreateMessageParts(Packet message, int mtuSize, RaknetSession 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 - RaknetHandler.UdpHeaderSize - 4 - GetHeaderSize(message.ReliabilityHeader, false);
            bool split = encodedMessage.Length >= maxPayloadSizeNoSplit;

            List <(int @from, int length)> splits = ArraySplit(encodedMessage.Length, mtuSize - RaknetHandler.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);
            }

            if (message.ReliabilityHeader.Reliability == Reliability.Unreliable)
            {
                message.ReliabilityHeader.Reliability = Reliability.Reliable;
            }

            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);
        }
Exemple #3
0
 public MessageHandler(RaknetSession session, IMcpeClientMessageHandler handler) : base()
 {
     _session           = session;
     _messageDispatcher = new McpeClientMessageDispatcher(handler);
 }