public static void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            VerifyConnection(connectionId);
            Condition.IsNull(ConnectionList[connectionId].Request);

            #region Combinations

            Combination.NWise(1, connectionId, sessionId, previousSessionId, signed, flags, user);
            #endregion

            #region Other contraints

            // Do not estabilish 2nd session if no session exist yet
            Condition.IfThen(GlobalSessionTable.Count == 0,
                             sessionId != ModelSessionId.AlternativeSessionId &&
                             user == ModelUser.DefaultUser);

            // Do not establish new session if there's one in the requested connection
            Condition.IfThen(ConnectionList[connectionId].Session != null, sessionId != ModelSessionId.ZeroSessionId);

            // Do not establish new session if 2 sessions exist
            Condition.IfThen(GlobalSessionTable.Count == 2, sessionId != ModelSessionId.ZeroSessionId);

            // Do not set previousSessionId to session1 if currently establish session1
            Condition.IfThen(GlobalSessionTable.Count == 0 &&
                             sessionId == ModelSessionId.ZeroSessionId,
                             previousSessionId != ModelSessionId.MainSessionId);

            // If session id is zero, it's the same that the binding flag is set or not.
            Condition.IfThen(sessionId == ModelSessionId.ZeroSessionId, flags == ModelFlags.NotBinding);

            // Restrict the condition to no session exist yet as we only simulate one session in this Model
            Condition.IsNull(ConnectionList[connectionId].Session);

            // If we need to skip SessionSetup when it's re-auth an existing one
            if (ReAuthentication == ModelAllowReauthentication.NotAllowReauthentication)
            {
                Condition.IsTrue(ConnectionList[connectionId].Session == null ||
                                 ConnectionList[connectionId].Session.State != ModelSessionState.Valid);
            }

            #endregion

            ConnectionList[connectionId].Request = new ModelSessionSetupRequest(
                connectionId,
                sessionId,
                previousSessionId,
                signed == ModelSigned.SignFlagSet,
                flags,
                user);
        }
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
                case ModelFlags.Binding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                        break;
                    }
                case ModelFlags.NotBinding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                        break;
                    }
                default:
                    throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
                case ModelUser.DefaultUser:
                    {
                        credential = testConfig.AccountCredential;
                        break;
                    }
                case ModelUser.DiffUser:
                    {
                        credential = testConfig.NonAdminAccountCredential;
                        break;
                    }
                default:
                    throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response? sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection
                && sessionId == ModelSessionId.MainSessionId
                && connectionList[connectionId].SessionKey == null
                && connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
                {
                    sessionSetupResponse = response;
                });

            if (status != Smb2Status.STATUS_SUCCESS
                && status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId)
                && (status == Smb2Status.STATUS_SUCCESS
                || status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values  headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential           credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
            case ModelFlags.Binding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                break;
            }

            case ModelFlags.NotBinding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                break;
            }

            default:
                throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
            case ModelUser.DefaultUser:
            {
                credential = testConfig.AccountCredential;
                break;
            }

            case ModelUser.DiffUser:
            {
                credential = testConfig.NonAdminAccountCredential;
                break;
            }

            default:
                throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response?sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection &&
                sessionId == ModelSessionId.MainSessionId &&
                connectionList[connectionId].SessionKey == null &&
                connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
            {
                sessionSetupResponse = response;
            });

            if (status != Smb2Status.STATUS_SUCCESS &&
                status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId) &&
                (status == Smb2Status.STATUS_SUCCESS ||
                 status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }