Returns now GNUNET_SYSERR
[oweals/gnunet.git] / src / util / server_mst.c
index b124b80b6f62b6a431723ae868613ff7a6c8023c..835d8eebaaa0a874f8857f43d7abf368c10cc6ef 100644 (file)
@@ -59,7 +59,7 @@ struct GNUNET_SERVER_MessageStreamTokenizer
   /**
    * Size of the buffer (starting at 'hdr').
    */
-  size_t maxbuf;
+  size_t curr_buf;
 
   /**
    * How many bytes in buffer have we already processed?
@@ -74,7 +74,7 @@ struct GNUNET_SERVER_MessageStreamTokenizer
   /**
    * Beginning of the buffer.  Typed like this to force alignment.
    */
-  struct GNUNET_MessageHeader hdr;
+  struct GNUNET_MessageHeader *hdr;
 
 };
 
@@ -83,21 +83,19 @@ struct GNUNET_SERVER_MessageStreamTokenizer
 /**
  * Create a message stream tokenizer.
  *
- * @param maxbuf maximum message size to support (typically
- *    GNUNET_SERVER_MAX_MESSAGE_SIZE)
  * @param cb function to call on completed messages
  * @param cb_cls closure for cb
  * @return handle to tokenizer
  */
 struct GNUNET_SERVER_MessageStreamTokenizer *
-GNUNET_SERVER_mst_create (size_t maxbuf,
-                         GNUNET_SERVER_MessageTokenizerCallback cb,
+GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
                          void *cb_cls)
 {
   struct GNUNET_SERVER_MessageStreamTokenizer *ret;
 
-  ret = GNUNET_malloc (maxbuf + sizeof (struct GNUNET_SERVER_MessageStreamTokenizer));
-  ret->maxbuf = maxbuf;
+  ret = GNUNET_malloc (sizeof (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->cb_cls = cb_cls;
   return ret;
@@ -121,7 +119,7 @@ GNUNET_SERVER_mst_create (size_t maxbuf,
  */
 int
 GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
-                          void *client,
+                          void *client_identity,
                           const char *buf,
                           size_t size,
                           int purge,
@@ -142,11 +140,11 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
              (unsigned int) (mst->pos - mst->off));
 #endif
   ret = GNUNET_OK;
-  ibuf = (char*) &mst->hdr;
+  ibuf = (char*)mst->hdr;
   while (mst->pos > 0)
     {
     do_align:
-      if ( (mst->maxbuf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
+      if ( (mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
           (0 != (mst->off % ALIGN_FACTOR)) )
        {
          /* need to align or need more space */
@@ -183,7 +181,7 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
          GNUNET_break_op (0);
          return GNUNET_SYSERR;
        }
-      if (mst->maxbuf - mst->off < want)
+      if (mst->curr_buf - mst->off < want)
        {
          /* need more space */
          mst->pos -= mst->off;
@@ -192,6 +190,13 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
                   mst->pos);
          mst->off = 0;
        }
+      if (want > mst->curr_buf)
+       {
+         mst->hdr = GNUNET_realloc(mst->hdr, want);
+         ibuf = (char*)mst->hdr;         
+         mst->curr_buf = want;
+       }
+      hdr = (const struct GNUNET_MessageHeader*) &ibuf[mst->off];
       if (mst->pos - mst->off < want)
        {
          delta = GNUNET_MIN (want - (mst->pos - mst->off),
@@ -221,7 +226,7 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
        }
       if (one_shot == GNUNET_YES)
        one_shot = GNUNET_SYSERR;
-      mst->cb (mst->cb_cls, client, hdr);
+      mst->cb (mst->cb_cls, client_identity, hdr);
       mst->off += want;
       if (mst->off == mst->pos)
        {
@@ -246,6 +251,12 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
          /* can try to do zero-copy and process directly from original buffer */
          hdr = (const struct GNUNET_MessageHeader *) buf;
          want = ntohs (hdr->size);
+         if (want < sizeof (struct GNUNET_MessageHeader))
+           {
+             GNUNET_break_op (0);
+             mst->off = 0;
+             return GNUNET_SYSERR;
+           }
          if (size < want)
            break; /* or not, buffer incomplete, so copy to private buffer... */
          if (one_shot == GNUNET_SYSERR)
@@ -257,7 +268,7 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
            }
          if (one_shot == GNUNET_YES)
            one_shot = GNUNET_SYSERR;
-         mst->cb (mst->cb_cls, client, hdr);
+         mst->cb (mst->cb_cls, client_identity, hdr);
          buf += want;
          size -= want;
        }
@@ -271,7 +282,13 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
  copy:
   if ( (size > 0) && (! purge) )
     {
-      GNUNET_assert (mst->pos + size <= mst->maxbuf);
+      if (size + mst->pos > mst->curr_buf)
+       {
+         mst->hdr = GNUNET_realloc(mst->hdr, size + mst->pos);
+         ibuf = (char*)mst->hdr;         
+         mst->curr_buf = size + mst->pos;
+       }
+      GNUNET_assert (mst->pos + size <= mst->curr_buf);
       memcpy (&ibuf[mst->pos], buf, size);
       mst->pos += size;
     }
@@ -294,6 +311,7 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
 void
 GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst)
 {
+  GNUNET_free (mst->hdr);
   GNUNET_free (mst);
 }