private async Task SendAckQueueAsync() { RakSession session = this; var queue = session.OutgoingAckQueue; int queueCount = queue.Count; if (queueCount == 0) { return; } var acks = Acks.CreateObject(); for (int i = 0; i < queueCount; i++) { if (!queue.TryDequeue(out int ack)) { break; } Interlocked.Increment(ref ConnectionInfo.NumberOfAckSent); acks.acks.Add(ack); } if (acks.acks.Count > 0) { byte[] data = acks.Encode(); await _packetSender.SendDataAsync(data, session.EndPoint); } acks.PutPool(); }
public static void HandleRakNetMessage(MiNetServer server, IPEndPoint senderEndpoint, OpenConnectionRequest2 incoming) { RakSession session; lock (server._rakNetSessions) { if (!server._connectionAttemps.TryRemove(senderEndpoint, out _)) { Log.WarnFormat("Unexpected connection request packet from {0}. Probably a resend.", senderEndpoint.Address); return; } if (server._rakNetSessions.TryGetValue(senderEndpoint, out session)) { // Already connecting, then this is just a duplicate if (session.State == ConnectionState.Connecting /* && DateTime.UtcNow < session.LastUpdatedTime + TimeSpan.FromSeconds(2)*/) { return; } Log.InfoFormat("Unexpected session from {0}. Removing old session and disconnecting old player.", senderEndpoint.Address); session.Disconnect("Reconnecting.", false); server._rakNetSessions.TryRemove(senderEndpoint, out _); } session = new RakSession(server, null, senderEndpoint, incoming.mtuSize) { State = ConnectionState.Connecting, LastUpdatedTime = DateTime.UtcNow, MtuSize = incoming.mtuSize, NetworkIdentifier = incoming.clientGuid }; server._rakNetSessions.TryAdd(senderEndpoint, session); } session.MessageHandler = new LoginMessageHandler(session); var reply = OpenConnectionReply2.CreateObject(); reply.serverGuid = server.MotdProvider.ServerId; reply.clientEndpoint = senderEndpoint; reply.mtuSize = incoming.mtuSize; reply.doSecurityAndHandshake = new byte[1]; byte[] data = reply.Encode(); TraceSend(reply); reply.PutPool(); server.SendData(data, senderEndpoint); }
private void HandleRakNetMessage(IPEndPoint senderEndpoint, OpenConnectionRequest2 incoming) { ConcurrentDictionary <IPEndPoint, RakSession> sessions = _connectionInfo.RakSessions; ConcurrentDictionary <IPEndPoint, DateTime> connectionAttempts = _connectionAttempts; lock (sessions) { if (!connectionAttempts.ContainsKey(senderEndpoint)) { Log.Warn($"Unexpected connection request packet from {senderEndpoint}. Probably a resend."); return; } if (sessions.TryGetValue(senderEndpoint, out _)) { Log.Warn($"Trying to create session where session already exist. Please wait for timeout on {senderEndpoint}. Ignoring this request."); return; } var session = new RakSession(_connectionInfo, _sender, senderEndpoint, incoming.mtuSize) { State = ConnectionState.Connecting, LastUpdatedTime = DateTime.UtcNow, MtuSize = incoming.mtuSize, NetworkIdentifier = incoming.clientGuid, }; session.CustomMessageHandler = _connection.CustomMessageHandlerFactory?.Invoke(session); sessions.TryAdd(senderEndpoint, session); } var reply = OpenConnectionReply2.CreateObject(); reply.serverGuid = _motdProvider.ServerId; reply.clientEndpoint = senderEndpoint; reply.mtuSize = incoming.mtuSize; reply.doSecurityAndHandshake = new byte[1]; byte[] data = reply.Encode(); TraceSend(reply); reply.PutPool(); _sender.SendData(data, senderEndpoint); }
private void SendConnectionRequest(IPEndPoint targetEndPoint, short mtuSize) { ConcurrentDictionary <IPEndPoint, RakSession> sessions = _connectionInfo.RakSessions; RakSession session; lock (sessions) { if (sessions.ContainsKey(targetEndPoint)) { Log.Debug($"Session already exist, ignoring"); return; } session = new RakSession(_connectionInfo, _sender, targetEndPoint, mtuSize) { State = ConnectionState.Connecting, LastUpdatedTime = DateTime.UtcNow, NetworkIdentifier = ClientGuid, }; session.CustomMessageHandler = _connection.CustomMessageHandlerFactory?.Invoke(session); if (!sessions.TryAdd(targetEndPoint, session)) { Log.Debug($"Session already exist, ignoring"); return; } } var packet = ConnectionRequest.CreateObject(); packet.clientGuid = ClientGuid; packet.timestamp = DateTime.UtcNow.Ticks; packet.doSecurity = 0; session.SendPacket(packet); }
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); }
public static IEnumerable <Datagram> CreateDatagrams(Packet message, int mtuSize, RakSession session) { 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); }
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); }