;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: 4Chaosnet Overview* =Text: 3CHAOSNET OVERVIEW* The purpose of the basic software protocol of Chaosnet is to allow high-speed communication among processes on different machines, with no undetected transmission errors. The principal service provided by Chaosnet is a 1connection* between two user processes. This is a full-duplex reliable packet-transmission channel. The network undertakes never to garble, lose, duplicate, or resequence the packets; in the event of a serious error it may break the connection off entirely, informing both user processes. User programs may deal explicitly in terms of packets. They may also ignore packet boundaries and treat the connection as two uni-directional streams of 8-bit or 16-bit bytes, but this really works by means of packets. If you just want to ask a question of another process or host and receive a reply, you can use a 1simple transaction*: You send only one packet to the other host, and it sends one packet back. This is more efficient than establishing a connection and using it only briefly. In a simple transaction, the server cannot tell whether the user received the answer; and if the user does not receive the answer, it cannot tell whether the server received the question. In fact, the server might receive the question more than once. If this is unacceptable, a connection must be used. Each node (or host) on the network is identified by an 1address*, which is a 16-bit number. These addresses are used in the routing of packets. There is a table (the system host table, 2SYS: CHAOS; HOSTS TXT*) that relates symbolic host names to numeric host addresses. The host table can record addresses on any number of different networks, and in certain contexts a host address is meaningful only together with the name of the network it is for. The data transmitted over connections are in units called 1packets*. Each packet contains an 8-bit number, the 1opcode*, which indicates what its function is. Opcode numbers are always given in octal. Opcodes less than 200 (octal) are special purpose. Each such opcode that is used has an assigned name and a specific function. Users need not know about all of them. Opcodes 200 through 277 (octal) are used for 8-bit user data. Opcodes 300 through 377 (octal) are used for 16-bit user data. Each packet also contains some number of data bytes, whose meaning depends on the opcode. If the opcode is for user data, then it is up to the application user software to decide on the interpretation. Establishing a connection: A connection is created because one process sends a request to a host. The request is a packet containing the special-purpose opcode RFC. The data contains a 1contact name* which is used to find the process to connect to. There may be a process on the target host 1listening* on this contact name. If so, it decides whether to agree to the connection. Alternatively, the contact name can be the name of a standard service such as 3TELNET*. In this case, the receiving host creates a process to respond, loaded with the program for that service. Once a connection has been established, there is no more need for the contact name and it is discarded. The Lisp Machine remembers what contact name was used to open a connection, but this is only for the user's information. In the case where two existing processes that already know about each other want to establish a connection, they must agree on a contact name, and then one of them must send the request while the other listens. They must agree between themselves which is to do which. Contact names are restricted to strings of upper-case letters, numbers, and ASCII punctuation. The maximum length of a contact name is limited only by the packet size, although on ITS hosts the names of automatically-started servers are limited by the file-system to six characters. The contact name is terminated by a space. If the RFC packet contains data beyond the contact name, it is just for interpretation by the listening process, which can also use it in deciding whether to accept the connection. A simple transaction is also begun with an RFC packet. There is nothing in the RFC packet which indicates whether it is intended to start a connection or a simple transaction. The server has the option of doing either one. But normally any given server always does one or the other, and the requestor knows which one to expect. The server accepts the request for a connection by sending an OPN packet (a packet with opcode OPN) to the requestor. It can also refuse the connection by sending a CLS packet. The data in the CLS packet is a string explaining the reason for the refusal. Another alternative is to tell the requestor to try a different host or a different contact name. This is called 1forwarding* the request, and is done with a FWD packet. The server can also respond with an answer, an ANS packet, which is the second half of a simple transaction. (Refusing and forwarding are also meaningful when a simple transaction is intended, just as when a connection is intended). Once the connection is open: Data transmitted through Chaosnet generally follow Lisp Machine standards. Bits and bytes are numbered from right to left, or least-significant to most-significant. The first 8-bit byte in a 16-bit word is the one in the arithmetically least-significant position. The first 16-bit word in a 32-bit double-word is the one in the arithmetically least-significant position. This is the ``little-endian'' convention. Big-endian machines such as the PDP-10 need to reorder the characters in a word in order to access them conveniently. For their sake, some packet opcodes imply 8-bit data and some imply 16-bit data. Packets known to contain 8-bit bytes, including opcodes 200 through 277, are stored in the big-endian machine's memory a character at a time, whereas packets containing 16-bit data are stored 16 bits at a time. The character set used is dictated by the higher-level protocol in use. Telnet and Supdup, for example, each specifies its own ASCII-based character set. The default character set--used for new protocols and for text that appears in the basic Chaosnet protocol, such as contact names--is the Lisp Machine character set. If one process tries to send data faster than the other can process it, the buffered packets could devour lots of memory. Preventing this is the purpose of 1flow control*. Each process specifies a 1window size*, which is the number of packets that are allowed to be waiting for that process to read. Attempting to send on a connection whose other side's window is full waits until the other side reads some packets. The default window size is 13, but for some applications you might wish to specify a larger value (see 4(CHAOSNET-1)Opening and Closing Connections - User Side*). There is little reason ever to specify a smaller value. Breaking a connection: Either end of a connection can break the connection abruptly by sending a CLS packet. The data in this packet is a string describing why the connection was broken. To break a connection gently, it is necessary to verify that all the data transmitted was received properly before sending a CLS. This matters in some applications and is unnecessary in others. When it is needed, it is done by sending a special packet, an EOF packet, which is mostly like a data packet except for its significance with regard to closing the connection. The EOF packet is like the words ``the end'' at the end of a book: it tells the recipient that it has received all the data it is supposed to receive, that there are no missing pages that should have followed. When the sender of the EOF sees the acknowledgement for the EOF packet, indicating that the EOF was received and understood, it can break the connection with a CLS. If a process that expects to receive an EOF gets a CLS with no EOF, it takes this to mean that the connection was broken before the transmission was finished. If the process does receive an EOF, it does not break the connection itself immediately. It waits to see the sender of the EOF break it. If this does not happen in a few seconds, the EOF recipient can break the connection. It is illegal to put data in an EOF packet; in other words, the byte count should always be zero. Most Chaosnet implementations simply ignore any data that is present in an EOF. If both sides are sending data and both need to know for certain where ``the end'' is, they must do something a little more complicated. Arbitrarily call one party the user and the other the server. The protocol is that after sending all its data, each party sends an EOF and waits for it to be acknowledged. The server, having seen its EOF acknowledged, sends a second EOF. The user, having seen its EOF acknowledged, looks for a second EOF and 1then* sends a CLS and goes away. The server goes away when it sees the user's CLS, or after a brief timeout has elapsed. This asymmetrical protocol guarantees that each side gets a chance to know that both sides agree that all the data have been transferred. The first CLS is sent only after both sides have waited for their (first) EOF to be acknowledged. Clearing up inconsistencies: If a host crashes, it is supposed to forget all the connections that it had. When a packet arrives on one of the former connections, the host will report ``no such connection'' to the sender with a LOS packet, whose data is a string explaining what happened. The same thing happens if a CLS packet is lost; the intended recipient may keep trying to use the connection that the other side (which sent the CLS) no longer believes should exist. LOS packets are used whenever a host receives a packet that it should not be getting; the recipient of the LOS packet knows that the connection it thought it was using does not exist any more. =Node: 4Conns* =Text: 3CONNS* On the Lisp Machine, your handle on a connection is a named structure of type 2chaos:conn*. The 2conn* may have an actual connection attached to it, or it may have a connection still being made, or record that a connection was refused, closed or broken. 2chaos:inactive-state* This 2conn* is not really in use at all. 2chaos:rfc-sent-state* This 2conn* was used to request a connection to another process, but no reply has been received. When the reply is received, it may change the 2conn*'s state to 2chaos:answered-state*, 2chaos:cls-received-state*, or 2chaos:open-state*. 2chaos:listening-state* This 2conn* is being used to listen with. If a RFC packet is received for the contact name you are listening on, the state changes to 2chaos:rfc-received-state*. 2chaos:rfc-received-state* This means that your listen has ``heard'' an RFC packet that matches it. You can accept, reject, forward or answer the request. Accepting goes to state 2chaos:open-state*; refusing or forwarding goes to to state 2chaos:inactive-state*. 2chaos:open-state* This 2conn* is one end of an open connection. You can receive any data packets that are waiting and you can transmit data. 2chaos:answered-state* This 2conn* was used to send an RFC packet and an ANS packet was received in response (a simple transaction answer arrived). You can read the ANS packet, that is all. 2chaos:cls-received-state* This 2conn* has received a CLS packet (the connection was closed or refused). You can read any data packets that came in before the CLS; after them you can read the CLS. 2chaos:los-received-state* This 2conn*'s connection was broken and the other end sent a LOS packet to say so. The LOS packet is the only packet available to be read. 2chaos:host-down-state* The host at the other end of this 2conn*'s connection has not responded to anything for a significant time. 2chaos:foreign-state* The connection is being used with a foreign protocol encapsulated in UNC packets (see the MIT AI Lab memo entitled ``Chaosnet'' for more information on this). These are the fields of a 2conn* that you might be interested in: 3chaos:conn-state* 1conn* This slot holds the state of 1conn*. It is one of the symbols listed above. 3chaos:conn-foreign-address* 1conn* Returns the address of the host at the other end of this connection. Use 2si:get-host-from-address* to find out which host this is (see 4(FILENAMES-4)Parsing Hostnames*). 3chaos:conn-read-pkts* 1conn* Internally threaded chain of incoming packets available to be read from 1conn*. Its main use for the applications programmer is to test whether there are any incoming packets. 3chaos:conn-window-available* 1conn* Returns the number of packets you may transmit before the network software forces you to wait for the receiver to read some. This is just a minimum. By the time you actually send this many packets, the receiver may already have said he has room for some more. 3chaos:conn-plist* 1conn* This slot is used to store arbitrary properties on 1conn*. You can store properties yourself; use property names that are not in the 2chaos* package to avoid conflict. 3chaos:contact-name* 1conn* Returns the contact name with which 1conn* was created. The contact name is not significant to the functioning of the connection once an RFC and LSN have matched, but it is remembered for the sake of debugging. The user can use this function or the 2:contact-name* message to a stream to determine any contact name ``arguments.'' 3chaos:wait* 1conn* 1state* 1timeout* &optional 1whostate* Waits until the state of 1conn* is not the symbol 1state*, or until 1timeout* 60ths of a second have elapsed. If the timeout occurs, 2nil* is returned; otherwise 2t* is returned. 1whostate* is the process state to put in the who-line; it defaults to 2"Chaosnet wait"*. =Node: 4Opening and Closing Connections* - User Side =Text: 3OPENING AND CLOSING CONNECTIONS - USER* 3SIDE chaos:connect* 1host* 1contact-name* &optional 1window-size* 1timeout* Opens a stream connection; returns a 2conn* if it succeeds or else a string giving the reason for failure. 1host* may be a number or the name of a known host. 1contact-name* is a string containing the contact name and any additional arguments to go in the RFC packet. If 1window-size* is not specified it defaults to 13. If 1timeout* is not specified it defaults to 600 (ten seconds). 3chaos:simple* 1host* 1contact-name* &optional 1timeout* Taking arguments similar to those of 2chaos:connect*, this performs the user side of a simple-transaction. The returned value is either an ANS packet or a string containing a failure message. The ANS packet should be disposed of (using 2chaos:return-pkt*, see below) when you are done with it. 3chaos:remove-conn* 1conn* Makes 1conn* null and void. It becomes inactive, all its buffered packets are freed, and the corresponding Chaosnet connection (if any) goes away. This is called 1removing* the connection. 1conn* itself is marked for reuse for another Chaosnet connection, so you should not do anything else with it after it is removed. 3chaos:close-conn* 1conn* &optional 1reason* Closes and removes the connection. If it is open, a CLS packet is sent containing the string 1reason*. Don't use this to reject RFC's; use 2chaos:reject* for that. 3chaos:open-foreign-connection* 1host* 1index* &optional 1pkt-allocation* 1distinguished-port* Creates a 2conn* that may be used to transmit and receive foreign protocols encapsulated in UNC packets. 1host* and 1index* are the destination address for packets sent with 2chaos:send-unc-pkt*. 1pkt-allocation* is the `window size', i.e. the maximum number of input packets that may be buffered. It defaults to 10. If 1distinguished-port* is supplied, the local index is set to it. This is necessary for protocols that define the meanings of particular index numbers. See the MIT AI Lab memo entitled ``Chaosnet'' for more information on using foreign protocols. =Node: 4Opening and Closing Connections* - Server Side =Text: 3OPENING AND CLOSING CONNECTIONS - SERVER SIDE chaos:listen* 1contact-name* &optional 1window-size* 1wait-for-rfc* Waits for an RFC for the specified contact name to arrive, then returns a 2conn* that is in 2chaos:rfc-received-state*. If 1window-size* is not specified it defaults to 13. If 1wait-for-rfc* is specified as 2nil* (it defaults to 2t*) then the 2conn* is returned immediately without waiting for an RFC to arrive. 3chaos:server-alist* 1Variable* Contains an entry for each server that always exists. When an RFC arrives for one of these servers, the specified form is evaluated in the background process; typically it creates a process that will then do a 2chaos:listen*. Use the 2add-initialization* function to add entries to this list. Here is how the EVAL server is installed: 3(ADD-INITIALIZATION "EVAL"* 3 '(PROCESS-RUN-FUNCTION "EVAL Server" 'EVAL-SERVER-FUNCTION)* 3 NIL* 3 'CHAOS:SERVER-ALIST) chaos:accept* 1conn* 1conn* must be in 2chaos:rfc-received-state*. An OPN packet is transmitted and 1conn* enters the 2chaos:open-state*. If the RFC packet has not already been read with 2chaos:get-next-pkt*, it is discarded. You should read it before accepting, if it contains arguments in addition to the contact name. 3chaos:reject* 1conn* 1reason* 1conn* must be in 2chaos:rfc-received-state*. A CLS packet containing the string 1reason* is sent and 1conn* is removed from the connection table. 3chaos:forward-all* 1contact-name* 1host* Causes all future requests for connection to this host on 1contact-name* to be forwarded to the same contact name at host 1host*. 3chaos:answer-string* 1conn* 1string* 1conn* must be in 2chaos:rfc-received-state*. An ANS packet containing the string 1string* is sent and 1conn* is removed from the connection table. 3chaos:answer* 1conn* 1pkt* 1conn* must be in 2chaos:rfc-received-state*. 1pkt* is transmitted as an ANS packet and 1conn* is removed. Use this function when the answer is some binary data rather than a text string. 3chaos:fast-answer-string* 1contact-name* 1string* If a pending RFC exists to 1contact-name*, an ANS containing 1string* is sent in response to it and 2t* is returned. Otherwise 2nil* is returned. This function involves the minimum possible overhead. No 2conn* is created. =Node: 4Stream Input and Output* =Text: 3STREAM INPUT AND OUTPUT chaos:open-stream* 1host* 1contact-name* &key 1window-size* 1timeout* 1error* 1direction* 1characters* 1ascii-translation* Opens a Chaosnet connection and returns a stream that does I/O to it. 1host* is the host to connect to; 1contact-name* is the contact name at that host. These two arguments are passed along to 2chaos:connect*. If 1host* is 2nil*, a connection to 1contact-name* is listened for, and a stream is returned as soon as a request comes in for that contact name. At this time, you must accept or reject the connection by invoking the stream operation 2:accept* or 2:reject*. Before you decide which to do, you can use the 2:foreign-host* operation to find out where the connection came from. The remaining arguments are: 1window-size* 1timeout*These two arguments specify two arguments for 2chaos:connect*. 1error* If the value is non-2nil*, a failure to connect causes a Lisp error. Otherwise, it causes a string describing the error to be returned. 1direction* 1characters* 1ascii-translation*These three arguments are passed along to 2chaos:make-stream*. 3chaos:make-stream* 1conn* &key 1direction* 1characters* 1ascii-translation* Creates and returns a stream that does I/O on the connection 1conn*, which should be open as a stream connection. 1direction* may be 2:input*, 2:output* or 2:bidirectional*. If 1characters* is non-nil (which is the default), the stream reads and writes 8-bit bytes. If 1characters* is 2nil*, the stream reads and writes 16-bit bytes. If 1ascii-translation* is non-2nil*, characters written to the stream are translated to standard ASCII before they are sent, and characters read are translated from ASCII to the Lisp Machine character set. 3:connection* 1Operation on 2chaos:basic-stream** Returns the connection with which this stream is connected. 3:contact-name* 1Operation on 2chaos:basic-stream** Return the contact name with with this stream was opened. 3:foreign-host* 1Operation on 2chaos:basic-stream** Returns the host object for the host at the other end of this stream's connection. 3:accept* 1Operation on 2chaos:basic-stream** Accepts the request for a connection which this stream received. Used only for streams made by 2chaos:open-stream* with 2nil* as the 1host* argument. 3:reject* 1reason-string* 1Operation on 2chaos:basic-stream** Rejects the request for a connection which this stream received, sending 1reason-string* in the CLS packet as the reason. Used only for streams made by 2chaos:open-stream* with 2nil* as the 1host* argument. 3:close* &optional 1abort-p* 1Operation on 2chaos:basic-stream** Sends a CLS packet and removes the connection. For output connections and bidirectional connections, the 2:eof* operation is performed first, if 1abort-p* is 2nil*. 3:force-output* 1Operation on 2chaos:basic-output-stream** Any buffered output is transmitted. Normally output is accumulated until a full packet's worth of bytes are available, so that maximum-size packets are transmitted. 3:finish* 1Operation on 2chaos:basic-output-stream** Waits until either all packets have been sent and acknowledged, or the connection ceases to be open. If successful, returns 2t*; if the connection goes into a bad state, returns 2nil*. 3:eof* 1Operation on 2chaos:basic-output-stream** Forces out any buffered output, sends an EOF packet, and does a 2:finish*. 3:clear-eof* 1Operation on 2chaos:basic-input-stream** Allows you to read past an EOF packet on input. Normally, each 2:tyi* done at eof returns 2nil* or signals the specified eof error. If you do 2:clear-eof* on the stream, you can then read more data (assuming there are data packets following the EOF packet). =Node: 4Packet Input and Output* =Text: 3PACKET INPUT AND OUTPUT* Input and output on a Chaosnet connection can be done at the whole-packet level, using the functions in this section. A packet is represented by a 2chaos:pkt* data structure. Allocation of 2pkts* is controlled by the system; each 2pkt* that it gives you must be given back. There are functions to convert between 2pkts* and strings. A 2pkt* is an 2art-16b* array containing the packet header and data; the leader of a 2pkt* contains a number of fields used by the system. 3chaos:first-data-word-in-pkt* 1Constant* This is the index in any 2pkt* of the element that is the first 16-bit word of user data. (Preceding elements are used to store a header used by the hardware.) 3chaos:max-data-words-per-pkt* 1Constant* The maximum number of 16-bit data words allowed in a packet. 3chaos:pkt-opcode* 1pkt* Accessor for the opcode of the packet 1pkt*. To set the opcode, do 3(setf (chaos:pkt-opcode my-pkt) my-opcode)* The system provides names for all the opcodes standardly used. The names useful to the applications programmer appear at the end of this section. 3chaos:pkt-nbytes* 1pkt* Accessor for the number-of-data-bytes field of 1pkt*'s. This field says how much of 1pkt*'s contects are valid data, measured in 8-bit bytes. This field can be set with 2setf* also. 3chaos:pkt-string* 1pkt* An indirect array that is the data field of 1pkt* as a string of 8-bit bytes. The length of this string is equal to 2(chaos:pkt-nbytes 1pkt*)*. If you wish to record the contects of 1pkt* permanently, you must copy this string. 3chaos:set-pkt-string* 1pkt* &rest 1strings* Copies the 1strings* into the data field of 1pkt*, concatenating them, and sets 2(chaos:pkt-nbytes* 1pkt2)** accordingly. 3chaos:get-pkt* Allocates a 2pkt* for use by the user. 3chaos:return-pkt* 1pkt* Returns 1pkt* to the system for reuse. The packets given to you by 2chaos:get-pkt*, 2chaos:get-next-pkt* and 2chaos:simple* should be returned to the system in this way when you are finished with them. 3chaos:send-pkt* 1conn* 1pkt* &optional 1(opcode* 3chaos:dat-op1)** Transmits 1pkt* on 1conn*. 1pkt* should have been allocated with 2chaos:get-pkt* and then had its data field and n-bytes filled in. 1opcode* must be a data opcode (#o200 or more) or EOF. An error is signaled, with condition 2chaos:not-open-state*, if 1conn* is not open. Giving a 2pkt* to 2chaos:send-pkt* constitutes giving it back to the system. You do not need to call 2chaos:return-pkt*. 3chaos:send-string* 1conn* &rest 1strings* Sends a data packet containing the concatenation of 1strings* as its data. 3chaos:send-unc-pkt* 1conn* 1pkt* &optional 1pkt-number* 1ack-number* Transmits 1pkt*, an UNC packet, on 1conn*. The opcode, packet number, and acknowledge number fields in the packet header are filled in (the latter two only if the optional arguments are supplied). See the MIT AI Lab memo entitled ``Chaosnet'' for more information on using foreign protocols. 3chaos:may-transmit* 1conn* A predicate that returns 2t* if there is any space in the window for transmitting on 1conn*. If the value is 2nil*, you may have to wait if you try to transmit. If the value is 2t*, you certainly do not have to wait. 3chaos:finish-conn* 1conn* &optional 1(whostate* 3"Net1 Finish")** Waits until either all packets have been sent and acknowledged, or the connection ceases to be open. If successful, returns 2t*; if the connection goes into a bad state, returns 2nil*. 1whostate* is the process state to display in the who-line while waiting. 3chaos:conn-finished-p* 1conn* 2t* unless 1conn* is open and has sent packets which have not been acknowledged. 3chaos:get-next-pkt* 1conn* &optional 1(no-hang-p* 3nil1)** 1whostate* 1check-conn-state* Returns the next input packet from 1conn*. When you are done with the packet you must give it back to the system with 2chaos:return-pkt*. This can return an RFC, CLS, or ANS packet, in addition to data, UNC, or EOF. If no packets are available, 2nil* is returned if 1no-hang-p* is 2t*. Otherwise, 2chaos:get-next-pkt* waits for a packet to come in or for the state to change. 1whostate* is displayed in the who line; it defaults to 2"Chaosnet Input"*. If 1check-conn-state* is non-2nil*, the connection state is checked for validity before anything else is done, and an error is signaled if the connection is in a bad state, with condition name 2chaos:host-down*, 2chaos:los-received-state*, or 2chaos:read-on-closed-connection*. If 1check-conn-state* is 2nil* and 1no-hang-p* is 2t*, 2nil* is returned. 1check-conn-state* defaults to 2(not* 1no-hang-p2)**. 3chaos:data-available* 1conn* A predicate that returns 2t* if there any input packets available from 1conn*. Here are symbolic names for the opcodes that an applications programmer needs to know about: 3chaos:rfc-op* 1Constant* This special-purpose opcode is used for requesting a connection. The data consists of the contact name terminated by a space character, followed optionally by additional data whose meaning is up to the server for that contact name. 3chaos:brd-op* 1Constant* This special purpose opcode is for requesting responses from many hosts. Currently, there is no user end for initiating these requests in the Lisp Machine system, but the Lisp Machine can respond to such requests. An incoming packet of this type is treated like an RFC packet. 3chaos:lsn-op* 1Constant* This special-purpose opcode is used when you ask to listen on a contact name. The data is just the contact name. This packet is never actually sent over the network, just kept in the Chaosnet software and compared with the contact names in RFC packets that arrive. 3chaos:opn-op* 1Constant* This special-purpose opcode is used by the server process to accept the request for a connection conveyed by an RFC packet. Its data serves only internal functions. 3chaos:ans-op* 1Constant* This special-purpose opcode is used to send a simple reply. The simple reply is sent back in place of opening a connection. 3chaos:los-op* 1Constant* This special-purpose packet is what you receive if you try to use a connection that has been broken. Its data is a message explaining the situation, which you can print for the user. 3chaos:cls-op* 1Constant* This special-purpose packet is used to close a connection. Its data is a message explaining the reason, and it can be printed for the user. Note that you cannot count on receiving a CLS packet because it is not retransmitted if it is lost. If that happens you get a LOS when you try to use the connection (thinking it is still open). CLS packets are also used for refusing to open a connection in the first place. 3chaos:eof-op* 1Constant* This special-purpose opcode is used to indicate the end of the data that you really want to transmit. When this packet is acknowledged by the other process, you know that all the real data was received properly. You can wait for this with 2chaos:finish*. The EOF packet carries no data itself. 3chaos:dat-op* 1Constant* This is opcode 200 (octal), which is the normal opcode used for 8-bit user data. Some protocols use multiple data opcodes in the range 200 through 277, but simple protocols that do not need to distinguish types of packets just use opcode 200. =Node: 4Connection Interrupts* =Text: 3CONNECTION INTERRUPTS chaos:interrupt-function* 1conn* This attribute of a 2conn* is a function to be called when certain events occur on this connection. Normally this is 2nil*, which means not to call any function, but you can use 2setf* to store a function here. Since the function is called in the Chaosnet background process, it should not do any operations that might have to wait for the network, since that could permanently hang the background process. The function's first argument is one of the following symbols, giving the reason for the interrupt. The function's second argument is 1conn*. Additional arguments may be present depending on the reason. The possible reasons are: 2:input* A packet has arrived for the connection when it had no input packets queued. It is now possible to do 2chaos:get-next-pkt* without having to wait. There are no additional arguments. 2:output* An acknowledgement has arrived for the connection and made space in the window when formerly it was full. Additional output packets may now be transmitted with 2chaos:send-pkt* without having to wait. There are no additional arguments. 2:change-of-state* The state of the connection has changed. The third argument to the function is the symbol for the new state. 3chaos:read-pkts* 1conn* Some interrupt functions want to look at the queued input packets of a connection when they get a 2:input* interrupt. 2chaos:read-pkts* returns the first packet available for reading. Successive packets can be found by following 2chaos:pkt-link*. 3chaos:pkt-link* 1pkt* Lists of packets in the NCP are threaded together by storing each packet in the 2chaos:pkt-link* of its predecessor. The list is terminated with 2nil*.