-- FTPDefs.mesa,  Edit: HGM July 28, 1980  8:38 PM  

-- Copyright  Xerox Corporation 1979, 1980

FTPDefs: DEFINITIONS =
  BEGIN

-- **********************!  Version  !***********************

ftpMajorVersion: Byte = 6;
ftpMinorVersion: Byte = 0;

-- **********************!  File System  !***********************

-- file types
FileSystem: TYPE = POINTER TO FileSystemObject;
FileSystemObject: TYPE = RECORD [dummy: UNSPECIFIED];
VirtualFilename: TYPE = POINTER TO VirtualFilenameObject;
VirtualFilenameObject: TYPE = RECORD [device, directory, name, version: STRING];
Status: TYPE = {primary, secondary};
Intent: TYPE = {enumeration, retrieval, deletion, renaming, unspecified};
EnumerateFilesIntent: TYPE = Intent[enumeration..deletion];
DumpFileIntent: TYPE = Intent[enumeration..retrieval];
FileInfo: TYPE = POINTER TO FileInfoObject;
FileInfoObject: TYPE = RECORD [
  fileType: FileType,
  byteSize: CARDINAL,
  byteCount: LONG CARDINAL,
  creationDate, writeDate, readDate,
  author: STRING];
FileType: TYPE = {text, binary, unknown};
ConcreteFileType: TYPE = FileType[text..binary];
Mode: TYPE = {read, write, append, writeThenRead, readThenWrite};
FileHandle: TYPE = POINTER TO FileHandleObject;
FileHandleObject: TYPE = RECORD [dummy: UNSPECIFIED];

-- file primitives
FilePrimitives: TYPE = POINTER TO FilePrimitivesObject;
FilePrimitivesObject: TYPE = RECORD [
  CreateFileSystem: PROCEDURE [bufferSize: CARDINAL] RETURNS [fileSystem: FileSystem],
  DestroyFileSystem: PROCEDURE [fileSystem: FileSystem],
  DecomposeFilename,
  ComposeFilename: PROCEDURE [
    fileSystem: FileSystem, absoluteFilename: STRING, virtualFilename: VirtualFilename],
  InspectCredentials: PROCEDURE [
    fileSystem: FileSystem, status: Status, user, password: STRING],
  EnumerateFiles: PROCEDURE [
    fileSystem: FileSystem, files: STRING, intent: EnumerateFilesIntent,
    processFile: PROCEDURE [UNSPECIFIED, STRING, FileInfo],
    processFileData: UNSPECIFIED],
  OpenFile: PROCEDURE [
    fileSystem: FileSystem, file: STRING, mode: Mode,
    fileTypePlease: BOOLEAN, info: FileInfo]
    RETURNS [fileHandle: FileHandle, fileType: FileType],
  ReadFile: PROCEDURE [fileSystem: FileSystem, fileHandle: FileHandle,
    sendBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL],
    sendBlockData: UNSPECIFIED],
  WriteFile: PROCEDURE [fileSystem: FileSystem, fileHandle: FileHandle,
    receiveBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL] RETURNS [CARDINAL],
    receiveBlockData: UNSPECIFIED],
  CloseFile: PROCEDURE [fileSystem: FileSystem, fileHandle: FileHandle, aborted: BOOLEAN],
  DeleteFile: PROCEDURE [fileSystem: FileSystem, file: STRING],
  RenameFile: PROCEDURE [fileSystem: FileSystem, currentFile, newFile: STRING]];

-- file system
AltoFilePrimitives: PROCEDURE RETURNS [filePrimitives: FilePrimitives];

-- **********************!  Mail System  !***********************

-- mail types
MailSystem: TYPE = POINTER TO MailSystemObject;
MailSystemObject: TYPE = RECORD [dummy: UNSPECIFIED];
Mailbox: TYPE = POINTER TO MailboxObject;
MailboxObject: TYPE = RECORD [
  number: CARDINAL,
  mailbox, location: STRING,
  located, delivered: BOOLEAN,
  nextMailbox: Mailbox];
