-- 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