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

- Ravi Pratap provided work on libcurl making pipelining more robust and

  fixing some bugs:
  o Don't mix GET and POST requests in a pipeline
  o Fix the order in which requests are dispatched from the pipeline
  o Fixed several curl bugs with pipelining when the server is returning
    chunked encoding:
    * Added states to chunked parsing for final CRLF
    * Rewind buffer after parsing chunk with data remaining
    * Moved chunked header initializing to a spot just before receiving
      headers
parent 3a634a27
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -6,6 +6,23 @@

                                  Changelog

Daniel (21 February 2007)
- Ravi Pratap provided work on libcurl making pipelining more robust and
  fixing some bugs:
  o Don't mix GET and POST requests in a pipeline
  o Fix the order in which requests are dispatched from the pipeline
  o Fixed several curl bugs with pipelining when the server is returning
    chunked encoding:
    * Added states to chunked parsing for final CRLF
    * Rewind buffer after parsing chunk with data remaining
    * Moved chunked header initializing to a spot just before receiving
      headers

Daniel (20 February 2007)
- Linus Nielsen Feltzing changed the CURLOPT_FTP_SSL_CCC option to handle
  active and passive CCC shutdown and added the --ftp-ssl-ccc-mode command
  line option.

Daniel (19 February 2007)
- Ian Turner fixed the libcurl.m4 macro's support for --with-libcurl.

+4 −2
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ Curl and libcurl 7.16.2

 Public curl release number:               98
 Releases counted from the very beginning: 125
 Available command line options:           116
 Available command line options:           117
 Available curl_easy_setopt() options:     141
 Number of public functions in libcurl:    54
 Amount of public web site mirrors:        39
@@ -32,6 +32,7 @@ This release includes the following bugfixes:
 o libcurl.m4's --with-libcurl is improved
 o curl-config --libs and libcurl.pc no longer list unnecessary dependencies
 o fixed an issue with CCC not working on some servers
 o several HTTP pipelining problems

This release includes the following known bugs:

@@ -50,6 +51,7 @@ advice from friends like these:

 Yang Tse, Manfred Schwarb, Michael Wallner, Jeff Pohlmeyer, Shmulik Regev,
 Rob Crittenden, Robert A. Monat, Dan Fandrich, Duncan Mac-Vicar Prett,
 Michal Marek, Robson Braga Araujo, Ian Turner
 Michal Marek, Robson Braga Araujo, Ian Turner, Linus Nielsen Feltzing,
 Ravi Pratap

        Thanks! (and sorry if I forgot to mention someone)
+57 −15
Original line number Diff line number Diff line
@@ -181,20 +181,25 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        if(0 == ch->datasize) {
          if (conn->bits.trailerHdrPresent!=TRUE) {
            /* No Trailer: header found - revert to original Curl processing */
            ch->state = CHUNK_STOP;
            if (1 == length) {
               /* This is the final byte, return right now */
               return CHUNKE_STOP;
            }
            ch->state = CHUNK_STOPCR;

            /* We need to increment the datap here since we bypass the
               increment below with the immediate break */
            length--;
            datap++;

            /* This is the final byte, continue to read the final CRLF */
            break;
          }
          else {
            ch->state = CHUNK_TRAILER; /* attempt to read trailers */
            conn->trlPos=0;
          }
        }
        else
        else {
          ch->state = CHUNK_DATA;
        }
      }
      else
        /* previously we got a fake CR, go back to CR waiting! */
        ch->state = CHUNK_CR;
@@ -270,8 +275,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        datap++;
        length--;
      }
      else
      else {
        return CHUNKE_BAD_CHUNK;
      }
      break;

    case CHUNK_POSTLF:
@@ -284,8 +290,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        datap++;
        length--;
      }
      else
      else {
        return CHUNKE_BAD_CHUNK;
      }

      break;

    case CHUNK_TRAILER:
@@ -331,7 +339,17 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        conn->trailer[conn->trlPos]=0;
        if (conn->trlPos==2) {
          ch->state = CHUNK_STOP;
          return CHUNKE_STOP;
          datap++;
          length--;

          /*
           * Note that this case skips over the final STOP states since we've
           * already read the final CRLF and need to return
           */

          ch->dataleft = length;

          return CHUNKE_STOP; /* return stop */
        }
        else {
#ifdef CURL_DOES_CONVERSIONS
@@ -358,11 +376,35 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        return CHUNKE_BAD_CHUNK;
      break;

    case CHUNK_STOPCR:
      /* Read the final CRLF that ends all chunk bodies */

      if(*datap == 0x0d) {
        ch->state = CHUNK_STOP;
        datap++;
        length--;
      }
      else {
        return CHUNKE_BAD_CHUNK;
      }
      break;

    case CHUNK_STOP:
      /* If we arrive here, there is data left in the end of the buffer
      if (*datap == 0x0a) {
        datap++;
        length--;

        /* Record the length of any 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 */
      }
      else {
        return CHUNKE_BAD_CHUNK;
      }
      break;

    default:
      return CHUNKE_STATE_ERROR;
    }
+5 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -56,6 +56,10 @@ typedef enum {
     CRLF combination marks the end of a chunk */
  CHUNK_POSTLF,

  /* Each Chunk body should end with a CRLF.  Read a CR and nothing else,
     then move to CHUNK_STOP */
  CHUNK_STOPCR,

  /* 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
+26 −14
Original line number Diff line number Diff line
@@ -354,6 +354,12 @@ CURLM *curl_multi_init(void)
    return NULL;
  }

  /* Let's make the doubly-linked list a circular list.  This makes
     the linked list code simpler and allows inserting at the end
     with less work (we didn't keep a tail pointer before). */
  multi->easy.next = &multi->easy;
  multi->easy.prev = &multi->easy;

  return (CURLM *) multi;
}

@@ -435,18 +441,21 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
  /* Make sure the type is setup correctly */
  easy->easy_handle->state.connc->type = CONNCACHE_MULTI;

  /* We add this new entry first in the list. We make our 'next' point to the
     previous next and our 'prev' point back to the 'first' struct */
  easy->next = multi->easy.next;
  easy->prev = &multi->easy;
  /* This adds the new entry at the back of the list
     to try and maintain a FIFO queue so the pipelined
     requests are in order. */

  /* We add this new entry last in the list. We make our 'next' point to the
     'first' struct and our 'prev' point to the previous 'prev' */
  easy->next = &multi->easy;
  easy->prev = multi->easy.prev;

  /* make 'easy' the first node in the chain */
  multi->easy.next = easy;
  /* make 'easy' the last node in the chain */
  multi->easy.prev = easy;

  /* if there was a next node, make sure its 'prev' pointer links back to
  /* if there was a prev node, make sure its 'next' pointer links to
     the new node */
  if(easy->next)
    easy->next->prev = easy;
  easy->prev->next = easy;

  Curl_easy_addmulti(easy_handle, multi_handle);

@@ -506,7 +515,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,

  /* scan through the list and remove the 'curl_handle' */
  easy = multi->easy.next;
  while(easy) {
  while(easy != &multi->easy) {
    if(easy->easy_handle == (struct SessionHandle *)curl_handle)
      break;
    easy=easy->next;
@@ -726,7 +735,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
    return CURLM_BAD_HANDLE;

  easy=multi->easy.next;
  while(easy) {
  while(easy != &multi->easy) {
    bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);

    for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
@@ -1092,6 +1101,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
                               easy->easy_conn->recv_pipe);
      multistate(easy, CURLM_STATE_WAITPERFORM);
      result = CURLM_CALL_MULTI_PERFORM;

      Curl_pre_readwrite(easy->easy_conn);

      break;

    case CURLM_STATE_WAITPERFORM:
@@ -1313,7 +1325,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
    return CURLM_BAD_HANDLE;

  easy=multi->easy.next;
  while(easy) {
  while(easy != &multi->easy) {
    CURLMcode result;

    if (easy->easy_handle->state.cancelled &&
@@ -1409,7 +1421,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)

    /* remove all easy handles */
    easy = multi->easy.next;
    while(easy) {
    while(easy != &multi->easy) {
      nexteasy=easy->next;
      if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
        /* clear out the usage of the shared DNS cache */
@@ -1588,7 +1600,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
    /* walk through each easy handle and do the socket state change magic
       and callbacks */
    easyp=multi->easy.next;
    while(easyp) {
    while(easyp != &multi->easy) {
      singlesocket(multi, easyp);
      easyp = easyp->next;
    }
Loading