This file is part of GNUnet.
Copyright (C) 2009, 2010, 2011, 2016 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.
-
- 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ Affero General Public License for more details.
*/
/**
/**
* How many messages do we queue up at most for any client? This can
* cause messages to be dropped if clients do not process them fast
- * enough!
+ * enough! Note that this is a soft limit; we try
+ * to keep a few larger messages above the limit.
*/
-#define MAX_QUEUE 128
+#define SOFT_MAX_QUEUE 128
+
+/**
+ * How many messages do we queue up at most for any client? This can
+ * cause messages to be dropped if clients do not process them fast
+ * enough! Note that this is the hard limit.
+ */
+#define HARD_MAX_QUEUE 256
/**
*
* @param cls reservation request (`struct TokenizerContext`)
* @param message the actual message
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO to stop further processing (no error)
+ * #GNUNET_SYSERR to stop further processing with error
*/
static int
tokenized_cb (void *cls,
{
size_t size = msize + sizeof (struct NotifyTrafficMessage);
- if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ if (size >= GNUNET_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
return;
struct GNUNET_MQ_Envelope *env;
struct NotifyTrafficMessage *ntm;
uint16_t mtype;
+ unsigned int qlen;
int tm;
tm = type_match (ntohs (msg->type),
if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
(0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) )
continue;
- if (MAX_QUEUE < GNUNET_MQ_get_length (c->mq))
+
+ /* Drop messages if:
+ 1) We are above the hard limit, or
+ 2) We are above the soft limit, and a coin toss limited
+ to the message size (giving larger messages a
+ proportionally higher chance of being queued) falls
+ below the threshold. The threshold is based on where
+ we are between the soft and the hard limit, scaled
+ to match the range of message sizes we usually encounter
+ (i.e. up to 32k); so a 64k message has a 50% chance of
+ being kept if we are just barely below the hard max,
+ and a 99% chance of being kept if we are at the soft max.
+ The reason is to make it more likely to drop control traffic
+ (ACK, queries) which may be cummulative or highly redundant,
+ and cheap to drop than data traffic. */
+ qlen = GNUNET_MQ_get_length (c->mq);
+ if ( (qlen >= HARD_MAX_QUEUE) ||
+ ( (qlen > SOFT_MAX_QUEUE) &&
+ ( (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ ntohs (msg->size)) ) <
+ (qlen - SOFT_MAX_QUEUE) * 0x8000 /
+ (HARD_MAX_QUEUE - SOFT_MAX_QUEUE) ) ) )
{
char buf[1024];
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
"Dropping decrypted message of type %u as client is too busy (queue full)\n",
(unsigned int) ntohs (msg->type));
GNUNET_snprintf (buf,