1 /**
2  * @file  large_fd_set.h
3  *
4  * @brief Macro's and functions for manipulation of large file descriptor sets.
5  */
6 
7 
8 #ifndef LARGE_FD_SET_H
9 #define LARGE_FD_SET_H
10 
11 
12 #include <net-snmp/net-snmp-config.h>
13 #include <net-snmp/types.h>
14 
15 #ifdef HAVE_SYS_SELECT_H
16 #include <sys/select.h>
17 #endif
18 
19 #if defined(HAVE_WINSOCK_H) && !defined(_WINSOCKAPI_) && !defined(_WINSOCK_H)
20 #error <winsock.h> or <winsock2.h> must have been included before this file.
21 #endif
22 
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 
29 
30 /**
31  * Add socket fd to the set *fdset if not yet present.
32  * Enlarges the set if necessary.
33  */
34 #define NETSNMP_LARGE_FD_SET(fd, fdset) \
35                     netsnmp_large_fd_setfd(fd, fdset)
36 
37 /**
38  * Remove socket fd from the set *fdset.
39  * Do nothing if fd is not present in *fdset.
40  * Do nothing if fd >= fdset->lfs_setsize.
41  */
42 #define NETSNMP_LARGE_FD_CLR(fd, fdset) \
43                     netsnmp_large_fd_clr(fd, fdset)
44 
45 /**
46  * Test whether set *fdset contains socket fd.
47  * Evaluates to zero (false) if fd >= fdset->lfs_setsize.
48  */
49 #define NETSNMP_LARGE_FD_ISSET(fd, fdset) \
50                     netsnmp_large_fd_is_set(fd, fdset)
51 
52 #if !defined(cygwin) && defined(HAVE_WINSOCK_H)
53 
54 /**
55  * Number of bytes needed to store a number of file descriptors as a
56  * struct fd_set.
57  */
58 #define NETSNMP_FD_SET_BYTES(setsize)                                   \
59     (sizeof(fd_set) + ((setsize) > FD_SETSIZE ?                         \
60                        ((setsize) - FD_SETSIZE) * sizeof(SOCKET) : 0))
61 
62 /** Remove all sockets from the set *fdset. */
63 #define NETSNMP_LARGE_FD_ZERO(fdset) \
64     do { (fdset)->lfs_setptr->fd_count = 0; } while(0)
65 
66 
67 struct timeval;
68 
69 
70 NETSNMP_IMPORT
71 void   netsnmp_large_fd_setfd( SOCKET fd, netsnmp_large_fd_set *fdset);
72 NETSNMP_IMPORT
73 void   netsnmp_large_fd_clr(   SOCKET fd, netsnmp_large_fd_set *fdset);
74 NETSNMP_IMPORT
75 int    netsnmp_large_fd_is_set(SOCKET fd, netsnmp_large_fd_set *fdset);
76 
77 #else
78 
79 /**
80  * Size of a single element of the array with file descriptor bitmasks.
81  *
82  * According to SUSv2, this array must have the name fds_bits. See also
83  * <a href="http://www.opengroup.org/onlinepubs/007908775/xsh/systime.h.html">The Single UNIX Specification, Version 2, &lt;sys/time.h&gt;</a>.
84  */
85 #define NETSNMP_FD_MASK_SIZE sizeof(((fd_set*)0)->fds_bits[0])
86 
87 /** Number of bits in one element of the fd_set.fds_bits array. */
88 #define NETSNMP_BITS_PER_FD_MASK (8 * NETSNMP_FD_MASK_SIZE)
89 
90 /** Number of elements needed for the fds_bits array. */
91 #define NETSNMP_FD_SET_ELEM_COUNT(setsize) \
92     (setsize + NETSNMP_BITS_PER_FD_MASK - 1) / NETSNMP_BITS_PER_FD_MASK
93 
94 /**
95  * Number of bytes needed to store a number of file descriptors as a
96  * struct fd_set.
97  */
98 #define NETSNMP_FD_SET_BYTES(setsize)                                    \
99     (sizeof(fd_set) + ((setsize) > FD_SETSIZE ?                          \
100                        NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \
101                        * NETSNMP_FD_MASK_SIZE : 0))
102 
103 /** Remove all file descriptors from the set *fdset. */
104 #define NETSNMP_LARGE_FD_ZERO(fdset)                            \
105     do {                                                        \
106         memset((fdset)->lfs_setptr, 0,                          \
107                NETSNMP_FD_SET_BYTES((fdset)->lfs_setsize));     \
108     } while (0)
109 
110 
111 void   netsnmp_large_fd_setfd( int fd, netsnmp_large_fd_set *fdset);
112 void   netsnmp_large_fd_clr(   int fd, netsnmp_large_fd_set *fdset);
113 int    netsnmp_large_fd_is_set(int fd, netsnmp_large_fd_set *fdset);
114 
115 #endif
116 
117 /**
118  * Initialize a netsnmp_large_fd_set structure.
119  *
120  * Note: this function only initializes the lfs_setsize and lfs_setptr
121  * members of netsnmp_large_fd_set, not the file descriptor set itself.
122  * The file descriptor set must be initialized separately, e.g. via
123  * NETSNMP_LARGE_FD_CLR().
124  */
125 NETSNMP_IMPORT
126 void   netsnmp_large_fd_set_init(   netsnmp_large_fd_set *fdset, int setsize);
127 
128 /**
129  * Modify the size of a file descriptor set and preserve the first
130  * min(fdset->lfs_setsize, setsize) file descriptors.
131  *
132  * Returns 1 upon success or 0 if memory allocation failed.
133  */
134 int    netsnmp_large_fd_set_resize( netsnmp_large_fd_set *fdset, int setsize);
135 
136 /**
137  * Synchronous I/O multiplexing for large file descriptor sets.
138  *
139  * On POSIX systems, any file descriptor set with size below numfds will be
140  * resized before invoking select().
141  *
142  * @see See also select(2) for more information.
143  */
144 NETSNMP_IMPORT
145 int    netsnmp_large_fd_set_select(int numfds, netsnmp_large_fd_set *readfds,
146 			    netsnmp_large_fd_set *writefds,
147 			    netsnmp_large_fd_set *exceptfds,
148 			    struct timeval *timeout);
149 
150 /** Deallocate the memory allocated by netsnmp_large_fd_set_init. */
151 NETSNMP_IMPORT
152 void   netsnmp_large_fd_set_cleanup(netsnmp_large_fd_set *fdset);
153 
154 /**
155  * Copy an fd_set to a netsnmp_large_fd_set structure.
156  *
157  * @note dst must have been initialized before this function is called.
158  */
159 void   netsnmp_copy_fd_set_to_large_fd_set(netsnmp_large_fd_set *dst,
160                                                    const fd_set *src);
161 
162 /**
163  * Copy a netsnmp_large_fd_set structure into an fd_set.
164  *
165  * @return 0 upon success, -1 when copying fails because *src is too large to
166  *         fit into *dst.
167  */
168 int    netsnmp_copy_large_fd_set_to_fd_set(              fd_set *dst,
169                                      const netsnmp_large_fd_set *src);
170 
171 #ifdef __cplusplus
172 }
173 #endif
174 
175 
176 #endif /* LARGE_FD_SET_H */
177