net-snmp 5.7
|
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 }