-----------------------------------------------------------------------------
File name:	TCPCLOSE.TXT			Revision date:	1999.04.12
File author:	Ronald Andersson		Creation date:	1999.04.12
-----------------------------------------------------------------------------
The text below is intended for inclusion in the programming section of the
STinG hypertext documentation.  It describes the TCP_close enhancements.
-----------------------------------------------------------------------------

    int16  cdecl  TCP_close (int16 handle, int16 time, int16 *result_p);

NB: This prototype differs from that used by STiK, but the new STinG API
    will still work with TCP_close calls compiled for STiK or old STinG.

Function :
   Closes a TCP connection.

Argument 'time' serves a dual purpose as timeout value and mode flag.

time > 0    STiK-like delay.  'time' is the timeout value, and if it
            is exceeded without completion of TCP_close negotiation
            the function will return E_CNTIMEOUT.  Negotiation will
            then proceed internally under interrupt control. If the
            negotiation succeeds before timeout, the function returns
            E_NORMAL.  During timeout, calling program is blocked.
            This mode does not use 'result_p' (Use NULL for it).

time == 0   STiK-like without delay.  A TCP_close negotiation is
            started, which is then handled entirely by interrupt
            driven code. The function returns E_NORMAL immediately.
            This mode does not use 'result_p' (Use NULL for it).

time == -1  STinG half duplex mode. 'result_p' is stored in the
            connection struct, and will be used to return the real
            end result of the function, which immediately returns
            E_NODATA. The TCP_close negotiation is handled entirely
            by interrupt driven code, and any final result will be
            stored at the address specified by 'result_p'.  It is
            legal to use NULL for 'result_p' in which case results
            will not be stored anywhere.

Other negative values of 'time' are reserved.

For all of the above modes an internal limit of 1000 seconds is used
for the closing negotiation, and if that is exceeded the connection
will be forcibly closed at this end by interrupt driven code.  For
connections using 'result_p' this timeout will cause E_CNTIMEOUT to
be stored at the specified address.  The same will also be done with
appropriate error codes in case of network errors.

If a connection has been closed in half duplex mode and with non-NULL
'result_p' argument, then it is legal for the client/server to call
TCP_close once more, using zero for the 'time' argument.  This will
cause the 'result_p' value in the connection struct to be NULLed,
so that the interrupt routines will not write result data anywhere
when close negotiation finally completes or fails.

That special usage is needed when a client that normally uses the
'result_p' value needs to terminate, or simply to reuse the variable
for some other purpose.


Two new constants are defined in TRANSPRT.H for the 'time' modes:

TCP_IMMEDIATE   = 0
TCP_HALFDUPLEX  = -1


Usage examples:
---------------
err = TCP_close( handle, 0, NULL );  /* STiK method, no real result */
-----
err = TCP_close( handle, 5, NULL );  /* STiK method, blocking delay */
-----
/* STinG method, fully non-blocking with results as and when needed */

err = TCP_close( handle, TCP_HALFDUPLEX, &err );
now = TIMER_now();
while (err == E_NODATA && (TIMER_elapsed(now) < 5000)  && !userbreak_f)
{
...  This loop can contain anything, like an APP's main event routines
...  In this example I assume that a need to exit will set 'userbreak_f
...  and that we no longer want results if 5 seconds are exceeded.
}
if  ( userbreak_f || (TIMER_elapsed(now) >= 5000) )
{   TCP_close( handle, TCP_IMMEDIATE, NULL );
    if  ( err == E_NODATA )
        err = E_CNTIMEOUT;      /* fake E_CNTIMEOUT when 'bored' */
}
-----
The second TCP_close in the last example tells the interrupt routines
that the 'result_p' variable (here 'err') is no longer waiting for any
result.  It may then be reused by the program for other purposes, but
I suggest that some test be made first, at exit from the code above,
so that the user can be told if any network errors have occurred.


Here is the STiK TCP_close specification by Steve Adam for comparison :

  - Closes a connection.  `handle' is the connection handle.
  - Returns 0 or a negative error code.
  - timeout is the time in seconds to wait for the connection to close.
    TCP_close() must negotiate the close with the remote host, so
    it can take some time if the net is slow.  Pending data may need
    to be received and discarded before the connection closes cleanly.
  - Note that TCP_close() *must* be called in order to free memory
    that has been allocated for the connection.
  - A timeout of 0 is acceptable for immediate close.
  - If the ESC key is pressed during the timeout period, TCP_close()
    returns immediately with a E_USERTIMEOUT error code.

Note that only a dummy function is available if TCP.STX is not loaded.
This dummy always returns E_BADHANDLE.
-----------------------------------------------------------------------------
End of file:	TCPCLOSE.TXT
-----------------------------------------------------------------------------
