=head1	NAME

dktcpip - TCP and UDP client module

=head1	SYNOPSIS

=head2	DATA TYPES

The I<dk_ip_addr_t> data type stores an IP address.

The I<dk_tcpip_t> data type stores data related to a transport endpoint.

=head2	FUNCTIONS

 #include <dktcpip.h>

 int
 dktcpip_start(void);
 int
 dktcpip_end(void);
 dk_tcpip_t *
 dktcpip_new(void);
 void
 dktcpip_delete(dk_tcpip_t *p);
 int
 dktcpip_set_connectionless(dk_tcpip_t *p, int fl);
 int
 dktcpip_get_addr(dk_tcpip_t *p, int wh);
 int
 dktcpipaddr_set_ip_byname(dk_ip_addr_t *a, char *hn, dk_tcpip *p);
 int
 dktcpipaddr_set_ip_loopback(dk_ip_addr_t *a);
 int
 dktcpipaddr_set_ip_local(dk_ip_addr_t *a, dk_tcpip *p);
 int
 dktcpip_addr_set_port(dk_ip_addr_t *a, unsigned short min, unsigned short max);
 int
 dktcpip_init(dk_tcpip_t *p);
 int
 dktcpip_read(dk_tcpip_t *p, char *b, size_t *lgt);
 int
 dktcpip_write(dk_tcpip_t *p, char *b, size_t *lgt);
 int
 dktcpip_is_rdclosed(dk_tcpip_t *p);
 int
 dktcpip_closewrite(dk_tcpip_t *p);
 int
 dktcpip_down(dk_tcpip_t *p);
 int
 dktcpip_set_nonblock(dk_tcpip_t *p, int fl);
 int
 dktcpip_set_timeout(dk_tcpip_t *p, double to);
 int
 dktcpip_respond(dk_tcpip_t *p);
 int
 dktcpip_set_reuse(dk_tcpip_t *p, int fl);
 int
 dktcpip_set_keepalive(dk_tcpip_t *p, int fl);
 int
 dktcpip_get_error_code(dk_tcpip_t *p, int cl);


=head1	DESCRIPTION

The dktcpip module implements client side TCP and UDP connectivity.

For server programming you should deal with BSD sockets, TLI/XTI or
Windows sockets directly to increase performance.

Before using any of the networking functions the application must call
dktcpip_start() to initialize TCP/IP networking. If you are done with
networking call dktcpip_end(). Both function do nothing on *x systems
but call WSAStartup() and WSAEnd() on W* systems.

Use dktcpip_new() to create a new transport endpoint.

If the transport endpoint is not longer needed, call dktcpip_delete()
to free memory and release ressources.

The dktcpip_get_addr() function can be used to obtain a pointer to one
of the involved addresses to edit the address. The I<w> paramter decides
about which address pointer is returned: DK_IP_ADDR_REMOTE_WISHED for 
the remote address we want to connect to,
DK_IP_ADDR_REMOTE_FOUND for the remote address we are connected to,
DK_IP_ADDR_LOCAL_WISHED for the local address we wish to bind to and
DK_IP_ADDR_LOCAL_FOUND for the local address we are bound to.
The dktcpipaddr_set_...() functions can be used to edit addresses.

The dktcpipaddr_set_ip_byname() function sets the IP address for a host name
I<hn>.

The dktcpipaddr_set_ip_loopback() function sets the IP address to
127.0.0.1 (the local loopback address).

The dktcpipaddr_set_ip_local() function sets the IP addres to the IP address
of the primary network interface.

The dktcpipaddr_set_ip_any() function sets the I<dk_ip_addr_t> structure to
use any available IP address.

The dktcpip_addr_set_port() function sets the port number. A minimum and maximum
number can be specified.

For the most TCP clients it is usual to set the hostname/IP address and port
number of the peer (DK_IP_ADDR_REMOTE_WISHED). The OS chooses a local port and
the local IP address and binds the connection automatically to the local IP and
port.

The dktcpip_set_connectionles() function sets up a I<dk_tcpip_t> structure
for connectionless (UDP) or connection-oriented (TCP) transport,
depending on fl (flag==0: TCP, flag!=0: UDP).

The dktcpip_set_timeout() function configures a timeout in microseconds.

The dktcpip_set_nonblock() function sets a  I<dk_tcpip_t> structure into
nonblocking mode (I<fl>!=0) or blocking mode (I<fl>==0).

The dktcpip_set_reuse() function sets the SO_REUSEADDR option for the
transport endpoint if I<fl>!=0.

The dktcpip_set_broadcast() function sets the SO_BROADCAST option for the
transport endpoint if I<fl>!=0. This allows UDP transport endpoints to
send broadcast datagrams.

The dktcpip_set_keepalive() function configures the transport endpoint to
send periodic test datagrams to keep the socket alive if no data is
transmitted.

The dktcpip_up() function brings a transport endpoint ``up and running''
(makes it ready to send and receive data). The transport endpoint must be
configured for connection-oriented or connection-less transport. The local
wished address must be configured if UDP is used.
For connection-oriented transport (TCP)
the remote wished address must be configured. Calls to dktcpip_set_timeout(),
dktcpip_set_reuse(), dktcp_ip_set_broadcast() or dktcpip_set_keepalive() must
be made before dktcpip_up().

The dktcpip_read() function reads data from the transport endpoint into a
buffer. The I<*lgt> argument contains the available buffer size on function
invokation and the used buffer size after the function returns successfully.

The dktcpip_respond() function sets up the remote wished address from the
remote found address. This is useful for connectionless transport (UDP) to send
a response datagram to the sender of the last datagram received.

The dktcpip_write() function sends data over a transport endpoint. For
connectionless transport the remote wished addres must be configured before
invoking this function.

The dktcpip_closewrite() function marks up a transport endpoint
as ``no longer writable''.

The dktcpip_is_rdclosed() checks whether the peer has closed the connection.

The dktcpip_down() function shuts down a transport endpoint. For
connection-oriented transport dktcpip_closewrite() is called for an orderly
release, dktcpip_read() is called until dktcpip_is_rdclosed() returns true.

The dktcpip_get_error_code() function returns an error code for the last
error on the endpoint. If I<cl>!=0 the error condition is cleared.

=head1	RETURN VALUE

The functions return valid pointers or positive integers on success,
NULL or 0 (or negative numbers) on errors.

=head1	AUTHOR

Dirk Krause.

=head1	COPYRIGHT AND LICENSE

Copyright (c) 2007-2008, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above
   copyright notice, this list of conditions and the
   following disclaimer.

 * Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the following
   disclaimer in the documentation and/or other materials
   provided with the distribution.

 * Neither the name of the Dirk Krause nor the names of
   contributors may be used to endorse or promote products
   derived from this software without specific prior written
   permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
