[mod.protocols.appletalk] TCP Driver Specification

saf@CITI.UMICH.EDU.UUCP (04/09/87)

What follows is CITI's draft proposal for a TCP driver interface specification.
Readers should be familiar with CITI's Driver Interface Guide, which appeared
on this mailing list about a month ago.  Address comments and questions to :

            apple_corps@citi.umich.edu

A copy of this in word 3.0 with fancy fonts (symbol, palatino, courier)
is available for anonymous FTP from citi.umich.edu.

_______________________________________________________________________________

                TCP Driver Interface Specification


INTRODUCTION

The TCP driver layer, part of the CITI MacIP driver, implements the 
Transmission Control Protocol [RFC 793].  This document describes the 
program interface to the TCP layer.  Driver requests are made by 
preparing a driver parameter block and a protocol parameter block, 
and issuing a driver control call.  The driver parameter block is 
described in [CITI MacIP]. 



DATA STRUCTURES

The reader should be familiar with the common C derived types, 
such as those described in <sys/types.h>, MPW C, and Inside 
Macintosh [MAC].  All TCP datagrams are described by the TCP header [RFC 793]
described below in C:

	typedef struct tcp_header {
		u_short	tc_lport;	 	/* Source port */
		u_short	tc_fport;	  	/* Destination port */
		u_long	tc_seq;	  		/* Sequence number of packet */
		u_long	tc_ack;	 		/* Acknowledgement number of packet*/
		u_short	tc_thl : 4;		/* Total header length (long-words) */
		u_short	tc_rsv : 6;	  	/* Reserved */
		u_short	tc_flags : 6; 	/* Flag bits */
		u_short	tc_wnd;	  		/* Window size for sender */
		u_short	tc_chksum;	  	/* Packet checksum */
		u_short	tc_urg;	  		/* Urgent data pointer */
	} tcp_header_t, *tcp_header_p;

For each TCP stream, a TCP client allocates a TCP parameter block, 
described as follows:

	typedef struct tcp_param {
		struct timeval *	io_timeout;	  /* Timeout value */
		caddr_t	 	io_buffer;	  /* Pointer to data */
		caddr_t	 	io_buflen;	  /* Length of data in bytes */
		caddr_t	 	io_stream;	  /* Private TCP data */
		u_long		io_fhost;	  /* Destination IP address */
		u_short		io_fport;	  /* Destination TCP port */
		u_short		io_lport;	  /* Source TCP port */
		Boolean		io_furg;	  /* Urgent data flag */
		Boolean		io_fpush;	  /* Push data flag */
		Boolean		io_mark;	  /* At Mark */
		Boolean		io_lstasync;  /* Listen asynchronously */
		tcp_header_p	io_tcph;	  /* Raw TCP header */
		u_long		io_nclass;	  /* Class of async notification */
		u_long		io_ndata;	  /* Notification data */
		caddr_t		io_notify;	  /* Notification routine */
		u_long		io_userdata;  /* User data field */
	} tcp_param_t, *tcp_param_p;



TCP FUNCTIONS

The following functions provide a program interface to the TCP 
driver layer.  Each function has a single argument of type 
tcp_param_p and returns failure (-1) or success (non-negative).  
Error status should be examined by the client after each TCP driver 
call.

All TCP functions except tcp_listen are synchronous.  Some 
functions accept io_timeout as a parameter.  For these routines, if 
io_timeout is NULL, the function blocks forever, or until the call can 
be completed.  If io_timeout is non-NULL, the function blocks until 
the timeout value expires or the call can be completed.

TCP notifies clients of asynchronous events by executing a client 
supplied notification routine. 
Right and left arrows indicate values passed to and from the driver 
functions, respectively.

	int tcp_open(tcp_pb)
	   -> io_buffer
	   -> io_buflen
	   <- io_stream
	   -> io_lport
	   -> io_nclass
	   -> io_notify
	   -> io_userdata
	csCode TCP_OPEN_S

tcp_open creates a TCP stream.  If io_lport is non-zero, 
tcp_open binds the stream to port io_lport.  Otherwise, the client 
must call tcp_setport. 

