DIRECTORY Basics USING [Byte], Commander USING [ CommandProc, Register ], CommBuffer, CommDriver USING [ CreateInterceptor, DestroyInterceptor, GetNetworkChain, Interceptor, Network, RecvInterceptor ], CommDriverType 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, CommDriver, IO, LupineRuntime, MulticastRpcControl, RPC, VoiceUtils EXPORTS CommBuffer -- for Encapsulation --, Multicast = { ourNet: Pup.Net; ourHost: Pup.Host; multicastOK: BOOL _ FALSE; interceptor: CommDriver.Interceptor _ NIL; map: PACKED ARRAY Basics.Byte OF Pup.Host _ ALL[Pup.allHosts]; TurnOnMulticastForNet: PUBLIC PROC [shh: RPC.Conversation, net: Pup.Net] RETURNS [ok: BOOL] = { network: CommDriver.Network _ NIL; IF multicastOK THEN RETURN[TRUE]; FOR network _ CommDriver.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; map _ ALL[Pup.allHosts]; interceptor _ CommDriver.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]; }; TurnOffMulticast: PUBLIC PROC[shh: RPC.Conversation] = { IF NOT multicastOK THEN RETURN; CommDriver.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; 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; }; }; numForwarded: CARDINAL_0; -- can wrap numConsidered: CARDINAL_0; Encapsulation: PUBLIC TYPE = CommDriverType.Encapsulation; MulticastForwarder: CommDriver.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 \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 MulticastImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. L. Stewart December 22, 1983 3:56 pm Swinehart, June 6, 1986 7:54:03 am PDT etherDevice: EthernetOneFace.Handle _ EthernetOneFace.nullHandle; hostArray: EthernetOneFace.HostArray _ ALL[FALSE]; 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]; 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. EthernetOneFace.SetInputHost[etherDevice, ourHost]; Or the equivalent non-promisc., 1-only hostArray[realHost] _ TRUE; Be specific about what to listen to, at ucode level. EthernetOneFace.SetInputHosts[etherDevice, @hostArray]; hostArray[realHost] _ FALSE; EthernetOneFace.SetInputHosts[etherDevice, @hostArray]; 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 Κβ˜™Icodešœ Οmœ1™Jšœ'žœžœ™2J˜šΟnœžœž˜"Jšœžœžœžœ˜