This document describes the design and operation of the 'completion port'
abstraction used in the ssh server.  A completion port is a synchronization
mechanism which allows a thread to service several asynchronous data streams
in the order their operations complete, stalling between these completion
events.

Data structures:

    I/O context
		An I/O context holds the state necessary to access a particular
		data object or stream.  To support full duplex operation,
		an I/O context may have more than one ISB assigned to it.
		The details of each I/O context are driver specific, the
		context is returned as an opaque pointer by the driver's
		'open' function.  The pointer is then passed back to the
		driver to allow it to bind streams created by
		cport_assign_stream().  Usually the .drv field of an isb
		points directly to the I/O context.

    stream handler
		A stream handler is a table of function pointers that
		the completion port uses to perform I/O to a stream.
		Fields in a stream handler structure:
		    ftable mask
		    function table	Start I/O function table.
		    attach stream
		    detach stream
		    cancel I/O
		    

    I/O Synchronization Block (isb)
		The I/O synchronization block is a structure used to represent
		an active stream. Each isb is associated with a completion
		port object and must be created via cport_assign_stream() or
		cport_assign_channel().  An I/O stream is always in 1 of
		3 states:

		    Busy	An I/O is in progress.  To port an I/O in
				progress us the cport_cancel function.

		    Completed	The completion port has noticed an I/O
				started on the stream has finished and the
				isb is now queued for final processing and/or
				return to caller.

		    Processed	A new I/O may be started on the stream.
				

    Completion port
		The completion port object holds a database of assigned
		streams and their status.

Functions:

    cport_port cport_create_port(int flags);
	Creates a new completion port, returning it's address or NULL
        if create fails.  Flags is reserved for future use and must be zero.

	
    cport_isb cport_assign_stream(cport_port port, cport_stream_handler driver,
		void *arg1, int arg2 )
	Creates I/O synchronization block (ISB) and initializes with
	driver using driver-specific arguments arg1 and arg2.  If the
        driver initializes the ISB succesfully, the ISB is assigned to
	the specified port and returned as the function value.  If init
	fails, the isb is deallocated and NULL is returned.

    int cport last_assign_status ( cport_port port, char errmsg[256] );
	If cport_assign_stream fails, detail about the failure (status
	code and error text) saved by port for retrieval by this function.

    int cport_start_io ( cport_isb isb, int func, void *buf, int buflen );
	Initiate I/O operation on I/O context assigned to isb.  Function code
	and buf/buflen argments are driver specific.  Standard codes are
	defined for read and write (CPORT_READ, CPORT_WRITE).  If function
	value returned in odd (success), I/O is pending and isb will be
        returned via cport_next_completion after operation completed.

    cport_isb cport_next_completion ( cport_port port );
	Wait for next pending I/O to complete.

    int cport_cancel ( cport_isb isb );
	Cancel any pending I/O on the isb.  Cancelled I/O still queues
	it's completion event.

    int cport_deassign(cport_isb isb);
	Disconnect isb, and deallocate structures.

    cport_destroy ( cport_port port );
	Destroy port.  Any assigned streams are deassigned prior to 
	deallocating the port structures.

    cport_set_timeout ( cport_isb isb, int seconds, int nanoseconds );
	Set time limit on isb.  Any I/O pending on the isb at current
	time + seconds + nanoseconds will abort with a timeout status.


Driver operation:
