- Armel Asselin improved libcurl to behave a lot better when an easy handle
authorDaniel Stenberg <daniel@haxx.se>
Tue, 16 Jan 2007 22:22:10 +0000 (22:22 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 16 Jan 2007 22:22:10 +0000 (22:22 +0000)
  doing an FTP transfer is removed from a multi handle before completion. The
  fix also fixed the "alive counter" to be correct on "premature removal" for
  all protocols.

19 files changed:
CHANGES
RELEASE-NOTES
lib/file.c
lib/file.h
lib/ftp.c
lib/ftp.h
lib/http.c
lib/http.h
lib/multi.c
lib/ssh.c
lib/ssh.h
lib/telnet.c
lib/telnet.h
lib/tftp.c
lib/tftp.h
lib/transfer.c
lib/url.c
lib/url.h
lib/urldata.h

diff --git a/CHANGES b/CHANGES
index c583790..22d3564 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@
 
                                   Changelog
 
+Daniel (16 January 2007)
+- Armel Asselin improved libcurl to behave a lot better when an easy handle
+  doing an FTP transfer is removed from a multi handle before completion. The
+  fix also fixed the "alive counter" to be correct on "premature removal" for
+  all protocols.
+
 Dan F (16 January 2007)
 - Fixed a small memory leak in tftp uploads discovered by curl's memory leak
   detector.  Also changed tftp downloads to URL-unescape the downloaded
index 5f2ec0a..1aa4c49 100644 (file)
@@ -51,6 +51,8 @@ This release includes the following bugfixes:
  o base64 encoding/decoding works on non-ASCII platforms
  o large file downloads
  o CURLOPT_COOKIELIST set to "ALL" crash
+ o easy handle removal from multi handle before completion
+ o TFTP upload memory leak
 
 Other curl-related news:
 
@@ -71,6 +73,7 @@ advice from friends like these:
  Matt Witherspoon, Alexey Simak, Martin Skinner, Sh Diao, Jared Lundell,
  Stefan Krause, Sebastien Willemijns, Alexey Simak, Brendan Jurd,
  Robson Braga Araujo, David McCreedy, Robert Foreman, Nathanael Nerode,
- Victor Snezhko, Linus Nielsen Feltzing, Toby Peterson
+ Victor Snezhko, Linus Nielsen Feltzing, Toby Peterson, Dan Fandrich, 
+ Armel Asselin
 
         Thanks! (and sorry if I forgot to mention someone)
index 602299d..b247a77 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, 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
@@ -165,7 +165,7 @@ CURLcode Curl_file_connect(struct connectdata *conn)
   file->fd = fd;
   if(!conn->data->set.upload && (fd == -1)) {
     failf(conn->data, "Couldn't open file %s", conn->data->reqdata.path);
-    Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
+    Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
     return CURLE_FILE_COULDNT_READ_FILE;
   }
 
@@ -173,10 +173,11 @@ CURLcode Curl_file_connect(struct connectdata *conn)
 }
 
 CURLcode Curl_file_done(struct connectdata *conn,
-                        CURLcode status)
+                        CURLcode status, bool premature)
 {
   struct FILEPROTO *file = conn->data->reqdata.proto.file;
   (void)status; /* not used */
+  (void)premature; /* not used */
   Curl_safefree(file->freepath);
 
   if(file->fd != -1)
index f78acfe..20a1c4c 100644 (file)
@@ -8,7 +8,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
@@ -25,7 +25,7 @@
  ***************************************************************************/
 #ifndef CURL_DISABLE_FILE
 CURLcode Curl_file(struct connectdata *, bool *done);
-CURLcode Curl_file_done(struct connectdata *, CURLcode);
+CURLcode Curl_file_done(struct connectdata *, CURLcode, bool premature);
 CURLcode Curl_file_connect(struct connectdata *);
 #endif
 #endif
index 4b6139e..900def4 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2964,7 +2964,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
  *
  * Input argument is already checked for validity.
  */
-CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
+CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature)
 {
   struct SessionHandle *data = conn->data;
   struct FTP *ftp = data->reqdata.proto.ftp;
@@ -2998,8 +2998,12 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
     /* the connection stays alive fine even though this happened */
     /* fall-through */
   case CURLE_OK: /* doesn't affect the control connection's status */
-    ftpc->ctl_valid = was_ctl_valid;
-    break;
+    if (!premature) {
+      ftpc->ctl_valid = was_ctl_valid;
+      break;
+    }
+    /* until we cope better with prematurely ended requests, let them 
+     * fallback as if in complete failure */
   default:       /* by default, an error means the control connection is
                     wedged and should not be used anymore */
     ftpc->ctl_valid = FALSE;
@@ -3048,7 +3052,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
 
   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
 
-  if(!ftp->no_transfer && !status) {
+  if(!ftp->no_transfer && !status && !premature) {
     /*
      * Let's see what the server says about the transfer we just performed,
      * but lower the timeout as sometimes this connection has died while the
@@ -3081,7 +3085,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
     }
   }
 
-  if(result)
+  if(result || premature)
     /* the response code from the transfer showed an error already so no
        use checking further */
     ;
@@ -3123,7 +3127,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
   ftpc->dont_check = FALSE;
 
   /* Send any post-transfer QUOTE strings? */
-  if(!status && !result && data->set.postquote)
+  if(!status && !result && !premature && data->set.postquote)
     result = ftp_sendquote(conn, data->set.postquote);
 
   return result;
index c85d89e..2949d32 100644 (file)
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -25,7 +25,7 @@
 
 #ifndef CURL_DISABLE_FTP
 CURLcode Curl_ftp(struct connectdata *conn, bool *done);
-CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
+CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode, bool premature);
 CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_ftp_disconnect(struct connectdata *conn);
 CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
index 0387298..babe3f1 100644 (file)
@@ -1503,11 +1503,12 @@ int Curl_https_getsock(struct connectdata *conn,
  */
 
 CURLcode Curl_http_done(struct connectdata *conn,
-                        CURLcode status)
+                        CURLcode status, bool premature)
 {
   struct SessionHandle *data = conn->data;
   struct HTTP *http =data->reqdata.proto.http;
   struct Curl_transfer_keeper *k = &data->reqdata.keep;
+  (void)premature; /* not used */
 
   /* set the proper values (possibly modified on POST) */
   conn->fread = data->set.fread; /* restore */
index 1c8ee7e..7b4b633 100644 (file)
@@ -35,7 +35,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
 
 /* protocol-specific functions set up to be called by the main engine */
 CURLcode Curl_http(struct connectdata *conn, bool *done);
-CURLcode Curl_http_done(struct connectdata *, CURLcode);
+CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
 CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
 int Curl_https_getsock(struct connectdata *conn,
index 0411cc9..e10f5e4 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, 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
@@ -512,9 +512,11 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
   }
 
   if(easy) {
+    bool premature = easy->state != CURLM_STATE_COMPLETED;
+
     /* If the 'state' is not INIT or COMPLETED, we might need to do something
        nice to put the easy_handle in a good known state when this returns. */
-    if(easy->state != CURLM_STATE_COMPLETED)
+    if(premature)
       /* this handle is "alive" so we need to count down the total number of
          alive connections when this is removed */
       multi->num_alive--;
@@ -547,7 +549,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
 
       /* Curl_done() clears the conn->data field to lose the association
          between the easy handle and the connection */
-      Curl_done(&easy->easy_conn, easy->result);
+      Curl_done(&easy->easy_conn, easy->result, premature);
 
       if(easy->easy_conn)
         /* the connection is still alive, set back the association to enable
@@ -802,7 +804,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       char *gotourl;
       Curl_posttransfer(easy->easy_handle);
 
-      easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
+      easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
       /* We make sure that the pipe broken flag is reset
          because in this case, it isn't an actual break */
       easy->easy_handle->state.pipe_broke = FALSE;
@@ -950,7 +952,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       else if(easy->result) {
         /* failure detected */
         Curl_posttransfer(easy->easy_handle);
-        Curl_done(&easy->easy_conn, easy->result);
+        Curl_done(&easy->easy_conn, easy->result, FALSE);
         Curl_disconnect(easy->easy_conn); /* close the connection */
         easy->easy_conn = NULL;           /* no more connection */
       }
@@ -1017,7 +1019,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         else {
           /* failure detected */
           Curl_posttransfer(easy->easy_handle);
-          Curl_done(&easy->easy_conn, easy->result);
+          Curl_done(&easy->easy_conn, easy->result, FALSE);
           Curl_disconnect(easy->easy_conn); /* close the connection */
           easy->easy_conn = NULL;           /* no more connection */
         }
@@ -1050,7 +1052,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       else {
         /* failure detected */
         Curl_posttransfer(easy->easy_handle);
-        Curl_done(&easy->easy_conn, easy->result);
+        Curl_done(&easy->easy_conn, easy->result, FALSE);
         Curl_disconnect(easy->easy_conn); /* close the connection */
         easy->easy_conn = NULL;           /* no more connection */
       }
@@ -1169,7 +1171,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
         }
         Curl_posttransfer(easy->easy_handle);
-        Curl_done(&easy->easy_conn, easy->result);
+        Curl_done(&easy->easy_conn, easy->result, FALSE);
       }
       else if(TRUE == done) {
         char *newurl;
@@ -1188,7 +1190,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             newurl = easy->easy_handle->reqdata.newurl;
             easy->easy_handle->reqdata.newurl = NULL;
           }
-          easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
+          easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
           if(easy->result == CURLE_OK)
             easy->result = Curl_follow(easy->easy_handle, newurl, retry);
           if(CURLE_OK == easy->result) {
@@ -1224,7 +1226,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
       if (!easy->easy_handle->state.cancelled) {
         /* post-transfer command */
-        easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
+        easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
 
         /* after we have DONE what we're supposed to do, go COMPLETED, and
            it doesn't matter what the Curl_done() returned! */
index ed596be..9d277a3 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
-* Copyright (C) 1998 - 2006, 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
@@ -568,9 +568,11 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
   return res;
 }
 
-CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status)
+CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
+                       bool premature)
 {
   struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
+  (void)premature; /* not used */
 
   Curl_safefree(scp->path);
   scp->path = NULL;
@@ -891,9 +893,11 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
   return res;
 }
 
-CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status)
+CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
+                        bool premature)
 {
   struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
+  (void)premature; /* not used */
 
   Curl_safefree(sftp->path);
   sftp->path = NULL;
index b491a76..d914490 100644 (file)
--- a/lib/ssh.h
+++ b/lib/ssh.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, 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
@@ -29,7 +29,7 @@
 CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done);
 
 CURLcode Curl_scp_do(struct connectdata *conn, bool *done);
