Private Data Stamp: No X:6.5" Y:11.25"
Page Numbers: Yes X: 527 Y: -.5" First Page: 25
Heading:
Mesa Pup Package Functional Specification
EFTP Package
The EFTP Package implements a very simple Pup-based Ethernet File Transfer Protocol. This protocol is currently used to communicate with Press printers in the Parc environment. The package comes in two separate modules that are not included in either FatPup or TinyPup: EFTPSend.bcd and EFTPRecv.bcd. Only one connection per module is supported: if you want more than one active connection in the same direction you will have to make another instance.
Each half should not be called from more than one PROCESS. I doubt if it will recover correctly if you ABORT it. The intention is that it will timeout often enough so that there will not be a need to use ABORT.
EFTPTimeOut: SIGNAL;
Many of the procedure calls may generate the resumable SIGNAL EFTPTimeOut. The timeouts used within the EFTP Package are very simple. The default timeout for both send and receive wakeups is 1 second. Someday, I may get around to implementing an adaptive timeout scheme. The SIGNAL is generated under the following situations:
Open for Sending SIGNALs every 10 retransmissions.
Put SIGNALs every 25 retransmissions.
Finish Sending SIGNALs every 10 retransmissions.
Open for Receiving SIGNALs every 10 ticks.
Get SIGNALs every tick.
EFTPSetSendTimeout: PROCEDURE [ms: CARDINAL, tries: CARDINAL];
EFTPSetRecvTimeout: PROCEDURE [ms: CARDINAL];
EFTPSetSendTimeout is used to change the timeout parameters used in the send side of the EFTP Package. EFTPSetRecvTimeout is used to change the timeout used in the receive side of the EFTP Package. The values of the timeouts are measured in milliseconds.
EFTPAbortCode: TYPE = RECORD [WORD];
eftpOK: EFTPAbortCode = [0]; -- pseudo code
eftpExternalSenderAbort: EFTPAbortCode = [1];
eftpExternalRecieverAbort: EFTPAbortCode = [2];
eftpReceiverBusyAbort: EFTPAbortCode = [3];
eftpOutOfSyncAbort: EFTPAbortCode = [4];
eftpRejected: EFTPAbortCode = [1001]; -- pseudo code
EFTPOpenForSending: PROCEDURE [
to: PupAddress, waitForAck:
BOOLEAN ← TRUE];
EFTPAlreadySending: ERROR;
EFTPTroubleSending: ERROR [e: EFTPAbortCode, s: STRING];
EFTPTimeOut: SIGNAL;
EFTPOpenForSending is used to create an EFTP connection to the remote address to. If there is already an EFTP connection then the ERROR EFTPAlreadySending is generated. If waitForAck is TRUE, EFTPOpenForSending transmits a packet with sequence number 0 and no data, until the packet is acknowledged. This is a way to be reasonably sure that the other end is willing to talk to you if you don’t want to open a file or such until the connection is open. If there is any problem in transmitting the packet, then the ERROR EFTPTroubleSending is generated. The SIGNAL EFTPTimeOut will be generated if the initial packet is not acknowledged soon enough. It may be resumed.
EFTPSendBlock: PROCEDURE [p: POINTER, l: CARDINAL];
EFTPNotSending: ERROR;
EFTPTroubleSending: ERROR [e: EFTPAbortCode, s: STRING];
EFTPTimeOut: SIGNAL;
EFTPSendBlock is used to send a block of data over the open EFTP connection. p is a pointer to the data and l is the length in bytes. If the EFTP connection has not been opened then the ERROR EFTPNotSending is generated. If there is any problem in transmitting the data, then the ERROR EFTPTroubleSending is generated. The SIGNAL EFTPTimeOut may be generated. This SIGNAL may be resumed.
EFTPAbortSending: PROCEDURE [s: STRING];
EFTPAbortSending is used to abort the EFTP connection and to transmit the string s to the destination indicating some reason for aborting the EFTP connection.
EFTPFinishSending: PROCEDURE;
EFTPNotSending: ERROR;
EFTPTimeOut: SIGNAL;
EFTPFinishSending is used to terminate the EFTP connection. If the EFTP connection has not been opened then the ERROR EFTPNotSending is generated. If there is any problem in transmitting the data and closing the connection, then the ERROR EFTPTroubleSending is generated. The SIGNAL EFTPTimeOut may be generated. This SIGNAL may be resumed.
EFTPOpenForReceiving: PROCEDURE [PupAddress] RETURNS [PupAddress];
EFTPAlreadyReceiving: ERROR;
EFTPTimeOut: SIGNAL;
EFTPOpenForReceiving is used to wait for an EFTP connection to be opened from any remote address. If there is already an EFTP connection then the ERROR EFTPAlreadyReceiving is generated. This procedure waits for a packet with sequence number 0, and acknowledges it. When this happens the EFTP connection is open. The SIGNAL EFTPTimeOut may be generated. This SIGNAL may be resumed.
EFTPGetBlock: PROCEDURE [p: POINTER, l: CARDINAL] RETURNS [CARDINAL];
EFTPNotReceiving: ERROR;
EFTPEndReceiving: ERROR;
EFTPTroubleReceiving: ERROR [e: EFTPAbortCode, s: STRING];
EFTPTimeOut: SIGNAL;
EFTPGetBlock is used to receive a block of data over the open EFTP connecction. p is a pointer to the data block and l is the length in bytes. The procedure call returns the actual number of bytes stored into the block. If the EFTP connection has not been opened then the ERROR EFTPNotReceiving is generated. If the EFTP connection is terminated or aborted by the remote end, then the ERROR EFTPEndReceiving is generated. If there is any problem in receiving the data, then the ERROR EFTPTroubleReceiving is generated. The SIGNAL EFTPTimeOut may be generated. This SIGNAL may be resumed.
EFTPAbortReceiving: PROCEDURE [s: STRING];
EFTPAbortReceiving is used to abort the EFTP connection and to transmit the string s to the destination indicating some reason for aborting the EFTP connection.
EFTPFinishReceiving: PROCEDURE;
EFTPNotReceiving: ERROR;
EFTPFinishReceiving is used to terminate the EFTP connection. If the EFTP connection has not been opened then the ERROR EFTPNotReceiving is generated.
Multiple EFTP connections
Since there is no handle passed to the EFTP routines, it is not possible for a particular instance of the code to keep track of more than one connection (in a particular direction) at a time. If you need more than one, you will have to Bind in more instances of EFTPSend or EFTPRecv inot your config. Be sure that you do not use code links on your module that is calling EFTP if you have several instances if it. Also, be careful when using code links on EFTPRecv. It imports EFTPTimeOut from EFTPSend, and if you have several instances of both there is opportunity for confusion.
ByteBlt
Within the Pup BSP implementation module, there is a complication that arises when buffers are not aligned conveniently. In case anybody else ever runs into the same problem, the critical routine has been split out into a separate interface called ByteBltDefs. ByteBlt uses Blt for the easy case, and BitBlt to do the ripple.
ByteBlt: PROCEDURE [to, from: Stream.Block] RETURNS [nBytes: CARDINAL];
StartIndexGreaterThanStopIndexPlusOne: ERROR;
Block: TYPE = RECORD [
blockPointer:
LONG POINTER,
startIndex, stopIndexPlusOne:
CARDINAL];
ByteBlt moves as much as it can, and tells you what that was. Zero is ok. StartIndexGreaterThanStopIndexPlusOne will be generated if either argument is trying to wrap around memory.
ByteBlt will probably not work as desired if the source and destination overlap.
ShortenPointer: PROCEDURE [LONG POINTER] RETURNS [POINTER];
HyperSpaceNotSupported: ERROR;
NilRejected: ERROR;
On an Alto, the LONG POINTER in a Block must be shortened before it can be used. If either of two unreasonable conditions are detected the obvious ERRORs are generated.
Stats Package
The Stats Package may help you to understand what your program is doing. Basically, it just maintains a set of counters that can be printed out when desired. The counters are LONG CARDINALs, and they are indexed by a huge enumerated type. Most of the types are pretty specific to the Pup Package, but there are a clump of spares. The Stats Package is included in FatPup. The interface is StatsDefs.
StatNew: PROCEDURE;
StatStart: PROCEDURE [STRING];
StatPrintCurrent: PROCEDURE;
StatFinish: PROCEDURE;
StatNew should be called before calling MakeImage. It just remembers the current date and time to be used in a header line by StatStart. StatStart resets all the counters, and prints out a header line. StatPrintCurrent prints out the current values of the counters without changing them. StatFinish prints out the current values of the counters and resets them in case you start another test. The printout also includes a few derived numbers, like bits per second sent and received.
StatIncr: PROCEDURE [StatCounterIndex];
StatBump: PROCEDURE [StatCounterIndex, CARDINAL];
StatLog: PROCEDURE [StatCounterIndex, POINTER, CARDINAL];
StatCounterIndex: TYPE = {....};
StatIncr adds one to the specified counter. StatBump adds a specified amount. You will have to look in StatsDefs to find the values of StatCounterIndex. They change every now and then. StatLog adds one to the specified counter, and prints out the specified block of memory. Someday, it may do something more interesting, like send the data someplace for later analysis. The idea is that if an obscure glitch has happened, the data may be useful in tracking it down.
StatReady: PROCEDURE;
StatSince: PROCEDURE;
There is also another set of counters that can be used for specific tests without disturbing the main counters. StatReady resets the secondary counters. StatSince prints out everything that has happened since the last call to StatReady or StatSince, and then resets the secondary counters.
StatsStringToIndex: PROCEDURE [STRING] RETURNS [StatCounterIndex];
StatStringsFull: ERROR;
If you want to add your own counters at runtime, StatsStringToIndex will search the string table, and assign a free slot if it isn’t already there. The answer can then be used as an argument to StatIncr or StatBump. StatStringsFull will be generated if there are no more spare slots. Feel free to use counters that are already there if you prefer.
StatUpdate: PROCEDURE;
StatsGetCounters: PROCEDURE RETURNS [
POINTER TO ARRAY
StatCounterIndex OF LONG CARDINAL];
StatsGetText: PROCEDURE RETURNS [
POINTER TO ARRAY
StatCounterIndex OF STRING];
If you get really desperate and need to wander around in the bits, these routines will give you pointers to the inner secrets. If a string is NIL, that slot is considered to be unused. StatUpdate updates several clock counters. You should call it before looking at any of them.
References


For details of the EFTP protocol: [Maxc]<Pup>EftpSpec.press.

For details on Error Pups: [Maxc]<Pup>Error.press.

For the truth on Pup Names: [Maxc]<Pup>PupName.press.

For general background about Pups: [Maxc]<Pup>PupSpec.press.

You might also want to browse through (the rest of) [Maxc]<Pup>*.press.