282 lines
10 KiB
Plaintext
282 lines
10 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Note: Provider-side helper for the Routing Channel Contract
|
|
//
|
|
|
|
using System.Threading;
|
|
using Drivers.Net;
|
|
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.Net.IP;
|
|
using NetStack.Contracts;
|
|
using NetStack.Channels.Public;
|
|
|
|
namespace NetStack.Channels.Private
|
|
{
|
|
public class RoutingExpManager : StoppableThread
|
|
{
|
|
private IPModule! ip;
|
|
|
|
protected override void Run(StopThreadContract.Exp:Ready! terminator)
|
|
{
|
|
ServiceProviderContract.Exp nsExp = Register();
|
|
|
|
if (nsExp == null) {
|
|
DebugStub.Print("Failed to register the routing module!");
|
|
return;
|
|
}
|
|
|
|
// Here is the set of client channels we service
|
|
ESet<RoutingContract.Exp:ReadyState> epSet = new ESet<RoutingContract.Exp:ReadyState>();
|
|
|
|
bool run = true;
|
|
|
|
while (run) {
|
|
switch receive {
|
|
//
|
|
// Don't forget that we're selecting RoutingContract 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.GetRoutingTable() in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
NetStack.Contracts.RouteEntry[] in ExHeap retval =
|
|
new[ExHeap] NetStack.Contracts.RouteEntry[h.RoutingTable.Count];
|
|
int i = 0;
|
|
|
|
foreach (NetStack.Runtime.RouteEntry! r in h.RoutingTable) {
|
|
retval[i] = ConvertRouteEntry(r);
|
|
i++;
|
|
}
|
|
|
|
ep.SendRoutingTable(retval);
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.AddRoute(Network dest, uint gateway, uint ifaddr) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
IPv4Network destination =
|
|
new IPv4Network(new IPv4(dest.network),
|
|
new IPv4(dest.netmask));
|
|
|
|
if (h.RoutingTable.AddRoute(
|
|
new NetStack.Runtime.RouteEntry(destination,
|
|
new IPv4(gateway),
|
|
new IPv4(ifaddr))))
|
|
{
|
|
ep.SendOK();
|
|
}
|
|
else {
|
|
ep.SendErr();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.FindHostRoute(uint dest) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
NetStack.Runtime.RouteEntry re =
|
|
h.RoutingTable.Lookup(new IPv4(dest));
|
|
|
|
if (re != null) {
|
|
ep.SendRoute(ConvertRouteEntry(re));
|
|
}
|
|
else {
|
|
ep.SendNoRouteFound();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.FindNetRoute(Network dest) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
IPv4Network nwrk = ChannelUtils.ChannelNetworkToNetwork(dest);
|
|
NetStack.Runtime.RouteEntry re =
|
|
h.RoutingTable.Lookup(nwrk);
|
|
|
|
if (re != null) {
|
|
ep.SendRoute(ConvertRouteEntry(re));
|
|
}
|
|
else {
|
|
ep.SendNoRouteFound();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.FindSpecificHostRoute(uint dest) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
NetStack.Runtime.RouteEntry re =
|
|
h.RoutingTable.LookupSpecific(new IPv4(dest));
|
|
|
|
if (re != null) {
|
|
ep.SendRoute(ConvertRouteEntry(re));
|
|
}
|
|
else {
|
|
ep.SendNoRouteFound();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.FindSpecificNetRoute(Network dest) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
IPv4Network nwrk = ChannelUtils.ChannelNetworkToNetwork(dest);
|
|
NetStack.Runtime.RouteEntry re =
|
|
h.RoutingTable.LookupSpecific(nwrk);
|
|
|
|
if (re != null) {
|
|
ep.SendRoute(ConvertRouteEntry(re));
|
|
}
|
|
else {
|
|
ep.SendNoRouteFound();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case ep.DeleteRoute(Network dest) in epSet :
|
|
{
|
|
HostConfiguration h = ip.HostConfiguration;
|
|
IPv4Network destNet = ChannelUtils.ChannelNetworkToNetwork(dest);
|
|
NetStack.Runtime.RouteEntry re =
|
|
h.RoutingTable.LookupSpecific(destNet);
|
|
|
|
if (re == null) {
|
|
ep.SendNoRouteFound();
|
|
}
|
|
else {
|
|
h.RoutingTable.DeleteRoute(re);
|
|
ep.SendOK();
|
|
}
|
|
|
|
epSet.Add(ep);
|
|
}
|
|
break;
|
|
|
|
case nsExp.Connect(ServiceContract.Exp:Start! newEp) :
|
|
{
|
|
// We expect people top give us RoutingContract.Exp instances
|
|
//RoutingContract.Exp:Start newTcpEp = newEp as RoutingContract.Exp;
|
|
RoutingContract.Exp newTcpEp = newEp as RoutingContract.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():
|
|
run = false;
|
|
break;
|
|
|
|
case terminator.Terminate():
|
|
terminator.SendAckTerminate();
|
|
run = false;
|
|
break;
|
|
|
|
case terminator.ChannelClosed():
|
|
run = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete nsExp;
|
|
epSet.Dispose();
|
|
}
|
|
|
|
private ServiceProviderContract.Exp Register()
|
|
{
|
|
// 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(RoutingContract.ModuleName), nsImp);
|
|
|
|
switch receive {
|
|
case epNS.AckRegister() :
|
|
// All is well.
|
|
return nsExp;
|
|
break;
|
|
|
|
case epNS.NakRegister(ServiceProviderContract.Imp:Start rejectedEP, error) :
|
|
// All is very much not well; abort.
|
|
delete rejectedEP;
|
|
delete nsExp;
|
|
return null;
|
|
break;
|
|
}
|
|
}
|
|
finally {
|
|
delete epNS;
|
|
}
|
|
}
|
|
|
|
private NetStack.Contracts.RouteEntry ConvertRouteEntry(NetStack.Runtime.RouteEntry! r)
|
|
{
|
|
// Copy the contents of each RouteEntry into the
|
|
// channel structure
|
|
NetStack.Contracts.RouteEntry retval = new NetStack.Contracts.RouteEntry();
|
|
|
|
retval.network = new NetStack.Contracts.Network();
|
|
retval.network.network = (uint)r.Network.Network;
|
|
retval.network.netmask = (uint)r.Network.NetMask;
|
|
|
|
retval.gateway = (uint)r.Gateway;
|
|
retval.ifaddr = (uint)r.InterfaceAddress;
|
|
retval.metric = r.Metric;
|
|
retval.tag = r.Tag;
|
|
|
|
return retval;
|
|
}
|
|
|
|
public RoutingExpManager()
|
|
{
|
|
ip = (IPModule!)Core.Instance().GetProtocolByName("IP");
|
|
}
|
|
}
|
|
}
|