refactoring my API
[oweals/gnunet.git] / src / my / my_result_helper.c
1  /*
2   This file is part of GNUnet
3   Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4   GNUnet is free software; you can redistribute it and/or modify it under the
5   terms of the GNU General Public License as published by the Free Software
6   Foundation; either version 3, or (at your option) any later version.
7   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
8   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
9   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
10   You should have received a copy of the GNU General Public License along with
11   GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
12 */
13 /**
14  * @file my/my_result_helper.c
15  * @brief functions to extract result values
16  * @author Christophe Genevey
17  */
18
19 #include "platform.h"
20 #include "gnunet_util_lib.h"
21 #include "gnunet_my_lib.h"
22
23 /**
24  * extract data from a Mysql database @a result at row @a row
25  *
26  * @param cls closure
27  * @param qp data about the query
28  * @param result mysql result
29  * @return
30  *   #GNUNET_OK if all results could be extracted
31  *   #GNUNET_SYSERR if a result was invalid
32  */
33 static int
34 pre_extract_varsize_blob (void *cls,
35                           struct GNUNET_MY_ResultSpec *rs,
36                           MYSQL_BIND *results)
37 {
38   results[0].buffer = NULL;
39   results[0].buffer_length = 0;
40   results[0].length = &rs->mysql_bind_output_length;
41   return GNUNET_OK;
42 }
43
44
45 /**
46  * extract data from a Mysql database @a result at row @a row
47  *
48  * @param cls closure
49  * @param[in,out] rs
50  * @param stmt the mysql statement that is being run
51  * @param column the column that is being processed
52  * @param[out] results
53  * @return
54  *   #GNUNET_OK if all results could be extracted
55  *   #GNUNET_SYSERR if a result was invalid
56  */
57 static int
58 post_extract_varsize_blob (void *cls,
59                            struct GNUNET_MY_ResultSpec *rs,
60                            MYSQL_STMT *stmt,
61                            unsigned int column,
62                            MYSQL_BIND *results)
63 {
64   void *buf;
65   size_t size;
66
67   size = (size_t) rs->mysql_bind_output_length;
68   if (rs->mysql_bind_output_length != size)
69     return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
70   buf = GNUNET_malloc (size);
71   results[0].buffer = buf;
72   results[0].buffer_length = size;
73   if (0 !=
74       mysql_stmt_fetch_column (stmt,
75                                results,
76                                column,
77                                0))
78   {
79     GNUNET_free (buf);
80     return GNUNET_SYSERR;
81   }
82   *(void **) rs->dst = buf;
83   *rs->result_size = size;
84   return GNUNET_OK;
85 }
86
87
88 /**
89  * extract data from a Mysql database @a result at row @a row
90  *
91  * @param cls closure
92  * @param[in,out] rs
93  */
94 static void
95 cleanup_varsize_blob (void *cls,
96                       struct GNUNET_MY_ResultSpec *rs)
97 {
98   void *ptr;
99
100   ptr = * (void **) rs->dst;
101   if (NULL == ptr)
102     return;
103   GNUNET_free (ptr);
104   *(void **) rs->dst = NULL;
105   *rs->result_size = 0;
106 }
107
108
109 /**
110  * Variable-size result expected
111  *
112  * @param[out] dst where to store the result, allocated
113  * @param[out] sptr where to store the size of @a dst
114  * @return array entru for the result specification to use
115  */
116 struct GNUNET_MY_ResultSpec
117 GNUNET_MY_result_spec_variable_size (void **dst,
118                                     size_t *ptr_size)
119 {
120   struct GNUNET_MY_ResultSpec res =
121   {
122     .pre_conv = &pre_extract_varsize_blob,
123     .post_conv = &post_extract_varsize_blob,
124     .cleaner = &cleanup_varsize_blob,
125     .dst =  (void *)(dst),
126     .result_size = ptr_size,
127     .num_fields = 1
128   };
129
130   return res;
131 }
132
133
134 /**
135  * Extract data from a Mysql database @a result at row @a row
136  *
137  * @param cls closure
138  * @param result where to extract data from
139  * @param int row to extract data from
140  * @param fname name (or prefix) of the fields to extract from
141  * @param[in] dst_size desired size, never NULL
142  * @param[out] dst where to store the result
143  * @return
144  *  #GNUNET_OK if all results could be extracted
145  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
146  */
147 static int
148 pre_extract_fixed_blob (void *cls,
149                         struct GNUNET_MY_ResultSpec *rs,
150                         MYSQL_BIND *results)
151 {
152   results[0].buffer = rs->dst;
153   results[0].buffer_length = rs->dst_size;
154   results[0].length = &rs->mysql_bind_output_length;
155   return GNUNET_OK;
156 }
157
158
159 /**
160  * Check size of extracted fixed size data from a Mysql database @a
161  * result at row @a row
162  *
163  * @param cls closure
164  * @param result where to extract data from
165  * @param int row to extract data from
166  * @param fname name (or prefix) of the fields to extract from
167  * @param[in] dst_size desired size, never NULL
168  * @param[out] dst where to store the result
169  * @return
170  *  #GNUNET_OK if all results could be extracted
171  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
172  */
173 static int
174 post_extract_fixed_blob (void *cls,
175                          struct GNUNET_MY_ResultSpec *rs,
176                          MYSQL_BIND *results)
177 {
178   if (rs->dst_size != rs->mysql_bind_output_length)
179     return GNUNET_SYSERR;
180   return GNUNET_OK;
181 }
182
183
184 /**
185  * Fixed-size result expected.
186  *
187  * @param name name of the field in the table
188  * @param[out] dst where to store the result
189  * @param dst_size number of bytes in @a dst
190  * @return array entry for the result specification to use
191  */
192 struct GNUNET_MY_ResultSpec
193 GNUNET_MY_result_spec_fixed_size (void *ptr,
194                                   size_t ptr_size)
195 {
196   struct GNUNET_MY_ResultSpec res =
197   {
198     .pre_conv = &pre_extract_fixed_blob,
199     .post_conv = &post_extract_fixed_blob,
200     .dst = (void *)(ptr),
201     .dst_size = ptr_size,
202     .num_fields = 1
203   };
204
205   return res;
206 }
207
208 /**
209   * Extract data from a Mysql database @a result at row @a row
210   *
211   * @param cls closure
212   * @param result where to extract data from
213   * @param int row to extract data from
214   * @param fname name (or prefix) of the fields to extract from
215   * @param[in, out] dst_size where to store size of result, may be NULL
216   * @param[out] dst where to store the result
217   * @return
218   *   #GNUNET_OK if all results could be extracted
219   *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
220   */
221 static int
222 extract_rsa_public_key (void *cls,
223                        struct GNUNET_MY_ResultSpec *rs,
224                         MYSQL_BIND *results)
225
226 {
227   struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
228
229   size_t len;
230   const char *res;
231
232   if (results->is_null)
233   {
234     return GNUNET_SYSERR;
235   }
236
237   len = results->buffer_length;
238   res = results->buffer;
239
240   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
241                                             len);
242
243   if (NULL == *pk)
244   {
245     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
246                 "Results contains bogus value (fail to decode)\n");
247     return GNUNET_SYSERR;
248   }
249
250   return GNUNET_OK;
251 }
252
253 /**
254   * RSA public key expected
255   *
256   * @param name name of the field in the table
257   * @param[out] rsa where to store the result
258   * @return array entry for the result specification to use
259   */
260 struct GNUNET_MY_ResultSpec
261 GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
262 {
263   struct GNUNET_MY_ResultSpec res = {
264     &extract_rsa_public_key,
265     NULL,
266     (void *) rsa,
267     0,
268     NULL,
269     1
270   };
271
272   return res;
273 }
274
275 /**
276   * Extract data from a Mysql database @a result at row @a row.
277   *
278   * @param cls closure
279   * @param result where to extract data from
280   * @param int row to extract data from
281   * @param fname name (or prefix) of the fields to extract from
282   * @param[in,out] dst_size where to store size of result, may be NULL
283   * @param[out] dst where to store the result
284   * @return
285   *    #GNUNET_OK if all results could be extracted
286   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
287   */
288 static int
289 extract_rsa_signature (void *cls,
290                       struct GNUNET_MY_ResultSpec *rs,
291                       MYSQL_BIND *results)
292 {
293   struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
294   size_t len;
295   const char *res;
296
297   if (results->is_null)
298   {
299     return GNUNET_SYSERR;
300   }
301
302   len = results->buffer_length;
303   res = results->buffer;
304
305   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
306                                             len);
307
308   if (NULL != *sig)
309   {
310     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311                 "Resuls contains bogus value (fails to decode)\n");
312     return GNUNET_SYSERR;
313   }
314
315   return GNUNET_OK;
316 }
317
318 /**
319   * RSA signature expected.
320   *
321   * @param[out] sig where to store the result;
322   * @return array entry for the result specification to use
323   */
324 struct GNUNET_MY_ResultSpec
325 GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
326 {
327   struct GNUNET_MY_ResultSpec res =
328   {
329     &extract_rsa_signature,
330     NULL,
331     (void *)sig,
332     0,
333     NULL,
334     1
335   };
336   return res;
337 }
338
339 /**
340   * Extract data from a Mysql database @a result at row @a row
341   *
342   * @param cls closure
343   * @param result where to extract data from
344   * @param int row to extract data from
345   * @param fname name (or prefix) of the fields to extract from
346   * @param[in, out] dst_size where to store size of result, may be NULL
347   * @param[out] dst where to store the result
348   * @return
349   *    #GNUNET_OK if all results could be extracted
350   *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
351   */
352 static int
353 extract_string (void * cls,
354                 struct GNUNET_MY_ResultSpec *rs,
355                 MYSQL_BIND *results)
356 {
357   char **str = rs->dst;
358   size_t len;
359   const char *res;
360
361   *str = NULL;
362
363   if (results->is_null)
364   {
365     return GNUNET_SYSERR;
366   }
367
368   len = results->buffer_length;
369   res = results->buffer;
370
371   *str = GNUNET_strndup (res,
372                         len);
373
374   if (NULL == *str)
375   {
376     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
377                 "Results contains bogus value (fail to decode)\n");
378     return GNUNET_SYSERR;
379   }
380   return GNUNET_OK;
381 }
382
383
384 /**
385  * 0- terminated string exprected.
386  *
387  * @param[out] dst where to store the result, allocated
388  * @return array entry for the result specification to use
389  */
390 struct GNUNET_MY_ResultSpec
391 GNUNET_MY_result_spec_string (char **dst)
392 {
393   struct GNUNET_MY_ResultSpec res = {
394     &extract_string,
395     NULL,
396     (void *) dst,
397     0,
398     NULL,
399     1
400   };
401   return res;
402 }
403
404
405 /**
406  * Absolute time expected
407  *
408  * @param name name of the field in the table
409  * @param[out] at where to store the result
410  * @return array entry for the result specification to use
411   */
412 struct GNUNET_MY_ResultSpec
413 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
414 {
415   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
416 }
417
418
419 /**
420   * Absolute time in network byte order expected
421   *
422   * @param[out] at where to store the result
423   * @return array entry for the result specification to use
424   */
425 struct GNUNET_MY_ResultSpec
426 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
427 {
428   struct GNUNET_MY_ResultSpec res =
429     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
430   return res;
431 }
432
433
434 /**
435  * Extract data from a Postgres database @a result at row @a row.
436  *
437  * @param cls closure
438  * @param result where to extract data from
439  * @param int row to extract data from
440  * @param fname name (or prefix) of the fields to extract from
441  * @param[in,out] dst_size where to store size of result, may be NULL
442  * @param[out] dst where to store the result
443  * @return
444  *   #GNUNET_YES if all results could be extracted
445  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
446  */
447 static int
448 extract_uint16 (void *cls,
449                 struct GNUNET_MY_ResultSpec *rs,
450                 MYSQL_BIND *results)
451 {
452   uint16_t *udst = rs->dst;
453   const uint16_t *res;
454
455   if(results->is_null)
456   {
457     return GNUNET_SYSERR;
458   }
459
460   GNUNET_assert (NULL != rs->dst);
461   if (sizeof (uint16_t) != rs->dst_size)
462   {
463     GNUNET_break (0);
464     return GNUNET_SYSERR;
465   }
466
467   res = (uint16_t *)results->buffer;
468   *udst = ntohs (*res);
469
470   return GNUNET_OK;
471 }
472
473
474 /**
475  * uint16_t expected
476  *
477  * @param[out] u16 where to store the result
478  * @return array entry for the result specification to use
479  */
480 struct GNUNET_MY_ResultSpec
481 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
482 {
483   struct GNUNET_MY_ResultSpec res = {
484     &extract_uint16,
485     NULL,
486     (void *) u16,
487     sizeof (*u16),
488     NULL,
489     1
490   };
491   return res;
492 }
493
494 /**
495   * Extrac data from a  MYSQL database @a result at row @a row
496   *
497   * @param cls closure
498   * @param result where to extract data from
499   * @param int row to extract data from
500   * @param fname name (or prefix) of the fields to extract from
501   * @param[in, out] dst_size where to store size of result, may be NULL
502   * @param[out] dst where to store the result
503   * @return
504   *      #GNUNET_OK if all results could be extracted
505   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
506   */
507 static int
508 extract_uint32 (void *cls,
509                 struct GNUNET_MY_ResultSpec *rs,
510                 MYSQL_BIND *results)
511 {
512   uint32_t *udst = rs->dst;
513   const uint32_t *res;
514
515   if(results->is_null)
516   {
517     return GNUNET_SYSERR;
518   }
519
520   GNUNET_assert (NULL != rs->dst);
521   if (sizeof (uint32_t) != rs->dst_size)
522   {
523     GNUNET_break (0);
524     return GNUNET_SYSERR;
525   }
526
527   res = (uint32_t *)results->buffer;
528
529   *udst = ntohl (*res);
530
531   return GNUNET_OK;
532 }
533
534 /**
535   * uint32_t expected
536   *
537   * @param[out] u32 where to store the result
538   * @return array entry for the result specification to use
539   */
540 struct GNUNET_MY_ResultSpec
541 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
542 {
543   struct GNUNET_MY_ResultSpec res = {
544     &extract_uint32,
545     NULL,
546     (void *) u32,
547     sizeof (*u32),
548     NULL,
549     1
550   };
551   return res;
552 }
553
554 /**
555   * Extract data from a MYSQL database @a result at row @a row
556   *
557   * @param cls closure
558   * @param result where to extract data from
559   * @param int row to extract data from
560   * @param fname name (or prefix) of the fields to extract from
561   * @param[in, out] dst_size where to store size of result, may be null
562   * @param[out] dst where to store the result
563   * @return
564   *    #GNUNET_OK if all results could be extracted
565   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
566   */
567 static int
568 extract_uint64 (void *cls,
569                 struct GNUNET_MY_ResultSpec *rs,
570                 MYSQL_BIND *results)
571 {
572   uint64_t *udst = rs->dst;
573   const uint64_t *res;
574
575   results[0].buffer = &rs->dst;
576   results[0].buffer_length = 42;
577
578   GNUNET_assert (NULL != rs->dst);
579   if (sizeof (uint64_t) != rs->dst_size)
580   {
581     GNUNET_break (0);
582     return GNUNET_SYSERR;
583   }
584
585   res = (uint64_t *)results->buffer;
586   *udst = GNUNET_ntohll (*res);
587
588   return GNUNET_OK;
589 }
590
591
592 /**
593   * uint64_t expected.
594   *
595   * @param[out] u64 where to store the result
596   * @return array entry for the result specification to use
597   */
598 struct GNUNET_MY_ResultSpec
599 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
600 {
601   struct GNUNET_MY_ResultSpec res = {
602     .pre_conv = &extract_uint64,
603     .dst = (void *) u64,
604     .dst_size = sizeof (*u64),
605     .num_fields = 1
606   };
607   return res;
608 }
609
610 /* end of pq_result_helper.c */