private void SendAck(ushort sequence) { // Check the last ack time if (!_lastAckTimes.TryGet(sequence, out NetTime value) || ((NetTime.Now - value).TotalMilliseconds > connection.SmoothRoundtrip * config.ReliabilityResendRoundtripMultiplier && (NetTime.Now - value).TotalMilliseconds > config.ReliabilityMinAckResendDelay)) { // Set the last ack time _lastAckTimes.Set(sequence, NetTime.Now); // Alloc ack memory HeapMemory ackMemory = memoryManager.AllocHeapMemory(4 + (uint)(config.EnableMergedAcks ? config.MergedAckBytes : 0)); // Write header ackMemory.Buffer[0] = HeaderPacker.Pack(MessageType.Ack); ackMemory.Buffer[1] = (byte)channelId; // Write sequence ackMemory.Buffer[2] = (byte)sequence; ackMemory.Buffer[3] = (byte)(sequence >> 8); if (config.EnableMergedAcks) { // Reset the memory for (int i = 0; i < config.MergedAckBytes; i++) { ackMemory.Buffer[4 + i] = 0; } // Set the bit fields for (int i = 0; i < config.MergedAckBytes * 8; i++) { ushort bitSequence = (ushort)(sequence - (i + 1)); bool bitAcked = SequencingUtils.Distance(bitSequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0 || _incomingAckedSequences.Contains(bitSequence); if (bitAcked) { // Set the ack time for this packet _lastAckTimes.Set(bitSequence, NetTime.Now); } // Write single ack bit ackMemory.Buffer[4 + (i / 8)] |= (byte)((bitAcked ? 1 : 0) << (7 - (i % 8))); } } // Send ack connection.SendInternal(new ArraySegment <byte>(ackMemory.Buffer, 0, 4 + (config.EnableMergedAcks ? config.MergedAckBytes : 0)), false); // Return memory memoryManager.DeAlloc(ackMemory); } }
private void SendAck(ushort sequence) { // Check the last ack time if (!_lastAckTimes.TryGet(sequence, out NetTime value) || ((NetTime.Now - value).TotalMilliseconds > connection.SmoothRoundtrip * config.ReliabilityResendRoundtripMultiplier && (NetTime.Now - value).TotalMilliseconds > config.ReliabilityMinAckResendDelay)) { // Set the last ack time _lastAckTimes.Set(sequence, NetTime.Now); // Alloc ack memory HeapMemory ackMemory = memoryManager.AllocHeapMemory(4); // Write header ackMemory.Buffer[0] = HeaderPacker.Pack(MessageType.Ack); ackMemory.Buffer[1] = (byte)channelId; // Write sequence ackMemory.Buffer[2] = (byte)sequence; ackMemory.Buffer[3] = (byte)(sequence >> 8); // Send ack connection.SendInternal(new ArraySegment <byte>(ackMemory.Buffer, 0, 4), false); // Return memory memoryManager.DeAlloc(ackMemory); } }
public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload) { // Read the sequence number ushort sequence = (ushort)(payload.Array[payload.Offset] | (ushort)(payload.Array[payload.Offset + 1] << 8)); lock (_receiveLock) { if (_incomingAckedPackets.Contains(sequence)) { // We have already received this message. Ignore it. return(null); } // Add to sequencer _incomingAckedPackets.Set(sequence, true); // Alloc pointers HeapPointers pointers = memoryManager.AllocHeapPointers(1); // Alloc wrapper pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(new ArraySegment <byte>(payload.Array, payload.Offset + 2, payload.Count - 2)); return(pointers); } }
public HeapPointers HandleIncomingMessagePoll(ArraySegment <byte> payload) { // -> Sorting happens in the ConcurrentCircularQueue when messages are Enqueued // // Read the sequence number ushort sequence = (ushort)(payload.Array[payload.Offset] | (ushort)(payload.Array[payload.Offset + 1] << 8)); lock (_receiveLock) { if (_incomingAckedPackets.Contains(sequence)) { // We have already received this message. Ignore it. return(null); } /* if (SequencingUtils.Distance(sequence, _incomingLowestAckedSequence, sizeof(ushort)) <= 0) * { * if (SequencingUtils.Distance(sequence, _lastPollSequence, sizeof(ushort)) > 0) * { * Logging.LogInfo("Skipping dropping packet since it's newer than _lastPollSequence (" + _lastPollSequence + ") | _incomingLowestAckedSequence: " + _incomingLowestAckedSequence + " | currentSequence: " + sequence); * } * } */ if (SequencingUtils.Distance(sequence, _lastPollSequence, sizeof(ushort)) > 0) // ! We're using _lastPollSequence instead of _incomingLowestAckedSequence to not drop old packets if we're still waiting for them to be polled by the game/MLAPI, which can still be sorted properly { // Set the new sequence _incomingLowestAckedSequence = sequence; _incomingAckedPackets.Set(sequence, true); // Alloc pointers HeapPointers pointers = memoryManager.AllocHeapPointers(1); // Alloc wrapper pointers.Pointers[0] = memoryManager.AllocMemoryWrapper(new ArraySegment <byte>(payload.Array, payload.Offset + 2, payload.Count - 2)); return(pointers); } return(null); } }