<> <> <> 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_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]; }; 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!