extend API to enalbe exclusive port ranges to be specified for testing-system objects
[oweals/gnunet.git] / src / include / gnunet_common.h
index 2636824d319fd3f5153e22b66d1062316d2c5a0b..dae3d4945aed75b348e5391d6a7bd58e940a0d69 100644 (file)
 #include <stdarg.h>
 #endif
 
-/**
- * Version of the API (for entire gnunetutil.so library).
- */
-#define GNUNET_UTIL_VERSION 0x00089900
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
 
 /**
- * Name used for "services" that are actually command-line
- * programs invoked by the end user.
+ * Version of the API (for entire gnunetutil.so library).
  */
-#define GNUNET_CLIENT_SERVICE_NAME "client"
+#define GNUNET_UTIL_VERSION 0x00090200
 
 /**
  * Named constants for return values.  The following
 
 #define GNUNET_MAX(a,b) (((a) > (b)) ? (a) : (b))
 
+/* some systems use one underscore only, and mingw uses no underscore... */
+#ifndef __BYTE_ORDER
+#ifdef _BYTE_ORDER
+#define __BYTE_ORDER _BYTE_ORDER
+#else
+#ifdef BYTE_ORDER
+#define __BYTE_ORDER BYTE_ORDER
+#endif
+#endif
+#endif
+#ifndef __BIG_ENDIAN
+#ifdef _BIG_ENDIAN
+#define __BIG_ENDIAN _BIG_ENDIAN
+#else
+#ifdef BIG_ENDIAN
+#define __BIG_ENDIAN BIG_ENDIAN
+#endif
+#endif
+#endif
+#ifndef __LITTLE_ENDIAN
+#ifdef _LITTLE_ENDIAN
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#else
+#ifdef LITTLE_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#endif
+#endif
+#endif
+
+/**
+ * Endian operations
+ */
+
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define GNUNET_htobe16(x) __bswap_16 (x)
+#  define GNUNET_htole16(x) (x)
+#  define GNUNET_be16toh(x) __bswap_16 (x)
+#  define GNUNET_le16toh(x) (x)
+
+#  define GNUNET_htobe32(x) __bswap_32 (x)
+#  define GNUNET_htole32(x) (x)
+#  define GNUNET_be32toh(x) __bswap_32 (x)
+#  define GNUNET_le32toh(x) (x)
+
+#  define GNUNET_htobe64(x) __bswap_64 (x)
+#  define GNUNET_htole64(x) (x)
+#  define GNUNET_be64toh(x) __bswap_64 (x)
+#  define GNUNET_le64toh(x) (x)
+#endif
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define GNUNET_htobe16(x) (x)
+#  define GNUNET_htole16(x) __bswap_16 (x)
+#  define GNUNET_be16toh(x) (x)
+#  define GNUNET_le16toh(x) __bswap_16 (x)
+
+#  define GNUNET_htobe32(x) (x)
+#  define GNUNET_htole32(x) __bswap_32 (x)
+#  define GNUNET_be32toh(x) (x)
+#  define GNUNET_le32toh(x) __bswap_32 (x)
+
+#  define GNUNET_htobe64(x) (x)
+#  define GNUNET_htole64(x) __bswap_64 (x)
+#  define GNUNET_be64toh(x) (x)
+#  define GNUNET_le64toh(x) __bswap_64 (x)
+#endif
+
+
+
+
 /**
  * gcc-ism to get packed structs.
  */
 #define GNUNET_PACKED __attribute__((packed))
 
