/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dk3sock.ctr
*/

/*
Copyright (C) 2012-2013, Dirk Krause

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 opyright 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 author 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.
*/

/**	@file */

#ifndef DK3SOCK_H_INCLUDED
/** Avoid multiple inclusions. */
#define DK3SOCK_H_INCLUDED 1


#line 11 "dk3sock.ctr"

#include "dk3conf.h"

#if DK3_HAVE_WINSOCK2_H
#if !DK3_WINSOCK2_H_INCLUDED
#define DK3_WINSOCK2_H_INCLUDED 1
#include <winsock2.h>
#endif
#endif
#if DK3_HAVE_WS2TCPIP_H
#if !DK3_WS2TCPIP_H_INCLUDED
#define DK3_WS2TCPIP_H_INCLUDED
#include <ws2tcpip.h>
#endif
#endif
#if DK3_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if DK3_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#if DK3_HAVE_SYS_UN_H
#include <sys/un.h>
#endif

#include "dk3all.h"


#if DK3_ON_WINDOWS

/**	Data type for network sockets.
*/
typedef SOCKET	dk3_socket_t;

#else
/* if DK3_ON_WINDOWS */

/**	Data type for network sockets.
*/
typedef	int	dk3_socket_t;

#endif
/* if DK3_ON_WINDOWS */



/**	A socket set for listening or receiving datagrams.
	On systems with both IPv4 and IPv6 support we might listen
	on both the IPv4 and IPv6 address for TCP connection requests
	or UDP diagrams. So one socket is not sufficient.
*/
typedef struct {
  dk3_socket_t		*pData;		/**< Individual sockets. */
  size_t		 szMax;		/**< Allocated array size. */
  size_t		 szUsed;	/**< Sockets used in array. */
} dk3_socket_set_t;



#if !DK3_HAVE_IN_ADDR
/**	IPv4 address (host address without port number).
*/
typedef struct in_addr IN_ADDR;
#endif

#if !DK3_HAVE_IN6_ADDR
/**	IPv6 address (host address without port number).
*/
typedef struct in6_addr IN6_ADDR;
#endif



/**	Allowed IPv4 peer.
*/
typedef struct {
  IN_ADDR	ad;	/**< Network address. */
  IN_ADDR	ma;	/**< Network mask. */
} dk3_peer_ip4_t;



/**	Allowed IPv6 peer.
*/
typedef struct {
  IN6_ADDR	ad;	/**< Network address. */
  IN6_ADDR	ma;	/**< Network mask. */
} dk3_peer_ip6_t;



/**	Union containing either an IPv4 or an IPv6 allowed peer address.
*/
typedef union {
  dk3_peer_ip4_t	ip4;	/**< IPv4 allowed peer address. */
  dk3_peer_ip6_t	ip6;	/**< IPv6 allowed peer address. */
} dk3_peer_allowed_data_t;



/**	Allowed peer address structure.
*/
typedef struct {
  int		wh;		/**< What is the type, 0=IPv4, 1=IPv6. */
  dk3_peer_allowed_data_t d;	/**< Address data. */
} dk3_peer_allowed_t;



/**	Socket address large enough to hold either IPv4 or IPv6 address.
*/
#if DK3_HAVE_STRUCT_SOCKADDR_STORAGE
typedef struct sockaddr_storage		dk3_sockaddr_storage_t;
#else
typedef struct {
  struct sockaddr_in	ip4addr;	/**< IPv4 address. */
#ifdef AF_INET6
  struct sockaddr_in6	ip6addr;	/**< IPv6 address. */
#endif
}					dk3_sockaddr_storage_t;
#endif