MessageInfo: TYPE = POINTER TO MessageInfoObject;
MessageInfoObject: TYPE = RECORD [
  byteCount: LONG CARDINAL,
  deliveryDate: STRING,
  opened, deleted: BOOLEAN];

-- mail primitives
MailPrimitives: TYPE = POINTER TO MailPrimitivesObject;
MailPrimitivesObject: TYPE = RECORD [
  CreateMailSystem: PROCEDURE [filePrimitives: FilePrimitives, bufferSize: CARDINAL]
    RETURNS [mailSystem: MailSystem, forwardingProvided: BOOLEAN],
  DestroyMailSystem: PROCEDURE [mailSystem: MailSystem],
  InspectCredentials: PROCEDURE [
    mailSystem: MailSystem, status: Status, user, password: STRING],
  LocateMailboxes: PROCEDURE [mailSystem: MailSystem, localMailboxList: Mailbox],
  StageMessage: PROCEDURE [mailSystem: MailSystem,
    receiveBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL] RETURNS [CARDINAL],
    receiveBlockData: UNSPECIFIED],
  DeliverMessage: PROCEDURE [mailSystem: MailSystem, localMailboxList: Mailbox],
  ForwardMessage: PROCEDURE [mailSystem: MailSystem, remoteMailboxList: Mailbox],
  RetrieveMessages: PROCEDURE [mailSystem: MailSystem, localMailbox: Mailbox,
    processMessage: PROCEDURE [MessageInfo],
    sendBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL],
    sendBlockData: UNSPECIFIED]];

-- mail systems
SysMailPrimitives,
SomeMailPrimitives: PROCEDURE RETURNS [mailPrimitives: MailPrimitives];

-- **********************!  Communication System  !***********************

-- communication types
CommunicationSystem: TYPE = POINTER TO CommunicationSystemObject;
CommunicationSystemObject: TYPE = RECORD [dummy: UNSPECIFIED];
Connection: TYPE = POINTER TO ConnectionObject;
ConnectionObject: TYPE = RECORD [dummy: UNSPECIFIED];
Port: TYPE = POINTER TO PortObject;
PortObject: TYPE = RECORD [dummy: UNSPECIFIED];
BytePointer: TYPE = POINTER TO BytePointerObject;
BytePointerObject: TYPE = RECORD [
  address: POINTER, offset: BOOLEAN, count: CARDINAL];
Byte: TYPE = [0..377B];

-- communication primitives
CommunicationPrimitives: TYPE = POINTER TO CommunicationPrimitivesObject;
CommunicationPrimitivesObject: TYPE = RECORD [
  CreateCommunicationSystem: PROCEDURE
    RETURNS [communicationSystem: CommunicationSystem],
  DestroyCommunicationSystem: PROCEDURE [communicationSystem: CommunicationSystem],
  OpenConnection: PROCEDURE [communicationSystem: CommunicationSystem,
    remoteHost: STRING, remoteSocket: LONG CARDINAL, receiveSeconds: CARDINAL]
    RETURNS [connection: Connection],
  CloseConnection: PROCEDURE [
    communicationSystem: CommunicationSystem, connection: Connection],
  ActivatePort: PROCEDURE [
    communicationSystem: CommunicationSystem, localSocket: LONG CARDINAL,
    serviceConnection: PROCEDURE [UNSPECIFIED, Connection, STRING],
    serviceConnectionData: UNSPECIFIED, receiveSeconds: CARDINAL,
    filter: PROCEDURE [STRING,Purpose],
    purpose: Purpose ]
    RETURNS [port: Port],
  DeactivatePort: PROCEDURE [communicationSystem: CommunicationSystem, port: Port],
  SendBytes: PROCEDURE [communicationSystem: CommunicationSystem,
    connection: Connection, bytePointer: BytePointer],
  ReceiveBytes: PROCEDURE [communicationSystem: CommunicationSystem, 
    connection: Connection, bytePointer: BytePointer, settleForLess: BOOLEAN],
  SendByte: PROCEDURE [
    communicationSystem: CommunicationSystem, connection: Connection, byte: Byte],
  ReceiveByte: PROCEDURE [communicationSystem: CommunicationSystem,
    connection: Connection, settleForNone: BOOLEAN]
    RETURNS [byte: Byte, settledForNone: BOOLEAN],
  ProduceDiscontinuity,
  ConsumeDiscontinuity,
  ForceOutput: PROCEDURE [
    communicationSystem: CommunicationSystem,  connection: Connection]];

