Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / rps / rps-test_util.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C)
4
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.
9
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.
14     
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/>.
17 */
18
19 /**
20  * @file rps/rps-test_util.c
21  * @brief Some utils faciliating the view into the internals for the sampler
22  *        needed for evaluation
23  *
24  * @author Julius Bünger
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29
30 #include <inttypes.h>
31
32 #define LOG(kind, ...) GNUNET_log_from(kind,"rps-test_util",__VA_ARGS__)
33
34 #ifndef TO_FILE
35 #define TO_FILE
36 #endif /* TO_FILE */
37
38 #ifdef TO_FILE
39
40 #define min(x,y) ((x) > (y) ? (y) : (x))
41
42 /**
43  * @brief buffer for storing the unaligned bits for the next write
44  */
45 static char buf_unaligned;
46
47 /**
48  * @brief number of bits in unaligned buffer
49  */
50 static unsigned num_bits_buf_unaligned;
51
52 void
53 to_file_ (const char *file_name, char *line)
54 {
55   struct GNUNET_DISK_FileHandle *f;
56   char output_buffer[512];
57   size_t output_buffer_size = 512;
58   char *output_buffer_p;
59   //size_t size;
60   int size;
61   size_t size2;
62
63
64   if (NULL == (f = GNUNET_DISK_file_open (file_name,
65                                           GNUNET_DISK_OPEN_APPEND |
66                                           GNUNET_DISK_OPEN_WRITE |
67                                           GNUNET_DISK_OPEN_CREATE,
68                                           GNUNET_DISK_PERM_USER_READ |
69                                           GNUNET_DISK_PERM_USER_WRITE |
70                                           GNUNET_DISK_PERM_GROUP_READ |
71                                           GNUNET_DISK_PERM_OTHER_READ)))
72   {
73     LOG (GNUNET_ERROR_TYPE_WARNING,
74          "Not able to open file %s\n",
75          file_name);
76     return;
77   }
78   output_buffer_size = strlen (line) + 18;
79   if (512 < output_buffer_size)
80   {
81     output_buffer_p = GNUNET_malloc ((output_buffer_size) * sizeof (char));
82   } else {
83     output_buffer_p = &output_buffer[0];
84   }
85   size = GNUNET_snprintf (output_buffer_p,
86                           output_buffer_size,
87                           "%llu %s\n",
88                           (GNUNET_TIME_absolute_get ().abs_value_us) / 1000000, // microsec -> sec
89                           line);
90   if (0 > size)
91   {
92     LOG (GNUNET_ERROR_TYPE_WARNING,
93          "Failed to write string to buffer (size: %i)\n",
94          size);
95     return;
96   }
97
98   size2 = GNUNET_DISK_file_write (f, output_buffer_p, size);
99   if (size != size2)
100   {
101     LOG (GNUNET_ERROR_TYPE_WARNING,
102          "Unable to write to file! (Size: %u, size2: %u)\n",
103          size,
104          size2);
105
106     if (GNUNET_YES != GNUNET_DISK_file_close (f))
107       LOG (GNUNET_ERROR_TYPE_WARNING,
108            "Unable to close file\n");
109
110     return;
111   }
112
113   if (512 < output_buffer_size)
114   {
115     GNUNET_free (output_buffer_p);
116   }
117
118   if (GNUNET_YES != GNUNET_DISK_file_close (f))
119     LOG (GNUNET_ERROR_TYPE_WARNING,
120          "Unable to close file\n");
121 }
122
123 void
124 to_file_raw (const char *file_name, const char *buf, size_t size_buf)
125 {
126   struct GNUNET_DISK_FileHandle *f;
127   size_t size_written;
128
129   if (NULL == (f = GNUNET_DISK_file_open (file_name,
130                                           GNUNET_DISK_OPEN_APPEND |
131                                           GNUNET_DISK_OPEN_WRITE |
132                                           GNUNET_DISK_OPEN_CREATE,
133                                           GNUNET_DISK_PERM_USER_READ |
134                                           GNUNET_DISK_PERM_USER_WRITE |
135                                           GNUNET_DISK_PERM_GROUP_READ |
136                                           GNUNET_DISK_PERM_OTHER_READ)))
137   {
138     LOG (GNUNET_ERROR_TYPE_WARNING,
139          "Not able to open file %s\n",
140          file_name);
141     return;
142   }
143
144   size_written = GNUNET_DISK_file_write (f, buf, size_buf);
145   if (size_buf != size_written)
146   {
147     LOG (GNUNET_ERROR_TYPE_WARNING,
148          "Unable to write to file! (Size: %u, size_written: %u)\n",
149          size_buf,
150          size_written);
151
152     if (GNUNET_YES != GNUNET_DISK_file_close (f))
153       LOG (GNUNET_ERROR_TYPE_WARNING,
154            "Unable to close file\n");
155
156     return;
157   }
158 }
159
160 void
161 to_file_raw_unaligned (const char *file_name,
162                        const char *buf,
163                        size_t size_buf,
164                        unsigned bits_needed)
165 {
166   // TODO endianness!
167   GNUNET_assert (size_buf >= (bits_needed/8));
168   //if (0 == num_bits_buf_unaligned)
169   //{
170   //  if (0 == (bits_needed % 8))
171   //  {
172   //    to_file_raw (file_name, buf, size_buf);
173   //    return;
174   //  }
175   //  to_file_raw (file_name, buf, size_buf - 1);
176   //  buf_unaligned = buf[size_buf - 1];
177   //  num_bits_buf_unaligned = bits_needed % 8;
178   //  return;
179   //}
180
181   char buf_write[size_buf + 1];
182   const unsigned bytes_iter = (0 != bits_needed % 8?
183                                (bits_needed/8)+1:
184                                bits_needed/8);
185   // TODO what if no iteration happens?
186   unsigned size_buf_write = 0;
187   buf_write[0] = buf_unaligned;
188   /* Iterate over input bytes */
189   for (unsigned i = 0; i < bytes_iter; i++)
190   {
191     /* Number of bits needed in this iteration - 8 for all except last iter */
192     unsigned num_bits_needed_iter;
193     /* Mask for bits to actually use */
194     unsigned mask_bits_needed_iter;
195     char byte_input;
196     /* Number of bits needed to align unaligned byte */
197     unsigned num_bits_to_align;
198     /* Number of bits that are to be moved */
199     unsigned num_bits_to_move;
200     /* Mask for bytes to be moved */
201     char mask_input_to_move;
202     /* Masked bits to be moved */
203     char bits_to_move;
204     /* The amount of bits needed to fit the bits to shift to the nearest spot */
205     unsigned distance_shift_bits;
206     /* Shifted bits on the move */
207     char bits_moving;
208     /* (unaligned) byte being filled with bits */
209     char byte_to_fill;
210     /* mask for needed bits of the input byte that have not been moved */
211     char mask_input_leftover;
212     /* needed bits of the input byte that have not been moved */
213     char byte_input_leftover;
214     unsigned num_bits_leftover;
215     unsigned num_bits_discard;
216     char byte_unaligned_new;
217
218     if ( (bits_needed - (i * 8)) <= 8)
219     {
220       /* last iteration */
221       num_bits_needed_iter = bits_needed - (i * 8);
222     }
223     else
224     {
225       num_bits_needed_iter = 8;
226     }
227     mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1;
228     byte_input = buf[i];
229     byte_input &= mask_bits_needed_iter;
230     num_bits_to_align = 8 - num_bits_buf_unaligned;
231     num_bits_to_move  = min (num_bits_to_align, num_bits_needed_iter);
232     mask_input_to_move = ((char) 1 << num_bits_to_move) - 1;
233     bits_to_move = byte_input & mask_input_to_move;
234     distance_shift_bits = num_bits_buf_unaligned;
235     bits_moving = bits_to_move << distance_shift_bits;
236     byte_to_fill = buf_unaligned | bits_moving;
237     if (num_bits_buf_unaligned + num_bits_needed_iter > 8)
238     {
239       /* buf_unaligned was aligned by filling
240        * -> can be written to storage */
241       buf_write[i] = byte_to_fill;
242       size_buf_write++;
243
244       /* store the leftover, unaligned bits in buffer */
245       mask_input_leftover = mask_bits_needed_iter & (~ mask_input_to_move);
246       byte_input_leftover = byte_input & mask_input_leftover;
247       num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
248       num_bits_discard = 8 - num_bits_needed_iter;
249       byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
250       buf_unaligned = byte_unaligned_new;
251       num_bits_buf_unaligned = num_bits_leftover % 8;
252     }
253     else
254     {
255       /* unaligned buffer still unaligned but 'fuller' */
256       buf_unaligned = byte_to_fill;
257       num_bits_buf_unaligned = (num_bits_buf_unaligned + bits_needed) % 8;
258     }
259   }
260   to_file_raw (file_name, buf_write, size_buf_write);
261   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
262 }
263
264 char *
265 auth_key_to_string (struct GNUNET_CRYPTO_AuthKey auth_key)
266 {
267   int size;
268   size_t name_buf_size;
269   char *end;
270   char *buf;
271   char *name_buf;
272   size_t keylen = (sizeof (struct GNUNET_CRYPTO_AuthKey)) * 8;
273
274   name_buf_size = 512 * sizeof (char);
275   name_buf = GNUNET_malloc (name_buf_size);
276
277   if (keylen % 5 > 0)
278     keylen += 5 - keylen % 5;
279   keylen /= 5;
280   buf = GNUNET_malloc (keylen + 1);
281
282   end = GNUNET_STRINGS_data_to_string (&(auth_key.key),
283       sizeof (struct GNUNET_CRYPTO_AuthKey),
284       buf,
285       keylen);
286
287   if (NULL == end)
288   {
289     GNUNET_free (buf);
290     GNUNET_break (0);
291   }
292   else
293   {
294     *end = '\0';
295   }
296
297   size = GNUNET_snprintf (name_buf, name_buf_size, "sampler_el-%s", buf);
298   if (0 > size)
299     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
300
301   GNUNET_free (buf);
302
303   return name_buf;
304 }
305
306
307 struct GNUNET_CRYPTO_AuthKey
308 string_to_auth_key (const char *str)
309 {
310   struct GNUNET_CRYPTO_AuthKey auth_key;
311
312   if (GNUNET_OK !=
313       GNUNET_STRINGS_string_to_data (str,
314                                      strlen (str),
315                                      &auth_key.key,
316                                      sizeof (struct GNUNET_CRYPTO_AuthKey)))
317   {
318     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
319   }
320
321   return auth_key;
322 }
323
324
325 char *
326 create_file (const char *name)
327 {
328   int size;
329   size_t name_buf_size;
330   char *name_buf;
331   char *prefix;
332   char *file_name;
333
334   prefix = "/tmp/rps/";
335   name_buf_size = (strlen (prefix) + strlen (name) + 2) * sizeof (char);
336   name_buf = GNUNET_malloc (name_buf_size);
337
338   size = GNUNET_snprintf (name_buf, name_buf_size, "%s%s", prefix, name);
339   if (0 > size)
340     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
341
342   if (GNUNET_YES != GNUNET_DISK_directory_create (prefix))
343   {
344     LOG (GNUNET_ERROR_TYPE_WARNING,
345          "Could not create directory %s.\n",
346          prefix);
347   }
348
349   if (NULL == strstr (name, "sampler_el"))
350   {/* only append random string to sampler */
351     if (NULL == (file_name = GNUNET_DISK_mktemp (name_buf)))
352           LOG (GNUNET_ERROR_TYPE_WARNING, "Could not create file\n");
353
354   GNUNET_free (name_buf);
355   return file_name;
356   }
357
358   return name_buf;
359 }
360
361 #endif /* TO_FILE */
362
363 /**
364  * @brief Try to ensure that `/tmp/rps` exists.
365  *
366  * @return #GNUNET_YES on success
367  *         #GNUNET_SYSERR on failure
368  */
369 static int ensure_folder_exist (void)
370 {
371   if (GNUNET_NO == GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
372   {
373     GNUNET_DISK_directory_create ("/tmp/rps");
374   }
375   if (GNUNET_YES != GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
376   {
377     return GNUNET_SYSERR;
378   }
379   return GNUNET_YES;
380 }
381
382 const char *
383 store_prefix_file_name (const struct GNUNET_PeerIdentity *peer,
384     const char *prefix)
385 {
386   unsigned int len_file_name;
387   unsigned int out_size;
388   char *file_name;
389   const char *pid_long;
390
391   if (GNUNET_SYSERR == ensure_folder_exist()) return NULL;
392   pid_long = GNUNET_i2s_full (peer);
393   len_file_name = (strlen (prefix) +
394                    strlen (pid_long) +
395                    11)
396                      * sizeof (char);
397   file_name = GNUNET_malloc (len_file_name);
398   out_size = GNUNET_snprintf (file_name,
399                               len_file_name,
400                               "/tmp/rps/%s-%s",
401                               prefix,
402                               pid_long);
403   if (len_file_name < out_size ||
404       0 > out_size)
405   {
406     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
407                "Failed to write string to buffer (size: %i, out_size: %i)\n",
408                len_file_name,
409                out_size);
410   }
411   return file_name;
412 }
413
414 /* end of gnunet-service-rps.c */