Implement a Full Domain Hash (FDH) for RSA signatures and blind signatures
[oweals/gnunet.git] / src / util / server_mst.c
index 0a6eee49cd2a98548f0e8ebb6f3982aeb432f55d..0a686a079e6323e44ef949a774fd4c6ef991c21c 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2010 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2010 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
 
      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 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      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.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 */
 
 /**
  */
 
 #include "platform.h"
  */
 
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_connection_lib.h"
-#include "gnunet_scheduler_lib.h"
-#include "gnunet_server_lib.h"
-#include "gnunet_time_lib.h"
+#include "gnunet_util_lib.h"
 
 
-#define DEBUG_SERVER_MST GNUNET_EXTRA_LOGGING 
 
 #if HAVE_UNALIGNED_64_ACCESS
 #define ALIGN_FACTOR 4
 
 #if HAVE_UNALIGNED_64_ACCESS
 #define ALIGN_FACTOR 4
@@ -86,7 +81,7 @@ struct GNUNET_SERVER_MessageStreamTokenizer
  * Create a message stream tokenizer.
  *
  * @param cb function to call on completed messages
  * Create a message stream tokenizer.
  *
  * @param cb function to call on completed messages
- * @param cb_cls closure for cb
+ * @param cb_cls closure for @a cb
  * @return handle to tokenizer
  */
 struct GNUNET_SERVER_MessageStreamTokenizer *
  * @return handle to tokenizer
  */
 struct GNUNET_SERVER_MessageStreamTokenizer *
@@ -95,7 +90,7 @@ GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
 {
   struct GNUNET_SERVER_MessageStreamTokenizer *ret;
 
 {
   struct GNUNET_SERVER_MessageStreamTokenizer *ret;
 
-  ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_MessageStreamTokenizer));
+  ret = GNUNET_new (struct GNUNET_SERVER_MessageStreamTokenizer);
   ret->hdr = GNUNET_malloc (GNUNET_SERVER_MIN_BUFFER_SIZE);
   ret->curr_buf = GNUNET_SERVER_MIN_BUFFER_SIZE;
   ret->cb = cb;
   ret->hdr = GNUNET_malloc (GNUNET_SERVER_MIN_BUFFER_SIZE);
   ret->curr_buf = GNUNET_SERVER_MIN_BUFFER_SIZE;
   ret->cb = cb;
@@ -111,17 +106,18 @@ GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
  * @param mst tokenizer to use
  * @param client_identity ID of client for which this is a buffer
  * @param buf input data to add
  * @param mst tokenizer to use
  * @param client_identity ID of client for which this is a buffer
  * @param buf input data to add
- * @param size number of bytes in buf
+ * @param size number of bytes in @a buf
  * @param purge should any excess bytes in the buffer be discarded
  *       (i.e. for packet-based services like UDP)
  * @param one_shot only call callback once, keep rest of message in buffer
  * @param purge should any excess bytes in the buffer be discarded
  *       (i.e. for packet-based services like UDP)
  * @param one_shot only call callback once, keep rest of message in buffer
- * @return GNUNET_OK if we are done processing (need more data)
- *         GNUNET_NO if one_shot was set and we have another message ready
- *         GNUNET_SYSERR if the data stream is corrupt
+ * @return #GNUNET_OK if we are done processing (need more data)
+ *         #GNUNET_NO if @a one_shot was set and we have another message ready
+ *         #GNUNET_SYSERR if the data stream is corrupt
  */
 int
 GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
  */
 int
 GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
-                           void *client_identity, const char *buf, size_t size,
+                           void *client_identity,
+                           const char *buf, size_t size,
                            int purge, int one_shot)
 {
   const struct GNUNET_MessageHeader *hdr;
                            int purge, int one_shot)
 {
   const struct GNUNET_MessageHeader *hdr;
@@ -132,16 +128,17 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
   unsigned long offset;
   int ret;
 
   unsigned long offset;
   int ret;
 
-#if DEBUG_SERVER_MST
+  GNUNET_assert (mst->off <= mst->pos);
+  GNUNET_assert (mst->pos <= mst->curr_buf);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Server-mst receives %u bytes with %u bytes already in private buffer\n",
        (unsigned int) size, (unsigned int) (mst->pos - mst->off));
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Server-mst receives %u bytes with %u bytes already in private buffer\n",
        (unsigned int) size, (unsigned int) (mst->pos - mst->off));
