Blame src/microhttpd/mhd_itc.h

Packit 875988
/*
Packit 875988
  This file is part of libmicrohttpd
Packit 875988
  Copyright (C) 2016 Karlson2k (Evgeny Grin)
Packit 875988
Packit 875988
  This library is free software; you can redistribute it and/or
Packit 875988
  modify it under the terms of the GNU Lesser General Public
Packit 875988
  License as published by the Free Software Foundation; either
Packit 875988
  version 2.1 of the License, or (at your option) any later version.
Packit 875988
Packit 875988
  This library is distributed in the hope that it will be useful,
Packit 875988
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
  Lesser General Public License for more details.
Packit 875988
Packit 875988
  You should have received a copy of the GNU Lesser General Public
Packit 875988
  License along with this library; if not, write to the Free Software
Packit 875988
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 875988
Packit 875988
*/
Packit 875988
Packit 875988
/**
Packit 875988
 * @file microhttpd/mhd_itc.h
Packit 875988
 * @brief  Header for platform-independent inter-thread communication
Packit 875988
 * @author Karlson2k (Evgeny Grin)
Packit 875988
 * @author Christian Grothoff
Packit 875988
 *
Packit 875988
 * Provides basic abstraction for inter-thread communication.
Packit 875988
 * Any functions can be implemented as macro on some platforms
Packit 875988
 * unless explicitly marked otherwise.
Packit 875988
 * Any function argument can be skipped in macro, so avoid
Packit 875988
 * variable modification in function parameters.
Packit 875988
 */
Packit 875988
#ifndef MHD_ITC_H
Packit 875988
#define MHD_ITC_H 1
Packit 875988
#include "mhd_itc_types.h"
Packit 875988
Packit 875988
#include <fcntl.h>
Packit 875988
Packit 875988
#ifndef MHD_PANIC
Packit 875988
#  include <stdio.h>
Packit 875988
#  include <stdlib.h>
Packit 875988
/* Simple implementation of MHD_PANIC, to be used outside lib */
Packit 875988
#  define MHD_PANIC(msg) do { fprintf (stderr,           \
Packit 875988
     "Abnormal termination at %d line in file %s: %s\n", \
Packit 875988
     (int)__LINE__, __FILE__, msg); abort();} while(0)
Packit 875988
#endif /* ! MHD_PANIC */
Packit 875988
Packit 875988
#if defined(_MHD_ITC_EVENTFD)
Packit 875988
Packit 875988
/* **************** Optimized GNU/Linux ITC implementation by eventfd ********** */
Packit 875988
#include <sys/eventfd.h>
Packit 875988
#include <stdint.h>      /* for uint64_t */
Packit 875988
#ifdef HAVE_UNISTD_H
Packit 875988
#include <unistd.h>      /* for read(), write(), errno */
Packit 875988
#endif /* HAVE_UNISTD_H */
Packit 875988
#ifdef HAVE_STRING_H
Packit 875988
#include <string.h> /* for strerror() */
Packit 875988
#endif
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Initialise ITC by generating eventFD
Packit 875988
 * @param itc the itc to initialise
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_init_(itc) (-1 != ((itc).fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK)))
Packit 875988
Packit 875988
/**
Packit 875988
 * Get description string of last errno for itc operations.
Packit 875988
 */
Packit 875988
#define MHD_itc_last_strerror_() strerror(errno)
Packit 875988
Packit 875988
/**
Packit 875988
 * Internal static const helper for MHD_itc_activate_()
Packit 875988
 */
Packit 875988
static const uint64_t _MHD_itc_wr_data = 1;
Packit 875988
Packit 875988
/**
Packit 875988
 * Activate signal on @a itc
Packit 875988
 * @param itc the itc to use
Packit 875988
 * @param str ignored
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_activate_(itc, str) \
Packit 875988
  ((write((itc).fd, (const void*)&_MHD_itc_wr_data, 8) > 0) || (EAGAIN == errno))
Packit 875988
Packit 875988
/**
Packit 875988
 * Return read FD of @a itc which can be used for poll(), select() etc.
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of read side
Packit 875988
 */
