aboutsummaryrefslogtreecommitdiff
path: root/src/pq/pq_result_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq/pq_result_helper.c')
-rw-r--r--src/pq/pq_result_helper.c674
1 files changed, 674 insertions, 0 deletions
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
new file mode 100644
index 000000000..dc5700730
--- /dev/null
+++ b/src/pq/pq_result_helper.c
@@ -0,0 +1,674 @@
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/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 */
33static void
34clean_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_NO if at least one result was NULL
59 * #GNUNET_SYSERR if a result was invalid (non-existing field)
60 */
61static int
62extract_varsize_blob (void *cls,
63 PGresult *result,
64 int row,
65 const char *fname,
66 size_t *dst_size,
67 void *dst)
68{
69 size_t len;
70 const char *res;
71 void *idst;
72 int fnum;
73
74 fnum = PQfnumber (result,
75 fname);
76 if (fnum < 0)
77 {
78 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
79 "Field `%s' does not exist in result\n",
80 fname);
81 return GNUNET_SYSERR;
82 }
83 if (PQgetisnull (result,
84 row,
85 fnum))
86 return GNUNET_NO;
87
88 /* if a field is null, continue but
89 * remember that we now return a different result */
90 len = PQgetlength (result,
91 row,
92 fnum);
93 res = PQgetvalue (result,
94 row,
95 fnum);
96 GNUNET_assert (NULL != res);
97 *dst_size = len;
98 idst = GNUNET_malloc (len);
99 *((void **) dst) = idst;
100 memcpy (idst,
101 res,
102 len);
103 return GNUNET_OK;
104}
105
106
107/**
108 * Variable-size result expected.
109 *
110 * @param name name of the field in the table
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 entry for the result specification to use
114 */
115struct GNUNET_PQ_ResultSpec
116GNUNET_PQ_result_spec_variable_size (const char *name,
117 void **dst,
118 size_t *sptr)
119{
120 struct GNUNET_PQ_ResultSpec res =
121 { &extract_varsize_blob,
122 &clean_varsize_blob, NULL,
123 (void *) (dst), 0, name, sptr };
124 return res;
125}
126
127
128/**
129 * Extract data from a Postgres database @a result at row @a row.
130 *
131 * @param cls closure
132 * @param result where to extract data from
133 * @param int row to extract data from
134 * @param fname name (or prefix) of the fields to extract from
135 * @param[in] dst_size desired size, never NULL
136 * @param[out] dst where to store the result
137 * @return
138 * #GNUNET_YES if all results could be extracted
139 * #GNUNET_NO if at least one result was NULL
140 * #GNUNET_SYSERR if a result was invalid (non-existing field)
141 */
142static int
143extract_fixed_blob (void *cls,
144 PGresult *result,
145 int row,
146 const char *fname,
147 size_t *dst_size,
148 void *dst)
149{
150 size_t len;
151 const char *res;
152 int fnum;
153
154 fnum = PQfnumber (result,
155 fname);
156 if (fnum < 0)
157 {
158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
159 "Field `%s' does not exist in result\n",
160 fname);
161 return GNUNET_SYSERR;
162 }
163 if (PQgetisnull (result,
164 row,
165 fnum))
166 return GNUNET_NO;
167
168 /* if a field is null, continue but
169 * remember that we now return a different result */
170 len = PQgetlength (result,
171 row,
172 fnum);
173 if (*dst_size != len)
174 {
175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176 "Field `%s' has wrong size (got %u, expected %u)\n",
177 fname,
178 (unsigned int) len,
179 (unsigned int) *dst_size);
180 return GNUNET_SYSERR;
181 }
182 res = PQgetvalue (result,
183 row,
184 fnum);
185 GNUNET_assert (NULL != res);
186 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 */
201struct GNUNET_PQ_ResultSpec
202GNUNET_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_NO if at least one result was NULL
226 * #GNUNET_SYSERR if a result was invalid (non-existing field)
227 */
228static int
229extract_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_rsa_PublicKey **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_NO;
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 */
284static void
285clean_rsa_public_key (void *cls,
286 void *rd)
287{
288 struct GNUNET_CRYPTO_rsa_PublicKey **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 */
305struct GNUNET_PQ_ResultSpec
306GNUNET_PQ_result_spec_rsa_public_key (const char *name,
307 struct GNUNET_CRYPTO_rsa_PublicKey **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_NO if at least one result was NULL
330 * #GNUNET_SYSERR if a result was invalid (non-existing field)
331 */
332static int
333extract_rsa_signature (void *cls,
334 PGresult *result,
335 int row,
336 const char *fname,
337 size_t *dst_size,
338 void *dst)
339{
340 struct GNUNET_CRYPTO_rsa_Signature **sig = dst;
341 size_t len;
342 const char *res;
343 int fnum;
344
345 *sig = NULL;
346 fnum = PQfnumber (result,
347 fname);
348 if (fnum < 0)
349 {
350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
351 "Field `%s' does not exist in result\n",
352 fname);
353 return GNUNET_SYSERR;
354 }
355 if (PQgetisnull (result,
356 row,
357 fnum))
358 return GNUNET_NO;
359
360 /* if a field is null, continue but
361 * remember that we now return a different result */
362 len = PQgetlength (result,
363 row,
364 fnum);
365 res = PQgetvalue (result,
366 row,
367 fnum);
368 *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
369 len);
370 if (NULL == *sig)
371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
373 "Field `%s' contains bogus value (fails to decode)\n",
374 fname);
375 return GNUNET_SYSERR;
376 }
377 return GNUNET_OK;
378}
379
380
381/**
382 * Function called to clean up memory allocated
383 * by a #GNUNET_PQ_ResultConverter.
384 *
385 * @param cls closure
386 * @param rd result data to clean up
387 */
388static void
389clean_rsa_signature (void *cls,
390 void *rd)
391{
392 struct GNUNET_CRYPTO_rsa_Signature **sig = rd;
393
394 if (NULL != *sig)
395 {
396 GNUNET_CRYPTO_rsa_signature_free (*sig);
397 *sig = NULL;
398 }
399}
400
401
402/**
403 * RSA signature expected.
404 *
405 * @param name name of the field in the table
406 * @param[out] sig where to store the result;
407 * @return array entry for the result specification to use
408 */
409struct GNUNET_PQ_ResultSpec
410GNUNET_PQ_result_spec_rsa_signature (const char *name,
411 struct GNUNET_CRYPTO_rsa_Signature **sig)
412{
413 struct GNUNET_PQ_ResultSpec res =
414 { &extract_rsa_signature,
415 &clean_rsa_signature,
416 NULL,
417 (void *) sig, 0, (name), NULL };
418 return res;
419}
420
421
422/**
423 * Absolute time expected.
424 *
425 * @param name name of the field in the table
426 * @param[out] at where to store the result
427 * @return array entry for the result specification to use
428 */
429struct GNUNET_PQ_ResultSpec
430GNUNET_PQ_result_spec_absolute_time (const char *name,
431 struct GNUNET_TIME_Absolute *at)
432{
433 return GNUNET_PQ_result_spec_uint64 (name,
434 &at->abs_value_us);
435}
436
437
438/**
439 * Absolute time in network byte order expected.
440 *
441 * @param name name of the field in the table
442 * @param[out] at where to store the result
443 * @return array entry for the result specification to use
444 */
445struct GNUNET_PQ_ResultSpec
446GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
447 struct GNUNET_TIME_AbsoluteNBO *at)
448{
449 struct GNUNET_PQ_ResultSpec res =
450 GNUNET_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
451 return res;
452}
453
454
455/**
456 * Extract data from a Postgres database @a result at row @a row.
457 *
458 * @param cls closure
459 * @param result where to extract data from
460 * @param int row to extract data from
461 * @param fname name (or prefix) of the fields to extract from
462 * @param[in,out] dst_size where to store size of result, may be NULL
463 * @param[out] dst where to store the result
464 * @return
465 * #GNUNET_YES if all results could be extracted
466 * #GNUNET_NO if at least one result was NULL
467 * #GNUNET_SYSERR if a result was invalid (non-existing field)
468 */
469static int
470extract_uint16 (void *cls,
471 PGresult *result,
472 int row,
473 const char *fname,
474 size_t *dst_size,
475 void *dst)
476{
477 uint16_t *udst = dst;
478 const uint16_t *res;
479 int fnum;
480
481 fnum = PQfnumber (result,
482 fname);
483 if (fnum < 0)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 "Field `%s' does not exist in result\n",
487 fname);
488 return GNUNET_SYSERR;
489 }
490 if (PQgetisnull (result,
491 row,
492 fnum))
493 return GNUNET_NO;
494 GNUNET_assert (NULL != dst);
495 if (sizeof (uint16_t) != *dst_size)
496 {
497 GNUNET_break (0);
498 return GNUNET_SYSERR;
499 }
500 res = (uint16_t *) PQgetvalue (result,
501 row,
502 fnum);
503 *udst = ntohs (*res);
504 return GNUNET_OK;
505}
506
507
508/**
509 * uint16_t expected.
510 *
511 * @param name name of the field in the table
512 * @param[out] u16 where to store the result
513 * @return array entry for the result specification to use
514 */
515struct GNUNET_PQ_ResultSpec
516GNUNET_PQ_result_spec_uint16 (const char *name,
517 uint16_t *u16)
518{
519 struct GNUNET_PQ_ResultSpec res =
520 { &extract_uint16,
521 NULL,
522 NULL,
523 (void *) u16, sizeof (*u16), (name), NULL };
524 return res;
525}
526
527
528/**
529 * Extract data from a Postgres database @a result at row @a row.
530 *
531 * @param cls closure
532 * @param result where to extract data from
533 * @param int row to extract data from
534 * @param fname name (or prefix) of the fields to extract from
535 * @param[in,out] dst_size where to store size of result, may be NULL
536 * @param[out] dst where to store the result
537 * @return
538 * #GNUNET_YES if all results could be extracted
539 * #GNUNET_NO if at least one result was NULL
540 * #GNUNET_SYSERR if a result was invalid (non-existing field)
541 */
542static int
543extract_uint32 (void *cls,
544 PGresult *result,
545 int row,
546 const char *fname,
547 size_t *dst_size,
548 void *dst)
549{
550 uint32_t *udst = dst;
551 const uint32_t *res;
552 int fnum;
553
554 fnum = PQfnumber (result,
555 fname);
556 if (fnum < 0)
557 {
558 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
559 "Field `%s' does not exist in result\n",
560 fname);
561 return GNUNET_SYSERR;
562 }
563 if (PQgetisnull (result,
564 row,
565 fnum))
566 return GNUNET_NO;
567 GNUNET_assert (NULL != dst);
568 if (sizeof (uint32_t) != *dst_size)
569 {
570 GNUNET_break (0);
571 return GNUNET_SYSERR;
572 }
573 res = (uint32_t *) PQgetvalue (result,
574 row,
575 fnum);
576 *udst = ntohl (*res);
577 return GNUNET_OK;
578}
579
580
581/**
582 * uint32_t expected.
583 *
584 * @param name name of the field in the table
585 * @param[out] u32 where to store the result
586 * @return array entry for the result specification to use
587 */
588struct GNUNET_PQ_ResultSpec
589GNUNET_PQ_result_spec_uint32 (const char *name,
590 uint32_t *u32)
591{
592 struct GNUNET_PQ_ResultSpec res =
593 { &extract_uint32,
594 NULL,
595 NULL,
596 (void *) u32, sizeof (*u32), (name), NULL };
597 return res;
598}
599
600
601/**
602 * Extract data from a Postgres database @a result at row @a row.
603 *
604 * @param cls closure
605 * @param result where to extract data from
606 * @param int row to extract data from
607 * @param fname name (or prefix) of the fields to extract from
608 * @param[in,out] dst_size where to store size of result, may be NULL
609 * @param[out] dst where to store the result
610 * @return
611 * #GNUNET_YES if all results could be extracted
612 * #GNUNET_NO if at least one result was NULL
613 * #GNUNET_SYSERR if a result was invalid (non-existing field)
614 */
615static int
616extract_uint64 (void *cls,
617 PGresult *result,
618 int row,
619 const char *fname,
620 size_t *dst_size,
621 void *dst)
622{
623 uint64_t *udst = dst;
624 const uint64_t *res;
625 int fnum;
626
627 fnum = PQfnumber (result,
628 fname);
629 if (fnum < 0)
630 {
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
632 "Field `%s' does not exist in result\n",
633 fname);
634 return GNUNET_SYSERR;
635 }
636 if (PQgetisnull (result,
637 row,
638 fnum))
639 return GNUNET_NO;
640 GNUNET_assert (NULL != dst);
641 if (sizeof (uint64_t) != *dst_size)
642 {
643 GNUNET_break (0);
644 return GNUNET_SYSERR;
645 }
646 res = (uint64_t *) PQgetvalue (result,
647 row,
648 fnum);
649 *udst = GNUNET_ntohll (*res);
650 return GNUNET_OK;
651}
652
653
654/**
655 * uint64_t expected.
656 *
657 * @param name name of the field in the table
658 * @param[out] u64 where to store the result
659 * @return array entry for the result specification to use
660 */
661struct GNUNET_PQ_ResultSpec
662GNUNET_PQ_result_spec_uint64 (const char *name,
663 uint64_t *u64)
664{
665 struct GNUNET_PQ_ResultSpec res =
666 { &extract_uint64,
667 NULL,
668 NULL,
669 (void *) u64, sizeof (*u64), (name), NULL };
670 return res;
671}
672
673
674/* end of pq_result_helper.c */