/**
 * @file large_fd_set.c
 *
 * @brief Macro's and functions for manipulation of large file descriptor sets.
 */


#include <net-snmp/net-snmp-config.h>

#include <stdio.h>
#include <string.h> /* memset(), which is invoked by FD_ZERO() */

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif

#include <net-snmp/library/snmp_assert.h>
#include <net-snmp/library/large_fd_set.h>


#if !defined(cygwin) && defined(HAVE_WINSOCK_H)

#define LFD_SET(n, p)    FD_SET(n, p)
#define LFD_CLR(n, p)    FD_CLR(n, p)
#define LFD_ISSET(n, p)  FD_ISSET(n, p)

void
netsnmp_large_fd_setfd(SOCKET fd, netsnmp_large_fd_set * fdset)
{
    unsigned        i;

    netsnmp_assert(fd != INVALID_SOCKET);

    if (fdset->lfs_set.fd_count == fdset->lfs_setsize)
        netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1));

    for (i = 0; i < fdset->lfs_set.fd_count; i++) {
        if (fdset->lfs_set.fd_array[i] == (SOCKET) (fd))
            break;
    }

    if (i == fdset->lfs_set.fd_count
        && fdset->lfs_set.fd_count < fdset->lfs_setsize) {
        fdset->lfs_set.fd_count++;
        fdset->lfs_set.fd_array[i] = fd;
    }
}

void
netsnmp_large_fd_clr(SOCKET fd, netsnmp_large_fd_set * fdset)
{
    unsigned        i;

    netsnmp_assert(fd != INVALID_SOCKET);

    for (i = 0; i < fdset->lfs_set.fd_count; i++) {
        if (fdset->lfs_set.fd_array[i] == fd) {
            while (i < fdset->lfs_set.fd_count - 1) {
                fdset->lfs_set.fd_array[i] =
                    fdset->lfs_set.fd_array[i + 1];
                i++;
            }
            fdset->lfs_set.fd_count--;
            break;
        }
    }
}

int
netsnmp_large_fd_is_set(SOCKET fd, netsnmp_large_fd_set * fdset)
{
    unsigned int    i;

    netsnmp_assert(fd != INVALID_SOCKET);

    for (i = 0; i < fdset->lfs_set.fd_count; i++) {
        if (fdset->lfs_set.fd_array[i] == fd)
            return 1;
    }
    return 0;
}

#else

/*
 * Recent versions of glibc trigger abort() if FD_SET(), FD_CLR() or
 * FD_ISSET() is invoked with n >= FD_SETSIZE. Hence these replacement macros.
 */
#define LFD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |=  (1ULL << ((n) % NFDBITS)))
#define LFD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1ULL << ((n) % NFDBITS)))
#define LFD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] &   (1ULL << ((n) % NFDBITS)))

void
netsnmp_large_fd_setfd(int fd, netsnmp_large_fd_set * fdset)
{
    netsnmp_assert(fd >= 0);

    while (fd >= (int)fdset->lfs_setsize)
        netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1));

    LFD_SET(fd, fdset->lfs_setptr);
}

void
netsnmp_large_fd_clr(int fd, netsnmp_large_fd_set * fdset)
{
    netsnmp_assert(fd >= 0);

    if ((unsigned)fd < fdset->lfs_setsize)
        LFD_CLR(fd, fdset->lfs_setptr);
}

int
netsnmp_large_fd_is_set(int fd, netsnmp_large_fd_set * fdset)
{
    netsnmp_assert(fd >= 0);

    return ((unsigned)fd < fdset->lfs_setsize &&
            LFD_ISSET(fd, fdset->lfs_setptr));
}

#endif

void
netsnmp_large_fd_set_init(netsnmp_large_fd_set * fdset, int setsize)
{
    fdset->lfs_setsize = 0;
    fdset->lfs_setptr  = NULL;
#if !defined(cygwin) && defined(HAVE_WINSOCK_H)
    fdset->lfs_set.fd_count = 0;
#endif
    netsnmp_large_fd_set_resize(fdset, setsize);
}

