zmq_utils.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 
5 #include "macros.hpp"
6 #include "clock.hpp"
7 #include "err.hpp"
8 #include "thread.hpp"
9 #include "atomic_counter.hpp"
10 #include "atomic_ptr.hpp"
11 #include "random.hpp"
12 #include <assert.h>
13 #include <new>
14 
15 #if !defined ZMQ_HAVE_WINDOWS
16 #include <unistd.h>
17 #endif
18 
19 #if defined(ZMQ_USE_LIBSODIUM)
20 #include "sodium.h"
21 #endif
22 
23 void zmq_sleep (int seconds_)
24 {
25 #if defined ZMQ_HAVE_WINDOWS
26  Sleep (seconds_ * 1000);
27 #else
28  sleep (seconds_);
29 #endif
30 }
31 
33 {
34  uint64_t *watch = static_cast<uint64_t *> (malloc (sizeof (uint64_t)));
35  alloc_assert (watch);
36  *watch = zmq::clock_t::now_us ();
37  return static_cast<void *> (watch);
38 }
39 
40 unsigned long zmq_stopwatch_intermediate (void *watch_)
41 {
42  const uint64_t end = zmq::clock_t::now_us ();
43  const uint64_t start = *static_cast<uint64_t *> (watch_);
44  return static_cast<unsigned long> (end - start);
45 }
46 
47 unsigned long zmq_stopwatch_stop (void *watch_)
48 {
49  const unsigned long res = zmq_stopwatch_intermediate (watch_);
50  free (watch_);
51  return res;
52 }
53 
54 void *zmq_threadstart (zmq_thread_fn *func_, void *arg_)
55 {
56  zmq::thread_t *thread = new (std::nothrow) zmq::thread_t;
57  alloc_assert (thread);
58  thread->start (func_, arg_, "ZMQapp");
59  return thread;
60 }
61 
62 void zmq_threadclose (void *thread_)
63 {
64  zmq::thread_t *p_thread = static_cast<zmq::thread_t *> (thread_);
65  p_thread->stop ();
66  LIBZMQ_DELETE (p_thread);
67 }
68 
69 // Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding
70 
71 // Maps base 256 to base 85
72 static char encoder[85 + 1] = {"0123456789"
73  "abcdefghij"
74  "klmnopqrst"
75  "uvwxyzABCD"
76  "EFGHIJKLMN"
77  "OPQRSTUVWX"
78  "YZ.-:+=^!/"
79  "*?&<>()[]{"
80  "}@%$#"};
81 
82 // Maps base 85 to base 256
83 // We chop off lower 32 and higher 128 ranges
84 // 0xFF denotes invalid characters within this range
85 static uint8_t decoder[96] = {
86  0xFF, 0x44, 0xFF, 0x54, 0x53, 0x52, 0x48, 0xFF, 0x4B, 0x4C, 0x46, 0x41,
87  0xFF, 0x3F, 0x3E, 0x45, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
88  0x08, 0x09, 0x40, 0xFF, 0x49, 0x42, 0x4A, 0x47, 0x51, 0x24, 0x25, 0x26,
89  0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
90  0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x4D,
91  0xFF, 0x4E, 0x43, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
92  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
93  0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x4F, 0xFF, 0x50, 0xFF, 0xFF};
94 
95 // --------------------------------------------------------------------------
96 // Encode a binary frame as a string; destination string MUST be at least
97 // size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
98 // dest. Size must be a multiple of 4.
99 // Returns NULL and sets errno = EINVAL for invalid input.
100 
101 char *zmq_z85_encode (char *dest_, const uint8_t *data_, size_t size_)
102 {
103  if (size_ % 4 != 0) {
104  errno = EINVAL;
105  return NULL;
106  }
107  unsigned int char_nbr = 0;
108  unsigned int byte_nbr = 0;
109  uint32_t value = 0;
110  while (byte_nbr < size_) {
111  // Accumulate value in base 256 (binary)
112  value = value * 256 + data_[byte_nbr++];
113  if (byte_nbr % 4 == 0) {
114  // Output value in base 85
115  unsigned int divisor = 85 * 85 * 85 * 85;
116  while (divisor) {
117  dest_[char_nbr++] = encoder[value / divisor % 85];
118  divisor /= 85;
119  }
120  value = 0;
121  }
122  }
123  assert (char_nbr == size_ * 5 / 4);
124  dest_[char_nbr] = 0;
125  return dest_;
126 }
127 
128 
129 // --------------------------------------------------------------------------
130 // Decode an encoded string into a binary frame; dest must be at least
131 // strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
132 // must be a multiple of 5.
133 // Returns NULL and sets errno = EINVAL for invalid input.
134 
135 uint8_t *zmq_z85_decode (uint8_t *dest_, const char *string_)
136 {
137  unsigned int byte_nbr = 0;
138  unsigned int char_nbr = 0;
139  uint32_t value = 0;
140  size_t src_len = strlen (string_);
141 
142  if (src_len < 5 || src_len % 5 != 0)
143  goto error_inval;
144 
145  while (string_[char_nbr]) {
146  // Accumulate value in base 85
147  if (UINT32_MAX / 85 < value) {
148  // Invalid z85 encoding, represented value exceeds 0xffffffff
149  goto error_inval;
150  }
151  value *= 85;
152  const uint8_t index = string_[char_nbr++] - 32;
153  if (index >= sizeof (decoder)) {
154  // Invalid z85 encoding, character outside range
155  goto error_inval;
156  }
157  const uint32_t summand = decoder[index];
158  if (summand == 0xFF || summand > (UINT32_MAX - value)) {
159  // Invalid z85 encoding, invalid character or represented value exceeds 0xffffffff
160  goto error_inval;
161  }
162  value += summand;
163  if (char_nbr % 5 == 0) {
164  // Output value in base 256
165  unsigned int divisor = 256 * 256 * 256;
166  while (divisor) {
167  dest_[byte_nbr++] = value / divisor % 256;
168  divisor /= 256;
169  }
170  value = 0;
171  }
172  }
173  if (char_nbr % 5 != 0) {
174  goto error_inval;
175  }
176  assert (byte_nbr == strlen (string_) * 4 / 5);
177  return dest_;
178 
179 error_inval:
180  errno = EINVAL;
181  return NULL;
182 }
183 
184 // --------------------------------------------------------------------------
185 // Generate a public/private keypair with libsodium.
186 // Generated keys will be 40 byte z85-encoded strings.
187 // Returns 0 on success, -1 on failure, setting errno.
188 // Sets errno = ENOTSUP in the absence of a CURVE library.
189 
190 int zmq_curve_keypair (char *z85_public_key_, char *z85_secret_key_)
191 {
192 #if defined(ZMQ_HAVE_CURVE)
193 #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32
194 #error "CURVE encryption library not built correctly"
195 #endif
196 
197  uint8_t public_key[32];
198  uint8_t secret_key[32];
199 
200  zmq::random_open ();
201 
202  const int res = crypto_box_keypair (public_key, secret_key);
203  zmq_z85_encode (z85_public_key_, public_key, 32);
204  zmq_z85_encode (z85_secret_key_, secret_key, 32);
205 
207 
208  return res;
209 #else
210  (void) z85_public_key_, (void) z85_secret_key_;
211  errno = ENOTSUP;
212  return -1;
213 #endif
214 }
215 
216 // --------------------------------------------------------------------------
217 // Derive the public key from a private key using libsodium.
218 // Derived key will be 40 byte z85-encoded string.
219 // Returns 0 on success, -1 on failure, setting errno.
220 // Sets errno = ENOTSUP in the absence of a CURVE library.
221 
222 int zmq_curve_public (char *z85_public_key_, const char *z85_secret_key_)
223 {
224 #if defined(ZMQ_HAVE_CURVE)
225 #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32
226 #error "CURVE encryption library not built correctly"
227 #endif
228 
229  uint8_t public_key[32];
230  uint8_t secret_key[32];
231 
232  zmq::random_open ();
233 
234  if (zmq_z85_decode (secret_key, z85_secret_key_) == NULL)
235  return -1;
236 
237  // Return codes are suppressed as none of these can actually fail.
238  crypto_scalarmult_base (public_key, secret_key);
239  zmq_z85_encode (z85_public_key_, public_key, 32);
240 
242 
243  return 0;
244 #else
245  (void) z85_public_key_, (void) z85_secret_key_;
246  errno = ENOTSUP;
247  return -1;
248 #endif
249 }
250 
251 
252 // --------------------------------------------------------------------------
253 // Initialize a new atomic counter, which is set to zero
254 
256 {
257  zmq::atomic_counter_t *counter = new (std::nothrow) zmq::atomic_counter_t;
258  alloc_assert (counter);
259  return counter;
260 }
261 
262 // Se the value of the atomic counter
263 
265 {
266  (static_cast<zmq::atomic_counter_t *> (counter_))->set (value_);
267 }
268 
269 // Increment the atomic counter, and return the old value
270 
272 {
273  return (static_cast<zmq::atomic_counter_t *> (counter_))->add (1);
274 }
275 
276 // Decrement the atomic counter and return 1 (if counter >= 1), or
277 // 0 if counter hit zero.
278 
280 {
281  return (static_cast<zmq::atomic_counter_t *> (counter_))->sub (1) ? 1 : 0;
282 }
283 
284 // Return actual value of atomic counter
285 
287 {
288  return (static_cast<zmq::atomic_counter_t *> (counter_))->get ();
289 }
290 
291 // Destroy atomic counter, and set reference to NULL
292 
293 void zmq_atomic_counter_destroy (void **counter_p_)
294 {
295  delete (static_cast<zmq::atomic_counter_t *> (*counter_p_));
296  *counter_p_ = NULL;
297 }
LIBZMQ_DELETE
#define LIBZMQ_DELETE(p_object)
Definition: macros.hpp:7
zmq::random_open
void random_open()
Definition: random.cpp:59
data_
StringPiece data_
Definition: bytestream_unittest.cc:60
zmq::thread_t::stop
void stop()
Definition: thread.cpp:245
end
GLuint GLuint end
Definition: glcorearb.h:2858
ENOTSUP
#define ENOTSUP
Definition: zmq.h:104
atomic_counter.hpp
NULL
NULL
Definition: test_security_zap.cpp:405
EINVAL
#define EINVAL
Definition: errno.hpp:25
google::protobuf.internal.wire_format.UINT32_MAX
tuple UINT32_MAX
Definition: wire_format.py:59
precompiled.hpp
random.hpp
errno
int errno
clock.hpp
encoder
static char encoder[85+1]
Definition: zmq_utils.cpp:72
zmq::thread_t::start
void start(thread_fn *tfn_, void *arg_, const char *name_)
Definition: thread.cpp:234
zmq_thread_fn
void() zmq_thread_fn(void *)
Definition: zmq.h:605
zmq_z85_decode
uint8_t * zmq_z85_decode(uint8_t *dest_, const char *string_)
Definition: zmq_utils.cpp:135
zmq::random_close
void random_close()
Definition: random.cpp:64
zmq_stopwatch_intermediate
unsigned long zmq_stopwatch_intermediate(void *watch_)
Definition: zmq_utils.cpp:40
alloc_assert
#define alloc_assert(x)
Definition: err.hpp:146
zmq_sleep
void zmq_sleep(int seconds_)
Definition: zmq_utils.cpp:23
macros.hpp
zmq_stopwatch_start
void * zmq_stopwatch_start()
Definition: zmq_utils.cpp:32
start
GLuint start
Definition: glcorearb.h:2858
zmq::atomic_counter_t
Definition: atomic_counter.hpp:61
zmq::clock_t::now_us
static uint64_t now_us()
Definition: clock.cpp:118
zmq_threadclose
void zmq_threadclose(void *thread_)
Definition: zmq_utils.cpp:62
zmq_z85_encode
char * zmq_z85_encode(char *dest_, const uint8_t *data_, size_t size_)
Definition: zmq_utils.cpp:101
zmq_curve_public
int zmq_curve_public(char *z85_public_key_, const char *z85_secret_key_)
Definition: zmq_utils.cpp:222
thread.hpp
zmq::thread_t
Definition: thread.hpp:26
zmq_atomic_counter_set
void zmq_atomic_counter_set(void *counter_, int value_)
Definition: zmq_utils.cpp:264
decoder
static uint8_t decoder[96]
Definition: zmq_utils.cpp:85
void
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
zmq_curve_keypair
int zmq_curve_keypair(char *z85_public_key_, char *z85_secret_key_)
Definition: zmq_utils.cpp:190
value_
int value_
Definition: gmock-matchers_test.cc:571
zmq_atomic_counter_destroy
void zmq_atomic_counter_destroy(void **counter_p_)
Definition: zmq_utils.cpp:293
zmq_threadstart
void * zmq_threadstart(zmq_thread_fn *func_, void *arg_)
Definition: zmq_utils.cpp:54
err.hpp
zmq_atomic_counter_dec
int zmq_atomic_counter_dec(void *counter_)
Definition: zmq_utils.cpp:279
zmq_atomic_counter_value
int zmq_atomic_counter_value(void *counter_)
Definition: zmq_utils.cpp:286
divisor
GLuint divisor
Definition: glcorearb.h:3337
zmq_atomic_counter_new
void * zmq_atomic_counter_new(void)
Definition: zmq_utils.cpp:255
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
atomic_ptr.hpp
assert.h
zmq_atomic_counter_inc
int zmq_atomic_counter_inc(void *counter_)
Definition: zmq_utils.cpp:271
zmq_stopwatch_stop
unsigned long zmq_stopwatch_stop(void *watch_)
Definition: zmq_utils.cpp:47
index
GLuint index
Definition: glcorearb.h:3055
counter_
int counter_
Definition: tokenizer_unittest.cc:150


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:02