Packit 875988
#define MHD_itc_r_fd_(itc) ((itc).fd)
Packit 875988
Packit 875988
/**
Packit 875988
 * Return write FD of @a itc
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of write side
Packit 875988
 */
Packit 875988
#define MHD_itc_w_fd_(itc) ((itc).fd)
Packit 875988
Packit 875988
/**
Packit 875988
 * Clear signaled state on @a itc
Packit 875988
 * @param itc the itc to clear
Packit 875988
 */
Packit 875988
#define MHD_itc_clear_(itc)                  \
Packit 875988
  do { uint64_t __b; int __r;                \
Packit 875988
       __r = read((itc).fd, &__b, sizeof(__b)); \
Packit 875988
       (void)__r; } while(0)
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy previously initialised ITC
Packit 875988
 * @param itc the itc to destroy
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_destroy_(itc) ((0 != close ((itc).fd)) || (EBADF != errno))
Packit 875988
Packit 875988
/**
Packit 875988
 * Check whether ITC has valid value.
Packit 875988
 *
Packit 875988
 * Macro check whether @a itc value is valid (allowed),
Packit 875988
 * macro does not check whether @a itc was really initialised.
Packit 875988
 * @param itc the itc to check
Packit 875988
 * @return boolean true if @a itc has valid value,
Packit 875988
 *         boolean false otherwise.
Packit 875988
 */
Packit 875988
#define MHD_ITC_IS_VALID_(itc)  (-1 != ((itc).fd))
Packit 875988
Packit 875988
/**
Packit 875988
 * Set @a itc to invalid value.
Packit 875988
 * @param itc the itc to set
Packit 875988
 */
Packit 875988
#define MHD_itc_set_invalid_(itc) ((itc).fd = -1)
Packit 875988
Packit 875988
Packit 875988
#elif defined(_MHD_ITC_PIPE)
Packit 875988
Packit 875988
/* **************** Standard UNIX ITC implementation by pipe ********** */
Packit 875988
Packit 875988
#if defined(HAVE_PIPE2_FUNC) && defined(HAVE_FCNTL_H)
Packit 875988
#  include <fcntl.h>     /* for O_CLOEXEC, O_NONBLOCK */
Packit 875988
#endif /* HAVE_PIPE2_FUNC && HAVE_FCNTL_H */
Packit 875988
#ifdef HAVE_UNISTD_H
Packit 875988
#include <unistd.h>      /* for read(), write(), errno */
Packit 875988
#endif /* HAVE_UNISTD_H */
Packit 875988
#ifdef HAVE_STRING_H
Packit 875988
#include <string.h> /* for strerror() */
Packit 875988
#endif
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Initialise ITC by generating pipe
Packit 875988
 * @param itc the itc to initialise
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#ifdef HAVE_PIPE2_FUNC
Packit 875988
#  define MHD_itc_init_(itc) (!pipe2((itc).fd, O_CLOEXEC | O_NONBLOCK))
Packit 875988
#else  /* ! HAVE_PIPE2_FUNC */
Packit 875988
#  define MHD_itc_init_(itc)              \
Packit 875988
     ( (!pipe((itc).fd)) ?                \
Packit 875988
         (MHD_itc_nonblocking_((itc)) ?   \
Packit 875988
           (!0) :                         \
Packit 875988
           (MHD_itc_destroy_((itc)), 0) ) \
Packit 875988
         : (0) )
Packit 875988
#endif /* ! HAVE_PIPE2_FUNC */
Packit 875988
Packit 875988
/**
Packit 875988
 * Get description string of last errno for itc operations.
Packit 875988
 */
Packit 875988
#define MHD_itc_last_strerror_() strerror(errno)
Packit 875988
Packit 875988
/**
Packit 875988
 * Activate signal on @a itc
Packit 875988
 * @param itc the itc to use
Packit 875988
 * @param str one-symbol string, useful only for strace debug
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_activate_(itc, str) \
Packit 875988
  ((write((itc).fd[1], (const void*)(str), 1) > 0) || (EAGAIN == errno))
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Return read FD of @a itc which can be used for poll(), select() etc.
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of read side
Packit 875988
 */
Packit 875988
#define MHD_itc_r_fd_(itc) ((itc).fd[0])
Packit 875988
Packit 875988
/**
Packit 875988
 * Return write FD of @a itc
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of write side
Packit 875988
 */
Packit 875988
#define MHD_itc_w_fd_(itc) ((itc).fd[1])
Packit 875988
Packit 875988
/**
Packit 875988
 * Clear signaled state on @a itc
Packit 875988
 * @param itc the itc to clear
Packit 875988
 */
Packit 875988
#define MHD_itc_clear_(itc) do                      \
Packit 875988
  { long __b;                                       \
Packit 875988
    while(0 < read((itc).fd[0], &__b, sizeof(__b))) \
Packit 875988
    {} } while(0)
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy previously initialised ITC
Packit 875988
 * @param itc the itc to destroy
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_destroy_(itc)      \
Packit 875988
  ( (0 == close ((itc).fd[0])) ?   \
Packit 875988
      (0 == close ((itc).fd[1])) : \
Packit 875988
      ((close ((itc).fd[1])), 0) )
Packit 875988
Packit 875988
/**
Packit 875988
 * Check whether ITC has valid value.
Packit 875988
 *
Packit 875988
 * Macro check whether @a itc value is valid (allowed),
Packit 875988
 * macro does not check whether @a itc was really initialised.
Packit 875988
 * @param itc the itc to check
Packit 875988
 * @return boolean true if @a itc has valid value,
Packit 875988
 *         boolean false otherwise.
Packit 875988
 */
Packit 875988
#define MHD_ITC_IS_VALID_(itc)  (-1 != (itc).fd[0])
Packit 875988
Packit 875988
/**
Packit 875988
 * Set @a itc to invalid value.
Packit 875988
 * @param itc the itc to set
Packit 875988
 */
Packit 875988
#define MHD_itc_set_invalid_(itc) ((itc).fd[0] = (itc).fd[1] = -1)
Packit 875988
Packit 875988
#ifndef HAVE_PIPE2_FUNC
Packit 875988
  /**
Packit 875988
   * Change itc FD options to be non-blocking.
Packit 875988
   *
Packit 875988
   * @param fd the FD to manipulate
Packit 875988
   * @return non-zero if succeeded, zero otherwise
Packit 875988
   */
Packit 875988
  int
Packit 875988
  MHD_itc_nonblocking_ (struct MHD_itc_ itc);
Packit 875988
#endif /* ! HAVE_PIPE2_FUNC */
Packit 875988
Packit 875988
Packit 875988
#elif defined(_MHD_ITC_SOCKETPAIR)
Packit 875988
Packit 875988
/* **************** ITC implementation by socket pair ********** */
Packit 875988
Packit 875988
#include "mhd_sockets.h"
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Initialise ITC by generating socketpair
Packit 875988
 * @param itc the itc to initialise
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#ifdef MHD_socket_pair_nblk_
Packit 875988
#  define MHD_itc_init_(itc) MHD_socket_pair_nblk_((itc).sk)
Packit 875988
#else  /* ! MHD_socket_pair_nblk_ */
Packit 875988
#  define MHD_itc_init_(itc)            \
Packit 875988
     (MHD_socket_pair_((itc).sk) ?      \
Packit 875988
       (MHD_itc_nonblocking_((itc)) ?   \
Packit 875988
         (!0) :                         \
Packit 875988
         (MHD_itc_destroy_((itc)), 0) ) \
Packit 875988
       : (0))
Packit 875988
#endif /* ! MHD_socket_pair_nblk_ */
Packit 875988
Packit 875988
/**
Packit 875988
 * Get description string of last error for itc operations.
Packit 875988
 */
Packit 875988
#define MHD_itc_last_strerror_() MHD_socket_last_strerr_()
Packit 875988
Packit 875988
/**
Packit 875988
 * Activate signal on @a itc
Packit 875988
 * @param itc the itc to use
Packit 875988
 * @param str one-symbol string, useful only for strace debug
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_activate_(itc, str)          \
Packit 875988
  ((MHD_send_((itc).sk[1], (str), 1) > 0) || \
Packit 875988
   (MHD_SCKT_ERR_IS_EAGAIN_(MHD_socket_get_error_())))
Packit 875988
Packit 875988
/**
Packit 875988
 * Return read FD of @a itc which can be used for poll(), select() etc.
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of read side
Packit 875988
 */