int
netsnmp_large_fd_set_select(int numfds, netsnmp_large_fd_set *readfds,
                     netsnmp_large_fd_set *writefds,
                     netsnmp_large_fd_set *exceptfds,
                     struct timeval *timeout)
{
#if defined(cygwin) || !defined(HAVE_WINSOCK_H)
    /* Bit-set representation: make sure all fds have at least size 'numfds'. */
    if (readfds && readfds->lfs_setsize < numfds)
        netsnmp_large_fd_set_resize(readfds, numfds);
    if (writefds && writefds->lfs_setsize < numfds)
        netsnmp_large_fd_set_resize(writefds, numfds);
    if (exceptfds && exceptfds->lfs_setsize < numfds)
        netsnmp_large_fd_set_resize(exceptfds, numfds);
#else
    /* Array representation: no resizing is necessary. */
#endif

    return select(numfds,
            readfds ? readfds->lfs_setptr : NULL,
            writefds ? writefds->lfs_setptr : NULL,
            exceptfds ? exceptfds->lfs_setptr : NULL,
            timeout);
}

int
netsnmp_large_fd_set_resize(netsnmp_large_fd_set * fdset, int setsize)
{
    int             fd_set_bytes;

    if (fdset->lfs_setsize == setsize)
        goto success;

    if (setsize > FD_SETSIZE) {
        fd_set_bytes = NETSNMP_FD_SET_BYTES(setsize);
        if (fdset->lfs_setsize > FD_SETSIZE) {
            fdset->lfs_setptr = realloc(fdset->lfs_setptr, fd_set_bytes);
            if (!fdset->lfs_setptr)
                goto out_of_mem;
        } else {
            fdset->lfs_setptr = malloc(fd_set_bytes);
            if (!fdset->lfs_setptr)
                goto out_of_mem;
            *fdset->lfs_setptr = fdset->lfs_set;
        }
    } else {
        if (fdset->lfs_setsize > FD_SETSIZE) {
            fdset->lfs_set = *fdset->lfs_setptr;
            free(fdset->lfs_setptr);
        }
        fdset->lfs_setptr = &fdset->lfs_set;
    }

#if defined(cygwin) || !defined(HAVE_WINSOCK_H)
    /*
     * Unix: when enlarging, clear the file descriptors defined in the
     * resized *fdset but that were not defined in the original *fdset.
     */
    if ( fdset->lfs_setsize == 0 && setsize == FD_SETSIZE ) {
        /* In this case we can use the OS's FD_ZERO */
        FD_ZERO(fdset->lfs_setptr);
    } else {
        int             i;

        for (i = fdset->lfs_setsize; i < setsize; i++)
            LFD_CLR(i, fdset->lfs_setptr);
    }
#endif

    fdset->lfs_setsize = setsize;
#if !defined(cygwin) && defined(HAVE_WINSOCK_H)
    if (setsize < fdset->lfs_set.fd_count)
        fdset->lfs_set.fd_count = setsize;
#endif
success:
    return 1;

out_of_mem:
    fdset->lfs_setsize = 0;
#if !defined(cygwin) && defined(HAVE_WINSOCK_H)
    fdset->lfs_set.fd_count = 0;
#endif
    return 0;
}

void
netsnmp_large_fd_set_cleanup(netsnmp_large_fd_set * fdset)
{
    netsnmp_large_fd_set_resize(fdset, 0);
    fdset->lfs_setsize = 0;
    fdset->lfs_setptr  = 0;
}

void
netsnmp_copy_fd_set_to_large_fd_set(netsnmp_large_fd_set * dst,
                                    const fd_set * src)
{
    netsnmp_large_fd_set_resize(dst, FD_SETSIZE);
    *dst->lfs_setptr = *src;
}

int
netsnmp_copy_large_fd_set_to_fd_set(fd_set * dst,
                                    const netsnmp_large_fd_set * src)
{
    /* Report failure if *src is larger than FD_SETSIZE. */
    if (src->lfs_setsize > FD_SETSIZE) {
        FD_ZERO(dst);
        return -1;
    }

    *dst = *src->lfs_setptr;

#if !(!defined(cygwin) && defined(HAVE_WINSOCK_H))
    {
        int             i;

        /* Unix: clear any file descriptors defined in *dst but not in *src. */
        for (i = src->lfs_setsize; i < FD_SETSIZE; ++i)
            FD_CLR(i, dst);
    }
#endif

    return 0;
}
