MulticastImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
L. Stewart December 22, 1983 3:56 pm
Swinehart, May 27, 1986 12:55:42 pm PDT
DIRECTORY
Basics USING [Byte],
Commander USING [ CommandProc, Register ],
CommBuffer,
Driver USING [
CreateInterceptor, DestroyInterceptor, GetNetworkChain, Interceptor, Network, RecvInterceptor ],
DriverType USING [ Encapsulation ],
IO,
LupineRuntime USING [ BindingError ],
Multicast,
MulticastRpcControl,
Pup USING [allHosts, Host, Net],
PupBuffer USING [Buffer],
Rope USING [ ROPE ],
RPC USING [ Conversation, EncryptionKey, ExportFailed, matchAllVersions, unencrypted ],
VoiceUtils USING [ CmdOrToken, CurrentPasskey, MakeRName, OwnNetAddress, Problem, ReportFR ]
;
MulticastImpl: CEDAR PROGRAM
IMPORTS Commander, Driver, IO, LupineRuntime, MulticastRpcControl, RPC, VoiceUtils
EXPORTS CommBuffer -- for Encapsulation --, Multicast = {
ourNet: Pup.Net;
ourHost: Pup.Host;
multicastOK: BOOLFALSE;
interceptor: Driver.Interceptor ← NIL;
etherDevice: EthernetOneFace.Handle ← EthernetOneFace.nullHandle;
map: PACKED ARRAY Basics.Byte OF Pup.Host ← ALL[Pup.allHosts];
hostArray: EthernetOneFace.HostArray ← ALL[FALSE];
TurnOnMulticastForNet: PUBLIC PROC
[shh: RPC.Conversation, net: Pup.Net] RETURNS [ok: BOOL] = {
network: Driver.Network ← NIL;
IF multicastOK THEN RETURN[TRUE];
FOR network ← Driver.GetNetworkChain[], network.next WHILE network#NIL DO
IF network.pup.net = net THEN EXIT;
REPEAT FINISHED => RETURN[FALSE];
ENDLOOP;
ourNet ← net;
ourHost ← network.pup.host;
hostArray ← ALL[FALSE]; -- Not using selective receive these days, but are promiscuous
hostArray[Pup.allHosts] ← TRUE; Allows PupWatch to work and so on, but is less efficient.
hostArray[ourHost] ← TRUE;
Code to get etherDevice ← EthernetOneFace.Device for ourHost.
EthernetOneFace.SetInputHosts[etherDevice, @hostArray];
map ← ALL[Pup.allHosts];
interceptor ← Driver.CreateInterceptor[
network: network,
sendMask: ALL[FALSE],
sendProc: NIL,
recvMask: [FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE],
recvProc: MulticastForwarder,
data: NIL,
promiscuous: TRUE];
RETURN[multicastOK ← TRUE];
};
N.B.: We're making the server promiscuous, instead of listening just for the set of realHosts that are presently tuned in elsewhere. This means we'll be hearing all of the traffic on the network, and dealing with each packet in the MulticastForwarder procedure, below. That might be OK.
TurnOffMulticast: PUBLIC PROC[shh: RPC.Conversation] = {
IF NOT multicastOK THEN RETURN;
EthernetOneFace.SetInputHost[etherDevice, ourHost]; Or the equivalent non-promisc., 1-only
Driver.DestroyInterceptor[interceptor];
multicastOK ← FALSE;
};
HandleMulticast: PUBLIC PROC [shh: RPC.Conversation,
net: Pup.Net, realHost, listeningTo: Pup.Host] RETURNS [ok: BOOL] = {
IF multicastOK AND net = ourNet AND realHost # Pup.allHosts AND realHost # ourHost THEN {
IF map[realHost] # Pup.allHosts THEN RETURN[FALSE];
IF map[listeningTo] # Pup.allHosts THEN RETURN[FALSE]; -- prevent loops!
map[realHost] ← listeningTo;
hostArray[realHost] ← TRUE; Be specific about what to listen to, at ucode level.
EthernetOneFace.SetInputHosts[etherDevice, @hostArray];
RETURN[TRUE];
};
RETURN[FALSE];
};
StopHandlingMulticast: PUBLIC PROC [
shh: RPC.Conversation, realHost: Pup.Host] = {
IF multicastOK AND realHost # Pup.allHosts AND realHost # ourHost THEN {
map[realHost] ← Pup.allHosts;
hostArray[realHost] ← FALSE;
EthernetOneFace.SetInputHosts[etherDevice, @hostArray];
};
};
numForwarded: CARDINAL𡤀 -- can wrap
numConsidered: CARDINAL𡤀
Encapsulation: PUBLIC TYPE = DriverType.Encapsulation;
MulticastForwarder: Driver.RecvInterceptor = TRUSTED {
pupBuffer: PupBuffer.Buffer = LOOPHOLE[buffer];
encap: LONG POINTER TO Encapsulation = @buffer.ovh.encap;
listeningTo: Pup.Host;
numConsidered ← numConsidered+1;
IF encap.ethernetOneType # pup THEN RETURN;
listeningTo ← map[encap.ethernetOneDest]; -- Must test the encapsulation, to avoid loops!!
IF listeningTo = Pup.allHosts THEN RETURN; -- that host isn't in forwarding list.
encap.ethernetOneDest ← listeningTo;
network.pup.send[network, buffer, bytes];
};
serverInterfaceName: MulticastRpcControl.InterfaceName;
serverPassword: RPC.EncryptionKey;
MulticastInit: Commander.CommandProc = {
ENABLE
RPC.ExportFailed => { VoiceUtils.Problem["Multicast export failed", $System]; GOTO Failed; };
serverInstance: Rope.ROPE ← VoiceUtils.MakeRName[style: rName, name:
VoiceUtils.CmdOrToken[cmd: cmd, key: "MulticastInstance", default: "Michaelson.Lark"]];
serverInterfaceName ← [
type: "Multicast.Lark",
instance: serverInstance];
serverPassword ← VoiceUtils.CurrentPasskey[VoiceUtils.CmdOrToken[
cmd: cmd, key: "MulticastPassword", default: "MFLFLX"]];
MulticastRpcControl.UnexportInterface[!LupineRuntime.BindingError=>CONTINUE];
MulticastRpcControl.ExportInterface[
interfaceName: serverInterfaceName,
user: serverInterfaceName.instance,
password: serverPassword];
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[Michaelson]> <ServerPassword[...]>\nInitialize 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
Swinehart, May 15, 1986 4:40:36 pm PDT
Convert to Cedar 6.1
changes to: EXPORTS, multicastOK, interceptor, map, TurnOnMulticastForNet, TurnOffMulticast, net, HandleMulticast, shh, StopHandlingMulticast, MulticastForwarder, DIRECTORY, IMPORTS, ourNet, ourHost
Swinehart, May 27, 1986 12:55:19 pm PDT
Wasn't too good to use the Pup destination as a determiner whether to forward or not.
changes to: MulticastForwarder