RECLAIM/OIDC: code cleanup
[oweals/gnunet.git] / src / include / gnunet_common.h
index 4e882c1135bd4d9f002110db6b753cb41a3ce999..2c40aef797e348700a4b92699726843707ffe043 100644 (file)
@@ -1,21 +1,21 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2006-2013 Christian Grothoff (and other contributing authors)
+     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., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, 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)
+ *
  * @defgroup memory Memory management
  */
 #ifndef GNUNET_COMMON_H
@@ -64,7 +67,7 @@ extern "C"
 /**
  * Version of the API (for entire gnunetutil.so library).
  */
-#define GNUNET_UTIL_VERSION 0x000A0100
+#define GNUNET_UTIL_VERSION 0x000A0102
 
 
 /**
@@ -111,6 +114,12 @@ extern "C"
 #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
@@ -158,6 +167,19 @@ extern "C"
 #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)
 
 
 /**
@@ -234,6 +256,27 @@ extern "C"
 
 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.
  */
@@ -330,10 +373,14 @@ enum GNUNET_ErrorType
   GNUNET_ERROR_TYPE_NONE = 0,
   GNUNET_ERROR_TYPE_ERROR = 1,
   GNUNET_ERROR_TYPE_WARNING = 2,
-  GNUNET_ERROR_TYPE_INFO = 4,
-  GNUNET_ERROR_TYPE_DEBUG = 8,
-  GNUNET_ERROR_TYPE_INVALID = 16,
-  GNUNET_ERROR_TYPE_BULK = 32
+  /* UX: We need a message type that is output by
+   * default without looking like there is a problem.
+   */
+  GNUNET_ERROR_TYPE_MESSAGE = 4,
+  GNUNET_ERROR_TYPE_INFO = 8,
+  GNUNET_ERROR_TYPE_DEBUG = 16,
+  GNUNET_ERROR_TYPE_INVALID = 32,
+  GNUNET_ERROR_TYPE_BULK = 64
 };
 
 
@@ -384,7 +431,8 @@ GNUNET_get_log_call_status (int caller_level,
  * @param ... arguments for format string
  */
 void
-GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...);
+GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
+  __attribute__ ((format (printf, 2, 3)));
 
 /* from glib */
 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
@@ -524,7 +572,10 @@ GNUNET_log_setup (const char *comp,
 
 /**
  * @ingroup logging
- * Add a custom logger.
+ * Add a custom logger.  Note that installing any custom logger
+ * will disable the standard logger.  When multiple custom loggers
+ * are installed, all will be called.  The standard logger will
+ * only be used if no custom loggers are present.
  *
  * @param logger log function
  * @param logger_cls closure for @a logger
@@ -546,6 +597,19 @@ GNUNET_logger_remove (GNUNET_Logger logger,
                       void *logger_cls);
 
 
+/**
+ * @ingroup logging
+ * Convert a short 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!
+ *
+ * @param shc the hash code
+ * @return string
+ */
+const char *
+GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc);
+
+
 /**
  * @ingroup logging
  * Convert a hash value to a string (for printing debug messages).
@@ -556,7 +620,22 @@ GNUNET_logger_remove (GNUNET_Logger logger,
  * @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);
 
 
 /**
@@ -570,7 +649,71 @@ GNUNET_h2s (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);
 
 
 /**
@@ -587,6 +730,22 @@ const char *
 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).
@@ -632,14 +791,24 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * @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)
+
+
+/**
+ * @ingroup logging
+ * Use this for fatal errors that cannot be handled
+ *
+ * @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. Aborting.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
 
 
 /**
@@ -686,7 +855,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * a failure of the command 'cmd' with the message given
  * by strerror(errno).
  */