-CURLcode Curl_scp_done(struct connectdata *conn, CURLcode);
+CURLcode Curl_scp_done(struct connectdata *conn, CURLcode, bool premature);
 
 ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
                       void *mem, size_t len);
@@ -37,7 +37,7 @@ ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
                       char *mem, size_t len);
 
 CURLcode Curl_sftp_do(struct connectdata *conn, bool *done);
-CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode);
+CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode, bool premature);
 
 ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
                        void *mem, size_t len);
index 14ff11d..97d22b7 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, 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
@@ -1073,10 +1073,11 @@ void telrcv(struct connectdata *conn,
   }
 }
 
-CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status)
+CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status, bool premature)
 {
   struct TELNET *tn = (struct TELNET *)conn->data->reqdata.proto.telnet;
   (void)status; /* unused */
+  (void)premature; /* not used */
 
   curl_slist_free_all(tn->telnet_vars);
 
index bb30f08..693abf3 100644 (file)
@@ -8,7 +8,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
@@ -25,6 +25,6 @@
  ***************************************************************************/
 #ifndef CURL_DISABLE_TELNET
 CURLcode Curl_telnet(struct connectdata *conn, bool *done);
-CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode);
+CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode, bool premature);
 #endif
 #endif
index 6f1dfaa..9ec1a15 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, 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
@@ -77,6 +77,7 @@
 #include "connect.h"
 #include "strerror.h"
 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "url.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
