Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include "macros.hpp"
32 : #include "platform.hpp"
33 :
34 : #include "clock.hpp"
35 : #include "err.hpp"
36 : #include "thread.hpp"
37 : #include "atomic_counter.hpp"
38 : #include "atomic_ptr.hpp"
39 : #include <assert.h>
40 :
41 : #if !defined ZMQ_HAVE_WINDOWS
42 : # include <unistd.h>
43 : #else
44 : # include "windows.hpp"
45 : #endif
46 :
47 : #if defined (ZMQ_USE_TWEETNACL)
48 : # include "tweetnacl.h"
49 : #elif defined (ZMQ_USE_LIBSODIUM)
50 : # include "sodium.h"
51 : #endif
52 :
53 6 : void zmq_sleep (int seconds_)
54 : {
55 : #if defined ZMQ_HAVE_WINDOWS
56 : Sleep (seconds_ * 1000);
57 : #else
58 6 : sleep (seconds_);
59 : #endif
60 6 : }
61 :
62 3 : void *zmq_stopwatch_start ()
63 : {
64 3 : uint64_t *watch = (uint64_t*) malloc (sizeof (uint64_t));
65 3 : alloc_assert (watch);
66 3 : *watch = zmq::clock_t::now_us ();
67 3 : return (void*) watch;
68 : }
69 :
70 3 : unsigned long zmq_stopwatch_stop (void *watch_)
71 : {
72 3 : uint64_t end = zmq::clock_t::now_us ();
73 3 : uint64_t start = *(uint64_t*) watch_;
74 3 : free (watch_);
75 3 : return (unsigned long) (end - start);
76 : }
77 :
78 3444 : void *zmq_threadstart(zmq_thread_fn* func, void* arg)
79 : {
80 6888 : zmq::thread_t* thread = new zmq::thread_t;
81 3444 : thread->start(func, arg);
82 3444 : return thread;
83 : }
84 :
85 3444 : void zmq_threadclose(void* thread)
86 : {
87 3444 : zmq::thread_t* pThread = static_cast<zmq::thread_t*>(thread);
88 3444 : pThread->stop();
89 3444 : LIBZMQ_DELETE(pThread);
90 3444 : }
91 :
92 : // Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding
93 :
94 : // Maps base 256 to base 85
95 : static char encoder [85 + 1] = {
96 : "0123456789" "abcdefghij" "klmnopqrst" "uvwxyzABCD"
97 : "EFGHIJKLMN" "OPQRSTUVWX" "YZ.-:+=^!/" "*?&<>()[]{"
98 : "}@%$#"
99 : };
100 :
101 : // Maps base 85 to base 256
102 : // We chop off lower 32 and higher 128 ranges
103 : static uint8_t decoder [96] = {
104 : 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
105 : 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
106 : 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
107 : 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
108 : 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
109 : 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
110 : 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
111 : 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
112 : 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
113 : 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
114 : 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
115 : 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00
116 : };
117 :
118 : // --------------------------------------------------------------------------
119 : // Encode a binary frame as a string; destination string MUST be at least
120 : // size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
121 : // dest. Size must be a multiple of 4.
122 : // Returns NULL and sets errno = EINVAL for invalid input.
123 :
124 24 : char *zmq_z85_encode (char *dest, const uint8_t *data, size_t size)
125 : {
126 24 : if (size % 4 != 0) {
127 0 : errno = EINVAL;
128 0 : return NULL;
129 : }
130 : unsigned int char_nbr = 0;
131 : unsigned int byte_nbr = 0;
132 : uint32_t value = 0;
133 792 : while (byte_nbr < size) {
134 : // Accumulate value in base 256 (binary)
135 768 : value = value * 256 + data [byte_nbr++];
136 768 : if (byte_nbr % 4 == 0) {
137 : // Output value in base 85
138 : unsigned int divisor = 85 * 85 * 85 * 85;
139 1152 : while (divisor) {
140 960 : dest [char_nbr++] = encoder [value / divisor % 85];
141 960 : divisor /= 85;
142 : }
143 : value = 0;
144 : }
145 : }
146 : assert (char_nbr == size * 5 / 4);
147 24 : dest [char_nbr] = 0;
148 24 : return dest;
149 : }
150 :
151 :
152 : // --------------------------------------------------------------------------
153 : // Decode an encoded string into a binary frame; dest must be at least
154 : // strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
155 : // must be a multiple of 5.
156 : // Returns NULL and sets errno = EINVAL for invalid input.
157 :
158 63 : uint8_t *zmq_z85_decode (uint8_t *dest, const char *string)
159 : {
160 63 : if (strlen (string) % 5 != 0) {
161 0 : errno = EINVAL;
162 0 : return NULL;
163 : }
164 : unsigned int byte_nbr = 0;
165 : unsigned int char_nbr = 0;
166 : size_t string_len = strlen (string);
167 : uint32_t value = 0;
168 2583 : while (char_nbr < string_len) {
169 : // Accumulate value in base 85
170 2520 : value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
171 2520 : if (char_nbr % 5 == 0) {
172 : // Output value in base 256
173 : unsigned int divisor = 256 * 256 * 256;
174 2520 : while (divisor) {
175 2016 : dest [byte_nbr++] = value / divisor % 256;
176 2016 : divisor /= 256;
177 : }
178 : value = 0;
179 : }
180 : }
181 : assert (byte_nbr == strlen (string) * 4 / 5);
182 : return dest;
183 : }
184 :
185 : // --------------------------------------------------------------------------
186 : // Generate a public/private keypair with tweetnacl or libsodium.
187 : // Generated keys will be 40 byte z85-encoded strings.
188 : // Returns 0 on success, -1 on failure, setting errno.
189 : // Sets errno = ENOTSUP in the absence of a CURVE library.
190 :
191 9 : int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key)
192 : {
193 : #if defined (ZMQ_HAVE_CURVE)
194 : # if crypto_box_PUBLICKEYBYTES != 32 \
195 : || crypto_box_SECRETKEYBYTES != 32
196 : # error "CURVE encryption library not built correctly"
197 : # endif
198 :
199 : uint8_t public_key [32];
200 : uint8_t secret_key [32];
201 :
202 9 : int rc = crypto_box_keypair (public_key, secret_key);
203 : // Is there a sensible errno to set here?
204 9 : if (rc)
205 : return rc;
206 :
207 9 : zmq_z85_encode (z85_public_key, public_key, 32);
208 9 : zmq_z85_encode (z85_secret_key, secret_key, 32);
209 :
210 : return 0;
211 : #else
212 : (void) z85_public_key, (void) z85_secret_key;
213 : errno = ENOTSUP;
214 : return -1;
215 : #endif
216 : }
217 :
218 :
219 : // --------------------------------------------------------------------------
220 : // Initialize a new atomic counter, which is set to zero
221 :
222 3 : void *zmq_atomic_counter_new (void)
223 : {
224 6 : zmq::atomic_counter_t *counter = new zmq::atomic_counter_t;
225 3 : alloc_assert (counter);
226 3 : return counter;
227 : }
228 :
229 : // Se the value of the atomic counter
230 :
231 3 : void zmq_atomic_counter_set (void *counter_, int value_)
232 : {
233 3 : ((zmq::atomic_counter_t *) counter_)->set (value_);
234 3 : }
235 :
236 : // Increment the atomic counter, and return the old value
237 :
238 9 : int zmq_atomic_counter_inc (void *counter_)
239 : {
240 9 : return ((zmq::atomic_counter_t *) counter_)->add (1);
241 : }
242 :
243 : // Decrement the atomic counter and return 1 (if counter >= 1), or
244 : // 0 if counter hit zero.
245 :
246 15 : int zmq_atomic_counter_dec (void *counter_)
247 : {
248 15 : return ((zmq::atomic_counter_t *) counter_)->sub (1)? 1: 0;
249 : }
250 :
251 : // Return actual value of atomic counter
252 :
253 6 : int zmq_atomic_counter_value (void *counter_)
254 : {
255 6 : return ((zmq::atomic_counter_t *) counter_)->get ();
256 : }
257 :
258 : // Destroy atomic counter, and set reference to NULL
259 :
260 3 : void zmq_atomic_counter_destroy (void **counter_p_)
261 : {
262 3 : delete ((zmq::atomic_counter_t *) *counter_p_);
263 3 : *counter_p_ = NULL;
264 3 : }
|