From: Christian Grothoff Date: Tue, 28 Feb 2017 03:07:26 +0000 (+0100) Subject: completing sq_result_helper X-Git-Tag: taler-0.2.1~8^2~26 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=67935d7aa1090eed2eb00212741dcc4d13c0bb40;p=oweals%2Fgnunet.git completing sq_result_helper --- diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h index 4484c2851..c03f83e07 100644 --- a/src/include/gnunet_sq_lib.h +++ b/src/include/gnunet_sq_lib.h @@ -252,7 +252,9 @@ struct GNUNET_SQ_ResultSpec size_t dst_size; /** - * Where to store actual size of the result. + * Where to store actual size of the result. If left at + * NULL, will be made to point to @e dst_size before + * @a conv is called. */ size_t *result_size; diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index 180c5fc18..c5c8e56b9 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -77,9 +77,7 @@ extract_varsize_blob (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -156,9 +154,7 @@ extract_fixed_blob (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -173,11 +169,7 @@ extract_fixed_blob (void *cls, fnum); if (*dst_size != len) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' has wrong size (got %u, expected %u)\n", - fname, - (unsigned int) len, - (unsigned int) *dst_size); + GNUNET_break (0); return GNUNET_SYSERR; } res = PQgetvalue (result, @@ -243,9 +235,7 @@ extract_rsa_public_key (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -265,9 +255,7 @@ extract_rsa_public_key (void *cls, len); if (NULL == *pk) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' contains bogus value (fails to decode)\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; @@ -346,9 +334,7 @@ extract_rsa_signature (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -368,9 +354,7 @@ extract_rsa_signature (void *cls, len); if (NULL == *sig) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' contains bogus value (fails to decode)\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; @@ -449,9 +433,7 @@ extract_string (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -471,9 +453,7 @@ extract_string (void *cls, len); if (NULL == *str) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' contains bogus value (fails to decode)\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; @@ -583,9 +563,7 @@ extract_uint16 (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -655,9 +633,7 @@ extract_uint32 (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, @@ -727,9 +703,7 @@ extract_uint64 (void *cls, fname); if (fnum < 0) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); + GNUNET_break (0); return GNUNET_SYSERR; } if (PQgetisnull (result, diff --git a/src/sq/sq.c b/src/sq/sq.c index 47fcaf24e..dc4416761 100644 --- a/src/sq/sq.c +++ b/src/sq/sq.c @@ -75,6 +75,8 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result, for (unsigned int i=0;NULL != rs[i].conv; i++) { + if (NULL == rs[i].result_size) + rs[i].result_size = &rs[i].dst_size; if (GNUNET_OK != rs[i].conv (rs[i].cls, result, diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c index 36ce53317..9ac2e2533 100644 --- a/src/sq/sq_result_helper.c +++ b/src/sq/sq_result_helper.c @@ -24,26 +24,75 @@ /** - * Extract fixed-sized binary data from a Postgres database @a result at row @a row. + * Extract variable-sized binary data from a Postgres database @a result at row @a row. * * @param cls closure * @param result where to extract data from - * @param row row to extract data from * @param column column to extract data from * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result + * @param[out] dst where to store the result (actually a `void **`) * @return * #GNUNET_YES if all results could be extracted * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) */ static int -extract_fixed_blob (void *cls, - sqlite3_stmt *result, - int row, - unsigned int column, - size_t *dst_size, - void *dst) +extract_var_blob (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) { + int have; + const void *ret; + void **rdst = (void **) dst; + + if (SQLITE_BLOB != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* sqlite manual says to invoke 'sqlite3_column_blob()' + before calling sqlite3_column_bytes() */ + ret = sqlite3_column_blob (result, + column); + have = sqlite3_column_bytes (result, + column); + if (have < 0) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *dst_size = have; + if (0 == have) + { + *rdst = NULL; + return GNUNET_OK; + } + *rdst = GNUNET_malloc (have); + GNUNET_memcpy (*rdst, + ret, + have); + return GNUNET_OK; +} + + +/** + * Cleanup memory allocated by #extract_var_blob(). + * + * @param cls pointer to pointer of allocation + */ +static void +clean_var_blob (void *cls) +{ + void **dptr = (void **) cls; + + if (NULL != *dptr) + { + GNUNET_free (*dptr); + *dptr = NULL; + } } @@ -58,6 +107,62 @@ struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_variable_size (void **dst, size_t *sptr) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_var_blob, + .cleaner = &clean_var_blob, + .cls = dst, + .result_size = sptr, + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract fixed-sized binary data from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_fixed_blob (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + int have; + const void *ret; + + if (SQLITE_BLOB != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* sqlite manual says to invoke 'sqlite3_column_blob()' + before calling sqlite3_column_bytes() */ + ret = sqlite3_column_blob (result, + column); + have = sqlite3_column_bytes (result, + column); + if (*dst_size != have) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + GNUNET_memcpy (dst, + ret, + have); + return GNUNET_OK; } @@ -72,6 +177,76 @@ struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_fixed_size (void *dst, size_t dst_size) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_fixed_blob, + .dst = dst, + .dst_size = dst_size, + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract fixed-sized binary data from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_utf8_string (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + const char *text; + char **rdst = dst; + + if (SQLITE_TEXT != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* sqlite manual guarantees that 'sqlite3_column_text()' + is 0-terminated */ + text = (const char *) sqlite3_column_text (result, + column); + if (NULL == text) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *dst_size = strlen (text) + 1; + *rdst = GNUNET_strdup (text); + return GNUNET_OK; +} + + +/** + * Cleanup memory allocated by #extract_var_blob(). + * + * @param cls pointer to pointer of allocation + */ +static void +clean_utf8_string (void *cls) +{ + char **dptr = (char **) cls; + + if (NULL != *dptr) + { + GNUNET_free (*dptr); + *dptr = NULL; + } } @@ -84,6 +259,87 @@ GNUNET_SQ_result_spec_fixed_size (void *dst, struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_string (char **dst) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_utf8_string, + .cleaner = &clean_utf8_string, + .cls = dst, + .dst = dst, + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract data from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_rsa_pub (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + struct GNUNET_CRYPTO_RsaPublicKey **pk = dst; + int have; + const void *ret; + + if (SQLITE_BLOB != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* sqlite manual says to invoke 'sqlite3_column_blob()' + before calling sqlite3_column_bytes() */ + ret = sqlite3_column_blob (result, + column); + have = sqlite3_column_bytes (result, + column); + if (have < 0) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret, + have); + if (NULL == *pk) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Function called to clean up memory allocated + * by a #GNUNET_PQ_ResultConverter. + * + * @param cls closure + */ +static void +clean_rsa_pub (void *cls) +{ + struct GNUNET_CRYPTO_RsaPublicKey **pk = cls; + + if (NULL != *pk) + { + GNUNET_CRYPTO_rsa_public_key_free (*pk); + *pk = NULL; + } } @@ -96,6 +352,87 @@ GNUNET_SQ_result_spec_string (char **dst) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_rsa_pub, + .cleaner = &clean_rsa_pub, + .dst = rsa, + .cls = rsa, + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract data from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_rsa_sig (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + struct GNUNET_CRYPTO_RsaSignature **sig = dst; + int have; + const void *ret; + + if (SQLITE_BLOB != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* sqlite manual says to invoke 'sqlite3_column_blob()' + before calling sqlite3_column_bytes() */ + ret = sqlite3_column_blob (result, + column); + have = sqlite3_column_bytes (result, + column); + if (have < 0) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + *sig = GNUNET_CRYPTO_rsa_signature_decode (ret, + have); + if (NULL == *sig) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Function called to clean up memory allocated + * by a #GNUNET_PQ_ResultConverter. + * + * @param cls result data to clean up + */ +static void +clean_rsa_sig (void *cls) +{ + struct GNUNET_CRYPTO_RsaSignature **sig = cls; + + if (NULL != *sig) + { + GNUNET_CRYPTO_rsa_signature_free (*sig); + *sig = NULL; + } } @@ -108,6 +445,15 @@ GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_rsa_sig, + .cleaner = &clean_rsa_sig, + .dst = sig, + .cls = sig, + .num_params = 1 + }; + + return rs; } @@ -120,6 +466,44 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) { + return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us); +} + + +/** + * Extract absolute time value in NBO from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_abs_time_nbo (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + struct GNUNET_TIME_AbsoluteNBO *u = dst; + struct GNUNET_TIME_Absolute t; + + GNUNET_assert (sizeof (uint64_t) == *dst_size); + if (SQLITE_INTEGER != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, + column); + *u = GNUNET_TIME_absolute_hton (t); + return GNUNET_OK; } @@ -132,6 +516,56 @@ GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_abs_time_nbo, + .dst = at, + .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO), + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract 16-bit integer from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_uint16 (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + uint64_t v; + uint32_t *u = dst; + + GNUNET_assert (sizeof (uint16_t) == *dst_size); + if (SQLITE_INTEGER != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + v = (uint64_t) sqlite3_column_int64 (result, + column); + if (v > UINT16_MAX) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *u = (uint16_t) v; + return GNUNET_OK; } @@ -144,6 +578,56 @@ GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint16 (uint16_t *u16) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_uint16, + .dst = u16, + .dst_size = sizeof (uint16_t), + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract 32-bit integer from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_uint32 (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + uint64_t v; + uint32_t *u = dst; + + GNUNET_assert (sizeof (uint32_t) == *dst_size); + if (SQLITE_INTEGER != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + v = (uint64_t) sqlite3_column_int64 (result, + column); + if (v > UINT32_MAX) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *u = (uint32_t) v; + return GNUNET_OK; } @@ -156,6 +640,49 @@ GNUNET_SQ_result_spec_uint16 (uint16_t *u16) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint32 (uint32_t *u32) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_uint32, + .dst = u32, + .dst_size = sizeof (uint32_t), + .num_params = 1 + }; + + return rs; +} + + +/** + * Extract 64-bit integer from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_uint64 (void *cls, + sqlite3_stmt *result, + unsigned int column, + size_t *dst_size, + void *dst) +{ + uint64_t *u = dst; + + GNUNET_assert (sizeof (uint64_t) == *dst_size); + if (SQLITE_INTEGER != + sqlite3_column_type (result, + column)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *u = (uint64_t) sqlite3_column_int64 (result, + column); + return GNUNET_OK; } @@ -168,6 +695,14 @@ GNUNET_SQ_result_spec_uint32 (uint32_t *u32) struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint64 (uint64_t *u64) { + struct GNUNET_SQ_ResultSpec rs = { + .conv = &extract_uint64, + .dst = u64, + .dst_size = sizeof (uint64_t), + .num_params = 1 + }; + + return rs; }