RFC 55
Prototypical implementation of the NCP
A Prototypical Implementation of the NCP π
Okay bestie, so this is RFC 55, published 19 June 1970 by J. Newkirk and M. Kraley of Harvard, and J. Postel and S. Crocker of UCLA, all from the Network Working Group π§. The header doesn't list anything it obsoletes or updates, and it doesn't give a category or status. It's a prototype write-up, so it's basically "here's how we'd build an NCP" π
Intro
Okay so, while the team was trying to write the formal protocol spec, they also tried to make a prototype NCP in an Algol-like language π After some weeks of intense effort, they dropped it because the code was getting unreadable π They still felt like they needed to show how an NCP could be implemented, since that would help figure out problems when you try to fit the formal specs into a real existing system π«Ά So this doc is their attempt to describe, in plain prose, what an NCP could look like β¨
Obviously this kind of project has limits π They don't, and can't, know every quirk of every system that has to run an NCP, so they had to make some assumptions about the environment, system calls, and stuff like that. They tried to stay as general as possible, but tons of sites are gonna think about the NCP totally differently π Explaining their concepts and mechanisms to people who see things in completely different ways is super hard. Still, coding this for their fictional machine helped a lot, since loads of unexpected problems popped up during coding π₯ They're hoping that sharing this doc can help people dodge similar problems in their own setups πΈ
Also, there is absolutely no requirement to build anything in this doc π
The only strict rules an NCP must follow are in NWG/RFC#54. This description is just an example, not a model π¦
Here's the roadmap β First they describe the environment they're assuming and come up with a set of system calls. Then they go over the NCP's overall architecture and the tables it uses to store info. After that come narratives of network operations π§ Next there's a state diagram, which is a neat way to picture the cause-and-effect order of events π Last, they go through how each kind of network event gets processed in detail. Those events are either system calls or incoming network messages π
II. Environment β¨
Okay so the host is assumed to have a time-sharing operating system, where the CPU gets shared between processes π
Each process gets tagged with a user number π More than one process can have the same user number. If they do, they're supposed to cooperate when it comes to using the network π«Ά
Each process has its own set of ports π These ports are used for input to or output from the process, and that input or output can go to or come from files, devices, or other processes π¦
A process doesn't get put to sleep (blocked or dismissed) when it tries to LISTEN or CONNECT π Instead, it gets informed when the action is complete π₯ Of course, a process can choose to dismiss itself so it only wakes up on some external event π
To do anything on the network, a process attaches a local socket to one of its ports π§ Sockets are identified by user number, host, and AEN. A socket counts as local to a process when the user numbers match and they're on the same host π That means a process only needs to specify an AEN when it's talking about a local socket β¨
Every port has a status. That status gets changed by system calls and by stuff happening outside the process, like a 'close connection' command from a foreign host πΈ The process can check a port's status at any time, using the STATUS system call π
We assume there's a one-to-one correspondence between ports and sockets π
IV. The NCP - Gross Structure β¨
Okay so, bestie, we see the NCP as having five component programs, several associative tables, and some queues and buffers π
The Component Programs (see Fig. 4.1) π§
1. The Input Handler
This is an interrupt-driven routine. It starts Imp-to-Host transmission into a resident buffer, and then it wakes up the input interpreter once transmission is complete π₯
2. The Output Handler
This is an interrupt-driven output routine. It starts Host-to-Imp transmission out of a resident buffer, and then it wakes up the output scheduler once transmission is complete π
3. The Input Interpreter
This is the program that decides whether the input is a regular message meant for a user, a network control message, an Imp-to Host message, or an error π For each class of message, it calls a subroutine to handle the right action π
4. The Output Scheduler
Three classes of messages get sent to the Imp, and they are:
(a) Host-to-Imp messages (b) Control messages (c) Regular messages
We believe a priority should be set among these classes πΈ The priority we suggest is the order listed above. The output scheduler picks the highest priority message and passes it along to the output handler π¦
Host-to-Imp messages are processed first come, first served π Control messages are processed one host at a time, with each host getting its turn π There is a control message queue for each foreign host. When a particular host is scheduled for output, as many control commands for that host as will fit get concatenated into one single message π«Ά Regular messages are processed in groups by host and link, with each unique combination taking its turn β¨
5. The System Call Interpreter
This is the program that interprets requests from the user π Each system call has its own routine that takes the appropriate action π
The two interesting components are the input interpreter and the system call interpreter, and honestly they're kind of twins π They're similar because the input interpreter services foreign requests, and the system call interpreter services local requests π₯Ή
The diagram in Figure 4.1 is our idea of the Network Control Program π Squishy amoeba-like objects stand for component programs, cylinders stand for queues, and arrows stand for data paths π«§ In this simplified diagram, tables are not shown.
["Amoeba-like" objects in original hand drawing are now firm rectangular boxes: Ed.]
The abbreviated labels in the figure mean the following:
HIQ - Host-to-Imp Queue
OCCQ - Output Control Command Queue
DQ - Data Queue
IHBUF - Input Handler Buffer
OHBUF - Output Handler Buffer
____________
| USER | STRUCTURE OF THE NETWORK CONTROL PROGRAM
|____________|
^ | Fig. 4.1
_____|______V____
| |
| System |
| Call |
| Interpreter |
|_________________| _____________
^ | | | |
| | | +---------------| Input |
| | | | +-----| Interpreter |
| | | | | | |
| V V V V -------------
|======| |=========| |=======| | ^
| D Q | | O C C Q | | H I Q | | |
|======| |=========| |=======| | |
| ^ | | | |
| | | | | |
| +--------)----------)---------+ |
| | | |
+-------+ | +------+ |
__V___V___V__ |
| | |
| Output | |
| Scheduler | |
|_____________| |
| |
V |
(===========) (===========)
( O H B U F ) ( I H B U F )
(===========) (===========)
| ^
______V______ ______|______
| | | |
| Output | | Input |
| Handler | | Handler |
| | | |
------------- -------------
| ^
| |
+----------+ +-----------+
| |
____V____|____
| |
| I M P |
|______________|
V. Tables in the NCP π
We picture the bulk of the NCP's data base living in associative tables ποΈ By "associative," we mean there's some lookup routine that gets handed a key, and then it either returns successfully with a pointer to the matching entry, or it fails if no entry matches the key π The major tables are as follows:
1. The Rendezvous Table
This table holds the attributes of a connection π« The table is accessed by the local socket, but other tables may have pointers to existing entries π
The components of an entry are:
(a) Local Socket (b) Foreign Socket (c) Link (d) Connection State (e) Flow State (f) Data Queue (g) Call Queue (h) Port Pointer (i) Their Buffer Size (only needed on the send side) (j) Error State
An entry gets created when either a CONNECT or a LISTEN system call is executed, or when a request for connection is received π¦ Lots of fields stay unused until after the connection is established π€
2. The Input Link Table
The input interpreter uses the concatenation of the foreign host and link as a key into the input table π This table gets used when processing a user-destined message on an incoming link, and it does that by providing a pointer into the rendezvous table πΈ
3. The Output Link Table
The input interpreter uses the output link table to access the flow state as RFNM's return from transmitted messages π¬ The output link table is keyed by host and link, and it provides a pointer into the rendezvous table π
4. The Port Table
The system call interpreter uses the concatenation of the process identification and the port identification as a key, so it can get a pointer into the rendezvous table π§
5. The Output Control Command Table
The system call interpreter and the input interpreter both use this table to make entries in the right output control command queues π«Ά Commands get queued in separate table entries that match foreign hosts π Before output, the contents of the queue get concatenated into one large control message π The components of an entry are:
(a) Host (b) Output Control Command Queue
6. The Output Request Queue
This queue has an entry for each connection that has data needing transmission to the net β¨ There's only one entry per connection. It gets deleted when the last packet of data is transmitted, and it gets entered whenever a user makes a system request for data transmission π
The entry gets re-inserted if transmission isn't completed (message too long) or if it's prevented by the flow control mechanism π The only component of an entry is a local socket π
7. The Host Live Table
This is a simple table that lists the hosts which are alive π It gets checked before establishing a connection and before sending any data, just to make sure the destination host actually exists π₯ At present, the protocol does not define the procedure to be followed for the Host up/Host down conditions. See NWG/RFC#57 π¦
8. The Link Assignment Table
Link numbers get assigned by the receiver πΈ This table records which links are free and can, therefore, be assigned π
VI. Informal Description of Network Operations β¨
okay so this section is basically the story of a connection's life π¦ we're gonna walk through the three big phases of network usage: opening, flow control, and closing. let's go bestie π
A. Opening
okay so to set up a connection for data, you need a pair of RFCs, no cap π an RTS has to go from the receive-side to the send-side, and the send-side has to issue an STR back to the receive-side. the receive-side's RTS also has to name a link number π these RFCs (RFC is the umbrella term for RTS and STR) can show up in any time sequence, honestly it's giving chaos but in a good way β¨ there also has to be a spot for queuing pending calls (aka RFCs the user program hasn't dealt with yet). so when a user is done with a connection, they can check the next pending call from another process and either accept or refuse it π«Ά
the tea is that the user might never bother checking their pending calls π so those calls just sit there taking up queue space in the NCP. we'll talk about some fixes for this later, promise π§
using the prototype system calls from earlier, we can picture at least four different timelines that end with a successfully opened connection π
- the user issues a
LISTEN, which basically means "i'm down to chat with anyone who sends me anRFC." when one comes in, the user gets notified. then they decide whether they want to connect to this socket and issue either anACCEPTor aCLOSEdepending on that choice. aCLOSEhere "refuses" the connection (more on that under "Closing" π). anACCEPTmeans yes, they're willing to connect, anRFCgets issued, and the connection becomes fully opened π - when the NCP handles a user's
LISTENrequest, it finds that a pending call already exists for that local socket. the user gets notified right away and canACCEPTorCLOSE, same as before π - the user issues a
CONNECT, naming a specific foreign socket they'd like to reach. anRFCgets issued. if the foreign process accepts, it replies with anRFC. once that acknowledgingRFCarrives, the connection is opened π - when the NCP gets a
CONNECT, it might discover that a pending call already exists from that specified foreign socket to this local socket. then an acknowledgingRFCis issued and the connection is opened β
no matter which of these happens, the user is notified when the connection opens π BUT data flow can't start until buffer space gets allocated and an ALL command is transmitted. so close, but not yet π₯Ί
any of these connection scenarios can get interrupted if a CLS comes in, which we'll cover under "Closing" π
1. Pending Call Queues
some form of queuing for pending RFCs is essential, periodt π
the easiest way to see why is to look at a typical LISTEN-CONNECT sequence. one side issues a LISTEN and the other side issues a CONNECT. if the LISTEN happens before the RFC from the remote CONNECT shows up, everything is fine β¨ but the net is asynchronous, so we can never guarantee that order. if calls aren't queued, and the RFC arrives before the LISTEN is issued, it gets refused. if it arrives later, it gets accepted. so yeah, it's a super ambiguous situation π
unless you have infinite queue space (which, same), it's desirable to have some way to purge old RFCs that the user never got around to examining π§Ή an obvious but informal approach is to note the time each RFC enters the queue, then periodically refuse every RFC that has exceeded some arbitrary time limit. another idea, which should probably be part of any scheme, is for the NCP to send a CLS on all outstanding connections or pending calls when a user logs out or blows up π
the scheme in this description might seem non-intuitive at first blush π but we think it's more realistic than other proposals, not gonna lie. basically, when a CONNECT is issued, the NCP assumes this socket wants to talk to the specified foreign socket and only that socket. so it purges every non-matching RFC from the pending call queue by sending back CLSs π«Ά similarly, when the connection is in the RFC-SEND state (a CONNECT has been issued), all non-matching RFCs get refused. if a LISTEN-ACCEPT or LISTEN-CLOSE sequence runs, the rest of the pending calls stay in the queue, since the user might want to accept those requests later π¦
yes, this method might look arbitrary and/or unnecessarily restrictive. but we haven't come up with a scenario it would block, assuming we're dealing with a competent programmer (someone who is wary of race conditions and the asynchronous nature of the net) π of course, whatever scheme a particular site picks is highly implementation dependent πΈ we do suggest that some provision for queuing RFCs be made for a period at least on the order of magnitude that they're retained in the CONNECT-clear scheme mentioned above β¨
B. Flow Control
meaningful data can only flow on a connection when it's fully opened (meaning two RFCs have been exchanged and closing hasn't started) π we assume the NCPs have a buffer for incoming data, and that there's some meaningful quantity they can advertise (per connection) saying what size message they can handle π we also assume the sending side regulates its transmission according to those advertisements π
when a connection opens, a cell called Their Size gets set to zero π§ the receive-side decides how much space it can allocate and sends an ALL message specifying that space. the send-side increments Their Size by the allocated space, and then it can send messages with length less than or equal to Their Size. when messages get transmitted, the message length is subtracted from Their Size π when the receive-side allocates more buffer space (for example, when a user takes a message and frees up some system buffer space), the number of bits released gets sent to the send-side in an ALL message π«Ά
so Their Size is never allowed to go negative, and no transmission can happen when Their Size equals zero π
notice that the lengths in ALL messages are increments, not the absolute size of the receiving buffer π
this is necessitated by the full duplex nature of the flow control protocol π¦ the length field of the ALL message can be 32 bits long (note: it's an unsigned integer), which gives you essentially an infinite "bit sink" if that's ever desired πβ¨
C. Closing
just like two RFCs are required to open a connection, two CLSs are required to close one π closing happens under different circumstances and serves several purposes. to make the race condition analysis simpler, we split it into four cases: aborting, refusing, termination by receiver, and termination by sender πΈ
a user "aborts" a connection when they issue a CONNECT and then a CLOSE before the CONNECT gets acknowledged π usually a user aborts after waiting a super long time for the acknowledgment. their system might also abort for them if they blow up π
a user "refuses" a connection when they issue a LISTEN, get notified about a prospective caller, and then issue a CLOSE π
ββοΈ any requests to connect to a socket that's expecting a call from a particular socket are also refused π«Ά
after a connection is established, either side can terminate π¦ the required sequence of events suggests that CLOSE attempts from the receive-side should be treated as "requests," which the send-side always honors as soon as possible π any data that hasn't been passed to the user yet, or that's still traveling over the network, gets discarded ποΈ CLOSE requests from the send-side are honored as soon as all data transmission is complete β¨
1. Aborting
we can tell apart three cases here π
- a) the simplest case: we send an
RFC, then later aCLS. the other side responds with aCLS, and the connection attempt ends π - b) the foreign process might accept the connection at the same time the local process aborts it. in this case, the foreign process will think the local process is terminating an open connection π³
- c) the foreign process might refuse the connection at the same time the local process aborts it. in this case, the foreign process will think the local process is acknowledging its refusal π
2. Refusing
after an RFC is received, the local host can respond with an RFC or a CLS, or it can fail to respond at all π§ (the local host may have already sent its own RFC, etc.) if the local host sends a CLS, it's said to be "refusing" the connection request π
we require that CLS commands get exchanged to close a connection, so the local host has to keep the rendezvous table entry until an acknowledging CLS comes back π
3. Terminating by the Sender
when the user on the send side issues a CLOSE system call, their NCP must accept it immediately π but it may not send out a CLS command until all the data in the local buffers has been passed to the foreign host π«Ά so it's necessary to test for both buffer-empty and RFNM-received before sending the CLS command π as usual, the CLS has to be acknowledged before the entry can be deleted π
4. Terminating by the Receiver
when the user on the receive side issues a CLOSE system call, their NCP accepts it and sends the CLS command immediately β data might still arrive though, and that data should be discarded ποΈ the send side, upon receiving the CLS, should immediately stop the data flow π
VII. Connection Status π
okay so this part is literally my favorite, bestie π¦ an excellent way to describe how a connection gets set up and torn down is a state diagram! π we pretend every socket has its own little state machine, and at any moment that machine can be in one of ten possible states. πΈ in each state, certain network events push the connection into a new state, some events just get ignored π, and some are straight up errors π. a transition can also make the local NCP do something, so it's not just vibes, it's actions too β¨
Figure 7.1 is the whole state machine. the boxes are the states (ed changed them from circles to boxes, iykyk π§), and the arrows are the legal transitions between them. each arrow label is the event that caused it. ngl the labels are a little tricky: CLOSE is a system call, but CLS is a control command, so don't mix them up π«Ά phrases after slashes tell you what should be done while you're traveling that arrow. the arrow labeled [E]RFC (between states 0 and 1) means that whenever a connection goes into the CLOSED state, the pending call queue for that connection gets checked. (the original had that "E" backwards, and ed fixed it, so it's [E]RFC now π)
if there are any pending calls in the queue, the connection moves to PENDING. and if an RFC shows up for a socket in the CLOSED state, it takes the same path over to PENDING too π the events and what they trigger are covered in sections VIII and IX, so stay tuned, bestie π
Here are the ten states, the main character lineup π
- (0) CLOSED π
The local socket isn't attached to any port, and no user has asked for a connection with it. (The table entry doesn't exist at all.)
- (1) PENDING CALL β
The socket isn't attached to any port, but one or more connection requests have come in. A LISTEN system call gets satisfied right away by the first entry in the pending call queue that matches a request. Every other pending call gets deleted π
- (2) LISTENING π¦
The socket is attached to a port, and we're waiting for a user to request a connection with it. π«Ά
- (3) RFC-RCVD π₯
We're listening and an RFC came in. The local user has been told about the pending call, and they have to answer with either a CLOSE or an ACCEPT. no other options, bestie π
- (4) ABORT π
We told the user their LISTEN got satisfied, but they haven't responded yet. If the foreign user aborts the connection during this time by sending a CLS, we send a CLS back to acknowledge the abort, and we mark it with this state. Once the user accepts or refuses the call, we can let them know the connection got terminated early π₯
- (5) RFC-SENT π
this state gets entered when:
- a) the local user has attached this socket to a port by issuing a
CONNECT, - b) an RFC has been sent, and
- c) no reply has come back yet.
when the user issues a CONNECT, the pending call queue gets searched π
if there's no matching RFC in the queue, the queue gets deleted and we enter this state. as new RFCs arrive, they get compared with our user's request. if they don't match, the RFC is immediately refused π ββοΈ if the RFC does match, it finishes the initialization process, and the connection enters the OPEN state. slay π
- (6) OPEN πΈ
RFCs have been exchanged, and the connection is securely established β¨ transmission can start after we receive an ALL command from the receive side, and then it proceeds subject to flow control. π
- (7) CLS-WAIT π§
after the local user executes a CLOSE and we've issued a CLS, we have to wait for an acknowledging CLS before the connection can be fully closed. if that appropriate CLS hasn't already arrived, this state gets entered π
- (8) DATA-WAIT π
if we're on the send side and the local user runs a CLOSE system call, we can't issue a CLS if our data buffer isn't empty, or if an RFNM for the last data message is still outstanding. so the connection enters this state to wait for those conditions to be met. once the output is completed and acknowledged, a CLS may be issued, and the connection enters the CLS-WAIT state to wait for the acknowledging CLS. π«Ά
and if a CLS shows up while we're in DATA-WAIT, we clear our buffer (the CLS came from a receive socket, which means it's no longer interested in our data) and enter the RFNM-WAIT state to wait for the network to clear π
- (9) RFNM-WAIT π
if we're on the send side and a CLS command arrives, we can't issue an acknowledging CLS until we've received the RFNM for our last data message. we enter this state to wait for that RFNM, and we stop all further data transmission. when the RFNM comes in, a CLS may then be issued, and the connection gets closed π
Figure 7.1 below is the full diagram, so you can see every one of these paths together π
______________
| | CLOSE
CONN/ | CLOSED |<---------------------------+
send RFC | (0) | LISTEN |
+----------------| |-----------------------+ |
| |______________| | |
| | ^ | |
| [E]RFC | | CLS/send CLS | |
| ___V____|____ ___V____|____
| non-matching | | | |
| CONN/send RFC | PENDING | LISTEN RFC | LISTENING |
| +-------------| (1) |----------+ +----| (2) |
| | |_____________| | | |_____________|
| | matching | | |
___V___V_____ CONN/send RFC| __V___V______
| | | ACCEPT/ | | CLS/
| RFC-SENT | RFC | send RFC | RFC-RECD | send CLS
| (5) |----------+ | +----------| (3) |---------+
|_____________| | | | |_____________| |
| | | | | | |
| | ___V___V___V___ SND&CLOSE | ____________ |
| | RCV&CLS/ | |-----------)->| | |
| | send CLS | OPEN | SND&CLS | | DATA-WAIT | |
| | +---------| (6) |--------+ | | (8) | |
| | | |_______________| | | |____________| |
| | | RCV&CLOSE/ | | | | |
| | | send CLS | | | | |
| | | | | | | CLS |
| | | ______V______ | | | |
| | | CLOSE/ | |CLOSE/ | | | |
| | | send CLS| CLS-WAIT |send CLS | | | |
| +---)--------->| (8) |<--------)--+ | |
| | |_____________| | | |
| | | ___V______V_ ______V___
| | | | | | |
| | | | RFNM-WAIT | | ABORT |
| | CLS | | (9) | | (4) |
| | | |____________| |__________|
| | | | |
| | ______V_______ RFNM/ | |
| | | | send CLS | |
| CLS/ +--------->| CLOSED |<----------+ |
| send CLS | (0) | ACCEPT|CLOSE |
+----------------->| |<----------------------------+
|______________|
Figure 7.1
Connection State Diagram
VIII. Algorithms for the Input Interpreter β¨
Okay bestie, this is where the NCP decides what to do when a network command slides into its DMs π. CS is just Connection State, fr. And heads up: CLOSE is the system call the local user runs, while CLS is the network command. Don't mix them up π
NOP
Discard. ποΈ
RFC (RTS or STR)
Okay so when an RFC shows up:
- If no entry exists, create one with
status = PENDING CALL, and queue the message. - If
CS = LISTENING, then queue the entry, enter theRFC-RCVDstate, and inform the user of the request. π¬ - If
CS = RFC-SENTbut the new RFC does not match the request, refuse the RFC. π ββοΈ - In all other cases, check the RFC for a match. If none exists, queue the RFC. If the RFC matches, then if:
CS = RFC-SENT, we enter theOPENstate. πCS = CLOSE-WAIT, the RFC is ignored.- otherwise, the request is illegal in all states which indicate it has already been received (these states are 1,3,4,6,8,9). π
- In any case, if processing the RFC causes an overflow condition (resources are exhausted), refuse the connection (send a
CLS). π
CLS
The pending call queue gets searched first. If the CLS doesn't match the current request but does match some other request, then delete that request and issue a CLS. If there's no match at all, the CLS gets ignored π« .
If the CLS matches the current request, here's the tea depending on CS:
PENDING: delete the current request. If the request queue is empty, delete the entry; otherwise, leave the entry alone.RFC-RCVD: issue aCLSand enter theABORTstate.ABORT: ignore.RFC-SENT: issue aCLS. If the pending call queue is empty, delete the entry, else enter thePENDINGstate.OPEN: if we are on the receive side, the response is identical to the response forRFC-SENT. If we are on the send side, clear the data queue, and if a RFNM is still pending, enter theRFNM-WAITstate. Otherwise the response is identical to the response forRFC-SENT. πCLS-WAIT: issue aCLS, and if the pending call queue is empty, delete the entry, otherwiseCS = PENDING.DATA-WAIT: clear the data queue and enter theRFNM-WAITstate.
A matching CLS cannot occur in the CLOSED or LISTENING states. Not possible, bestie π
ββοΈ
ERR
Errors get queued up for later attention by system programmers, and they're treated as a system error in the host that originated the exchange. This one isn't tied to any state at all π§Ύ.
ECO
The op code gets changed to ERP and retransmitted. Also not tied to any state π.
ERP
When an ERP arrives, the system passes the text of the command back to the process that issued the ECO. Full circle moment π¦.
INR, INS
These commands are only enabled in the OPEN state. When an INTERRUPT comes in, the system sends an event to the associated process. An INTERRUPT is ignored in the CLS-WAIT, DATA-WAIT, and RFNM-WAIT states. In any other state it's an error β‘.
ALL
ALLOCATE is only valid in the OPEN state, and it may be sent only to a send socket. The NCP increments the 'Their Size' field in the associated rendezvous table entry by the size specified in the ALLOCATE command π.
In the CLS-WAIT and DATA-WAIT states this command gets ignored. In any other state it's an error π.
Data-RFNM
- If in the
OPENstate, mark the Flow Control Status field in the appropriate rendezvous table entry asRFNM-RECVD, and send more data if required. π¨ - If in the
DATA-WAITstate, maintain the Flow Control Status. If the data queue is empty, issue aCLSand enter theCLS-WAITstate; otherwise, transmit the next message. π - If in the
RFNM-WAITstate, maintain the Flow Control Status and issue aCLS. If the Pending Call queue is empty, delete the rendezvous table entry, otherwiseCS = PENDING.
A Data-RFNM is an error in all other states π¨.
IX. Algorithms for the System Call Interpreter π
Each System Call gets its own moment, and the state changes it may effect are listed right under it πΈ.
CONNECT
- If there is no entry, create one, issue an RFC, and enter the
RFC-SENTstate. π - If
CS = PENDING, search the queue and reject all non-matching requests. If no match is found, issue an RFC and enter theRFC-SENTstate. If a match is found, issue an RFC and enter theOPENstate. Transmission can commence as soon as buffer space has been allocated. β¨ - In any other state this command is illegal.
LISTEN
- If an entry doesn't exist, create one, and enter the
LISTENINGstate. π - If
CS = PENDING, inform the user and enter theRFC-RCVDstate. - In any other state this command is illegal.
ACCEPT
- If
CS = RFC-RCVD, then issue an RFC and enter theOPENstate. Data transmission can occur as soon as buffer space is allocated. π₯³ - If
CS = ABORT, inform the user of the premature termination of the connection. If the pending call queue is empty, delete the entry; otherwise, enter thePENDINGstate. π - This command cannot be legally executed in any other state.
CLOSE
If CS =:
LISTENING, then delete the entry.RFC-RCVD, then issue aCLSand enter theCLS-WAITstate.ABORT, inform the user of the premature termination of the connection. If the pending call queue is empty, delete the entry; otherwise, enter thePENDINGstate.RFC-SENT, then issue aCLSand enter theCLS-WAITstate.OPEN, if we are on the send side, and the data queue is not empty, or if a Data-RFNM is still outstanding, enter theDATA-WAITstate; otherwise, issue aCLSand enter theCLS-WAITstate. π§ΉCLS-WAIT, issuing a CLOSE in this state is a USER ERROR. π«DATA-WAIT, issuing a CLOSE in this state is also an illegal sequence.RFNM-WAIT, ignore the CLOSE.
A valid CLOSE cannot be issued if an entry does not exist, or if a socket is in the PENDING state. Main character energy, but only when the timing is right ππ
[ This RFC was put into machine readable form for entry ]
[ into the online RFC archives by Anthony Anderberg 5/00 ]
π¦ where this page comes from
- ietf: rfc55 1970-06
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms