diff options
Diffstat (limited to 'extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c')
-rw-r--r-- | extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c | 3331 |
1 files changed, 0 insertions, 3331 deletions
diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c deleted file mode 100644 index 6ddb245b421..00000000000 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c +++ /dev/null @@ -1,3331 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <unistd.h> -#include <stdio.h> -#include <signal.h> -#include <dlfcn.h> -#include <pthread.h> -#include <time.h> -#include <stdarg.h> -#include <sys/resource.h> - -#include <libvcl-ldpreload/vcom_socket_wrapper.h> -#include <libvcl-ldpreload/vcom.h> -#include <sys/time.h> - -#include <uri/vppcom.h> -#include <libvcl-ldpreload/vcom_socket.h> - -/* GCC have printf type attribute check. */ -#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT -#define PRINTF_ATTRIBUTE(a,b) \ - __attribute__ ((__format__ (__printf__, a, b))) -#else -#define PRINTF_ATTRIBUTE(a,b) -#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */ - -#define HAVE_CONSTRUCTOR_ATTRIBUTE -#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE -#define CONSTRUCTOR_ATTRIBUTE \ - __attribute__ ((constructor)) -#else -#define CONSTRUCTOR_ATTRIBUTE -#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ - -#define HAVE_DESTRUCTOR_ATTRIBUTE -#ifdef HAVE_DESTRUCTOR_ATTRIBUTE -#define DESTRUCTOR_ATTRIBUTE \ - __attribute__ ((destructor)) -#else -#define DESTRUCTOR_ATTRIBUTE -#endif - -#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE \ - __attribute__((no_sanitize_address)) -#else -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE -#endif - -#define VCOM_SOCKET_FD_MAX 0x10000 - -static char vcom_app_name[MAX_VCOM_APP_NAME]; - -/* - * RETURN: 0 on success or -1 on error. - * */ -int -vcom_set_app_name (char *__app_name) -{ - return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d", - __app_name, getpid ()) < 0 ? -1 : 0; -} - -static char * -vcom_get_app_name () -{ - if (vcom_app_name[0] == '\0') - { - snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ()); - } - return vcom_app_name; -} - -/* - * 1 if init, 0 otherwise - */ -static int is_vcom_init; - -/* - * TBD: Make it thread safe - */ - -/* - * constructor function called before main is called - * RETURN: 0 on success -1 on failure - * */ -static inline int -vcom_init () -{ - pid_t pid = getpid (); - - if (!is_vcom_init) - { - if (vppcom_app_create (vcom_get_app_name ()) != 0) - { - printf ("\n[%d] vcom_init...failed!\n", pid); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_init: vppcom_app_create failed!\n", pid); - return -1; - } - if (vcom_socket_main_init () != 0) - { - printf ("\n[%d] vcom_init...failed!\n", pid); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_init: vcom_socket_main_init failed!\n", pid); - return -1; - } - - is_vcom_init = 1; - printf ("\n[%d] vcom_init...done!\n", pid); - } - return 0; -} - -static inline void -vcom_destroy (void) -{ - pid_t pid = getpid (); - - if (is_vcom_init) - { - vcom_socket_main_destroy (); - vppcom_app_destroy (); - is_vcom_init = 0; - fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid); - } -} - -static inline int -is_vcom_socket_fd (int fd) -{ - return vcom_socket_is_vcom_fd (fd); -} - -static inline int -is_vcom_epfd (int epfd) -{ - return vcom_socket_is_vcom_epfd (epfd); -} - - -/* - * - * Generic glibc fd api - * - */ - -/* Close the file descriptor FD. - - This function is a cancellation point and therefore - not marked with __THROW. */ -/* - * PRE: is_vcom_socket_fd(__fd) == 1 - * RETURN: 0 on success and -1 for errors. - * */ -int -vcom_close (int __fd) -{ - if (vcom_init () != 0) - { - return -1; - } - - if (vcom_socket_close (__fd) != 0) - { - return -1; - } - - return 0; -} - -/* - * RETURN: 0 on success, or -1 on error - */ -int -close (int __fd) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd)) - { - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - rv = vcom_close (__fd); - if (VCOM_DEBUG > 0) - fprintf (stderr, "[%d] close: " "'%04d'='%04d'\n", pid, rv, __fd); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_close (__fd); -} - -/* Read NBYTES into BUF from FD. Return the - number read, -1 for errors or 0 for EOF. - - This function is a cancellation point and therefore - not marked with __THROW. */ -ssize_t -vcom_read (int __fd, void *__buf, size_t __nbytes) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_read (__fd, __buf, __nbytes); -} - -ssize_t -read (int __fd, void *__buf, size_t __nbytes) -{ - ssize_t size = 0; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); - - if (is_vcom_socket_fd (__fd)) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] read:1 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __nbytes); - size = vcom_read (__fd, __buf, __nbytes); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] read:2 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __nbytes); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_read (__fd, __buf, __nbytes); -} - -ssize_t -vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_readv (__fd, __iov, __iovcnt); -} - -ssize_t -readv (int __fd, const struct iovec * __iov, int __iovcnt) -{ - ssize_t size = 0; - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_readv (__fd, __iov, __iovcnt); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - else - return libc_readv (__fd, __iov, __iovcnt); -} - -/* Write N bytes of BUF to FD. Return the number written, or -1. - - This function is a cancellation point and therefore - not marked with __THROW. */ -ssize_t -vcom_write (int __fd, const void *__buf, size_t __n) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_write (__fd, (void *) __buf, __n); -} - -ssize_t -write (int __fd, const void *__buf, size_t __n) -{ - ssize_t size = 0; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); - - if (is_vcom_socket_fd (__fd)) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] write:1 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __n); - size = vcom_write (__fd, __buf, __n); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] write:2 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __n); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_write (__fd, __buf, __n); -} - -ssize_t -vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_writev (__fd, __iov, __iovcnt); -} - -ssize_t -writev (int __fd, const struct iovec * __iov, int __iovcnt) -{ - ssize_t size = 0; - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_writev (__fd, __iov, __iovcnt); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - else - return libc_writev (__fd, __iov, __iovcnt); -} - -/* Do the file control operation described by CMD on FD. - The remaining arguments are interpreted depending on CMD. - - This function is a cancellation point and therefore - not marked with __THROW. */ -int -vcom_fcntl_va (int __fd, int __cmd, va_list __ap) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_fcntl_va (__fd, __cmd, __ap); -} - -int -vcom_fcntl (int __fd, int __cmd, ...) -{ - int rv = -1; - va_list ap; - - if (is_vcom_socket_fd (__fd)) - { - va_start (ap, __cmd); - rv = vcom_fcntl_va (__fd, __cmd, ap); - va_end (ap); - } - return rv; -} - -int -fcntl (int __fd, int __cmd, ...) -{ - int rv; - va_list ap; - pid_t pid = getpid (); - - va_start (ap, __cmd); - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_fcntl_va (__fd, __cmd, ap); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] fcntl: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd); - if (rv < 0) - { - errno = -rv; - rv = -1; - } - goto out; - } - rv = libc_vfcntl (__fd, __cmd, ap); - -out: - va_end (ap); - return rv; -} - -int -vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_ioctl_va (__fd, __cmd, __ap); -} - -int -vcom_ioctl (int __fd, unsigned long int __cmd, ...) -{ - int rv = -1; - va_list ap; - - if (is_vcom_socket_fd (__fd)) - { - va_start (ap, __cmd); - rv = vcom_ioctl_va (__fd, __cmd, ap); - va_end (ap); - } - return rv; -} - -int -ioctl (int __fd, unsigned long int __cmd, ...) -{ - int rv; - va_list ap; - pid_t pid = getpid (); - - va_start (ap, __cmd); - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_ioctl_va (__fd, __cmd, ap); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] ioctl: " - "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd); - if (rv < 0) - { - errno = -rv; - rv = -1; - } - goto out; - } - rv = libc_vioctl (__fd, __cmd, ap); - -out: - va_end (ap); - return rv; -} - -/* - * Check the first NFDS descriptors each in READFDS (if not NULL) for - * read readiness, in WRITEFDS (if not NULL) for write readiness, - * and in EXCEPTFDS (if not NULL) for exceptional conditions. - * If TIMEOUT is not NULL, time out after waiting the interval - * specified therein. Returns the number of ready descriptors, - * or -1 for errors. - * - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ - -/* - * clear all vcom FDs from fd_sets __readfds, __writefds and - * __exceptfds and update the new nfds - * - * new nfds is the highest-numbered file descriptor - * in any of the three sets, plus 1 - * - * Return the number of file descriptors contained in the - * three descriptor sets. ie. the total number of the bits - * that are set in __readfds, __writefds and __exceptfds - */ -static inline int -vcom_fd_clear (int __nfds, - int *__new_nfds, - fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd = 0; - - - /* clear all vcom fd from the sets */ - for (fd = 0; fd < __nfds; fd++) - { - - /* clear vcom fd from set */ - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - FD_CLR (fd, (F)); \ - } \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - /* - * compute nfd and __new_nfds - */ - for (fd = 0; fd < __nfds; fd++) - { - - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (fd > max_fd) \ - { \ - max_fd = fd; \ - } \ - ++nfd; \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - *__new_nfds = max_fd != -1 ? max_fd + 1 : 0; - return nfd; -} - -/* - * Return the number of file descriptors contained in the - * three descriptor sets. ie. the total number of the bits - * that are set in __readfds, __writefds and __exceptfds - */ -static inline int -vcom_fd_set (int __nfds, - /* dest */ - int *__new_nfds, - fd_set * __restrict __readfds, - fd_set * __restrict __writefds, fd_set * __restrict __exceptfds, - /* src */ - fd_set * __restrict __saved_readfds, - fd_set * __restrict __saved_writefds, - fd_set * __restrict __saved_exceptfds) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd = 0; - - for (fd = 0; fd < __nfds; fd++) - { - /* - * F fd set - * S saved fd set - */ -#define _(S,F) \ - if ((F) && (S) && FD_ISSET (fd, (S))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - FD_SET (fd, (F)); \ - } \ - } - - - _(__saved_readfds, __readfds); - _(__saved_writefds, __writefds); -#undef _ - } - - - /* - * compute nfd and __new_nfds - */ - for (fd = 0; fd < __nfds; fd++) - { - - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (fd > max_fd) \ - { \ - max_fd = fd; \ - } \ - ++nfd; \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - *__new_nfds = max_fd != -1 ? max_fd + 1 : 0; - return nfd; -} - -/* - * split select sets(src) into - * vcom sets(dest1) and libc sets(dest2) - */ -static inline void -vcom_fd_set_split ( - /* src, select sets */ - int nfds, - fd_set * __restrict readfds, - fd_set * __restrict writefds, - fd_set * __restrict exceptfds, - /* dest1, vcom sets */ - int *vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, int *vcom_nfd, - /* dest2, libc sets */ - int *libc_nfds, - fd_set * __restrict libc_readfds, - fd_set * __restrict libc_writefds, - fd_set * __restrict libc_exceptfds, int *libc_nfd) -{ - int fd; - - /* vcom */ - /* invalid max_fd is -1 */ - int vcom_max_fd = -1; - int vcom_nfd2 = 0; - - /* libc */ - /* invalid max_fd is -1 */ - int libc_max_fd = -1; - int libc_nfd2 = 0; - - - for (fd = 0; fd < nfds; fd++) - { - /* - * S select fd set - * V vcom fd set - * L libc fd set - */ -#define _(S,V,L) \ - if ((S) && FD_ISSET (fd, (S))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - if ((V)) \ - { \ - FD_SET(fd, (V)); \ - if (fd > vcom_max_fd) \ - { \ - vcom_max_fd = fd; \ - } \ - ++vcom_nfd2; \ - } \ - } \ - else \ - { \ - if ((L)) \ - { \ - FD_SET(fd, (L)); \ - if (fd > libc_max_fd) \ - { \ - libc_max_fd = fd; \ - } \ - ++libc_nfd2; \ - } \ - } \ - } - - - _(readfds, vcom_readfds, libc_readfds); - _(writefds, vcom_writefds, libc_writefds); - _(exceptfds, vcom_exceptfds, libc_exceptfds); -#undef _ - } - - if (vcom_nfds) - *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0; - if (vcom_nfd) - *vcom_nfd = vcom_nfd2; - if (libc_nfds) - *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0; - if (libc_nfd) - *libc_nfd = libc_nfd2; -} - -/* - * merge vcom sets(src1) and libc sets(src2) - * into select sets(dest) - */ -static inline void -vcom_fd_set_merge ( - /* dest, select sets */ - int *nfds, - fd_set * __restrict readfds, - fd_set * __restrict writefds, - fd_set * __restrict exceptfds, int *nfd, - /* src1, vcom sets */ - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, int vcom_nfd, - /* src2, libc sets */ - int libc_nfds, - fd_set * __restrict libc_readfds, - fd_set * __restrict libc_writefds, - fd_set * __restrict libc_exceptfds, int libc_nfd) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd2 = 0; - - - /* FD_BIT_OR - * - * dest |= src at current bit index - * update MAX and NFD of dest fd set - * - * - * FS source fd set - * FD dest fd set - * BI bit index - * MAX current max_fd of dest fd sets - * NFD current nfd of dest fd sets - * N nfds of source fd set - */ -#define FD_BIT_OR(FD,FS,BI, \ - MAX,NFD) \ - if ((FS) && (FD) && FD_ISSET ((BI), (FS))) \ - { \ - FD_SET ((BI), (FD)); \ - if ((BI) > (MAX)) \ - { \ - (MAX) = (BI); \ - } \ - ++(NFD); \ - } - - - /* FD_RWE_SET_OR */ - /* - * SR,SW,SE source RWE fd sets - * DR,DW,DE dest RWE fd sets - * BI bit index - * NFDS nfds of source fd sets - * MAX current max_fd of dest fd sets - * NFD current nfd of dest fd sets - */ -#define FD_RWE_SETS_OR(DR,DW,DE, \ - SR,SW,SE, \ - BI,NFDS, \ - MAX,NFD) \ - do \ - { \ - for ((BI) = 0; (BI) < (NFDS); (BI)++) \ - { \ - FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD)); \ - FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD)); \ - FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD)); \ - } \ - } \ - while (0); - - - /* source(vcom) to dest(select) rwe fd sets */ - FD_RWE_SETS_OR (readfds, writefds, exceptfds, - vcom_readfds, vcom_writefds, vcom_exceptfds, - fd, vcom_nfds, max_fd, nfd2); - - /* source(libc) to dest(select) rwe fd sets */ - FD_RWE_SETS_OR (readfds, writefds, exceptfds, - libc_readfds, libc_writefds, libc_exceptfds, - fd, libc_nfds, max_fd, nfd2); - -#undef FD_RWE_SETS_OR -#undef FD_BIT_OR - - if (nfds) - *nfds = max_fd != -1 ? max_fd + 1 : 0; - if (nfd) - *nfd = nfd2; -} - -/* - * RETURN 1 if fds is NULL or empty. 0 otherwise - */ -static inline int -fd_set_iszero (fd_set * __restrict fds) -{ - int fd; - - /* NULL fds */ - if (!fds) - return 1; - - for (fd = 0; fd < FD_SETSIZE; fd++) - { - if (FD_ISSET (fd, fds)) - { - /* non-empty fds */ - return 0; - } - } - /* empty fds */ - return 1; -} - - -/* - * ################ - * kernel time64.h - * ################ - * */ -typedef long int s64; -typedef unsigned long int u64; - -typedef long long int __s64; -typedef unsigned long long int __u64; - -typedef __s64 time64_t; -typedef __u64 timeu64_t; - -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L -#define USEC_PER_MSEC 1000L -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC 1000000L -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L -#define FSEC_PER_SEC 1000000000000000LL - - -/* - * ################ - * kernel time.h - * ################ - * */ - - -#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) - -static inline int -timespec_equal (const struct timespec *a, const struct timespec *b) -{ - return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec); -} - -/* - * lhs < rhs: return <0 - * lhs == rhs: return 0 - * lhs > rhs: return >0 - */ -static inline int -timespec_compare (const struct timespec *lhs, const struct timespec *rhs) -{ - if (lhs->tv_sec < rhs->tv_sec) - return -1; - if (lhs->tv_sec > rhs->tv_sec) - return 1; - return lhs->tv_nsec - rhs->tv_nsec; -} - -static inline int -timeval_compare (const struct timeval *lhs, const struct timeval *rhs) -{ - if (lhs->tv_sec < rhs->tv_sec) - return -1; - if (lhs->tv_sec > rhs->tv_sec) - return 1; - return lhs->tv_usec - rhs->tv_usec; -} - -extern void set_normalized_timespec (struct timespec *ts, time_t sec, - s64 nsec); - - -static inline struct timespec -timespec_add (struct timespec lhs, struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec, - lhs.tv_nsec + rhs.tv_nsec); - return ts_delta; -} - -/* - * sub = lhs - rhs, in normalized form - */ -static inline struct timespec -timespec_sub (struct timespec lhs, struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec, - lhs.tv_nsec - rhs.tv_nsec); - return ts_delta; -} - -/* - * ################ - * kernel time.c - * ################ - * */ - - -/** - * set_normalized_timespec - set timespec sec and nsec parts and normalize - * - * @ts: pointer to timespec variable to be set - * @sec: seconds to set - * @nsec: nanoseconds to set - * - * Set seconds and nanoseconds field of a timespec variable and - * normalize to the timespec storage format - * - * Note: The tv_nsec part is always in the range of - * 0 <= tv_nsec < NSEC_PER_SEC - * For negative values only the tv_sec field is negative ! - */ -void -set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec) -{ - while (nsec >= NSEC_PER_SEC) - { - /* - * The following asm() prevents the compiler from - * optimising this loop into a modulo operation. See - * also __iter_div_u64_rem() in include/linux/time.h - */ - asm ("":"+rm" (nsec)); - nsec -= NSEC_PER_SEC; - ++sec; - } - while (nsec < 0) - { - asm ("":"+rm" (nsec)); - nsec += NSEC_PER_SEC; - --sec; - } - ts->tv_sec = sec; - ts->tv_nsec = nsec; -} - -#define vcom_timerisvalid(tvp) (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0)) - -/* Macros for converting between `struct timeval' and `struct timespec'. */ -#define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) { \ - (ts)->tv_sec = (tv)->tv_sec; \ - (ts)->tv_nsec = (tv)->tv_usec * 1000; \ -} -#define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) { \ - (tv)->tv_sec = (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ -} - -static inline int -vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, - struct timeval *__restrict timeout) -{ - return vcom_socket_select (vcom_nfds, vcom_readfds, - vcom_writefds, vcom_exceptfds, timeout); -} - -int -vcom_select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout) -{ - int rv; - int rv2 = 0; - pid_t pid = getpid (); - - int timedout = 0; - /* block indefinitely */ - int no_timeout = 0; - int first_clock_gettime_failed = 0; - /* timeout value in units of timespec */ - struct timespec timeout_ts; - struct timespec start_time, now, end_time; - - /* select sets attributes - after merge */ - int new_nfds = 0; - int new_nfd = -1; - - /* vcom */ - int vcom_nfds = 0; - fd_set vcom_readfds; - fd_set vcom_writefds; - fd_set vcom_exceptfds; - int vcom_nfd = -1; - - /* libc */ - int libc_nfds = 0; - fd_set libc_readfds; - fd_set libc_writefds; - fd_set libc_exceptfds; - int libc_nfd = -1; - - /* for polling */ - struct timeval tv = {.tv_sec = 0,.tv_usec = 0 }; - - /* validate __timeout */ - if (__timeout) - { - /* validate tv_sec */ - /* bogus */ - if (!vcom_timerisvalid (__timeout)) - { - rv = -EINVAL; - goto select_done; - } - - /* validate tv_usec */ - /* TBD: */ - /* init timeout_ts */ - VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts); - set_normalized_timespec (&timeout_ts, - timeout_ts.tv_sec, timeout_ts.tv_nsec); - } - - rv = clock_gettime (CLOCK_MONOTONIC, &start_time); - if (rv == -1) - { - rv = -errno; - first_clock_gettime_failed = 1; - goto select_done; - } - - /* init end_time */ - if (__timeout) - { - if (timerisset (__timeout)) - { - end_time = timespec_add (start_time, timeout_ts); - } - else - { - /* - * if both fields of the timeout structure are zero, - * then select returns immediately - * */ - end_time = start_time; - } - } - else - { - /* block indefinitely */ - no_timeout = 1; - } - - - - if (vcom_init () != 0) - { - rv = -1; - goto select_done; - } - - /* validate __nfds */ - if (__nfds < 0 || __nfds > FD_SETSIZE) - { - rv = -EINVAL; - goto select_done; - } - - - /* - * usleep(3) emulation - * */ - - /* call libc_select() with a finite timeout and - * no file descriptors or empty fd sets and - * zero nfds */ - if (__nfds == 0 && - (!__readfds || fd_set_iszero (__readfds)) && - (!__writefds || fd_set_iszero (__writefds)) && - (!__exceptfds || fd_set_iszero (__exceptfds))) - { - if (__timeout) - { - rv = libc_select (__nfds, - __readfds, __writefds, __exceptfds, __timeout); - if (rv == -1) - rv = -errno; - } - else - { - /* TBD: block indefinitely or return -EINVAL */ - rv = -EINVAL; - } - goto select_done; - } - - /* init once before the polling loop */ - - /* zero vcom and libc fd sets */ - /* - * S select fd set - * V vcom fd set - * L libc fd set - */ -#define _(S,V,L) \ - if ((S)) \ - { \ - FD_ZERO ((V)); \ - FD_ZERO ((L)); \ - } - - - _(__readfds, &vcom_readfds, &libc_readfds); - _(__writefds, &vcom_writefds, &libc_writefds); - _(__exceptfds, &vcom_exceptfds, &libc_exceptfds); -#undef _ - new_nfds = 0; - new_nfd = -1; - - vcom_nfds = 0; - vcom_nfd = -1; - libc_nfds = 0; - libc_nfd = -1; - - vcom_fd_set_split ( - /* src, select sets */ - __nfds, __readfds, __writefds, __exceptfds, - /* dest1, vcom sets */ - __readfds || __writefds || __exceptfds ? - &vcom_nfds : NULL, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, - __readfds || __writefds || __exceptfds ? - &vcom_nfd : NULL, - /* dest2, libc sets */ - __readfds || __writefds || __exceptfds ? - &libc_nfds : NULL, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, - __readfds || __writefds || __exceptfds ? - &libc_nfd : NULL); - - /* - * polling loop - * */ - do - { - new_nfd = -1; - vcom_nfd = -1; - libc_nfd = -1; - - /* - * if both fields of timeval structure are zero, - * vcom_select_impl and libc_select returns immediately. - * useful for polling and ensure fairness among - * file descriptors watched. - */ - - /* for polling */ - tv.tv_sec = 0; - tv.tv_usec = 0; - - /* select on vcom fds */ - if (vcom_nfds) - { - vcom_nfd = vcom_select_impl (vcom_nfds, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, - &tv); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] select vcom: " - "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds); - - if (vcom_nfd < 0) - { - rv = vcom_nfd; - goto select_done; - } - } - /* select on libc fds */ - if (libc_nfds) - { - libc_nfd = libc_select (libc_nfds, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, &tv); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] select libc: " - "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds); - - if (libc_nfd < 0) - { - /* tv becomes undefined */ - libc_nfd = errno; - rv = libc_nfd; - goto select_done; - } - } - - /* check if any file descriptors changed status */ - if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0)) - { - /* zero the sets before merge and exit */ - - /* - * F fd set - */ -#define _(F) \ - if ((F)) \ - { \ - FD_ZERO ((F)); \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - new_nfds = 0; - new_nfd = -1; - - /* - * on exit, sets are modified in place to indicate which - * file descriptors actually changed status - * */ - vcom_fd_set_merge ( - /* dest, select sets */ - __readfds || __writefds || __exceptfds ? - &new_nfds : NULL, - __readfds, - __writefds, - __exceptfds, - __readfds || __writefds || __exceptfds ? - &new_nfd : NULL, - /* src1, vcom sets */ - vcom_nfds, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd, - /* src2, libc sets */ - libc_nfds, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, libc_nfd); - /* - * return the number of file descriptors contained in the - * three returned sets - * */ - rv = 0; - /* - * for documentation - * - * if(vcom_nfd > 0) - * rv += vcom_nfd; - * if(libc_nfd > 0) - * rv += libc_nfd; - */ - - rv = new_nfd == -1 ? 0 : new_nfd; - goto select_done; - } - - rv = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv == -1) - { - rv = -errno; - goto select_done; - } - } - while (no_timeout || timespec_compare (&now, &end_time) < 0); - - /* timeout expired before anything interesting happened */ - timedout = 1; - rv = 0; - -select_done: - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds); - /* - * modify timeout parameter to reflect the amount of time not slept - * */ - if (__timeout) - { - if (vcom_timerisvalid (__timeout)) - { - /* timeout expired */ - if (timedout) - { - timerclear (__timeout); - } - else if (!first_clock_gettime_failed) - { - rv2 = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv2 == -1) - { - rv = -errno; - } - else - { - struct timespec ts_delta; - ts_delta = timespec_sub (end_time, now); - VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta); - } - } - } - } - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds); - - return rv; -} - -int -vcom_select_internal (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout) -{ - int rv; - int new_nfds = 0; - int nfd = 0; - pid_t pid = getpid (); - - fd_set saved_readfds; - fd_set saved_writefds; - fd_set saved_exceptfds; - - /* validate __nfds */ - if (__nfds < 0) - { - errno = EINVAL; - return -1; - } - - /* validate __timeout */ - if (__timeout) - { - /* validate tv_sec */ - /* bogus */ - if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0) - { - errno = EINVAL; - return -1; - } - - /* validate tv_usec */ - /* TBD: */ - } - - /* init saved_x fds */ - if (__readfds) - { - saved_readfds = *__readfds; - /* - memcpy (&saved_readfds, __readfds, sizeof (*__readfds)); - */ - } - else - { - FD_ZERO (&saved_readfds); - } - - if (__writefds) - { - saved_writefds = *__writefds; - /* - memcpy (&saved_writefds, __writefds, sizeof (*__writefds)); - */ - - } - else - { - FD_ZERO (&saved_writefds); - } - - if (__exceptfds) - { - saved_exceptfds = *__exceptfds; - /* - memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds)); - */ - - } - else - { - FD_ZERO (&saved_exceptfds); - } - - /* clear vcom fds */ - nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds); - - /* set to an invalid value */ - rv = -2; - /* have kernel fds */ - if (new_nfds) - rv = libc_select (new_nfds, __readfds, - __writefds, __exceptfds, __timeout); - - if (new_nfds && rv == -1) - { - /* on error, the file descriptor sets are unmodified */ - if (__readfds) - *__readfds = saved_readfds; - if (__writefds) - *__writefds = saved_writefds; - if (__exceptfds) - *__exceptfds = saved_exceptfds; - return rv; - } - else if ((new_nfds && rv != -1) || (rv == -2)) - { - /* restore vcom fds */ - nfd = vcom_fd_set (__nfds, - &new_nfds, - __readfds, - __writefds, - __exceptfds, - &saved_readfds, &saved_writefds, &saved_exceptfds); - rv = nfd; - } - - if (VCOM_DEBUG > 0) - fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds); - return rv; -} - -int -select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout) -{ - int rv = 0; - pid_t pid = getpid (); - - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds); - rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout); - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; -} - -#ifdef __USE_XOPEN2K -/* - * Same as above only that the TIMEOUT value is given with higher - * resolution and a sigmask which is been set temporarily. This - * version should be used. - * - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_pselect (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t * __restrict __sigmask) -{ - int fd; - int vcom_nfds = 0; - - for (fd = 0; fd < __nfds; fd++) - { - if (__readfds && FD_ISSET (fd, __readfds)) - { - if (is_vcom_socket_fd (fd)) - { - vcom_nfds++; - } - } - - if (__writefds && FD_ISSET (fd, __writefds)) - { - if (is_vcom_socket_fd (fd)) - { - vcom_nfds++; - } - } - if (__exceptfds && FD_ISSET (fd, __exceptfds)) - { - if (is_vcom_socket_fd (fd)) - { - FD_CLR (fd, __exceptfds); - } - } - } - return vcom_nfds; -} - -int -pselect (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t * __restrict __sigmask) -{ - int rv; - int new_nfds = 0; - int nfd = 0; - pid_t pid = getpid (); - - fd_set saved_readfds; - fd_set saved_writefds; - fd_set saved_exceptfds; - - /* validate __nfds */ - if (__nfds < 0) - { - errno = EINVAL; - return -1; - } - - /* validate __timeout */ - if (__timeout) - { - /* validate tv_sec */ - /* bogus */ - if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0) - { - errno = EINVAL; - return -1; - } - - /* validate tv_usec */ - /* TBD: */ - } - - /* init saved fds */ - if (__readfds) - { - saved_readfds = *__readfds; - /* - memcpy (&saved_readfds, __readfds, sizeof (*__readfds)); - */ - } - else - { - FD_ZERO (&saved_readfds); - } - - if (__writefds) - { - saved_writefds = *__writefds; - /* - memcpy (&saved_writefds, __writefds, sizeof (*__writefds)); - */ - - } - else - { - FD_ZERO (&saved_writefds); - } - - if (__exceptfds) - { - saved_exceptfds = *__exceptfds; - /* - memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds)); - */ - - } - else - { - FD_ZERO (&saved_exceptfds); - } - - /* clear vcom fds */ - nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds); - - /* set to an invalid value */ - rv = -2; - if (new_nfds) - rv = libc_pselect (new_nfds, - __readfds, - __writefds, __exceptfds, __timeout, __sigmask); - - if (new_nfds && rv == -1) - { - /* on error, the file descriptor sets are unmodified */ - if (__readfds) - *__readfds = saved_readfds; - if (__writefds) - *__writefds = saved_writefds; - if (__exceptfds) - *__exceptfds = saved_exceptfds; - return rv; - } - else if ((new_nfds && rv != -1) || (rv == -2)) - { - /* restore vcom fds */ - nfd = vcom_fd_set (__nfds, - &new_nfds, - __readfds, - __writefds, - __exceptfds, - &saved_readfds, &saved_writefds, &saved_exceptfds); - rv = nfd; - } - - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds); - return rv; -} -#endif - -/* - * - * Socket specific glibc api - * - */ - -/* Create a new socket of type TYPE in domain DOMAIN, using - * protocol PROTOCOL. If PROTOCOL is zero, one is chosen - * automatically. Returns a file descriptor for the new socket, - * or -1 for errors. - * RETURN: a valid file descriptor for the new socket, - * or -1 for errors. - * */ - -int -vcom_socket (int __domain, int __type, int __protocol) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_socket (__domain, __type, __protocol); -} - -int -socket (int __domain, int __type, int __protocol) -{ - int rv; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); - - /* handle domains implemented by vpp */ - switch (__domain) - { - case AF_INET: - case AF_INET6: - /* handle types implemented by vpp */ - switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) - { - case SOCK_STREAM: - case SOCK_DGRAM: - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - rv = vcom_socket (__domain, __type, __protocol); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] socket: " - "'%04d'= D='%04d', T='%04d', P='%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __domain, __type, __protocol); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; - break; - - default: - goto CALL_GLIBC_SOCKET_API; - break; - } - - break; - - default: - goto CALL_GLIBC_SOCKET_API; - break; - } - -CALL_GLIBC_SOCKET_API: - return libc_socket (__domain, __type, __protocol); -} - -/* - * Create two new sockets, of type TYPE in domain DOMAIN and using - * protocol PROTOCOL, which are connected to each other, and put file - * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, - * one will be chosen automatically. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2]) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_socketpair (__domain, __type, __protocol, __fds); -} - -int -socketpair (int __domain, int __type, int __protocol, int __fds[2]) -{ - int rv; - pid_t pid = getpid (); - - /* handle domains implemented by vpp */ - switch (__domain) - { - case AF_INET: - case AF_INET6: - /* handle types implemented by vpp */ - switch (__type) - { - case SOCK_STREAM: - case SOCK_DGRAM: - rv = vcom_socketpair (__domain, __type, __protocol, __fds); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] socketpair: " - "'%04d'= D='%04d', T='%04d', P='%04d'\n", - pid, rv, __domain, __type, __protocol); - if (rv < 0) - { - errno = -rv; - return -1; - } - return 0; - break; - - default: - goto CALL_GLIBC_SOCKET_API; - break; - } - - break; - - default: - goto CALL_GLIBC_SOCKET_API; - break; - } - -CALL_GLIBC_SOCKET_API: - return libc_socketpair (__domain, __type, __protocol, __fds); -} - -/* - * Give the socket FD the local address ADDR - * (which is LEN bytes long). - * */ -int -vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv; - - if (vcom_init () != 0) - { - return -1; - } - - /* validate __len */ - switch (__addr->sa_family) - { - case AF_INET: - if (__len != sizeof (struct sockaddr_in)) - return -EINVAL; - break; - case AF_INET6: - if (__len != sizeof (struct sockaddr_in6)) - return -EINVAL; - break; - - default: - return -1; - break; - } - - /* handle domains implemented by vpp */ - switch (__addr->sa_family) - { - case AF_INET: - case AF_INET6: - rv = vcom_socket_bind (__fd, __addr, __len); - return rv; - break; - - default: - return -1; - break; - } - - return -1; -} - -int -bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - - rv = vcom_bind (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] bind: " - "'%04d'='%04d', '%p', '%04d'\n", - pid, rv, __fd, __addr, __len); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_bind (__fd, __addr, __len); -} - -/* - * Put the local address of FD into *ADDR and its length in *LEN. - * */ -int -vcom_getsockname (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_getsockname (__fd, __addr, __len); -} - -int -getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_getsockname (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] getsockname: " - "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_getsockname (__fd, __addr, __len); -} - -/* - * Open a connection on socket FD to peer at ADDR - * (which LEN bytes long). For connectionless socket types, just set - * the default address to send to and the only address from which to - * accept transmissions. Return 0 on success, -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv = -1; - - if (vcom_init () != 0) - { - return -1; - } - - /* validate __len */ - switch (__addr->sa_family) - { - case AF_INET: - if (__len != INET_ADDRSTRLEN) - return -1; - break; - case AF_INET6: - if (__len != INET6_ADDRSTRLEN) - return -1; - break; - - default: - return -1; - break; - } - - /* handle domains implemented by vpp */ - switch (__addr->sa_family) - { - case AF_INET: - case AF_INET6: - rv = vcom_socket_connect (__fd, __addr, __len); - break; - - default: - return -1; - break; - } - - return rv; -} - -int -connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_connect (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] connect: " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __fd, __addr, __len); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - - return libc_connect (__fd, __addr, __len); -} - -/* - * Put the address of the peer connected to socket FD into *ADDR - * (which is *LEN bytes long), and its actual length into *LEN. - * */ -int -vcom_getpeername (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_getpeername (__fd, __addr, __len); -} - -int -getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_getpeername (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] getpeername: " - "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_getpeername (__fd, __addr, __len); -} - -/* - * Send N bytes of BUF to socket FD. Returns the number sent or -1. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_send (int __fd, const void *__buf, size_t __n, int __flags) -{ - - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags); -} - -ssize_t -send (int __fd, const void *__buf, size_t __n, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_send (__fd, __buf, __n, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] send: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_send (__fd, __buf, __n, __flags); -} - -/* - * Read N bytes into BUF from socket FD. - * Returns the number read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_recv (int __fd, void *__buf, size_t __n, int __flags) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_recv (__fd, __buf, __n, __flags); -} - -ssize_t -recv (int __fd, void *__buf, size_t __n, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_recv (__fd, __buf, __n, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recv: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_recv (__fd, __buf, __n, __flags); -} - -/* - * Send N bytes of BUF on socket FD to peer at address ADDR (which is - * ADDR_LEN bytes long). Returns the number sent, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags, - __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); -} - -ssize_t -sendto (int __fd, const void *__buf, size_t __n, int __flags, - __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendto: " - "'%04d'='%04d', '%p', '%04d', '%04x', " - "'%p', '%04d'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags, - __addr, __addr_len); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); -} - -/* - * Read N bytes into BUF through socket FD. - * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the - * address of the sender, and store the actual size of the address - * in *ADDR_LEN. - * Returns the number of bytes read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); -} - -ssize_t -recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvfrom: " - "'%04d'='%04d', '%p', '%04d', '%04x', " - "'%p', '%p'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags, - __addr, __addr_len); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); -} - -/* - * Send a message described MESSAGE on socket FD. - * Returns the number of bytes sent, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_sendmsg (__fd, __message, __flags); -} - -ssize_t -sendmsg (int __fd, const struct msghdr * __message, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_sendmsg (__fd, __message, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendmsg: " - "'%04d'='%04d', '%p', '%04x'\n", - pid, (int) size, __fd, __message, __flags); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_sendmsg (__fd, __message, __flags); -} - -#ifdef __USE_GNU -/* - * Send a VLEN messages as described by VMESSAGES to socket FD. - * Returns the number of datagrams successfully written - * or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags); -} - -int -sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_sendmmsg (__fd, __message, __vlen, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendmmsg: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __vmessages, __vlen, __flags); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_sendmmsg (__fd, __message, __vlen, __flags); -} - -#endif - -/* - * Receive a message as described by MESSAGE from socket FD. - * Returns the number of bytes read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_recvmsg (int __fd, struct msghdr * __message, int __flags) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_recvmsg (__fd, __message, __flags); -} - -ssize_t -recvmsg (int __fd, struct msghdr * __message, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_recvmsg (__fd, __message, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvmsg: " - "'%04d'='%04d', '%p', '%04x'\n", - pid, (int) size, __fd, __message, __flags); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_recvmsg (__fd, __message, __flags); -} - -#ifdef __USE_GNU -/* - * Receive up to VLEN messages as described by VMESSAGES from socket FD. - * Returns the number of messages received or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo); -} - -int -recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo) -{ - ssize_t size; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvmmsg: " - "'%04d'='%04d', '%p', " - "'%04d', '%04x', '%p'\n", - pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo); - if (size < 0) - { - errno = -size; - return -1; - } - return size; - } - return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo); -} - -#endif - -/* - * Put the current value for socket FD's option OPTNAME - * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long), - * and set *OPTLEN to the value's actual length. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_getsockopt (__fd, __level, __optname, - __optval, __optlen); -} - -int -getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] getsockopt: " - "'%04d'='%04d', '%04d', '%04d', " - "'%p', '%p'\n", - pid, rv, __fd, __level, __optname, __optval, __optlen); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_getsockopt (__fd, __level, __optname, __optval, __optlen); -} - -/* - * Set socket FD's option OPTNAME at protocol level LEVEL - * to *OPTVAL (which is OPTLEN bytes long). - * Returns 0 on success, -1 for errors. - * */ -int -vcom_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_setsockopt (__fd, __level, __optname, - __optval, __optlen); -} - -int -setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] setsockopt: " - "'%04d'='%04d', '%04d', '%04d', " - "'%p', '%04d'\n", - pid, rv, __fd, __level, __optname, __optval, __optlen); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_setsockopt (__fd, __level, __optname, __optval, __optlen); -} - -/* - * Prepare to accept connections on socket FD. - * N connection requests will be queued before further - * requests are refused. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_listen (int __fd, int __n) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_listen (__fd, __n); -} - -int -listen (int __fd, int __n) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_listen (__fd, __n); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] listen: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_listen (__fd, __n); -} - -/* - * Await a connection on socket FD. - * When a connection arrives, open a new socket to communicate - * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address - * of the connecting peer and *ADDR_LEN to the address's actual - * length, and return the new socket's descriptor, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_accept (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len) -{ - - if (vcom_init () != 0) - { - return -1; - } - return vcom_socket_accept (__fd, __addr, __addr_len); -} - -int -accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) -{ - int rv = -1; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); - - if (is_vcom_socket_fd (__fd)) - { - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] accept1: " - "'%04d'='%04d', '%p', '%p'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __fd, __addr, __addr_len); - rv = vcom_accept (__fd, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] accept2: " - "'%04d'='%04d', '%p', '%p'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __fd, __addr, __addr_len); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; - } - return libc_accept (__fd, __addr, __addr_len); -} - -#ifdef __USE_GNU -/* - * Similar to 'accept' but takes an additional parameter to specify - * flags. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags) -{ - - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags); -} - -int -accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - rv = vcom_accept4 (__fd, __addr, __addr_len, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] accept4: " - "'%04d'='%04d', '%p', '%p', '%04x'\n", - pid, rv, __fd, __addr, __addr_len, __flags); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; - } - return libc_accept4 (__fd, __addr, __addr_len, __flags); -} - -#endif - -/* - * Shut down all or part of the connection open on socket FD. - * HOW determines what to shut down: - * SHUT_RD = No more receptions; - * SHUT_WR = No more transmissions; - * SHUT_RDWR = No more receptions or transmissions. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_shutdown (int __fd, int __how) -{ - if (vcom_init () != 0) - { - return -1; - } - return vcom_socket_shutdown (__fd, __how); -} - -int -shutdown (int __fd, int __how) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_shutdown (__fd, __how); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] shutdown: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - return libc_shutdown (__fd, __how); -} - -int -vcom_epoll_create (int __size) -{ - - if (vcom_init () != 0) - { - return -1; - } - - if (__size <= 0) - { - return -EINVAL; - } - - /* __size argument is ignored "thereafter" */ - return vcom_epoll_create1 (0); -} - -/* - * __size argument is ignored, but must be greater than zero - */ -int -epoll_create (int __size) -{ - int rv = 0; - pid_t pid = getpid (); - - rv = vcom_epoll_create (__size); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; -} - -int -vcom_epoll_create1 (int __flags) -{ - if (vcom_init () != 0) - { - return -1; - } - - if (__flags < 0) - { - return -EINVAL; - } - if (__flags & ~EPOLL_CLOEXEC) - { - return -EINVAL; - } - /* __flags can be either zero or EPOLL_CLOEXEC */ - /* implementation */ - return vcom_socket_epoll_create1 (__flags); -} - -/* - * __flags can be either zero or EPOLL_CLOEXEC - * */ -int -epoll_create1 (int __flags) -{ - int rv = 0; - pid_t pid = getpid (); - - rv = vcom_epoll_create1 (__flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; -} - -static inline int -ep_op_has_event (int op) -{ - return op != EPOLL_CTL_DEL; -} - -int -vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) -{ - if (vcom_init () != 0) - { - return -1; - } - - /* - * the requested operation __op is not supported - * by this interface */ - if (!((__op == EPOLL_CTL_ADD) || - (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL))) - { - return -EINVAL; - } - - /* op is ADD or MOD but event parameter is NULL */ - if ((ep_op_has_event (__op) && !__event)) - { - return -EFAULT; - } - - /* fd is same as epfd */ - /* do not permit adding an epoll file descriptor inside itself */ - if (__epfd == __fd) - { - return -EINVAL; - } - - /* implementation */ - return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event); -} - -/* - * implement the controller interface for epoll - * that enables the insertion/removal/change of - * file descriptors inside the interest set. - */ -int -epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) -{ - int rv; - pid_t pid = getpid (); - - if (is_vcom_epfd (__epfd)) - { - /* TBD: currently limiting epoll to support only vcom fds */ - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_epoll_ctl (__epfd, __op, __fd, __event); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_ctl: " - "'%04d'='%04d', '%04d', '%04d'\n", - pid, rv, __epfd, __op, __fd); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; - } - else - { - /* - * TBD: currently epoll does not support kernel fds - * or epoll fds */ - errno = EBADF; - return -1; - } - } - else - { - /* epfd is not an epoll file descriptor */ - errno = EINVAL; - return -1; - } - return 0; -} - -int -vcom_epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout) -{ - if (vcom_init () != 0) - { - return -1; - } - - return vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL); -} - -int -epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout) -{ - int rv; - pid_t pid = getpid (); - - if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS) - { - errno = EINVAL; - return -1; - } - - if (is_vcom_epfd (__epfd)) - { - rv = vcom_epoll_wait (__epfd, __events, __maxevents, __timeout); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_wait: " - "'%04d'='%04d', '%p', " - "'%04d', '%04d'\n", - pid, rv, __epfd, __events, __maxevents, __timeout); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; - } - else - { - errno = EINVAL; - return -1; - } - return 0; -} - - -int -vcom_epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, const __sigset_t * __ss) -{ - if (vcom_init () != 0) - { - return -1; - } - - /* implementation */ - return vcom_socket_epoll_pwait (__epfd, __events, - __maxevents, __timeout, __ss); -} - -int -epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, const __sigset_t * __ss) -{ - int rv; - pid_t pid = getpid (); - - if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS) - { - errno = EINVAL; - return -1; - } - - if (is_vcom_epfd (__epfd)) - { - rv = vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_pwait: " - "'%04d'='%04d', '%p', " - "'%04d', '%04d', " - "'%p'\n", - pid, rv, __epfd, __events, __maxevents, __timeout, __ss); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; - } - else - { - errno = EINVAL; - return -1; - } - - return 0; -} - -/* Poll the file descriptors described by the NFDS structures starting at - FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for - an event to occur; if TIMEOUT is -1, block until an event occurs. - Returns the number of file descriptors with events, zero if timed out, - or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ - -int -vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) -{ - int rv = 0; - pid_t pid = getpid (); - - struct rlimit nofile_limit; - struct pollfd vcom_fds[MAX_POLL_NFDS_DEFAULT]; - nfds_t fds_idx = 0; - - /* actual set of file descriptors to be monitored */ - nfds_t libc_nfds = 0; - nfds_t vcom_nfds = 0; - - /* ready file descriptors - * - * number of structures which have nonzero revents fields - * in other words, descriptors with events or errors reported. - * */ - /* after call to libc_poll () */ - int rlibc_nfds = 0; - /* after call to vcom_socket_poll () */ - int rvcom_nfds = 0; - - - /* timeout value in units of timespec */ - struct timespec timeout_ts; - struct timespec start_time, now, end_time; - - - /* get start_time */ - rv = clock_gettime (CLOCK_MONOTONIC, &start_time); - if (rv == -1) - { - rv = -errno; - goto poll_done; - } - - /* set timeout_ts & end_time */ - if (__timeout >= 0) - { - /* set timeout_ts */ - timeout_ts.tv_sec = __timeout / MSEC_PER_SEC; - timeout_ts.tv_nsec = (__timeout % MSEC_PER_SEC) * NSEC_PER_MSEC; - set_normalized_timespec (&timeout_ts, - timeout_ts.tv_sec, timeout_ts.tv_nsec); - /* set end_time */ - if (__timeout) - { - end_time = timespec_add (start_time, timeout_ts); - } - else - { - end_time = start_time; - } - } - - if (vcom_init () != 0) - { - rv = -1; - goto poll_done; - } - - /* validate __fds */ - if (!__fds) - { - rv = -EFAULT; - goto poll_done; - } - - /* validate __nfds */ - /*TBD: call getrlimit once when vcl-ldpreload library is init */ - rv = getrlimit (RLIMIT_NOFILE, &nofile_limit); - if (rv != 0) - { - rv = -errno; - goto poll_done; - } - if (__nfds >= nofile_limit.rlim_cur || __nfds < 0) - { - rv = -EINVAL; - goto poll_done; - } - - /* - * for the POC, it's fair to assume that nfds is less than 1024 - * */ - if (__nfds >= MAX_POLL_NFDS_DEFAULT) - { - rv = -EINVAL; - goto poll_done; - } - - /* set revents field (output parameter) - * to zero - * */ - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - __fds[fds_idx].revents = 0; - } - -#if 0 - /* set revents field (output parameter) - * to zero for user ignored fds - * */ - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* - * if negative fd, ignore events field - * and set output parameter (revents field) to zero */ - if (__fds[fds_idx].fd < 0) - { - __fds[fds_idx].revents = 0; - } - } -#endif - - /* - * 00. prepare __fds and vcom_fds for polling - * copy __fds to vcom_fds - * 01. negate all except libc fds in __fds, - * ignore user negated fds - * 02. negate all except vcom_fds in vocm fds, - * ignore user negated fds - * ignore fd 0 by setting it to negative number - * */ - memcpy (vcom_fds, __fds, sizeof (*__fds) * __nfds); - libc_nfds = 0; - vcom_nfds = 0; - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - /* - * 00. ignore vcom fds in __fds - * 01. ignore libc fds in vcom_fds, - * ignore fd 0 by setting it to negative number. - * as fd 0 cannot be ignored. - */ - if (is_vcom_socket_fd (__fds[fds_idx].fd) || - is_vcom_epfd (__fds[fds_idx].fd)) - { - __fds[fds_idx].fd = -__fds[fds_idx].fd; - vcom_nfds++; - } - else - { - libc_nfds++; - /* ignore fd 0 by setting it to negative number */ - if (!vcom_fds[fds_idx].fd) - { - vcom_fds[fds_idx].fd = -1; - } - vcom_fds[fds_idx].fd = -vcom_fds[fds_idx].fd; - } - } - - /* - * polling loop - * - * poll on libc fds and vcom fds - * - * specifying a timeout of zero causes libc_poll() and - * vcom_socket_poll() to return immediately, even if no - * file descriptors are ready - * */ - do - { - rlibc_nfds = 0; - rvcom_nfds = 0; - - /* - * timeout parameter for libc_poll () set to zero - * to poll on libc fds - * */ - - /* poll on libc fds */ - if (libc_nfds) - { - /* - * a timeout of zero causes libc_poll() - * to return immediately - * */ - rlibc_nfds = libc_poll (__fds, __nfds, 0); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] poll libc: " - "'%04d'='%08lu'\n", pid, rlibc_nfds, __nfds); - - if (rlibc_nfds < 0) - { - rv = -errno; - goto poll_done_update_nfds; - } - } - - /* - * timeout parameter for vcom_socket_poll () set to zero - * to poll on vcom fds - * */ - - /* poll on vcom fds */ - if (vcom_nfds) - { - /* - * a timeout of zero causes vcom_socket_poll() - * to return immediately - * */ - rvcom_nfds = vcom_socket_poll (vcom_fds, __nfds, 0); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] poll vcom: " - "'%04d'='%08lu'\n", pid, rvcom_nfds, __nfds); - if (rvcom_nfds < 0) - { - rv = rvcom_nfds; - goto poll_done_update_nfds; - } - } - - /* check if any file descriptors changed status */ - if ((libc_nfds && rlibc_nfds > 0) || (vcom_nfds && rvcom_nfds > 0)) - { - /* something interesting happened */ - rv = rlibc_nfds + rvcom_nfds; - goto poll_done_update_nfds; - } - - rv = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv == -1) - { - rv = -errno; - goto poll_done_update_nfds; - } - } - - /* block indefinitely || timeout elapsed */ - while ((__timeout < 0) || timespec_compare (&now, &end_time) < 0); - - /* timeout expired before anything interesting happened */ - rv = 0; - -poll_done_update_nfds: - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds in vcom_fds - * 00. user negated fds - * 01. libc fds - * */ - if (vcom_fds[fds_idx].fd < 0) - { - continue; - } - - /* from here on handle positive vcom fds */ - /* - * restore vcom fds to positive number in __fds - * and update revents in __fds with the events - * that actually occurred in vcom fds - * */ - __fds[fds_idx].fd = -__fds[fds_idx].fd; - if (rvcom_nfds) - { - __fds[fds_idx].revents = vcom_fds[fds_idx].revents; - } - } - -poll_done: - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vpoll: " "'%04d'='%08lu'\n", pid, rv, __nfds); - return rv; -} - -/* - * 00. The field __fds[i].fd contains a file descriptor for an - * open file. - * If this field is negative, then the corresponding - * events field is ignored and the revents field returns zero. - * The field __fds[i].events is an input parameter. - * The field __fds[i].revents is an output parameter. - * 01. Specifying a negative value in timeout - * means an infinite timeout. - * Specifying a timeout of zero causes poll() to return - * immediately, even if no file descriptors are ready. - * - * NOTE: observed __nfds is less than 128 from kubecon strace files - */ - - -int -poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) -{ - int rv = 0; - pid_t pid = getpid (); - - - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] poll1: " "'%04d'='%08lu, %d, 0x%x'\n", - pid, rv, __nfds, __fds[0].fd, __fds[0].events); - rv = vcom_poll (__fds, __nfds, __timeout); - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] poll2: " "'%04d'='%08lu, %d, 0x%x'\n", - pid, rv, __nfds, __fds[0].fd, __fds[0].revents); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; -} - -#ifdef __USE_GNU -/* Like poll, but before waiting the threads signal mask is replaced - with that specified in the fourth parameter. For better usability, - the timeout value is specified using a TIMESPEC object. - - This function is a cancellation point and therefore not marked with - __THROW. */ -int -vcom_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss) -{ - if (vcom_init () != 0) - { - return -1; - } - - return -EOPNOTSUPP; -} - -int -ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss) -{ - int rv = 0; - - errno = EOPNOTSUPP; - rv = -1; - return rv; -} -#endif - -void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void); - -void DESTRUCTOR_ATTRIBUTE vcom_destructor (void); - -void -vcom_constructor (void) -{ - pid_t pid = getpid (); - - swrap_constructor (); - if (vcom_init () != 0) - { - printf ("\n[%d] vcom_constructor...failed!\n", pid); - } - else - { - printf ("\n[%d] vcom_constructor...done!\n", pid); - } -} - -/* - * This function is called when the library is unloaded - */ -void -vcom_destructor (void) -{ - pid_t pid = getpid (); - - vcom_destroy (); - swrap_destructor (); - printf ("\n[%d] vcom_destructor...done!\n", pid); -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |