]> granicus.if.org Git - curl/commitdiff
url: provide dead_connection flag in Curl_handler::disconnect
authorKamil Dudka <kdudka@redhat.com>
Fri, 19 Nov 2010 12:43:20 +0000 (13:43 +0100)
committerKamil Dudka <kdudka@redhat.com>
Mon, 6 Dec 2010 13:35:42 +0000 (14:35 +0100)
It helps to prevent a hangup with some FTP servers in case idle session
timeout has exceeded.  But it may be useful also for other protocols
that send any quit message on disconnect.  Currently used by FTP, POP3,
IMAP and SMTP.

14 files changed:
lib/ftp.c
lib/imap.c
lib/multi.c
lib/openldap.c
lib/pop3.c
lib/rtsp.c
lib/rtsp.h
lib/smtp.c
lib/ssh.c
lib/tftp.c
lib/transfer.c
lib/url.c
lib/url.h
lib/urldata.h

index 49e15713856763abfc1a31d2231b3790fd8ab260..8e370c5d2943b993b62e89a2f808289c96a1bb45 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -136,7 +136,7 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done);
 static CURLcode ftp_done(struct connectdata *conn,
                          CURLcode, bool premature);
 static CURLcode ftp_connect(struct connectdata *conn, bool *done);
-static CURLcode ftp_disconnect(struct connectdata *conn);
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
 static CURLcode ftp_nextconnect(struct connectdata *conn);
 static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
 static int ftp_getsock(struct connectdata *conn,
@@ -3840,7 +3840,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
  * Disconnect from an FTP server. Cleanup protocol-specific per-connection
  * resources. BLOCKING.
  */
-static CURLcode ftp_disconnect(struct connectdata *conn)
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
 {
   struct ftp_conn *ftpc= &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
@@ -3852,6 +3852,8 @@ static CURLcode ftp_disconnect(struct connectdata *conn)
      ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
      will try to send the QUIT command, otherwise it will just return.
   */
+  if(dead_connection)
+    ftpc->ctl_valid = FALSE;
 
   /* The FTP session may or may not have been allocated/setup at this point! */
   (void)ftp_quit(conn); /* ignore errors on the QUIT */
index cdadd17135da632fb5a4627a774d9c8c17b8de1a..9c39625b32f97de2574f44b50f2a4a3eb99c59bf 100644 (file)
@@ -100,7 +100,7 @@ static CURLcode imap_do(struct connectdata *conn, bool *done);
 static CURLcode imap_done(struct connectdata *conn,
                           CURLcode, bool premature);
 static CURLcode imap_connect(struct connectdata *conn, bool *done);
-static CURLcode imap_disconnect(struct connectdata *conn);
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection);
 static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
 static int imap_getsock(struct connectdata *conn,
                         curl_socket_t *socks,
@@ -877,13 +877,13 @@ static CURLcode imap_logout(struct connectdata *conn)
  * Disconnect from an IMAP server. Cleanup protocol-specific per-connection
  * resources. BLOCKING.
  */
-static CURLcode imap_disconnect(struct connectdata *conn)
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
 {
   struct imap_conn *imapc= &conn->proto.imapc;
 
   /* The IMAP session may or may not have been allocated/setup at this
      point! */
-  if (imapc->pp.conn)
+  if(!dead_connection && imapc->pp.conn)
     (void)imap_logout(conn); /* ignore errors on the LOGOUT */
 
   Curl_pp_disconnect(&imapc->pp);
index b57724e626f6969dee4dcf6c9ac23112dc2f991d..7be479bd49efd3817237d2cd68d2bd670f95d926 100644 (file)
@@ -1634,7 +1634,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         }
 
         if(disconnect_conn) {
-          Curl_disconnect(easy->easy_conn); /* disconnect properly */
+          /* disconnect properly */
+          Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
 
           /* This is where we make sure that the easy_conn pointer is reset.
              We don't have to do this in every case block above where a
@@ -1759,7 +1760,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
     for(i=0; i< multi->connc->num; i++) {
       if(multi->connc->connects[i] &&
          multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
-        Curl_disconnect(multi->connc->connects[i]);
+        Curl_disconnect(multi->connc->connects[i], /* dead_connection */ FALSE);
         multi->connc->connects[i] = NULL;
       }
     }
