gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r28500 - libmicrohttpd/src/microspdy


From: gnunet
Subject: [GNUnet-SVN] r28500 - libmicrohttpd/src/microspdy
Date: Sun, 11 Aug 2013 22:40:36 +0200

Author: andreyu
Date: 2013-08-11 22:40:36 +0200 (Sun, 11 Aug 2013)
New Revision: 28500

Modified:
   libmicrohttpd/src/microspdy/internal.h
   libmicrohttpd/src/microspdy/session.c
   libmicrohttpd/src/microspdy/session.h
   libmicrohttpd/src/microspdy/stream.c
   libmicrohttpd/src/microspdy/structures.h
Log:
spdy: WINDOW_UPDATE sent on data receiving to allow big HTTP bodies

Modified: libmicrohttpd/src/microspdy/internal.h
===================================================================
--- libmicrohttpd/src/microspdy/internal.h      2013-08-11 19:35:43 UTC (rev 
28499)
+++ libmicrohttpd/src/microspdy/internal.h      2013-08-11 20:40:36 UTC (rev 
28500)
@@ -28,14 +28,24 @@
 #include "platform.h"
 #include "microspdy.h"
 
-/* size of read buffers for each connection
- * must be at least the size of SPDY_MAX_SUPPORTED_FRAME_SIZE */
+/**
+ * size of read buffers for each connection
+ * must be at least the size of SPDY_MAX_SUPPORTED_FRAME_SIZE
+ */
 #define SPDYF_BUFFER_SIZE 8192
 
-/* number of frames written to the socket at once. After X frames
+/**
+ * initial size of window for each stream (this is for the data
+ * within data frames that can be handled)
+ */
+#define SPDYF_INITIAL_WINDOW_SIZE 65536
+
+/**
+ * number of frames written to the socket at once. After X frames
  * everything should be run again. In this way the application can
  * response to more important requests while a big file is still
- * being transmitted to the client  */
+ * being transmitted to the client
+ */
 #define SPDYF_NUM_SENT_FRAMES_AT_ONCE 10
 
 

Modified: libmicrohttpd/src/microspdy/session.c
===================================================================
--- libmicrohttpd/src/microspdy/session.c       2013-08-11 19:35:43 UTC (rev 
28499)
+++ libmicrohttpd/src/microspdy/session.c       2013-08-11 20:40:36 UTC (rev 
28500)
@@ -380,7 +380,9 @@
                                       frame->length,
                                       0 == (SPDY_DATA_FLAG_FIN & 
frame->flags));
         
-    session->read_buffer_beginning += frame->length;   
+    session->read_buffer_beginning += frame->length;
+    
+    stream->window_size -= frame->length;  
          
     //TODO close in and send rst maybe
     SPDYF_ASSERT(SPDY_YES == ret, "Cancel POST data is not yet implemented");
@@ -389,6 +391,20 @@
     {
       stream->is_in_closed = true;
     }
+    else if(stream->window_size < SPDYF_INITIAL_WINDOW_SIZE / 2)
+    {
+      //very simple implementation of flow control
+      //when the window's size is under the half of the initial value,
+      //increase it again up to the initial value
+      
+      //prepare WINDOW_UPDATE
+      if(SPDY_YES == SPDYF_prepare_window_update(session, stream,
+            SPDYF_INITIAL_WINDOW_SIZE - stream->window_size))
+      {
+        stream->window_size = SPDYF_INITIAL_WINDOW_SIZE;
+      }
+      //else: do it later
+    }
     session->status = SPDY_SESSION_STATUS_WAIT_FOR_HEADER;
     free(frame);
        }
@@ -751,7 +767,48 @@
        return SPDY_YES;
 }
 
