/*
This file is part of GNUnet.
Copyright (C)
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file rps/rps-test_util.c
* @brief Some utils faciliating the view into the internals for the sampler
* needed for evaluation
*
* @author Julius Bünger
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "rps-test_util.h"
#include
#define LOG(kind, ...) GNUNET_log_from(kind,"rps-test_util",__VA_ARGS__)
#define B2B_PAT "%c%c%c%c%c%c%c%c"
#define B2B(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
#ifdef TO_FILE
/**
* @brief buffer for storing the unaligned bits for the next write
*/
static char buf_unaligned;
/**
* @brief number of bits in unaligned buffer
*/
static unsigned num_bits_buf_unaligned;
static struct GNUNET_CONTAINER_MultiHashMap *open_files;
/**
* @brief Get file handle
*
* If necessary, create file handle and store it with the other file handles.
*
* @param name Name of the file
*
* @return File handle
*/
struct GNUNET_DISK_FileHandle *
get_file_handle (const char *name)
{
struct GNUNET_HashCode hash;
struct GNUNET_DISK_FileHandle *fh;
if (NULL == open_files)
{
open_files = GNUNET_CONTAINER_multihashmap_create (16,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
}
GNUNET_CRYPTO_hash (name,
strnlen (name,
512),
&hash);
if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (open_files,
&hash))
{
fh = GNUNET_DISK_file_open (name,
GNUNET_DISK_OPEN_WRITE |
GNUNET_DISK_OPEN_CREATE |
GNUNET_DISK_OPEN_APPEND,
GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE |
GNUNET_DISK_PERM_GROUP_READ);
if (NULL == fh)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
"Opening file `%s' failed.\n",
name);
GNUNET_assert (0);
}
GNUNET_CONTAINER_multihashmap_put (open_files,
&hash,
fh,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
return fh;
}
else
{
fh = GNUNET_CONTAINER_multihashmap_get (open_files,
&hash);
return fh;
}
}
/**
* @brief Closes the file of the current entry
*
* Implements #GNUNET_CONTAINER_HashMapIterator
*
* @param cls unused
* @param key unused
* @param value the file handle
*
* @return #GNUNET_YES if we should continue to
* iterate,
* #GNUNET_NO if not.
*/
int
close_files_iter (void *cls,
const struct GNUNET_HashCode *key,
void *value)
{
(void) cls;
(void) key;
struct GNUNET_DISK_FileHandle *fh = value;
if (NULL != fh)
{
GNUNET_DISK_file_close (fh);
}
return GNUNET_YES;
}
/**
* @brief Close all files that were opened with #get_file_handle
*
* @return Success of iterating over files
*/
int
close_all_files ()
{
int ret;
ret = GNUNET_CONTAINER_multihashmap_iterate (open_files,
close_files_iter,
NULL);
GNUNET_CONTAINER_multihashmap_destroy (open_files);
return ret;
}
void
to_file_raw (const char *file_name, const char *buf, size_t size_buf)
{
struct GNUNET_DISK_FileHandle *f;
size_t size_written;
if (NULL == (f = GNUNET_DISK_file_open (file_name,
GNUNET_DISK_OPEN_APPEND |
GNUNET_DISK_OPEN_WRITE |
GNUNET_DISK_OPEN_CREATE,
GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE |
GNUNET_DISK_PERM_GROUP_READ |
GNUNET_DISK_PERM_OTHER_READ)))
{
LOG (GNUNET_ERROR_TYPE_WARNING,
"Not able to open file %s\n",
file_name);
return;
}
size_written = GNUNET_DISK_file_write (f, buf, size_buf);
if (size_buf != size_written)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
"Unable to write to file! (Size: %u, size_written: %u)\n",
size_buf,
size_written);
if (GNUNET_YES != GNUNET_DISK_file_close (f))
LOG (GNUNET_ERROR_TYPE_WARNING,
"Unable to close file\n");
return;
}
LOG (GNUNET_ERROR_TYPE_WARNING,
"Wrote %u bytes raw.\n",
size_written);
if (GNUNET_YES != GNUNET_DISK_file_close (f))
LOG (GNUNET_ERROR_TYPE_WARNING,
"Unable to close file\n");
}
void
to_file_raw_unaligned (const char *file_name,
const char *buf,
size_t size_buf,
unsigned bits_needed)
{
// TODO endianness!
GNUNET_assert (size_buf >= (bits_needed/8));
//if (0 == num_bits_buf_unaligned)
//{
// if (0 == (bits_needed % 8))
// {
// to_file_raw (file_name, buf, size_buf);
// return;
// }
// to_file_raw (file_name, buf, size_buf - 1);
// buf_unaligned = buf[size_buf - 1];
// num_bits_buf_unaligned = bits_needed % 8;
// return;
//}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Was asked to write %u bits\n", bits_needed);
char buf_write[size_buf + 1];
const unsigned bytes_iter = (0 != bits_needed % 8?
(bits_needed/8)+1:
bits_needed/8);
// TODO what if no iteration happens?
unsigned size_buf_write = 0;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"num_bits_buf_unaligned: %u\n",
num_bits_buf_unaligned);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"ua args: size_buf: %u, bits_needed: %u -> iter: %u\n",
size_buf,
bits_needed,
bytes_iter);
buf_write[0] = buf_unaligned;
/* Iterate over input bytes */
for (unsigned i = 0; i < bytes_iter; i++)
{
/* Number of bits needed in this iteration - 8 for all except last iter */
unsigned num_bits_needed_iter;
/* Mask for bits to actually use */
unsigned mask_bits_needed_iter;
char byte_input;
/* Number of bits needed to align unaligned byte */
unsigned num_bits_to_align;
/* Number of bits that are to be moved */
unsigned num_bits_to_move;
/* Mask for bytes to be moved */
char mask_input_to_move;
/* Masked bits to be moved */
char bits_to_move;
/* The amount of bits needed to fit the bits to shift to the nearest spot */
unsigned distance_shift_bits;
/* Shifted bits on the move */
char bits_moving;
/* (unaligned) byte being filled with bits */
char byte_to_fill;
/* mask for needed bits of the input byte that have not been moved */
char mask_input_leftover;
/* needed bits of the input byte that have not been moved */
char byte_input_leftover;
unsigned num_bits_leftover;
//unsigned num_bits_discard;
char byte_unaligned_new;
if ( (bits_needed - (i * 8)) <= 8)
{
/* last iteration */
num_bits_needed_iter = bits_needed - (i * 8);
}
else
{
num_bits_needed_iter = 8;
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"number of bits needed in this iteration: %u\n",
num_bits_needed_iter);
mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"mask needed bits (current iter): "B2B_PAT"\n",
B2B(mask_bits_needed_iter));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Unaligned byte: "B2B_PAT" (%u bits)\n",
B2B(buf_unaligned),
num_bits_buf_unaligned);
byte_input = buf[i];
LOG (GNUNET_ERROR_TYPE_DEBUG,
"next whole input byte: "B2B_PAT"\n",
B2B(byte_input));
byte_input &= mask_bits_needed_iter;
num_bits_to_align = 8 - num_bits_buf_unaligned;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"input byte, needed bits: "B2B_PAT"\n",
B2B(byte_input));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"number of bits needed to align unaligned bit: %u\n",
num_bits_to_align);
num_bits_to_move = GNUNET_MIN (num_bits_to_align, num_bits_needed_iter);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"number of bits of new byte to move: %u\n",
num_bits_to_move);
mask_input_to_move = ((char) 1 << num_bits_to_move) - 1;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"mask of bits of new byte to take for moving: "B2B_PAT"\n",
B2B(mask_input_to_move));
bits_to_move = byte_input & mask_input_to_move;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"masked bits of new byte to take for moving: "B2B_PAT"\n",
B2B(bits_to_move));
distance_shift_bits = num_bits_buf_unaligned;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"distance needed to shift bits to their correct spot: %u\n",
distance_shift_bits);
bits_moving = bits_to_move << distance_shift_bits;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"shifted, masked bits of new byte being moved: "B2B_PAT"\n",
B2B(bits_moving));
byte_to_fill = buf_unaligned | bits_moving;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"byte being filled: "B2B_PAT"\n",
B2B(byte_to_fill));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"pending bytes: %u\n",
num_bits_buf_unaligned + num_bits_needed_iter);
if (num_bits_buf_unaligned + num_bits_needed_iter >= 8)
{
/* buf_unaligned was aligned by filling
* -> can be written to storage */
buf_write[i] = byte_to_fill;
size_buf_write++;
/* store the leftover, unaligned bits in buffer */
mask_input_leftover = mask_bits_needed_iter & (~ mask_input_to_move);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"mask of leftover bits of new byte: "B2B_PAT"\n",
B2B(mask_input_leftover));
byte_input_leftover = byte_input & mask_input_leftover;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"masked, leftover bits of new byte: "B2B_PAT"\n",
B2B(byte_input_leftover));
num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"number of unaligned bits left: %u\n",
num_bits_leftover);
//num_bits_discard = 8 - num_bits_needed_iter;
byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"new unaligned byte: "B2B_PAT"\n",
B2B(byte_unaligned_new));
buf_unaligned = byte_unaligned_new;
num_bits_buf_unaligned = num_bits_leftover % 8;
}
else
{
/* unaligned buffer still unaligned but 'fuller' */
buf_unaligned = byte_to_fill;
num_bits_buf_unaligned = (num_bits_buf_unaligned + bits_needed) % 8;
}
}
to_file_raw (file_name, buf_write, size_buf_write);
LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
}
char *
auth_key_to_string (struct GNUNET_CRYPTO_AuthKey auth_key)
{
int size;
size_t name_buf_size;
char *end;
char *buf;
char *name_buf;
size_t keylen = (sizeof (struct GNUNET_CRYPTO_AuthKey)) * 8;
name_buf_size = 512 * sizeof (char);
name_buf = GNUNET_malloc (name_buf_size);
if (keylen % 5 > 0)
keylen += 5 - keylen % 5;
keylen /= 5;
buf = GNUNET_malloc (keylen + 1);
end = GNUNET_STRINGS_data_to_string (&(auth_key.key),
sizeof (struct GNUNET_CRYPTO_AuthKey),
buf,
keylen);
if (NULL == end)
{
GNUNET_free (buf);
GNUNET_break (0);
}
else
{
*end = '\0';
}
size = GNUNET_snprintf (name_buf, name_buf_size, "sampler_el-%s", buf);
if (0 > size)
LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
GNUNET_free (buf);
return name_buf;
}
char *
create_file (const char *name)
{
int size;
size_t name_buf_size;
char *name_buf;
char *prefix;
char *file_name;
prefix = "/tmp/rps/";
name_buf_size = (strlen (prefix) + strlen (name) + 2) * sizeof (char);
name_buf = GNUNET_malloc (name_buf_size);
size = GNUNET_snprintf (name_buf, name_buf_size, "%s%s", prefix, name);
if (0 > size)
LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
if (GNUNET_YES != GNUNET_DISK_directory_create (prefix))
{
LOG (GNUNET_ERROR_TYPE_WARNING,
"Could not create directory %s.\n",
prefix);
}
if (NULL == strstr (name, "sampler_el"))
{/* only append random string to sampler */
if (NULL == (file_name = GNUNET_DISK_mktemp (name_buf)))
LOG (GNUNET_ERROR_TYPE_WARNING, "Could not create file\n");
GNUNET_free (name_buf);
return file_name;
}
return name_buf;
}
#endif /* TO_FILE */
struct GNUNET_CRYPTO_AuthKey
string_to_auth_key (const char *str)
{
struct GNUNET_CRYPTO_AuthKey auth_key;
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (str,
strlen (str),
&auth_key.key,
sizeof (struct GNUNET_CRYPTO_AuthKey)))
{
LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
}
return auth_key;
}
/**
* @brief Try to ensure that `/tmp/rps` exists.
*
* @return #GNUNET_YES on success
* #GNUNET_SYSERR on failure
*/
static int ensure_folder_exist (void)
{
if (GNUNET_NO == GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
{
GNUNET_DISK_directory_create ("/tmp/rps");
}
if (GNUNET_YES != GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
{
return GNUNET_SYSERR;
}
return GNUNET_YES;
}
char *
store_prefix_file_name (const struct GNUNET_PeerIdentity *peer,
const char *prefix)
{
int len_file_name;
int out_size;
char *file_name;
const char *pid_long;
if (GNUNET_SYSERR == ensure_folder_exist()) return NULL;
pid_long = GNUNET_i2s_full (peer);
len_file_name = (strlen (prefix) +
strlen (pid_long) +
11)
* sizeof (char);
file_name = GNUNET_malloc (len_file_name);
out_size = GNUNET_snprintf (file_name,
len_file_name,
"/tmp/rps/%s-%s",
prefix,
pid_long);
if (len_file_name < out_size ||
0 > out_size)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to write string to buffer (size: %i, out_size: %i)\n",
len_file_name,
out_size);
}
return file_name;
}
/* end of gnunet-service-rps.c */