Various plugins: Use the IS_TRUE and IS_FALSE macros everywhere.
[collectd.git] / src / network.c
index 0e416bd..f4b8757 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/network.c
  * Copyright (C) 2005-2009  Florian octo Forster
+ * Copyright (C) 2009       Aman Gupta
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -17,6 +18,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Aman Gupta <aman at tmm1.net>
  **/
 
 #define _BSD_SOURCE /* For struct ip_mreq */
 
 #if HAVE_LIBGCRYPT
 # include <gcrypt.h>
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
 #endif
 
-/* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
-/* #define BUFF_SIZE 1452 */
-
 #ifndef IPV6_ADD_MEMBERSHIP
 # ifdef IPV6_JOIN_GROUP
 #  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -65,9 +65,6 @@
 # endif
 #endif /* !IP_ADD_MEMBERSHIP */
 
-/* Buffer size to allocate. */
-#define BUFF_SIZE 1024
-
 /*
  * Maximum size required for encryption / signing:
  *
@@ -245,7 +242,7 @@ typedef struct part_encryption_aes256_s part_encryption_aes256_t;
 
 struct receive_list_entry_s
 {
-  char data[BUFF_SIZE];
+  char *data;
   int  data_len;
   int  fd;
   struct receive_list_entry_s *next;
@@ -256,6 +253,7 @@ typedef struct receive_list_entry_s receive_list_entry_t;
  * Private variables
  */
 static int network_config_ttl = 0;
+static size_t network_config_packet_size = 1024;
 static int network_config_forward = 0;
 
 static sockent_t *sending_sockets = NULL;
@@ -278,7 +276,7 @@ static int       dispatch_thread_running = 0;
 static pthread_t dispatch_thread_id;
 
 /* Buffer in which to-be-sent network packets are constructed. */
-static char             send_buffer[BUFF_SIZE];
+static char            *send_buffer;
 static char            *send_buffer_ptr;
 static int              send_buffer_fill;
 static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
@@ -1431,6 +1429,10 @@ static int parse_packet (sockent_t *se, /* {{{ */
                }
        } /* while (buffer_size > sizeof (part_header_t)) */
 
+       if (status == 0 && buffer_size > 0)
+               WARNING ("network plugin: parse_packet: Received truncated "
+                               "packet, try increasing `MaxPacketSize'");
+
        return (status);
 } /* }}} int parse_packet */
 
@@ -1959,7 +1961,7 @@ static void *dispatch_thread (void __attribute__((unused)) *arg) /* {{{ */
     /* Lock and wait for more data to come in */
     pthread_mutex_lock (&receive_list_lock);
     while ((listen_loop == 0)
-       && (receive_list_head == NULL))
+        && (receive_list_head == NULL))
       pthread_cond_wait (&receive_list_cond, &receive_list_lock);
 
     /* Remove the head entry and unlock */
@@ -1991,14 +1993,16 @@ static void *dispatch_thread (void __attribute__((unused)) *arg) /* {{{ */
 
     if (se == NULL)
     {
-           ERROR ("network plugin: Got packet from FD %i, but can't "
-                           "find an appropriate socket entry.",
-                           ent->fd);
-           sfree (ent);
-           continue;
+      ERROR ("network plugin: Got packet from FD %i, but can't "
+          "find an appropriate socket entry.",
+          ent->fd);
+      sfree (ent->data);
+      sfree (ent);
+      continue;
     }
 
     parse_packet (se, ent->data, ent->data_len, /* flags = */ 0);
+    sfree (ent->data);
     sfree (ent);
   } /* while (42) */
 
@@ -2007,7 +2011,7 @@ static void *dispatch_thread (void __attribute__((unused)) *arg) /* {{{ */
 
 static int network_receive (void) /* {{{ */
 {
-       char buffer[BUFF_SIZE];
+       char buffer[network_config_packet_size];
        int  buffer_len;
 
        int i;
@@ -2067,14 +2071,15 @@ static int network_receive (void) /* {{{ */
                                return (-1);
                        }
                        memset (ent, 0, sizeof (receive_list_entry_t));
+                       ent->data = malloc (network_config_packet_size);
+                       if (ent->data == NULL)
+                       {
+                               ERROR ("network plugin: malloc failed.");
+                               return (-1);
+                       }
                        ent->fd = listen_sockets_pollfd[i].fd;
                        ent->next = NULL;
 
