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! ÄMulticastImpl.mesa L. Stewart December 22, 1983 3:56 pm Last Edited by: Swinehart, November 21, 1985 2:44:04 pm PST Stolen from PupRouterOut.PupRouterSendThis driver encapsulate and send it �ÊQ˜J™J™$J™;šÏk ˜ Jšœ�œ˜Jšœ �œ ˜Jšœ �œ"˜2Jšœ˜Jšœ�œ[˜pJš�œ˜Jšœ�œ#˜.Jšœ�œ ˜J˜ J˜Jšœ�œ˜"Jšœ�œZ˜mJšœ �œ!˜/Jš�œ�œ.˜7Jšœ �œ˜!J˜J˜—J˜Jšœ� ˜Jš�œ�œX˜Jš�œ ˜Jš�œ˜J˜Jšœ˜Jšœ˜Jšœ �œ�œ˜J˜MJš œ� œ�œ�œ�œ˜LJ˜Jš œ�œ�œ �œ�œ˜MJšœ'�œ�œ˜2J˜šÏnœ�œ�œ�œ'�œ�œ�œ˜qJ˜%J˜Jšœ�œ�œ�œ˜)J˜OJš�œ �œ�œ�œ˜!Jš �œ�œ�œ�œ�œ˜ Jšœ˜Jš �œ �œ�œ�œ�œ˜$Jš�œ�œ�œ�œ˜3Jšœ�œ�œ˜HJ˜Jšœ#˜#Jš �œ�œ5�œ�œ�œ˜NJš�œA�œ�œ�œ˜VJšœ ˜ Jšœ �œ˜)Jšœ �œ�œ˜Jšœ�œ˜$Jšœ�œ˜Jšœ�œ˜J˜Jšœ4˜4Jšœ�œ˜Jšœ+˜+Jšœ)˜)Jš�œ�œ˜ J˜—J˜š žœ�œ�œ�œ�œ˜@Jšœ0˜0JšœB˜BJšœ*˜*Jšœ�œ˜Jšœ�œ˜J˜—J˜šžœ�œ�œ�œ˜4JšœC�œ�œ�œ˜aš �œ �œ�œ�œ�œ˜^Jš�œ#�œ�œ�œ˜8Jš �œ�œ�œ�œÏc˜@Jšœ�œ˜Jšœ˜Jšœ4˜4Jš�œ�œ˜ J˜—Jš�œ�œ˜J˜—J˜šžœ�œ�œ˜$Jšœ�œ/�œ˜@š�œ �œ�œ�œ˜MJšœ"˜"Jšœ�œ˜Jšœ4˜4J˜—J˜—J˜Jšœ�œ˜%Jšœ�œ˜J˜šž œ�œ�œ� œ˜@J™*J˜"J˜MJ˜J˜3Jšœ ˜ š�œ �œ�œ�œ �œ�œ�œ�œ˜~Jšœ&˜&Jš�œ˜J˜—J™J˜Jšœ'˜'J˜J˜—J˜š žœ�œ�œ�œ�œ� œ˜UJš �œ�œ�œ�œ�œ�œ˜BJšœ$˜$Jš�œ�œ˜ J˜—J˜˜-J˜J˜S—šœ�œ8˜KJ˜.—˜$J˜J˜J˜—J˜Jšœ �œ#�œ"˜TJš�œ�œ,˜RJ˜Jšœ˜Jšœ*�œ˜5Jšœ+˜+J˜0—…—¢·