@@ -2665,7 +2666,7 @@ static void multi_connc_remove_handle(struct Curl_multi *multi,
           data->state.shared_conn = multi;
         else {
           /* out of memory - so much for graceful shutdown */
-          Curl_disconnect(conn);
+          Curl_disconnect(conn, /* dead_connection */ FALSE);
           multi->connc->connects[i] = NULL;
         }
       }
index e9dcfcc71754dea4472727818a6fd6baf2c7373a..7010da6c224937ee6c151a0d6681a73a2134ab61 100644 (file)
@@ -61,7 +61,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done);
 static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
 static CURLcode ldap_connect(struct connectdata *conn, bool *done);
 static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
-static CURLcode ldap_disconnect(struct connectdata *conn);
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection);
 
 static Curl_recv ldap_recv;
 
@@ -344,9 +344,10 @@ retry:
   return CURLE_OK;
 }
 
-static CURLcode ldap_disconnect(struct connectdata *conn)
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
 {
   ldapconninfo *li = conn->proto.generic;
+  (void) dead_connection;
 
   if (li) {
     if (li->ld) {
index 9609b624967f6a955fd5e4e94cef85f232d12b46..9f6744363be32886bd40c186ffbe980c1b60ffca 100644 (file)
@@ -101,7 +101,7 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done);
 static CURLcode pop3_done(struct connectdata *conn,
                           CURLcode, bool premature);
 static CURLcode pop3_connect(struct connectdata *conn, bool *done);
-static CURLcode pop3_disconnect(struct connectdata *conn);
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection);
 static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
 static int pop3_getsock(struct connectdata *conn,
                         curl_socket_t *socks,
@@ -817,7 +817,7 @@ static CURLcode pop3_quit(struct connectdata *conn)
  * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
  * resources. BLOCKING.
  */
-static CURLcode pop3_disconnect(struct connectdata *conn)
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
 {
   struct pop3_conn *pop3c= &conn->proto.pop3c;
 
@@ -828,7 +828,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn)
 
   /* The POP3 session may or may not have been allocated/setup at this
      point! */
-  if(pop3c->pp.conn)
+  if(!dead_connection && pop3c->pp.conn)
     (void)pop3_quit(conn); /* ignore errors on the LOGOUT */
 
 
index 1254c7389568faa2e3951e70ce1d028b4b0b9961..066e10fe3a7d868d838289bb5f70ca628144f2fd 100644 (file)
@@ -117,7 +117,9 @@ CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done)
   return httpStatus;
 }
 
-CURLcode Curl_rtsp_disconnect(struct connectdata *conn) {
+CURLcode Curl_rtsp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+  (void) dead_connection;
   Curl_safefree(conn->proto.rtspc.rtp_buf);
   return CURLE_OK;
 }
index c3f8bd7496f836436142620525642852a0d093ef..82e07068d535e6b1f33b2fdf457033c02e8bab32 100644 (file)
@@ -43,7 +43,7 @@ CURLcode Curl_rtsp_rtp_readwrite(struct SessionHandle *data,
 CURLcode Curl_rtsp(struct connectdata *conn, bool *done);
 CURLcode Curl_rtsp_done(struct connectdata *conn, CURLcode, bool premature);
 CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done);
-CURLcode Curl_rtsp_disconnect(struct connectdata *conn);
+CURLcode Curl_rtsp_disconnect(struct connectdata *conn, bool dead_connection);
 
 CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
 
index a0082fc79885ba8b41a64d1203f7d0370fff6fbc..82621a42b7c86c952bfa893a007ee905d461f490 100644 (file)
@@ -107,7 +107,7 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done);
 static CURLcode smtp_done(struct connectdata *conn,
                           CURLcode, bool premature);
 static CURLcode smtp_connect(struct connectdata *conn, bool *done);
