2 This file is part of GNUnet.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file rps/rps-test_util.c
23 * @brief Some utils faciliating the view into the internals for the sampler
24 * needed for evaluation
26 * @author Julius Bünger
30 #include "gnunet_util_lib.h"
31 #include "rps-test_util.h"
35 #define LOG(kind, ...) GNUNET_log_from (kind, "rps-test_util", __VA_ARGS__)
37 #define B2B_PAT "%c%c%c%c%c%c%c%c"
39 (byte & 0x80 ? '1' : '0'), \
40 (byte & 0x40 ? '1' : '0'), \
41 (byte & 0x20 ? '1' : '0'), \
42 (byte & 0x10 ? '1' : '0'), \
43 (byte & 0x08 ? '1' : '0'), \
44 (byte & 0x04 ? '1' : '0'), \
45 (byte & 0x02 ? '1' : '0'), \
46 (byte & 0x01 ? '1' : '0')
52 * @brief buffer for storing the unaligned bits for the next write
54 static char buf_unaligned;
57 * @brief number of bits in unaligned buffer
59 static unsigned num_bits_buf_unaligned;
61 static struct GNUNET_CONTAINER_MultiHashMap *open_files;
65 * @brief Get file handle
67 * If necessary, create file handle and store it with the other file handles.
69 * @param name Name of the file
73 struct GNUNET_DISK_FileHandle *
74 get_file_handle (const char *name)
76 struct GNUNET_HashCode hash;
77 struct GNUNET_DISK_FileHandle *fh;
79 if (NULL == open_files)
81 open_files = GNUNET_CONTAINER_multihashmap_create (16,
83 LOG (GNUNET_ERROR_TYPE_DEBUG,
84 "Created map of open files.\n");
86 GNUNET_CRYPTO_hash (name,
89 if (NULL != (fh = GNUNET_CONTAINER_multihashmap_get (open_files,
92 fh = GNUNET_DISK_file_open (name,
93 GNUNET_DISK_OPEN_WRITE
94 | GNUNET_DISK_OPEN_CREATE
95 | GNUNET_DISK_OPEN_APPEND,
96 GNUNET_DISK_PERM_USER_READ
97 | GNUNET_DISK_PERM_USER_WRITE
98 | GNUNET_DISK_PERM_GROUP_READ);
101 LOG (GNUNET_ERROR_TYPE_ERROR,
102 "Opening file `%s' failed.\n",
106 GNUNET_assert (GNUNET_YES ==
107 GNUNET_CONTAINER_multihashmap_put (open_files,
110 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
116 * @brief Closes the file of the current entry
118 * Implements #GNUNET_CONTAINER_HashMapIterator
122 * @param value the file handle
124 * @return #GNUNET_YES if we should continue to
129 close_files_iter (void *cls,
130 const struct GNUNET_HashCode *key,
135 struct GNUNET_DISK_FileHandle *fh = value;
139 GNUNET_DISK_file_close (fh);
146 * @brief Close all files that were opened with #get_file_handle
148 * @return Success of iterating over files
155 ret = GNUNET_CONTAINER_multihashmap_iterate (open_files,
158 GNUNET_CONTAINER_multihashmap_destroy (open_files);
165 to_file_raw (const char *file_name, const char *buf, size_t size_buf)
167 struct GNUNET_DISK_FileHandle *f;
170 if (NULL == (f = GNUNET_DISK_file_open (file_name,
171 GNUNET_DISK_OPEN_APPEND
172 | GNUNET_DISK_OPEN_WRITE
173 | GNUNET_DISK_OPEN_CREATE,
174 GNUNET_DISK_PERM_USER_READ
175 | GNUNET_DISK_PERM_USER_WRITE
176 | GNUNET_DISK_PERM_GROUP_READ
177 | GNUNET_DISK_PERM_OTHER_READ)))
179 LOG (GNUNET_ERROR_TYPE_WARNING,
180 "Not able to open file %s\n",
185 size_written = GNUNET_DISK_file_write (f, buf, size_buf);
186 if (size_buf != size_written)
188 LOG (GNUNET_ERROR_TYPE_WARNING,
189 "Unable to write to file! (Size: %u, size_written: %u)\n",
193 if (GNUNET_YES != GNUNET_DISK_file_close (f))
194 LOG (GNUNET_ERROR_TYPE_WARNING,
195 "Unable to close file\n");
199 LOG (GNUNET_ERROR_TYPE_WARNING,
200 "Wrote %u bytes raw.\n",
202 if (GNUNET_YES != GNUNET_DISK_file_close (f))
203 LOG (GNUNET_ERROR_TYPE_WARNING,
204 "Unable to close file\n");
209 to_file_raw_unaligned (const char *file_name,
212 unsigned bits_needed)
215 GNUNET_assert (size_buf >= (bits_needed / 8));
216 // if (0 == num_bits_buf_unaligned)
218 // if (0 == (bits_needed % 8))
220 // to_file_raw (file_name, buf, size_buf);
223 // to_file_raw (file_name, buf, size_buf - 1);
224 // buf_unaligned = buf[size_buf - 1];
225 // num_bits_buf_unaligned = bits_needed % 8;
228 LOG (GNUNET_ERROR_TYPE_DEBUG,
229 "Was asked to write %u bits\n", bits_needed);
231 char buf_write[size_buf + 1];
232 const unsigned bytes_iter = (0 != bits_needed % 8 ?
233 (bits_needed / 8) + 1 :
235 // TODO what if no iteration happens?
236 unsigned size_buf_write = 0;
237 LOG (GNUNET_ERROR_TYPE_DEBUG,
238 "num_bits_buf_unaligned: %u\n",
239 num_bits_buf_unaligned);
240 LOG (GNUNET_ERROR_TYPE_DEBUG,
241 "ua args: size_buf: %u, bits_needed: %u -> iter: %u\n",
245 buf_write[0] = buf_unaligned;
246 /* Iterate over input bytes */
247 for (unsigned i = 0; i < bytes_iter; i++)
249 /* Number of bits needed in this iteration - 8 for all except last iter */
250 unsigned num_bits_needed_iter;
251 /* Mask for bits to actually use */
252 unsigned mask_bits_needed_iter;
254 /* Number of bits needed to align unaligned byte */
255 unsigned num_bits_to_align;
256 /* Number of bits that are to be moved */
257 unsigned num_bits_to_move;
258 /* Mask for bytes to be moved */
259 char mask_input_to_move;
260 /* Masked bits to be moved */
262 /* The amount of bits needed to fit the bits to shift to the nearest spot */
263 unsigned distance_shift_bits;
264 /* Shifted bits on the move */
266 /* (unaligned) byte being filled with bits */
268 /* mask for needed bits of the input byte that have not been moved */
269 char mask_input_leftover;
270 /* needed bits of the input byte that have not been moved */
271 char byte_input_leftover;
272 unsigned num_bits_leftover;
273 // unsigned num_bits_discard;
274 char byte_unaligned_new;
276 if ((bits_needed - (i * 8)) <= 8)
279 num_bits_needed_iter = bits_needed - (i * 8);
283 num_bits_needed_iter = 8;
285 LOG (GNUNET_ERROR_TYPE_DEBUG,
286 "number of bits needed in this iteration: %u\n",
287 num_bits_needed_iter);
288 mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1;
289 LOG (GNUNET_ERROR_TYPE_DEBUG,
290 "mask needed bits (current iter): "B2B_PAT "\n",
291 B2B (mask_bits_needed_iter));
292 LOG (GNUNET_ERROR_TYPE_DEBUG,
293 "Unaligned byte: "B2B_PAT " (%u bits)\n",
295 num_bits_buf_unaligned);
297 LOG (GNUNET_ERROR_TYPE_DEBUG,
298 "next whole input byte: "B2B_PAT "\n",
300 byte_input &= mask_bits_needed_iter;
301 num_bits_to_align = 8 - num_bits_buf_unaligned;
302 LOG (GNUNET_ERROR_TYPE_DEBUG,
303 "input byte, needed bits: "B2B_PAT "\n",
305 LOG (GNUNET_ERROR_TYPE_DEBUG,
306 "number of bits needed to align unaligned bit: %u\n",
308 num_bits_to_move = GNUNET_MIN (num_bits_to_align, num_bits_needed_iter);
309 LOG (GNUNET_ERROR_TYPE_DEBUG,
310 "number of bits of new byte to move: %u\n",
312 mask_input_to_move = ((char) 1 << num_bits_to_move) - 1;
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "mask of bits of new byte to take for moving: "B2B_PAT "\n",
315 B2B (mask_input_to_move));
316 bits_to_move = byte_input & mask_input_to_move;
317 LOG (GNUNET_ERROR_TYPE_DEBUG,
318 "masked bits of new byte to take for moving: "B2B_PAT "\n",
320 distance_shift_bits = num_bits_buf_unaligned;
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "distance needed to shift bits to their correct spot: %u\n",
323 distance_shift_bits);
324 bits_moving = bits_to_move << distance_shift_bits;
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "shifted, masked bits of new byte being moved: "B2B_PAT "\n",
328 byte_to_fill = buf_unaligned | bits_moving;
329 LOG (GNUNET_ERROR_TYPE_DEBUG,
330 "byte being filled: "B2B_PAT "\n",
332 LOG (GNUNET_ERROR_TYPE_DEBUG,
333 "pending bytes: %u\n",
334 num_bits_buf_unaligned + num_bits_needed_iter);
335 if (num_bits_buf_unaligned + num_bits_needed_iter >= 8)
337 /* buf_unaligned was aligned by filling
338 * -> can be written to storage */
339 buf_write[i] = byte_to_fill;
342 /* store the leftover, unaligned bits in buffer */
343 mask_input_leftover = mask_bits_needed_iter & (~mask_input_to_move);
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "mask of leftover bits of new byte: "B2B_PAT "\n",
346 B2B (mask_input_leftover));
347 byte_input_leftover = byte_input & mask_input_leftover;
348 LOG (GNUNET_ERROR_TYPE_DEBUG,
349 "masked, leftover bits of new byte: "B2B_PAT "\n",
350 B2B (byte_input_leftover));
351 num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
352 LOG (GNUNET_ERROR_TYPE_DEBUG,
353 "number of unaligned bits left: %u\n",
355 // num_bits_discard = 8 - num_bits_needed_iter;
356 byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
357 LOG (GNUNET_ERROR_TYPE_DEBUG,
358 "new unaligned byte: "B2B_PAT "\n",
359 B2B (byte_unaligned_new));
360 buf_unaligned = byte_unaligned_new;
361 num_bits_buf_unaligned = num_bits_leftover % 8;
365 /* unaligned buffer still unaligned but 'fuller' */
366 buf_unaligned = byte_to_fill;
367 num_bits_buf_unaligned = (num_bits_buf_unaligned + bits_needed) % 8;
370 to_file_raw (file_name, buf_write, size_buf_write);
371 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
376 auth_key_to_string (struct GNUNET_CRYPTO_AuthKey auth_key)
379 size_t name_buf_size;
383 size_t keylen = (sizeof(struct GNUNET_CRYPTO_AuthKey)) * 8;
385 name_buf_size = 512 * sizeof(char);
386 name_buf = GNUNET_malloc (name_buf_size);
389 keylen += 5 - keylen % 5;
391 buf = GNUNET_malloc (keylen + 1);
393 end = GNUNET_STRINGS_data_to_string (&(auth_key.key),
394 sizeof(struct GNUNET_CRYPTO_AuthKey),
408 size = GNUNET_snprintf (name_buf, name_buf_size, "sampler_el-%s", buf);
410 LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
421 struct GNUNET_CRYPTO_AuthKey
422 string_to_auth_key (const char *str)
424 struct GNUNET_CRYPTO_AuthKey auth_key;
427 GNUNET_STRINGS_string_to_data (str,
430 sizeof(struct GNUNET_CRYPTO_AuthKey)))
432 LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
440 * @brief Try to ensure that `/tmp/rps` exists.
442 * @return #GNUNET_YES on success
443 * #GNUNET_SYSERR on failure
446 ensure_folder_exist (void)
449 GNUNET_DISK_directory_create ("/tmp/rps"))
451 LOG (GNUNET_ERROR_TYPE_ERROR,
452 "Could not create directory `/tmp/rps'\n");
453 return GNUNET_SYSERR;
460 store_prefix_file_name (const unsigned int index,
468 if (GNUNET_SYSERR == ensure_folder_exist ())
470 out_size = GNUNET_snprintf (index_str,
474 if ((64 < out_size) ||
477 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
478 "Failed to write string to buffer (size: %i, out_size: %i)\n",
482 len_file_name = (strlen (prefix)
486 file_name = GNUNET_malloc (len_file_name);
487 out_size = GNUNET_snprintf (file_name,
492 if ((len_file_name < out_size) ||
495 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
496 "Failed to write string to buffer (size: %i, out_size: %i)\n",
507 * @param x Number of which to compute the factorial
509 * @return Factorial of @a x
518 return x * fac (x - 1);
523 * @brief Binomial coefficient (n choose k)
528 * @return Binomial coefficient of @a n and @a k
531 binom (uint32_t n, uint32_t k)
533 // GNUNET_assert (n >= k);
536 /* if (0 > n) return 0; - always false */
537 /* if (0 > k) return 0; - always false */
542 fac (k) * fac (n - k);
546 /* end of gnunet-service-rps.c */