Commit a23db7b7 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

"Transfer-Encoding: chunked" support added

parent f6b6dff4
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@
#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;
+5 −0
Original line number Diff line number Diff line
@@ -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
+10 −7
Original line number Diff line number Diff line
@@ -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;
    }
+9 −4
Original line number Diff line number Diff line
@@ -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
+28 −5
Original line number Diff line number Diff line
@@ -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);
            
            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 ) */
Loading