]> granicus.if.org Git - curl/commitdiff
"Transfer-Encoding: chunked" support added
authorDaniel Stenberg <daniel@haxx.se>
Wed, 7 Mar 2001 23:51:41 +0000 (23:51 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 7 Mar 2001 23:51:41 +0000 (23:51 +0000)
lib/http.c
lib/http.h
lib/http_chunks.c
lib/http_chunks.h
lib/transfer.c
lib/urldata.h

index 71ef7aa35b188d6c8b53842328ab5fa9a60132e2..2da7cbf72ebf8c1da66fcde8d071b97fb12f126e 100644 (file)
 #include "memdebug.h"
 #endif
 
+/* ------------------------------------------------------------------------- */
 /*
  * The add_buffer series of functions are used to build one large memory chunk
  * from repeated function invokes. Used so that the entire HTTP request can
@@ -205,7 +206,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
 }
 
 /* end of the add_buffer functions */
-/*****************************************************************************/
+/* ------------------------------------------------------------------------- */
 
 /*
  * Read everything until a newline.
@@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
   return CURLE_OK;
 }
 
+/*
+ * HTTP stuff to do at connect-time.
+ */
 CURLcode Curl_http_connect(struct connectdata *conn)
 {
   struct UrlData *data;
index bfd73b5f6800cbe56e716d7e4d1588270e655726..52ea73b7b4d139c91e504deef5f036a40a53fc7a 100644 (file)
@@ -35,4 +35,9 @@ CURLcode Curl_http_done(struct connectdata *conn);
 CURLcode Curl_http_connect(struct connectdata *conn);
 CURLcode Curl_http_close(struct connectdata *conn);
 
+/* The following functions are defined in http_chunks.c */
+void Curl_httpchunk_init(struct connectdata *conn);
+CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
+                              ssize_t length, ssize_t *wrote);
+
 #endif
index d22de18d16c5e8fcbed361c5d54329f734430116..bbc208e21bb4d4b87427afad92349b5c8f28cea0 100644 (file)
@@ -82,15 +82,15 @@ void Curl_httpchunk_init(struct connectdata *conn)
 {
   struct Curl_chunker *chunk = &conn->proto.http->chunk;
   chunk->hexindex=0; /* start at 0 */
+  chunk->dataleft=0; /* no data left yet! */
   chunk->state = CHUNK_HEX; /* we get hex first! */
 }
 
 /*
- * chunk_read() returns a 0 for normal operations, or a positive return code
- * for errors. A negative number means this sequence of chunks is complete,
- * and that many ~bytes were NOT used at the end of the buffer passed in.
- * The 'wrote' argument is set to tell the caller how many bytes we actually
- * passed to the client (for byte-counting and whatever).
+ * chunk_read() returns a OK for normal operations, or a positive return code
+ * for errors. STOP means this sequence of chunks is complete.  The 'wrote'
+ * argument is set to tell the caller how many bytes we actually passed to the
+ * client (for byte-counting and whatever).
  *
  * The states and the state-machine is further explained in the header file.
  */
@@ -142,7 +142,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
           ch->state = CHUNK_STOP; /* stop reading! */
           if(1 == length) {
             /* This was the final byte, return right now */
-            return ~0;
+            return CHUNKE_STOP;
           }
         }
         else
@@ -179,7 +179,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
       break;
     case CHUNK_STOP:
-      return ~length; /* return the data size left */
+      /* If we arrive here, there is data left in the end of the buffer
+         even if there's no more chunks to read */
+      ch->dataleft = length;
+      return CHUNKE_STOP; /* return stop */
     default:
       return CHUNKE_STATE_ERROR;
     }
index 5869b917376e45cbff343e84f01d94e0d10d3daf..6f7716e430c10ad41aee3b35c1768243fe6da317 100644 (file)
@@ -49,15 +49,19 @@ typedef enum {
      HEX state. */
   CHUNK_DATA,
 
-  /* This is only used to really mark that we're out of the game */
+  /* This is mainly used to really mark that we're out of the game.
+     NOTE: that there's a 'dataleft' field in the struct that will tell how
+     many bytes that were not passed to the client in the end of the last
+     buffer! */
   CHUNK_STOP,
 
   CHUNK_LAST /* never use */
 } ChunkyState;
 
 typedef enum {
-  CHUNKE_OK,
-  CHUNKE_TOO_LONG_HEX,
+  CHUNKE_STOP = -1,
+  CHUNKE_OK = 0,
+  CHUNKE_TOO_LONG_HEX = 1,
   CHUNKE_WRITE_ERROR,
   CHUNKE_STATE_ERROR,
   CHUNKE_LAST
@@ -67,7 +71,8 @@ struct Curl_chunker {
   char hexbuffer[ MAXNUM_SIZE + 1];
   int hexindex;
   ChunkyState state;
-  unsigned long datasize;
+  size_t datasize;
+  size_t dataleft; /* untouched data amount at the end of the last buffer */
 };
 
 #endif
index 5786ce77788e2a5fbef263e978a107ed037fb144..80cdc0968b111a725d2102289db9c0477605e1ed 100644 (file)
@@ -89,6 +89,7 @@
 #include "getpass.h"
 #include "progress.h"
 #include "getdate.h"
+#include "http.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
@@ -390,6 +391,9 @@ _Transfer(struct connectdata *c_conn)
                  * of chunks, and a chunk-data set to zero signals the
                  * end-of-chunks. */
                 conn->bits.chunk = TRUE; /* chunks coming our way */
+
+                /* init our chunky engine */
+                Curl_httpchunk_init(conn);
               }
               else if (strnequal("Content-Range", p, 13)) {
                 if (sscanf (p+13, ": bytes %d-", &offset) ||
@@ -536,8 +540,24 @@ _Transfer(struct connectdata *c_conn)
             if(conn->bits.chunk) {
               /*
                * Bless me father for I have sinned. Here come a chunked
-               * transfer flighing and we need to decode this properly.
-               */
+               * transfer flying and we need to decode this properly.  While
+               * the name says read, this function both reads and writes away
+               * the data. The returned 'nread' holds the number of actual
+               * data it wrote to the client.  */
+              CHUNKcode res =
+                Curl_httpchunk_read(conn, str, nread, &nread);
+
+              if(CHUNKE_OK < res)
+                return CURLE_READ_ERROR;
+              else if(CHUNKE_STOP == res) {
+                /* we're done reading chunks! */
+                keepon &= ~KEEP_READ; /* read no more */
+
+                /* There are now (~res) bytes at the end of the str buffer
+                   that weren't written to the client, but we don't care
+                   about them right now. */
+              }
+              /* If it returned OK, we just keep going */
             }
 
             if(conn->maxdownload &&
@@ -552,9 +572,12 @@ _Transfer(struct connectdata *c_conn)
 
             Curl_pgrsSetDownloadCounter(data, (double)bytecount);
             
-            urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
-            if(urg)
-              return urg;
+            if(! conn->bits.chunk) {
+              /* If this is chunky transfer, it was already written */
+              urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
+              if(urg)
+                return urg;
+            }
 
           } /* if (! header and data to read ) */
         } /* if( read from socket ) */
index 40e9e5c43f4c286eaf8dfb1a026694ebfb1739d2..a0b9d508b923e83794bcca2313f2e9728f653e33 100644 (file)
@@ -79,6 +79,8 @@
 
 #include <curl/curl.h>
 
+#include "http_chunks.h" /* for the structs and enum stuff */
+
 /* Download buffer size, keep it fairly big for speed reasons */
 #define BUFSIZE (1024*50)
 
@@ -167,6 +169,8 @@ struct HTTP {
   struct Form form;
   size_t (*storefread)(char *, size_t , size_t , FILE *);
   FILE *in;
+
+  struct Curl_chunker chunk;
 };
 
 /****************************************************************************