-#define GNUNET_log_strerror_file(level, cmd, filename) do { GNUNET_log(level, _("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename,__FILE__, __LINE__, STRERROR(errno)); } while(0)
+#define GNUNET_log_strerror_file(level, cmd, filename) do { GNUNET_log(level, _("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename, __FILE__, __LINE__, STRERROR(errno)); } while(0)
 
 
 /**
@@ -727,9 +896,9 @@ GNUNET_ntohll (uint64_t n);
  * Convert double to network byte order.
  *
  * @param d
- *        The value in network byte order.
+ *        The value in host byte order.
  *
- * @return The same value in host byte order.
+ * @return The same value in network byte order.
  */
 double
 GNUNET_hton_double (double d);
@@ -747,106 +916,95 @@ double
 GNUNET_ntoh_double (double d);
 
 
-/**
- * Convert signed 64-bit integer to network byte order.
- *
- * @param n
- *        The value in host byte order.
- *
- * @return The same value in network byte order.
- */
-uint64_t
-GNUNET_htonll_signed (int64_t n);
-
+/* ************************* allocation functions ****************** */
 
 /**
- * Convert signed 64-bit integer to host byte order.
- *
- * @param n
- *        The value in network byte order.
- *
- * @return The same value in host byte order.
+ * @ingroup memory
+ * Maximum allocation with GNUNET_malloc macro.
  */
-int64_t
-GNUNET_ntohll_signed (uint64_t n);
-
+#define GNUNET_MAX_MALLOC_CHECKED (1024 * 1024 * 40)
 
 /**
- * Convert signed 32-bit integer to network byte order.
- *
- * @param n
- *        The value in host byte order.
+ * @ingroup memory
+ * Allocate a struct or union of the given @a type.
+ * Wrapper around #GNUNET_malloc that returns a pointer
+ * to the newly created object of the correct type.
  *
- * @return The same value in network byte order.
+ * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-uint32_t
-GNUNET_htonl_signed (int32_t n);
+#define GNUNET_new(type) (type *) GNUNET_malloc (sizeof (type))
 
 
 /**
- * Convert signed 32-bit integer to host byte order.
- *
- * @param n
- *        The value in network byte order.
- *
- * @return The same value in host byte order.
+ * Compare memory in @a a and @a b, where both must be of
+ * the same pointer type.
  */
-int32_t
-GNUNET_ntohl_signed (uint32_t n);
+#define GNUNET_memcmp(a,b) ({ \
+  const typeof(*b) * _a = (a); \
+  const typeof(*a) * _b = (b); \
+  memcmp(_a, \
+         _b, \
+         sizeof (*a)); })
 
 
 /**
- * Convert signed 16-bit integer to network byte order.
+ * Check that memory in @a a is all zeros. @a a must be a pointer.
  *
- * @param n
- *        The value in host byte order.
- *
- * @return The same value in network byte order.
+ * @param a pointer to a struct which should be tested for the
+ *          entire memory being zero'ed out.
  */
-uint16_t
-GNUNET_htons_signed (int16_t n);
+#define GNUNET_is_zero(a) ({ \
+  static const typeof(*a) _z;      \
+  memcmp((a), \
+         &_z, \
+         sizeof (_z)); })
 
 
 /**
- * Convert signed 16-bit integer to host byte order.
+ * 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.
+ * Unlike traditional memcpy(), returns nothing.
  *
- * @param n
- *        The value in network byte order.
- *
- * @return The same value in host byte order.
+ * @param dst destination of the copy, may be NULL if @a n is zero
+ * @param src source of the copy, may be NULL if @a n is zero
+ * @param n number of bytes to copy
  */