TCP clients may specify a receive buffer pointer io_buffer.  
io_buffer must be a non-relocatable block of size io_buflen.  If 
io_buffer is NULL, TCP  will allocate an internal receive buffer

A client wishing  asynchronous notification should pass the address 
of its notification routine in io_notify.    io_userdata is client 
data passed by TCP to io_notify.    io_nclass is the set of events 
for which the client accepts notification.  It is constructed by  taking 
the bitwise  or of the notification identifiers specified under "TCP 
NOTIFICATION."


	int tcp_release(tcp_pb)
	   -> io_stream
	csCode TCP_RELEASE_S

tcp_release releases a TCP stream.  Input and output buffers are 
freed and the port is unbound.  If the stream is connected 
tcp_release aborts the connection.


	int tcp_setport(tcp_pb)
	   -> io_stream
	   -> io_lport
	csCode TCP_SETPORT_S

tcp_setport binds a port to a TCP stream.  If io_lport is zero TCP 
will assign an unused port.


	int tcp_connect(tcp_pb)
	   -> io_timeout
	   -> io_stream
	   -> io_fhost
	   -> io_fport
	csCode TCP_CONNECT_S

tcp_connect attempts to connect to io_fhost on io_fport.   If the 
connection can not be established in io_timeout TCP gives up.   
Note that the stream must have been previously bound to a port.

Once established, connections may used send and receive data (with 
tcp_put and tcp_get).


	int tcp_listen(tcp_pb)
	   -> io_timeout
	   -> io_stream
	   <> io_fhost
	   <> io_fport
	   -> io_lsnasync
	csCode TCP_LISTEN_S

tcp_listen listens for connection requests on io_stream.  

If io_fport(io_fhost) is non-zero,  connection requests are 
delivered only if they originate at the specified port(host).

If io_lsnasync is FALSE, tcp_listen blocks until a connection 
request arrives.  If no request arrives within io_timeout, 
tcp_listen returns an error.  If a connection is established, the 
foreign host and port are returned in io_fhost and io_fport.

If io_lsnasync is TRUE, tcp_listen enters a "listening" state and 
returns immediately.  If TCP receives a connection request for 
io_stream, TCP notifies the client by running the notification 
routine (specified at tcp_open).


	int tcp_abort(tcp_pb)
	   -> io_stream
	csCode TCP_ABORT_S

tcp_abort aborts a connection.  Any data in transit is lost.  
tcp_release should be called after tcp_abort to reclaim buffer 
space.


	int tcp_close(tcp_pb)
	   -> io_timeout
	   -> io_stream
	csCode TCP_CLOSE_S

tcp_close negotiates the termination of a connection.  All 
outstanding data is delivered --  i.e., clients may continue to call 
tcp_get until all input buffers are read.  If TCP cannot negotiate the 
close within io_timeout, an error is returned, but  TCP continues to 
negotiate the close.  Clients may call tcp_release after tcp_close 
to reclaim buffer space.


	int tcp_put(tcp_pb)
	   -> io_buffer
	   -> io_buflen
	   -> io_stream
	   -> io_furg
	   -> io_fpush
	csCode TCP_PUT_S

tcp_put sends io_buflen bytes of io_buffer on io_stream.

The io_fpush and io_furg flags correspond to the "data stream 
push" and "urgent data signalling" facilities of TCP; see [RFC 793].

tcp_put returns immediately; the TCP driver schedules actual data 
delivery.


	int tcp_get(tcp_pb)
	   -> io_timeout
	   <> io_buffer
	   <> io_buflen
	   -> io_stream
	   <- io_furg
	   <- io_mark
	csCode TCP_GET_S

tcp_get requests data on a TCP stream.  io_buffer points to a 
client supplied buffer.  
io_buflen specifies the length of that buffer in bytes.

tcp_get blocks until one of the following conditions occurs:
>	io_timeout expires.
		No data is returned.
>	urgent data is outstanding.
		All available data is returned (up to io_buflen).  
		io_furg is set.