-#endif
   ret = GNUNET_OK;
   ibuf = (char *) mst->hdr;
   while (mst->pos > 0)
   {
 do_align:
   ret = GNUNET_OK;
   ibuf = (char *) mst->hdr;
   while (mst->pos > 0)
   {
 do_align:
+    GNUNET_assert (mst->pos >= mst->off);
     if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
         (0 != (mst->off % ALIGN_FACTOR)))
     {
     if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
         (0 != (mst->off % ALIGN_FACTOR)))
     {
@@ -176,15 +173,18 @@ do_align:
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    if (mst->curr_buf - mst->off < want)
+    if ( (mst->curr_buf - mst->off < want) &&
+        (mst->off > 0) )
     {
     {
-      /* need more space */
+      /* can get more space by moving */
       mst->pos -= mst->off;
       memmove (ibuf, &ibuf[mst->off], mst->pos);
       mst->off = 0;
     }
       mst->pos -= mst->off;
       memmove (ibuf, &ibuf[mst->off], mst->pos);
       mst->off = 0;
     }
-    if (want > mst->curr_buf)
+    if (mst->curr_buf < want)
     {
     {
+      /* need to get more space by growing buffer */
+      GNUNET_assert (0 == mst->off);
       mst->hdr = GNUNET_realloc (mst->hdr, want);
       ibuf = (char *) mst->hdr;
       mst->curr_buf = want;
       mst->hdr = GNUNET_realloc (mst->hdr, want);
       ibuf = (char *) mst->hdr;
       mst->curr_buf = want;
@@ -193,6 +193,7 @@ do_align:
     if (mst->pos - mst->off < want)
     {
       delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
     if (mst->pos - mst->off < want)
     {
       delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
+      GNUNET_assert (mst->pos + delta <= mst->curr_buf);
       memcpy (&ibuf[mst->pos], buf, delta);
       mst->pos += delta;
       buf += delta;
       memcpy (&ibuf[mst->pos], buf, delta);
       mst->pos += delta;
       buf += delta;
@@ -217,7 +218,8 @@ do_align:
     if (one_shot == GNUNET_YES)
       one_shot = GNUNET_SYSERR;
     mst->off += want;
     if (one_shot == GNUNET_YES)
       one_shot = GNUNET_SYSERR;
     mst->off += want;
-    mst->cb (mst->cb_cls, client_identity, hdr);
+    if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr))
+      return GNUNET_SYSERR;
     if (mst->off == mst->pos)
     {
       /* reset to beginning of buffer, it's free right now! */
     if (mst->off == mst->pos)
     {
       /* reset to beginning of buffer, it's free right now! */
@@ -225,17 +227,16 @@ do_align:
       mst->pos = 0;
     }
   }
       mst->pos = 0;
     }
   }
+  GNUNET_assert (0 == mst->pos);
   while (size > 0)
   {
   while (size > 0)
   {
-#if DEBUG_SERVER_MST
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Server-mst has %u bytes left in inbound buffer\n",
          (unsigned int) size);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Server-mst has %u bytes left in inbound buffer\n",
          (unsigned int) size);
-#endif
     if (size < sizeof (struct GNUNET_MessageHeader))
       break;
     offset = (unsigned long) buf;
     if (size < sizeof (struct GNUNET_MessageHeader))
       break;
     offset = (unsigned long) buf;
-    need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
+    need_align = (0 != (offset % ALIGN_FACTOR)) ? GNUNET_YES : GNUNET_NO;
     if (GNUNET_NO == need_align)
     {
       /* can try to do zero-copy and process directly from original buffer */
     if (GNUNET_NO == need_align)
     {
       /* can try to do zero-copy and process directly from original buffer */
@@ -248,7 +249,7 @@ do_align:
         return GNUNET_SYSERR;
       }
       if (size < want)
         return GNUNET_SYSERR;
       }
       if (size < want)
-        break;                  /* or not, buffer incomplete, so copy to private buffer... */
+        break;                  /* or not: buffer incomplete, so copy to private buffer... */
       if (one_shot == GNUNET_SYSERR)
       {
         /* cannot call callback again, but return value saying that
       if (one_shot == GNUNET_SYSERR)
       {
         /* cannot call callback again, but return value saying that
@@ -258,7 +259,8 @@ do_align:
       }
       if (one_shot == GNUNET_YES)
         one_shot = GNUNET_SYSERR;
       }
       if (one_shot == GNUNET_YES)
         one_shot = GNUNET_SYSERR;
-      mst->cb (mst->cb_cls, client_identity, hdr);
+      if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr))
+        return GNUNET_SYSERR;
       buf += want;
       size -= want;
     }
       buf += want;
       size -= want;
     }
@@ -278,17 +280,18 @@ copy:
       ibuf = (char *) mst->hdr;
       mst->curr_buf = size + mst->pos;
     }
       ibuf = (char *) mst->hdr;
       mst->curr_buf = size + mst->pos;
     }
-    GNUNET_assert (mst->pos + size <= mst->curr_buf);
+    GNUNET_assert (size + mst->pos <= mst->curr_buf);
     memcpy (&ibuf[mst->pos], buf, size);
     mst->pos += size;
   }
   if (purge)
     memcpy (&ibuf[mst->pos], buf, size);
     mst->pos += size;
   }
   if (purge)
+  {
     mst->off = 0;
     mst->off = 0;
-#if DEBUG_SERVER_MST
+    mst->pos = 0;
+  }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Server-mst leaves %u bytes in private buffer\n",
        (unsigned int) (mst->pos - mst->off));
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Server-mst leaves %u bytes in private buffer\n",
        (unsigned int) (mst->pos - mst->off));
-#endif
   return ret;
 }
 
   return ret;
 }