ArpaTCP.mesa
Copyright (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.
David Nichols, September 1, 1983 4:20 pm
Taft, January 4, 1984 11:06 am
HGM, March 21, 1984 0:49:04 am PST
Hal Murray May 16, 1985 3:11:54 am PDT
John Larson, April 14, 1986 11:17:31 pm PST
Doug Terry, November 16, 1987 10:23:41 am PST
Weiser, October 19, 1987 7:51:31 pm PDT
Demers, February 2, 1988 12:30:36 pm PST
DIRECTORY
Arpa USING [Address, nullAddress],
IO USING [STREAM];
ArpaTCP: CEDAR DEFINITIONS =
BEGIN
Types
TCPInfo: TYPE ~ RECORD [ -- describes the kind of connection we want.
matchLocalPort: BOOLFALSE, -- true to use LocalPort field, false to assign an unused local port
localPort: Port ← nullPort, -- TCP port
matchForeignAddr: BOOLTRUE, -- true to match ForeignAddress
foreignAddress: Arpa.Address ← Arpa.nullAddress, -- address of remote TCP
matchForeignPort: BOOLTRUE, -- true to match ForeignPort
foreignPort: Port ← nullPort, -- TCP port at remote TCP
active: BOOLTRUE, -- true to initiate connection, false to wait as listener. If true, matchForeignAddr and matchForeignPort must also be true.
timeout: INT ← neverTimeout, -- raise Timeout if data not delivered in this time (in msec)
maxSegmentSize: INT ← 0 -- max bytes we can send in a datagram (If 0, default to maxArpanetSegmentSize when sending to external destinations, ArpaTCPOps.maxTCPDataLength otherwise)
];
maxArpanetSegmentSize: INT = 536;
maxTimeout: INT ~ LAST[INT] / 1000; -- don't make it bigger than this
neverTimeout: INT ~ -1; -- use this to never timeout
DByte: TYPE ~ INT [0..65535]; -- Two byte field.
Port: TYPE ~ DByte;
nullPort: Port ~ 0;
STREAM: TYPE = IO.STREAM;
TCP Interface
Use CreateTCPStream to get an ordinary IO.STREAM. You can read and write on it to receive and send TCP data. Doing a Flush causes a TCP push operation to take place. If you are interested in urgent data, the WaitForUrgentData call will return as soon as TCP knows about some urgent data in the stream, giving the caller the index of the urgent data.
CreateTCPStream: PROC [tcpInfo: TCPInfo] RETURNS [s: STREAM];
Make a new bidirectional stream. May raise Error.
AbortTCPStream: PROC [s: STREAM];
Instead of clean close.
GetTimeout: PROC [s: STREAM] RETURNS [timeout: INT];
Return the data timeout associated with stream.
SetTimeout: PROC [s: STREAM, timeout: INT ← neverTimeout];
Reset the timeout associated with stream.
WaitForListenerOpen: PROC [s: STREAM, timeout: INT ← neverTimeout];
Wait until the listening connection on this socket is open or the timeout expires. No signals.
GetRemoteSocket: PROC [s: STREAM] RETURNS [addr: Arpa.Address, port: Port];
GetLocalSocket: PROC [s: STREAM] RETURNS [addr: Arpa.Address, port: Port];
SendNow: PROC [s: STREAM];
Like IO.Flush[s], except that Flush waits for the packets to be acknowledged and SendNow doesn't.
SetUrgent: PROC [s: STREAM];
The urgent pointer is set to the current index in the output stream.
WaitForUrgentData: PROC [s: STREAM] RETURNS [urgentIndex: INT];
Wait asynchronously for urgent data indication. May raise Error.
Signals
Procedures defined in this interface may raise Error if something goes wrong. On the other hand, if something goes wrong during a generic operation on a TCP stream (e.g., GetChar), IO.Error[$Failure, self] is raised. In that case, if the client is interested in the Reason for the failure, it must call ErrorFromStream[self].
Warning: TCP.Error and IO.Error are sometimes raised with monitor locks held. Do not perform any other operations on the stream until you have unwound the ERROR.
Error: ERROR [reason: Reason];
Reason: TYPE ~ {
localConflict,
unspecifiedRemoteEnd,
neverOpen,
localClose,
localAbort,
remoteClose,
remoteAbort,
transmissionTimeout,
protocolViolation
};
ErrorFromStream: PROC [s: STREAM] RETURNS [reason: Reason];
Returns the Reason for the most recent error reported by IO.Error (not TCP.Error).
Timeout: SIGNAL;
Raised during data transfer operation if no data arrives within the interval specified when the stream was created (even although the other end is responding to our probes). This signal may be resumed to try again.
Timeout can be raised during any stream operation, seemingly in violation of the rule that all generic stream operations raise IO.Error exclusively. However, this is an INFORMATIONAL SIGNAL, meaning that if it is not caught it is automatically resumed. Consequently, no harm results if it is not caught. (In any event, Timeout can be raised only if the client supplied a non-default TCPInfo.Timeout, which presumably only a knowledgable client will do.)
It WAS an INFORMATIONAL SIGNAL, but you can't UNWIND them.
END.