+/**
+ * gcc-ism to get gcc bitfield layout when compiling with -mms-bitfields
+ */
+#if MINGW
+#define GNUNET_GCC_STRUCT_LAYOUT __attribute__((gcc_struct))
+#else
+#define GNUNET_GCC_STRUCT_LAYOUT
+#endif
+
+/**
+ * gcc-ism to force alignment; we use this to align char-arrays
+ * that may then be cast to 'struct's.  See also gcc
+ * bug #33594.
+ */
+#ifdef __BIGGEST_ALIGNMENT__
+#define GNUNET_ALIGN __attribute__((aligned (__BIGGEST_ALIGNMENT__)))
+#else
+#define GNUNET_ALIGN __attribute__((aligned (8)))
+#endif
+
+/**
+ * gcc-ism to document unused arguments
+ */
+#define GNUNET_UNUSED __attribute__((unused))
+
+/**
+ * gcc-ism to document functions that don't return
+ */
+#define GNUNET_NORETURN __attribute__((noreturn))
+
+#if MINGW
+#if __GNUC__ > 3
+/**
+ * gcc 4.x-ism to pack structures even on W32 (to be used before structs);
+ * Using this would cause structs to be unaligned on the stack on Sparc,
+ * so we *only* use this on W32 (see #670578 from Debian); fortunately,
+ * W32 doesn't run on sparc anyway.
+ */
+#define GNUNET_NETWORK_STRUCT_BEGIN \
+  _Pragma("pack(push)") \
+  _Pragma("pack(1)")
+
+/**
+ * gcc 4.x-ism to pack structures even on W32 (to be used after structs)
+ * Using this would cause structs to be unaligned on the stack on Sparc,
+ * so we *only* use this on W32 (see #670578 from Debian); fortunately,
+ * W32 doesn't run on sparc anyway.
+ */
+#define GNUNET_NETWORK_STRUCT_END _Pragma("pack(pop)")
+
+#else
+#error gcc 4.x or higher required on W32 systems
+#endif
+#else
+/**
+ * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32
+ */
+#define GNUNET_NETWORK_STRUCT_BEGIN 
+
+/**
+ * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;
+ */
+#define GNUNET_NETWORK_STRUCT_END
+#endif
 
 /* ************************ super-general types *********************** */
 
+GNUNET_NETWORK_STRUCT_BEGIN
+
 /**
  * Header for all communications.
  */
@@ -103,11 +240,10 @@ struct GNUNET_MessageHeader
 /**
  * @brief 512-bit hashcode
  */
-typedef struct
+struct GNUNET_HashCode
 {
   uint32_t bits[512 / 8 / sizeof (uint32_t)];   /* = 16 */
-}
-GNUNET_HashCode;
+};
 
 
 /**
@@ -116,9 +252,9 @@ GNUNET_HashCode;
  */
 struct GNUNET_PeerIdentity
 {
-  GNUNET_HashCode hashPubKey GNUNET_PACKED;
+  struct GNUNET_HashCode hashPubKey;
 };
-
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Function called with a filename.
@@ -138,6 +274,7 @@ typedef int (*GNUNET_FileNameCallback) (void *cls, const char *filename);
  */
 enum GNUNET_ErrorType
 {
+  GNUNET_ERROR_TYPE_UNSPECIFIED = -1,
   GNUNET_ERROR_TYPE_NONE = 0,
   GNUNET_ERROR_TYPE_ERROR = 1,
   GNUNET_ERROR_TYPE_WARNING = 2,
@@ -161,6 +298,20 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind,
                                const char *component, const char *date,
                                const char *message);
 
+
+/**
+ * Get the number of log calls that are going to be skipped
+ *
+ * @return number of log calls to be ignored
+ */
+int
+GNUNET_get_log_skip ();
+
+#if !defined(GNUNET_CULL_LOGGING)
+int
+GNUNET_get_log_call_status (int caller_level, const char *comp,
+                            const char *file, const char *function, int line);
+#endif
 /**
  * Main log function.
  *
@@ -169,9 +320,29 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind,
  * @param ... arguments for format string
  */
 void
-GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...);
-
+GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...);
+
+/* from glib */
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _GNUNET_BOOLEAN_EXPR(expr)              \
+ __extension__ ({                               \
+   int _gnunet_boolean_var_;                    \
+   if (expr)                                    \
+      _gnunet_boolean_var_ = 1;                 \
+   else                                         \
+      _gnunet_boolean_var_ = 0;                 \
+   _gnunet_boolean_var_;                        \
+})
+#define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 1))
+#define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 0))
+#else
+#define GN_LIKELY(expr) (expr)
+#define GN_UNLIKELY(expr) (expr)
+#endif
 
