MulticastImpl.mesa
L. Stewart December 22, 1983 3:56 pm
Last Edited by: Swinehart, November 21, 1985 2:44:04 pm PST
DIRECTORY
Basics USING [Byte],
BufferDefs USING [PupBuffer],
DriverDefs USING [Network, PutOnGlobalInputQueue],
EthernetOneDriver,
EthernetOneFace USING [DeviceHandle, HostArray, InputHost, InputHosts, MulticastCapabilities, nullDeviceHandle],
IO,
Names USING [ CurrentPasskey, OwnNetAddress ],
Log USING [ Report ],
Multicast,
MulticastRpcControl,
PrincOpsUtils USING [GlobalFrame],
PupRouterDefs USING [DontForwardPupBuffer, GetRoutingTableEntry, maxHop, RoutingTableEntry, SetPupForwarder],
PupTypes USING [allHosts, PupHostID, PupNetID],
RPC USING [ Conversation, EncryptionKey, unencrypted ],
RPCPrivate USING [GetRPCPackets],
UserProfile USING [ Token ]
;
MulticastImpl: CEDAR PROGRAM
IMPORTS DriverDefs, EthernetOneFace, IO, Log, MulticastRpcControl, Names, PrincOpsUtils, PupRouterDefs, RPCPrivate, UserProfile
EXPORTS Multicast
SHARES EthernetOneDriver = {
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];
};
myName: MulticastRpcControl.InterfaceName = [
type: "Multicast.Lark",
instance: UserProfile.Token[key: "MulticastInstance", default: "Michaelson.Lark"]];
serverPassword:
RPC.EncryptionKey = Names.CurrentPasskey[UserProfile.Token[
key: "MulticastPassword", default: "MFLFLX"]];
MulticastRpcControl.ExportInterface[
interfaceName: myName,
user: myName.instance,
password: serverPassword];
Log.Report[IO.PutFR["Multicast exported as %s", IO.rope[myName.instance]], $System];
TRUSTED { []←TurnOnMulticastForNet[RPC.unencrypted, Names.OwnNetAddress[].net]; };
}.
Stewart, July 18, 1983 5:12 pm, fixes for RPC Packets
Stewart, December 22, 1983 3:51 pm, Cedar 5
Swinehart, January 31, 1984 4:57 pm, RPC Access!