/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // 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 : StoppableThread { protected override void Run(StopThreadContract.Exp:Ready! terminator) { // Here is the set of client channels we service ESet epSet = new ESet(); // 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 goto quit; case terminator.Terminate(): terminator.SendAckTerminate(); goto quit; case terminator.ChannelClosed(): goto quit; } } quit: delete nsExp; epSet.Dispose(); } } }