new operation queue for limiting overlay connects
[oweals/gnunet.git] / src / transport / plugin_transport_http_server.c
index c674a675563cafb329d9dbc84908264f26a1503e..a8731907eafe7f3892a6b6ead986bcdde748e2f2 100644 (file)
@@ -397,6 +397,11 @@ struct HTTP_Message
    */
   size_t size;
 
+  /**
+   * HTTP/S specific overhead
+   */
+  size_t overhead;
+
   /**
    * Continuation function to call once the transmission buffer
    * has again space available.  NULL if there is no
@@ -510,6 +515,7 @@ http_server_plugin_send (void *cls,
   struct HTTP_Server_Plugin *plugin = cls;
   struct HTTP_Message *msg;
   int bytes_sent = 0;
+  char *stat_txt;
 
   GNUNET_assert (plugin != NULL);
   GNUNET_assert (session != NULL);
@@ -547,6 +553,11 @@ http_server_plugin_send (void *cls,
 
   GNUNET_CONTAINER_DLL_insert_tail (session->msg_head, session->msg_tail, msg);
 
+  GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers", plugin->protocol);
+  GNUNET_STATISTICS_update (plugin->env->stats,
+                            stat_txt, msgbuf_size, GNUNET_NO);
+  GNUNET_free (stat_txt);
+
   server_reschedule (session->plugin, session->server_send->mhd_daemon, GNUNET_YES);
   server_reschedule_session_timeout (session);
 
@@ -674,7 +685,8 @@ server_delete_session (struct Session *s)
     GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
     if (msg->transmit_cont != NULL)
     {
-      msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
+      msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR,
+                          msg->size, msg->pos + msg->overhead);
     }
     GNUNET_free (msg);
     msg = tmp;
@@ -852,9 +864,10 @@ server_mhd_connection_timeout (struct HTTP_Server_Plugin *plugin, struct Session
 /**
  * Parse incoming URL for tag and target
  *
- * @url incoming url
- * @target where to store the target
- * @tag where to store the tag
+ * @param plugin plugin
+ * @param url incoming url
+ * @param target where to store the target
+ * @param tag where to store the tag
  * @return GNUNET_OK on success, GNUNET_SYSERR on error
  */
 
@@ -869,6 +882,7 @@ server_parse_url (struct HTTP_Server_Plugin *plugin, const char * url, struct GN
   char * separator = NULL;
   char hash[plugin->peer_id_length+1];
   int hash_length;
+  unsigned long int ctag;
 
   /* URL parsing
    * URL is valid if it is in the form [prefix with (multiple) '/'][peerid[103];tag]*/
@@ -896,19 +910,26 @@ server_parse_url (struct HTTP_Server_Plugin *plugin, const char * url, struct GN
     if (debug) GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  (*tag) = strtoul (tag_start, &tag_end, 10);
-  if ((*tag) == 0)
+  ctag = strtoul (tag_start, &tag_end, 10);
+  if (ctag == 0)
   {
     /* tag == 0 , invalid */
     if (debug) GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  if (((*tag) == ULONG_MAX) && (ERANGE == errno))
+  if ((ctag == ULONG_MAX) && (ERANGE == errno))
   {
     /* out of range: > ULONG_MAX */
     if (debug) GNUNET_break (0);
     return GNUNET_SYSERR;
   }
+  if (ctag > UINT32_MAX)
+  {
+    /* out of range: > UINT32_MAX */
+    if (debug) GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  (*tag) = (uint32_t) ctag;
   if (NULL == tag_end)
   {
       /* no char after tag */
@@ -930,7 +951,7 @@ server_parse_url (struct HTTP_Server_Plugin *plugin, const char * url, struct GN
   if (NULL == target_start)
   {
       /* no leading '/' */
-      target_start = url;
+      target_start = (char *) url;
   }
   target_start++;
   hash_length = separator - target_start;
@@ -1169,6 +1190,7 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max)
   struct Session *s = cls;
   ssize_t bytes_read = 0;
   struct HTTP_Message *msg;
+  char *stat_txt;
 
   GNUNET_assert (NULL != p);
   if (GNUNET_NO == server_exist_session (p, s))
@@ -1187,13 +1209,24 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max)
     {
       GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
       if (NULL != msg->transmit_cont)
-        msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK);
+        msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK,
+                            msg->size, msg->size + msg->overhead);
       GNUNET_free (msg);
     }
   }
   if (0 < bytes_read)
+  {
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
                    "Sent %u bytes to peer `%s' with session %p \n", bytes_read, GNUNET_i2s (&s->target), s);
+    GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers", p->protocol);
+    GNUNET_STATISTICS_update (p->env->stats,
+                              stat_txt, -bytes_read, GNUNET_NO);
+    GNUNET_free (stat_txt);
+    GNUNET_asprintf (&stat_txt, "# bytes transmitted via %s_server", p->protocol);
+    GNUNET_STATISTICS_update (p->env->stats,
+                              stat_txt, bytes_read, GNUNET_NO);
+    GNUNET_free (stat_txt);
+  }
   return bytes_read;
 }
 
@@ -1213,6 +1246,7 @@ server_receive_mst_cb (void *cls, void *client,
   struct Session *s = cls;
   struct GNUNET_ATS_Information atsi[2];
   struct GNUNET_TIME_Relative delay;
+  char *stat_txt;
 
   GNUNET_assert (NULL != p);
   if (GNUNET_NO == server_exist_session(p, s))
@@ -1226,11 +1260,18 @@ server_receive_mst_cb (void *cls, void *client,
   atsi[1].value = s->ats_address_network_type;
   GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED));
 
+
   delay = plugin->env->receive (plugin->env->cls,
                                 &s->target,
                                 message,
                                 (const struct GNUNET_ATS_Information *) &atsi, 2,
                                 s, s->addr, s->addrlen);
+
+  GNUNET_asprintf (&stat_txt, "# bytes received via %s_server", plugin->protocol);
+  GNUNET_STATISTICS_update (plugin->env->stats,
+                            stat_txt, ntohs (message->size), GNUNET_NO);
+  GNUNET_free (stat_txt);
+
   s->session_passed = GNUNET_YES;
   s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay);
   if (delay.rel_value > 0)
@@ -1607,6 +1648,8 @@ server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 }
 
 
+#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG
+
 /**
  * Function that queries MHD's select sets and
  * starts the task waiting for them.
@@ -1628,7 +1671,7 @@ server_schedule (struct HTTP_Server_Plugin *plugin,
   struct GNUNET_NETWORK_FDSet *wws;
   struct GNUNET_NETWORK_FDSet *wes;
   int max;
-  unsigned MHD_LONG_LONG timeout;
+  UNSIGNED_MHD_LONG_LONG timeout;
   static unsigned long long last_timeout = 0;
   int haveto;