/* vim:set sw=4 ts=8 fileencoding=cp1251::Кодировка:WINDOWS-1251[АБЁЪЯабёъя] */
#ifdef _WIN32
    #pragma setlocale("rus")
#endif
/*
 * Copyright(C) 2010-2014 Крипто-Про, ООО
 *
 * Этот файл содержит информацию, являющуюся
 * собственностью компании Крипто-Про.
 *
 * Любая часть этого файла не может быть скопирована,
 * исправлена, переведена на другие языки,
 * локализована или модифицирована любым способом,
 * откомпилирована, передана по сети с или на
 * любую компьютерную систему без предварительного
 * заключения соглашения с компанией Крипто-Про.
 */

/*!
 * \file $RCSfile$
 * \version $Revision: 199136 $
 * \date $Date:: 2019-09-12 11:19:10 +0300#$
 * \author $Author: alexl $
 *
 * \brief Обертки имперсонализации и защиты вокруг POSIX <sys/socket.h>
 *
 */

#ifndef sup_sys_socket_h_
#define sup_sys_socket_h_

#ifdef UNIX
    #include <sys/socket.h>
#else
    #include <Winsock2.h>
#endif

#include "reader/support.h"
#include "reader/sup_errno.h"
#include "reader/sup_signal_safe.h"
#include "reader/sup_sys_types.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined MSG_NOSIGNAL
    #define SUP_MSG_NOSIGNAL MSG_NOSIGNAL
#else
    #define SUP_MSG_NOSIGNAL 0
#endif

#if !defined UNIX
    #define SUP_SHUT_RD	    SD_RECEIVE	// Disables further receive operations.
    #define SUP_SHUT_RDWR   SD_BOTH	// Disables further send and receive operations.
    #define SUP_SHUT_WR	    SD_SEND	// Disables further send operations.
#else
    #define SUP_SHUT_RD	    SHUT_RD	// Disables further receive operations.
    #define SUP_SHUT_RDWR   SHUT_RDWR	// Disables further send and receive operations.
    #define SUP_SHUT_WR	    SHUT_WR	// Disables further send operations.
#endif

#ifdef SUP_TEST_CC_CXX_
    #define t(x,y,z) x ## y ## z
	/* C99, 6.10.3, Exmpl. 5 */
    static
    int j[] = { t(1,2,3), t(,4,5), t(6,/* with comment */,7), t(8,9,),
		t(10,,), t(,11,), t(,,12), t(,,) };
    /* Должен получится результат
	int j[] = { 123, 45, 67, 89,
		    10, 11, 12, }; 
     */
#endif

	// TODO:XX socket(), а нужна ли ему обёртка?
SUPPORT_ACTUAL_NOSIG(SOCKET, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    socket, (int domain, int type, int protocol),
	    (domain, type, protocol),
	    0 <= ret,
	    (EET_FTEXT(db_ctx, "%s(%d, %d, %d) = %d fail %s(%d)"), 
	    SFUNC, domain, type, protocol, 
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(int,  /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    bind, (SOCKET asocket, const struct sockaddr *address, 
		    socklen_t address_len),
	    (asocket, address, address_len),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, ..., %d) = %d fail %s(%d)"),
	    SFUNC, asocket, /*TODO:address->sa_data,*/ address_len,
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(int, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    listen, (SOCKET asocket, int backlog),
	    (asocket, backlog),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, %d) = %d fail %s(%d)"),
	    SFUNC, asocket, backlog,
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(int, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    setsockopt, (SOCKET asocket, int level, int option_name, 
		    const SUP_SCKT_VOID *option_value, socklen_t option_len),
	    (asocket, level, option_name, option_value, option_len),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, %d, %d, 0x%p, %d) = %d fail %s(%d)"),
	    SFUNC, asocket, level, option_name, option_value, option_len,
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(int, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    getsockopt, (SOCKET asocket, int level, int option_name, 
			SUP_SCKT_VOID *SUPPORT_RESTRICT option_value, 
			socklen_t *SUPPORT_RESTRICT option_len),
	    (asocket, level, option_name, option_value, option_len),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, %d, %d, 0x%p, %p) = %d fail %s(%d)"),
	    SFUNC, asocket, level, option_name, option_value, option_len,
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(SOCKET, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    accept, (int asocket, struct sockaddr *SUPPORT_RESTRICT address,
		    socklen_t *SUPPORT_RESTRICT address_len),
	    (asocket, address, address_len),
	    0 <= ret,
	    (EET_FTEXT(db_ctx, "%s(%d, 0x%p, 0x%p) = %d fail %s(%d)"),
	    SFUNC, asocket, /*TODO:*/ address, address_len,
	    ret, SUP_STRERROR(serrno), serrno))
SUPPORT_ACTUAL_NOSIG(int, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    connect, (SOCKET asocket, const struct sockaddr *address, 
		    socklen_t address_len),
	    (asocket, address, address_len),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, ..., %d) = %d fail %s(%d)"),
	    SFUNC, asocket, /*address,*/ address_len,
	    ret, SUP_STRERROR(serrno), serrno))
