DIRECTORY IPConfig USING [ourLocalAddress], IPDefs USING [Datagram, Error, Errorcode, InternetHandle, InternetHandleRec, neverTimeout, nullAddress, RequestData], IPQueue, List USING [Nconc1, Remove], Process USING [SetTimeout, MsecToTicks]; IPQueueImpl: CEDAR MONITOR IMPORTS IPConfig, IPDefs, List, Process EXPORTS IPQueue ~ BEGIN OPEN IPQueue; handleQueue: LIST OF REF ANY _ NIL; -- only contains IPDefs.InternetHandles. Has to be REF ANY for List. CreateIPHandle: PUBLIC ENTRY PROC [requestData: IPDefs.RequestData] RETURNS [handle: IPDefs.InternetHandle] ~ { ENABLE UNWIND => NULL; q: LIST OF REF ANY _ handleQueue; thisHandle: IPDefs.InternetHandle; WHILE q # NIL DO -- check for conflicting requests thisHandle _ NARROW[q.first]; IF (requestData.matchProtocol AND thisHandle^.matchProtocol AND requestData.protocol # thisHandle^.protocol) OR (requestData.matchAddr AND thisHandle^.matchAddr AND requestData.address # thisHandle^.address) THEN -- no conflict, check next request q _ q.rest ELSE RETURN [NIL]; ENDLOOP; IF NOT requestData.matchLocalAddr OR requestData.localAddress = IPDefs.nullAddress THEN requestData.localAddress _ IPConfig.ourLocalAddress; handle _ NEW[IPDefs.InternetHandleRec]; handle^.matchProtocol _ requestData.matchProtocol; handle^.protocol _ requestData.protocol; handle^.matchAddr _ requestData.matchAddr; handle^.address _ requestData.address; handle^.matchLocalAddr _ requestData.matchLocalAddr; handle^.localAddress _ requestData.localAddress; handle^.printPkts _ requestData.printPkts; handle^.logPkts _ requestData.logPkts; handleQueue _ List.Nconc1[handleQueue, handle]; }; DestroyIPHandle: PUBLIC ENTRY PROC [handle: IPDefs.InternetHandle] ~ { ENABLE UNWIND => NULL; handleQueue _ List.Remove[handle, handleQueue]; handle.waitingDatagrams _ handle.lastWaitingElement _ NIL; handle.handleDestroyed _ TRUE; BROADCAST handle.newDatagram; }; Receive: PUBLIC ENTRY PROC [handle: IPDefs.InternetHandle, timeout: INT _ IPDefs.neverTimeout] RETURNS [data: IPDefs.Datagram] ~ { ENABLE UNWIND => NULL; IF handle.handleDestroyed THEN RETURN WITH ERROR IPDefs.Error[handleDestroyed]; IF timeout = 0 AND handle.waitingDatagrams = NIL THEN RETURN [NIL]; IF timeout # 0 THEN TRUSTED {Process.SetTimeout[@handle.newDatagram, Process.MsecToTicks[IF timeout > 0 THEN timeout ELSE 5000]]}; IF handle.waitingDatagrams = NIL THEN DO WAIT handle.newDatagram; IF handle.handleDestroyed THEN RETURN WITH ERROR IPDefs.Error[handleDestroyed]; IF handle.waitingDatagrams # NIL THEN EXIT; IF timeout > 0 THEN RETURN [NIL]; ENDLOOP; data _ handle.waitingDatagrams.first; handle.waitingDatagrams _ handle.waitingDatagrams.rest; IF handle.waitingDatagrams = NIL THEN handle.lastWaitingElement _ NIL; -- actually don't need this, but I feel better this way. }; QueueDatagram: PUBLIC ENTRY PROC [data: IPDefs.Datagram] ~ { ENABLE UNWIND => NULL; q: LIST OF REF ANY _ handleQueue; thisHandle: IPDefs.InternetHandle; WHILE q # NIL DO -- look at every handle. thisHandle _ NARROW[q.first]; IF (NOT thisHandle^.matchProtocol OR thisHandle^.protocol = data^.inHdr.protocol) AND (NOT thisHandle^.matchAddr OR thisHandle^.address = data^.inHdr.source) AND (NOT thisHandle^.matchLocalAddr OR thisHandle^.localAddress = data^.inHdr.destination) THEN GO TO Found -- found one ELSE q _ q.rest; -- try again REPEAT Found => AddNewDatagram[thisHandle, data]; FINISHED => NULL; ENDLOOP; }; AddNewDatagram: INTERNAL PROC [handle: IPDefs.InternetHandle, data: IPDefs.Datagram] ~ { IF handle.waitingDatagrams = NIL THEN { handle.waitingDatagrams _ LIST[data]; handle.lastWaitingElement _ handle.waitingDatagrams; } ELSE { handle.lastWaitingElement.rest _ CONS[data, NIL]; handle.lastWaitingElement _ handle.lastWaitingElement.rest; }; NOTIFY handle.newDatagram; }; END. dCopyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. The following program was created in 1983 but has not been published within the meaning of the copyright law, is furnished under license, and may not be used, copied and/or disclosed except in accordance with the terms of said license. IPQueueImpl.mesa Last Edited by: Nichols, August 24, 1983 6:56 pm Last Edited by: Taft, January 5, 1984 5:15 pm John Larson, June 12, 1987 11:24:44 pm PDT Hal Murray May 16, 1985 2:40:40 am PDT Add a new request for incoming packets. Returns a handle on the Internet. If the reqest conflicts with an existing one, then CreateIPHandle returns NIL. Default to local address. This code checks for a new local address and sets promiscuous mode. Not yet. IF requestData.LocalAddress # IPInfoPtr^.CurrentLocalAddr AND NOT IPInfoPtr^.ReceiveAllPkts THEN {SetReceiveAllPkts[]; IPInfoPtr^.ReceiveAllPkts _ TRUE}; no conflict found, add request Add this request to the list. Removes the request and flushes all waiting datagrams. Waits for a datagram that matches the request that was used to create the handle. Returns the datagram or NIL if timeout milliseconds (?) pass with no packet arriving. A value of neverTimeout for timeout will cause Receive to wait forever. Find a home for this datagram and queue it. Add a Datagram to the queue of waiting ones on a handle. Κ$– "cedar" style˜Icode2šœ―™―head™J™0J™-Icode™*J™&šΟk ˜ Kšœ œ˜!Kšœœi˜uK˜Kšœœ˜Kšœœ˜(——šΟn œœ˜Kšœ ˜'Kšœ˜Kšœ œ ˜Kš œ œœœœœΟcE˜išžœœ#œ$˜oKšœžœ œ™šKšœœœ˜Kš œœœœœ˜!Kšœ"˜"K˜šœœœŸ"˜3Kšœ œ ˜šœœœ˜@Kšœ-œ˜0Kšœœœ˜5šœ+œŸ#˜SK˜ —šœ˜Kšœœ˜ ——Kšœ˜ K˜—šœœœ/˜WK™Kšœ4Ÿ˜5K˜—K™Mšœ8œ™>Kšœ™"šœ™Kšœœ™#——K˜Kšœ™Kšœ œ˜(Kšœ3˜3Kšœ(˜(Kšœ+˜+Kšœ&˜&Kšœ4˜4Kšœ1˜1Kšœ+˜+Kšœ'˜'K™K˜/K˜—šžœœ$˜FK™6Kšœœœ˜K˜/Kšœ6œ˜:Kšœœ˜Kš œ˜K˜—š žœœœœ*œœ˜‚KšœΩžœ™ρKšœœœ˜šœ˜Kšœœœ˜0—šœ œœ˜5Kšœœ˜ —šœ ˜Kšœ>œ œ œ ˜n—šœœ˜%š˜Kšœ˜šœ˜Kšœœœ˜0—šœœ˜%Kšœ˜—šœ ˜Kšœœ˜ —Kšœ˜——K˜%K˜7šœœ˜%KšœœŸ8˜Z—K˜—šž œœœœ˜