+#if !defined(GNUNET_LOG_CALL_STATUS)
+#define GNUNET_LOG_CALL_STATUS -1
+#endif
 
 /**
  * Log function that specifies an alternative component.
@@ -183,18 +354,55 @@ GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...);
  * @param ... arguments for format string
  */
 void
-GNUNET_log_from (enum GNUNET_ErrorType kind, const char *comp,
-                 const char *message, ...);
+GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
+                         const char *message, ...);
+
+#if !defined(GNUNET_CULL_LOGGING)
+#define GNUNET_log_from(kind,comp,...) do { int log_line = __LINE__;\
+  static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
+  if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \
+    if (GN_UNLIKELY(log_call_enabled == -1))\
+      log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), (comp), __FILE__, __FUNCTION__, log_line); \
+    if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, GNUNET_NO); }\
+    else {\
+      if (GN_UNLIKELY(log_call_enabled))\
+        GNUNET_log_from_nocheck ((kind), comp, __VA_ARGS__);   \
+    }\
+  }\
+} while (0)
+
+#define GNUNET_log(kind,...) do { int log_line = __LINE__;\
+  static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
+  if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \
+    if (GN_UNLIKELY(log_call_enabled == -1))\
+      log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), NULL, __FILE__, __FUNCTION__, log_line);\
+    if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, GNUNET_NO); }\
+    else {\
+      if (GN_UNLIKELY(log_call_enabled))\
+        GNUNET_log_nocheck ((kind), __VA_ARGS__);      \
+    }\
+  }\
+} while (0)
+#else
+#define GNUNET_log(...)
+#define GNUNET_log_from(...)
+#endif
 
 
+/**
+ * Abort the process, generate a core dump if possible.
+ */
+void
+GNUNET_abort (void) GNUNET_NORETURN;
+
 /**
  * Ignore the next n calls to the log function.
  *
- * @param n number of log calls to ignore
+ * @param n number of log calls to ignore (could be negative)
  * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero
  */
 void
-GNUNET_log_skip (unsigned int n, int check_reset);
+GNUNET_log_skip (int n, int check_reset);
 
 
 /**
@@ -235,10 +443,10 @@ GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls);
  * NOT reentrant!
  *
  * @param hc the hash code
- * @return string 
+ * @return string
  */
 const char *
-GNUNET_h2s (const GNUNET_HashCode * hc);
+GNUNET_h2s (const struct GNUNET_HashCode * hc);
 
 
 /**
@@ -251,7 +459,7 @@ GNUNET_h2s (const GNUNET_HashCode * hc);
  * @return string
  */
 const char *
-GNUNET_h2s_full (const GNUNET_HashCode * hc);
+GNUNET_h2s_full (const struct GNUNET_HashCode * hc);
 
 
 /**
@@ -266,6 +474,17 @@ GNUNET_h2s_full (const GNUNET_HashCode * hc);
 const char *
 GNUNET_i2s (const struct GNUNET_PeerIdentity *pid);
 
+/**
+ * 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!
+ *
+ * @param pid the peer identity
+ * @return string form of the pid; will be overwritten by next
+ *         call to GNUNET_i2s.
+ */
+const char *
+GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid);
 
 /**
  * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string
@@ -293,12 +512,12 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
 /**
  * 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__); abort(); } } while(0)
+#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)
 
 /**
  * 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); abort(); } } while(0)
+#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)
 
 /**
  * Use this for internal assertion violations that are
@@ -314,7 +533,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * we still want to see these problems during
  * development and testing.  "OP == other peer".
  */
