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