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