-- communication system
PupCommunicationPrimitives: PROCEDURE
  RETURNS [communicationPrimitives: CommunicationPrimitives];

-- **********************!  Signals  !***********************

-- error
FTPError: SIGNAL [ftpError: FtpError, message: STRING];

-- Note:  To add a new error:
--   1) Add corresponding message to FTPAccessories.VerbalizeFtpError.
--   2) Modify error categories below as necessary.
--   3) Modify FTPProtocol.SignalToCode and CodeToSignal as necessary.

-- error codes
FtpError: TYPE = {
  -- communication errors
    noSuchHost,
    connectionTimedOut,
    connectionRejected,
    connectionClosed,
    noRouteToNetwork,
    noNameLookupResponse,
  -- credential errors
    credentialsMissing,
    noSuchPrimaryUser,
    noSuchSecondaryUser,
    incorrectPrimaryPassword,
    incorrectSecondaryPassword,
    requestedAccessDenied,
  -- file errors
    illegalFilename,
    noSuchFile,
    fileAlreadyExists,
    fileBusy,
    noRoomForFile,
    fileDataError,
  -- dump errors
    errorBlockInDumpFile,
    unrecognizedDumpFileBlock,
    dumpFileBlockTooLong,
    dumpFileCheckSumInError,
  -- mail errors
    noValidRecipients,
    noSuchMailbox,
  -- client errors
    filePrimitivesNotSpecified,
    mailPrimitivesNotSpecified,
    communicationPrimitivesNotSpecified,
    filesModuleNotLoaded,
    mailModuleNotLoaded,
    noConnectionEstablished,
    connectionAlreadyEstablished,
    connectionNotOpenedForFiles,
    connectionNotOpenedForMail,
    illegalProcedureCallSequence,
    fileGroupDesignatorUnexpected,
    filenameUnexpected,
  -- protocol errors
    protocolVersionMismatch,
    functionNotImplemented,
    inputDiscontinuityUnexpected,
    outputDiscontinuityUnexpected,
    illegalProtocolSequence,
    protocolParameterListMissing,
    illegalProtocolParameterList,
    unrecognizedProtocolParameter,
    missingProtocolParameter,
    duplicateProtocolParameter,
    illegalBooleanParameter,
    illegalFileAttribute,
    illegalFileType,
    unrecognizedProtocolErrorCode,
    noSuchRecipientNumber,
    duplicateMailboxException,
    unrecognizedMailboxExceptionErrorCode,
    missingMessageLength,
    messageLongerThanAdvertised,
    messageShorterThanAdvertised,
  -- internal errors,
    stringTooLong,
    queueInconsistent,
    unexpectedEndOfFile,
  -- unidentified errors
    unidentifiedTransientError,
    unidentifiedPermanentError,
    unidentifiedError,
  -- pseudo error (meaning none)
    ok};

-- error categories
CommunicationError:	TYPE = FtpError[noSuchHost..noNameLookupResponse];
CredentialError:	TYPE = FtpError[credentialsMissing..requestedAccessDenied];
FileError:		TYPE = FtpError[illegalFilename..fileDataError];
DumpError:		TYPE = FtpError[errorBlockInDumpFile..dumpFileCheckSumInError];
MailError:		TYPE = FtpError[noValidRecipients..noSuchMailbox];
ClientError:		TYPE = FtpError[filePrimitivesNotSpecified..filenameUnexpected];
ProtocolError:	TYPE = FtpError[protocolVersionMismatch..messageShorterThanAdvertised];
InternalError:	TYPE = FtpError[stringTooLong..unexpectedEndOfFile];
UnidentifiedError:	TYPE = FtpError[unidentifiedTransientError..unidentifiedError];

-- private error categories
UndefinedFunctionError:		PRIVATE TYPE = FtpError[protocolVersionMismatch..functionNotImplemented];
ProtocolSequenceError:		PRIVATE TYPE = FtpError[inputDiscontinuityUnexpected..illegalProtocolSequence];
IllegalParameterListError:		PRIVATE TYPE = FtpError[protocolParameterListMissing..illegalFileAttribute];

-- **********************!  Common Procedures  !***********************

-- program primitives
FTPInitialize,
FTPFinalize: PROCEDURE;

-- parameter primitives
FTPSetBufferSize: PROCEDURE [pages: CARDINAL];
FTPCatchUnidentifiedErrors: PROCEDURE [setting: BOOLEAN];

-- **********************!  User (Common) Procedures  !***********************

-- program primitives
FTPCreateUser: PROCEDURE [
  filePrimitives: FilePrimitives, communicationPrimitives: CommunicationPrimitives]
  RETURNS [ftpuser: FTPUser];
FTPDestroyUser: PROCEDURE [ftpuser: FTPUser];

-- connection primitives
FTPSetContactSocket: PROCEDURE [
  ftpuser: FTPUser, socket: LONG CARDINAL, purpose: Purpose];
FTPOpenConnection: PROCEDURE [
  ftpuser: FTPUser, host: STRING, purpose: Purpose, remoteInsignia: STRING];
FTPRenewConnection,
FTPCloseConnection: PROCEDURE [ftpuser: FTPUser];

-- trace primitives
FTPEnableTrace: PROCEDURE [ftpuser: FTPUser, writeString: PROCEDURE [STRING]];
FTPDisableTrace: PROCEDURE [ftpuser: FTPUser];

-- access primitive
FTPSetCredentials: PROCEDURE [
  ftpuser: FTPUser, status: Status, user, password: STRING];

-- **********************!  User (Files) Procedures  !***********************

-- file enumeration primitive
FTPEnumerateFiles: PROCEDURE [ftpuser: FTPUser, remoteFiles: STRING, intent: Intent,
  processFile: PROCEDURE [UNSPECIFIED, STRING, VirtualFilename, FileInfo],
  processFileData: UNSPECIFIED];

-- file manipulation primitives
FTPStoreFile,
FTPRetrieveFile: PROCEDURE [
  ftpuser: FTPUser, localFile, remoteFile: STRING, fileType: FileType]
  RETURNS [byteCount: LONG CARDINAL];
FTPTransferFile: PROCEDURE [
  srcFtpuser: FTPUser, srcFile: STRING, dstFtpuser: FTPUser, dstFile: STRING, fileType: FileType,
  transferFile: POINTER TO TransferFile, transferFileData: UNSPECIFIED]
  RETURNS [byteCount: LONG CARDINAL];

  TransferFile: TYPE = PROCEDURE [transferFileData: UNSPECIFIED,
    receiveBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL] RETURNS [CARDINAL],
    receiveBlockData: UNSPECIFIED,
    sendBlock: PROCEDURE [UNSPECIFIED, POINTER, CARDINAL],
    sendBlockData: UNSPECIFIED];

FTPDeleteFile: PROCEDURE [ftpuser: FTPUser, remoteFile: STRING];
FTPRenameFile: PROCEDURE [ftpuser: FTPUser, currentFile, newFile: STRING];