@@ -288,7 +289,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
     }
     /* As RFC3617 describes the separator slash is not actually part of the
     file name so we skip the always-present first letter of the path string. */
-    filename = curl_easy_unescape(data, &state->conn->data->reqdata.path[1], 0, NULL);
+    filename = curl_easy_unescape(data, &state->conn->data->reqdata.path[1], 0,
+                                  NULL);
     snprintf((char *)&state->spacket.data[2],
              TFTP_BLOCKSIZE,
              "%s%c%s%c", filename, '\0',  mode, '\0');
@@ -622,9 +624,11 @@ CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
  * The done callback
  *
  **********************************************************/
-CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status)
+CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status,
+                        bool premature)
 {
   (void)status; /* unused */
+  (void)premature; /* not used */
 
 #if 0
   free(conn->data->reqdata.proto.tftp);
index 1120e26..c712541 100644 (file)
@@ -8,7 +8,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
@@ -26,6 +26,6 @@
 #ifndef CURL_DISABLE_TFTP
 CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_tftp(struct connectdata *conn, bool *done);
-CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode);
+CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode, bool premature);
 #endif
 #endif
index ee3c985..45117c7 100644 (file)
@@ -2303,7 +2303,7 @@ Curl_connect_host(struct SessionHandle *data,
        to the new URL */
     urlchanged = data->change.url_changed;
     if ((CURLE_OK == res) && urlchanged) {
-      res = Curl_done(conn, res);
+      res = Curl_done(conn, res, FALSE);
       if(CURLE_OK == res) {
         char *gotourl = strdup(data->change.url);
         res = Curl_follow(data, gotourl, FALSE);
@@ -2379,7 +2379,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
       if(data->set.connect_only) {
         /* keep connection open for application to use the socket */
         conn->bits.close = FALSE;
-        res = Curl_done(&conn, CURLE_OK);
+        res = Curl_done(&conn, CURLE_OK, FALSE);
         break;
       }
       res = Curl_do(&conn, &do_done);
@@ -2412,14 +2412,14 @@ CURLcode Curl_perform(struct SessionHandle *data)
 
         /* Always run Curl_done(), even if some of the previous calls
            failed, but return the previous (original) error code */
-        res2 = Curl_done(&conn, res);
+        res2 = Curl_done(&conn, res, FALSE);
 
         if(CURLE_OK == res)
           res = res2;
       }
       else
         /* Curl_do() failed, clean up left-overs in the done-call */
-        res2 = Curl_done(&conn, res);
+        res2 = Curl_done(&conn, res, FALSE);
 
       /*
        * Important: 'conn' cannot be used here, since it may have been closed
index 123d75b..91cb57e 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -4087,7 +4087,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
 
 
 CURLcode Curl_done(struct connectdata **connp,
-                   CURLcode status) /* an error if this is called after an
+                   CURLcode status, bool premature) /* an error if this is called after an
                                        error was detected */
 {
   CURLcode result;
@@ -4127,7 +4127,7 @@ CURLcode Curl_done(struct connectdata **connp,
 
   /* this calls the protocol-specific function pointer previously set */
   if(conn->curl_done)
-    result = conn->curl_done(conn, status);
+    result = conn->curl_done(conn, status, premature);
   else
     result = CURLE_OK;
 
@@ -4193,7 +4193,7 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
       infof(data, "Re-used connection seems dead, get a new one\n");
 
       conn->bits.close = TRUE; /* enforce close of this connection */
-      result = Curl_done(&conn, result); /* we are so done with this */
+      result = Curl_done(&conn, result, FALSE); /* we are so done with this */
 
       /* conn may no longer be a good pointer */
 
index b924673..ecbd45f 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -39,7 +39,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
                              bool *protocol_connect);
 CURLcode Curl_do(struct connectdata **, bool *done);
 CURLcode Curl_do_more(struct connectdata *);
-CURLcode Curl_done(struct connectdata **, CURLcode);
+CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
 CURLcode Curl_disconnect(struct connectdata *);
 CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
index e2cc0d1..9537ce3 100644 (file)
@@ -614,7 +614,7 @@ struct Curl_async {
    within the source when we need to cast between data pointers (such as NULL)
    and function pointers. */
 typedef CURLcode (*Curl_do_more_func)(struct connectdata *);
-typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode);
+typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
 
 
 /*