Blame snmplib/fd_event_manager.c

Packit fcad23
/* UNIT: File Descriptor (FD) Event Manager                              */
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#ifdef HAVE_SYS_SELECT
Packit fcad23
#include <sys/select.h>
Packit fcad23
#endif
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
#include <net-snmp/library/snmp_api.h>
Packit fcad23
#include <net-snmp/library/fd_event_manager.h>
Packit fcad23
#include <net-snmp/library/snmp_logging.h>
Packit fcad23
#include <net-snmp/library/large_fd_set.h>
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(fd_event_manager, libnetsnmp)
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER
Packit fcad23
int     external_readfd[NUM_EXTERNAL_FDS],   external_readfdlen   = 0;
Packit fcad23
int     external_writefd[NUM_EXTERNAL_FDS],  external_writefdlen  = 0;
Packit fcad23
int     external_exceptfd[NUM_EXTERNAL_FDS], external_exceptfdlen = 0;
Packit fcad23
void  (*external_readfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
Packit fcad23
void  (*external_writefdfunc[NUM_EXTERNAL_FDS]) (int, void *);
Packit fcad23
void  (*external_exceptfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
Packit fcad23
void   *external_readfd_data[NUM_EXTERNAL_FDS];
Packit fcad23
void   *external_writefd_data[NUM_EXTERNAL_FDS];
Packit fcad23
void   *external_exceptfd_data[NUM_EXTERNAL_FDS];
Packit fcad23
Packit fcad23
static int external_fd_unregistered;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Register a given fd for read events.  Call callback when events
Packit fcad23
 * are received.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
register_readfd(int fd, void (*func) (int, void *), void *data)
Packit fcad23
{
Packit fcad23
    if (external_readfdlen < NUM_EXTERNAL_FDS) {
Packit fcad23
        external_readfd[external_readfdlen] = fd;
Packit fcad23
        external_readfdfunc[external_readfdlen] = func;
Packit fcad23
        external_readfd_data[external_readfdlen] = data;
Packit fcad23
        external_readfdlen++;
Packit fcad23
        DEBUGMSGTL(("fd_event_manager:register_readfd", "registered fd %d\n", fd));
Packit fcad23
        return FD_REGISTERED_OK;
Packit fcad23
    } else {
Packit fcad23
        snmp_log(LOG_CRIT, "register_readfd: too many file descriptors\n");
Packit fcad23
        return FD_REGISTRATION_FAILED;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Register a given fd for write events.  Call callback when events
Packit fcad23
 * are received.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
register_writefd(int fd, void (*func) (int, void *), void *data)
Packit fcad23
{
Packit fcad23
    if (external_writefdlen < NUM_EXTERNAL_FDS) {
Packit fcad23
        external_writefd[external_writefdlen] = fd;
Packit fcad23
        external_writefdfunc[external_writefdlen] = func;
Packit fcad23
        external_writefd_data[external_writefdlen] = data;
Packit fcad23
        external_writefdlen++;
Packit fcad23
        DEBUGMSGTL(("fd_event_manager:register_writefd", "registered fd %d\n", fd));
Packit fcad23
        return FD_REGISTERED_OK;
Packit fcad23
    } else {
Packit fcad23
        snmp_log(LOG_CRIT,
Packit fcad23
                 "register_writefd: too many file descriptors\n");
Packit fcad23
        return FD_REGISTRATION_FAILED;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Register a given fd for exception events.  Call callback when events
Packit fcad23
 * are received.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
register_exceptfd(int fd, void (*func) (int, void *), void *data)
Packit fcad23
{
Packit fcad23
    if (external_exceptfdlen < NUM_EXTERNAL_FDS) {
Packit fcad23
        external_exceptfd[external_exceptfdlen] = fd;
Packit fcad23
        external_exceptfdfunc[external_exceptfdlen] = func;
Packit fcad23
        external_exceptfd_data[external_exceptfdlen] = data;
Packit fcad23
        external_exceptfdlen++;
Packit fcad23
        DEBUGMSGTL(("fd_event_manager:register_exceptfd", "registered fd %d\n", fd));
Packit fcad23
        return FD_REGISTERED_OK;
Packit fcad23
    } else {
Packit fcad23
        snmp_log(LOG_CRIT,
Packit fcad23
                 "register_exceptfd: too many file descriptors\n");
Packit fcad23
        return FD_REGISTRATION_FAILED;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Unregister a given fd for read events.
Packit fcad23
 */ 
Packit fcad23
int
Packit fcad23
unregister_readfd(int fd)
Packit fcad23
{
Packit fcad23
    int             i, j;
Packit fcad23
Packit fcad23
    for (i = 0; i < external_readfdlen; i++) {
Packit fcad23
        if (external_readfd[i] == fd) {
Packit fcad23
            external_readfdlen--;
Packit fcad23
            for (j = i; j < external_readfdlen; j++) {
Packit fcad23
                external_readfd[j] = external_readfd[j + 1];
Packit fcad23
                external_readfdfunc[j] = external_readfdfunc[j + 1];
Packit fcad23
                external_readfd_data[j] = external_readfd_data[j + 1];
Packit fcad23
            }
Packit fcad23
            DEBUGMSGTL(("fd_event_manager:unregister_readfd", "unregistered fd %d\n", fd));
Packit fcad23
            external_fd_unregistered = 1;
Packit fcad23
            return FD_UNREGISTERED_OK;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return FD_NO_SUCH_REGISTRATION;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Unregister a given fd for read events.
Packit fcad23
 */ 
Packit fcad23
int
Packit fcad23
unregister_writefd(int fd)
Packit fcad23
{
Packit fcad23
    int             i, j;
Packit fcad23
Packit fcad23
    for (i = 0; i < external_writefdlen; i++) {
Packit fcad23
        if (external_writefd[i] == fd) {
Packit fcad23
            external_writefdlen--;
Packit fcad23
            for (j = i; j < external_writefdlen; j++) {
Packit fcad23
                external_writefd[j] = external_writefd[j + 1];
Packit fcad23
                external_writefdfunc[j] = external_writefdfunc[j + 1];
Packit fcad23
                external_writefd_data[j] = external_writefd_data[j + 1];
Packit fcad23
            }
Packit fcad23
            DEBUGMSGTL(("fd_event_manager:unregister_writefd", "unregistered fd %d\n", fd));
Packit fcad23
            external_fd_unregistered = 1;
Packit fcad23
            return FD_UNREGISTERED_OK;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return FD_NO_SUCH_REGISTRATION;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Unregister a given fd for exception events.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
unregister_exceptfd(int fd)
Packit fcad23
{
Packit fcad23
    int             i, j;
Packit fcad23
Packit fcad23
    for (i = 0; i < external_exceptfdlen; i++) {
Packit fcad23
        if (external_exceptfd[i] == fd) {
Packit fcad23
            external_exceptfdlen--;
Packit fcad23
            for (j = i; j < external_exceptfdlen; j++) {
Packit fcad23
                external_exceptfd[j] = external_exceptfd[j + 1];
Packit fcad23
                external_exceptfdfunc[j] = external_exceptfdfunc[j + 1];
Packit fcad23
                external_exceptfd_data[j] = external_exceptfd_data[j + 1];
Packit fcad23
            }
Packit fcad23
            DEBUGMSGTL(("fd_event_manager:unregister_exceptfd", "unregistered fd %d\n",
Packit fcad23
                        fd));
Packit fcad23
            external_fd_unregistered = 1;
Packit fcad23
            return FD_UNREGISTERED_OK;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return FD_NO_SUCH_REGISTRATION;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* 
Packit fcad23
 * NET-SNMP External Event Info 
Packit fcad23
 */
Packit fcad23
void netsnmp_external_event_info(int *numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
Packit fcad23
{
Packit fcad23
  netsnmp_large_fd_set lreadfds;
Packit fcad23
  netsnmp_large_fd_set lwritefds;
Packit fcad23
  netsnmp_large_fd_set lexceptfds;
Packit fcad23
Packit fcad23
  netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
Packit fcad23
  netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
Packit fcad23
  netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
Packit fcad23
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
Packit fcad23
Packit fcad23
  netsnmp_external_event_info2(numfds, &lreadfds, &lwritefds, &lexceptfds);
Packit fcad23
Packit fcad23
  if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
Packit fcad23
      || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0
Packit fcad23
      || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
Packit fcad23
  {
Packit fcad23
    snmp_log(LOG_ERR,
Packit fcad23
	     "Use netsnmp_external_event_info2() for processing"
Packit fcad23
	     " large file descriptors\n");
Packit fcad23
  }
Packit fcad23
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lreadfds);
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lwritefds);
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lexceptfds);
Packit fcad23
}
Packit fcad23
Packit fcad23
void netsnmp_external_event_info2(int *numfds,
Packit fcad23
                                  netsnmp_large_fd_set *readfds,
Packit fcad23
                                  netsnmp_large_fd_set *writefds,
Packit fcad23
                                  netsnmp_large_fd_set *exceptfds)
Packit fcad23
{
Packit fcad23
  int i;
Packit fcad23
Packit fcad23
  external_fd_unregistered = 0;
Packit fcad23
Packit fcad23
  for (i = 0; i < external_readfdlen; i++) {
Packit fcad23
    NETSNMP_LARGE_FD_SET(external_readfd[i], readfds);
Packit fcad23
    if (external_readfd[i] >= *numfds)
Packit fcad23
      *numfds = external_readfd[i] + 1;
Packit fcad23
  }
Packit fcad23
  for (i = 0; i < external_writefdlen; i++) {
Packit fcad23
    NETSNMP_LARGE_FD_SET(external_writefd[i], writefds);
Packit fcad23
    if (external_writefd[i] >= *numfds)
Packit fcad23
      *numfds = external_writefd[i] + 1;
Packit fcad23
  }
Packit fcad23
  for (i = 0; i < external_exceptfdlen; i++) {
Packit fcad23
    NETSNMP_LARGE_FD_SET(external_exceptfd[i], exceptfds);
Packit fcad23
    if (external_exceptfd[i] >= *numfds)
Packit fcad23
      *numfds = external_exceptfd[i] + 1;
Packit fcad23
  }
Packit fcad23
}
Packit fcad23
Packit fcad23
/* 
Packit fcad23
 * NET-SNMP Dispatch External Events 
Packit fcad23
 */
Packit fcad23
void netsnmp_dispatch_external_events(int *count, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
Packit fcad23
{
Packit fcad23
  netsnmp_large_fd_set lreadfds;
Packit fcad23
  netsnmp_large_fd_set lwritefds;
Packit fcad23
  netsnmp_large_fd_set lexceptfds;
Packit fcad23
Packit fcad23
  netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
Packit fcad23
  netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
Packit fcad23
  netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
Packit fcad23
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
Packit fcad23
  netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
Packit fcad23
Packit fcad23
  netsnmp_dispatch_external_events2(count, &lreadfds, &lwritefds, &lexceptfds);
Packit fcad23
Packit fcad23
  if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
Packit fcad23
      || netsnmp_copy_large_fd_set_to_fd_set(writefds,  &lwritefds) < 0
Packit fcad23
      || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
Packit fcad23
  {
Packit fcad23
    snmp_log(LOG_ERR,
Packit fcad23
	     "Use netsnmp_dispatch_external_events2() for processing"
Packit fcad23
	     " large file descriptors\n");
Packit fcad23
  }
Packit fcad23
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lreadfds);
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lwritefds);
Packit fcad23
  netsnmp_large_fd_set_cleanup(&lexceptfds);
Packit fcad23
}
Packit fcad23
Packit fcad23
void netsnmp_dispatch_external_events2(int *count,
Packit fcad23
                                       netsnmp_large_fd_set *readfds,
Packit fcad23
                                       netsnmp_large_fd_set *writefds,
Packit fcad23
                                       netsnmp_large_fd_set *exceptfds)
Packit fcad23
{
Packit fcad23
  int i;
Packit fcad23
  for (i = 0;
Packit fcad23
       *count && (i < external_readfdlen) && !external_fd_unregistered; i++) {
Packit fcad23
      if (NETSNMP_LARGE_FD_ISSET(external_readfd[i], readfds)) {
Packit fcad23
          DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
Packit fcad23
                     "readfd[%d] = %d\n", i, external_readfd[i]));
Packit fcad23
          external_readfdfunc[i] (external_readfd[i],
Packit fcad23
                                  external_readfd_data[i]);
Packit fcad23
          NETSNMP_LARGE_FD_CLR(external_readfd[i], readfds);
Packit fcad23
          (*count)--;
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
  for (i = 0;
Packit fcad23
       *count && (i < external_writefdlen) && !external_fd_unregistered; i++) {
Packit fcad23
      if (NETSNMP_LARGE_FD_ISSET(external_writefd[i], writefds)) {
Packit fcad23
          DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
Packit fcad23
                     "writefd[%d] = %d\n", i, external_writefd[i]));
Packit fcad23
          external_writefdfunc[i] (external_writefd[i],
Packit fcad23
                                   external_writefd_data[i]);
Packit fcad23
          NETSNMP_LARGE_FD_CLR(external_writefd[i], writefds);
Packit fcad23
          (*count)--;
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
  for (i = 0;
Packit fcad23
       *count && (i < external_exceptfdlen) && !external_fd_unregistered; i++) {
Packit fcad23
      if (NETSNMP_LARGE_FD_ISSET(external_exceptfd[i], exceptfds)) {
Packit fcad23
          DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
Packit fcad23
                     "exceptfd[%d] = %d\n", i, external_exceptfd[i]));
Packit fcad23
          external_exceptfdfunc[i] (external_exceptfd[i],
Packit fcad23
                                    external_exceptfd_data[i]);
Packit fcad23
          NETSNMP_LARGE_FD_CLR(external_exceptfd[i], exceptfds);
Packit fcad23
          (*count)--;
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
}
Packit fcad23
#else  /*  !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
Packit fcad23
netsnmp_feature_unused(fd_event_manager);
Packit fcad23
#endif /*  !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */