fix codesonar finding: add GNUnet_free
[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   if (GNUNET_YES != GNUNET_DISK_file_close (f))
159     LOG (GNUNET_ERROR_TYPE_WARNING,
160          "Unable to close file\n");
161 }
162
163 void
164 to_file_raw_unaligned (const char *file_name,
165                        const char *buf,
166                        size_t size_buf,
167                        unsigned bits_needed)
168 {
169   // TODO endianness!
170   GNUNET_assert (size_buf >= (bits_needed/8));
171   //if (0 == num_bits_buf_unaligned)
172   //{
173   //  if (0 == (bits_needed % 8))
174   //  {
175   //    to_file_raw (file_name, buf, size_buf);
176   //    return;
177   //  }
178   //  to_file_raw (file_name, buf, size_buf - 1);
179   //  buf_unaligned = buf[size_buf - 1];
180   //  num_bits_buf_unaligned = bits_needed % 8;
181   //  return;
182   //}
183
184   char buf_write[size_buf + 1];
185   const unsigned bytes_iter = (0 != bits_needed % 8?
186                                (bits_needed/8)+1:
187                                bits_needed/8);
188   // TODO what if no iteration happens?
189   unsigned size_buf_write = 0;
190   buf_write[0] = buf_unaligned;
191   /* Iterate over input bytes */
192   for (unsigned i = 0; i < bytes_iter; i++)
193   {
194     /* Number of bits needed in this iteration - 8 for all except last iter */
195     unsigned num_bits_needed_iter;
196     /* Mask for bits to actually use */
197     unsigned mask_bits_needed_iter;
198     char byte_input;
199     /* Number of bits needed to align unaligned byte */
200     unsigned num_bits_to_align;
201     /* Number of bits that are to be moved */
202     unsigned num_bits_to_move;
203     /* Mask for bytes to be moved */
204     char mask_input_to_move;
205     /* Masked bits to be moved */
206     char bits_to_move;
207     /* The amount of bits needed to fit the bits to shift to the nearest spot */
208     unsigned distance_shift_bits;
209     /* Shifted bits on the move */
210     char bits_moving;
211     /* (unaligned) byte being filled with bits */
212     char byte_to_fill;
213     /* mask for needed bits of the input byte that have not been moved */
214     char mask_input_leftover;
215     /* needed bits of the input byte that have not been moved */
216     char byte_input_leftover;
217     unsigned num_bits_leftover;
218     unsigned num_bits_discard;
219     char byte_unaligned_new;
220
221     if ( (bits_needed - (i * 8)) <= 8)
222     {
223       /* last iteration */
224       num_bits_needed_iter = bits_needed - (i * 8);
225     }
226     else
227     {
228       num_bits_needed_iter = 8;
229     }
230     mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1;
231     byte_input = buf[i];
232     byte_input &= mask_bits_needed_iter;
233     num_bits_to_align = 8 - num_bits_buf_unaligned;
234     num_bits_to_move  = min (num_bits_to_align, num_bits_needed_iter);
235     mask_input_to_move = ((char) 1 << num_bits_to_move) - 1;
236     bits_to_move = byte_input & mask_input_to_move;
237     distance_shift_bits = num_bits_buf_unaligned;
238     bits_moving = bits_to_move << distance_shift_bits;
239     byte_to_fill = buf_unaligned | bits_moving;
240     if (num_bits_buf_unaligned + num_bits_needed_iter > 8)
241     {
242       /* buf_unaligned was aligned by filling
243        * -> can be written to storage */
244       buf_write[i] = byte_to_fill;
245       size_buf_write++;
246
247       /* store the leftover, unaligned bits in buffer */
248       mask_input_leftover = mask_bits_needed_iter & (~ mask_input_to_move);
249       byte_input_leftover = byte_input & mask_input_leftover;
250       num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
251       num_bits_discard = 8 - num_bits_needed_iter;
252       byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
253       buf_unaligned = byte_unaligned_new;
254       num_bits_buf_unaligned = num_bits_leftover % 8;
255     }
256     else
257     {
258       /* unaligned buffer still unaligned but 'fuller' */
259       buf_unaligned = byte_to_fill;
260       num_bits_buf_unaligned = (num_bits_buf_unaligned + bits_needed) % 8;
261     }
262   }
263   to_file_raw (file_name, buf_write, size_buf_write);
264   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
265 }
266
267 char *
268 auth_key_to_string (struct GNUNET_CRYPTO_AuthKey auth_key)
269 {
270   int size;
271   size_t name_buf_size;
272   char *end;
273   char *buf;
274   char *name_buf;
275   size_t keylen = (sizeof (struct GNUNET_CRYPTO_AuthKey)) * 8;
276
277   name_buf_size = 512 * sizeof (char);
278   name_buf = GNUNET_malloc (name_buf_size);
279
280   if (keylen % 5 > 0)
281     keylen += 5 - keylen % 5;
282   keylen /= 5;
283   buf = GNUNET_malloc (keylen + 1);
284
285   end = GNUNET_STRINGS_data_to_string (&(auth_key.key),
286       sizeof (struct GNUNET_CRYPTO_AuthKey),
287       buf,
288       keylen);
289
290   if (NULL == end)
291   {
292     GNUNET_free (buf);
293     GNUNET_break (0);
294   }
295   else
296   {
297     *end = '\0';
298   }
299
300   size = GNUNET_snprintf (name_buf, name_buf_size, "sampler_el-%s", buf);
301   if (0 > size)
302     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
303
304   GNUNET_free (buf);
305
306   return name_buf;
307 }
308
309
310 struct GNUNET_CRYPTO_AuthKey
311 string_to_auth_key (const char *str)
312 {
313   struct GNUNET_CRYPTO_AuthKey auth_key;
314
315   if (GNUNET_OK !=
316       GNUNET_STRINGS_string_to_data (str,
317                                      strlen (str),
318                                      &auth_key.key,
319                                      sizeof (struct GNUNET_CRYPTO_AuthKey)))
320   {
321     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
322   }
323
324   return auth_key;
325 }
326
327
328 char *
329 create_file (const char *name)
330 {
331   int size;
332   size_t name_buf_size;
333   char *name_buf;
334   char *prefix;
335   char *file_name;
336
337   prefix = "/tmp/rps/";
338   name_buf_size = (strlen (prefix) + strlen (name) + 2) * sizeof (char);
339   name_buf = GNUNET_malloc (name_buf_size);
340
341   size = GNUNET_snprintf (name_buf, name_buf_size, "%s%s", prefix, name);
342   if (0 > size)
343     LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
344
345   if (GNUNET_YES != GNUNET_DISK_directory_create (prefix))
346   {
347     LOG (GNUNET_ERROR_TYPE_WARNING,
348          "Could not create directory %s.\n",
349          prefix);
350   }
351
352   if (NULL == strstr (name, "sampler_el"))
353   {/* only append random string to sampler */
354     if (NULL == (file_name = GNUNET_DISK_mktemp (name_buf)))
355           LOG (GNUNET_ERROR_TYPE_WARNING, "Could not create file\n");
356
357   GNUNET_free (name_buf);
358   return file_name;
359   }
360
361   return name_buf;
362 }
363
364 #endif /* TO_FILE */
365
366 /**
367  * @brief Try to ensure that `/tmp/rps` exists.
368  *
369  * @return #GNUNET_YES on success
370  *         #GNUNET_SYSERR on failure
371  */
372 static int ensure_folder_exist (void)
373 {
374   if (GNUNET_NO == GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
375   {
376     GNUNET_DISK_directory_create ("/tmp/rps");
377   }
378   if (GNUNET_YES != GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
379   {
380     return GNUNET_SYSERR;
381   }
382   return GNUNET_YES;
383 }
384
385 const char *
386 store_prefix_file_name (const struct GNUNET_PeerIdentity *peer,
387     const char *prefix)
388 {
389   unsigned int len_file_name;
390   int out_size;
391   char *file_name;
392   const char *pid_long;
393
394   if (GNUNET_SYSERR == ensure_folder_exist()) return NULL;
395   pid_long = GNUNET_i2s_full (peer);
396   len_file_name = (strlen (prefix) +
397                    strlen (pid_long) +
398                    11)
399                      * sizeof (char);
400   file_name = GNUNET_malloc (len_file_name);
401   out_size = GNUNET_snprintf (file_name,
402                               len_file_name,
403                               "/tmp/rps/%s-%s",
404                               prefix,
405                               pid_long);
406   if (len_file_name < out_size ||
407       0 > out_size)
408   {
409     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
410                "Failed to write string to buffer (size: %i, out_size: %i)\n",
411                len_file_name,
412                out_size);
413   }
414   return file_name;
415 }
416
417 /* end of gnunet-service-rps.c */