summaryrefslogtreecommitdiff
path: root/include/net-snmp/library/large_fd_set.h
blob: 9b547cd3043332364d52cab469b852b5ac087a2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
 * @file  large_fd_set.h
 *
 * @brief Macro's and functions for manipulation of large file descriptor sets.
 */


#ifndef LARGE_FD_SET_H
#define LARGE_FD_SET_H


#include <net-snmp/net-snmp-config.h>
#include <net-snmp/types.h>

#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif

#if defined(HAVE_WINSOCK_H) && !defined(_WINSOCKAPI_) && !defined(_WINSOCK_H)
#error <winsock.h> or <winsock2.h> must have been included before this file.
#endif


#ifdef __cplusplus
extern "C" {
#endif



/**
 * Add socket fd to the set *fdset if not yet present.
 * Enlarges the set if necessary.
 */
#define NETSNMP_LARGE_FD_SET(fd, fdset) \
                    netsnmp_large_fd_setfd(fd, fdset)

/**
 * Remove socket fd from the set *fdset.
 * Do nothing if fd is not present in *fdset.
 * Do nothing if fd >= fdset->lfs_setsize.
 */
#define NETSNMP_LARGE_FD_CLR(fd, fdset) \
                    netsnmp_large_fd_clr(fd, fdset)

/**
 * Test whether set *fdset contains socket fd.
 * Evaluates to zero (false) if fd >= fdset->lfs_setsize.
 */
#define NETSNMP_LARGE_FD_ISSET(fd, fdset) \
                    netsnmp_large_fd_is_set(fd, fdset)

#if !defined(cygwin) && defined(HAVE_WINSOCK_H)

/**
 * Number of bytes needed to store a number of file descriptors as a
 * struct fd_set.
 */
#define NETSNMP_FD_SET_BYTES(setsize)                           \
    (sizeof(fd_set) + ((setsize) - FD_SETSIZE) * sizeof(SOCKET))

/** Remove all sockets from the set *fdset. */
#define NETSNMP_LARGE_FD_ZERO(fdset) \
    do { (fdset)->lfs_setptr->fd_count = 0; } while(0)


NETSNMP_IMPORT
void   netsnmp_large_fd_setfd( SOCKET fd, netsnmp_large_fd_set *fdset);
NETSNMP_IMPORT
void   netsnmp_large_fd_clr(   SOCKET fd, netsnmp_large_fd_set *fdset);
NETSNMP_IMPORT
int    netsnmp_large_fd_is_set(SOCKET fd, netsnmp_large_fd_set *fdset);

#else

/**
 * Size of a single element of the array with file descriptor bitmasks.
 *
 * According to SUSv2, this array must have the name fds_bits. See also
 * <a href="http://www.opengroup.org/onlinepubs/007908775/xsh/systime.h.html">The Single UNIX Specification, Version 2, &lt;sys/time.h&gt;</a>.
 */
#define NETSNMP_FD_MASK_SIZE sizeof(((fd_set*)0)->fds_bits[0])

/** Number of bits in one element of the fd_set.fds_bits array. */
#define NETSNMP_BITS_PER_FD_MASK (8 * NETSNMP_FD_MASK_SIZE)

/** Number of elements needed for the fds_bits array. */
#define NETSNMP_FD_SET_ELEM_COUNT(setsize) \
    (setsize + NETSNMP_BITS_PER_FD_MASK - 1) / NETSNMP_BITS_PER_FD_MASK

/**
 * Number of bytes needed to store a number of file descriptors as a
 * struct fd_set.
 */
#define NETSNMP_FD_SET_BYTES(setsize)                                   \
    (sizeof(fd_set) + NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \
     * NETSNMP_FD_MASK_SIZE)

/** Remove all file descriptors from the set *fdset. */
#define NETSNMP_LARGE_FD_ZERO(fdset)                            \
    do {                                                        \
        memset((fdset)->lfs_setptr, 0,                          \
               NETSNMP_FD_SET_BYTES((fdset)->lfs_setsize));     \
    } while (0)


void   netsnmp_large_fd_setfd( int fd, netsnmp_large_fd_set *fdset);
void   netsnmp_large_fd_clr(   int fd, netsnmp_large_fd_set *fdset);
int    netsnmp_large_fd_is_set(int fd, netsnmp_large_fd_set *fdset);

#endif

/**
 * Initialize a netsnmp_large_fd_set structure.
 *
 * Note: this function only initializes the lfs_setsize and lfs_setptr
 * members of netsnmp_large_fd_set, not the file descriptor set itself.
 * The file descriptor set must be initialized separately, e.g. via
 * NETSNMP_LARGE_FD_CLR().
 */
NETSNMP_IMPORT
void   netsnmp_large_fd_set_init(   netsnmp_large_fd_set *fdset, int setsize);

/**
 * Modify the size of a file descriptor set and preserve the first
 * min(fdset->lfs_setsize, setsize) file descriptors.
 *
 * Returns 1 upon success or 0 if memory allocation failed.
 */
int    netsnmp_large_fd_set_resize( netsnmp_large_fd_set *fdset, int setsize);

/**
 * Synchronous I/O multiplexing for large file descriptor sets.
 *
 * On POSIX systems, any file descriptor set with size below numfds will be
 * resized before invoking select().
 *
 * @see See also select(2) for more information.
 */
NETSNMP_IMPORT
int    netsnmp_large_fd_set_select(int numfds, netsnmp_large_fd_set *readfds,
			    netsnmp_large_fd_set *writefds,
			    netsnmp_large_fd_set *exceptfds,
			    struct timeval *timeout);

/** Deallocate the memory allocated by netsnmp_large_fd_set_init. */
NETSNMP_IMPORT
void   netsnmp_large_fd_set_cleanup(netsnmp_large_fd_set *fdset);

/**
 * Copy an fd_set to a netsnmp_large_fd_set structure.
 *
 * @note dst must have been initialized before this function is called.
 */
void   netsnmp_copy_fd_set_to_large_fd_set(netsnmp_large_fd_set *dst,
                                                   const fd_set *src);

/**
 * Copy a netsnmp_large_fd_set structure into an fd_set.
 *
 * @return 0 upon success, -1 when copying fails because *src is too large to
 *         fit into *dst.
 */
int    netsnmp_copy_large_fd_set_to_fd_set(              fd_set *dst,
                                     const netsnmp_large_fd_set *src);

#ifdef __cplusplus
}
#endif


#endif /* LARGE_FD_SET_H */