DIRECTORY CommDriver USING [Buffer, Network, NoThankYou, RecvInterceptor, RecvProc, RecvType, SendInterceptor, SendProc, SendType], Process USING [Pause]; CommDriverInterceptImpl: CEDAR MONITOR IMPORTS CommDriver, Process EXPORTS CommDriver = { Buffer: TYPE = CommDriver.Buffer; Network: TYPE = CommDriver.Network; networks: Network _ NIL; numberOfNetworks: CARDINAL _ 0; defaultRecvProcs: ARRAY CommDriver.RecvType OF CommDriver.RecvProc _ ALL[CommDriver.NoThankYou]; GetNetworkChain: PUBLIC PROC RETURNS [Network] = { RETURN[networks]; }; GetNumberOfNetworks: PUBLIC PROC RETURNS [CARDINAL] = { RETURN[numberOfNetworks]; }; AddNetwork: PUBLIC ENTRY PROC [network: Network] = { IF network.next # NIL THEN ERROR; network.arpa.recv _ defaultRecvProcs[arpa]; network.arpa.recvTranslate _ defaultRecvProcs[arpaTranslate]; network.xns.recv _ defaultRecvProcs[xns]; network.xns.recvTranslate _ defaultRecvProcs[xnsTranslate]; network.pup.recv _ defaultRecvProcs[pup]; network.pup.recvTranslate _ defaultRecvProcs[pupTranslate]; network.other.recv _ defaultRecvProcs[other]; network.other.recvTranslate _ defaultRecvProcs[otherTranslate]; network.error.recv _ defaultRecvProcs[error]; IF networks = NIL THEN networks _ network ELSE { FOR finger: Network _ networks, finger.next DO IF finger.next # NIL THEN LOOP; finger.next _ network; EXIT; ENDLOOP; }; numberOfNetworks _ numberOfNetworks + 1; network.index _ numberOfNetworks; }; InsertReceiveProc: PUBLIC ENTRY PROC [ network: Network, -- NIL => all networks type: CommDriver.RecvType, proc: CommDriver.RecvProc] = { ENABLE UNWIND => NULL; IF network # NIL THEN { InsertReceiveInner[network, type, proc]; RETURN; }; FOR network: Network _ networks, network.next UNTIL network = NIL DO InsertReceiveInner[network, type, proc]; ENDLOOP; defaultRecvProcs[type] _ proc; -- only if all networks }; SlotAlreadyCaptured: SIGNAL = CODE; InsertReceiveInner: INTERNAL PROC [ network: Network, type: CommDriver.RecvType, proc: CommDriver.RecvProc] = { interceptor: Interceptor _ network.interceptor; IF interceptor = NIL THEN { -- normal case, no interception in progress previous: CommDriver.RecvProc; SELECT type FROM arpa => previous _ network.arpa.recv; arpaTranslate => previous _ network.arpa.recvTranslate; xns => previous _ network.xns.recv; xnsTranslate => previous _ network.xns.recvTranslate; pup => previous _ network.pup.recv; pupTranslate => previous _ network.pup.recvTranslate; other => previous _ network.other.recv; otherTranslate => previous _ network.other.recvTranslate; error => previous _ network.error.recv; ENDCASE => ERROR; IF previous # CommDriver.NoThankYou THEN SIGNAL SlotAlreadyCaptured; SELECT type FROM arpa => network.arpa.recv _ proc; arpaTranslate => network.arpa.recvTranslate _ proc; xns => network.xns.recv _ proc; xnsTranslate => network.xns.recvTranslate _ proc; pup => network.pup.recv _ proc; pupTranslate => network.pup.recvTranslate _ proc; other => network.other.recv _ proc; otherTranslate => network.other.recvTranslate _ proc; error => network.error.recv _ proc; ENDCASE => ERROR; } ELSE { -- Interesting case, interception in progress procs: REF Procs _ interceptor.procs; IF procs.recv[type] # CommDriver.NoThankYou THEN SIGNAL SlotAlreadyCaptured; procs.recv[type] _ proc; }; }; Interceptor: TYPE = REF InterceptorRep; InterceptorRep: PUBLIC TYPE = RECORD [ next: Interceptor, alive: BOOL, procs: REF Procs, network: Network, sendMask: PACKED ARRAY CommDriver.SendType OF BOOL, sendProc: CommDriver.SendInterceptor, recvMask: PACKED ARRAY CommDriver.RecvType OF BOOL, recvProc: CommDriver.RecvInterceptor, data: REF ANY, promiscuous: BOOL ]; Procs: TYPE = RECORD [ send: ARRAY CommDriver.SendType OF CommDriver.SendProc, recv: ARRAY CommDriver.RecvType OF CommDriver.RecvProc ]; CreateInterceptor: PUBLIC ENTRY PROC [ network: Network, sendMask: PACKED ARRAY CommDriver.SendType OF BOOL, sendProc: CommDriver.SendInterceptor, recvMask: PACKED ARRAY CommDriver.RecvType OF BOOL, recvProc: CommDriver.RecvInterceptor, data: REF ANY, promiscuous: BOOL] RETURNS [interceptor: Interceptor] = { others: Interceptor _ network.interceptor; procs: REF Procs; IF others # NIL THEN procs _ others.procs ELSE procs _ NEW[Procs _ [ send: [ arpa: network.arpa.send, arpaReturn: network.arpa.return, arpaTranslate: network.arpa.sendTranslate, xns: network.xns.send, xnsReturn: network.xns.return, xnsTranslate: network.xns.sendTranslate, pup: network.pup.send, pupReturn: network.pup.return, pupTranslate: network.pup.sendTranslate, other: network.other.send, otherReturn: network.other.return, otherTranslate: network.other.sendTranslate, raw: network.raw.send], recv: [ arpa: network.arpa.recv, arpaTranslate: network.arpa.recvTranslate, xns: network.xns.recv, xnsTranslate: network.xns.recvTranslate, pup: network.pup.recv, pupTranslate: network.pup.recvTranslate, other: network.other.recv, otherTranslate: network.other.recvTranslate, error: network.error.recv] ]]; interceptor _ NEW[InterceptorRep _ [ next: others, alive: TRUE, procs: procs, network: network, sendMask: sendMask, sendProc: sendProc, recvMask: recvMask, recvProc: recvProc, data: data, promiscuous: promiscuous] ]; network.interceptor _ interceptor; IF others = NIL THEN { network.arpa.send _ IPSend; network.arpa.return _ IPReturn; network.arpa.recv _ IPRecv; network.arpa.sendTranslate _ IPSendTranslate; network.arpa.recvTranslate _ IPRecvTranslate; network.xns.send _ NSSend; network.xns.return _ NSReturn; network.xns.recv _ NSRecv; network.xns.sendTranslate _ NSSendTranslate; network.xns.recvTranslate _ NSRecvTranslate; network.pup.send _ PupSend; network.pup.return _ PupReturn; network.pup.recv _ PupRecv; network.pup.sendTranslate _ PupSendTranslate; network.pup.recvTranslate _ PupRecvTranslate; network.other.send _ OtherSend; network.other.return _ OtherReturn; network.other.recv _ OtherRecv; network.other.sendTranslate _ OtherSendTranslate; network.other.recvTranslate _ OtherRecvTranslate; network.raw.send _ RawSend; network.error.recv _ ErrorRecv; }; IF promiscuous THEN network.setPromiscuous[network, TRUE]; }; DestroyInterceptor: PUBLIC ENTRY PROC [interceptor: Interceptor] = { network: Network _ interceptor.network; IF ~interceptor.alive THEN RETURN; interceptor.alive _ FALSE; IF network.interceptor = interceptor THEN { IF interceptor.next = NIL THEN { procs: REF Procs _ interceptor.procs; network.setPromiscuous[network, FALSE]; Process.Pause[5]; network.arpa.send _ procs.send[arpa]; network.arpa.return _ procs.send[arpaReturn]; network.arpa.sendTranslate _ procs.send[arpaTranslate]; network.xns.send _ procs.send[xns]; network.xns.return _ procs.send[xnsReturn]; network.xns.sendTranslate _ procs.send[xnsTranslate]; network.pup.send _ procs.send[pup]; network.pup.return _ procs.send[pupReturn]; network.pup.sendTranslate _ procs.send[pupTranslate]; network.other.send _ procs.send[other]; network.other.return _ procs.send[otherReturn]; network.other.sendTranslate _ procs.send[otherTranslate]; network.raw.send _ procs.send[raw]; network.arpa.recv _ procs.recv[arpa]; network.arpa.recvTranslate _ procs.recv[arpaTranslate]; network.xns.recv _ procs.recv[xns]; network.xns.recvTranslate _ procs.recv[xnsTranslate]; network.pup.recv _ procs.recv[pup]; network.pup.recvTranslate _ procs.recv[pupTranslate]; network.other.recv _ procs.recv[other]; network.other.recvTranslate _ procs.recv[otherTranslate]; network.error.recv _ procs.recv[error]; }; network.interceptor _ interceptor.next; } ELSE { first: Interceptor _ network.interceptor; FOR finger: Interceptor _ first, finger.next DO -- NIL fault if not found IF finger.next # interceptor THEN LOOP; finger.next _ interceptor.next; EXIT; ENDLOOP; }; }; IPSend: CommDriver.SendProc = { SendOne[arpa, network, buffer, bytes]; }; IPReturn: CommDriver.SendProc = { SendOne[arpaReturn, network, buffer, bytes]; }; IPSendTranslate: CommDriver.SendProc = { SendOne[arpaTranslate, network, buffer, bytes]; }; NSSend: CommDriver.SendProc = { SendOne[xns, network, buffer, bytes]; }; NSReturn: CommDriver.SendProc = { SendOne[xnsReturn, network, buffer, bytes]; }; NSSendTranslate: CommDriver.SendProc = { SendOne[xnsTranslate, network, buffer, bytes]; }; PupSend: CommDriver.SendProc = { SendOne[pup, network, buffer, bytes]; }; PupReturn: CommDriver.SendProc = { SendOne[pupReturn, network, buffer, bytes]; }; PupSendTranslate: CommDriver.SendProc = { SendOne[pupTranslate, network, buffer, bytes]; }; OtherSend: CommDriver.SendProc = { SendOne[other, network, buffer, bytes]; }; OtherReturn: CommDriver.SendProc = { SendOne[otherReturn, network, buffer, bytes]; }; OtherSendTranslate: CommDriver.SendProc = { SendOne[otherTranslate, network, buffer, bytes]; }; RawSend: CommDriver.SendProc = { SendOne[raw, network, buffer, bytes]; }; SendOne: PROC [send: CommDriver.SendType, network: Network, buffer: Buffer, bytes: NAT] = { first: Interceptor _ network.interceptor; kill: BOOL _ FALSE; IF first = NIL THEN RETURN; -- Race with DeleteInterceptor FOR interceptor: Interceptor _ first, interceptor.next UNTIL interceptor = NIL DO IF ~interceptor.sendMask[send] THEN LOOP; kill _ kill OR interceptor.sendProc[send, interceptor.data, network, buffer, bytes]; ENDLOOP; IF kill THEN RETURN; first.procs.send[send][network, buffer, bytes]; }; IPRecv: CommDriver.RecvProc = { RETURN[RecvOne[arpa, network, buffer, bytes]]; }; IPRecvTranslate: CommDriver.RecvProc = { RETURN[RecvOne[arpaTranslate, network, buffer, bytes]]; }; NSRecv: CommDriver.RecvProc = { RETURN[RecvOne[xns, network, buffer, bytes]]; }; NSRecvTranslate: CommDriver.RecvProc = { RETURN[RecvOne[xnsTranslate, network, buffer, bytes]]; }; PupRecv: CommDriver.RecvProc = { RETURN[RecvOne[pup, network, buffer, bytes]]; }; PupRecvTranslate: CommDriver.RecvProc = { RETURN[RecvOne[pupTranslate, network, buffer, bytes]]; }; OtherRecv: CommDriver.RecvProc = { RETURN[RecvOne[other, network, buffer, bytes]]; }; OtherRecvTranslate: CommDriver.RecvProc = { RETURN[RecvOne[otherTranslate, network, buffer, bytes]]; }; ErrorRecv: PROC [network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer] = { RETURN[RecvOne[error, network, buffer, bytes]]; }; RecvOne: PROC [recv: CommDriver.RecvType, network: Network, buffer: Buffer, bytes: NAT] RETURNS [Buffer] = { first: Interceptor _ network.interceptor; forMe: BOOL _ network.isThisForMe[network, buffer]; kill: BOOL _ FALSE; IF first = NIL THEN RETURN[buffer]; -- Race with DeleteInterceptor FOR interceptor: Interceptor _ first, interceptor.next UNTIL interceptor = NIL DO IF ~interceptor.recvMask[recv] THEN LOOP; IF ~forMe AND ~interceptor.promiscuous THEN LOOP; kill _ kill OR interceptor.recvProc[recv, interceptor.data, network, buffer, bytes]; ENDLOOP; IF kill THEN RETURN[buffer]; IF ~forMe THEN RETURN[buffer]; RETURN[first.procs.recv[recv][network, buffer, bytes]]; }; }. àCommDriverInterceptImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Hal Murray, May 29, 1986 2:43:44 am PDT Yetch. There is a race on turning off Promiscuous vs setting the procs back to normal. Ê Ò˜codešœ™Kšœ Ïmœ1™