DIRECTORY Basics USING [Byte], BufferDefs USING [PupBuffer], DriverDefs USING [Network, PutOnGlobalInputQueue], EthernetOneDriver, EthernetOneFace USING [DeviceHandle, HostArray, InputHost, InputHosts, MulticastCapabilities, nullDeviceHandle], IO, Log USING [ Report ], Names USING [ CurrentPasskey, OwnNetAddress ], 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[FALSE]; 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, May 16, 1985 5:16:46 pm PDT Stolen from PupRouterOut.PupRouterSendThis driver encapsulate and send it ÊQ˜J™J™$J™6šÏ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—…—¤µ