SEBWIN-219: Implemented logging of component and session IDs and introduced IProxyFactory for client proxy instantiation during session startup.
This commit is contained in:
parent
e3b8bb8cc8
commit
be761fd72c
13 changed files with 150 additions and 68 deletions
|
@ -45,6 +45,9 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
|
||||||
configuration.Settings = config.Settings;
|
configuration.Settings = config.Settings;
|
||||||
|
|
||||||
logger.Info("Successfully retrieved the application configuration from the runtime.");
|
logger.Info("Successfully retrieved the application configuration from the runtime.");
|
||||||
|
logger.Info($" -> Client-ID: {configuration.RuntimeInfo.ClientId}");
|
||||||
|
logger.Info($" -> Runtime-ID: {configuration.RuntimeInfo.RuntimeId}");
|
||||||
|
logger.Info($" -> Session-ID: {configuration.SessionId}");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
public class ConfigurationRepository : IConfigurationRepository
|
public class ConfigurationRepository : IConfigurationRepository
|
||||||
{
|
{
|
||||||
|
private const string BASE_ADDRESS = "net.pipe://localhost/safeexambrowser";
|
||||||
|
|
||||||
|
private bool firstSession = true;
|
||||||
private RuntimeInfo runtimeInfo;
|
private RuntimeInfo runtimeInfo;
|
||||||
|
|
||||||
public ISessionData CurrentSession { get; private set; }
|
public ISessionData CurrentSession { get; private set; }
|
||||||
|
@ -35,19 +38,6 @@ namespace SafeExamBrowser.Configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISessionData InitializeSessionData()
|
|
||||||
{
|
|
||||||
var session = new SessionData
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
StartupToken = Guid.NewGuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
CurrentSession = session;
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientConfiguration BuildClientConfiguration()
|
public ClientConfiguration BuildClientConfiguration()
|
||||||
{
|
{
|
||||||
return new ClientConfiguration
|
return new ClientConfiguration
|
||||||
|
@ -58,6 +48,24 @@ namespace SafeExamBrowser.Configuration
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InitializeSessionConfiguration()
|
||||||
|
{
|
||||||
|
CurrentSession = new SessionData
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
StartupToken = Guid.NewGuid()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!firstSession)
|
||||||
|
{
|
||||||
|
UpdateRuntimeInfo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstSession = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Settings LoadSettings(Uri path)
|
public Settings LoadSettings(Uri path)
|
||||||
{
|
{
|
||||||
// TODO: Implement loading mechanism
|
// TODO: Implement loading mechanism
|
||||||
|
@ -92,10 +100,7 @@ namespace SafeExamBrowser.Configuration
|
||||||
private void InitializeRuntimeInfo()
|
private void InitializeRuntimeInfo()
|
||||||
{
|
{
|
||||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
|
||||||
var baseAddress = "net.pipe://localhost/safeexambrowser";
|
|
||||||
var clientId = Guid.NewGuid();
|
|
||||||
var executable = Assembly.GetEntryAssembly();
|
var executable = Assembly.GetEntryAssembly();
|
||||||
var runtimeId = Guid.NewGuid();
|
|
||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
var logFolder = Path.Combine(appDataFolder, "Logs");
|
var logFolder = Path.Combine(appDataFolder, "Logs");
|
||||||
var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
||||||
|
@ -107,7 +112,7 @@ namespace SafeExamBrowser.Configuration
|
||||||
BrowserCachePath = Path.Combine(appDataFolder, "Cache"),
|
BrowserCachePath = Path.Combine(appDataFolder, "Cache"),
|
||||||
BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt"),
|
BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt"),
|
||||||
ClientId = Guid.NewGuid(),
|
ClientId = Guid.NewGuid(),
|
||||||
ClientAddress = $"{baseAddress}/client/{clientId}",
|
ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}",
|
||||||
ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executable.Location), $"{nameof(SafeExamBrowser)}.Client.exe"),
|
ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executable.Location), $"{nameof(SafeExamBrowser)}.Client.exe"),
|
||||||
ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt"),
|
ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt"),
|
||||||
DefaultSettingsFileName = "SebClientSettings.seb",
|
DefaultSettingsFileName = "SebClientSettings.seb",
|
||||||
|
@ -116,10 +121,16 @@ namespace SafeExamBrowser.Configuration
|
||||||
ProgramTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title,
|
ProgramTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title,
|
||||||
ProgramVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion,
|
ProgramVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion,
|
||||||
RuntimeId = Guid.NewGuid(),
|
RuntimeId = Guid.NewGuid(),
|
||||||
RuntimeAddress = $"{baseAddress}/runtime/{runtimeId}",
|
RuntimeAddress = $"{BASE_ADDRESS}/runtime/{Guid.NewGuid()}",
|
||||||
RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt"),
|
RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt"),
|
||||||
ServiceAddress = $"{baseAddress}/service"
|
ServiceAddress = $"{BASE_ADDRESS}/service"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateRuntimeInfo()
|
||||||
|
{
|
||||||
|
RuntimeInfo.ClientId = Guid.NewGuid();
|
||||||
|
RuntimeInfo.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
public class SessionData : ISessionData
|
public class SessionData : ISessionData
|
||||||
{
|
{
|
||||||
|
public IClientProxy ClientProxy { get; set; }
|
||||||
public IProcess ClientProcess { get; set; }
|
public IProcess ClientProcess { get; set; }
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public Guid StartupToken { get; set; }
|
public Guid StartupToken { get; set; }
|
||||||
|
|
21
SafeExamBrowser.Contracts/Communication/IProxyFactory.cs
Normal file
21
SafeExamBrowser.Contracts/Communication/IProxyFactory.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Communication
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A factory to create communication proxies during application runtime.
|
||||||
|
/// </summary>
|
||||||
|
public interface IProxyFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="IClientProxy"/> for the given endpoint address.
|
||||||
|
/// </summary>
|
||||||
|
IClientProxy CreateClientProxy(string address);
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes all relevant data for a new session.
|
/// Initializes all relevant data for a new session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISessionData InitializeSessionData();
|
void InitializeSessionConfiguration();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to load settings from the specified path.
|
/// Attempts to load settings from the specified path.
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
using SafeExamBrowser.Contracts.WindowsApi;
|
using SafeExamBrowser.Contracts.WindowsApi;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Configuration
|
namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
@ -16,6 +17,11 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISessionData
|
public interface ISessionData
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The communication proxy for the client instance associated to this session.
|
||||||
|
/// </summary>
|
||||||
|
IClientProxy ClientProxy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The process information of the client instance associated to this session.
|
/// The process information of the client instance associated to this session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -38,9 +38,6 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The communication address of the client component.
|
/// The communication address of the client component.
|
||||||
///
|
|
||||||
/// TODO: Will need to be updated for each new client instance!
|
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ClientAddress { get; set; }
|
public string ClientAddress { get; set; }
|
||||||
|
|
||||||
|
@ -51,9 +48,6 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The unique identifier for the currently running client instance.
|
/// The unique identifier for the currently running client instance.
|
||||||
///
|
|
||||||
/// TODO: Will need to be updated for each new client instance! -> Remove if unused!
|
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid ClientId { get; set; }
|
public Guid ClientId { get; set; }
|
||||||
|
|
||||||
|
@ -94,9 +88,6 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The unique identifier for the currently running runtime instance.
|
/// The unique identifier for the currently running runtime instance.
|
||||||
///
|
|
||||||
/// TODO: Remove if unused!
|
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid RuntimeId { get; set; }
|
public Guid RuntimeId { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
<Compile Include="Communication\IClientProxy.cs" />
|
<Compile Include="Communication\IClientProxy.cs" />
|
||||||
<Compile Include="Communication\ICommunicationHost.cs" />
|
<Compile Include="Communication\ICommunicationHost.cs" />
|
||||||
<Compile Include="Communication\ICommunicationProxy.cs" />
|
<Compile Include="Communication\ICommunicationProxy.cs" />
|
||||||
|
<Compile Include="Communication\IProxyFactory.cs" />
|
||||||
<Compile Include="Communication\IRuntimeHost.cs" />
|
<Compile Include="Communication\IRuntimeHost.cs" />
|
||||||
<Compile Include="Communication\IRuntimeProxy.cs" />
|
<Compile Include="Communication\IRuntimeProxy.cs" />
|
||||||
<Compile Include="Communication\IServiceProxy.cs" />
|
<Compile Include="Communication\IServiceProxy.cs" />
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
private bool sessionRunning;
|
private bool sessionRunning;
|
||||||
|
|
||||||
private IClientProxy client;
|
|
||||||
private IConfigurationRepository configuration;
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IOperationSequence bootstrapSequence;
|
private IOperationSequence bootstrapSequence;
|
||||||
|
@ -36,7 +35,6 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
public RuntimeController(
|
public RuntimeController(
|
||||||
IClientProxy client,
|
|
||||||
IConfigurationRepository configuration,
|
IConfigurationRepository configuration,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IOperationSequence bootstrapSequence,
|
IOperationSequence bootstrapSequence,
|
||||||
|
@ -47,7 +45,6 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
Action shutdown,
|
Action shutdown,
|
||||||
IUserInterfaceFactory uiFactory)
|
IUserInterfaceFactory uiFactory)
|
||||||
{
|
{
|
||||||
this.client = client;
|
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.bootstrapSequence = bootstrapSequence;
|
this.bootstrapSequence = bootstrapSequence;
|
||||||
|
@ -202,7 +199,6 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
|
|
||||||
private void RegisterEvents()
|
private void RegisterEvents()
|
||||||
{
|
{
|
||||||
client.ConnectionLost += Client_ConnectionLost;
|
|
||||||
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested += RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested += RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
@ -210,11 +206,11 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private void RegisterSessionEvents()
|
private void RegisterSessionEvents()
|
||||||
{
|
{
|
||||||
configuration.CurrentSession.ClientProcess.Terminated += ClientProcess_Terminated;
|
configuration.CurrentSession.ClientProcess.Terminated += ClientProcess_Terminated;
|
||||||
|
configuration.CurrentSession.ClientProxy.ConnectionLost += Client_ConnectionLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeregisterEvents()
|
private void DeregisterEvents()
|
||||||
{
|
{
|
||||||
client.ConnectionLost -= Client_ConnectionLost;
|
|
||||||
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
runtimeHost.ReconfigurationRequested -= RuntimeHost_ReconfigurationRequested;
|
||||||
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
runtimeHost.ShutdownRequested -= RuntimeHost_ShutdownRequested;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +218,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private void DeregisterSessionEvents()
|
private void DeregisterSessionEvents()
|
||||||
{
|
{
|
||||||
configuration.CurrentSession.ClientProcess.Terminated -= ClientProcess_Terminated;
|
configuration.CurrentSession.ClientProcess.Terminated -= ClientProcess_Terminated;
|
||||||
|
configuration.CurrentSession.ClientProxy.ConnectionLost -= Client_ConnectionLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClientProcess_Terminated(int exitCode)
|
private void ClientProcess_Terminated(int exitCode)
|
||||||
|
|
|
@ -22,28 +22,27 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
private const int TEN_SECONDS = 10000;
|
private const int TEN_SECONDS = 10000;
|
||||||
|
|
||||||
private bool sessionRunning;
|
private bool sessionRunning;
|
||||||
private IClientProxy client;
|
|
||||||
private IConfigurationRepository configuration;
|
private IConfigurationRepository configuration;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IProcessFactory processFactory;
|
private IProcessFactory processFactory;
|
||||||
|
private IProxyFactory proxyFactory;
|
||||||
private IRuntimeHost runtimeHost;
|
private IRuntimeHost runtimeHost;
|
||||||
private IServiceProxy service;
|
private IServiceProxy service;
|
||||||
private ISessionData session;
|
|
||||||
|
|
||||||
internal IProgressIndicator ProgressIndicator { private get; set; }
|
internal IProgressIndicator ProgressIndicator { private get; set; }
|
||||||
|
|
||||||
internal SessionController(
|
internal SessionController(
|
||||||
IClientProxy client,
|
|
||||||
IConfigurationRepository configuration,
|
IConfigurationRepository configuration,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IProcessFactory processFactory,
|
IProcessFactory processFactory,
|
||||||
|
IProxyFactory proxyFactory,
|
||||||
IRuntimeHost runtimeHost,
|
IRuntimeHost runtimeHost,
|
||||||
IServiceProxy service)
|
IServiceProxy service)
|
||||||
{
|
{
|
||||||
this.client = client;
|
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.processFactory = processFactory;
|
this.processFactory = processFactory;
|
||||||
|
this.proxyFactory = proxyFactory;
|
||||||
this.runtimeHost = runtimeHost;
|
this.runtimeHost = runtimeHost;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
@ -53,23 +52,19 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
logger.Info("Starting new session...");
|
logger.Info("Starting new session...");
|
||||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
|
||||||
|
|
||||||
session = configuration.InitializeSessionData();
|
InitializeSessionConfiguration();
|
||||||
runtimeHost.StartupToken = session.StartupToken;
|
StartServiceSession();
|
||||||
|
|
||||||
logger.Info("Initializing service session...");
|
|
||||||
service.StartSession(session.Id, configuration.CurrentSettings);
|
|
||||||
|
|
||||||
sessionRunning = TryStartClient();
|
sessionRunning = TryStartClient();
|
||||||
|
|
||||||
if (!sessionRunning)
|
if (!sessionRunning)
|
||||||
{
|
{
|
||||||
logger.Info($"Failed to start new session! Reverting service session and aborting procedure...");
|
logger.Info($"Failed to start new session! Reverting service session and aborting procedure...");
|
||||||
service.StopSession(session.Id);
|
service.StopSession(configuration.CurrentSession.Id);
|
||||||
|
|
||||||
return OperationResult.Failed;
|
return OperationResult.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info($"Successfully started new session with identifier '{session.Id}'.");
|
logger.Info($"Successfully started new session.");
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -78,24 +73,45 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
{
|
{
|
||||||
if (sessionRunning)
|
if (sessionRunning)
|
||||||
{
|
{
|
||||||
logger.Info($"Stopping session with identifier '{session.Id}'...");
|
logger.Info($"Stopping session with identifier '{configuration.CurrentSession.Id}'...");
|
||||||
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopSession, true);
|
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StopSession, true);
|
||||||
|
|
||||||
logger.Info("Stopping service session...");
|
StopServiceSession();
|
||||||
service.StopSession(session.Id);
|
|
||||||
|
|
||||||
if (!session.ClientProcess.HasTerminated)
|
if (!configuration.CurrentSession.ClientProcess.HasTerminated)
|
||||||
{
|
{
|
||||||
StopClient();
|
StopClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionRunning = false;
|
sessionRunning = false;
|
||||||
logger.Info($"Successfully stopped session with identifier '{session.Id}'.");
|
logger.Info($"Successfully stopped session.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeSessionConfiguration()
|
||||||
|
{
|
||||||
|
configuration.InitializeSessionConfiguration();
|
||||||
|
runtimeHost.StartupToken = configuration.CurrentSession.StartupToken;
|
||||||
|
|
||||||
|
logger.Info($" -> Client-ID: {configuration.RuntimeInfo.ClientId}");
|
||||||
|
logger.Info($" -> Runtime-ID: {configuration.RuntimeInfo.RuntimeId} (as reference, does not change)");
|
||||||
|
logger.Info($" -> Session-ID: {configuration.CurrentSession.Id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartServiceSession()
|
||||||
|
{
|
||||||
|
logger.Info("Initializing service session...");
|
||||||
|
service.StartSession(configuration.CurrentSession.Id, configuration.CurrentSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopServiceSession()
|
||||||
|
{
|
||||||
|
logger.Info("Stopping service session...");
|
||||||
|
service.StopSession(configuration.CurrentSession.Id);
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryStartClient()
|
private bool TryStartClient()
|
||||||
{
|
{
|
||||||
var clientReady = false;
|
var clientReady = false;
|
||||||
|
@ -104,11 +120,11 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
var clientExecutable = configuration.RuntimeInfo.ClientExecutablePath;
|
var clientExecutable = configuration.RuntimeInfo.ClientExecutablePath;
|
||||||
var clientLogFile = $"{'"' + configuration.RuntimeInfo.ClientLogFile + '"'}";
|
var clientLogFile = $"{'"' + configuration.RuntimeInfo.ClientLogFile + '"'}";
|
||||||
var hostUri = configuration.RuntimeInfo.RuntimeAddress;
|
var hostUri = configuration.RuntimeInfo.RuntimeAddress;
|
||||||
var token = session.StartupToken.ToString("D");
|
var token = configuration.CurrentSession.StartupToken.ToString("D");
|
||||||
|
|
||||||
logger.Info("Starting new client process.");
|
logger.Info("Starting new client process...");
|
||||||
runtimeHost.ClientReady += clientReadyEventHandler;
|
runtimeHost.ClientReady += clientReadyEventHandler;
|
||||||
session.ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token);
|
configuration.CurrentSession.ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token);
|
||||||
|
|
||||||
logger.Info("Waiting for client to complete initialization...");
|
logger.Info("Waiting for client to complete initialization...");
|
||||||
clientReady = clientReadyEvent.WaitOne(TEN_SECONDS);
|
clientReady = clientReadyEvent.WaitOne(TEN_SECONDS);
|
||||||
|
@ -122,8 +138,10 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Client has been successfully started and initialized.");
|
logger.Info("Client has been successfully started and initialized.");
|
||||||
|
logger.Info("Creating communication proxy for client host...");
|
||||||
|
configuration.CurrentSession.ClientProxy = proxyFactory.CreateClientProxy(configuration.RuntimeInfo.ClientAddress);
|
||||||
|
|
||||||
if (!client.Connect(session.StartupToken))
|
if (!configuration.CurrentSession.ClientProxy.Connect(configuration.CurrentSession.StartupToken))
|
||||||
{
|
{
|
||||||
logger.Error("Failed to connect to client!");
|
logger.Error("Failed to connect to client!");
|
||||||
|
|
||||||
|
@ -132,16 +150,16 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
|
|
||||||
logger.Info("Connection with client has been established.");
|
logger.Info("Connection with client has been established.");
|
||||||
|
|
||||||
var response = client.RequestAuthentication();
|
var response = configuration.CurrentSession.ClientProxy.RequestAuthentication();
|
||||||
|
|
||||||
if (session.ClientProcess.Id != response?.ProcessId)
|
if (configuration.CurrentSession.ClientProcess.Id != response?.ProcessId)
|
||||||
{
|
{
|
||||||
logger.Error("Failed to verify client integrity!");
|
logger.Error("Failed to verify client integrity!");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Authentication of client has been successful.");
|
logger.Info("Authentication of client has been successful, client is ready to operate.");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -157,13 +175,13 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
var terminatedEventHandler = new ProcessTerminatedEventHandler((_) => terminatedEvent.Set());
|
var terminatedEventHandler = new ProcessTerminatedEventHandler((_) => terminatedEvent.Set());
|
||||||
|
|
||||||
runtimeHost.ClientDisconnected += disconnectedEventHandler;
|
runtimeHost.ClientDisconnected += disconnectedEventHandler;
|
||||||
session.ClientProcess.Terminated += terminatedEventHandler;
|
configuration.CurrentSession.ClientProcess.Terminated += terminatedEventHandler;
|
||||||
|
|
||||||
logger.Info("Instructing client to initiate shutdown procedure.");
|
logger.Info("Instructing client to initiate shutdown procedure.");
|
||||||
client.InitiateShutdown();
|
configuration.CurrentSession.ClientProxy.InitiateShutdown();
|
||||||
|
|
||||||
logger.Info("Disconnecting from client communication host.");
|
logger.Info("Disconnecting from client communication host.");
|
||||||
client.Disconnect();
|
configuration.CurrentSession.ClientProxy.Disconnect();
|
||||||
|
|
||||||
logger.Info("Waiting for client to disconnect from runtime communication host...");
|
logger.Info("Waiting for client to disconnect from runtime communication host...");
|
||||||
disconnected = disconnectedEvent.WaitOne(TEN_SECONDS);
|
disconnected = disconnectedEvent.WaitOne(TEN_SECONDS);
|
||||||
|
@ -182,7 +200,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeHost.ClientDisconnected -= disconnectedEventHandler;
|
runtimeHost.ClientDisconnected -= disconnectedEventHandler;
|
||||||
session.ClientProcess.Terminated -= terminatedEventHandler;
|
configuration.CurrentSession.ClientProcess.Terminated -= terminatedEventHandler;
|
||||||
|
|
||||||
if (disconnected && terminated)
|
if (disconnected && terminated)
|
||||||
{
|
{
|
||||||
|
@ -206,10 +224,10 @@ namespace SafeExamBrowser.Runtime.Behaviour
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info($"Killing client process with ID = {session.ClientProcess.Id}.");
|
logger.Info($"Killing client process with ID = {configuration.CurrentSession.ClientProcess.Id}.");
|
||||||
session.ClientProcess.Kill();
|
configuration.CurrentSession.ClientProcess.Kill();
|
||||||
|
|
||||||
if (session.ClientProcess.HasTerminated)
|
if (configuration.CurrentSession.ClientProcess.HasTerminated)
|
||||||
{
|
{
|
||||||
logger.Info("Client process has terminated.");
|
logger.Info("Client process has terminated.");
|
||||||
}
|
}
|
||||||
|
|
30
SafeExamBrowser.Runtime/Communication/ProxyFactory.cs
Normal file
30
SafeExamBrowser.Runtime/Communication/ProxyFactory.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using SafeExamBrowser.Contracts.Communication;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Core.Communication;
|
||||||
|
using SafeExamBrowser.Core.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Runtime.Communication
|
||||||
|
{
|
||||||
|
internal class ProxyFactory : IProxyFactory
|
||||||
|
{
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public ProxyFactory(ILogger logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IClientProxy CreateClientProxy(string address)
|
||||||
|
{
|
||||||
|
return new ClientProxy(address, new ModuleLogger(logger, typeof(ClientProxy)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,10 +49,10 @@ namespace SafeExamBrowser.Runtime
|
||||||
var uiFactory = new UserInterfaceFactory(text);
|
var uiFactory = new UserInterfaceFactory(text);
|
||||||
var desktop = new Desktop(new ModuleLogger(logger, typeof(Desktop)));
|
var desktop = new Desktop(new ModuleLogger(logger, typeof(Desktop)));
|
||||||
var processFactory = new ProcessFactory(desktop, new ModuleLogger(logger, typeof(ProcessFactory)));
|
var processFactory = new ProcessFactory(desktop, new ModuleLogger(logger, typeof(ProcessFactory)));
|
||||||
var clientProxy = new ClientProxy(runtimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientProxy)));
|
var proxyFactory = new ProxyFactory(logger);
|
||||||
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, configuration, new ModuleLogger(logger, typeof(RuntimeHost)));
|
var runtimeHost = new RuntimeHost(runtimeInfo.RuntimeAddress, configuration, new ModuleLogger(logger, typeof(RuntimeHost)));
|
||||||
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ModuleLogger(logger, typeof(ServiceProxy)));
|
var serviceProxy = new ServiceProxy(runtimeInfo.ServiceAddress, new ModuleLogger(logger, typeof(ServiceProxy)));
|
||||||
var sessionController = new SessionController(clientProxy, configuration, logger, processFactory, runtimeHost, serviceProxy);
|
var sessionController = new SessionController(configuration, logger, processFactory, proxyFactory, runtimeHost, serviceProxy);
|
||||||
|
|
||||||
var bootstrapOperations = new Queue<IOperation>();
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
var sessionOperations = new Queue<IOperation>();
|
var sessionOperations = new Queue<IOperation>();
|
||||||
|
@ -69,7 +69,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
var boostrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||||
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
var sessionSequence = new OperationSequence(logger, sessionOperations);
|
||||||
|
|
||||||
RuntimeController = new RuntimeController(clientProxy, configuration, logger, boostrapSequence, sessionSequence, runtimeHost, runtimeInfo, serviceProxy, shutdown, uiFactory);
|
RuntimeController = new RuntimeController(configuration, logger, boostrapSequence, sessionSequence, runtimeHost, runtimeInfo, serviceProxy, shutdown, uiFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void LogStartupInformation()
|
internal void LogStartupInformation()
|
||||||
|
@ -81,6 +81,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
logger.Log(string.Empty);
|
logger.Log(string.Empty);
|
||||||
logger.Log($"# Application started at {runtimeInfo.ApplicationStartTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
logger.Log($"# Application started at {runtimeInfo.ApplicationStartTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||||
logger.Log($"# Running on {systemInfo.OperatingSystemInfo}");
|
logger.Log($"# Running on {systemInfo.OperatingSystemInfo}");
|
||||||
|
logger.Log($"# Runtime-ID: {runtimeInfo.RuntimeId}");
|
||||||
logger.Log(string.Empty);
|
logger.Log(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
<Compile Include="Behaviour\Operations\SessionSequenceEndOperation.cs" />
|
<Compile Include="Behaviour\Operations\SessionSequenceEndOperation.cs" />
|
||||||
<Compile Include="Behaviour\SessionController.cs" />
|
<Compile Include="Behaviour\SessionController.cs" />
|
||||||
<Compile Include="Behaviour\Operations\SessionSequenceStartOperation.cs" />
|
<Compile Include="Behaviour\Operations\SessionSequenceStartOperation.cs" />
|
||||||
|
<Compile Include="Communication\ProxyFactory.cs" />
|
||||||
<Compile Include="Communication\RuntimeHost.cs" />
|
<Compile Include="Communication\RuntimeHost.cs" />
|
||||||
<Compile Include="CompositionRoot.cs" />
|
<Compile Include="CompositionRoot.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
|
Loading…
Reference in a new issue