// the other end just sent us a message // and it told us the latest message it got // and the ack mask private void AckPackets(ushort receiveSequence, ulong ackMask) { while (sendWindow.Count > 0) { PacketEnvelope envelope = sendWindow.Peek(); int distance = (int)sequencer.Distance(envelope.Sequence, receiveSequence); if (distance > 0) { break; } sendWindow.Dequeue(); // if any of these cases trigger, packet is most likely lost if ((distance <= -ACK_MASK_BITS) || ((ackMask & (1UL << -distance)) == 0UL)) { NotifyLost?.Invoke(this, envelope.Token); } else { NotifyDelivered?.Invoke(this, envelope.Token); } } }
/// <summary> /// Sends a message, but notify when it is delivered or lost /// </summary> /// <typeparam name="T">type of message to send</typeparam> /// <param name="message">message to send</param> /// <param name="token">a arbitrary object that the sender will receive with their notification</param> public void SendNotify <T>(T message, object token, int channelId = Channel.Unreliable) { if (sendWindow.Count == WINDOW_SIZE) { NotifyLost?.Invoke(this, token); return; } using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { var notifyPacket = new NotifyPacket { Sequence = (ushort)sequencer.Next(), ReceiveSequence = receiveSequence, AckMask = receiveMask }; sendWindow.Enqueue(new PacketEnvelope { Sequence = notifyPacket.Sequence, Token = token }); MessagePacker.Pack(notifyPacket, writer); MessagePacker.Pack(message, writer); NetworkDiagnostics.OnSend(message, channelId, writer.Length, 1); Send(writer.ToArraySegment(), channelId); lastNotifySentTime = Time.unscaledTime; } }