This file is part of GNUnet.
Copyright (C) 2006-2013 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Affero General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
*
* @author Christian Grothoff
* @author Nils Durner
+ * @author Martin Schanzenbach
*
* @defgroup logging Logging
* @see [Documentation](https://gnunet.org/logging)
#endif
#endif
+/**
+ * wrap va_arg for enums
+ */
+#define GNUNET_VA_ARG_ENUM(va,X) ((enum X) va_arg (va, int))
+
+
/**
* @ingroup logging
* define #GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source
#endif
+/**
+ * Macro used to avoid using 0 for the length of a variable-size
+ * array (Non-Zero-Length).
+ *
+ * Basically, C standard says that "int[n] x;" is undefined if n=0.
+ * This was supposed to prevent issues with pointer aliasing.
+ * However, C compilers may conclude that n!=0 as n=0 would be
+ * undefined, and then optimize under the assumption n!=0, which
+ * could cause actual issues. Hence, when initializing an array
+ * on the stack with a variable-length that might be zero, write
+ * "int[GNUNET_NZL(n)] x;" instead of "int[n] x".
+ */
+#define GNUNET_NZL(l) GNUNET_MAX(1,l)
/**
GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * @brief A 512-bit hashcode. These are the default length for GNUnet, using SHA-512.
+ */
+struct GNUNET_HashCode
+{
+ uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */
+};
+
+
+
+/**
+ * @brief A 256-bit hashcode. Used under special conditions, like when space
+ * is critical and security is not impacted by it.
+ */
+struct GNUNET_ShortHashCode
+{
+ uint32_t bits[256 / 8 / sizeof (uint32_t)]; /* = 8 */
+};
+
+
+
/**
* Header for all communications.
*/
* @return string
*/
const char *
-GNUNET_h2s (const struct GNUNET_HashCode * hc);
+GNUNET_h2s (const struct GNUNET_HashCode *hc);
+
+
+/**
+ * @ingroup logging
+ * Convert a hash value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant! Identical to #GNUNET_h2s(), except that another
+ * buffer is used so both #GNUNET_h2s() and #GNUNET_h2s2() can be
+ * used within the same log statement.
+ *
+ * @param hc the hash code
+ * @return string
+ */
+const char *
+GNUNET_h2s2 (const struct GNUNET_HashCode *hc);
/**
* @return string
*/
const char *
-GNUNET_h2s_full (const struct GNUNET_HashCode * hc);
+GNUNET_h2s_full (const struct GNUNET_HashCode *hc);
+
+
+/**
+ * Public key. Details in gnunet_util_crypto.h.
+ */
+struct GNUNET_CRYPTO_EddsaPublicKey;
+
+
+/**
+ * Public key. Details in gnunet_util_crypto.h.
+ */
+struct GNUNET_CRYPTO_EcdhePublicKey;
+
+
+/**
+ * @ingroup logging
+ * Convert a public key value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param hc the hash code
+ * @return string
+ */
+const char *
+GNUNET_p2s (const struct GNUNET_CRYPTO_EddsaPublicKey *p);
+
+
+/**
+ * @ingroup logging
+ * Convert a public key value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param hc the hash code
+ * @return string
+ */
+const char *
+GNUNET_p2s2 (const struct GNUNET_CRYPTO_EddsaPublicKey *p);
+
+
+/**
+ * @ingroup logging
+ * Convert a public key value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param hc the hash code
+ * @return string
+ */
+const char *
+GNUNET_e2s (const struct GNUNET_CRYPTO_EcdhePublicKey *p);
+
+
+/**
+ * @ingroup logging
+ * Convert a public key value to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param hc the hash code
+ * @return string
+ */
+const char *
+GNUNET_e2s2 (const struct GNUNET_CRYPTO_EcdhePublicKey *p);
/**
GNUNET_i2s (const struct GNUNET_PeerIdentity *pid);
+/**
+ * @ingroup logging
+ * Convert a peer identity to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant! Identical to #GNUNET_i2s(), except that another
+ * buffer is used so both #GNUNET_i2s() and #GNUNET_i2s2() can be
+ * used within the same log statement.
+ *
+ * @param pid the peer identity
+ * @return string form of the pid; will be overwritten by next
+ * call to #GNUNET_i2s().
+ */
+const char *
+GNUNET_i2s2 (const struct GNUNET_PeerIdentity *pid);
+
+
/**
* @ingroup logging
* Convert a peer identity to a string (for printing debug messages).
* @ingroup logging
* Use this for fatal errors that cannot be handled
*/
-#define GNUNET_assert(cond) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert(cond) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d. Aborting.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
/**
* @ingroup logging
* Use this for fatal errors that cannot be handled
*/
-#define GNUNET_assert_at(cond, f, l) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), f, l); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert_at(cond, f, l) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d. Aborting.\n"), f, l); GNUNET_abort_(); } } while(0)
/**
* @param cond Condition to evaluate
* @param comp Component string to use for logging
*/
-#define GNUNET_assert_from(cond, comp) do { if (! (cond)) { GNUNET_log_from(GNUNET_ERROR_TYPE_ERROR, comp, _("Assertion failed at %s:%d.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert_from(cond, comp) do { if (! (cond)) { GNUNET_log_from(GNUNET_ERROR_TYPE_ERROR, comp, _("Assertion failed at %s:%d. Aborting.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
/**
*/
#define GNUNET_new(type) (type *) GNUNET_malloc (sizeof (type))
+
+/**
+ * Compare memory in @a a and @a b, where both must be of
+ * the same pointer type.
+ */
+#define GNUNET_memcmp(a,b) ({ \
+ const typeof(*b) * _a = (a); \
+ const typeof(*a) * _b = (b); \
+ memcmp(_a, \
+ _b, \
+ sizeof (*a)); })
+
+
+/**
+ * Check that memory in @a a is all zeros. @a a must be a pointer.
+ *
+ * @param a pointer to a struct which should be tested for the
+ * entire memory being zero'ed out.
+ */
+#define GNUNET_is_zero(a) ({ \
+ static const typeof(*a) _z; \
+ memcmp((a), \
+ &_z, \
+ sizeof (_z)); })
+
+
/**
* Call memcpy() but check for @a n being 0 first. In the latter
* case, it is now safe to pass NULL for @a src or @a dst.
* arr is important since size is the number of elements and
* not the size in bytes
* @param size the number of elements in the existing vector (number
- * of elements to copy over)
+ * of elements to copy over), will be updated with the new
+ * array size
* @param tsize the target size for the resulting vector, use 0 to
* free the vector (then, arr will be NULL afterwards).
*/
-#define GNUNET_array_grow(arr,size,tsize) GNUNET_xgrow_((void**)&arr, sizeof(arr[0]), &size, tsize, __FILE__, __LINE__)
+#define GNUNET_array_grow(arr,size,tsize) GNUNET_xgrow_((void**)&(arr), sizeof((arr)[0]), &size, tsize, __FILE__, __LINE__)
/**
* @ingroup memory
- * Append an element to a list (growing the
- * list by one).
+ * Append an element to a list (growing the list by one).
+ *
+ * @param arr base-pointer of the vector, may be NULL if size is 0;
+ * will be updated to reflect the new address. The TYPE of
+ * arr is important since size is the number of elements and
+ * not the size in bytes
+ * @param size the number of elements in the existing vector (number
+ * of elements to copy over), will be updated with the new
+ * array size
+ * @param element the element that will be appended to the array
*/
-#define GNUNET_array_append(arr,size,element) do { GNUNET_array_grow(arr,size,size+1); arr[size-1] = element; } while(0)
+#define GNUNET_array_append(arr,size,element) do { GNUNET_array_grow(arr,size,size+1); (arr)[size-1] = element; } while(0)
/**
* @ingroup memory