MulticastImpl.mesa
L. Stewart December 22, 1983 3:56 pm
Last Edited by: Swinehart, December 3, 1985 3:01:34 pm PST
DIRECTORY
Basics USING [Byte],
BufferDefs USING [PupBuffer],
Commander USING [ CommandProc, Register ],
DriverDefs USING [Network, PutOnGlobalInputQueue],
EthernetOneDriver,
EthernetOneFace USING [DeviceHandle, HostArray, InputHost, InputHosts, MulticastCapabilities, nullDeviceHandle],
ExplicitExport USING [ ExportExplicitly ],
IO,
LupineRuntime USING [ BindingError ],
Multicast,
MulticastRpcControl,
MulticastRpcServerImpl,
PrincOpsUtils USING [GlobalFrame],
PupRouterDefs USING [DontForwardPupBuffer, GetRoutingTableEntry, maxHop, RoutingTableEntry, SetPupForwarder],
PupTypes USING [allHosts, PupHostID, PupNetID],
RPC USING [ Conversation, EncryptionKey, ExportFailed, matchAllVersions, unencrypted ],
RPCPrivate USING [GetRPCPackets],
VoiceUtils USING [ CmdOrToken, CurrentPasskey, OwnNetAddress, Problem, ReportFR ]
;
MulticastImpl: CEDAR PROGRAM
IMPORTS Commander, DriverDefs, EthernetOneFace, ExplicitExport, IO, LupineRuntime, MulticastRpcControl, MulticastRpcServerImpl, PrincOpsUtils, PupRouterDefs, RPC, RPCPrivate, VoiceUtils
EXPORTS Multicast
SHARES EthernetOneDriver, MulticastRpcServerImpl = {
ourNet: PupTypes.PupNetID;
ourHost: PupTypes.PupHostID;
multicastOK: BOOL ← FALSE;
etherDevice: EthernetOneFace.DeviceHandle ← EthernetOneFace.nullDeviceHandle;
oldEnqueueRecvd: UNSAFE PROC [BufferDefs.PupBuffer] RETURNS [BOOLEAN] ← NIL;
map: PACKED ARRAY Basics.Byte OF PupTypes.PupHostID ← ALL[PupTypes.allHosts];
hostArray: EthernetOneFace.HostArray ← ALL[FALSE];
TurnOnMulticastForNet:
PUBLIC
PROC [shh:
RPC.Conversation, net: PupTypes.PupNetID]
RETURNS [ok:
BOOL] =
TRUSTED {
device: EthernetOneFace.DeviceHandle;
network: DriverDefs.Network;
him: POINTER TO FRAME[EthernetOneDriver];
rte: PupRouterDefs.RoutingTableEntry ← PupRouterDefs.GetRoutingTableEntry[net];
IF multicastOK THEN RETURN[TRUE];
IF rte = NIL THEN RETURN[FALSE];
network ← rte.network;
IF network = NIL THEN RETURN[FALSE];
IF network.device # ethernetOne THEN RETURN[FALSE];
him ← LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[network.sendBuffer]]];
device ← him.ether;
oldEnqueueRecvd ← him.EnqueueRecvd;
IF NOT EthernetOneFace.MulticastCapabilities[device].canDo THEN RETURN[FALSE];
IF EthernetOneFace.MulticastCapabilities[device].multicastsEnabled THEN RETURN[FALSE];
ourNet ← net;
ourHost ← [LOOPHOLE[network.hostNumber]];
hostArray ← ALL[FALSE];
hostArray[PupTypes.allHosts] ← TRUE;
hostArray[ourHost] ← TRUE;
map ← ALL[PupTypes.allHosts];
etherDevice ← device;
EthernetOneFace.InputHosts[etherDevice, @hostArray];
multicastOK ← TRUE;
PupRouterDefs.SetPupForwarder[MyForwarder];
RPCPrivate.GetRPCPackets[MyEnqueueRecvd];
RETURN[TRUE];
};
TurnOffMulticast:
PUBLIC
PROC[shh:
RPC.Conversation] =
TRUSTED {
EthernetOneFace.InputHost[etherDevice, ourHost];
PupRouterDefs.SetPupForwarder[PupRouterDefs.DontForwardPupBuffer];
RPCPrivate.GetRPCPackets[oldEnqueueRecvd];
oldEnqueueRecvd ← NIL;
multicastOK ← FALSE;
};
HandleMulticast:
PUBLIC
PROC [shh:
RPC.Conversation,
net: PupTypes.PupNetID, realHost, listeningTo: PupTypes.PupHostID] RETURNS [ok: BOOL] = TRUSTED {
IF multicastOK
AND net = ourNet
AND realHost # PupTypes.allHosts
AND realHost # ourHost
THEN {
IF map[realHost] # PupTypes.allHosts THEN RETURN[FALSE];
IF hostArray[listeningTo] THEN RETURN[FALSE]; -- prevent loops!
hostArray[realHost] ← TRUE;
map[realHost] ← listeningTo;
EthernetOneFace.InputHosts[etherDevice, @hostArray];
RETURN[TRUE];
};
RETURN[FALSE];
};
StopHandlingMulticast:
PUBLIC
PROC [
shh: RPC.Conversation, realHost: PupTypes.PupHostID] = TRUSTED {
IF multicastOK
AND realHost # PupTypes.allHosts
AND realHost # ourHost
THEN {
map[realHost] ← PupTypes.allHosts;
hostArray[realHost] ← FALSE;
EthernetOneFace.InputHosts[etherDevice, @hostArray];
};
};
numForwarded: CARDINAL𡤀 -- can wrap
numConsidered: CARDINAL𡤀
MyForwarder:
UNSAFE
PROC [b: BufferDefs.PupBuffer] =
UNCHECKED {
Stolen from PupRouterOut.PupRouterSendThis
n: PupTypes.PupNetID ← b.dest.net;
rte: PupRouterDefs.RoutingTableEntry ← PupRouterDefs.GetRoutingTableEntry[n];
network: DriverDefs.Network;
listeningTo: PupTypes.PupHostID ← map[b.dest.host];
numConsidered ← numConsidered+1;
IF n # ourNet
OR rte =
NIL
OR rte.hop > PupRouterDefs.maxHop
OR (network ← rte.network) =
NIL
OR hostArray[listeningTo]
THEN {
PupRouterDefs.DontForwardPupBuffer[b];
RETURN;
};
driver encapsulate and send it
numForwarded ← numForwarded+1;
network.encapsulatePup[b, listeningTo];
network.sendBuffer[b];
};
MyEnqueueRecvd:
UNSAFE
PROC [b: BufferDefs.PupBuffer]
RETURNS [
BOOLEAN] =
UNCHECKED {
IF oldEnqueueRecvd # NIL AND oldEnqueueRecvd[b] THEN RETURN[TRUE];
DriverDefs.PutOnGlobalInputQueue[b];
RETURN[TRUE];
};
serverInterfaceName: MulticastRpcControl.InterfaceName;
serverPassword: RPC.EncryptionKey;
MulticastInit: Commander.CommandProc = {
ENABLE
RPC.ExportFailed => { VoiceUtils.Problem["Multicast export failed", $System]; GOTO Failed; };
serverInterfaceName ← [
type: "Multicast.Lark",
instance: VoiceUtils.CmdOrToken[cmd: cmd, key: "MulticastInstance", default: "Michaelson.Lark"]];
serverPassword ← VoiceUtils.CurrentPasskey[VoiceUtils.CmdOrToken[
cmd: cmd, key: "MulticastPassword", default: "MFLFLX"]];
MulticastRpcControl.UnexportInterface[];
MulticastRpcControl.ExportInterface[
interfaceName: serverInterfaceName,
user: serverInterfaceName.instance,
password: serverPassword];
ExplicitExport.ExportExplicitly["Multicast.Lark", serverInterfaceName.instance, RPC.matchAllVersions, MulticastRpcControl.LupineProtocolVersion, MulticastRpcServerImpl.ServerDispatcher];
VoiceUtils.ReportFR["Export[Multicast.Lark, %s]", $System, NIL, IO.rope[serverInterfaceName.instance]];
IF ~TurnOnMulticastForNet[
RPC.unencrypted, VoiceUtils.OwnNetAddress[].net] THEN {
VoiceUtils.Problem["Multicast enabling failed", $System];
GOTO Failed;
};
EXITS
Failed => MulticastRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE];
};
Commander.Register["Multicast", MulticastInit,
"Multicast <ExportInstance(opt.) <ServerPassword (opt)>> -- Initialize and Export Multicast"];
}.
Stewart, July 18, 1983 5:12 pm, fixes for RPC Packets
Stewart, December 22, 1983 3:51 pm, Cedar 5
Swinehart, November 25, 1985 11:45:46 am PST, RPC Access!, Swinehart
Swinehart, November 25, 1985 11:45:02 am PST
Add Multicast command: "Multicast Michaelson.Lark MFFLX" is default.
changes to: DIRECTORY, IMPORTS, SHARES, MulticastInit, Commander