-                       /* Hopefully this be optimized out by the compiler. It
-                        * might help prevent stupid bugs in the future though.
-                        */
-                       assert (sizeof (ent->data) == sizeof (buffer));
-
                        memcpy (ent->data, buffer, buffer_len);
                        ent->data_len = buffer_len;
 
@@ -2131,7 +2136,7 @@ static void *receive_thread (void __attribute__((unused)) *arg)
 
 static void network_init_buffer (void)
 {
-       memset (send_buffer, 0, sizeof (send_buffer));
+       memset (send_buffer, 0, network_config_packet_size);
        send_buffer_ptr = send_buffer;
        send_buffer_fill = 0;
 
@@ -2450,7 +2455,7 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
        pthread_mutex_lock (&send_buffer_lock);
 
        status = add_to_buffer (send_buffer_ptr,
-                       sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
+                       network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
                        &send_buffer_vl,
                        ds, vl);
        if (status >= 0)
@@ -2464,7 +2469,7 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
                flush_buffer ();
 
                status = add_to_buffer (send_buffer_ptr,
-                               sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
+                               network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
                                &send_buffer_vl,
                                ds, vl);
 
@@ -2480,7 +2485,7 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
                ERROR ("network plugin: Unable to append to the "
                                "buffer for some weird reason");
        }
-       else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
+       else if ((network_config_packet_size - send_buffer_fill) < 15)
        {
                flush_buffer ();
        }
@@ -2513,13 +2518,9 @@ static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
   {
     char *str = ci->values[0].value.string;
 
-    if ((strcasecmp ("true", str) == 0)
-        || (strcasecmp ("yes", str) == 0)
-        || (strcasecmp ("on", str) == 0))
+    if (IS_TRUE (str))
       *retval = 1;
-    else if ((strcasecmp ("false", str) == 0)
-        || (strcasecmp ("no", str) == 0)
-        || (strcasecmp ("off", str) == 0))
+    else if (IS_FALSE (str))
       *retval = 0;
     else
     {
@@ -2551,6 +2552,24 @@ static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
   return (0);
 } /* }}} int network_config_set_ttl */
 
+static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
+{
+  int tmp;
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
+        "one numeric argument.");
+    return (-1);
+  }
+
+  tmp = (int) ci->values[0].value.number;
+  if ((tmp >= 1024) && (tmp <= 65535))
+    network_config_packet_size = tmp;
+
+  return (0);
+} /* }}} int network_config_set_buffer_size */
+
 #if HAVE_LIBGCRYPT
 static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
     char **ret_string)
@@ -2774,6 +2793,8 @@ static int network_config (oconfig_item_t *ci) /* {{{ */
       network_config_add_server (child);
     else if (strcasecmp ("TimeToLive", child->key) == 0)
       network_config_set_ttl (child);
+    else if (strcasecmp ("MaxPacketSize", child->key) == 0)
+      network_config_set_buffer_size (child);
     else if (strcasecmp ("Forward", child->key) == 0)
       network_config_set_boolean (child, &network_config_forward);
     else if (strcasecmp ("CacheFlush", child->key) == 0)
@@ -2791,7 +2812,7 @@ static int network_config (oconfig_item_t *ci) /* {{{ */
 static int network_notification (const notification_t *n,
                user_data_t __attribute__((unused)) *user_data)
 {
-  char  buffer[BUFF_SIZE];
+  char  buffer[network_config_packet_size];
   char *buffer_ptr = buffer;
   int   buffer_free = sizeof (buffer);
   int   status;
@@ -2890,6 +2911,8 @@ static int network_shutdown (void)
        if (send_buffer_fill > 0)
                flush_buffer ();
 
+       sfree (send_buffer);
+
        /* TODO: Close `sending_sockets' */
 
        plugin_unregister_config ("network");
@@ -2910,8 +2933,20 @@ static int network_init (void)
                return (0);
        have_init = true;
 
+#if HAVE_LIBGCRYPT
+       gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+       gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+       gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif
+
        plugin_register_shutdown ("network", network_shutdown);
 
+       send_buffer = malloc (network_config_packet_size);
+       if (send_buffer == NULL)
+       {
+               ERROR ("network plugin: malloc failed.");
+               return (-1);
+       }
        network_init_buffer ();
 
        /* setup socket(s) and so on */