"Transfer-Encoding: chunked" support added

This commit is contained in:
Daniel Stenberg 2001-03-07 23:51:41 +00:00
parent f6b6dff46a
commit a23db7b7c7
6 changed files with 61 additions and 17 deletions

View File

@ -104,6 +104,7 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/* ------------------------------------------------------------------------- */
/* /*
* The add_buffer series of functions are used to build one large memory chunk * 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 * 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 */ /* end of the add_buffer functions */
/*****************************************************************************/ /* ------------------------------------------------------------------------- */
/* /*
* Read everything until a newline. * Read everything until a newline.
@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/*
* HTTP stuff to do at connect-time.
*/
CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_connect(struct connectdata *conn)
{ {
struct UrlData *data; struct UrlData *data;

View File

@ -35,4 +35,9 @@ CURLcode Curl_http_done(struct connectdata *conn);
CURLcode Curl_http_connect(struct connectdata *conn); CURLcode Curl_http_connect(struct connectdata *conn);
CURLcode Curl_http_close(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 #endif

View File

@ -82,15 +82,15 @@ void Curl_httpchunk_init(struct connectdata *conn)
{ {
struct Curl_chunker *chunk = &conn->proto.http->chunk; struct Curl_chunker *chunk = &conn->proto.http->chunk;
chunk->hexindex=0; /* start at 0 */ chunk->hexindex=0; /* start at 0 */
chunk->dataleft=0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */ chunk->state = CHUNK_HEX; /* we get hex first! */
} }
/* /*
* chunk_read() returns a 0 for normal operations, or a positive return code * chunk_read() returns a OK for normal operations, or a positive return code
* for errors. A negative number means this sequence of chunks is complete, * for errors. STOP means this sequence of chunks is complete. The 'wrote'
* and that many ~bytes were NOT used at the end of the buffer passed in. * argument is set to tell the caller how many bytes we actually passed to the
* The 'wrote' argument is set to tell the caller how many bytes we actually * client (for byte-counting and whatever).
* passed to the client (for byte-counting and whatever).
* *
* The states and the state-machine is further explained in the header file. * 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! */ ch->state = CHUNK_STOP; /* stop reading! */
if(1 == length) { if(1 == length) {
/* This was the final byte, return right now */ /* This was the final byte, return right now */
return ~0; return CHUNKE_STOP;
} }
} }
else else
@ -179,7 +179,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
break; break;
case CHUNK_STOP: 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: default:
return CHUNKE_STATE_ERROR; return CHUNKE_STATE_ERROR;
} }

View File

@ -49,15 +49,19 @@ typedef enum {
HEX state. */ HEX state. */
CHUNK_DATA, 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_STOP,
CHUNK_LAST /* never use */ CHUNK_LAST /* never use */
} ChunkyState; } ChunkyState;
typedef enum { typedef enum {
CHUNKE_OK, CHUNKE_STOP = -1,
CHUNKE_TOO_LONG_HEX, CHUNKE_OK = 0,
CHUNKE_TOO_LONG_HEX = 1,
CHUNKE_WRITE_ERROR, CHUNKE_WRITE_ERROR,
CHUNKE_STATE_ERROR, CHUNKE_STATE_ERROR,
CHUNKE_LAST CHUNKE_LAST
@ -67,7 +71,8 @@ struct Curl_chunker {
char hexbuffer[ MAXNUM_SIZE + 1]; char hexbuffer[ MAXNUM_SIZE + 1];
int hexindex; int hexindex;
ChunkyState state; ChunkyState state;
unsigned long datasize; size_t datasize;
size_t dataleft; /* untouched data amount at the end of the last buffer */
}; };
#endif #endif

View File

@ -89,6 +89,7 @@
#include "getpass.h" #include "getpass.h"
#include "progress.h" #include "progress.h"
#include "getdate.h" #include "getdate.h"
#include "http.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@ -390,6 +391,9 @@ _Transfer(struct connectdata *c_conn)
* of chunks, and a chunk-data set to zero signals the * of chunks, and a chunk-data set to zero signals the
* end-of-chunks. */ * end-of-chunks. */
conn->bits.chunk = TRUE; /* chunks coming our way */ conn->bits.chunk = TRUE; /* chunks coming our way */
/* init our chunky engine */
Curl_httpchunk_init(conn);
} }
else if (strnequal("Content-Range", p, 13)) { else if (strnequal("Content-Range", p, 13)) {
if (sscanf (p+13, ": bytes %d-", &offset) || if (sscanf (p+13, ": bytes %d-", &offset) ||
@ -536,8 +540,24 @@ _Transfer(struct connectdata *c_conn)
if(conn->bits.chunk) { if(conn->bits.chunk) {
/* /*
* Bless me father for I have sinned. Here come a chunked * 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 && if(conn->maxdownload &&
@ -552,9 +572,12 @@ _Transfer(struct connectdata *c_conn)
Curl_pgrsSetDownloadCounter(data, (double)bytecount); Curl_pgrsSetDownloadCounter(data, (double)bytecount);
urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread); if(! conn->bits.chunk) {
if(urg) /* If this is chunky transfer, it was already written */
return urg; urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
if(urg)
return urg;
}
} /* if (! header and data to read ) */ } /* if (! header and data to read ) */
} /* if( read from socket ) */ } /* if( read from socket ) */

View File

@ -79,6 +79,8 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "http_chunks.h" /* for the structs and enum stuff */
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50) #define BUFSIZE (1024*50)
@ -167,6 +169,8 @@ struct HTTP {
struct Form form; struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *); size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in; FILE *in;
struct Curl_chunker chunk;
}; };
/**************************************************************************** /****************************************************************************