-#define GNUNET_break_op(cond)  do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("External protocol violation detected at %s:%d.\n"), __FILE__, __LINE__); } } while(0)
+#define GNUNET_break_op(cond)  do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("External protocol violation detected at %s:%d.\n"), __FILE__, __LINE__); } } while(0)
 
 /**
  * Log an error message at log-level 'level' that indicates
@@ -323,6 +542,13 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  */
 #define GNUNET_log_strerror(level, cmd) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, STRERROR(errno)); } while(0)
 
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' with the message given
+ * by strerror(errno).
+ */
+#define GNUNET_log_from_strerror(level, component, cmd) do { GNUNET_log_from (level, component, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, STRERROR(errno)); } while(0)
+
 /**
  * Log an error message at log-level 'level' that indicates
  * a failure of the command 'cmd' with the message given
@@ -330,24 +556,46 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  */
 #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)
 
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' with the message given
+ * by strerror(errno).
+ */
+#define GNUNET_log_from_strerror_file(level, component, cmd, filename) do { GNUNET_log_from (level, component, _("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename,__FILE__, __LINE__, STRERROR(errno)); } while(0)
+
 /* ************************* endianess conversion ****************** */
 
 /**
- * Convert a long-long to host-byte-order.
+ * Convert unsigned 64-bit integer to host-byte-order.
  * @param n the value in network byte order
  * @return the same value in host byte order
  */
-unsigned long long
-GNUNET_ntohll (unsigned long long n);
+uint64_t
+GNUNET_ntohll (uint64_t n);
 
 /**
- * Convert a long long to network-byte-order.
+ * Convert unsigned 64-bit integer to network-byte-order.
  * @param n the value in host byte order
  * @return the same value in network byte order
  */
-unsigned long long
-GNUNET_htonll (unsigned long long n);
+uint64_t
+GNUNET_htonll (uint64_t n);
 
+/**
+ * Convert double to network-byte-order.
+ * @param d the value in network byte order
+ * @return the same value in host byte order
+ */
+double 
+GNUNET_hton_double (double d);
+
+/**
+ * Convert double to host-byte-order
+ * @param d the value in network byte order
+ * @return the same value in host byte order
+ */
+double 
+GNUNET_ntoh_double (double d);
 
 /* ************************* allocation functions ****************** */
 
@@ -368,7 +616,7 @@ GNUNET_htonll (unsigned long long n);
 
 /**
  * Allocate and initialize a block of memory.
- * 
+ *
  * @param buf data to initalize the block with
  * @param size the number of bytes in buf (and size of the allocation)
  * @return pointer to size bytes of memory, never NULL (!)
@@ -428,7 +676,7 @@ GNUNET_htonll (unsigned long long n);
  * @param length of the string to duplicate
  * @return a partial copy of the string including zero-termination
  */
-#define GNUNET_strndup(a,b) GNUNET_xstrndup_(a,b,__FILE__,__LINE__)
+#define GNUNET_strndup(a,length) GNUNET_xstrndup_(a,length,__FILE__,__LINE__)
 
 /**
  * Grow a well-typed (!) array.  This is a convenience
@@ -513,7 +761,6 @@ void *
 GNUNET_xmalloc_ (size_t size, 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
@@ -577,8 +824,9 @@ GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber);
 
 /**
  * Dup partially a string. Don't call GNUNET_xstrndup_ directly. Use the GNUNET_strndup macro.
+ *
  * @param str string to duplicate
- * @param len lenght of the string to duplicate
+ * @param len length of the string to duplicate
  * @param filename where is this call being made (for debugging)
  * @param linenumber line where this call is being made (for debugging)
  * @return the duplicated string
@@ -607,6 +855,14 @@ GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
                unsigned int newCount, const char *filename, int linenumber);
 
 
+/**
+ * Create a copy of the given message.
+ *
+ * @param msg message to copy
+ * @return duplicate of the message
+ */
+struct GNUNET_MessageHeader *
+GNUNET_copy_message (const struct GNUNET_MessageHeader *msg);
 
 
 #if __STDC_VERSION__ < 199901L
@@ -617,4 +873,17 @@ GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
 #endif
 #endif
 
+
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
 #endif /*GNUNET_COMMON_H_ */