Packit 875988
#define MHD_itc_r_fd_(itc) ((itc).sk[0])
Packit 875988
Packit 875988
/**
Packit 875988
 * Return write FD of @a itc
Packit 875988
 * @param itc the itc to get FD
Packit 875988
 * @return FD of write side
Packit 875988
 */
Packit 875988
#define MHD_itc_w_fd_(itc) ((itc).sk[1])
Packit 875988
Packit 875988
/**
Packit 875988
 * Clear signaled state on @a itc
Packit 875988
 * @param itc the itc to clear
Packit 875988
 */
Packit 875988
#define MHD_itc_clear_(itc) do      \
Packit 875988
  { long __b;                       \
Packit 875988
    while(0 < recv((itc).sk[0],     \
Packit 875988
                   (char*)&__b,     \
Packit 875988
                   sizeof(__b), 0)) \
Packit 875988
    {} } while(0)
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy previously initialised ITC
Packit 875988
 * @param itc the itc to destroy
Packit 875988
 * @return non-zero if succeeded, zero otherwise
Packit 875988
 */
Packit 875988
#define MHD_itc_destroy_(itc)          \
Packit 875988
  ( MHD_socket_close_((itc).sk[0]) ?   \
Packit 875988
      MHD_socket_close_((itc).sk[1]) : \
Packit 875988
      ((void)MHD_socket_close_((itc).sk[1]), 0) )
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Check whether ITC has valid value.
Packit 875988
 *
Packit 875988
 * Macro check whether @a itc value is valid (allowed),
Packit 875988
 * macro does not check whether @a itc was really initialised.
Packit 875988
 * @param itc the itc to check
Packit 875988
 * @return boolean true if @a itc has valid value,
Packit 875988
 *         boolean false otherwise.
Packit 875988
 */
Packit 875988
#define MHD_ITC_IS_VALID_(itc)  (MHD_INVALID_SOCKET != (itc).sk[0])
Packit 875988
Packit 875988
/**
Packit 875988
 * Set @a itc to invalid value.
Packit 875988
 * @param itc the itc to set
Packit 875988
 */
Packit 875988
#define MHD_itc_set_invalid_(itc) ((itc).sk[0] = (itc).sk[1] = MHD_INVALID_SOCKET)
Packit 875988
Packit 875988
#ifndef MHD_socket_pair_nblk_
Packit 875988
#  define MHD_itc_nonblocking_(pip) (MHD_socket_nonblocking_((pip).sk[0]) && MHD_socket_nonblocking_((pip).sk[1]))
Packit 875988
#endif /* ! MHD_socket_pair_nblk_ */
Packit 875988
Packit 875988
#endif /* _MHD_ITC_SOCKETPAIR */
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy previously initialised ITC and abort execution
Packit 875988
 * if error is detected.
Packit 875988
 * @param itc the itc to destroy
Packit 875988
 */
Packit 875988
#define MHD_itc_destroy_chk_(itc) do {          \
Packit 875988
    if (!MHD_itc_destroy_(itc))                 \
Packit 875988
      MHD_PANIC(_("Failed to destroy ITC.\n")); \
Packit 875988
  } while(0)
Packit 875988
Packit 875988
/**
Packit 875988
 * Check whether ITC has invalid value.
Packit 875988
 *
Packit 875988
 * Macro check whether @a itc value is invalid,
Packit 875988
 * macro does not check whether @a itc was destroyed.
Packit 875988
 * @param itc the itc to check
Packit 875988
 * @return boolean true if @a itc has invalid value,
Packit 875988
 *         boolean false otherwise.
Packit 875988
 */
Packit 875988
#define MHD_ITC_IS_INVALID_(itc)  (! MHD_ITC_IS_VALID_(itc))
Packit 875988
Packit 875988
#endif /* MHD_ITC_H */