/// <summary> /// Sets up .NET Remoting Lifetime Services and TCP Channel for this AppDomain. /// /// @comment WARNING: If you need to change the parameters of the Constructor, /// you also need to change the parameters in the .NET Reflection call in /// TClientAppDomainConnection! /// /// </summary> /// <param name="AClientID">ClientID as assigned by the ClientManager</param> /// <param name="AClientServerConnectionType">Tells in which way the Client connected /// to the PetraServer</param> /// <param name="AClientManagerRef">A reference to the ClientManager object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ASystemDefaultsCacheRef">A reference to the SystemDefaultsCache object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ACacheableTablesManagerRef"></param> /// <param name="AUserInfo">An instantiated PetraPrincipal Object, containing User /// information /// </param> public TClientDomainManager(String AClientID, TClientServerConnectionType AClientServerConnectionType, TClientManagerCallForwarder AClientManagerRef, TSystemDefaultsCache ASystemDefaultsCacheRef, TCacheableTablesManager ACacheableTablesManagerRef, IPrincipal AUserInfo) : base(AClientID, AClientServerConnectionType, AClientManagerRef, ((TPetraPrincipal)AUserInfo).UserID) { TCacheableTablesManager.GCacheableTablesManager = ACacheableTablesManagerRef; TSystemDefaultsCache.GSystemDefaultsCache = ASystemDefaultsCacheRef; TLanguageCulture.Init(); UserInfo.GUserInfo = (TPetraPrincipal)AUserInfo; DomainManager.GSiteKey = TSystemDefaultsCache.GSystemDefaultsCache.GetInt64Default(SharedConstants.SYSDEFAULT_SITEKEY); if (DomainManager.GSiteKey <= 0) { // this is for connecting to legacy database format // we cannot add SiteKey to SystemDefaults, because Petra 2.3 would have a conflict since it adds it on startup already to the in-memory defaults, but not to the database // see also https://sourceforge.net/apps/mantisbt/openpetraorg/view.php?id=114 DomainManager.GSiteKey = TSystemDefaultsCache.GSystemDefaultsCache.GetInt64Default("SiteKeyPetra2"); } if (DomainManager.GSiteKey <= 0) { // this can happen either with a legacy Petra 2.x database or with a fresh OpenPetra database without any ledger yet Console.WriteLine("there is no SiteKey or SiteKeyPetra2 record in s_system_defaults"); DomainManager.GSiteKey = 99000000; } }
/// <summary> /// Constructor for passing in parameters. /// </summary> public TClientStillAliveCheck(TConnectedClient AConnectedClient, TClientServerConnectionType AClientServerConnectionType, TDelegateTearDownAppDomain ATearDownAppDomain, string AUser = "") { FClientObject = AConnectedClient; ClientName = FClientObject.ClientName; // Note: calls to TLogging here only go to the console. The log file doesn't get initialised in TLogging until TClientDomainManager.EstablishDBConnection() TLogging.LogAtLevel(10, "TClientStillAliveCheck (for ClientName '" + ClientName + "'') created"); Int32 ClientStillAliveTimeout = TAppSettingsManager.GetInt32("Server.ClientKeepAliveTimeoutAfterXSeconds_LAN", 60); UClientStillAliveTimeout = ClientStillAliveTimeout; UClientStillAliveCheckInterval = TAppSettingsManager.GetInt32("Server.ClientKeepAliveCheckIntervalInSeconds", 60); UTearDownAppDomain = ATearDownAppDomain; // UTearDownAppDomainToken = ATearDownAppDomainToken; TLogging.LogAtLevel(2, "ClientStillAliveTimeout: " + ClientStillAliveTimeout.ToString() + "; " + "ClientKeepAliveCheckIntervalInSeconds: " + UClientStillAliveCheckInterval.ToString()); // Start ClientStillAliveCheckThread UKeepServerAliveCheck = true; UClientStillAliveCheckThread = new Thread(new ThreadStart(ClientStillAliveCheckThread)); UClientStillAliveCheckThread.Name = "ClientStillAliveCheckThread" + Guid.NewGuid().ToString(); UClientStillAliveCheckThread.IsBackground = true; UClientStillAliveCheckThread.Start(); TLogging.LogAtLevel(10, "TClientStillAliveCheck (for ClientName '" + ClientName + "'): started " + UClientStillAliveCheckThread.Name); }
/// <summary> /// constructor /// </summary> public TClientDomainManager(String AClientID, TClientServerConnectionType AClientServerConnectionType, TClientManagerCallForwarder AClientManagerRef, ISystemDefaultsCache ASystemDefaultsCacheRef, ICacheableTablesManager ACacheableTablesManagerRef, IPrincipal AUserInfo) : base(AClientID, AClientServerConnectionType, AClientManagerRef, "007") { }
/// <summary> /// Loads the ClientDomain DLL into the Client's AppDomain, instantiates the /// main Class (TClientDomainManager) and initialises the AppDomain by calling /// several functions of that Class. /// /// </summary> /// <param name="AClientID">ClientID as assigned by the ClientManager</param> /// <param name="AClientServerConnectionType">Tells in which way the Client connected /// to the PetraServer</param> /// <param name="AClientManagerRef">A reference to the ClientManager object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ASystemDefaultsCacheRef">A reference to the SystemDefaultsCache object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ACacheableTablesManagerRef"></param> /// <param name="AUserInfo">An instantiated PetraPrincipal Object, containing User /// information</param> /// <param name="AServerSettings">A copy of the ServerSettings</param> /// <param name="ARemotingURLPollClientTasks">The .NET Remoting URL of the /// TPollClientTasks Class which the Client needs to calls to retrieve /// ClientTasks.</param> /// <param name="ARemotedPollClientTasksObject"></param> public void LoadDomainManagerAssembly(Int32 AClientID, TClientServerConnectionType AClientServerConnectionType, TClientManagerCallForwarder AClientManagerRef, object ASystemDefaultsCacheRef, object ACacheableTablesManagerRef, IPrincipal AUserInfo, TSrvSetting AServerSettings, out String ARemotingURLPollClientTasks, out ICrossDomainService ARemotedPollClientTasksObject) { // Console.WriteLine('TRemoteLoader.LoadDomainManagerAssembly in AppDomain: ' + AppDomain.CurrentDomain.ToString); Assembly LoadedAssembly = Assembly.Load(CLIENTDOMAIN_DLLNAME); FRemoteClientDomainManagerClass = LoadedAssembly.GetType(CLIENTDOMAIN_CLASSNAME); FRemoteClientDomainManagerObject = Activator.CreateInstance(FRemoteClientDomainManagerClass, (BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance), null, new Object[] { AClientID.ToString(), AClientServerConnectionType, AClientManagerRef, ASystemDefaultsCacheRef, ACacheableTablesManagerRef, AUserInfo }, null); FRemoteClientDomainManagerClass.InvokeMember("InitAppDomain", (BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod), null, FRemoteClientDomainManagerObject, new Object[] { AServerSettings }); // Create and remote the TPollClientTasks Class ARemotingURLPollClientTasks = Convert.ToString(FRemoteClientDomainManagerClass.InvokeMember("GetPollClientTasksURL", (BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod), null, FRemoteClientDomainManagerObject, null, null)); ARemotedPollClientTasksObject = (ICrossDomainService)FRemoteClientDomainManagerClass.InvokeMember("GetRemotedPollClientTasksObject", (BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod), null, FRemoteClientDomainManagerObject, null, null); // Establish (separate) DataBase connection for the AppDomain Convert.ToString(FRemoteClientDomainManagerClass.InvokeMember("EstablishDBConnection", (BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod), null, FRemoteClientDomainManagerObject, null, null)); // Perform any other initialisation required by the AppDomain FRemoteClientDomainManagerClass.InvokeMember("PostAppDomainSetupInitialisation", (BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod), null, FRemoteClientDomainManagerObject, null, null); // LoadClientDomainManager.ClientTaskAdd('USERMESSAGE','This is just for testing purposes!', 'blabla_1', 'blabla_2', 'blabla_3', 'blabla_4', 1); }
/// <summary> /// Constructor for passing in parameters. /// </summary> public TClientStillAliveCheck(TConnectedClient AConnectedClient, TClientServerConnectionType AClientServerConnectionType, TDelegateTearDownAppDomain ATearDownAppDomain, string AUser = "") { FClientObject = AConnectedClient; ClientName = FClientObject.ClientName; Int32 ClientStillAliveTimeout; // Note: calls to TLogging here only go to the console. The log file doesn't get initialised in TLogging until TClientDomainManager.EstablishDBConnection() TLogging.LogAtLevel(10, "TClientStillAliveCheck (for ClientName '" + ClientName + "'') created"); // Determine timeout limit (different for Clients connected via LAN or Remote) if (AClientServerConnectionType == TClientServerConnectionType.csctRemote) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsRemote; } else if (AClientServerConnectionType == TClientServerConnectionType.csctLAN) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } else { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } UClientStillAliveTimeout = ClientStillAliveTimeout; UClientStillAliveCheckInterval = TSrvSetting.ClientKeepAliveCheckIntervalInSeconds; UTearDownAppDomain = ATearDownAppDomain; // UTearDownAppDomainToken = ATearDownAppDomainToken; TLogging.LogAtLevel(2, "ClientStillAliveTimeout: " + ClientStillAliveTimeout.ToString() + "; " + "ClientKeepAliveCheckIntervalInSeconds: " + UClientStillAliveCheckInterval.ToString()); // Start ClientStillAliveCheckThread UKeepServerAliveCheck = true; UClientStillAliveCheckThread = new Thread(new ThreadStart(ClientStillAliveCheckThread)); UClientStillAliveCheckThread.Name = "ClientStillAliveCheckThread" + Guid.NewGuid().ToString(); UClientStillAliveCheckThread.IsBackground = true; UClientStillAliveCheckThread.Start(); TLogging.LogAtLevel(10, "TClientStillAliveCheck (for ClientName '" + ClientName + "'): started " + UClientStillAliveCheckThread.Name); }
/// <summary> /// Initialises fields. /// /// </summary> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="AUserID">AUserID for which the AppDomain was created</param> /// <param name="AClientName">Server-assigned name of the Client</param> /// <param name="AClientComputerName">Computer name of the Client</param> /// <param name="AClientIPAddress">IP Address of the Client</param> /// <param name="AClientServerConnectionType">Type of the connection (eg. LAN, Remote)</param> /// <param name="AAppDomainName">Server-assigned name of the Client AppDomain /// </param> /// <returns>void</returns> public TConnectedClient(System.Int32 AClientID, String AUserID, String AClientName, String AClientComputerName, String AClientIPAddress, TClientServerConnectionType AClientServerConnectionType, String AAppDomainName) { FClientID = AClientID; FUserID = AUserID; FClientName = AClientName; FClientComputerName = AClientComputerName; FClientIPAddress = AClientIPAddress; FClientServerConnectionType = AClientServerConnectionType; FClientConnectionStartTime = DateTime.Now; FAppDomainName = AAppDomainName; FAppDomainStatus = TSessionStatus.adsConnectingLoginVerification; FDisconnectClientMonitor = new System.Object(); }
/// <summary> /// Constructor for passing in parameters. /// </summary> public TClientStillAliveCheck(TConnectedClient AConnectedClient, TClientServerConnectionType AClientServerConnectionType, TDelegateTearDownAppDomain ATearDownAppDomain) { FClientObject = AConnectedClient; ClientName = FClientObject.ClientName; Int32 ClientStillAliveTimeout; TLogging.LogAtLevel(2, "TClientStillAliveCheck (for ClientName '" + ClientName + "'') created"); // Determine timeout limit (different for Clients connected via LAN or Remote) if (AClientServerConnectionType == TClientServerConnectionType.csctRemote) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsRemote; } else if (AClientServerConnectionType == TClientServerConnectionType.csctLAN) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } else { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } UClientStillAliveTimeout = ClientStillAliveTimeout; UClientStillAliveCheckInterval = TSrvSetting.ClientKeepAliveCheckIntervalInSeconds; UTearDownAppDomain = ATearDownAppDomain; // UTearDownAppDomainToken = ATearDownAppDomainToken; TLogging.LogAtLevel(2, "ClientStillAliveTimeout: " + ClientStillAliveTimeout.ToString() + "; " + "ClientKeepAliveCheckIntervalInSeconds: " + UClientStillAliveCheckInterval.ToString()); // Start ClientStillAliveCheckThread UKeepServerAliveCheck = true; UClientStillAliveCheckThread = new Thread(new ThreadStart(ClientStillAliveCheckThread)); UClientStillAliveCheckThread.Name = "ClientStillAliveCheckThread" + Guid.NewGuid().ToString(); UClientStillAliveCheckThread.IsBackground = true; UClientStillAliveCheckThread.Start(); TLogging.LogAtLevel(2, "TClientStillAliveCheck (for ClientName '" + ClientName + "'): started ClientStillAliveCheckThread."); }
/** * Constructor for passing in parameters. * * @param AClientServerConnectionType Type of Client connection * @param ATearDownAppDomain Delegate that is called once * ClientStillAliveCheckThread finds out that the Client is no longer 'alive' * @param ATearDownAppDomainToken Security Token. Prevents against unauthorized * tearing down of the Client's AppDomain. * */ public TClientStillAliveCheck(TClientServerConnectionType AClientServerConnectionType, TDelegateTearDownAppDomain ATearDownAppDomain, String ATearDownAppDomainToken) { Int32 ClientStillAliveTimeout; if (TLogging.DL >= 10) { Console.WriteLine("{0} TClientStillAliveCheck created", DateTime.Now); } // Determine timeout limit (different for Clients connected via LAN or Remote) if (AClientServerConnectionType == TClientServerConnectionType.csctRemote) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsRemote; } else if (AClientServerConnectionType == TClientServerConnectionType.csctLAN) { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } else { ClientStillAliveTimeout = TSrvSetting.ClientKeepAliveTimeoutAfterXSecondsLAN; } UClientStillAliveTimeout = ClientStillAliveTimeout; UClientStillAliveCheckInterval = TSrvSetting.ClientKeepAliveCheckIntervalInSeconds; UTearDownAppDomain = ATearDownAppDomain; UTearDownAppDomainToken = ATearDownAppDomainToken; // Start ClientStillAliveCheckThread UKeepServerAliveCheck = true; UClientStillAliveCheckThread = new Thread(new ThreadStart(ClientStillAliveCheckThread)); UClientStillAliveCheckThread.IsBackground = true; UClientStillAliveCheckThread.Start(); if (TLogging.DL >= 10) { Console.WriteLine("{0} TClientStillAliveCheck: started ClientStillAliveCheckThread.", DateTime.Now); } }
/// <summary> /// Loads the ClientDomain DLL into the Client's AppDomain, instantiates the /// main Class (TClientDomainManager) and initialises the AppDomain by calling /// several functions of that Class. /// /// </summary> /// <param name="AClientID">ClientID as assigned by the ClientManager</param> /// <param name="AClientServerConnectionType">Tells in which way the Client connected /// to the PetraServer</param> /// <param name="AClientManagerRef">A reference to the ClientManager object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ASystemDefaultsCacheRef">A reference to the SystemDefaultsCache object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="ACacheableTablesManagerRef"></param> /// <param name="AUserInfo">An instantiated PetraPrincipal Object, containing User /// information</param> /// <param name="ARemotingURLPollClientTasks">the .NET Remoting URL of the /// TPollClientTasks Class which the Client needs to calls to retrieve /// ClientTasks.</param> /// <returns>void</returns> public void LoadDomainManagerAssembly(Int32 AClientID, TClientServerConnectionType AClientServerConnectionType, TClientManagerCallForwarder AClientManagerRef, object ASystemDefaultsCacheRef, object ACacheableTablesManagerRef, IPrincipal AUserInfo, out String ARemotingURLPollClientTasks) { ICrossDomainService RemoteObject; FRemoteLoader.LoadDomainManagerAssembly(AClientID, AClientServerConnectionType, AClientManagerRef, ASystemDefaultsCacheRef, ACacheableTablesManagerRef, AUserInfo, TSrvSetting.ServerSettings, out ARemotingURLPollClientTasks, out RemoteObject); // register the remote url at the CrossDomainMarshaller TCrossDomainMarshaller.AddService(AClientID.ToString(), ARemotingURLPollClientTasks, RemoteObject); // Load the CallForwinding DLL into the Client's AppDomain FRemoteLoader.LoadCallForwardingAssembly(); // IMPORTANT: If the following code is uncommented, the ClientDomain DLL that is loaded only in the Client's AppDomain might get loaded into the Default AppDomain that's what we don't want!!! // Use this therefore only to find out what DLL's are loaded in the Client's AppDomain!!!!!! if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + AppDomain.CurrentDomain.FriendlyName + ": (after instantiation of TClientDomainManager)", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in AppDomain.CurrentDomain.GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } }
/// connect the client to the server public eLoginEnum ConnectClient(String AUserName, String APassword, String AClientComputerName, String AClientIPAddress, System.Version AClientExeVersion, TClientServerConnectionType AClientServerConnectionType, out Int32 AClientID, out String AWelcomeMessage, out Boolean ASystemEnabled, out IPrincipal AUserInfo) { AWelcomeMessage = string.Empty; ASystemEnabled = true; AUserInfo = null; AClientID = -1; THttpConnector.InitConnection(TAppSettingsManager.GetValue("OpenPetra.HTTPServer")); SortedList <string, object> Parameters = new SortedList <string, object>(); Parameters.Add("username", AUserName); Parameters.Add("password", APassword); Parameters.Add("version", AClientExeVersion.ToString()); List <object> ResultList = THttpConnector.CallWebConnector("SessionManager", "LoginClient", Parameters, "list"); eLoginEnum Result = (eLoginEnum)ResultList[0]; if (Result != eLoginEnum.eLoginSucceeded) { // failed login return(Result); } AClientID = (Int32)ResultList[1]; AWelcomeMessage = (string)ResultList[2]; ASystemEnabled = (Boolean)ResultList[3]; AUserInfo = (IPrincipal)ResultList[4]; return(eLoginEnum.eLoginSucceeded); }
/// connect the client to the server public eLoginEnum ConnectClient(String AUserName, String APassword, String AClientComputerName, String AClientIPAddress, System.Version AClientExeVersion, TClientServerConnectionType AClientServerConnectionType, out Int32 AClientID, out String AWelcomeMessage, out Boolean ASystemEnabled, out IPrincipal AUserInfo) { AWelcomeMessage = string.Empty; ASystemEnabled = true; AUserInfo = null; AClientID = -1; THttpConnector.InitConnection(TAppSettingsManager.GetValue("OpenPetra.HTTPServer")); SortedList <string, object>Parameters = new SortedList <string, object>(); Parameters.Add("username", AUserName); Parameters.Add("password", APassword); Parameters.Add("version", AClientExeVersion.ToString()); List <object>ResultList = THttpConnector.CallWebConnector("SessionManager", "LoginClient", Parameters, "list"); eLoginEnum Result = (eLoginEnum)ResultList[0]; if (Result != eLoginEnum.eLoginSucceeded) { // failed login return Result; } AClientID = (Int32)ResultList[1]; AWelcomeMessage = (string)ResultList[2]; ASystemEnabled = (Boolean)ResultList[3]; AUserInfo = (IPrincipal)ResultList[4]; return eLoginEnum.eLoginSucceeded; }
/// <summary> /// Sets up .NET Remoting Lifetime Services and TCP Channel for this AppDomain. /// /// @comment WARNING: If you need to change the parameters of the Constructor, /// you also need to change the parameters in the .NET Reflection call in /// TClientAppDomainConnection! /// /// </summary> /// <param name="AClientID">ClientID as assigned by the ClientManager</param> /// <param name="AClientServerConnectionType">Tells in which way the Client connected /// to the PetraServer</param> /// <param name="AClientManagerRef">A reference to the ClientManager object /// (Note: .NET Remoting will be working behind the scenes since calls to /// this Object will cross AppDomains!)</param> /// <param name="AUserID"></param> /// <returns>void</returns> public TClientDomainManagerBase(String AClientID, TClientServerConnectionType AClientServerConnectionType, TClientManagerCallForwarder AClientManagerRef, string AUserID) { new TAppSettingsManager(false); FUserID = AUserID; // Console.WriteLine('TClientDomainManager.Create in AppDomain: ' + Thread.GetDomain().FriendlyName); DomainManagerBase.GClientID = Convert.ToInt16(AClientID); DomainManagerBase.UClientManagerCallForwarderRef = AClientManagerRef; FClientServerConnectionType = AClientServerConnectionType; FClientTasksManager = new TClientTasksManager(); FTearDownAppDomainMonitor = new System.Object(); Random random = new Random(); FRandomAppDomainTearDownToken = random.Next(Int32.MinValue, Int32.MaxValue).ToString(); // // Set up .NET Remoting Lifetime Services and TCP Channel for this AppDomain. // Note: .NET Remoting needs to be set up separately for each AppDomain, and settings in // the .NET (Remoting) Configuration File are valid only for the Default AppDomain. // try { // The following settings equal to a config file's // <lifetime leaseTime="10MS" renewOnCallTime="10MS" leaseManagerPollTime = "5MS" /> // setting. // Please note that this breaks remoting on mono, but these settings help on MS .NET // to find any remoted objects whose lifetime was inadvertedly not configured, and // therefore live only very short and calls to them break... // LifetimeServices.LeaseTime := TimeSpan.FromMilliseconds(10); // LifetimeServices.RenewOnCallTime := TimeSpan.FromMilliseconds(10); // LifetimeServices.LeaseManagerPollTime := TimeSpan.FromMilliseconds(5); // More sensible settings for Lifetime Services // TODO 1 ochristiank cRemoting : .NET Remoting LifetimeSettings should be flexible instead hardcoded in the future! try { LifetimeServices.LeaseTime = TimeSpan.FromSeconds(60); LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(60); LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(5); } catch (RemotingException) { // ignore System.Runtime.Remoting.RemotingException : 'LeaseTime' can only be set once within an AppDomain. // this happens in the Server NUnit test, when running several tests, therefore reconnecting with the same AppDomain. } } catch (Exception e) { TLogging.Log(e.ToString()); throw; } if (TLogging.DL >= 4) { Console.WriteLine("Application domain: " + Thread.GetDomain().FriendlyName); Console.WriteLine(" for User: " + FUserID); } }
/// <summary> /// Called by a Client to request connection to the Petra Server. /// /// Authenticate the user and create a sesssion for the user. /// /// </summary> /// <param name="AUserName">Username with which the Client connects</param> /// <param name="APassword">Password with which the Client connects</param> /// <param name="AClientComputerName">Computer name of the Client</param> /// <param name="AClientExeVersion"></param> /// <param name="AClientIPAddress">IP Address of the Client</param> /// <param name="AClientServerConnectionType">Type of the connection (eg. LAN, Remote)</param> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="AWelcomeMessage"></param> /// <param name="ASystemEnabled"></param> /// <param name="ASiteKey"></param> /// <param name="ADataBase"></param> public static TConnectedClient ConnectClient(String AUserName, String APassword, String AClientComputerName, String AClientIPAddress, System.Version AClientExeVersion, TClientServerConnectionType AClientServerConnectionType, out System.Int32 AClientID, out String AWelcomeMessage, out Boolean ASystemEnabled, out System.Int64 ASiteKey, TDataBase ADataBase = null) { TDataBase DBConnectionObj = null; TDBTransaction ReadWriteTransaction = new TDBTransaction(); bool SystemEnabled = true; string WelcomeMessage = String.Empty; Int64 SiteKey = -1; TConnectedClient ConnectedClient = null; if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + " (at call of ConnectClient):", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } /* * Every Client Connection request is coming in in a separate Thread * (.NET Remoting does that for us and this is good!). However, the next block * of code must be executed only by exactly ONE thread at the same time to * preserve the integrity of Client tracking! */ try { // TODORemoting if (Monitor.TryEnter(UConnectClientMonitor, TSrvSetting.ClientConnectionTimeoutAfterXSeconds * 1000)) { if (Thread.CurrentThread.Name == String.Empty) { Thread.CurrentThread.Name = "Client_" + AUserName + "__CLIENTCONNECTION_THREAD"; } #region Logging if (TLogging.DL >= 4) { Console.WriteLine(FormatClientList(false)); Console.WriteLine(FormatClientList(true)); } if (TLogging.DL >= 4) { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToLogfile); } #endregion // check for username, if it is an email address if (AUserName.Contains('@')) { AUserName = GetUserIDFromEmail(AUserName); } #region Variable assignments // we are not really using the ClientID anymore, but the session ID! AClientID = (short)0; string ClientName = AUserName.ToUpper() + "_" + AClientID.ToString(); #endregion ConnectedClient = new TConnectedClient(AClientID, AUserName.ToUpper(), ClientName, AClientComputerName, AClientIPAddress, AClientServerConnectionType, ClientName); #region Client Version vs. Server Version check if (TLogging.DL >= 9) { Console.WriteLine( "Client EXE Program Version: " + AClientExeVersion.ToString() + "; Server EXE Program Version: " + TSrvSetting.ApplicationVersion.ToString()); } if (TSrvSetting.ApplicationVersion.Compare(new TFileVersionInfo(AClientExeVersion)) != 0) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; #region Logging if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion throw new EClientVersionMismatchException(String.Format(StrClientServerExeProgramVersionMismatchMessage, AClientExeVersion.ToString(), TSrvSetting.ApplicationVersion.ToString())); } #endregion #region Login request verification (incl. User authentication) DBConnectionObj = DBAccess.Connect("ConnectClient (User Login)", ADataBase); bool SubmitOK = false; DBConnectionObj.WriteTransaction(ref ReadWriteTransaction, ref SubmitOK, delegate { // Perform login checks such as User authentication and Site Key check try { PerformLoginChecks(AUserName, APassword, AClientComputerName, AClientIPAddress, out SystemEnabled, ReadWriteTransaction); } #region Exception handling catch (EPetraSecurityException) { #region Logging if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log( "Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion ConnectedClient.SessionStatus = TSessionStatus.adsStopped; // We need to set this flag to true here to get the failed login to be stored in the DB!!! SubmitOK = true; throw; } catch (Exception) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; throw; } #endregion // Login Checks were successful! ConnectedClient.SessionStatus = TSessionStatus.adsConnectingLoginOK; // Retrieve Welcome message and SiteKey try { if (UMaintenanceLogonMessage != null) { WelcomeMessage = UMaintenanceLogonMessage.GetLogonMessage(AUserName, true, ReadWriteTransaction); } else { WelcomeMessage = "Welcome"; } // we could do this directly, or via an interface, similar to LogonMessage, see above string sql = "SELECT s_default_value_c FROM s_system_defaults WHERE s_default_code_c = 'SiteKey'"; try { SiteKey = Convert.ToInt64(DBConnectionObj.ExecuteScalar(sql, ReadWriteTransaction)); } catch (EOPDBException) { // there is no site key defined yet. SiteKey = -1; } } catch (Exception) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; throw; } SubmitOK = true; }); #endregion /* * Uncomment the following statement to be able to better test how the * Client reacts when it tries to connect and receives a * ELoginFailedServerTooBusyException. */ // Thread.Sleep(7000); /* * Notify all waiting Clients (that have not timed out yet) that they can * now try to connect... */ // TODORemoting Monitor.PulseAll(UConnectClientMonitor); } // TODORemoting else { /* * Throw Exception to tell any timed-out connecting Client that the Server * is too busy to accept connect requests at the moment. */ // TODORemoting throw new ELoginFailedServerTooBusyException(); } } finally { // TODORemoting Monitor.Exit(UConnectClientMonitor); } ConnectedClient.StartSession(); #region Logging // // Assemblies successfully loaded into Client AppDomain // if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' successfully connected. ClientID: " + AClientID.ToString(), TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' successfully connected. ClientID: " + AClientID.ToString(), TLoggingType.ToLogfile); } #endregion ASystemEnabled = SystemEnabled; AWelcomeMessage = WelcomeMessage; ASiteKey = SiteKey; return(ConnectedClient); }
/// <summary> /// Called by a Client to request connection to the Petra Server. /// /// Creates an AppDomain, loads Petra Module DLL's into it and returns /// .NET Remoting URLs for intantiated objects that represent the Petra Module /// Root Namespaces (eg. MPartner, MFinance). /// /// </summary> /// <param name="AUserName">Username with which the Client connects</param> /// <param name="APassword">Password with which the Client connects</param> /// <param name="AClientComputerName">Computer name of the Client</param> /// <param name="AClientExeVersion"></param> /// <param name="AClientIPAddress">IP Address of the Client</param> /// <param name="AClientServerConnectionType">Type of the connection (eg. LAN, Remote)</param> /// <param name="AClientName">Server-assigned Name of the Client</param> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="ACrossDomainURL">there is only one url now for connecting to the services</param> /// <param name="ARemotingURLs">A HashTable containing .NET Remoting URLs of the Petra /// Module Root Namespaces (eg. MPartner, MFinance) and other important objects /// that need to be called from the Client.</param> /// <param name="AServerOS">Operating System that the Server is running on /// </param> /// <param name="AProcessID"></param> /// <param name="AWelcomeMessage"></param> /// <param name="ASystemEnabled"></param> /// <param name="AUserInfo"></param> /// <returns>void</returns> public void ConnectClient(String AUserName, String APassword, String AClientComputerName, String AClientIPAddress, System.Version AClientExeVersion, TClientServerConnectionType AClientServerConnectionType, out String AClientName, out System.Int32 AClientID, out string ACrossDomainURL, out Hashtable ARemotingURLs, out TExecutingOSEnum AServerOS, out Int32 AProcessID, out String AWelcomeMessage, out Boolean ASystemEnabled, out IPrincipal AUserInfo) { String LoadInAppDomainName; IClientAppDomainConnection ClientDomainManager = null; String RemotingURL_RemotedObject = ""; String RemotingURL_PollClientTasks; TRunningAppDomain AppDomainEntry; String CantDisconnectReason; ACrossDomainURL = CROSSDOMAINURL; if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + " (at call of ConnectClient):", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } /* * Every Client Connection request is coming in in a separate Thread * (.NET Remoting does that for us and this is good!). However, the next block * of code must be executed only by exactly ONE thread at the same time to * preserve the integrity of Client tracking! */ try { if (Monitor.TryEnter(UConnectClientMonitor, TSrvSetting.ClientConnectionTimeoutAfterXSeconds * 1000)) { #region Logging if (TLogging.DL >= 4) { Console.WriteLine(FormatClientList(false)); Console.WriteLine(FormatClientList(true)); } if (TLogging.DL >= 4) { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToLogfile); } #endregion #region Variable assignments ARemotingURLs = new Hashtable(6); AClientID = (short)FClientsConnectedTotal; FClientsConnectedTotal++; AClientName = AUserName.ToUpper() + "_" + AClientID.ToString(); AServerOS = TSrvSetting.ExecutingOS; LoadInAppDomainName = AClientName + "_Domain"; #endregion try { if (Monitor.TryEnter(UClientObjects.SyncRoot)) { // Add the new Client to UClientObjects SortedList UClientObjects.Add((object)AClientID, new TRunningAppDomain(AClientID, AUserName.ToUpper(), AClientName, AClientComputerName, AClientIPAddress, AClientServerConnectionType, LoadInAppDomainName)); } } finally { Monitor.Exit(UClientObjects.SyncRoot); } #region Client Version vs. Server Version check if (TLogging.DL >= 9) { Console.WriteLine( "Client EXE Program Version: " + AClientExeVersion.ToString() + "; Server EXE Program Version: " + TSrvSetting.ApplicationVersion.ToString()); } if (TSrvSetting.ApplicationVersion.Compare(new TFileVersionInfo(AClientExeVersion)) != 0) { ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsStopped; #region Logging if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion throw new EClientVersionMismatchException(String.Format(StrClientServerExeProgramVersionMismatchMessage, AClientExeVersion.ToString(), TSrvSetting.ApplicationVersion.ToString())); } #endregion #region Login request verification (incl. User authentication) // Perform login checks such as User authentication and Site Key check try { AUserInfo = PerformLoginChecks(AUserName, APassword, AClientComputerName, AClientIPAddress, out AProcessID, out ASystemEnabled); } catch (EPetraSecurityException) #region Exception handling { #region Logging if (TLogging.DL >= 4) { TLogging.Log("Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsStopped; throw; } catch (Exception) { ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsStopped; throw; } #endregion // Login Checks were successful! ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsConnectingLoginOK; // Retrieve Welcome message try { if (UMaintenanceLogonMessage != null) { AWelcomeMessage = UMaintenanceLogonMessage.GetLogonMessage(AUserInfo, true); } else { AWelcomeMessage = "Welcome"; } } catch (Exception) { ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsStopped; throw; } if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + " (before new AppDomain load):", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } #region Create new AppDomain for Client, load ClientDomain DLL into it, initialise AppDomain try { try { // The following statement creates a new AppDomain for the connecting // Client and remotes an instance of TRemoteLoader into it. ClientDomainManager = UClientDomainManager.CreateAppDomain(AClientName); if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + ": (after TClientAppDomainConnection.Create)", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } // The following statement loads the ClientDomain DLL into the Client's // AppDomain, instantiates the main Class and initialises the AppDomain ClientDomainManager.LoadDomainManagerAssembly(AClientID, AClientServerConnectionType, FClientManagerCallForwarder, USystemDefaultsCache, UCacheableTablesManager, AUserInfo, out RemotingURL_PollClientTasks); ARemotingURLs.Add(RemotingConstants.REMOTINGURL_IDENTIFIER_POLLCLIENTTASKS, RemotingURL_PollClientTasks); } catch (TargetInvocationException exp) { TLogging.Log( "Error while creating new AppDomain for Client! Exception: " + exp.ToString() + "\r\n" + "InnerException: " + exp.InnerException.ToString()); throw exp.InnerException; } catch (Exception exp) { TLogging.Log( "Error while creating new AppDomain for Client! Exception: " + exp.ToString()); throw; } } catch (Exception) { // we should cleanly shut down the appdomain, to avoid exception: // System.Net.Sockets.SocketException: Address already in use AppDomainEntry = (TRunningAppDomain)UClientObjects[(object)AClientID]; if ((AppDomainEntry == null) || (ClientDomainManager == null)) { // Application domain was not setup yet AppDomainEntry.AppDomainStatus = TAppDomainStatus.adsStopped; } else { AppDomainEntry.PassInClientRemotingInfo(RemotingURL_RemotedObject, ClientDomainManager); ServerDisconnectClient(AClientID, out CantDisconnectReason); } throw; } #endregion if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + " (after new AppDomain load):", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } ((TRunningAppDomain)UClientObjects[(object)AClientID]).PassInClientRemotingInfo(RemotingURL_RemotedObject, ClientDomainManager); ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsConnectingAppDomainSetupOK; /* * Uncomment the following statement to be able to better test how the * Client reacts when it tries to connect and receives a * ELoginFailedServerTooBusyException. */ // Thread.Sleep(7000); /* * Notify all waiting Clients (that have not timed out yet) that they can * now try to connect... */ Monitor.PulseAll(UConnectClientMonitor); } else { /* * Throw Exception to tell any timed-out connecting Client that the Server * is too busy to accept connect requests at the moment. */ throw new ELoginFailedServerTooBusyException(); } } finally { Monitor.Exit(UConnectClientMonitor); } ClientDomainManager.LoadAssemblies(AClientID.ToString(), AUserInfo, ref ARemotingURLs); ((TRunningAppDomain)UClientObjects[(object)AClientID]).AppDomainStatus = TAppDomainStatus.adsActive; ((TRunningAppDomain)UClientObjects[(object)AClientID]).FClientConnectionFinishedTime = DateTime.Now; #region Logging // // Assemblies successfully loaded into Client AppDomain // if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' successfully connected (took " + ((TRunningAppDomain)UClientObjects[(object)AClientID]).FClientConnectionFinishedTime.Subtract( ((TRunningAppDomain)UClientObjects[(object)AClientID]).FClientConnectionStartTime). TotalSeconds.ToString() + " sec). ClientID: " + AClientID.ToString(), TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' successfully connected. ClientID: " + AClientID.ToString(), TLoggingType.ToLogfile); } #endregion }
/// <summary> /// Called by a Client to request connection to the Petra Server. /// /// Authenticate the user and create a sesssion for the user. /// /// </summary> /// <param name="AUserName">Username with which the Client connects</param> /// <param name="APassword">Password with which the Client connects</param> /// <param name="AClientComputerName">Computer name of the Client</param> /// <param name="AClientExeVersion"></param> /// <param name="AClientIPAddress">IP Address of the Client</param> /// <param name="AClientServerConnectionType">Type of the connection (eg. LAN, Remote)</param> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="AWelcomeMessage"></param> /// <param name="ASystemEnabled"></param> /// <param name="AUserInfo"></param> public static TConnectedClient ConnectClient(String AUserName, String APassword, String AClientComputerName, String AClientIPAddress, System.Version AClientExeVersion, TClientServerConnectionType AClientServerConnectionType, out System.Int32 AClientID, out String AWelcomeMessage, out Boolean ASystemEnabled, out IPrincipal AUserInfo) { TConnectedClient ConnectedClient = null; if (TLogging.DL >= 10) { TLogging.Log( "Loaded Assemblies in AppDomain " + Thread.GetDomain().FriendlyName + " (at call of ConnectClient):", TLoggingType.ToConsole | TLoggingType.ToLogfile); foreach (Assembly tmpAssembly in Thread.GetDomain().GetAssemblies()) { TLogging.Log(tmpAssembly.FullName, TLoggingType.ToConsole | TLoggingType.ToLogfile); } } /* * Every Client Connection request is coming in in a separate Thread * (.NET Remoting does that for us and this is good!). However, the next block * of code must be executed only by exactly ONE thread at the same time to * preserve the integrity of Client tracking! */ try { // TODORemoting if (Monitor.TryEnter(UConnectClientMonitor, TSrvSetting.ClientConnectionTimeoutAfterXSeconds * 1000)) { if (Thread.CurrentThread.Name == String.Empty) { Thread.CurrentThread.Name = "Client_" + AUserName + "__CLIENTCONNECTION_THREAD"; } #region Logging if (TLogging.DL >= 4) { Console.WriteLine(FormatClientList(false)); Console.WriteLine(FormatClientList(true)); } if (TLogging.DL >= 4) { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' is connecting...", TLoggingType.ToLogfile); } #endregion #region Variable assignments AClientID = (short)FClientsConnectedTotal; FClientsConnectedTotal++; string ClientName = AUserName.ToUpper() + "_" + AClientID.ToString(); #endregion try { if (Monitor.TryEnter(UClientObjects.SyncRoot)) { ConnectedClient = new TConnectedClient(AClientID, AUserName.ToUpper(), ClientName, AClientComputerName, AClientIPAddress, AClientServerConnectionType, ClientName); // Add the new Client to UClientObjects SortedList UClientObjects.Add((object)AClientID, ConnectedClient); } } finally { Monitor.Exit(UClientObjects.SyncRoot); } #region Client Version vs. Server Version check if (TLogging.DL >= 9) { Console.WriteLine( "Client EXE Program Version: " + AClientExeVersion.ToString() + "; Server EXE Program Version: " + TSrvSetting.ApplicationVersion.ToString()); } if (TSrvSetting.ApplicationVersion.Compare(new TFileVersionInfo(AClientExeVersion)) != 0) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; #region Logging if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log( "Client '" + AUserName + "' tried to connect, but its Program Version (" + AClientExeVersion.ToString() + ") doesn't match! Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion throw new EClientVersionMismatchException(String.Format(StrClientServerExeProgramVersionMismatchMessage, AClientExeVersion.ToString(), TSrvSetting.ApplicationVersion.ToString())); } #endregion #region Login request verification (incl. User authentication) // Perform login checks such as User authentication and Site Key check try { AUserInfo = PerformLoginChecks(AUserName, APassword, AClientComputerName, AClientIPAddress, out ASystemEnabled); } catch (EPetraSecurityException) #region Exception handling { #region Logging if (TLogging.DL >= 4) { TLogging.Log("Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' tried to connect, but it failed the Login Checks. Aborting Client Connection!", TLoggingType.ToLogfile); } #endregion ConnectedClient.SessionStatus = TSessionStatus.adsStopped; throw; } catch (Exception) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; throw; } #endregion // Login Checks were successful! ConnectedClient.SessionStatus = TSessionStatus.adsConnectingLoginOK; #endregion // Retrieve Welcome message try { if (UMaintenanceLogonMessage != null) { AWelcomeMessage = UMaintenanceLogonMessage.GetLogonMessage(AUserInfo, true); } else { AWelcomeMessage = "Welcome"; } } catch (Exception) { ConnectedClient.SessionStatus = TSessionStatus.adsStopped; throw; } /* * Uncomment the following statement to be able to better test how the * Client reacts when it tries to connect and receives a * ELoginFailedServerTooBusyException. */ // Thread.Sleep(7000); /* * Notify all waiting Clients (that have not timed out yet) that they can * now try to connect... */ // TODORemoting Monitor.PulseAll(UConnectClientMonitor); } // TODORemoting else { /* * Throw Exception to tell any timed-out connecting Client that the Server * is too busy to accept connect requests at the moment. */ // TODORemoting throw new ELoginFailedServerTooBusyException(); } } finally { // TODORemoting Monitor.Exit(UConnectClientMonitor); } ConnectedClient.StartSession(new TDelegateTearDownAppDomain(DisconnectClient)); #region Logging // // Assemblies successfully loaded into Client AppDomain // if (TLogging.DL >= 4) { TLogging.Log( "Client '" + AUserName + "' successfully connected (took " + ConnectedClient.FClientConnectionFinishedTime.Subtract( ((TConnectedClient)UClientObjects[(object)AClientID]).FClientConnectionStartTime). TotalSeconds.ToString() + " sec). ClientID: " + AClientID.ToString(), TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client '" + AUserName + "' successfully connected. ClientID: " + AClientID.ToString(), TLoggingType.ToLogfile); } #endregion return ConnectedClient; }