RFC 91
Proposed User-User Protocol
RFC 91: A Proposed User-User Protocol π
Network Working Group π George H. Mealy (Harvard University), dated December 27, 1970. This copy doesn't list a category, and it doesn't say what it obsoletes or updates. π¦
Introduction β¨
okay so there are a bunch of really good reasons (and maybe one or two bad ones π) for making communication over the Network look like just a special case of input/output. at least when it comes to user programming, it's giving "everything is a device" energy π
The Harvard approach to the HOST-HOST protocol and Network Control Program treats each link as a "logical device," which is PDP-10 terminology. Setting up a connection is basically like local device assignment, and communicating over a link uses the standard system input/output UUO's. this is iconic because existing programs can use the Network without any modification, at least if the other machines are also PDP-10's πΈ
BUT this only gets us so far π the idea of a "logical device" doesn't exist on the PDP-10. it does exist on the IBM 360 (I'm talking here at the level of the operating system and user program interface). and without a Network standard that requires fixed representations for integers, reals, and so on (which the author would oppose π), any pair of user processes has to reach a local agreement, and one or both of them has to take on the burden of data conversion where needed. a standard protocol should let those agreements be expressed, and it should include at least the minimum control information that makes those agreements work in practice π§ finally, the IMP-IMP and HOST-HOST protocols don't check whether an action a user process asked for was actually completed by the other processes. this kind of issue has always been treated as something for the USER-USER protocol level to handle π
this proposal only tries to face those three types of issue to a certain extent. here's how the author judges any USER-USER protocol proposal:
- The notion of a (logical) _record_ should be present, and the notion of a _message_ should be suppressed. (To a FORTRAN programmer, whatever is written with one WRITE statement and no accompanying FORMAT is a record. To an OS/360 machine language programmer, PUT writes a record.)
- It should be possible to implement the protocol in HOST systems and/or library routines so that existing user programs can access files anywhere in the Network without program modifications. (At first, at least, this ability has to be limited to HOST systems of the same type.)
- The protocol should be implementable (not necessarily implemented) in any HOST system at the SVC or UUO level. Specific knowledge of the characteristics of the other HOST involved should be unnecessary.
it's worth noting that the above implies some user programs have to be aware of the nature of the other HOST, at least in each case where the second criterion fails π as progress is made on those failing cases (or the author gives up on them), the job of accommodating system differences will shift toward implementation in protocols (the HOST systems) or, by default, into user programs π
honestly, any proposal started today should be suspect about how much it really "solves" ultimate problems. how ambitious to be is totally a matter of taste. for now, the author prefers something that can be used by all of us (so it's worth doing), goes a reasonable distance toward solving our short-range problems, is easy to do, and has hope of staying viable in the long run β¨ below, the author describes the proposal itself, with (hopefully) proper motivational arguments for its pieces. then they sketch the specific implementation Harvard is making for the PDP-10, and describe how they plan to apply it to storing files on other PDP-10's in the Network π¦
User-User Protocol (Proposal) π
okay this part is the actual spec, so pay attention bestie π«Ά the following protocol is meant to apply to the data bits in messages, between the end of the marking bits and the beginning of the padding bits. The present IMP-IMP and HOST-HOST protocols are unaffected by this proposal. π
the general principle is that each segment (not a technical term, fr) of data is preceded by control information that says what its nature and extent are. the basic scheme was evolved from the one used in the SOS buffering system (see the papers in JACM, April 1959, and especially the one by O.R. Mock) π
the author's point of view is that a link is a carrier of information. information is carried in segments of a fixed maximum length called _messages_ [1]. that's an accident from the user's point of view. when a user wants to send a contiguous stream of data, they'll usually segment it in a different way (from the IMP-IMP or HOST-HOST protocol view), and they'll call their segment a _record_. this is entirely analogous to the relationship between a (physical) _block_ and a (logical) record. on the side, file storage systems also use control and status information, so we will too π
at the USER-USER protocol level, all information sent over the link is a sequence of flags followed by (possibly null) data blocks. the general format looks like this:
OPERATION COUNT DATA
the OPERATION field is always there and is four bits long. the COUNT field, when it's present, gives the number of data bytes that follow in the data block. the byte size is set by the last preceding SIZE flag (in most cases). a byte may be between zero and 255 bits long (yes, Virginia, zero is zero even when you have a System/360 π). the OPERATION field and the COUNT field (when present) are together called the flag, and the data bytes (when present) are called the data block. flags followed by data blocks (even when null because of a zero count) are called block flags, and all other flags are called whyte [2] flags π
here's the vibe check on byte size: since the SIZE flag sets the byte size for the blocks that follow, the byte size can be set to whatever is "natural" for the sending or the receiving HOST, depending on local agreement between the sending and receiving processes. it is specifically required that a SIZE flag appear in each message before any block flag (except the ASCII flag). the SIZE flag may be introduced on a default basis by the routine(s) implementing the protocol, and it's intended partly as a way to detect certain classes of error π₯
the flags are as follows:
Whyte Flags:
0 - NUL No operation (consider next flag)
1 - RS Record Separator (end of record)
2 - GS Group Separator (end of group)
3 - FS File Separator (end of file)
4 - ESC Escape to local convention for flags
5 - (reserved for later assignment)
6 - EOM N End of Message (N is total bit count)
7 - SIZE N Byte size is N bits
8 - IGNORE N Ignore following data bits
Block Flags:
9 - SYS N N bytes of data for receiving HOST system
10 - CONTROL N N bytes of control data follow
11 - STATUS N N bytes of status data follow
12 - LABEL N N bytes of identification data follow
13 - KEY N N bytes of key data follow
14 - ASCII N N (8-bit) bytes of ASCII data follow
15 - BLOCK N N bytes of data follow
the author already mentioned the SIZE requirement. not having a SIZE flag in any message that has block flags (except ASCII) is a definite error π¨ EOM is partly another error-checking device, and partly a way to get around the padding conundrum π a user program should never see EOM on input. the user can write an EOM to force transmission. EOM marks the end of the useful information in the message, and it restates the total number of bits in the message (counting from the first bit after the marking through the last bit of the EOM count field), so possible loss of information can be checked. this is a check against errors in the IMP-HOST electrical interface and in the HOST mushyware π€ EOM must appear at the end of each messager, unless ESC has apeared.
ESC is an (hopefully) unused escape hatch for installations and/or applications that want to avoid using more than four bits of the USER-USER protocol on any link. for example, someone might want to use a link as a bit stream and ignore even message boundaries. if anarchists ever achieve local agreement, more power to them! βπΈ
NUL and IGNORE are meant to be space fillers, in case it helps to make the first bit of the next data block land on a convenient address boundary. (an especially helpful HOST interrupt routine might even paste a combination of NUL and IGNORE over the marking bits when receiving a message, in which case their bit count should be passed on to the GET routines to correct the EOM bit count check.) the separator operations introduce the notions of logical record, group, and file. specifically, there is no requirement that a record be contained entirely within one message, or that only a single record be contained in a message! also, there is no requirement that only one file be sent during a connection. for example, a user might want to use a link to send a collection of routines and then do something else with the link π§
so by local agreement, a single routine might be made of several records forming a group, the whole collection might form a file, and the link might stay connected after the FS flag is received π
the interpretation of the various block flags is similarly open to local agreement. the two flags meant to convey pure data are ASCII and BLOCK. as far as the protocol is concerned, the only difference between them is that the byte size is implicit for ASCII (8 bits) and explicit for BLOCK (the count field of the next preceding SIZE flag). beyond that, the semantic content of the block following ASCII is governed by the current standards for ASCII. EBCDIC information may not be transmitted in an ASCII block!! ππ«
CONTROL and STATUS are meant for communicating control information between user processes, and how their accompanying data blocks are interpreted is up to local agreement. generally, CONTROL means "try to do the following," and STATUS means "but I feel this way, doctor." π a CONTROL flag will prompt a returned STATUS flag, sooner or later, or never. LABEL is for identifying the following unit(s) of data, at the file or group level. again, the specific interpretation is up to local agreement. KEY is meant to mimic the notion of an address or key. this works at the record, data item, or even physical storage block level. for anyone who knows the PDP-10 system and/or OS/360, here are some parallels for guidance π
USER-USER protocol OS/360 PDP-10
__________________ ______ ______
CONTROL OPEN OPEN
CLOSE CLOSE
to be continued... part 2 is coming, so stay tuned π¦π
Okay so, this table is basically a cheat sheet mapping DSCB stuff to the USETI/USETO world, and those ? marks mean there's no perfect match, bestie π
LABEL DSCB File retrieval information
KEY KEY USETI/USETO argument
CONTROL READ IN/INPUT
WRITE OUT/OUTPUT
ALLOCATE ? ENTER
OPEN ? LOOKUP
STATUS ? GETSTS
The ? notations mean there isn't a very direct parallel π But here's the tea: the OS/360 GET and PUT have direct parallels in any version of the USER-USER protocol that has the idea of a record πΌ Our version is gonna bring that notion in for ALL PDP-10 input/output, whether it's disc, tape, or IMP communication. It's giving consistency, honestly π«Ά
If I knew the MULTICS terminology, I could make these parallels way more precise π§ My terms come from systems with explicit input/output commands, BUT I really want to stress that this whole setup is meant to handle control and data communication in general. MULTICS is wild because the old line between external and internal storage is blurred from the user's point of view, and I'd love the USER-USER protocol to blur it too β¨ I'm only offering SYS with slight trepidation, ngl π The big idea is that you should be able to talk directly to a foreign HOST instead of going through a foreign user process as the middleman. SYS is like a UUO or SVC, except it's for the foreign HOST to consume rather than mine π¦
From the HOST's side, the implementation problem is setting up a process context record that isn't connected to any local user process. And that's super tied up with our current LOGON conundrum π On the PDP-10, users are basically identified with local teletype lines, and a link is NOT one of those! So you need some subterfuge just to let a foreign user log on π OS/360 is just as perverse (actually more) in its own special way πΈ
Logging a foreign process onto my local system isn't a simple thing, except maybe on MULTICS, of having some special (!!) user job hanging around to handle it π When and if anything else is possible, the HOST has to provide a system instruction (a UUO or SVC or whatever) that gives the info needed to establish a process that's independent in every sense from the process that made the request. Otherwise the self-protection mechanisms that are reasonable for any system will make us all way more interdependent than we want to be π€ So every system needs a UUO/SVC that does the right thing, basically ATTACH, but forget me π If that's true, then LOGON over the Network is basically the same as a foreign UUO/SVC being issued by another node in the Network. I don't see a reasonable way around this π© And if that's the case, then SYS N is the flag to use to carry the required data. And if THAT'S true, then it's only reasonable to let SYS carry a request for ANY OS instruction at the user program-operating system interface level!! Main character energy π
The practical implementation questions are a whole other thing π On the PDP-10, I can pretty well see how to turn a SYS into either a LOGON request to run a monitor command, or a UUO (would that they were the same π), depending on what the case calls for. OS/360 is more sophisticated, unfortunately π₯² MULTICS might be able to pull it off. Nevertheless, I hope it's clear that what we WANT to do, which is what the protocol should reflect, is a totally different question from how it's gonna get done on a specific HOST system π What we want is pretty independent of the system we're dealing with, as far as the protocol goes. And we should NOT skip putting general notions into the protocol just because we're unsure how they'll have to be translated into particular implementation practice π«Ά
A PDP-10 IMPLEMENTATION β¨
Okay so, the following can be implemented either as a set of user routines OR embedded in the monitor as UUO's (our first implementation will be the former π§), but the latter version is what we'll use for describing things. The UUO's would be:
PUTF CH, E Put flag
PUTD CH, E Put data
PUT CH, E Put record
GETFD CH, E Get flag or data
GET CH, E Get record
Here, "CH" is the logical channel number π¦ You use the customary OPEN or INIT UUO to open the channel. Standard format user buffers get assigned. BUT the ring and buffer headers are gonna be used in a nonstandard way, so data mode 12 gets assigned for use with Network buffering, and file status bit 31 has to be on for input π (Any of the devices DSK, DTA, MTA, or IMP can be used in this mode, so no drama there π)
In the Harvard NCP and HOST-HOST protocol implementation, user buffers DON'T correspond directly to messages π On output, each user buffer gets formatted into a message. On input, a message might become one or two user buffer loads (128 word buffers are used so we get the most out of the disk service routines π).
PUTF UUO
This UUO places a flag into the output buffer π The effective address is the location of a word:
XWD operation, count
For block flags, the count gets ignored, since it's computed from the number of bytes actually placed in the buffer before the next use of PUTF. PUTF and PUTD insert EOM flags automatically as each buffer fills up. And if data bytes are currently being placed in the buffer by PUTD, it'll also insert an EOM flag after computing the count for the previous block flag in the buffer, then place a new block flag of the same type at the beginning of the next buffer, after inserting a SIZE flag that states the current byte size. Very organized, very iconic π
PUTD UUO
This UUO places data into the output buffer πΈ The effective address is the location of the data byte (if the byte size is less than 36), or the location of the next 36 bit word of data to be placed in the buffer. In the first case, the byte is assumed to be in the low order part of the word. In the second case, the data word holding the final bits of the byte keeps them in the high order part of the word, and the next data byte starts a new word in PDP-10 storage π§ So for a byte size of 64, you'd use two entries to PUTD per byte transmitted: the first with 36 bits and the second with 28 bits, left-justified. This strategy gets the most out of the PDP-10 byte handling instructions, which is honestly so smart π€β¨
PUT UUO
This UUO places a whole logical record in the output buffer(s) πΌ The effective address is that of a word:
IOWD count, location
You need to have used a PUTF UUO to output the proper SIZE flag first π After that, each use of PUT outputs a BLOCK flag, [3] simulates a bunch of calls to PUTD using the IOWD to find the location and size of the user data area, and then outputs an RS flag to indicate the end of the record. Main character energy, no notes π
For byte sizes less than 36 bits, PUT uses the ILDB instruction to pick up the bytes that PUTD will output. So the standard PDP-10 byte handling format is used, and the count part of the IOWD is the total byte count, NOT the word count π
The above UUO'S have both an error return and a normal return π¦
GETFD UUO
The calling sequence for this UUO is:
GETFD CH, E
error return
whyte flag return
block flag return
data return
The effective address is the location where the flag or data will be returned π The flag comes back in the same format as for PUTF, and the data comes back in the same format as for PUTD. Certain flags (NUL, IGNORE, and EOM) get handled entirely within the UUO and won't be reported to the user, bestie π«Ά SYS should eventually be handled this way too, but at first it'll be handled by the user π₯²
GET UUO
The calling sequence for this UUO is:
GET CH, E
error return
end of file return
end of group return
normal return
GET transmits the next logical record to the user, using GETFD together with an IOWD in the same format as for PUT π If the IOWD count runs out before the end of the record, the rest of the record gets skipped π Either way, the updated IOWD gets returned at the effective address of the UUO, so the user knows how much data was transmitted or skipped. Iconic, honestly π₯
PDP-10 FILE TRANSMISSION: β¨
Okay bestie, picture this π₯οΈ I've got a link hooked up to another PDP-10, and there's a user process over there just listening. So if I want that process to send me a file, here's the flag sequence that might get transmitted. The UUOs I run are in the left margin, the flags are indented, and the commentary next to each one says what kind of data block is moving. It's giving organized chaos π
PUT F
CONTROL Data with OPEN parameters, requesting OPEN
LABEL File identification data for LOOKUP
EOM Forces message to be transmitted
GETFD
STATUS Status returned by OPEN
SIZE Byte size to be used
LABEL File retrieval information
PUTF
CONTROL Data requesting INPUT from file
EOM Forces request to be transmitted
GETFD
STATUS Status bits returned by INPUT
GET Logical record (one file buffer load)
(loop back to second PUTF, above, for other records)
Finally, the status info that comes back from the second GETF says end of file, and then the sequence wraps up with a CLOSE π
PUTF
CONTROL Data requesting a CLOSE
EOM Forces transmission
GETFD
STATUS Status bits returned by CLOSE
If I'm the one sending a file instead, the main loop looks like this π¦
PUTF
CONTROL Data requesting OUTPUT
PUT Logical record (one file buffer load)
PUTF
EOM Forces transmission
GETFD
STATUS Status bits returned by OUTPUT
Something to notice: both the record and the flag transmission UUOs are doing work here π Also, the EOM flag is what forces a message out when the link switches between input and output. PUT and GET UUOs are clearly required above for sending the CONTROL and LABEL data, but I left them out so things stay clean.
For this application, the handshaking on CONTROL and STATUS flags is mandatory π«Ά The protocol could send a whole file without any handshaking, but that's an all or nothing situation. One error and you'd have to start over from scratch, assuming the receiving process didn't end up in a complete tangle π
BRIEF DISCUSSION: πΈ
The PDP-10 space needed to implement all of this is about 400 instructions, split evenly between the input side and the output side. Experimental coding has already confirmed the basic strategy is feasible, especially alongside experience using the SOS buffering system π§
The protocol doesn't really touch LOGON protocol, except indirectly. My belief is that it can fit inside this framework, but I haven't actually tested that theory yet π Like I said earlier, I'd be tempted to handle it with the SYS flag, since SYS data gets interpreted directly by the system. In our setup, we'd use the RUN UUO to run the LOGON CUSP, which would then handshake using ASCII data over the link. If that works, we might be able to skip dedicated sockets and the whole reconnection morass πβ¨
There's one more thing that needs some thought: how to handle the interrupt on link facility. Should it have any direct relation to the GET/PUT UUOs, or should it be handled on the side? My instinct is to treat it qua interrupt of the user process, totally separate from data transmission over the link. Some of our current PDP-10 monitor work would actually make it pretty easy to build as a true interrupt π₯
ENDNOTES* π
- A message is that string of bits between any two HOST-HOST headers.
- In memory of an attractive, but nonspelling, SDC secretary who could not distinguish between black and white, at least during 1957 and in manuscript form. π
- PUTF may be used to ouput the block flag, if a different from BLOCK is required.
[ This RFC was put into machine readable form for entry ] [ into the online RFC archives by Colin Barrett 9/97 ]
π¦ where this page comes from
- ietf: rfc91 1970-12
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms