Link libgnunetblockgroup to libgnunetblock
[oweals/gnunet.git] / src / pq / pq_result_helper.c
1  /*
2   This file is part of GNUnet
3   Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5   GNUnet is free software; you can redistribute it and/or modify it under the
6   terms of the GNU General Public License as published by the Free Software
7   Foundation; either version 3, or (at your option) any later version.
8
9   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
13   You should have received a copy of the GNU General Public License along with
14   GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
15 */
16 /**
17  * @file pq/pq_result_helper.c
18  * @brief functions to extract result values
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_pq_lib.h"
24
25
26 /**
27  * Function called to clean up memory allocated
28  * by a #GNUNET_PQ_ResultConverter.
29  *
30  * @param cls closure
31  * @param rd result data to clean up
32  */
33 static void
34 clean_varsize_blob (void *cls,
35                     void *rd)
36 {
37   void **dst = rd;
38
39   if (NULL != *dst)
40   {
41     GNUNET_free (*dst);
42     *dst = NULL;
43   }
44 }
45
46
47 /**
48  * Extract data from a Postgres database @a result at row @a row.
49  *
50  * @param cls closure
51  * @param result where to extract data from
52  * @param int row to extract data from
53  * @param fname name (or prefix) of the fields to extract from
54  * @param[in,out] dst_size where to store size of result, may be NULL
55  * @param[out] dst where to store the result
56  * @return
57  *   #GNUNET_YES if all results could be extracted
58  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
59  */
60 static int
61 extract_varsize_blob (void *cls,
62                       PGresult *result,
63                       int row,
64                       const char *fname,
65                       size_t *dst_size,
66                       void *dst)
67 {
68   size_t len;
69   const char *res;
70   void *idst;
71   int fnum;
72
73   *dst_size = 0;
74   *((void **) dst) = NULL;
75
76   fnum = PQfnumber (result,
77                     fname);
78   if (fnum < 0)
79   {
80     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
81                 "Field `%s' does not exist in result\n",
82                 fname);
83     return GNUNET_SYSERR;
84   }
85   if (PQgetisnull (result,
86                    row,
87                    fnum))
88     return GNUNET_SYSERR;
89
90   /* if a field is null, continue but
91    * remember that we now return a different result */
92   len = PQgetlength (result,
93                      row,
94                      fnum);
95   res = PQgetvalue (result,
96                     row,
97                     fnum);
98   GNUNET_assert (NULL != res);
99   *dst_size = len;
100   idst = GNUNET_malloc (len);
101   *((void **) dst) = idst;
102   GNUNET_memcpy (idst,
103           res,
104           len);
105   return GNUNET_OK;
106 }
107
108
109 /**
110  * Variable-size result expected.
111  *
112  * @param name name of the field in the table
113  * @param[out] dst where to store the result, allocated
114  * @param[out] sptr where to store the size of @a dst
115  * @return array entry for the result specification to use
116  */
117 struct GNUNET_PQ_ResultSpec
118 GNUNET_PQ_result_spec_variable_size (const char *name,
119                                      void **dst,
120                                      size_t *sptr)
121 {
122   struct GNUNET_PQ_ResultSpec res =
123     { &extract_varsize_blob,
124       &clean_varsize_blob, NULL,
125       (void *) (dst), 0, name, sptr };
126   return res;
127 }
128
129
130 /**
131  * Extract data from a Postgres 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_YES if all results could be extracted
141  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
142  */
143 static int
144 extract_fixed_blob (void *cls,
145                     PGresult *result,
146                     int row,
147                     const char *fname,
148                     size_t *dst_size,
149                     void *dst)
150 {
151   size_t len;
152   const char *res;
153   int fnum;
154
155   fnum = PQfnumber (result,
156                     fname);
157   if (fnum < 0)
158   {
159     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
160                 "Field `%s' does not exist in result\n",
161                 fname);
162     return GNUNET_SYSERR;
163   }
164   if (PQgetisnull (result,
165                    row,
166                    fnum))
167     return GNUNET_SYSERR;
168
169   /* if a field is null, continue but
170    * remember that we now return a different result */
171   len = PQgetlength (result,
172                      row,
173                      fnum);
174   if (*dst_size != len)
175   {
176     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
177                 "Field `%s' has wrong size (got %u, expected %u)\n",
178                 fname,
179                 (unsigned int) len,
180                 (unsigned int) *dst_size);
181     return GNUNET_SYSERR;
182   }
183   res = PQgetvalue (result,
184                     row,
185                     fnum);
186   GNUNET_assert (NULL != res);
187   GNUNET_memcpy (dst,
188           res,
189           len);
190   return GNUNET_OK;
191 }
192
193
194 /**
195  * Fixed-size result expected.
196  *
197  * @param name name of the field in the table
198  * @param[out] dst where to store the result
199  * @param dst_size number of bytes in @a dst
200  * @return array entry for the result specification to use
201  */
202 struct GNUNET_PQ_ResultSpec
203 GNUNET_PQ_result_spec_fixed_size (const char *name,
204                                   void *dst,
205                                   size_t dst_size)
206 {
207   struct GNUNET_PQ_ResultSpec res =
208     { &extract_fixed_blob,
209       NULL, NULL,
210       (dst), dst_size, name, NULL };
211   return res;
212 }
213
214
215 /**
216  * Extract data from a Postgres database @a result at row @a row.
217  *
218  * @param cls closure
219  * @param result where to extract data from
220  * @param int row to extract data from
221  * @param fname name (or prefix) of the fields to extract from
222  * @param[in,out] dst_size where to store size of result, may be NULL
223  * @param[out] dst where to store the result
224  * @return
225  *   #GNUNET_YES if all results could be extracted
226  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
227  */
228 static int
229 extract_rsa_public_key (void *cls,
230                         PGresult *result,
231                         int row,
232                         const char *fname,
233                         size_t *dst_size,
234                         void *dst)
235 {
236   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
237   size_t len;
238   const char *res;
239   int fnum;
240
241   *pk = NULL;
242   fnum = PQfnumber (result,
243                     fname);
244   if (fnum < 0)
245   {
246     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
247                 "Field `%s' does not exist in result\n",
248                 fname);
249     return GNUNET_SYSERR;
250   }
251   if (PQgetisnull (result,
252                    row,
253                    fnum))
254     return GNUNET_SYSERR;
255
256   /* if a field is null, continue but
257    * remember that we now return a different result */
258   len = PQgetlength (result,
259                      row,
260                      fnum);
261   res = PQgetvalue (result,
262                     row,
263                     fnum);
264   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
265                                              len);
266   if (NULL == *pk)
267   {
268     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
269                 "Field `%s' contains bogus value (fails to decode)\n",
270                 fname);
271     return GNUNET_SYSERR;
272   }
273   return GNUNET_OK;
274 }
275
276
277 /**
278  * Function called to clean up memory allocated
279  * by a #GNUNET_PQ_ResultConverter.
280  *
281  * @param cls closure
282  * @param rd result data to clean up
283  */
284 static void
285 clean_rsa_public_key (void *cls,
286                       void *rd)
287 {
288   struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
289
290   if (NULL != *pk)
291   {
292     GNUNET_CRYPTO_rsa_public_key_free (*pk);
293     *pk = NULL;
294   }
295 }
296
297
298 /**
299  * RSA public key expected.
300  *
301  * @param name name of the field in the table
302  * @param[out] rsa where to store the result
303  * @return array entry for the result specification to use
304  */
305 struct GNUNET_PQ_ResultSpec
306 GNUNET_PQ_result_spec_rsa_public_key (const char *name,
307                                       struct GNUNET_CRYPTO_RsaPublicKey **rsa)
308 {
309   struct GNUNET_PQ_ResultSpec res =
310     { &extract_rsa_public_key,
311       &clean_rsa_public_key,
312       NULL,
313       (void *) rsa, 0, name, NULL };
314   return res;
315 }
316
317
318 /**
319  * Extract data from a Postgres database @a result at row @a row.
320  *
321  * @param cls closure
322  * @param result where to extract data from
323  * @param int row to extract data from
324  * @param fname name (or prefix) of the fields to extract from
325  * @param[in,out] dst_size where to store size of result, may be NULL
326  * @param[out] dst where to store the result
327  * @return
328  *   #GNUNET_YES if all results could be extracted
329  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
330  */
331 static int
332 extract_rsa_signature (void *cls,
333                        PGresult *result,
334                        int row,
335                        const char *fname,
336                        size_t *dst_size,
337                        void *dst)
338 {
339   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
340   size_t len;
341   const char *res;
342   int fnum;
343
344   *sig = NULL;
345   fnum = PQfnumber (result,
346                     fname);
347   if (fnum < 0)
348   {
349     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
350                 "Field `%s' does not exist in result\n",
351                 fname);
352     return GNUNET_SYSERR;
353   }
354   if (PQgetisnull (result,
355                    row,
356                    fnum))
357     return GNUNET_SYSERR;
358
359   /* if a field is null, continue but
360    * remember that we now return a different result */
361   len = PQgetlength (result,
362                      row,
363                      fnum);
364   res = PQgetvalue (result,
365                     row,
366                     fnum);
367   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
368                                              len);
369   if (NULL == *sig)
370   {
371     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
372                 "Field `%s' contains bogus value (fails to decode)\n",
373                 fname);
374     return GNUNET_SYSERR;
375   }
376   return GNUNET_OK;
377 }
378
379
380 /**
381  * Function called to clean up memory allocated
382  * by a #GNUNET_PQ_ResultConverter.
383  *
384  * @param cls closure
385  * @param rd result data to clean up
386  */
387 static void
388 clean_rsa_signature (void *cls,
389                      void *rd)
390 {
391   struct GNUNET_CRYPTO_RsaSignature **sig = rd;
392
393   if (NULL != *sig)
394   {
395     GNUNET_CRYPTO_rsa_signature_free (*sig);
396     *sig = NULL;
397   }
398 }
399
400
401 /**
402  * RSA signature expected.
403  *
404  * @param name name of the field in the table
405  * @param[out] sig where to store the result;
406  * @return array entry for the result specification to use
407  */
408 struct GNUNET_PQ_ResultSpec
409 GNUNET_PQ_result_spec_rsa_signature (const char *name,
410                                     struct GNUNET_CRYPTO_RsaSignature **sig)
411 {
412   struct GNUNET_PQ_ResultSpec res =
413     { &extract_rsa_signature,
414       &clean_rsa_signature,
415       NULL,
416       (void *) sig, 0, (name), NULL };
417   return res;
418 }
419
420
421 /**
422  * Extract data from a Postgres database @a result at row @a row.
423  *
424  * @param cls closure
425  * @param result where to extract data from
426  * @param int row to extract data from
427  * @param fname name (or prefix) of the fields to extract from
428  * @param[in,out] dst_size where to store size of result, may be NULL
429  * @param[out] dst where to store the result
430  * @return
431  *   #GNUNET_YES if all results could be extracted
432  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
433  */
434 static int
435 extract_string (void *cls,
436                 PGresult *result,
437                 int row,
438                 const char *fname,
439                 size_t *dst_size,
440                 void *dst)
441 {
442   char **str = dst;
443   size_t len;
444   const char *res;
445   int fnum;
446
447   *str = NULL;
448   fnum = PQfnumber (result,
449                     fname);
450   if (fnum < 0)
451   {
452     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
453                 "Field `%s' does not exist in result\n",
454                 fname);
455     return GNUNET_SYSERR;
456   }
457   if (PQgetisnull (result,
458                    row,
459                    fnum))
460     return GNUNET_SYSERR;
461
462   /* if a field is null, continue but
463    * remember that we now return a different result */
464   len = PQgetlength (result,
465                      row,
466                      fnum);
467   res = PQgetvalue (result,
468                     row,
469                     fnum);
470   *str = GNUNET_strndup (res,
471                          len);
472   if (NULL == *str)
473   {
474     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
475                 "Field `%s' contains bogus value (fails to decode)\n",
476                 fname);
477     return GNUNET_SYSERR;
478   }
479   return GNUNET_OK;
480 }
481
482
483 /**
484  * Function called to clean up memory allocated
485  * by a #GNUNET_PQ_ResultConverter.
486  *
487  * @param cls closure
488  * @param rd result data to clean up
489  */
490 static void
491 clean_string (void *cls,
492               void *rd)
493 {
494   char **str = rd;
495
496   if (NULL != *str)
497   {
498     GNUNET_free (*str);
499     *str = NULL;
500   }
501 }
502
503
504 /**
505  * 0-terminated string expected.
506  *
507  * @param name name of the field in the table
508  * @param[out] dst where to store the result, allocated
509  * @return array entry for the result specification to use
510  */
511 struct GNUNET_PQ_ResultSpec
512 GNUNET_PQ_result_spec_string (const char *name,
513                               char **dst)
514 {
515   struct GNUNET_PQ_ResultSpec res =
516     { &extract_string,
517       &clean_string,
518       NULL,
519       (void *) dst, 0, (name), NULL };
520   return res;
521 }
522
523
524 /**
525  * Absolute time expected.
526  *
527  * @param name name of the field in the table
528  * @param[out] at where to store the result
529  * @return array entry for the result specification to use
530  */
531 struct GNUNET_PQ_ResultSpec
532 GNUNET_PQ_result_spec_absolute_time (const char *name,
533                                      struct GNUNET_TIME_Absolute *at)
534 {
535   return GNUNET_PQ_result_spec_uint64 (name,
536                                        &at->abs_value_us);
537 }
538
539
540 /**
541  * Absolute time in network byte order expected.
542  *
543  * @param name name of the field in the table
544  * @param[out] at where to store the result
545  * @return array entry for the result specification to use
546  */
547 struct GNUNET_PQ_ResultSpec
548 GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
549                                          struct GNUNET_TIME_AbsoluteNBO *at)
550 {
551   struct GNUNET_PQ_ResultSpec res =
552     GNUNET_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
553   return res;
554 }
555
556
557 /**
558  * Extract data from a Postgres database @a result at row @a row.
559  *
560  * @param cls closure
561  * @param result where to extract data from
562  * @param int row to extract data from
563  * @param fname name (or prefix) of the fields to extract from
564  * @param[in,out] dst_size where to store size of result, may be NULL
565  * @param[out] dst where to store the result
566  * @return
567  *   #GNUNET_YES if all results could be extracted
568  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
569  */
570 static int
571 extract_uint16 (void *cls,
572                 PGresult *result,
573                 int row,
574                 const char *fname,
575                 size_t *dst_size,
576                 void *dst)
577 {
578   uint16_t *udst = dst;
579   const uint16_t *res;
580   int fnum;
581
582   fnum = PQfnumber (result,
583                     fname);
584   if (fnum < 0)
585   {
586     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
587                 "Field `%s' does not exist in result\n",
588                 fname);
589     return GNUNET_SYSERR;
590   }
591   if (PQgetisnull (result,
592                    row,
593                    fnum))
594     return GNUNET_SYSERR;
595   GNUNET_assert (NULL != dst);
596   if (sizeof (uint16_t) != *dst_size)
597   {
598     GNUNET_break (0);
599     return GNUNET_SYSERR;
600   }
601   res = (uint16_t *) PQgetvalue (result,
602                                  row,
603                                  fnum);
604   *udst = ntohs (*res);
605   return GNUNET_OK;
606 }
607
608
609 /**
610  * uint16_t expected.
611  *
612  * @param name name of the field in the table
613  * @param[out] u16 where to store the result
614  * @return array entry for the result specification to use
615  */
616 struct GNUNET_PQ_ResultSpec
617 GNUNET_PQ_result_spec_uint16 (const char *name,
618                               uint16_t *u16)
619 {
620   struct GNUNET_PQ_ResultSpec res =
621     { &extract_uint16,
622       NULL,
623       NULL,
624       (void *) u16, sizeof (*u16), (name), NULL };
625   return res;
626 }
627
628
629 /**
630  * Extract data from a Postgres database @a result at row @a row.
631  *
632  * @param cls closure
633  * @param result where to extract data from
634  * @param int row to extract data from
635  * @param fname name (or prefix) of the fields to extract from
636  * @param[in,out] dst_size where to store size of result, may be NULL
637  * @param[out] dst where to store the result
638  * @return
639  *   #GNUNET_YES if all results could be extracted
640  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
641  */
642 static int
643 extract_uint32 (void *cls,
644                 PGresult *result,
645                 int row,
646                 const char *fname,
647                 size_t *dst_size,
648                 void *dst)
649 {
650   uint32_t *udst = dst;
651   const uint32_t *res;
652   int fnum;
653
654   fnum = PQfnumber (result,
655                     fname);
656   if (fnum < 0)
657   {
658     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
659                 "Field `%s' does not exist in result\n",
660                 fname);
661     return GNUNET_SYSERR;
662   }
663   if (PQgetisnull (result,
664                    row,
665                    fnum))
666     return GNUNET_SYSERR;
667   GNUNET_assert (NULL != dst);
668   if (sizeof (uint32_t) != *dst_size)
669   {
670     GNUNET_break (0);
671     return GNUNET_SYSERR;
672   }
673   res = (uint32_t *) PQgetvalue (result,
674                                  row,
675                                  fnum);
676   *udst = ntohl (*res);
677   return GNUNET_OK;
678 }
679
680
681 /**
682  * uint32_t expected.
683  *
684  * @param name name of the field in the table
685  * @param[out] u32 where to store the result
686  * @return array entry for the result specification to use
687  */
688 struct GNUNET_PQ_ResultSpec
689 GNUNET_PQ_result_spec_uint32 (const char *name,
690                               uint32_t *u32)
691 {
692   struct GNUNET_PQ_ResultSpec res =
693     { &extract_uint32,
694       NULL,
695       NULL,
696       (void *) u32, sizeof (*u32), (name), NULL };
697   return res;
698 }
699
700
701 /**
702  * Extract data from a Postgres database @a result at row @a row.
703  *
704  * @param cls closure
705  * @param result where to extract data from
706  * @param int row to extract data from
707  * @param fname name (or prefix) of the fields to extract from
708  * @param[in,out] dst_size where to store size of result, may be NULL
709  * @param[out] dst where to store the result
710  * @return
711  *   #GNUNET_YES if all results could be extracted
712  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
713  */
714 static int
715 extract_uint64 (void *cls,
716                 PGresult *result,
717                 int row,
718                 const char *fname,
719                 size_t *dst_size,
720                 void *dst)
721 {
722   uint64_t *udst = dst;
723   const uint64_t *res;
724   int fnum;
725
726   fnum = PQfnumber (result,
727                     fname);
728   if (fnum < 0)
729   {
730     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
731                 "Field `%s' does not exist in result\n",
732                 fname);
733     return GNUNET_SYSERR;
734   }
735   if (PQgetisnull (result,
736                    row,
737                    fnum))
738     return GNUNET_SYSERR;
739   GNUNET_assert (NULL != dst);
740   if (sizeof (uint64_t) != *dst_size)
741   {
742     GNUNET_break (0);
743     return GNUNET_SYSERR;
744   }
745   res = (uint64_t *) PQgetvalue (result,
746                                  row,
747                                  fnum);
748   *udst = GNUNET_ntohll (*res);
749   return GNUNET_OK;
750 }
751
752
753 /**
754  * uint64_t expected.
755  *
756  * @param name name of the field in the table
757  * @param[out] u64 where to store the result
758  * @return array entry for the result specification to use
759  */
760 struct GNUNET_PQ_ResultSpec
761 GNUNET_PQ_result_spec_uint64 (const char *name,
762                               uint64_t *u64)
763 {
764   struct GNUNET_PQ_ResultSpec res =
765     { &extract_uint64,
766       NULL,
767       NULL,
768       (void *) u64, sizeof (*u64), (name), NULL };
769   return res;
770 }
771
772
773 /* end of pq_result_helper.c */