#if defined UNIX
    SUPPORT_ACTUAL_NOSIG(int,  /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		socketpair, (int domain, int type, int protocol, 
			    int socket_vector[2]),
		(domain, type, protocol, socket_vector),
		0 == ret,
		(EET_FTEXT(db_ctx, "%s(%d, %d, %d, 0x%p) = %d fail %s(%d)"),
		SFUNC, domain, type, protocol, socket_vector,
		ret, SUP_STRERROR(serrno), serrno))
    SUPPORT_ACTUAL_NOSIG(SUP_SSIZE_T, 
		/* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		sendmsg, (int asocket, const struct msghdr *buffer, 
			    int flags),
		(asocket, buffer, flags),
		0 <= ret,
		(EET_FTEXT(db_ctx, "%s(%d, 0x%p, %d) = %ld fail %s(%d)"),
		SFUNC, asocket, buffer, flags,
		(long)ret, SUP_STRERROR(serrno), serrno))
    SUPPORT_ACTUAL_NOSIG(SUP_SSIZE_T, 
		/* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		recvmsg, (int asocket, struct msghdr *message, int flags),
		(asocket, message, flags),
		0 <= ret,
		(EET_FTEXT(db_ctx, "%s(%d, 0x%p, %d) = %ld fail %s(%d)"),
		SFUNC, asocket, message, flags,
		(long)ret, SUP_STRERROR(serrno), serrno))
#endif
#if defined AIX || defined DARWIN
    SUPPORT_ACTUAL_NOSIG(int, /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		getpeereid, (int s, uid_t *euid, gid_t *egid),
		(s, euid, egid),
		0 == ret,
		(EET_FTEXT(db_ctx, "%s(%d, 0x%p, 0x%p) = %d fail %s(%d)"),
		SFUNC, s, euid, egid,
		ret, SUP_STRERROR(serrno), serrno))
#endif

SUPPORT_SIMPLE_NONBLOCK(SUP_POLLIN, SOCKET, 
	    /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    accept, (SOCKET asocket, 
		    struct sockaddr *SUPPORT_RESTRICT address,
		    socklen_t *SUPPORT_RESTRICT address_len),
	    (asocket, address, address_len),
	    0 <= ret,
	    (EET_FTEXT(db_ctx, "%s(%d, 0x%p, 0x%p) = %d fail %s(%d)"),
	    SFUNC, asocket, /*TODO:*/ address, address_len,
	    ret, SUP_STRERROR(serrno), serrno))
// Для connect() нужна ли версия support_snb_connect()?
SUPPORT_SIMPLE_NONBLOCK(SUP_POLLOUT, int, 
	    /* No prefix, see C99, 6.10.3, Exmpl. 5 */,
	    getsockopt, (SOCKET asocket, int level, int option_name, 
			char *SUPPORT_RESTRICT option_value, 
			socklen_t *SUPPORT_RESTRICT option_len),
	    (asocket, level, option_name, option_value, option_len),
	    0 == ret,
	    (EET_FTEXT(db_ctx, "%s(%d, %d, %d, 0x%p, 0x%p) = %d fail %s(%d)"),
	    SFUNC, asocket, level, option_name, option_value, option_len,
	    ret, SUP_STRERROR(serrno), serrno))
#if defined UNIX
    SUPPORT_SIMPLE_NONBLOCK(SUP_POLLOUT, SUP_SSIZE_T, 
		/* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		sendmsg, (SOCKET asocket, const struct msghdr *buffer, 
			    int flags),
		(asocket, buffer, flags),
		0 <= ret,
		(EET_FTEXT(db_ctx, "%s(%d, 0x%p, %d) = %ld fail %s(%d)"),
		SFUNC, asocket, buffer, flags,
		(long)ret, SUP_STRERROR(serrno), serrno))
    //TODO: SUPPORT_SIMPLE_NONBLOCK(int,
    //TODO: 	    ioctl, (int fildes, unsigned long request, int arg),
    //TODO: 	    0 <= ret);
    SUPPORT_SIMPLE_NONBLOCK(SUP_POLLIN, SUP_SSIZE_T, 
		/* No prefix, see C99, 6.10.3, Exmpl. 5 */,
		recvmsg, (SOCKET asocket, struct msghdr *message, int flags),
		(asocket, message, flags),
		0 <= ret,
		(EET_FTEXT(db_ctx, "%s(%d, 0x%p, %d) = %ld fail %s(%d)"),
		SFUNC, asocket, message, flags,
		(long)ret, SUP_STRERROR(serrno), serrno))
#endif

#ifdef __cplusplus
}
#endif
#endif /* sup_sys_socket_h_ */