-- filename primitives
FTPSetFilenameDefaults: PROCEDURE [
  ftpuser: FTPUser, status: Status, virtualFilename: VirtualFilename];
FTPNoteFilenameUsed: PROCEDURE [
  ftpuser: FTPUser, absoluteFilename: STRING, virtualFilename: VirtualFilename];

-- **********************!  User (Dump) Procedures  !***********************

FTPInventoryDumpFile: PROCEDURE [
  ftpuser: FTPUser, remoteDumpFile: STRING, intent: DumpFileIntent,
  processFile: PROCEDURE [UNSPECIFIED, STRING, VirtualFilename, FileInfo],
  processFileData: UNSPECIFIED];
FTPBeginDumpFile: PROCEDURE [ftpuser: FTPUser, remoteDumpFile: STRING];
FTPEndDumpFile: PROCEDURE [ftpuser: FTPUser];

-- **********************!  User (Mail) Procedures  !***********************

-- delivery primitives
FTPBeginDeliveryOfMessage: PROCEDURE [ftpuser: FTPUser];
FTPSendRecipientOfMessage: PROCEDURE [
  ftpuser: FTPUser, mailboxName: STRING,
  -- mailboxHostName and dmsName are going away soon
  mailboxHostName: STRING ← NIL, dmsName: STRING ← NIL];
FTPIdentifyNextRejectedRecipient: PROCEDURE [ftpuser: FTPUser, errorMessage: STRING]
  RETURNS [recipientNumber: CARDINAL, recipientError: RecipientError];

  RecipientError: TYPE = {noSuchMailbox, noForwardingProvided,
    unspecifiedTransientError, unspecifiedPermanentError, unspecifiedError};

FTPSendBlockOfMessage: PROCEDURE [
  ftpuser: FTPUser, source: POINTER, byteCount: CARDINAL];
FTPEndDeliveryOfMessage: PROCEDURE [ftpuser: FTPUser];

-- retrieval primitives
FTPBeginRetrievalOfMessages: PROCEDURE [ftpuser: FTPUser, mailboxName: STRING];
FTPIdentifyNextMessage: PROCEDURE [ftpuser: FTPUser, messageInfo: MessageInfo];
FTPRetrieveBlockOfMessage: PROCEDURE [
  ftpuser: FTPUser, destination: POINTER, maxWordCount: CARDINAL]
  RETURNS [actualByteCount: CARDINAL];
FTPEndRetrievalOfMessages: PROCEDURE [ftpuser: FTPUser];

-- **********************!  Server (Common) Procedures  !***********************

FTPCreateListener: PROCEDURE [purpose: Purpose,
  filePrimitives: FilePrimitives,
  mailPrimitives: MailPrimitives,
  communicationPrimitives: CommunicationPrimitives,
  backstopServer: POINTER TO BackstopServer,
  backstopServerData: UNSPECIFIED,
  filter: PROCEDURE[STRING,Purpose] ← RejectNothing]
  RETURNS [ftplistener: FTPListener];
RejectNothing: PROCEDURE [STRING,Purpose];
RejectThisConnection: ERROR [error: STRING];

  Purpose: TYPE = {files, mail, filesAndMail};
  SingularPurpose: TYPE = Purpose[files..mail];
  BackstopServer: TYPE = PROCEDURE [backstopServerData: UNSPECIFIED,
    purpose: SingularPurpose, originOfRequest, localInsignia: STRING, server: PROCEDURE];

FTPDestroyListener: PROCEDURE [ftplistener: FTPListener, abortServers: BOOLEAN];

-- **********************!  Externally Visible Objects  !***********************

-- Note:  The client manipulates the object handles
--   but not the objects themselves.