+                  
+int
+SPDYF_handler_write_window_update (struct SPDY_Session *session)
+{
+       struct SPDYF_Response_Queue *response_queue = 
session->response_queue_head;
+       struct SPDYF_Control_Frame control_frame;
+       size_t total_size;
+       
+       SPDYF_ASSERT(NULL == session->write_buffer, "the function is called not 
in the correct moment");
+       
+       memcpy(&control_frame, response_queue->control_frame, 
sizeof(control_frame));
+       
+       total_size = sizeof(struct SPDYF_Control_Frame) //SPDY header
+               + 4 // stream id as "subheader"
+               + 4; // delta-window-size as "subheader"
 
+       if(NULL == (session->write_buffer = malloc(total_size)))
+       {
+               return SPDY_NO;
+       }
+       session->write_buffer_beginning = 0;
+       session->write_buffer_offset = 0;
+       session->write_buffer_size = total_size;
+       
+       control_frame.length = 8; // always for WINDOW_UPDATE
+       SPDYF_CONTROL_FRAME_HTON(&control_frame);
+       
+       //put frame headers to write buffer
+       memcpy(session->write_buffer + 
session->write_buffer_offset,&control_frame,sizeof(struct SPDYF_Control_Frame));
+       session->write_buffer_offset +=  sizeof(struct SPDYF_Control_Frame);
+       
+       //put stream id and delta-window-size to write buffer
+       memcpy(session->write_buffer + session->write_buffer_offset, 
response_queue->data, 8);
+       session->write_buffer_offset +=  8;
+       
+       SPDYF_ASSERT(0 == session->write_buffer_beginning, "bug1");
+       SPDYF_ASSERT(session->write_buffer_offset == 
session->write_buffer_size, "bug2");
+
+       return SPDY_YES;
+}
+
+
 void
 SPDYF_handler_ignore_frame (struct SPDY_Session *session)
 {
@@ -1638,3 +1695,55 @@
 
        return SPDY_YES;
 }
+
+
+int
+SPDYF_prepare_window_update (struct SPDY_Session *session,
+                                       struct SPDYF_Stream * stream,
+                                       int32_t delta_window_size)
+{
+       struct SPDYF_Response_Queue *response_to_queue;
+       struct SPDYF_Control_Frame *control_frame;
+       uint32_t *data;
+       
+  SPDYF_ASSERT(NULL != stream, "stream cannot be NULL");
+  
+       if(NULL == (response_to_queue = malloc(sizeof(struct 
SPDYF_Response_Queue))))
+       {
+               return SPDY_NO;
+       }
+       memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
+       
+       if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
+       {
+               free(response_to_queue);
+               return SPDY_NO;
+       }
+       memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
+       
+       if(NULL == (data = malloc(8)))
+       {
+               free(control_frame);
+               free(response_to_queue);
+               return SPDY_NO;
+       }
+       *(data) = HTON31(stream->stream_id);
+       *(data + 1) = HTON31(delta_window_size);
+       
+       control_frame->control_bit = 1;
+       control_frame->version = SPDY_VERSION;
+       control_frame->type = SPDY_CONTROL_FRAME_TYPES_WINDOW_UPDATE;
+       control_frame->flags = 0;
+       
+       response_to_queue->control_frame = control_frame;
+       response_to_queue->process_response_handler = 
&SPDYF_handler_write_window_update;
+       response_to_queue->data = data;
+       response_to_queue->data_size = 8;
+       response_to_queue->stream = stream;
+       
+       SPDYF_queue_response (response_to_queue,
+                                               session,
+                                               -1);
+
+       return SPDY_YES;
+}

Modified: libmicrohttpd/src/microspdy/session.h
===================================================================
--- libmicrohttpd/src/microspdy/session.h       2013-08-11 19:35:43 UTC (rev 
28499)
+++ libmicrohttpd/src/microspdy/session.h       2013-08-11 20:40:36 UTC (rev 
28500)
@@ -172,6 +172,23 @@
 
 
 /**
+ * Prepares WINDOW_UPDATE frame to tell the other party that more
+ * data can be sent on the stream. The frame will be put at the head of
+ * the queue.
+ * 
+ * @param session SPDY session
+ * @param stream stream to which the changed window will apply
+ * @param delta_window_size how much the window grows
+ * @return SPDY_NO on memory error or
+ *                     SPDY_YES on success
+ */
+int
+SPDYF_prepare_window_update (struct SPDY_Session *session,
+                                       struct SPDYF_Stream * stream,
+                                       int32_t delta_window_size);
+          
+
+/**
  * Handler called by session_write to fill the write buffer according to
  * the data frame waiting in the response queue.
  * When response data is given by user callback, the lib does not know
@@ -233,6 +250,20 @@
 
 
 /**
+ * Handler called by session_write to fill the write buffer based on the
+ * control frame (WINDOW_UPDATE) waiting in the response queue.
+ * 
+ * @param session SPDY session
+ * @return SPDY_NO on error (not enough memory). If
+ *         the error is unrecoverable the handler changes session's
+ *         status.
+ *                     SPDY_YES on success
+ */                    
+int
+SPDYF_handler_write_window_update (struct SPDY_Session *session);
+
+
+/**
  * Carefully ignore the full size of frames which are not yet supported
  * by the lib.
  * TODO Ignoring frames containing compressed bodies means that the

Modified: libmicrohttpd/src/microspdy/stream.c
===================================================================
--- libmicrohttpd/src/microspdy/stream.c        2013-08-11 19:35:43 UTC (rev 
28499)
+++ libmicrohttpd/src/microspdy/stream.c        2013-08-11 20:40:36 UTC (rev 
28500)
@@ -104,6 +104,7 @@
        stream->flag_unidirectional = (frame->flags & 
SPDY_SYN_STREAM_FLAG_UNIDIRECTIONAL) != 0;
        stream->is_out_closed = stream->flag_unidirectional;
        stream->is_server_initiator = false;
+       stream->window_size = SPDYF_INITIAL_WINDOW_SIZE;
        
        //put the stream to the list of streams for the session
        DLL_insert(session->streams_head, session->streams_tail, stream);

Modified: libmicrohttpd/src/microspdy/structures.h
===================================================================
--- libmicrohttpd/src/microspdy/structures.h    2013-08-11 19:35:43 UTC (rev 
28499)
+++ libmicrohttpd/src/microspdy/structures.h    2013-08-11 20:40:36 UTC (rev 
28500)
@@ -554,6 +554,11 @@
        uint32_t assoc_stream_id;
        
        /**
+        * The window of the data within data frames.
+        */
+       uint32_t window_size;
+       
+       /**
         * Stream priority. 0 is the highest, 7 is the lowest.
         */
        uint8_t priority;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]