#ifndef _socket_h__
#define _socket_h__

/** socket **
 * 
 * Simple and portable IP socket helper functions.
 * 
 * The main goal of this module is to simplify the opening and configuration of
 * non-blocking IP sockets using a single code base compatible with Win32 and *nix.
 * 
 * Actually, let's not kid ourselves: this is all because of Winsock ;-)
 */

#ifdef _WIN32
    #include <winsock2.h>
    #include <windows.h>
    #include <ws2tcpip.h>
    #include <iphlpapi.h>
    typedef SOCKET socket_t;
#else
    #include <sys/socket.h>
    #include <sys/select.h>
    #include <netinet/in.h>
    #include <netinet/tcp.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <ifaddrs.h>
    #include <unistd.h>
    #include <fcntl.h>
    typedef int socket_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif


/**
 * Wrapper over the socket() system call that also configures the socket as non-blocking.
 * 
 * Arguments: same as the socket() system call
 * 
 * Return: socket descriptor, or -1 if an error occurred
 */
socket_t socket_open_nonblocking(int domain, int type, int protocol);

/**
 * Wrapper over the connect() system call that also simplifies error-checking.
 * Meant to be used with non-blocking sockets.
 * 
 * Arguments: same as the connect() system call
 * 
 * Return: 0 on success, otherwise a system-specific error code is returned
 * 
 * Here an error *really* means an error. There are no special codes to indicate that
 * the non-blocking connection is pending. If the return is non-zero, there's a problem.
 */
int socket_connect_nonblocking(socket_t sock, const struct sockaddr *addr, socklen_t addrlen);


#ifdef _WIN32


/**
 * Close a socket.
 */
#define socket_close closesocket

/**
 * Set TCP options. Refer to the setsockopt() and WSAIoctl() manuals for details.
 */
int socket_set_tcp_options(socket_t sock, DWORD nodelay, DWORD keepalive, DWORD keepidle, DWORD keepintvl, DWORD keepcnt);


#else


/**
 * Close a socket.
 */
#define socket_close close

/**
 * Set TCP options. Refer to the setsockopt() manual for details.
 */
int socket_set_tcp_options(socket_t sock, int nodelay, int keepalive, int keepidle, int keepintvl, int keepcnt);


#endif


#ifdef __cplusplus
}
#endif

#endif