#ifdef __cplusplus
extern "C" {
#endif

/**	Bring socket subsystem up.
	On Windows systems this function initializes the WinSock DLL.
	On other systems this function does nothing and simply indicates
	success.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_up(int *ec, dk3_app_t *app);

/**	Bring socket subsystem down.
	On Windows systems this function cleans up after using the
	WinSock DLL. On other system this function does nothing and
	indicates success.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_down(int *ec, dk3_app_t *app);

/**	Convert IPv4 or IPv6 address to socket address.
	@param	af	Address family (AF_INET or AF_INET6).
	@param	hn	IP address, 8-bit char string.
	@param	addr	Address structure to fill, must be of
	type struct in_addr / IN_ADDR for af==AF_INET or
	struct in6_addr / IN6_ADDR for af==AF_INET6.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_inet_pton(
  int		 af,
  char const	*hn,
  void		*addr,
  int		*ec,
  dk3_app_t	*app
);

/**	Convert IPv4 or IPv6 address to socket address.
	@param	af	Address family (AF_INET or AF_INET6).
	@param	hn	IP address, portable string.
	@param	addr	Address structure to fill, must be of
	type struct in_addr / IN_ADDR for af==AF_INET or
	struct in6_addr / IN6_ADDR for af==AF_INET6.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_dkchar_inet_pton(
  int		 af,
  dkChar const	*hn,
  void		*addr,
  int		*ec,
  dk3_app_t	*app
);

#if DK3_HAVE_STRUCT_SOCKADDR_UN
/**	Find current length of UNIX domain socket address (UNIX/Linux only).
	@param	p	Pointer to address.
	@return	Address length.
*/
size_t
dk3socket_un_length(struct sockaddr_un const *p);

/**	Create a UNIX domain listener socket (UNIX/Linux only).
	This is a server socket listening on a UNIX domain socket
	for incoming connection requests.
	@param	fn	File name, length must be less than 108.
	@param	backlog	Number of connection attempts in backlog.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid file descriptr on success, INVALID_SOCKET on error.
*/
dk3_socket_t
dk3socket_un_listener(char const *fn, int backlog, int *ec, dk3_app_t *app);

/**	Create UNIX domain listener socket set (UNIX/Linux only).
	The returned set typically contains one socket.
	@param	fn	File name, length must be less than 108.
	@param	backlog	Number of connection attempts in backlog.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Pointer to new socket set on success, NULL on error.
*/
dk3_socket_set_t *
dk3socket_un_listeners(char const *fn, int backlog, int *ec, dk3_app_t *app);

/**	Connect via UNIX domain socket.
	This function creates a client-side socket, connected to a
	server process.
	@param	fn	File name for socket.
	@param	nsecs	Timeout in seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid socket on success, INVALID_SOCKET on error.
*/
dk3_socket_t
dk3socket_un_stream_client(
  char const	*fn,
  long		 nsecs,
  long		 usecs,
  int		*ec,
  dk3_app_t	*app
);

#endif

/**	Check socket for validity.
	@param	so	Socket to check.
	@return	1 if socket is valid, 0 for an invalid socket.
*/
int
dk3socket_check(dk3_socket_t so);

/**	Return value to mark socket as invalid.
	@return	Value to mark socket as invalid.
*/
dk3_socket_t
dk3socket_invalid(void);

/**	Open a socket. This is a wrapper around the socket() function
	from the BSD socket API.
	@param	af	Address family.
	@param	tp	Socket type (stream or datagram).
	@param	pr	Socket protocol (typically 0).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	New socket on success, INVALID_SOCKET on error.
*/
dk3_socket_t
dk3socket_open(
  int		 af,
  int		 tp,
  int		 pr,
  int		*ec,
  dk3_app_t	*app
);

/**	Open a TCP client socket and connect it to a server.
	If the @arg sh parameter is NULL, the function connects to
	the local host.
	@param	sh	Server host name, 8-bit character string.
	@param	sp	Server port.
	@param	lp	Local port number, 0 for any.
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid socket on success, INVALID_SOCKET on error.
	On success the socket is ready to be used for sending and
	receiving data.
*/
dk3_socket_t
dk3socket_open_net_stream_client(
  char const		*sh,
  unsigned short	 sp,
  unsigned short	 lp,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app
);

/**	Open a client socket and connect it to a server.
	If the @arg sh parameter is NULL, the function connects to the
	local host.
	@param	sh	Server host name, portable string.
	@param	sp	Server port.
	@param	lp	Local port number, 0 for any.
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid socket on success, INVALID_SOCKET on error.
*/
dk3_socket_t
dk3socket_dkchar_open_net_stream_client(
  dkChar const		*sh,
  unsigned short	 sp,
  unsigned short	 lp,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app
);

/**	Bind socket to local address.
	This function is a wrapper around the bind() function from the
	BSD sockets API.
	@param	sock	Socket to bind.
	@param	pAddr	Pointer to address buffer.
	@param	szAddr	Address buffer size.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_bind(
  dk3_socket_t		 sock,
  struct sockaddr const	*pAddr,
  size_t		 szAddr,
  int			*ec,
  dk3_app_t		*app
);

/**	Connect a socket in known blocking/non-blocking state to a server.
	This is a wrapper around the
	connect() function from the BSD sockets API.
	@param	so	Socket to connect.
	@param	pAddr	Server address.
	@param	szAddr	Size of server address.
	@param	secs	Seconds in timeout (ignored if spnb==0).
	@param	usecs	Microseconds in timeout (ignored if spnb==0).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	str	Descriptive string for server.
	@param	spnb	Flag: Use nb value.
	Note: The spnb flag is used on Windows systems only, on other
	systems we use fcntl() to check for blocking/non-blocking mode.
	@param	nb	Flag: Socket in non-blocking mode.
	Note: The nb flag is used on Windows systems only, on other systems
	we use fcntl() to check for blocking/non-blocking mode.
	@return	1 on success, 0 on error.
*/
int
dk3socket_connect_spnb(
  dk3_socket_t		 so,
  struct sockaddr const	*pAddr,
  size_t		 szAddr,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app,
  dkChar const		*str,
  int			 spnb,
  int			 nb
);

/**	Connect a socket to a server. This is a wrapper around the
	connect() function from the BSD sockets API.
	@param	so	Socket to connect.
	@param	pAddr	Server address.
	@param	szAddr	Size of server address.
	@param	secs	Seconds in timeout (ignored on Windows).
	@param	usecs	Microseconds in timeout (ignored on Windows).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	str	Descriptive string for server.
	@return	1 on success, 0 on error.
*/
int
dk3socket_connect(
  dk3_socket_t		 so,
  struct sockaddr const	*pAddr,
  size_t		 szAddr,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app,
  dkChar const		*str
);

/**	Connect a socket in known blocking/non-blocking state to a server.
	This is a wrapper around the
	connect() function from the BSD sockets API.
	@param	so	Socket to connect.
	@param	pAddr	Server address.
	@param	szAddr	Size of server address.
	@param	secs	Seconds in timeout.
	@param	usecs	Microseconds in timeout.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	str	Descriptive string for server.
	@param	nb	Flag: Socket in non-blocking mode.
	Note: The nb flag is used on Windows systems only, on other systems
	we use fcntl() to check for blocking/non-blocking mode.
	@return	1 on success, 0 on error.
*/
int
dk3socket_connect_nb(
  dk3_socket_t		 so,
  struct sockaddr const	*pAddr,
  size_t		 szAddr,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app,
  dkChar const		*str,
  int			 nb
);


/**	Listen on a socket. This function is a wrapper around the listen()
	function from the BSD sockets API.
	@param	so	Socket to use for listening.
	@param	bl	Backlog (number of connection attempts queued).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_listen(
  dk3_socket_t	 so,
  int		 bl,
  int		*ec,
  dk3_app_t	*app
);

/**	Accept a new client connection. This is a wrapper around the
	accept() function from the BSD sockets API.
	@param	ls	Listener socket.
	@param	pAddr	Pointer to address buffer (may be NULL).
	@param	pSzAddr	Pointer to address size (in/out).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid socket on success, -1 (INVALID_SOCKET) on error.
*/
dk3_socket_t
dk3socket_accept(
  dk3_socket_t		 ls,
  struct sockaddr	*pAddr,
  size_t		*pSzAddr,
  int			*ec,
  dk3_app_t		*app
);

/**	Send data. This is a wrapper around the send() function from the
	BSD sockets API.
	@param	so	Socket.
	@param	bu	Buffer pointer.
	@param	sz	Buffer size in bytes.
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Number of bytes sent.
*/
int
dk3socket_send(
  dk3_socket_t	 so,
  void const	*bu,
  size_t	 sz,
  long		 secs,
  long		 usecs,
  int		*ec,
  dk3_app_t	*app
);

/**	Send datagram. This is a wrapper around the sendto() function from
	the BSD sockets API.
	@param	so	Socket.
	@param	bu	Buffer pointer.
	@param	sz	Buffer size in bytes.
	@param	pAddr	Pointer to destination address buffer.
	@param	szAddr	Size of destination address.
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Number of bytes sent.
*/
int
dk3socket_sendto(
  dk3_socket_t		 so,
  void			*bu,
  size_t		 sz,
  struct sockaddr const	*pAddr,
  size_t		 szAddr,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app
);

/**	Receive data. This is a wrapper around the recv() function from
	the BSD sockets API.
	@param	so	Socket.
	@param	bu	Buffer pointer.
	@param	sz	Buffer size in bytes.
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Number of bytes received.
*/
int
dk3socket_recv(
  dk3_socket_t	 so,
  void		*bu,
  size_t	 sz,
  long		 secs,
  long		 usecs,
  int		*ec,
  dk3_app_t	*app
);

/**	Receive datagram. This is a wrapper around the recvfrom() function
	from the BSD sockets API.
	@param	so	Socket.
	@param	bu	Buffer pointer.
	@param	sz	Buffer size in bytes.
	@param	pAddr	Pointer to address buffer for remote address.
	@param	pSzAddr	Pointer to address size (in/out).
	@param	secs	Timeout seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Number of bytes received.
*/
int
dk3socket_recvfrom(
  dk3_socket_t		 so,
  void			*bu,
  size_t		 sz,
  struct sockaddr	*pAddr,
  size_t		*pSzAddr,
  long			 secs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app
);

/**	Shut down a socket. This is a wrapper around the shutdown() function
	from the BSD sockets API.
	@param	so	Socket to shut down.
	@param	sv	Shutdown type DK3_TCPIP_SHUTDOWN_xxx,
	see @ref shutdownvalues.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_shutdown(dk3_socket_t so, int sv, int *ec, dk3_app_t *app);

/**	Prepare an IPv4 address for localhost.
	@param sp	Socket address pointer.
*/
void
dk3socket_ip4addr_set_localhost(struct sockaddr_in *sp);

/**	Convert IPv4 address to text buffer.
	@param	dp	Destination buffer pointer.
	@param	szdp	Size of destination buffer (number of dkChar).
	@param	ia4	Address to convert.
	@return	1 on success, 0 on error.
*/
int
dk3socket_ip4addr_to_text(dkChar *dp, size_t szdp, IN_ADDR *ia4);

#if DK3_HAVE_STRUCT_SOCKADDR_IN6

/**	Prepare an IPv6 address for localhost (only if IPv6 support is
	available).
	@param	sp	Socket address pointer.
*/
void
dk3socket_ip6addr_set_localhost(struct sockaddr_in6 *sp);

/**	Convert IPv6 address to text buffer.
	@param	dp	Destination buffer pointer.
	@param	szdp	Size of destination buffer (number of dkChar).
	@param	ia6	Address to convert.
	@return	1 on success, 0 on error.
*/
int
dk3socket_ip6addr_to_text(dkChar *dp, size_t szdp, IN6_ADDR *ia6);

#endif

/**	Convert IP address to dkChar text.
	@param	dp	Destination buffer pointer.
	@param	szdp	Size of @a dp (number of elements).
	@param	ia	Internet address (IPv4 or IPv6).
	@param	sz	Address length.
	@return	1 on success, 0 on error.
*/
int
dk3socket_ipaddr_to_text(dkChar *dp, size_t szdp, void *ia, size_t sz);

/**	Set re-use flag for socket.
	@param	so	Socket to modify.
	@param	v	New flag value (non-zero/zero).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_set_reuse(dk3_socket_t so, int v, int *ec, dk3_app_t *app);

/**	Set socket to non-blocking mode.
	@param	so	Socket to modify.
	@param	v	New non-block value (non-zero/zero).
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_set_non_block(dk3_socket_t so, int v, int *ec, dk3_app_t *app);

/**	Retrieve non-block status for a socket.
	On Windows systems this function always returns an error,
	as ioctlsocket() can be used to set/reset non-blocking behaviour,
	but not to check it.
	@param	so	Socket to test.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 for non-blocking, 0 for blocking, -1 for error.
*/
int
dk3socket_get_non_block(dk3_socket_t so, int *ec, dk3_app_t *app);

/**	Close socket.
	@param	so	Socket to close.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_close(
  dk3_socket_t	 so,
  int		*ec,
  dk3_app_t	*app
);

/**	Allocate memory for a socket set.
	@param	sz	Maximum number of sockets in set.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	APplication structure for diagnostics, may be NULL.
	@return	Pointer to new socket set on success, NULL on error.
*/
dk3_socket_set_t *
dk3socket_set_new(
  size_t		 sz,
  int			*ec,
  dk3_app_t		*app
);

/**	Release memory for socket set. This function only releases memory,
	it does not close the sockets.
	@param	ps	Socket set to close.
*/
void
dk3socket_set_delete(dk3_socket_set_t	*ps);

/**	Close socket set (close all sockets, release memory).
	@param	ps	Socket set to close.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
*/
void
dk3socket_set_close(dk3_socket_set_t *ps, int *ec, dk3_app_t *app);

/**	Open a socket set to listen on a TCP port.
	On systems with IPv4 and IPv6 support we might need more than
	one socket to listen on both IPv4 and IPv6 addresses.
	@param	portno	TCP port number in host representation.
	@param	backlog	Listener backlog.
	@param	fLocalOnly	Flag: Listen on local loopback interfaces only.
	By default the socket set will listen on any address.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for  diagnostics, may be NULL.
	@return	Pointer to new socket set on success, NULL on error.
*/
dk3_socket_set_t *
dk3socket_listeners(
  unsigned short	 portno,
  int			 backlog,
  int			 fLocalOnly,
  int			*ec,
  dk3_app_t		*app
);

/**	Accept an incoming connection request on a listener socket set.
	@param	ss	Socket set.
	@param	pAddr	Buffer for peer address, may be NULL.
	@param	pSzAddr	Buffer for peer address size (in+out), may be NULL.
	When entering the function this parameter must be set to the
	available buffer size. On output it is set to the used buffer
	size on success.
	@param	iAllowed	Iterator through storage of allowed peer.
	@param	skipDenied	Continue silently after rejecting a denied
	client.
	addresses. The storage must have dk3socket_compare_peer() set
	as comparison function.
	@param	nsecs	Timeout in seconds.
	@param	usecs	Timeout microseconds.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Valid socket on success, INVALID_SOCKET on error.
*/
dk3_socket_t
dk3socket_set_accept(
  dk3_socket_set_t	*ss,
  struct sockaddr	*pAddr,
  size_t		*pSzAddr,
  dk3_sto_it_t		*iAllowed,
  int			 skipDenied,
  long			 nsecs,
  long			 usecs,
  int			*ec,
  dk3_app_t		*app
);

/**	Open a socket set for UDP traffic. On systems with both IPv4 and
	IPv6 addresses we might need more than one socket to listen on
	all addresses.
	@param	portno	TCP port number in host representation.
	@param	fLocalOnly	Flag: Listen on local loopback interfaces only.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for  diagnostics, may be NULL.
	@return	Pointer to new socket set on success, NULL on error.
*/
dk3_socket_set_t *
dk3socket_datagram_sockets(
  unsigned short	 portno,
  int			 fLocalOnly,
  int			*ec,
  dk3_app_t		*app
);

/**	Fill data for allowed peer (8-bit character text version).
	@param	dp	Destination peer data.
	@param	sr	Source string, typically from configuration file.
	The string contains an allowed client address, either IP
	address (preferred) or host name. Optionally you can
	add a network mask as IP address or number of bits.
	Use a slash to separate address and mask.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_set_peer(
  dk3_peer_allowed_t	*dp,
  char const		*sr,
  int			*ec,
  dk3_app_t		*app
);

/**	Fill data for allowed peer (portable text version).
	@param	dp	Destination peer data.
	@param	sr	Source string, typically from configuration file.
	The string contains an allowed client address, either IP
	address (preferred) or host name. Optionally you can
	add a network mask as IP address or number of bits.
	Use a slash to separate address and mask.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	1 on success, 0 on error.
*/
int
dk3socket_dkchar_set_peer(
  dk3_peer_allowed_t	*dp,
  dkChar const		*sr,
  int			*ec,
  dk3_app_t		*app
);

/**	Compare two allowed peer structures. You can use this function
	as comparison function for a dk3_sto_t containing information
	about all allowed clients.
	@param	l	Left peer object.
	@param	r	Right peer object.
	@param	cr	Comparison criteria (0=peer/peer, 1=peer/sockaddr).
	@return	Comparison result.
*/
int
dk3socket_compare_peer(void *l, void *r, int cr);

/**	Report error from opening a socket.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_socket(int *ec, dk3_app_t *app, int err);

/**	Report error from binding a socket.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
	@param	lat	Local address as text, may be NULL.
*/
void
dk3socket_error_bind(int *ec, dk3_app_t *app, int err, dkChar const *lat);

/**	Report error from connect attempt.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
	@param	str	String describing connection target.
*/
void
dk3socket_error_connect(int *ec, dk3_app_t *app, int err, dkChar const *str);

/**	Report error from listen attempt.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_listen(int *ec, dk3_app_t *app, int err);

/**	Report error from closing a socket.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_close(int *ec, dk3_app_t *app, int err);

/**	Report error from send attempt.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_send(int *ec, dk3_app_t *app, int err);

/**	Report error from receive attempt.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_recv(int *ec, dk3_app_t *app, int err);

/**	Report error from accepting a connection.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_accept(int *ec, dk3_app_t *app, int err);

/**	Report error from shutting down a socket.
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_shutdown(int *ec, dk3_app_t *app, int err);

/**	Report error from inet_pton().
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_inet_pton(int *ec, dk3_app_t *app, int err);

/**	Report error from getaddrinfo().
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_getaddrinfo(int *ec, dk3_app_t *app, int err);

/**	Report error from gethostbyname().
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
	@param	hn	Host name for error.
*/
void
dk3socket_error_gethostbyname(int *ec, dk3_app_t *app, int err, char const *hn);

/**	Report error from setsockopt().
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_setsockopt(int *ec, dk3_app_t *app, int err);


/**	Report error from select().
	@param	ec	Pointer to error code variable, may be NULL.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	err	Error code to report.
*/
void
dk3socket_error_select(int *ec, dk3_app_t *app, int err);

/**	Eat up input (for orderly release).
	@param	so	Socket to clean up.
	@param	app	Application structure for diagnostics, may be NULL.
*/
void
dk3socket_eat_input(dk3_socket_t so, dk3_app_t *app);

#ifdef __cplusplus
}
#endif


#if !DK3_ON_WINDOWS
#ifndef INVALID_SOCKET
/**	Invalid socket.
*/
#define	INVALID_SOCKET	(-1)
#endif
#endif



#if DK3_ON_WINDOWS
/**	On Windows retrieve error codes using WSAGetLastError().
*/
#define	dk3socket_error(x) WSAGetLastError()
#else
/**	On non-Windows systems retrieve error codes from the
	usual places.
*/
#define	dk3socket_error(x) x
#endif



#endif