-int16_t
-GNUNET_ntohs_signed (uint16_t n);
+#define GNUNET_memcpy(dst,src,n) do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0)
 
 
-/* ************************* allocation functions ****************** */
-
 /**
  * @ingroup memory
- * Maximum allocation with GNUNET_malloc macro.
+ * Allocate a size @a n array with structs or unions of the given @a type.
+ * Wrapper around #GNUNET_malloc that returns a pointer
+ * to the newly created objects of the correct type.
+ *
+ * @param n number of elements in the array
+ * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-#define GNUNET_MAX_MALLOC_CHECKED (1024 * 1024 * 40)
+#define GNUNET_new_array(n, type) (type *) GNUNET_malloc ((n) * sizeof (type))
 
 /**
  * @ingroup memory
- * Allocate a struct or union of the given @a type.
- * Wrapper around #GNUNET_malloc that returns a pointer
- * to the newly created object of the correct type.
+ * Allocate a size @a n times @a m array
+ * with structs or unions of the given @a type.
  *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
  * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-#define GNUNET_new(type) (type *) GNUNET_malloc (sizeof (type))
+#define GNUNET_new_array_2d(n, m, type) (type **) GNUNET_xnew_array_2d_ (n, m, sizeof (type), __FILE__, __LINE__)
 
 /**
  * @ingroup memory
- * Allocate a size @a n array with structs or unions of the given @a type.
- * Wrapper around #GNUNET_malloc that returns a pointer
- * to the newly created objects of the correct type.
+ * Allocate a size @a n times @a m times @a o array
+ * with structs or unions of the given @a type.
  *
- * @param n number of elements in the array
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param o size of the third dimension
  * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-#define GNUNET_new_array(n, type) (type *) GNUNET_malloc ((n) * sizeof (type))
+#define GNUNET_new_array_3d(n, m, o, type) (type ***) GNUNET_xnew_array_3d_ (n, m, o, sizeof (type), __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -881,7 +1039,8 @@ GNUNET_ntohs_signed (uint16_t n);
 
 /**
  * @ingroup memory
- * Wrapper around realloc. Rellocates size bytes of memory.
+ * Wrapper around realloc. Reallocates size bytes of memory.
+ * The content of the intersection of the new and old size will be unchanged.
  *
  * @param ptr the pointer to reallocate
  * @param size the number of bytes to reallocate
@@ -892,7 +1051,7 @@ GNUNET_ntohs_signed (uint16_t n);
 /**
  * @ingroup memory
  * Wrapper around free. Frees the memory referred to by ptr.
- * Note that is is generally better to free memory that was
+ * Note that it is generally better to free memory that was
  * allocated with #GNUNET_array_grow using #GNUNET_array_grow(mem, size, 0) instead of #GNUNET_free.
  *
  * @param ptr location where to free the memory. ptr must have
@@ -945,12 +1104,12 @@ GNUNET_ntohs_signed (uint16_t n);
  *
  * static void push(struct foo * elem) {
  *   GNUNET_array_grow(myVector, myVecLen, myVecLen+1);
- *   memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
+ *   GNUNET_memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
  * }
  *
  * static void pop(struct foo * elem) {
  *   if (myVecLen == 0) die();
- *   memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
+ *   GNUNET_memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
  *   GNUNET_array_grow(myVector, myVecLen, myVecLen-1);
  * }
  * </pre>
@@ -960,18 +1119,27 @@ GNUNET_ntohs_signed (uint16_t n);
  *        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
@@ -1017,6 +1185,45 @@ void *
 GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber);
 
 
+/**
+ * Allocate memory for a two dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_2d_ directly. Use the
+ * #GNUNET_new_array_2d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param elementSize size of a single element in bytes
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return allocated memory, never NULL
+ */
+void **
+GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t elementSize,
+                       const char *filename, int linenumber);
+
+
+/**
+ * Allocate memory for a three dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_3d_ directly. Use the
+ * #GNUNET_new_array_3d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param o size of the third dimension
+ * @param elementSize size of a single element in bytes
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return allocated memory, never NULL
+ */
+void ***
+GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize,
+                       const char *filename, int linenumber);
+
+
 /**
  * Allocate and initialize memory. Checks the return value, aborts if no more
  * memory is available.  Don't use GNUNET_xmemdup_ directly. Use the
@@ -1211,7 +1418,4 @@ enum GNUNET_SCHEDULER_Priority
 }
 #endif
 
-
-
-
-#endif /*GNUNET_COMMON_H_ */
+#endif /* GNUNET_COMMON_H */