singrdk/base/Services/NetStack/Channels.Private/TCPExpManager.sg

129 lines
4.8 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: TcpExpManager.sg
// Note: Provider-side helper for the IP Channel Contract
//
using System.Threading;
using System.Net.IP;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using NetStack.Contracts;
using NetStack.Runtime;
using System.Collections;
using System;
namespace NetStack.Channels.Private
{
public class TcpExpManager
{
public void Run()
{
// Here is the set of client channels we service
ESet<TcpContract.Exp:ReadyState> epSet = new ESet<TcpContract.Exp:ReadyState>();
// Here is the channel we use to communicate with
// the NameServer
ServiceProviderContract.Imp! nsImp;
ServiceProviderContract.Exp! nsExp;
ServiceProviderContract.NewChannel(out nsImp, out nsExp);
// Here is our NameServer connection over which we
// receive new client channels. When we become a
// process, this will be present automatically,
// somehow.
DirectoryServiceContract.Imp epNS = DirectoryService.NewClientEndpoint();
try {
epNS.SendRegister(Bitter.FromString2(TcpContract.ModuleName), nsImp);
switch receive {
case epNS.AckRegister() :
// All is well.
break;
case epNS.NakRegister(ServiceProviderContract.Imp:Start rejectedEP, error) :
// All is very much not well; abort.
DebugStub.Print("Failed to register the Tcp module.\n");
delete rejectedEP;
delete nsExp;
epSet.Dispose();
return;
}
}
finally {
delete epNS;
}
while(true) {
switch receive {
//
// Don't forget that we're selecting TcpContract endpoints
// from the epSet endpoint-set. In each case that we
// receive a message from one of those endpoints, we
// need to remember to put the endpoint back into epSet
// if we want to keep listening to it.
//
case ep.CreateTcpSession(TcpConnectionContract.Exp:Start! newEP) in epSet :
{
// Transition the endpoint to the ReadyState
newEP.SendReady();
// Create a dedicated thread to service this connection
TcpConnectionExpThread tcpThread = new TcpConnectionExpThread(newEP);
tcpThread.Start();
ep.SendAck();
epSet.Add(ep);
}
break;
case nsExp.Connect(ServiceContract.Exp:Start! newEp) :
{
// We expect people top give us TcpContract.Exp instances
//TcpContract.Exp:Start newTcpEp = newEp as TcpContract.Exp;
TcpContract.Exp newTcpEp = newEp as TcpContract.Exp;
if (newTcpEp == null) {
// Invalid contract type. Fail.
nsExp.SendNackConnect(newEp);
}
else {
// Signal ready and start servicing this contract
nsExp.SendAckConnect();
newTcpEp.SendReady();
epSet.Add(newTcpEp);
}
}
break;
case ep.ChannelClosed() in epSet:
delete ep;
break;
case nsExp.ChannelClosed():
// Exit this thread
delete nsExp;
epSet.Dispose();
return;
break;
}
}
}
public void Start()
{
#if THREAD_POOL
Core.Instance().ThreadPool.QueueUserWorkItem(new ThreadStart(Run));
#else
Thread newThread = new Thread(new ThreadStart(Run));
newThread.Start();
#endif
}
}
}