///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
namespace Microsoft.Singularity.Security
{
using System;
using System.Collections;
using System.Text;
using System.Threading;
using Microsoft.Contracts;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Security;
///
/// The implementation of the SecurityService
state machine.
///
public class SecurityDiagnostics
{
///
/// The exporting endpoint of the security service.
///
private TRef channel;
private bool run = true;
private ArrayList! coreList;
public SecurityDiagnostics()
{
coreList = new ArrayList();
}
///
/// Starts the service and registers it in the namespace
///
public void Start()
{
DebugStub.WriteLine("Starting the Security Diagnostics provider");
// register the service with the namespace
ServiceProviderContract.Imp! nsImp;
ServiceProviderContract.Exp! nsExp;
ServiceProviderContract.NewChannel(out nsImp, out nsExp);
DirectoryServiceContract.Imp epNS = DirectoryService.NewClientEndpoint();
try {
epNS.SendRegister(Bitter.FromString2(SecurityDiagnosticsContract.ModuleName), nsImp);
switch receive {
case epNS.AckRegister() :
// All is well.
break;
case epNS.NakRegister(ServiceProviderContract.Imp:Start rejectedEP, ErrorCode error) :
// All is very much not well; abort.
DebugStub.WriteLine("Failed to register the Security Service under: {0}",
__arglist(SecurityDiagnosticsContract.ModuleName));
delete nsExp;
delete rejectedEP;
throw new Exception("Failed to register the Security Diagnostics provider");
case epNS.ChannelClosed():
delete nsExp;
DebugStub.WriteLine(
"Failed to register the Security Diagnostics provider under: {0}",
__arglist(SecurityDiagnosticsContract.ModuleName));
throw new Exception("Failed to register the Security Diagnostics provider");
}
}
finally {
delete epNS;
}
channel = new TRef(nsExp);
Thread thread = Thread.CreateThread(((!)Thread.CurrentThread).Process,
new ThreadStart(StateMachine));
if (thread != null)
{
thread.Start();
}
else
{
throw new Exception("Could not create worker thread");
}
}
public void RegisterAclCore(AclCore core)
{
//*** need locking here, but it doesn't work for now
//we're called at the wrong point in the init sequence
coreList.Add(core);
}
///
/// State machine for the security namespace
///
private void StateMachine()
requires this.channel != null;
{
// get the endpoint and start listening
ServiceProviderContract.Exp! exp = channel.Acquire();
// the clients
ESet clients =
new ESet();
while(run)
{
switch receive
{
case exp.Connect(ServiceContract.Exp:Start! epClient):
{
// incoming bind request: always grant, anyone should be able to talk to us
SecurityDiagnosticsContract.Exp client =
epClient as SecurityDiagnosticsContract.Exp;
if (client == null){
exp.SendNackConnect(epClient);
}
else
{
exp.SendAckConnect();
client.SendReady();
clients.Add(client);
}
}
break;
case client.GetStatistics() in clients:
{
StringBuilder sb = new StringBuilder();
DumpAllStats(sb);
client.SendGetStatisticsAck(Bitter.FromString2(sb.ToString()));
clients.Add(client);
}
break;
case client.ClearStatistics() in clients:
{
ClearAllStats();
client.SendAck();
clients.Add(client);
}
break;
case client.Disable(bool yes) in clients:
{
DisableAll(yes);
client.SendAck();
clients.Add(client);
}
break;
case client.FlushCaches() in clients:
{
FlushAllCaches();
client.SendAck();
clients.Add(client);
}
break;
case client.ChannelClosed() in clients:
{
delete client;
}
break;
case exp.ChannelClosed():
{
run = false;
}
break;
}
}
delete exp;
clients.Dispose();
}
private void DisableAll(bool value) {
lock (coreList) {
for (int i = 0; (i