2018-02-06 15:12:11 +01:00
|
|
|
|
/*
|
|
|
|
|
* 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 System;
|
|
|
|
|
using System.ServiceModel;
|
|
|
|
|
using SafeExamBrowser.Contracts.Communication;
|
|
|
|
|
using SafeExamBrowser.Contracts.Communication.Messages;
|
|
|
|
|
using SafeExamBrowser.Contracts.Communication.Responses;
|
|
|
|
|
using SafeExamBrowser.Contracts.Logging;
|
2018-02-14 15:26:05 +01:00
|
|
|
|
using SafeExamBrowser.Core.Communication.Responses;
|
2018-02-06 15:12:11 +01:00
|
|
|
|
|
|
|
|
|
namespace SafeExamBrowser.Core.Communication
|
|
|
|
|
{
|
|
|
|
|
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
|
|
|
|
|
public abstract class BaseHost : ICommunication, ICommunicationHost
|
|
|
|
|
{
|
|
|
|
|
private string address;
|
|
|
|
|
private ILogger logger;
|
|
|
|
|
private ServiceHost host;
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
protected Guid? CommunicationToken { get; private set; }
|
|
|
|
|
protected ILogger Logger { get; private set; }
|
|
|
|
|
|
2018-02-06 15:12:11 +01:00
|
|
|
|
public bool IsRunning
|
|
|
|
|
{
|
|
|
|
|
get { return host?.State == CommunicationState.Opened; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public BaseHost(string address, ILogger logger)
|
|
|
|
|
{
|
|
|
|
|
this.address = address;
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
protected abstract bool OnConnect(Guid? token);
|
|
|
|
|
protected abstract void OnDisconnect();
|
2018-02-08 13:32:48 +01:00
|
|
|
|
protected abstract IResponse OnReceive(IMessage message);
|
2018-02-14 15:26:05 +01:00
|
|
|
|
protected abstract IResponse OnReceive(Message message);
|
2018-02-08 13:32:48 +01:00
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
public IConnectionResponse Connect(Guid? token = null)
|
2018-02-08 13:32:48 +01:00
|
|
|
|
{
|
2018-02-14 15:26:05 +01:00
|
|
|
|
logger.Debug($"Received connection request with authentication token '{token}'.");
|
|
|
|
|
|
|
|
|
|
var response = new ConnectionResponse();
|
|
|
|
|
var connected = OnConnect(token);
|
2018-02-08 13:32:48 +01:00
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
if (connected)
|
|
|
|
|
{
|
|
|
|
|
response.CommunicationToken = CommunicationToken = Guid.NewGuid();
|
|
|
|
|
response.ConnectionEstablished = true;
|
|
|
|
|
}
|
2018-02-08 13:32:48 +01:00
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
logger.Debug($"{(connected ? "Accepted" : "Denied")} connection request.");
|
2018-02-08 13:32:48 +01:00
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
public IDisconnectionResponse Disconnect(IDisconnectionMessage message)
|
2018-02-08 13:32:48 +01:00
|
|
|
|
{
|
2018-02-14 15:26:05 +01:00
|
|
|
|
var response = new DisconnectionResponse();
|
|
|
|
|
|
|
|
|
|
// TODO: Compare with ToString in BaseProxy - needed?
|
2018-02-08 13:32:48 +01:00
|
|
|
|
logger.Debug($"Received disconnection request with message '{message}'.");
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
if (IsAuthorized(message?.CommunicationToken))
|
|
|
|
|
{
|
|
|
|
|
OnDisconnect();
|
|
|
|
|
|
|
|
|
|
CommunicationToken = null;
|
|
|
|
|
response.ConnectionTerminated = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response;
|
2018-02-08 13:32:48 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IResponse Send(IMessage message)
|
|
|
|
|
{
|
2018-02-14 15:26:05 +01:00
|
|
|
|
IResponse response = null;
|
|
|
|
|
|
2018-02-08 13:32:48 +01:00
|
|
|
|
logger.Debug($"Received message '{message}'.");
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
if (IsAuthorized(message?.CommunicationToken))
|
|
|
|
|
{
|
|
|
|
|
if (message is ISimpleMessage)
|
|
|
|
|
{
|
|
|
|
|
response = OnReceive((message as ISimpleMessage).Purport);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
response = OnReceive(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-08 13:32:48 +01:00
|
|
|
|
|
|
|
|
|
logger.Debug($"Sending response '{response}'.");
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
2018-02-06 15:12:11 +01:00
|
|
|
|
|
|
|
|
|
public void Start()
|
|
|
|
|
{
|
|
|
|
|
host = new ServiceHost(this);
|
|
|
|
|
host.AddServiceEndpoint(typeof(ICommunication), new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), address);
|
|
|
|
|
host.Closed += Host_Closed;
|
|
|
|
|
host.Closing += Host_Closing;
|
|
|
|
|
host.Faulted += Host_Faulted;
|
|
|
|
|
host.Opened += Host_Opened;
|
|
|
|
|
host.Opening += Host_Opening;
|
|
|
|
|
host.UnknownMessageReceived += Host_UnknownMessageReceived;
|
|
|
|
|
host.Open();
|
|
|
|
|
|
|
|
|
|
logger.Debug($"Successfully started communication host for endpoint '{address}'.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Stop()
|
|
|
|
|
{
|
|
|
|
|
host?.Close();
|
|
|
|
|
logger.Debug($"Terminated communication host for endpoint '{address}'.");
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-14 15:26:05 +01:00
|
|
|
|
private bool IsAuthorized(Guid? token)
|
|
|
|
|
{
|
|
|
|
|
return CommunicationToken == token;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-06 15:12:11 +01:00
|
|
|
|
private void Host_Closed(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Communication host has been closed.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Host_Closing(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Communication host is closing...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Host_Faulted(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Communication host has faulted!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Host_Opened(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Communication host has been opened.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Host_Opening(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Communication host is opening...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Host_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"Communication host has received an unknown message: {e?.Message}.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|