-- Copyright (C) 1979, 1980, 1984 by Xerox Corporation. All rights reserved. -- FTPPupComHot.mesa, Edited by: HGM July 31, 1980 5:50 PM DIRECTORY FTPDefs, FTPPrivateDefs, FTPPupComDefs USING [PupConnection, AbortBecauseStreamClosing], PupStream USING [CloseReason, StreamClosing], Stream USING [ Block, CompletionCode, defaultInputOptions, GetBlock, GetByte, InputOptions, PutBlock, PutByte, SendNow, SetInputOptions, SetSST, SSTChange, TimeOut]; FTPPupComHot: PROGRAM IMPORTS PupStream, Stream, FTPPrivateDefs, FTPPupComDefs EXPORTS FTPPupComDefs SHARES FTPDefs = BEGIN OPEN FTPDefs, FTPPrivateDefs; -- **********************! Constants !*********************** ftpsystem: POINTER TO FTPSystem = LocateFtpSystemObject[]; SendBytes: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection, bytePointer: BytePointer] = BEGIN -- catchphrase ENABLE BEGIN PupStream.StreamClosing => --FTPPupComDefs.-- MyAbortBecauseStreamClosing[why, text]; Stream.TimeOut => Abort[connectionTimedOut]; END; -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; startIndex: CARDINAL = IF bytePointer.offset THEN 1 ELSE 0; -- local variables block: Stream.Block = [ blockPointer: bytePointer.address, startIndex: startIndex, stopIndexPlusOne: startIndex + bytePointer.count]; -- abort if output discontinuity IF pupConnection.outputDiscontinuity THEN Abort[outputDiscontinuityUnexpected]; -- send bytes Stream.PutBlock[pupConnection.streamHandle, block, FALSE]; -- advance caller's byte pointer AdvanceBytePointer[bytePointer, bytePointer.count]; END; ReceiveBytes: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection, bytePointer: BytePointer, settleForLess: BOOLEAN] = BEGIN -- catchphrase ENABLE BEGIN PupStream.StreamClosing => --FTPPupComDefs.-- MyAbortBecauseStreamClosing[why, text]; Stream.TimeOut => Abort[connectionTimedOut]; END; -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; startIndex: CARDINAL = IF bytePointer.offset THEN 1 ELSE 0; -- local variables inputOptions: Stream.InputOptions ← Stream.defaultInputOptions; block: Stream.Block = [ blockPointer: bytePointer.address, startIndex: startIndex, stopIndexPlusOne: startIndex + bytePointer.count]; bytesTransferred: CARDINAL ← 0; completionCode: Stream.CompletionCode ← normal; -- return if no operation IF bytePointer.count = 0 THEN RETURN; -- abort if input discontinuity IF pupConnection.inputDiscontinuity OR pupConnection.inputDiscontinuityConsumed THEN Abort[inputDiscontinuityUnexpected]; -- adjust input options if necessary IF settleForLess # pupConnection.terminateOnEndPhysicalRecord THEN BEGIN -- select and record new input option inputOptions.terminateOnEndRecord ← pupConnection.terminateOnEndPhysicalRecord ← settleForLess; -- instate new input option Stream.SetInputOptions[pupConnection.streamHandle, inputOptions]; END; -- receive bytes [bytesTransferred, completionCode, pupConnection.mark] ← Stream.GetBlock[ pupConnection.streamHandle, block]; -- note input discontinuity if any pupConnection.inputDiscontinuity ← completionCode = sstChange; -- advance caller's byte pointer AdvanceBytePointer[bytePointer, bytesTransferred]; END; SendByte: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection, byte: Byte] = BEGIN -- catchphrase ENABLE BEGIN PupStream.StreamClosing => --FTPPupComDefs.-- MyAbortBecauseStreamClosing[why, text]; Stream.TimeOut => Abort[connectionTimedOut]; END; -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; -- send mark IF pupConnection.outputDiscontinuity THEN BEGIN pupConnection.outputDiscontinuity ← FALSE; Stream.SetSST[pupConnection.streamHandle, byte]; END -- send byte ELSE Stream.PutByte[pupConnection.streamHandle, byte]; END; ReceiveByte: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection, settleForNone: BOOLEAN] RETURNS [byte: Byte, settledForNone: BOOLEAN] = BEGIN -- catchphrase ENABLE BEGIN PupStream.StreamClosing => --FTPPupComDefs.-- MyAbortBecauseStreamClosing[why, text]; Stream.TimeOut => Abort[connectionTimedOut]; END; -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; -- settle for none or abort if input discontinuity IF pupConnection.inputDiscontinuity THEN IF settleForNone THEN RETURN[byte, TRUE] ELSE Abort[inputDiscontinuityUnexpected]; -- assume won't have to settle for none settledForNone ← FALSE; -- return mark IF pupConnection.inputDiscontinuityConsumed THEN BEGIN pupConnection.inputDiscontinuityConsumed ← FALSE; byte ← pupConnection.mark; END -- receive byte ELSE byte ← Stream.GetByte[ pupConnection.streamHandle ! Stream.SSTChange => IF settleForNone THEN BEGIN pupConnection.inputDiscontinuity ← TRUE; pupConnection.mark ← sst; settledForNone ← TRUE; CONTINUE; END ELSE Abort[inputDiscontinuityUnexpected]]; END; ProduceDiscontinuity: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection] = BEGIN -- Note: Extra calls to this procedure without intervening data -- are treated as no operations. -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; -- produce output discontinuity pupConnection.outputDiscontinuity ← TRUE; END; ConsumeDiscontinuity: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection] = BEGIN -- Note: Extra calls to this procedure without intervening data -- are treated as no operations. -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; -- consume input discontinuity IF pupConnection.inputDiscontinuity THEN BEGIN pupConnection.inputDiscontinuity ← FALSE; pupConnection.inputDiscontinuityConsumed ← TRUE; END; END; ForceOutput: PUBLIC PROCEDURE [ communicationSystem: CommunicationSystem, connection: Connection] = BEGIN -- catchphrase ENABLE BEGIN PupStream.StreamClosing => --FTPPupComDefs.-- MyAbortBecauseStreamClosing[why, text]; Stream.TimeOut => Abort[connectionTimedOut]; END; -- local constants pupConnection: FTPPupComDefs.PupConnection = LOOPHOLE[connection]; -- force output Stream.SendNow[pupConnection.streamHandle]; END; MyAbortBecauseStreamClosing: PROC [ closeReason: PupStream.CloseReason, message: LONG STRING] = { string: STRING ← [40]; IF message # NIL THEN { string.length ← MIN[string.maxlength, message.length]; FOR i: CARDINAL IN [0..string.length) DO string[i] ← message[i] ENDLOOP} ELSE string ← NIL; FTPPupComDefs.AbortBecauseStreamClosing[closeReason, string]}; -- **********************! Main Program !*********************** -- no operation END. -- of FTPPupComHot