-static CURLcode smtp_disconnect(struct connectdata *conn);
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection);
 static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
 static int smtp_getsock(struct connectdata *conn,
                         curl_socket_t *socks,
@@ -1310,7 +1310,7 @@ static CURLcode smtp_quit(struct connectdata *conn)
  * Disconnect from an SMTP server. Cleanup protocol-specific per-connection
  * resources. BLOCKING.
  */
-static CURLcode smtp_disconnect(struct connectdata *conn)
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
 {
   struct smtp_conn *smtpc= &conn->proto.smtpc;
 
@@ -1321,7 +1321,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn)
 
   /* The SMTP session may or may not have been allocated/setup at this
      point! */
-  if(smtpc->pp.conn)
+  if(!dead_connection && smtpc->pp.conn)
     (void)smtp_quit(conn); /* ignore errors on the LOGOUT */
 
   Curl_pp_disconnect(&smtpc->pp);
index 81f5f6420f348d6d96b20f810b309c3d274a925c..ffcb48b4216ec50d3766aab238b8a33a7e185faf 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -135,13 +135,13 @@ static CURLcode scp_done(struct connectdata *conn,
                          CURLcode, bool premature);
 static CURLcode scp_doing(struct connectdata *conn,
                           bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn);
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
 
 static CURLcode sftp_done(struct connectdata *conn,
                           CURLcode, bool premature);
 static CURLcode sftp_doing(struct connectdata *conn,
                            bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn);
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection);
 static
 CURLcode sftp_perform(struct connectdata *conn,
                       bool *connected,
@@ -2689,10 +2689,11 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
 /* BLOCKING, but the function is using the state machine so the only reason
    this is still blocking is that the multi interface code has no support for
    disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn)
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
 {
   CURLcode result = CURLE_OK;
   struct ssh_conn *ssh = &conn->proto.sshc;
+  (void) dead_connection;
 
   Curl_safefree(conn->data->state.proto.ssh);
   conn->data->state.proto.ssh = NULL;
@@ -2853,9 +2854,10 @@ static CURLcode sftp_doing(struct connectdata *conn,
 /* BLOCKING, but the function is using the state machine so the only reason
    this is still blocking is that the multi interface code has no support for
    disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn)
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
 {
   CURLcode result = CURLE_OK;
+  (void) dead_connection;
 
   DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
 
index 46ed2a71e7ee77942a15a3c9e2c012af041f2a34..fc741c9412fab6fcfab5fc450c859127b6828c25 100644 (file)
@@ -166,7 +166,7 @@ typedef struct tftp_state_data {
 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
 static CURLcode tftp_connect(struct connectdata *conn, bool *done);
-static CURLcode tftp_disconnect(struct connectdata *conn);
+static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection);
 static CURLcode tftp_do(struct connectdata *conn, bool *done);
 static CURLcode tftp_done(struct connectdata *conn,
                           CURLcode, bool premature);
@@ -925,9 +925,10 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
  * The disconnect callback
  *
  **********************************************************/
-static CURLcode tftp_disconnect(struct connectdata *conn)
+static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
 {
   tftp_state_data_t *state = conn->proto.tftpc;
+  (void) dead_connection;
 
   /* done, free dynamically allocated pkt buffers */
   if(state) {
index ead3a4deb0dd7b55ae9c78b7f37c49ff9f879481..e4e3405d307dcf5ce2189c3ce2c60f4deb62a9dc 100644 (file)
@@ -1959,7 +1959,7 @@ connect_host(struct SessionHandle *data,
       res = Curl_async_resolved(*conn, &protocol_done);
     else
       /* if we can't resolve, we kill this "connection" now */
-      (void)Curl_disconnect(*conn);
+      (void)Curl_disconnect(*conn, /* dead_connection */ FALSE);
   }
 
   return res;
index f1ab21c2d214b988de087273fd339d8dc65e1964..93a56002dab89415f92192b616b73f66189c4225 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -651,7 +651,7 @@ CURLcode Curl_ch_connc(struct SessionHandle *data,
        close handles not in use.
     */
     for(i=newamount; i< c->num; i++)
-      Curl_disconnect(c->connects[i]);
+      Curl_disconnect(c->connects[i], /* dead_connection */ FALSE);
 
     /* If the most recent connection is no longer valid, mark it
        invalid. */
@@ -2587,7 +2587,7 @@ static void conn_free(struct connectdata *conn)
   free(conn); /* free all the connection oriented data */
 }
 
-CURLcode Curl_disconnect(struct connectdata *conn)
+CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
 {
   struct SessionHandle *data;
   if(!conn)
@@ -2647,7 +2647,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
 
   if(conn->handler->disconnect)
     /* This is set if protocol-specific cleanups should be made */
-    conn->handler->disconnect(conn);
+    conn->handler->disconnect(conn, dead_connection);
 
   if(-1 != conn->connectindex) {
     /* unlink ourselves! */
@@ -2915,7 +2915,8 @@ ConnectionExists(struct SessionHandle *data,
         check->data = data;
         infof(data, "Connection #%ld seems to be dead!\n", i);
 
-        Curl_disconnect(check); /* disconnect resources */
+        /* disconnect resources */
+        Curl_disconnect(check, /* dead_connection */ TRUE);
         data->state.connc->connects[i]=NULL; /* nothing here */
 
         continue;
@@ -3102,7 +3103,7 @@ ConnectionKillOne(struct SessionHandle *data)
     conn->data = data;
 
     /* the winner gets the honour of being disconnected */
-    (void)Curl_disconnect(conn);
+    (void)Curl_disconnect(conn, /* dead_connection */ FALSE);
 
     /* clean the array entry */
     data->state.connc->connects[connindex] = NULL;
@@ -5116,7 +5117,7 @@ CURLcode Curl_connect(struct SessionHandle *data,
   if(code && *in_connect) {
     /* We're not allowed to return failure with memory left allocated
        in the connectdata struct, free those here */
-    Curl_disconnect(*in_connect); /* close the connection */
+    Curl_disconnect(*in_connect, FALSE); /* close the connection */
     *in_connect = NULL;           /* return a NULL */
   }
 
@@ -5236,7 +5237,7 @@ CURLcode Curl_done(struct connectdata **connp,
   */
   if(data->set.reuse_forbid || conn->bits.close || premature ||
      (-1 == conn->connectindex)) {
-    CURLcode res2 = Curl_disconnect(conn); /* close the connection */
+    CURLcode res2 = Curl_disconnect(conn, FALSE); /* close the connection */
 
     /* If we had an error already, make sure we return that one. But
        if we got a new error, return that. */
index 63d7f2c4822352ef2bc81f64ba4054f3d98cd80e..241dc28c0936954ae4abf674e4f6f3a28c4d3348 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -42,7 +42,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
 CURLcode Curl_do(struct connectdata **, bool *done);
 CURLcode Curl_do_more(struct connectdata *);
 CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
-CURLcode Curl_disconnect(struct connectdata *);
+CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
 CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
index 62dabebd84bab8d2d0ab6ba6cff9c4d9356482ba..f4f678620c7dbdc402755246b81b6e98f04cf3ff 100644 (file)
@@ -646,9 +646,11 @@ struct Curl_handler {
                          int numsocks);
 
   /* This function *MAY* be set to a protocol-dependent function that is run
-   * by the curl_disconnect(), as a step in the disconnection.
+   * by the curl_disconnect(), as a step in the disconnection.  If the handler
+   * is called because the connection has been considered dead, dead_connection
+   * is set to TRUE.
    */
-  CURLcode (*disconnect)(struct connectdata *);
+  CURLcode (*disconnect)(struct connectdata *, bool dead_connection);
 
   long defport;       /* Default port. */
   long protocol;      /* PROT_* flags concerning the protocol set */