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;
66 * @brief Get file handle
68 * If necessary, create file handle and store it with the other file handles.
70 * @param name Name of the file
74 struct GNUNET_DISK_FileHandle *
75 get_file_handle(const char *name)
77 struct GNUNET_HashCode hash;
78 struct GNUNET_DISK_FileHandle *fh;
80 if (NULL == open_files)
82 open_files = GNUNET_CONTAINER_multihashmap_create(16,
84 LOG(GNUNET_ERROR_TYPE_DEBUG,
85 "Created map of open files.\n");
87 GNUNET_CRYPTO_hash(name,
90 if (NULL != (fh = GNUNET_CONTAINER_multihashmap_get(open_files,
93 fh = GNUNET_DISK_file_open(name,
94 GNUNET_DISK_OPEN_WRITE |
95 GNUNET_DISK_OPEN_CREATE |
96 GNUNET_DISK_OPEN_APPEND,
97 GNUNET_DISK_PERM_USER_READ |
98 GNUNET_DISK_PERM_USER_WRITE |
99 GNUNET_DISK_PERM_GROUP_READ);
102 LOG(GNUNET_ERROR_TYPE_ERROR,
103 "Opening file `%s' failed.\n",
107 GNUNET_assert(GNUNET_YES ==
108 GNUNET_CONTAINER_multihashmap_put(open_files,
111 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
117 * @brief Closes the file of the current entry
119 * Implements #GNUNET_CONTAINER_HashMapIterator
123 * @param value the file handle
125 * @return #GNUNET_YES if we should continue to
130 close_files_iter(void *cls,
131 const struct GNUNET_HashCode *key,
136 struct GNUNET_DISK_FileHandle *fh = value;
140 GNUNET_DISK_file_close(fh);
147 * @brief Close all files that were opened with #get_file_handle
149 * @return Success of iterating over files
156 ret = GNUNET_CONTAINER_multihashmap_iterate(open_files,
159 GNUNET_CONTAINER_multihashmap_destroy(open_files);
167 to_file_raw(const char *file_name, const char *buf, size_t size_buf)
169 struct GNUNET_DISK_FileHandle *f;
172 if (NULL == (f = GNUNET_DISK_file_open(file_name,
173 GNUNET_DISK_OPEN_APPEND |
174 GNUNET_DISK_OPEN_WRITE |
175 GNUNET_DISK_OPEN_CREATE,
176 GNUNET_DISK_PERM_USER_READ |
177 GNUNET_DISK_PERM_USER_WRITE |
178 GNUNET_DISK_PERM_GROUP_READ |
179 GNUNET_DISK_PERM_OTHER_READ)))
181 LOG(GNUNET_ERROR_TYPE_WARNING,
182 "Not able to open file %s\n",
187 size_written = GNUNET_DISK_file_write(f, buf, size_buf);
188 if (size_buf != size_written)
190 LOG(GNUNET_ERROR_TYPE_WARNING,
191 "Unable to write to file! (Size: %u, size_written: %u)\n",
195 if (GNUNET_YES != GNUNET_DISK_file_close(f))
196 LOG(GNUNET_ERROR_TYPE_WARNING,
197 "Unable to close file\n");
201 LOG(GNUNET_ERROR_TYPE_WARNING,
202 "Wrote %u bytes raw.\n",
204 if (GNUNET_YES != GNUNET_DISK_file_close(f))
205 LOG(GNUNET_ERROR_TYPE_WARNING,
206 "Unable to close file\n");
210 to_file_raw_unaligned(const char *file_name,
213 unsigned bits_needed)
216 GNUNET_assert(size_buf >= (bits_needed / 8));
217 //if (0 == num_bits_buf_unaligned)
219 // if (0 == (bits_needed % 8))
221 // to_file_raw (file_name, buf, size_buf);
224 // to_file_raw (file_name, buf, size_buf - 1);
225 // buf_unaligned = buf[size_buf - 1];
226 // num_bits_buf_unaligned = bits_needed % 8;
229 LOG(GNUNET_ERROR_TYPE_DEBUG,
230 "Was asked to write %u bits\n", bits_needed);
232 char buf_write[size_buf + 1];
233 const unsigned bytes_iter = (0 != bits_needed % 8 ?
234 (bits_needed / 8) + 1 :
236 // TODO what if no iteration happens?
237 unsigned size_buf_write = 0;
238 LOG(GNUNET_ERROR_TYPE_DEBUG,
239 "num_bits_buf_unaligned: %u\n",
240 num_bits_buf_unaligned);
241 LOG(GNUNET_ERROR_TYPE_DEBUG,
242 "ua args: size_buf: %u, bits_needed: %u -> iter: %u\n",
246 buf_write[0] = buf_unaligned;
247 /* Iterate over input bytes */
248 for (unsigned i = 0; i < bytes_iter; i++)
250 /* Number of bits needed in this iteration - 8 for all except last iter */
251 unsigned num_bits_needed_iter;
252 /* Mask for bits to actually use */
253 unsigned mask_bits_needed_iter;
255 /* Number of bits needed to align unaligned byte */
256 unsigned num_bits_to_align;
257 /* Number of bits that are to be moved */
258 unsigned num_bits_to_move;
259 /* Mask for bytes to be moved */
260 char mask_input_to_move;
261 /* Masked bits to be moved */
263 /* The amount of bits needed to fit the bits to shift to the nearest spot */
264 unsigned distance_shift_bits;
265 /* Shifted bits on the move */
267 /* (unaligned) byte being filled with bits */
269 /* mask for needed bits of the input byte that have not been moved */
270 char mask_input_leftover;
271 /* needed bits of the input byte that have not been moved */
272 char byte_input_leftover;
273 unsigned num_bits_leftover;
274 //unsigned num_bits_discard;
275 char byte_unaligned_new;
277 if ((bits_needed - (i * 8)) <= 8)
280 num_bits_needed_iter = bits_needed - (i * 8);
284 num_bits_needed_iter = 8;
286 LOG(GNUNET_ERROR_TYPE_DEBUG,
287 "number of bits needed in this iteration: %u\n",
288 num_bits_needed_iter);
289 mask_bits_needed_iter = ((char)1 << num_bits_needed_iter) - 1;
290 LOG(GNUNET_ERROR_TYPE_DEBUG,
291 "mask needed bits (current iter): "B2B_PAT "\n",
292 B2B(mask_bits_needed_iter));
293 LOG(GNUNET_ERROR_TYPE_DEBUG,
294 "Unaligned byte: "B2B_PAT " (%u bits)\n",
296 num_bits_buf_unaligned);
298 LOG(GNUNET_ERROR_TYPE_DEBUG,
299 "next whole input byte: "B2B_PAT "\n",
301 byte_input &= mask_bits_needed_iter;
302 num_bits_to_align = 8 - num_bits_buf_unaligned;
303 LOG(GNUNET_ERROR_TYPE_DEBUG,
304 "input byte, needed bits: "B2B_PAT "\n",
306 LOG(GNUNET_ERROR_TYPE_DEBUG,
307 "number of bits needed to align unaligned bit: %u\n",
309 num_bits_to_move = GNUNET_MIN(num_bits_to_align, num_bits_needed_iter);
310 LOG(GNUNET_ERROR_TYPE_DEBUG,
311 "number of bits of new byte to move: %u\n",
313 mask_input_to_move = ((char)1 << num_bits_to_move) - 1;
314 LOG(GNUNET_ERROR_TYPE_DEBUG,
315 "mask of bits of new byte to take for moving: "B2B_PAT "\n",
316 B2B(mask_input_to_move));
317 bits_to_move = byte_input & mask_input_to_move;
318 LOG(GNUNET_ERROR_TYPE_DEBUG,
319 "masked bits of new byte to take for moving: "B2B_PAT "\n",
321 distance_shift_bits = num_bits_buf_unaligned;
322 LOG(GNUNET_ERROR_TYPE_DEBUG,
323 "distance needed to shift bits to their correct spot: %u\n",
324 distance_shift_bits);
325 bits_moving = bits_to_move << distance_shift_bits;
326 LOG(GNUNET_ERROR_TYPE_DEBUG,
327 "shifted, masked bits of new byte being moved: "B2B_PAT "\n",
329 byte_to_fill = buf_unaligned | bits_moving;
330 LOG(GNUNET_ERROR_TYPE_DEBUG,
331 "byte being filled: "B2B_PAT "\n",
333 LOG(GNUNET_ERROR_TYPE_DEBUG,
334 "pending bytes: %u\n",
335 num_bits_buf_unaligned + num_bits_needed_iter);
336 if (num_bits_buf_unaligned + num_bits_needed_iter >= 8)
338 /* buf_unaligned was aligned by filling
339 * -> can be written to storage */
340 buf_write[i] = byte_to_fill;
343 /* store the leftover, unaligned bits in buffer */
344 mask_input_leftover = mask_bits_needed_iter & (~mask_input_to_move);
345 LOG(GNUNET_ERROR_TYPE_DEBUG,
346 "mask of leftover bits of new byte: "B2B_PAT "\n",
347 B2B(mask_input_leftover));
348 byte_input_leftover = byte_input & mask_input_leftover;
349 LOG(GNUNET_ERROR_TYPE_DEBUG,
350 "masked, leftover bits of new byte: "B2B_PAT "\n",
351 B2B(byte_input_leftover));
352 num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
353 LOG(GNUNET_ERROR_TYPE_DEBUG,
354 "number of unaligned bits left: %u\n",
356 //num_bits_discard = 8 - num_bits_needed_iter;
357 byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
358 LOG(GNUNET_ERROR_TYPE_DEBUG,
359 "new unaligned byte: "B2B_PAT "\n",
360 B2B(byte_unaligned_new));
361 buf_unaligned = byte_unaligned_new;
362 num_bits_buf_unaligned = num_bits_leftover % 8;
366 /* unaligned buffer still unaligned but 'fuller' */
367 buf_unaligned = byte_to_fill;
368 num_bits_buf_unaligned = (num_bits_buf_unaligned + bits_needed) % 8;
371 to_file_raw(file_name, buf_write, size_buf_write);
372 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");
420 struct GNUNET_CRYPTO_AuthKey
421 string_to_auth_key(const char *str)
423 struct GNUNET_CRYPTO_AuthKey auth_key;
426 GNUNET_STRINGS_string_to_data(str,
429 sizeof(struct GNUNET_CRYPTO_AuthKey)))
431 LOG(GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
439 * @brief Try to ensure that `/tmp/rps` exists.
441 * @return #GNUNET_YES on success
442 * #GNUNET_SYSERR on failure
445 ensure_folder_exist(void)
448 GNUNET_DISK_directory_create("/tmp/rps"))
450 LOG(GNUNET_ERROR_TYPE_ERROR,
451 "Could not create directory `/tmp/rps'\n");
452 return GNUNET_SYSERR;
459 store_prefix_file_name(const unsigned int index,
467 if (GNUNET_SYSERR == ensure_folder_exist())
469 out_size = GNUNET_snprintf(index_str,
476 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
477 "Failed to write string to buffer (size: %i, out_size: %i)\n",
481 len_file_name = (strlen(prefix) +
485 file_name = GNUNET_malloc(len_file_name);
486 out_size = GNUNET_snprintf(file_name,
491 if (len_file_name < out_size ||
494 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
495 "Failed to write string to buffer (size: %i, out_size: %i)\n",
506 * @param x Number of which to compute the factorial
508 * @return Factorial of @a x
510 uint32_t fac(uint32_t x)
516 return x * fac(x - 1);
520 * @brief Binomial coefficient (n choose k)
525 * @return Binomial coefficient of @a n and @a k
527 uint32_t binom(uint32_t n, uint32_t k)
529 //GNUNET_assert (n >= k);
532 /* if (0 > n) return 0; - always false */
533 /* if (0 > k) return 0; - always false */
542 /* end of gnunet-service-rps.c */