protected void WriteRawPacket(BitStream stream, NetPacketType packetType) { WritePacketHeader(stream, packetType); if (packetType == NetPacketType.DataPacket) { var note = AllocNotify(); ++NumNotifies; if (NotifyQueueHead == null) { NotifyQueueHead = note; } else { NotifyQueueTail.NextPacket = note; } NotifyQueueTail = note; note.NextPacket = null; note.SendTime = Interface.GetCurrentTime(); WritePacketRateInfo(stream, note); //var start = stream.GetBitPosition(); stream.SetStringTable(StringTable); //Console.WriteLine("NetConnection {0}: START {1}", NetAddress, GetClassName()); WritePacket(stream, note); //Console.WriteLine("NetConnection {0}: END {1} - {2} bits", NetAddress, GetClassName(), stream.GetBitPosition() - start); } if (SymmetricCipher == null) { return; } SymmetricCipher.SetupCounter(LastSendSeq, LastSeqRecvd, (uint)packetType, 0U); stream.HashAndEncrypt(MessageSignatureBytes, PacketHeaderByteSize, SymmetricCipher); }
protected bool ReadPacketHeader(BitStream stream) { var packetType = (NetPacketType)stream.ReadInt(2); var sequenceNumber = stream.ReadInt(5); /*var dataPacketFlag = */ stream.ReadFlag(); sequenceNumber = sequenceNumber | (stream.ReadInt(SequenceNumberBitSize - 5) << 5); var highestAck = stream.ReadInt(AckSequenceNumberBitSize); var padBits = stream.ReadInt(PacketHeaderPadBits); if (padBits != 0) { return(false); } sequenceNumber |= (uint)(LastSeqRecvd & SequenceNumberMask); if (sequenceNumber < LastSeqRecvd) { sequenceNumber += SequenceNumberWindowSize; } if (sequenceNumber - LastSeqRecvd > (MaxPacketWindowSize - 1)) { return(false); } highestAck |= (uint)(HighestAckedSeq & AckSequenceNumberMask); if (highestAck < HighestAckedSeq) { highestAck += AckSequenceNumberWindowSize; } if (highestAck > LastSendSeq) { return(false); } if (SymmetricCipher != null) { SymmetricCipher.SetupCounter(sequenceNumber, highestAck, (uint)packetType, 0); if (!stream.DecryptAndCheckHash(MessageSignatureBytes, PacketHeaderByteSize, SymmetricCipher)) { Console.WriteLine("Packet failed crypto"); return(false); } } var ackByteCount = stream.ReadRangedU32(0, MaxAckByteCount); if (ackByteCount > MaxAckByteCount || packetType >= NetPacketType.InvalidPacketType) { return(false); } var ackMask = new uint[MaxAckMaskSize]; var ackWordCount = (ackByteCount + 3) >> 2; for (var i = 0U; i < ackWordCount; ++i) { ackMask[i] = stream.ReadInt((byte)(i == ackWordCount - 1 ? (ackByteCount - (i * 4)) * 8 : 32)); } var sendDelay = (stream.ReadInt(8) << 3) + 4; var ackMaskShift = sequenceNumber - LastSeqRecvd; while (ackMaskShift > 32) { for (var i = MaxAckMaskSize - 1; i > 0; --i) { AckMask[i] = AckMask[i - 1]; } AckMask[0] = 0; ackMaskShift -= 32; } var upShifted = packetType == NetPacketType.DataPacket ? 1U : 0U; for (var i = 0U; i < MaxAckMaskSize; ++i) { var nextShift = AckMask[i] >> (int)(32 - ackMaskShift); AckMask[i] = (AckMask[i] << (int)ackMaskShift) | upShifted; upShifted = nextShift; } var notifyCount = highestAck - HighestAckedSeq; for (var i = 0U; i < notifyCount; ++i) { var notifyIndex = HighestAckedSeq + i + 1; var ackMaskBit = (highestAck - notifyIndex) & 0x1FU; var ackMaskWord = (highestAck - notifyIndex) >> 5; var packetTransmitSuccess = (ackMask[ackMaskWord] & (1U << (int)ackMaskBit)) != 0U; HighestAckedSendTime = 0; HandleNotify(notifyIndex, packetTransmitSuccess); if (HighestAckedSendTime > 0) { var roundTripDelta = Interface.GetCurrentTime() - (HighestAckedSendTime + (int)sendDelay); RoundTripTime = RoundTripTime * 0.9f + roundTripDelta * 0.1f; if (RoundTripTime < 0.0f) { RoundTripTime = 0.0f; } } if (packetTransmitSuccess) { LastRecvAckAck = LastSeqRecvdAtSend[notifyIndex & PacketWindowMask]; } } if (sequenceNumber - LastRecvAckAck > MaxPacketWindowSize) { LastRecvAckAck = sequenceNumber - MaxPacketWindowSize; } HighestAckedSeq = highestAck; PingSendCount = 0; LastPingSendTime = 0; KeepAlive(); var prevLastSequence = LastSeqRecvd; LastSeqRecvd = sequenceNumber; if (packetType == NetPacketType.PingPacket || (sequenceNumber - LastRecvAckAck > (MaxPacketWindowSize >> 1))) { SendAckPacket(); } return(prevLastSequence != sequenceNumber && packetType == NetPacketType.DataPacket); }