1 /*
2 Copyright (c) 2007-2011 iMatix Corporation
3 Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
4
5 This file is part of 0MQ.
6
7 0MQ is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 0MQ is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdio.h>
22 #include <string.h>
23 #ifndef ZMQ_HAVE_WINDOWS
24 #include <sys/stat.h>
25 #endif
26
27 #include "../include/zmq.h"
28 #include "options.hpp"
29 #include "err.hpp"
30
options_t()31 zmq::options_t::options_t () :
32 hwm (0),
33 swap (0),
34 affinity (0),
35 rate (40 * 1000),
36 recovery_ivl (10),
37 recovery_ivl_msec (-1),
38 use_multicast_loop (true),
39 sndbuf (0),
40 rcvbuf (0),
41 type (-1),
42 linger (-1),
43 reconnect_ivl (100),
44 reconnect_ivl_max (0),
45 backlog (100),
46 requires_in (false),
47 requires_out (false),
48 immediate_connect (true),
49 rcvtimeo (-1),
50 sndtimeo (-1)
51 {
52 }
53
setsockopt(int option_,const void * optval_,size_t optvallen_)54 int zmq::options_t::setsockopt (int option_, const void *optval_,
55 size_t optvallen_)
56 {
57 switch (option_) {
58
59 case ZMQ_HWM:
60 if (optvallen_ != sizeof (uint64_t)) {
61 errno = EINVAL;
62 return -1;
63 }
64 hwm = *((uint64_t*) optval_);
65 return 0;
66
67 case ZMQ_SWAP:
68 if (optvallen_ != sizeof (int64_t) || *((int64_t*) optval_) < 0) {
69 errno = EINVAL;
70 return -1;
71 }
72 // Check that SWAP directory (.) is writable
73 struct stat stat_buf;
74 #if (ZMQ_HAVE_ANDROID || ZMQ_HAVE_LINUX)
75 if (stat (".", &stat_buf) || ((stat_buf.st_mode & S_IWUSR) == 0)) {
76 #else
77 if (stat (".", &stat_buf) || ((stat_buf.st_mode & S_IWRITE) == 0)) {
78 #endif
79 errno = EACCES;
80 return -1;
81 }
82 swap = *((int64_t*) optval_);
83 return 0;
84
85 case ZMQ_AFFINITY:
86 if (optvallen_ != sizeof (uint64_t)) {
87 errno = EINVAL;
88 return -1;
89 }
90 affinity = *((uint64_t*) optval_);
91 return 0;
92
93 case ZMQ_IDENTITY:
94
95 // Empty identity is invalid as well as identity longer than
96 // 255 bytes. Identity starting with binary zero is invalid
97 // as these are used for auto-generated identities.
98 if (optvallen_ < 1 || optvallen_ > 255 ||
99 *((const unsigned char*) optval_) == 0) {
100 errno = EINVAL;
101 return -1;
102 }
103 identity.assign ((const unsigned char*) optval_, optvallen_);
104 return 0;
105
106 case ZMQ_RATE:
107 if (optvallen_ != sizeof (int64_t) || *((int64_t*) optval_) < 0) {
108 errno = EINVAL;
109 return -1;
110 }
111 rate = (uint32_t) *((int64_t*) optval_);
112 return 0;
113
114 case ZMQ_RECOVERY_IVL:
115 if (optvallen_ != sizeof (int64_t) || *((int64_t*) optval_) < 0) {
116 errno = EINVAL;
117 return -1;
118 }
119 recovery_ivl = (uint32_t) *((int64_t*) optval_);
120 return 0;
121
122 case ZMQ_RECOVERY_IVL_MSEC:
123 if (optvallen_ != sizeof (int64_t) || *((int64_t*) optval_) < 0) {
124 errno = EINVAL;
125 return -1;
126 }
127 recovery_ivl_msec = (int32_t) *((int64_t*) optval_);
128 return 0;
129
130 case ZMQ_MCAST_LOOP:
131 if (optvallen_ != sizeof (int64_t)) {
132 errno = EINVAL;
133 return -1;
134 }
135 if ((int64_t) *((int64_t*) optval_) == 0)
136 use_multicast_loop = false;
137 else if ((int64_t) *((int64_t*) optval_) == 1)
138 use_multicast_loop = true;
139 else {
140 errno = EINVAL;
141 return -1;
142 }
143 return 0;
144
145 case ZMQ_SNDBUF:
146 if (optvallen_ != sizeof (uint64_t)) {
147 errno = EINVAL;
148 return -1;
149 }
150 sndbuf = *((uint64_t*) optval_);
151 return 0;
152
153 case ZMQ_RCVBUF:
154 if (optvallen_ != sizeof (uint64_t)) {
155 errno = EINVAL;
156 return -1;
157 }
158 rcvbuf = *((uint64_t*) optval_);
159 return 0;
160
161 case ZMQ_LINGER:
162 if (optvallen_ != sizeof (int)) {
163 errno = EINVAL;
164 return -1;
165 }
166 linger = *((int*) optval_);
167 return 0;
168
169 case ZMQ_RECONNECT_IVL:
170 if (optvallen_ != sizeof (int)) {
171 errno = EINVAL;
172 return -1;
173 }
174 if (*((int*) optval_) < 0) {
175 errno = EINVAL;
176 return -1;
177 }
178 reconnect_ivl = *((int*) optval_);
179 return 0;
180
181 case ZMQ_RECONNECT_IVL_MAX:
182 if (optvallen_ != sizeof (int)) {
183 errno = EINVAL;
184 return -1;
185 }
186 if (*((int*) optval_) < 0) {
187 errno = EINVAL;
188 return -1;
189 }
190 reconnect_ivl_max = *((int*) optval_);
191 return 0;
192
193 case ZMQ_BACKLOG:
194 if (optvallen_ != sizeof (int)) {
195 errno = EINVAL;
196 return -1;
197 }
198 backlog = *((int*) optval_);
199 return 0;
200
201 case ZMQ_RCVTIMEO:
202 if (optvallen_ != sizeof (int)) {
203 errno = EINVAL;
204 return -1;
205 }
206 rcvtimeo = *((int*) optval_);
207 return 0;
208
209 case ZMQ_SNDTIMEO:
210 if (optvallen_ != sizeof (int)) {
211 errno = EINVAL;
212 return -1;
213 }
214 sndtimeo = *((int*) optval_);
215 return 0;
216
217 }
218
219 errno = EINVAL;
220 return -1;
221 }
222
223 int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
224 {
225 switch (option_) {
226
227 case ZMQ_HWM:
228 if (*optvallen_ < sizeof (uint64_t)) {
229 errno = EINVAL;
230 return -1;
231 }
232 *((uint64_t*) optval_) = hwm;
233 *optvallen_ = sizeof (uint64_t);
234 return 0;
235
236 case ZMQ_SWAP:
237 if (*optvallen_ < sizeof (int64_t)) {
238 errno = EINVAL;
239 return -1;
240 }
241 *((int64_t*) optval_) = swap;
242 *optvallen_ = sizeof (int64_t);
243 return 0;
244
245 case ZMQ_AFFINITY:
246 if (*optvallen_ < sizeof (uint64_t)) {
247 errno = EINVAL;
248 return -1;
249 }
250 *((uint64_t*) optval_) = affinity;
251 *optvallen_ = sizeof (uint64_t);
252 return 0;
253
254 case ZMQ_IDENTITY:
255 if (*optvallen_ < identity.size ()) {
256 errno = EINVAL;
257 return -1;
258 }
259 memcpy (optval_, identity.data (), identity.size ());
260 *optvallen_ = identity.size ();
261 return 0;
262
263
264 case ZMQ_RATE:
265 if (*optvallen_ < sizeof (int64_t)) {
266 errno = EINVAL;
267 return -1;
268 }
269 *((int64_t*) optval_) = rate;
270 *optvallen_ = sizeof (int64_t);
271 return 0;
272
273 case ZMQ_RECOVERY_IVL:
274 if (*optvallen_ < sizeof (int64_t)) {
275 errno = EINVAL;
276 return -1;
277 }
278 *((int64_t*) optval_) = recovery_ivl;
279 *optvallen_ = sizeof (int64_t);
280 return 0;
281
282 case ZMQ_RECOVERY_IVL_MSEC:
283 if (*optvallen_ < sizeof (int64_t)) {
284 errno = EINVAL;
285 return -1;
286 }
287 *((int64_t*) optval_) = recovery_ivl_msec;
288 *optvallen_ = sizeof (int64_t);
289 return 0;
290
291 case ZMQ_MCAST_LOOP:
292 if (*optvallen_ < sizeof (int64_t)) {
293 errno = EINVAL;
294 return -1;
295 }
296 *((int64_t*) optval_) = use_multicast_loop ? 1 : 0;
297 *optvallen_ = sizeof (int64_t);
298 return 0;
299
300 case ZMQ_SNDBUF:
301 if (*optvallen_ < sizeof (uint64_t)) {
302 errno = EINVAL;
303 return -1;
304 }
305 *((uint64_t*) optval_) = sndbuf;
306 *optvallen_ = sizeof (uint64_t);
307 return 0;
308
309 case ZMQ_RCVBUF:
310 if (*optvallen_ < sizeof (uint64_t)) {
311 errno = EINVAL;
312 return -1;
313 }
314 *((uint64_t*) optval_) = rcvbuf;
315 *optvallen_ = sizeof (uint64_t);
316 return 0;
317
318 case ZMQ_TYPE:
319 if (*optvallen_ < sizeof (int)) {
320 errno = EINVAL;
321 return -1;
322 }
323 *((int*) optval_) = type;
324 *optvallen_ = sizeof (int);
325 return 0;
326
327 case ZMQ_LINGER:
328 if (*optvallen_ < sizeof (int)) {
329 errno = EINVAL;
330 return -1;
331 }
332 *((int*) optval_) = linger;
333 *optvallen_ = sizeof (int);
334 return 0;
335
336 case ZMQ_RECONNECT_IVL:
337 if (*optvallen_ < sizeof (int)) {
338 errno = EINVAL;
339 return -1;
340 }
341 *((int*) optval_) = reconnect_ivl;
342 *optvallen_ = sizeof (int);
343 return 0;
344
345 case ZMQ_RECONNECT_IVL_MAX:
346 if (*optvallen_ < sizeof (int)) {
347 errno = EINVAL;
348 return -1;
349 }
350 *((int*) optval_) = reconnect_ivl_max;
351 *optvallen_ = sizeof (int);
352 return 0;
353
354 case ZMQ_BACKLOG:
355 if (*optvallen_ < sizeof (int)) {
356 errno = EINVAL;
357 return -1;
358 }
359 *((int*) optval_) = backlog;
360 *optvallen_ = sizeof (int);
361 return 0;
362
363 case ZMQ_RCVTIMEO:
364 if (*optvallen_ < sizeof (int)) {
365 errno = EINVAL;
366 return -1;
367 }
368 *((int*) optval_) = rcvtimeo;
369 *optvallen_ = sizeof (int);
370 return 0;
371
372 case ZMQ_SNDTIMEO:
373 if (*optvallen_ < sizeof (int)) {
374 errno = EINVAL;
375 return -1;
376 }
377 *((int*) optval_) = sndtimeo;
378 *optvallen_ = sizeof (int);
379 return 0;
380
381 }
382
383 errno = EINVAL;
384 return -1;
385 }
386