-- user state information
FTPUser: TYPE = POINTER TO FTPUserObject;
FTPUserObject: PRIVATE TYPE = RECORD [
  filePrimitives: FilePrimitives,
  fileSystem: FileSystem,
  communicationPrimitives: CommunicationPrimitives,
  communicationSystem: CommunicationSystem,
  remoteFtpSocket, remoteMtpSocket: LONG CARDINAL,
  ftper, mtper: FTPer,
  propertyList, primaryPropertyList, secondaryPropertyList: PropertyList,
  purpose: Purpose,
  state: UserState,
  intent: Intent,
  nextBlockType: Byte,
  numberOfRecipients, numberOfValidRecipients: CARDINAL,
  numberOfBytesExpected, numberOfBytesReceived: LONG CARDINAL];

  UserState: PRIVATE TYPE = {unconnected, connected, enumeratingFiles,
    inventoryingDumpFile, dumpFileBeingSent, messageRecipientsBeingSent,
    initialMailboxExceptionsBeingReceived, messageTextBeingSent,
    finalMailboxExceptionsBeingReceived, messageDelivered,
    messageHeaderPending, messageTextPending, mailboxExhausted};

-- listener state information
FTPListener: TYPE = POINTER TO FTPListenerObject;
FTPListenerObject: PRIVATE TYPE = RECORD [
  filePrimitives: FilePrimitives,
  mailPrimitives: MailPrimitives,
  communicationPrimitives: CommunicationPrimitives,
  communicationSystem: CommunicationSystem,
  backstopServer: BackstopServer,
  backstopServerData: UNSPECIFIED,
  ftpCharterObject, mtpCharterObject: CharterObject,
  ftpPort, mtpPort: Port,
  serverQueueObject: QueueObject];

-- **********************!  Externally Invisible Objects  !***********************

-- Note: These objects are declared here because they or their handles
--   appear in the externally visible objects declared above.

-- connection state information
FTPer: PRIVATE TYPE = POINTER TO FTPerObject;
FTPerObject: PRIVATE TYPE = RECORD [
  communicationPrimitives: CommunicationPrimitives,
  communicationSystem: CommunicationSystem,
  connection: Connection,
  totalByteCount: LONG CARDINAL,
  inputString, outputString: STRING,
  tracing: BOOLEAN,
  writeString: PROCEDURE [STRING],
  directionOfLastTrace: TraceDirection];

  TraceDirection: PRIVATE TYPE = {in, out};

-- property list
PropertyList: PRIVATE TYPE = DESCRIPTOR FOR ARRAY Property OF STRING;
PropertyListObject: PRIVATE TYPE = ARRAY Property OF STRING;

  Property: PRIVATE TYPE = {userName, userPassword, connectName, connectPassword,
    directory, serverFilename, device, nameBody, version, type, endOfLineConvention,
    byteSize, size, creationDate, writeDate, readDate, author, userAccount, mailbox,
    sender, length, dateReceived, opened, deleted};
  FileProperty: PRIVATE TYPE = Property[directory..author];

-- server charter
Charter: PRIVATE TYPE = POINTER TO CharterObject;
CharterObject: PRIVATE TYPE = RECORD [
  ftplistener: FTPListener,
  purpose: SingularPurpose];

-- queue and queue element
Queue: PRIVATE TYPE = POINTER TO QueueObject;
QueueObject: PRIVATE TYPE = MONITORED RECORD [
  head, tail: Element,
  elementCount: CARDINAL,
  identifiersCoincide: IdentifiersCoincide,
  elementDequeued, elementUnlocked: CONDITION];

  IdentifiersCoincide: PRIVATE TYPE =
    PROCEDURE [UNSPECIFIED, UNSPECIFIED] RETURNS [BOOLEAN];

Element: PRIVATE TYPE = POINTER TO ElementObject;
ElementObject: PRIVATE TYPE = RECORD [
  previous, next: Element,
  identifier: UNSPECIFIED,
  allocated, locked, exclusive: BOOLEAN];
    
END. -- of FTPDefs