{Begin SubSec PUP Level One Functions} {Title PUP Level One Functions} {Text The functions in this section are used to implement level two and higher PUP protocols. That is, they deal with sending and receiving PUP packets. It is assumed the reader is familiar with the format and use of pups, e.g., from reading reference [3] on {PageRef Tag EtherReferences}. {Begin SubSec Creating and Managing Pups} {Title Creating and Managing Pups} {Text There is a record {lisp PUP} that overlays the data portion of an {lisp ETHERPACKET} and describes the format of a pup. This record defines the following numeric fields: {lisp PUPLENGTH} (16 bits), {lisp TCONTROL} (transmit control, 8 bits, cleared when a PUP is transmitted), {lisp PUPTYPE} (8 bits), {lisp PUPID} (32 bits), {lisp PUPIDHI} and {lisp PUPIDLO} (16 bits each overlaying {lisp PUPID}), {lisp PUPDEST} (16 bits overlayed by 8-bit fields {lisp PUPDESTNET} and {lisp PUPDESTHOST}), {lisp PUPDESTSOCKET} (32 bits, overlayed by 16-bit fields {lisp PUPDESTSOCKETHI} and {lisp PUPDESTSOCKETLO}), and {lisp PUPSOURCE}, {lisp PUPSOURCENET}, {lisp PUPSOURCEHOST}, {lisp PUPSOURCESOCKET}, {lisp PUPSOURCESOCKETHI}, and {lisp PUPSOURCESOCKETLO}, analagously. The field {lisp PUPCONTENTS} is a pointer to the start of the data portion of the pup. {FnDef {Name ALLOCATE.PUP} {Text Returns a (possibly used) pup. Keeps a free pool, creating new pups only when necessary. The pup header fields of the pup returned are guaranteed to be zero, but there may be garbage in the data portion if the pup had been recycled, so the caller should clear the data if desired. }} {FnDef {Name CLEARPUP} {Args PUP} {Text Clears {it all} information from {arg PUP}, including the pointer fields of the {lisp ETHERPACKET} and the pup data portion. }} {FnDef {Name RELEASE.PUP} {Args PUP} {Text Releases {arg PUP} to the free pool. }} }{End SubSec Creating and Managing Pups} {Begin SubSec Sockets} {Title Sockets} {Text Pups are sent and received on a {it socket}. Generally, for each "conversation" between one machine and another, there is a distinct socket. When a pup arrives at a machine, the low-level pup software examines the pup's destination socket number. If there is a socket on the machine with that number, the incoming pup is handed over to the socket; otherwise the incoming pup is discarded. When a {it user} process initiates a conversation, it generally selects a large, random socket number different from any other in use on the machine. A {it server} process, on the other hand, provides a specific service at a "well-known" socket, usually a fairly small number. In the PUP world, advertised sockets are in the range 0 to 100Q. {FnDef {Name OPENPUPSOCKET} {Args SKT# IFCLASH} {Text Opens a new pup socket. If {arg SKT#} is {lisp NIL} (the normal case), a socket number is chosen automatically, guaranteed to be unique, and probably different from any socket opened this way in the last 18 hours (the low half of the time of day clock is sampled). If a specific local socket is desired, as is typically the case when implementing a server, {arg SKT#} is given, and must be a (up to 32-bit) number. {Arg IFCLASH} indicates what to do in the case that the designated socket is already in use: if {lisp NIL}, an error is generated; if {lisp ACCEPT}, the socket is quietly returned; if {lisp FAIL}, then {fn OPENPUPSOCKET} returns {lisp NIL} without causing an error. Note that "well-known" socket numbers should be avoided unless the caller is actually implementing one of the services advertised as provided at the socket. }} {FnDef {Name CLOSEPUPSOCKET} {Args PUPSOC NOERRORFLG} {Text Closes and releases socket {arg PUPSOC}. If {arg PUPSOC} is {lisp T}, closes all pup sockets (this must be used with caution, since it will also close system sockets!). If {arg PUPSOC} is already closed, an error is generated unless {arg NOERRORFLG} is true. }} {FnDef {Name PUPSOCKETNUMBER} {Args PUPSOC} {Text Returns the socket number (a 32-bit integer) of {arg PUPSOC}. }} {FnDef {Name PUPSOCKETEVENT} {Args PUPSOC} {Text Returns the {lisp EVENT} of {arg PUPSOC} ({PageRef Fn AWAIT.EVENT}). This event is notified whenever a pup arrives on {arg PUPSOC}, so pup clients can perform an {fn AWAIT.EVENT} on this event if they have nothing else to do at the moment. }} }{End SubSec Sockets} {Begin SubSec Sending and Receiving Pups} {Title Sending and Receiving Pups} {Text {FnDef {Name SENDPUP} {Args PUPSOC PUP} {Text Sends {arg PUP} on socket {arg PUPSOC}. If any of the {lisp PUPSOURCESHOST}, {lisp PUPSOURCENET}, or {lisp PUPSOURCESOCKET} fields is zero, {fn SENDPUP} fills them in using the pup address of this machine and/or the socket number of {arg PUPSOC}, as needed. }} {FnDef {Name GETPUP} {Args PUPSOC WAIT} {Text Returns the next pup that has arrived addressed to socket {arg PUPSOC}. If there are no pups waiting on {arg PUPSOC}, then {fn GETPUP} returns {lisp NIL}, or waits for a pup to arrive if {arg WAIT} is {lisp T}. If {arg WAIT} is an integer, {fn GETPUP} interprets it as a number of milliseconds to wait, finally returning {lisp NIL} if a pup does not arrive within that time. }} {FnDef {Name DISCARDPUPS} {Args SOC} {Text Discards without examination any pups that have arrived on {arg SOC} and not yet been read by a {fn GETPUP}. }} {FnDef {Name EXCHANGEPUPS} {Args SOC OUTPUP DUMMY IDFILTER TIMEOUT} {Text Sends {arg OUTPUP} on {arg SOC}, then waits for a responding pup, which it returns. If {arg IDFILTER} is true, ignores pups whose {lisp PUPID} is different from that of {arg OUTPUP}. {arg TIMEOUT} is the length of time (msecs) to wait for a response before giving up and returning {lisp NIL}. {arg TIMEOUT} defaults to {var \ETHERTIMEOUT}.{index \ETHERTIMEOUT Var} {fn EXCHANGEPUPS} discards without examination any pups that are currently waiting on {arg SOC} before {arg OUTPUP} gets sent. ({arg DUMMY} is ignored; it exists for compatibility with an earlier implementation). }} }{End SubSec Sending and Receiving Pups} {Begin SubSec Pup Routing Information} {Title Pup Routing Information} {Text Ordinarily, a program calls {fn SENDPUP} and does not worry at all about the route taken to get the pup to its destination. There is an internet routing process in Lisp whose job it is to maintain information about the best routes to networks of interest. However, there are some algorithms for which routing information and/or the topology of the net are explicitly desired. To this end, the following functions are supplied: {FnDef {Name PUPNET.DISTANCE} {Args NET#} {Text Returns the "hop count" to network {arg NET#}, i.e., the number of gateways through which a pup must pass to reach {arg NET#}, according to the best routing information known at this point. The local (directly-connected) network is considered to be zero hops away. Current convention is that an inaccessible network is 16 hops away. {fn PUPNET.DISTANCE} may need to wait to obtain routing information from an Internetwork Router if {arg NET#} is not currently in its routing cache. }} {FnDef {Name SORT.PUPHOSTS.BY.DISTANCE} {Args HOSTLIST} {Text Sorts {arg HOSTLIST} by increasing distance, in the sense of {fn PUPNET.DISTANCE}. {arg HOSTLIST} is a list of lists, the {fn CAR} of each list being a 16-bit Net/Host address, such as returned by {fn ETHERHOSTNUMBER}. In particular, a list of ports ((nethost . socket) pairs) is in this format. }} {FnDef {Name PRINTROUTINGTABLE} {Args TABLE SORT FILE} {Text Prints to {arg FILE} the current routing cache. The table is sorted by network number if {Arg SORT} is true. {Arg TABLE} = {Lisp PUP} (the default) prints the PUP routing table; {Arg TABLE} = {Lisp NS} prints the NS routing table. }} }{End SubSec Pup Routing Information} {Begin SubSec Miscellaneous PUP Utilities} {Title Miscellaneous PUP Utilities} {Text {FnDef {Name SETUPPUP} {Args PUP DESTHOST DESTSOCKET TYPE ID SOC REQUEUE} {Text Fills in various fields in {arg PUP}'s header: its length (the header overhead length; assumes data length of zero), {arg TYPE}, {arg ID} (if {arg ID} is {lisp NIL}, generates a new one itself from an internal 16-bit counter), destination host and socket ({arg DESTHOST} may be anything that {fn ETHERPORT} accepts; an explicit nonzero socket in {arg DESTHOST} overrides {arg DESTSOCKET}). If {arg SOC} is not supplied, a new socket is opened. {arg REQUEUE} fills the packets {lisp EPREQUEUE} field (see above). Value of {fn SETUPPUP} is the socket. }} {FnDef {Name SWAPPUPPORTS} {Args PUP} {Text Swaps the source and destination addresses in {arg PUP}. This is useful in simple packet exchange protocols, where you want to respond to an input packet by diddling the data portion and then sending the pup back whence it came. }} {FnDef {Name GETPUPWORD} {Args PUP WORD#} {Text Returns as a 16-bit integer the contents of the {arg WORD#}th word of {arg PUP}'s data portion, counting the first word as word zero. }} {FnDef {Name PUTPUPWORD} {Args PUP WORD# VALUE} {Text Stores 16-bit integer {arg VALUE} in the {arg WORD#}th word of {arg PUP}'s data portion. }} {FnDef {Name GETPUPBYTE} {Args PUP BYTE#} {Text Returns as an integer the contents of the {arg BYTE#}th 8-bit byte of {arg PUP}'s data portion, counting the first byte as byte zero. }} {FnDef {Name PUTPUPBYTE} {Args PUP BYTE# VALUE} {Text Stores {arg VALUE} in the {arg BYTE#}th 8-bit byte of {arg PUP}'s data portion. }} {FnDef {Name GETPUPSTRING} {Args PUP OFFSET} {Text Returns a string consisting of the characters in {arg PUP}'s data portion starting at byte {arg OFFSET} (default zero) through the end of {arg PUP}. }} {FnDef {Name PUTPUPSTRING} {Args PUP STR} {Text Appends {arg STR} to the data portion of {arg PUP}, incrementing {arg PUP}'s length appropriately. }} }{End SubSec Miscellaneous PUP Utilities} {Begin SubSec PUP Debugging Aids} {Title PUP Debugging Aids} {Text Tracing facilities are provided to allow the user to see the pup traffic that passes through {fn SENDPUP} and {fn GETPUP}. The tracing can be verbose, displaying much information about each packet, or terse, which shows a concise "picture" of the traffic. {VarDef {Name PUPTRACEFLG} {Text Controls tracing information provided by {fn SENDPUP} and {fn GETPUP}. Legal values: {Begin LabeledList} {label {lisp NIL}} {Text No tracing.} {label {lisp T}} {Text Every {fn SENDPUP} and every successful {fn GETPUP} call {fn PRINTPUP} of the pup at hand (see below).} {label {lisp PEEK}} {Text Allows a concise "picture" of the traffic. For normal, non-broadcast packets, {fn SENDPUP} prints "{lisp !}", {fn GETPUP} prints "{lisp +}". For broadcast packets, {fn SENDPUP} prints "{lisp ↑}", {fn GETPUP} prints "{lisp *}". In addition, for packets that arrive not addressed to any socket on this machine (e.g., broadcast packets for a service not implemented on this machine), a "{lisp &}" is printed.} {End LabeledList} }} {VarDef {Name PUPIGNORETYPES} {Text A list of pup types (small integers). If the type of a pup is on this list, then {fn GETPUP} and {fn SENDPUP} will not print the pup verbosely, but treat it as though {var PUPTRACEFLG} were {lisp PEEK}. This allows the user to filter out "uninteresting" pups, e.g., routine routing information pups (type 201Q). }} {VarDef {Name PUPONLYTYPES} {Text A list of pup types. If this variable is non-{lisp NIL}, then {fn GETPUP} and {fn SENDPUP} print verbosely {it only} pups whose types appear on the list, treating others as though {var PUPTRACEFLG} were {lisp PEEK}. This lets the tracing be confined to only a certain class of pup traffic. }} {VarDef {Name PUPTRACEFILE} {Text The file to which pup tracing output is sent by default. The file must be open. {var PUPTRACEFILE} is initially {lisp T}. }} {VarDef {Name PUPTRACETIME} {Text If this variable is true, then each printout of a pup is accompanied by a relative timestamp (in seconds, with 2 decimal places) of the current time (i.e., when the {fn SENDPUP} or {fn GETPUP} was called; for incoming pups, this is not the same as when the pup actually arrived). }} {FnDef {Name PUPTRACE} {Args FLG REGION} {Text Creates a window for puptracing, and sets {var PUPTRACEFILE} to it. If {var PUPTRACEFILE} is currently a window and {arg FLG} is {lisp NIL}, closes the window. Sets {var PUPTRACEFLG} to be {arg FLG}. If {arg REGION} is supplied, the window is created with that region. The window's {lisp BUTTONEVENTFN} is set to cycle {var PUPTRACEFLG} through the values {lisp NIL}, {lisp T}, and {lisp PEEK} when the mouse is clicked in the window. }} {FnDef {Name PRINTPUP} {Args PACKET CALLER FILE PRE.NOTE DOFILTER} {Text Prints the information in the header and possibly data portions of pup {arg PACKET} to {arg FILE}. If {arg CALLER} is supplied, it identifies the direction of the pup ({lisp GET} or {lisp PUT}), and is printed in front of the header. {arg FILE} defaults to {var PUPTRACEFILE}. If {arg PRE.NOTE} is non-{lisp NIL}, it is {fn PRIN1}'ed first. If {arg DOFILTER} is true, then if {arg PUP}'s type fails the filtering criteria of {var PUPIGNORETYPES} or {var PUPONLYTYPES}, then {arg PUP} is printed "tersely", i.e., as a {lisp !}, {lisp +}, {lisp ↑}, or {lisp *}, as described above. {fn GETPUP} and {fn SENDPUP}, when {var PUPTRACEFLG} is non-{lisp NIL}, call {lisp (PRINTPUP {arg PUP} {bracket 'GET {rm or} 'PUT} NIL NIL T)}. }} The form of printing provided by {fn PRINTPUP} can be influenced by adding elements to {var PUPPRINTMACROS}. {VarDef {Name PUPPRINTMACROS} {Text An association list of elements ({arg PUPTYPE} . {arg MACRO}) for printing pups. The {arg MACRO} ({fn CDR} of each element) tells how to print the information in a pup of type {arg PUPTYPE} ({fn CAR} of the element). If {arg MACRO} is a litatom, then it is a function of two arguments ({arg PUP} {arg FILE}) that is applied to the pup to do the printing. Otherwise, {arg MACRO} is a list describing how to print the data portion of the pup (the header is printed in a standard way). The list form of {arg MACRO} consists of "commands" that specify a "datatype" to interpret the data, and an indication of how far that datatype extends in the packet. Each element of {arg MACRO} is one of the following: (a) a byte offset (positive integer), indicating the byte at which the next element, if any, takes effect; (b) a negative integer, the absolute value of which is the number of bytes until the next element, if any, takes effect; or (c) an atom giving the format in which to print the data, one of the following: {Begin LabeledList PUPPRINTMACRO tokens} {Label {lisp BYTES}} {Text Print the data as 8-bit bytes, enclosed in brackets. This is the default format to start with.} {Label {lisp CHARS}} {Text Print the data as (8-bit) characters. Non-printing characters are printed as if the format were {lisp BYTES}, except that the sequence 15Q, 12Q is printed specially as [crlf].} {Label {lisp WORDS}} {Text Print the data as 16-bit integers, separated by commas (or the current {lisp SEPR}).} {Label {lisp INTEGERS}} {Text Print the data as 32-bit integers, separated by commas (or the current {lisp SEPR}). Note: the singular {lisp BYTE}, {lisp CHAR}, {lisp WORD}, {lisp INTEGER} are accepted as synonyms for these four commands.} {Label {Lisp SEPR}} {Text Set the separator for {lisp WORDS} and {lisp INTEGERS} to be the next element of the macro. The separator is initially the two characters, comma, space.} {Label {lisp IFSSTRING}} {Text Interprets the data as a 16-bit length followed by that many 8-bit bytes or characters. If the current datatype is {lisp BYTES}, leaves it alone; otherwise, sets it to be {lisp CHARS}.} {Label {lisp ...}} {Text If there is still data left in the packet by the time processing reaches this command, prints "{ellipsis}" and stops.} {Label {Lisp FINALLY}} {Text The next element of the macro is printed when the end of the packet is reached (or printing stops because of a {ellipsis}). This command does not alter the datatype, and can appear anywhere in the macro as long as it is encountered before the actual end of the packet.} {Label {Lisp T}} {Text Perform a {fn TERPRI}.} {Label {Lisp REPEAT}} {Text The remainder of the macro is itself treated as a macro to be applied over and over until the packet is exhausted. Note that the offsets specified in the macro must be in the relative form, i.e., negative integers. For example, the macro {lisp (INTEGERS 4 REPEAT BYTES -2 WORDS -4)} says to print the first 4 bytes of the data as one 32-bit integer, then print the rest of the data as sets of 2 8-bit bytes and 2 16-bit words.} {End LabeledList PUPPRINTMACRO tokens} Only as much of the macro is processed as is needed to print the data in the given packet. The default macro for printing a pup is {lisp (BYTES 12 ...)}, meaning to print the first up to 12 bytes as bytes, and then print "{ellipsis}" if there is anything left. }} {FnDef {Name PUP.ECHOUSER} {Args HOST ECHOSTREAM INTERVAL NTIMES} {Text Sends dummy packets to be echoed by the host {arg HOST}. Can be used as a simple test of the functioning of the Ethernet and the host. {arg HOST} is the pup host to send the packets to. {arg ECHOSTREAM} is the stream for printing status information. {arg INTERVAL} is the interval (in milliseconds) to wait for the packet to be echoed (default 1000). {arg NTIMES} is the number of packets to send (default 1000). As each packet is sent and received, characters are printed to {arg ECHOSTREAM} as follows: {Begin LabeledList PUP.ECHOUSER chars} {Label {lisp !}} {Text Printed when a packet is sent.} {Label {lisp +}} {Text Printed when an echo packet is sucessfully received.} {Label {lisp .}} {Text Printed when an echo packet has not been received after {arg INTERVAL} milliseconds.} {Label {lisp ?}} {Text Printed when a packet is received, but it isn't an echo packet or an error packet.} {Label {lisp (late)}} {Text Printed when an error packet is received, after the echo request timed out.} {End LabeledList PUP.ECHOUSER chars} The trace can be used to test the functioning of the ethernet and host. For example, if the trace is {lisp !+!+!+!+!+}, the host is listening and echoing correctly. {lisp !.!.!.!.!.} indicates that for some reason the host is not responding. {lisp !+!.!.!(late).!(late)(late)+} indicates that the packets are being echoed, but not immediately. }} The following functions are used by {fn PRINTPUP} and similar functions, and may be of interest in special cases. {FnDef {Name PORTSTRING} {Args NETHOST SOCKET} {Text Converts the pup address {arg NETHOST}, {arg SOCKET} into octal string format as follows: {lisp {arg NET}#{arg HOST}#{arg SOCKET}}. {arg NETHOST} may be a port (dotted pair of nethost and socket), in which case {arg SOCKET} is ignored, and the socket portion of {arg NETHOST} is omitted from the string if it is zero. }} {FnDef {Name PRINTPUPROUTE} {Args PACKET CALLER FILE} {Text Prints the source and destination addresses of pup {arg PACKET} to {arg FILE} in the {fn PORTSTRING} format, preceded by {arg CALLER} (interpreted as with {fn PRINTPUP}). }} {FnDef {Name PRINTPACKETDATA} {Args BASE OFFSET MACRO LENGTH FILE} {Text Prints data according to {arg MACRO}, which is a list interpreted as described under {var PUPPRINTMACROS}, to {arg FILE}. The data starts at {arg BASE} and extends for {arg LENGTH} bytes. The actual printing starts at the {arg OFFSET}th byte, which defaults to zero. For example, {fn PRINTPUP} ordinarily calls {lisp (PRINTPACKETDATA (fetch PUPCONTENTS of {arg PUP}) 0 {arg MACRO} (IDIFFERENCE (fetch PUPLENGTH of {arg PUP}) 20) {arg FILE})}. }} {FnDef {Name PRINTCONSTANT} {Args VAR CONSTANTLIST FILE PREFIX} {Text {arg CONSTANTLIST} is a list of pairs ({arg VARNAME} {arg VALUE}), of the form given to the {FileCom CONSTANTS} File Package Command. {fn PRINTCONSTANT} prints {arg VAR} to {arg FILE}, followed in parentheses by the {arg VARNAME} out of {arg CONSTANTLIST} whose {arg VALUE} is {fn EQ} to {arg VAR}, or {lisp ?} if it finds no such element. If {arg PREFIX} is non-{lisp NIL} and is an initial substring of the selected {arg VARNAME}, then {arg VARNAME} is printed without the prefix. For example, if {lisp FOOCONSTANTS} is {lisp ((FOO.REQUEST 1) (FOO.ANSWER 2) (FOO.ERROR 3))}, then {lisp (PRINTCONSTANT 2 FOOCONSTANTS T "FOO.")} produces "{lisp 2 (ANSWER)}". }} {FnDef {Name OCTALSTRING} {Args N} {Text Returns a string of octal digits representing {arg N} in radix 8. }} }{End SubSec PUP Debugging Aids} }{End SubSec PUP Level One Functions}