net-snmp 5.7
large_fd_set.c
Go to the documentation of this file.
00001 
00008 #include <net-snmp/net-snmp-config.h>
00009 
00010 #include <stdio.h>
00011 #include <string.h> /* memset(), which is invoked by FD_ZERO() */
00012 
00013 #ifdef HAVE_STDLIB_H
00014 #include <stdlib.h>
00015 #endif
00016 
00017 #include <net-snmp/net-snmp-includes.h>
00018 #include <net-snmp/library/snmp_assert.h>
00019 #include <net-snmp/library/large_fd_set.h>
00020 
00021 
00022 #if ! defined(cygwin) && defined(HAVE_WINSOCK_H)
00023 
00024 void
00025 netsnmp_large_fd_setfd(SOCKET fd, netsnmp_large_fd_set * fdset)
00026 {
00027     unsigned        i;
00028 
00029     netsnmp_assert(fd != INVALID_SOCKET);
00030 
00031     if (fdset->lfs_set.fd_count == fdset->lfs_setsize)
00032         netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1));
00033 
00034     for (i = 0; i < fdset->lfs_set.fd_count; i++) {
00035         if (fdset->lfs_set.fd_array[i] == (SOCKET) (fd))
00036             break;
00037     }
00038 
00039     if (i == fdset->lfs_set.fd_count
00040         && fdset->lfs_set.fd_count < fdset->lfs_setsize) {
00041         fdset->lfs_set.fd_count++;
00042         fdset->lfs_set.fd_array[i] = (fd);
00043     }
00044 }
00045 
00046 void
00047 netsnmp_large_fd_clr(SOCKET fd, netsnmp_large_fd_set * fdset)
00048 {
00049     unsigned        i;
00050 
00051     netsnmp_assert(fd != INVALID_SOCKET);
00052 
00053     for (i = 0; i < fdset->lfs_set.fd_count; i++) {
00054         if (fdset->lfs_set.fd_array[i] == (fd)) {
00055             while (i < fdset->lfs_set.fd_count - 1) {
00056                 fdset->lfs_set.fd_array[i] =
00057                     fdset->lfs_set.fd_array[i + 1];
00058                 i++;
00059             }
00060             fdset->lfs_set.fd_count--;
00061             break;
00062         }
00063     }
00064 }
00065 
00066 int
00067 netsnmp_large_fd_is_set(SOCKET fd, netsnmp_large_fd_set * fdset)
00068 {
00069     unsigned int    i;
00070 
00071     netsnmp_assert(fd != INVALID_SOCKET);
00072 
00073     for (i = 0; i < fdset->lfs_set.fd_count; i++) {
00074         if (fdset->lfs_set.fd_array[i] == fd)
00075             return 1;
00076     }
00077     return 0;
00078 }
00079 
00080 #else
00081 
00082 void
00083 netsnmp_large_fd_setfd(int fd, netsnmp_large_fd_set * fdset)
00084 {
00085     netsnmp_assert(fd >= 0);
00086 
00087     while (fd >= (int)fdset->lfs_setsize)
00088         netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1));
00089 
00090     FD_SET(fd, fdset->lfs_setptr);
00091 }
00092 
00093 void
00094 netsnmp_large_fd_clr(int fd, netsnmp_large_fd_set * fdset)
00095 {
00096     netsnmp_assert(fd >= 0);
00097 
00098     if (fd < (int)fdset->lfs_setsize)
00099         FD_CLR(fd, fdset->lfs_setptr);
00100 }
00101 
00102 int
00103 netsnmp_large_fd_is_set(int fd, netsnmp_large_fd_set * fdset)
00104 {
00105     netsnmp_assert(fd >= 0);
00106 
00107     return fd < (int)fdset->lfs_setsize && FD_ISSET(fd, fdset->lfs_setptr);
00108 }
00109 
00110 #endif
00111 
00112 void
00113 netsnmp_large_fd_set_init(netsnmp_large_fd_set * fdset, int setsize)
00114 {
00115     fdset->lfs_setsize = 0;
00116     fdset->lfs_setptr  = NULL;
00117     netsnmp_large_fd_set_resize(fdset, setsize);
00118 }
00119 
00120 int
00121 netsnmp_large_fd_set_select(int numfds, netsnmp_large_fd_set *readfds,
00122                      netsnmp_large_fd_set *writefds,
00123                      netsnmp_large_fd_set *exceptfds,
00124                      struct timeval *timeout)
00125 {
00126 #if defined(cygwin) || !defined(HAVE_WINSOCK_H)
00127     /* Bit-set representation: make sure all fds have at least size 'numfds'. */
00128     if (readfds && readfds->lfs_setsize < numfds)
00129         netsnmp_large_fd_set_resize(readfds, numfds);
00130     if (writefds && writefds->lfs_setsize < numfds)
00131         netsnmp_large_fd_set_resize(writefds, numfds);
00132     if (exceptfds && exceptfds->lfs_setsize < numfds)
00133         netsnmp_large_fd_set_resize(exceptfds, numfds);
00134 #else
00135     /* Array representation: no resizing is necessary. */
00136 #endif
00137 
00138     return select(numfds, readfds->lfs_setptr, writefds->lfs_setptr,
00139                   exceptfds->lfs_setptr, timeout);
00140 }
00141 
00142 void
00143 netsnmp_large_fd_set_resize(netsnmp_large_fd_set * fdset, int setsize)
00144 {
00145     int             fd_set_bytes;
00146 
00147     if (fdset->lfs_setsize == setsize)
00148         return;
00149 
00150     if (setsize > FD_SETSIZE) {
00151         fd_set_bytes = NETSNMP_FD_SET_BYTES(setsize);
00152         if (fdset->lfs_setsize > FD_SETSIZE)
00153             fdset->lfs_setptr = (fd_set *)realloc(fdset->lfs_setptr, fd_set_bytes);
00154         else {
00155             fdset->lfs_setptr = (fd_set *)malloc(fd_set_bytes);
00156            *fdset->lfs_setptr = fdset->lfs_set;
00157         }
00158     } else {
00159         if (fdset->lfs_setsize > FD_SETSIZE) {
00160             fdset->lfs_set = *fdset->lfs_setptr;
00161             free(fdset->lfs_setptr);
00162         }
00163         fdset->lfs_setptr = &fdset->lfs_set;
00164     }
00165 
00166 #if ! (! defined(cygwin) && defined(HAVE_WINSOCK_H))
00167     {
00168         int             i;
00169 
00170         /*
00171          * Unix: clear the file descriptors defined in the resized *fdset
00172          * but that were not defined in the original *fdset.
00173          */
00174         for (i = fdset->lfs_setsize; i < setsize; i++)
00175             FD_CLR(i, fdset->lfs_setptr);
00176     }
00177 #endif
00178 
00179     fdset->lfs_setsize = setsize;
00180 }
00181 
00182 void
00183 netsnmp_large_fd_set_cleanup(netsnmp_large_fd_set * fdset)
00184 {
00185     netsnmp_large_fd_set_resize(fdset, 0);
00186     fdset->lfs_setsize = 0;
00187     fdset->lfs_setptr  = NULL;
00188 }
00189 
00190 void
00191 netsnmp_copy_fd_set_to_large_fd_set(netsnmp_large_fd_set * dst,
00192                                     const fd_set * src)
00193 {
00194     netsnmp_large_fd_set_resize(dst, FD_SETSIZE);
00195     *dst->lfs_setptr = *src;
00196 }
00197 
00198 int
00199 netsnmp_copy_large_fd_set_to_fd_set(fd_set * dst,
00200                                     const netsnmp_large_fd_set * src)
00201 {
00202     /* Report failure if *src is larger than FD_SETSIZE. */
00203     if (src->lfs_setsize > FD_SETSIZE) {
00204         FD_ZERO(dst);
00205         return -1;
00206     }
00207 
00208     *dst = *src->lfs_setptr;
00209 
00210 #if ! (! defined(cygwin) && defined(HAVE_WINSOCK_H))
00211     {
00212         int             i;
00213 
00214         /* Unix: clear any file descriptors defined in *dst but not in *src. */
00215         for (i = src->lfs_setsize; i < FD_SETSIZE; ++i)
00216           FD_CLR(i, dst);
00217     }
00218 #endif
00219 
00220     return 0;
00221 }