public static void OnLeaseBreakNotification(ushort newEpoch, LEASE_BREAK_Notification_Packet_Flags_Values flags,
                                                    uint currentLeaseState, uint newLeaseState)
        {
            Condition.IsTrue(state == ModelState.Connected);
            Condition.IsNotNull(smb2Lease);

            Condition.IsTrue(newEpoch == smb2Lease.Epoch);

            Condition.IsFalse(currentLeaseState == (uint)LeaseStateValues.SMB2_LEASE_NONE);

            // 3.3.4.7   Object Store Indicates a Lease Break
            Condition.IsTrue(currentLeaseState == smb2Lease.LeaseState);
            // According to 3.3.1.4   Algorithm for Leasing in an Object Store,
            // newLeaseState should not contain other lease state except smb2Lease.BreakToLeaseState
            Condition.IsTrue((newLeaseState | smb2Lease.BreakToLeaseState) == smb2Lease.BreakToLeaseState);

            #region Handle LeaseBreakNotification
            if (smb2Lease.LeaseState == (uint)LeaseStateValues.SMB2_LEASE_READ_CACHING)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.7: If Lease.LeaseState is SMB2_LEASE_READ_CACHING, " +
                    "the server MUST set the Flags field of the message to zero and MUST set Open.OplockState to None for all opens in Lease.LeaseOpens. " +
                    "The server MUST set Lease.Breaking to FALSE, and the LeaseKey field MUST be set to Lease.LeaseKey. ");
                ModelHelper.Log(LogType.TestInfo, "Lease.LeaseState is SMB2_LEASE_READ_CACHING.");
                Condition.IsFalse(smb2Lease.Breaking);
                smb2Lease.LeaseState = (uint)newLeaseState;
            }
            else
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.7: Otherwise the server MUST set the Flags field of the message to SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED, " +
                    "indicating to the client that lease acknowledgment is required.");
                ModelHelper.Log(LogType.TestInfo, "Lease.LeaseState is not SMB2_LEASE_READ_CACHING.");
                Condition.IsTrue(flags == LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);

                ModelHelper.Log(
                    LogType.Requirement,
                    "The server MUST set the CurrentLeaseState field of the message to Lease.LeaseState, set Lease.Breaking to TRUE, " +
                    "set Lease.BreakToLeaseState to the new lease state indicated by the object store");
                Condition.IsTrue(smb2Lease.Breaking);

                // smb2Lease.LeaseState is SMB2_LEASE_WRITE_CACHING or SMB2_LEASE_HANDLE_CACHING,
                // so when lease break, BreakToLeaseState should not contain SMB2_LEASE_WRITE_CACHING or SMB2_LEASE_HANDLE_CACHING
                Condition.IsTrue((smb2Lease.BreakToLeaseState & (uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING) == 0 ||
                                 (smb2Lease.BreakToLeaseState & (uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING) == 0);
            }

            #endregion
        }
        public Smb2LeaseBreakNotificationPacket CreateLeaseBreakNotificationResponse(
            Smb2Endpoint endpoint,
            LEASE_BREAK_Notification_Packet_Flags_Values flags,
            byte[] leaseKey,
            LeaseStateValues currentLeaseState,
            LeaseStateValues newLeaseState
            )
        {
            Smb2LeaseBreakNotificationPacket packet = new Smb2LeaseBreakNotificationPacket();

            packet.Header.Flags = Packet_Header_Flags_Values.FLAGS_SERVER_TO_REDIR;
            packet.Header.Command = Smb2Command.OPLOCK_BREAK;
            packet.Header.MessageId = ulong.MaxValue;
            packet.Header.ProtocolId = Smb2Consts.Smb2ProtocolId;
            packet.Header.Signature = new byte[Smb2Consts.SignatureSize];
            packet.Header.StructureSize = Packet_Header_StructureSize_Values.V1;

            packet.Endpoint = endpoint;

            packet.PayLoad.AccessMaskHint = LEASE_BREAK_Notification_Packet_AccessMaskHint_Values.V1;
            packet.PayLoad.BreakReason = LEASE_BREAK_Notification_Packet_BreakReason_Values.V1;
            packet.PayLoad.CurrentLeaseState = currentLeaseState;
            packet.PayLoad.Flags = LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
            packet.PayLoad.LeaseKey = leaseKey;
            packet.PayLoad.NewLeaseState = newLeaseState;
            packet.PayLoad.Reserved = LEASE_BREAK_Notification_Packet_Reserved_Values.V1;
            packet.PayLoad.ShareMaskHint = LEASE_BREAK_Notification_Packet_ShareMaskHint_Values.V1;
            packet.PayLoad.StructureSize = LEASE_BREAK_Notification_Packet_StructureSize_Values.V1;

            packet.Sign();

            return packet;
        }
        public static void OnLeaseBreakNotification(ushort newEpoch, LEASE_BREAK_Notification_Packet_Flags_Values flags,
            uint currentLeaseState, uint newLeaseState)
        {
            Condition.IsTrue(state == ModelState.Connected);
            Condition.IsNotNull(smb2Lease);

            Condition.IsTrue(newEpoch == smb2Lease.Epoch);

            Condition.IsFalse(currentLeaseState == (uint)LeaseStateValues.SMB2_LEASE_NONE);

            // 3.3.4.7   Object Store Indicates a Lease Break
            Condition.IsTrue(currentLeaseState == smb2Lease.LeaseState);
            // According to 3.3.1.4   Algorithm for Leasing in an Object Store,
            // newLeaseState should not contain other lease state except smb2Lease.BreakToLeaseState
            Condition.IsTrue((newLeaseState | smb2Lease.BreakToLeaseState) == smb2Lease.BreakToLeaseState);

            #region Handle LeaseBreakNotification
            if (smb2Lease.LeaseState == (uint)LeaseStateValues.SMB2_LEASE_READ_CACHING)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.7: If Lease.LeaseState is SMB2_LEASE_READ_CACHING, " +
                    "the server MUST set the Flags field of the message to zero and MUST set Open.OplockState to None for all opens in Lease.LeaseOpens. " +
                    "The server MUST set Lease.Breaking to FALSE, and the LeaseKey field MUST be set to Lease.LeaseKey. ");
                ModelHelper.Log(LogType.TestInfo, "Lease.LeaseState is SMB2_LEASE_READ_CACHING.");
                Condition.IsFalse(smb2Lease.Breaking);
                smb2Lease.LeaseState = (uint)newLeaseState;
            }
            else
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.7: Otherwise the server MUST set the Flags field of the message to SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED, " +
                    "indicating to the client that lease acknowledgment is required.");
                ModelHelper.Log(LogType.TestInfo, "Lease.LeaseState is not SMB2_LEASE_READ_CACHING.");
                Condition.IsTrue(flags == LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);

                ModelHelper.Log(
                    LogType.Requirement,
                    "The server MUST set the CurrentLeaseState field of the message to Lease.LeaseState, set Lease.Breaking to TRUE, " +
                    "set Lease.BreakToLeaseState to the new lease state indicated by the object store");
                Condition.IsTrue(smb2Lease.Breaking);

                // smb2Lease.LeaseState is SMB2_LEASE_WRITE_CACHING or SMB2_LEASE_HANDLE_CACHING,
                // so when lease break, BreakToLeaseState should not contain SMB2_LEASE_WRITE_CACHING or SMB2_LEASE_HANDLE_CACHING
                Condition.IsTrue((smb2Lease.BreakToLeaseState & (uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING) == 0
                    || (smb2Lease.BreakToLeaseState & (uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING) == 0);
            }

            #endregion
        }