<> <> <> 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_0; -- can wrap numConsidered: CARDINAL_0; MyForwarder: UNSAFE PROC [b: BufferDefs.PupBuffer] = UNCHECKED { <> 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; }; <> 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 > -- 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 <> <> <> <<>>