libgnunetmy begin result helper
[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_pq_lib.h"
22
23 /**
24   * Function called to clean up memory allocated
25   * by a #GNUNET_MY_ResultConverter.
26   *
27   * @param cls closure
28   * @param rd result data to clean up
29   */
30 static void
31 clean_varsize_blob (void *cls,
32                     void *rs)
33 {
34   void **dst = rd;
35
36   if (NULL != *dst)
37   {
38     GNUNET_free (*dst);
39     *dst = NULL;
40   }
41 }
42
43
44 /**
45   * extract data from a Mysql database @a result at row @a row
46   *
47   * @param cls closure
48   * @param result where to extract data from
49   * @param int row to extract data from
50   * @param fname name (or prefix) of the fields to extract from
51   * @param[in, out] dst_size where to store size of result, may be NULL
52   * @param[out] dst where to store the result
53   * @return
54   *   #GNUNET_OK if all results could be extracted
55   *   #GNUNET_SYSERR if a result was invalid
56   */
57 static int
58 extract_varsize_blob (void *cls,
59                       MYSQL_RES * result,
60                       int row,
61                       const char *fname,
62                       size_t *dst_size,
63                       void *dst)
64 {
65   const char *res;
66   void *idst;
67   size_t len;
68
69   MYSQL_ROW * rows;
70   MYSQL_FIELD * field;
71
72   rows = mysql_fetch_row (result);
73
74   field = mysql_fetch_field (result);
75
76   //If it's the correct field
77   if (field != fname)
78   {
79     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
80                 "Field '%s' does not exist in result",
81                 fname);
82
83     return GNUNET_SYSERR;
84   }
85
86
87   if (rows[row] == NULL)
88   {
89     return GNUNET_SYSERR;
90   }
91
92   res = rows[row];
93
94   len = strlen(res);
95
96   GNUNET_assert (NULL != res);
97   
98   *dst_size = len;
99   idst = GNUNET_malloc (len);
100   *((void **) dst) = idst;
101   memcpy (idst,
102           res,
103           len);
104
105   return GNUNET_OK;
106 }
107
108 /**
109   * Variable-size result expected
110   *
111   * @param[out] dst where to store the result, allocated
112   * @param[out] sptr where to store the size of @a dst
113   * @return array entru for the result specification to use
114   */
115 struct GNUNET_MY_ResultSpec
116 GNUNET_MY_result_spec_variable_size (void **dst,
117                                     size_t *ptr_size)
118 {
119   struct GNUNET_MY_ResultSpec res = {
120     &extract_varsize_blob,
121     NULL,
122     (void *)(dst),
123     0,
124     ptr_size
125   }
126
127   return res;
128 }
129
130 /**
131   * Extract data from a Mysql database @a result at row @a row
132   *
133   * @param cls closure
134   * @param result where to extract data from
135   * @param int row to extract data from
136   * @param fname name (or prefix) of the fields to extract from
137   * @param[in] dst_size desired size, never NULL
138   * @param[out] dst where to store the result
139   * @return
140   *  #GNUNET_OK if all results could be extracted
141   *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
142   *
143   */
144 static int
145 extracted_fixed_blob (void *cls,
146                       MYSQL_RES * result,
147                       int row,
148                       const char * fname,
149                       size_t * dst_size,
150                       void *dst)
151 {
152   size_t len;
153   const char *res;
154
155   MYSQL_ROW * rows;
156   MYSQL_FIELD * field;
157
158   rows = mysql_fetch_row (result);
159
160   field = mysql_fetch_field (result);
161
162   //If it's the correct field
163   if (field != fname)
164   {
165     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
166                 "Field '%s' does not exist in result",
167                 fname);
168
169     return GNUNET_SYSERR;
170   }
171
172
173   if (rows[row] == NULL)
174   {
175     return GNUNET_SYSERR;
176   }
177
178   res = rows[row];
179
180   len = strlen (res);
181   if (*dst_size != len)
182   {
183     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
184                 "Field '%s' has wrong size (got %u, expected %u)\n",
185                 fname,
186                 (unsigned int)len,
187                 (unsigned int) *dst_size);
188     return GNUNET_SYSERR;
189   }
190
191   GNUNET_assert (NULL != res);
192   
193   memcpy (dst,
194           res,
195           len);
196
197   return GNUNET_OK;
198 }
199 /**
200  * Fixed-size result expected.
201  *
202  * @param name name of the field in the table
203  * @param[out] dst where to store the result
204  * @param dst_size number of bytes in @a dst
205  * @return array entry for the result specification to use
206  */
207 struct GNUNET_MY_ResultSpec
208 GNUNET_MY_result_spec_fixed_size (void *ptr,
209                                   size_t ptr_size)
210 {
211   struct GNUNET_MY_ResultSpec res = { 
212     &extract_fixed_blob,
213     NULL,
214     (void *)(ptr),
215     ptr_size,
216     NULL 
217   };
218       
219   return res;
220 }
221
222 /**
223   * Extract data from a Mysql database @a result at row @a row
224   *
225   * @param cls closure
226   * @param result where to extract data from
227   * @param int row to extract data from
228   * @param fname name (or prefix) of the fields to extract from
229   * @param[in, out] dst_size where to store size of result, may be NULL
230   * @param[out] dst where to store the result
231   * @return
232   *   #GNUNET_OK if all results could be extracted
233   *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
234   */
235 static int
236 extract_rsa_public_key (void *cls,
237                         MYSQL_RES *result,
238                         int rown,
239                         const char *fname,
240                         size_t *dst_size,
241                         void *dst)
242 {
243   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
244   size_t len;
245   const char *res;
246
247   MYSQL_ROW * rows;
248   MYSQL_FIELD * field;
249
250   *pk = NULL;
251
252   rows = mysql_fetch_row (result);
253
254   field = mysql_fetch_field (result);
255
256   //If it's the correct field
257   if (field != fname)
258   {
259     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
260                 "Field '%s' does not exist in result",
261                 fname);
262     return GNUNET_SYSERR;
263   }
264
265
266   if (rows[row] == NULL)
267   {
268     return GNUNET_SYSERR;
269   }
270
271   res = rows[row];
272
273   len = strlen (res);
274   
275   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res, 
276                                             len);
277
278   if (NULL == *pk)
279   {
280     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
281                 "Field '%s' contains bogus value (fails to decode\n",
282                   fname);
283     return GNUNET_SYSERR;
284   }
285   return GNUNET_OK;
286 }
287
288 /**
289   * Function called to clean up memory allocated
290   * by a #GNUNET_MY_ResultConverter
291   *
292   * @param cls closure
293   * @param rd result data to clean up
294   */
295 static void
296 clean_rsa_public_key (void *cls,
297                       void *rd)
298 {
299   struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
300   if (NULL != *pk)
301   {
302     GNUNET_CRYPTO_rsa_public_key_free (*pk);
303     *pk = NULL;
304   }
305 }
306
307
308 /**
309   * RSA public key expected
310   *
311   * @param name name of the field in the table
312   * @param[out] rsa where to store the result
313   * @return array entry for the result specification to use
314   */
315 struct GNUNET_MY_ResultSpec
316 GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
317 {
318   struct GNUNET_MY_ResultSpec res = {
319     &extract_rsa_public_key,
320     NULL,
321     (void *) rsa,
322     0,
323     NULL    
324   };
325
326   return res;
327 }
328
329 /**
330   * Extract data from a Mysql database @a result at row @a row.
331   *
332   * @param cls closure
333   * @param result where to extract data from
334   * @param int row to extract data from
335   * @param fname name (or prefix) of the fields to extract from
336   * @param[in,out] dst_size where to store size of result, may be NULL
337   * @param[out] dst where to store the result
338   * @return
339   *    #GNUNET_OK if all results could be extracted
340   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
341   */
342 static int
343 extract_rsa_signature (void *cls,
344                       MYSQL_RES * result,
345                       int row, const char *fname,
346                       size_t * dst_size,
347                       void *dst)
348 {
349   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
350   size_t len;
351   const char *res;
352
353   
354   MYSQL_ROW * rows;
355   MYSQL_FIELD * field;
356
357   *sig = NULL;
358
359   rows = mysql_fetch_row (result);
360
361   field = mysql_fetch_field (result);
362
363   //If it's the correct field
364   if (field == fname)
365   {
366     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
367                 "Field '%s' does not exist in result",
368                 fname);
369     return GNUNET_SYSERR;
370   }
371
372
373   if (rows[row] == NULL)
374   {
375     return GNUNET_SYSERR;
376   }
377
378   res = rows[row];
379   len = strlen (res);
380
381   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
382                                             len);
383
384   if (NULL == *sig)
385   {
386     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
387                 "Field '%s' contains bogus value (fails to decode)\n",
388                 fname);
389     return GNUNET_SYSERR;
390   }
391
392   return GNUNET_OK;
393 }
394
395 /**
396   * RSA signature expected.
397   *
398   * @param[out] sig where to store the result;
399   * @return array entry for the result specification to use
400   */
401 struct GNUNET_MY_ResultSpec
402 GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
403 {
404   struct GNUNET_MY_ResultSpec res = 
405   {
406     &extract_rsa_signature,
407     NULL,
408     (void *)sig,
409     0,
410     NULL
411   };
412   return res;
413 }
414
415 /**
416   * Extract data from a Mysql database @a result at row @a row
417   *
418   * @param cls closure
419   * @param result where to extract data from
420   * @param int row to extract data from
421   * @param fname name (or prefix) of the fields to extract from
422   * @param[in, out] dst_size where to store size of result, may be NULL
423   * @param[out] dst where to store the result
424   * @return
425   *    #GNUNET_OK if all results could be extracted
426   *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
427   */
428 static int
429 extract_string (void * cls,
430                 MYSQL_RES * result,
431                 int row,
432                 const char * fname,
433                 size_t *dst_size,
434                 void *dst)
435 {
436   char **str = dst;
437   size_t len;
438   const char *res;
439
440   MYSQL_ROW * rows;
441   MYSQL_FIELD * field;
442
443   *str = NULL;
444
445   rows = mysql_fetch_row (result);
446
447   field = mysql_fetch_field (result);
448
449   //If it's the correct field
450   if (field == fname)
451   {
452     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
453                 "Field '%s' does not exist in result",
454                 fname);
455     return GNUNET_SYSERR;
456   }
457
458
459   if (rows[row] == NULL)
460   {
461     return GNUNET_SYSERR;
462   }
463
464   res = rows[row];
465   len = strlen (res);
466  
467   *str = GNUNET_strndup (res,
468                         len);
469
470   if (NULL == *str)
471   {
472     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
473                 "Field '%s' contains bogus value (fails to decode) \n",
474                 fname);
475     return GNUNET_SYSERR;
476   }
477   return GNUNET_OK;
478 }    
479 /**
480   * 0- terminated string exprected.
481   *
482   * @param[out] dst where to store the result, allocated
483   * @return array entry for the result specification to use
484   */
485 struct GNUNET_MY_ResultSpec
486 GNUNET_MY_result_spec_string (char **dst)
487 {
488   struct GNUNET_MY_ResultSpec res = {
489     &extract_string,
490     NULL,
491     (void *) dst,
492     0,
493     NULL
494   };
495   return res;
496 }
497
498 /**
499   * Absolute time expected
500   *
501   * @param name name of the field in the table
502   * @param[out] at where to store the result
503   * @return array entry for the result specification to use
504   */
505 struct GNUNET_MY_ResultSpec
506 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
507 {
508   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
509 }
510
511 /**
512   * Absolute time in network byte order expected
513   *
514   * @param[out] at where to store the result
515   * @return array entry for the result specification to use
516   */
517 struct GNUNET_MY_ResultSpec
518 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
519 {
520   struct GNUNET_MY_ResultSpec res = 
521     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
522     return res;
523 }
524
525 /**
526  * Extract data from a Postgres database @a result at row @a row.
527  *
528  * @param cls closure
529  * @param result where to extract data from
530  * @param int row to extract data from
531  * @param fname name (or prefix) of the fields to extract from
532  * @param[in,out] dst_size where to store size of result, may be NULL
533  * @param[out] dst where to store the result
534  * @return
535  *   #GNUNET_YES if all results could be extracted
536  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
537  */
538 static int
539 extract_uint16 (void *cls,
540               MYSQL_RES * result,
541               int row,
542               const char *fname,
543               size_t *dst_size,
544               void *dst)
545 {
546     //TO COMPLETE 
547 }
548
549 /**
550   * uint16_t expected
551   *
552   * @param[out] u16 where to store the result
553   * @return array entry for the result specification to use
554   */
555 struct GNUNET_MY_ResultSpec
556 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
557 {
558   struct GNUNET_MY_ResultSpec res = {
559     &extract_uint16,
560     NULL,
561     (void *) u16,
562     sizeof (*u16),
563     NULL
564   };
565   return res;
566 }
567
568 /**
569 /* end of pq_result_helper.c */