>	io_buflen bytes are available.
		io_buflen bytes are returned.

On return, if io_furg is TRUE, there is outstanding urgent data on 
io_stream.  The client should  "urgently" read data from TCP until 
all urgent data has been read.  tcp_get sets io_mark TRUE when 
the last of the urgent data was "gotten."   TCP will not deliver both 
urgent and non-urgent data in the same buffer.


	int tcp_task()
	csCode TCP_TASK_S

tcp_task allots time to TCP for asynchronous processing.


	int tcp_request(tcp_pb)
	   -> io_stream
	   -> io_nclass
	csCode TCP_REQUEST_S

tcp_request adds to the set of events for which the client accepts 
notification.
io_nclass is the bitwise or of the notification identifiers specified 
under "TCP NOTIFICATION."


	int tcp_cancel(tcp_pb)
	   -> io_stream
	   -> io_nclass
	csCode TCP_REQUEST_S

tcp_cancel subtracts from the set of events for which the client 
accepts notification.


	int tcp_control(tcp_pb)
	   <>io_buffer
	   <>io_buflen
	   -> io_stream
	csCode TCP_CONTROL_S

To be specified.



TCP  NOTIFICATION

Clients may specify asynchronous events to be notified of by 
specifying  io_notify during tcp_open and by calling tcp_request 
and tcp_cancel.  Later, as asynchronous events occurr, io_notify is 
called as follows:

	int (*io_notify)(tcp_pb)
	   -> io_buflen
	   -> io_stream
	   -> io_fhost
	   -> io_fport
	   -> io_nclass
	   -> io_ndata
	   -> io_userdata

io_nclass is the type of event that caused this notification.    
io_userdata was passwed to tcp_request by the client.  
io_ndata contains additional specification for the event.

Notification routines execute in the driver's context, which is
implementation dependent.  The notification routine should assume
that a5 is not pointing to its globals, no global variables can
be accessed and no other routines may be called.

The following  describes the valid  notification classes (io_nclass).

TCP_NT_CONNECT  Connection Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_userdata
Connection notification is delivered when a connection 
is established with io_fhost on io_fport.  To receive 
connection notification, the client must be 
"listening" for connections (see tcp_listen).  


TCP_NT_DATA  Data Arrival Notification
	-> io_buflen
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_userdata
Data arrival notification is delivered when a data 
segment arrives from io_fport on io_fhost.  io_buflen 
is the number of bytes in the segment.


TCP_NT_URGENT  Urgent Data Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_userdata

Urgent data notification is delivered when there is 
outstanding urgent data somewhere in the stream. The 
notification is delivered just once -- when the 
foreign host first puts urgent data  in the stream.  
Once all urgent data has been read by the local host,
TCP will again be ready to deliver urgent data notification.
 

TCP_NT_RETRANS  Retransmit Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_userdata
The client is notified when TCP retransmits data 
destined for io_fport on io_fhost.


TCP_NT_CLOSING  Closing Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_ndata
	-> io_userdata
The client is notified when the foreign host begins 
negotiating a close a connection with io_fhost on 
io_fport.


TCP_NT_CLOSED  Closed Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_userdata
The client is notified when the connection with 
io_fhost on io_fport has been gracefully closed.


TCP_NT_ERROR  Error Notification
	-> io_stream
	-> io_fhost
	-> io_fport
	-> io_nclass
	-> io_ndata
	-> io_userdata
The client is notified when an asynchronous error, such as connection 
reset, occurs.   io_ndata  identifies the error.



References

[CITI MacIP]	"Mac IP Driver Interface Guide"  Center For Information Technology Integration, 
		University of Michigan, Ann Arbor, MI, March 1987.

[CITI TCP]	"TCP Driver Interface Specification"  Center For Information Technology Inte-
		gration, University of Michigan, Ann Arbor, MI, March 1987.

[MAC]		Inside Macintosh, Vols I-III,  Addison-Wesley, Reading, MA, November 1985.

[RFC 793]	J. Postel (ed.), "Transmission Control Protocol" RFC 793, SRI International, Men-
		lo Park, CA, December 1985.