diff --git a/lib/easy.c b/lib/easy.c
index 041a831b1df752d9add98a88dce42fa3543c9d0d..0ad03f961fdaad852b8a08500fbcac5e4e231075 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -602,9 +602,8 @@ void Curl_easy_addmulti(struct SessionHandle *data,
 
 void Curl_easy_initHandleData(struct SessionHandle *data)
 {
-    memset(&data->req, 0, sizeof(struct SingleRequest));
-
-    data->req.maxdownload = -1;
+  memset(&data->req, 0, sizeof(struct SingleRequest));
+  data->req.maxdownload = -1;
 }
 
 /*
diff --git a/lib/file.c b/lib/file.c
index 038bf42e17b37785b9e5417cec6901623970a0b4..b77757596c879d2a551789322f3ebc87ff1acefd 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
@@ -186,31 +186,16 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
   char *actual_path;
 #endif
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
   real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
   if(!real_path)
     return CURLE_OUT_OF_MEMORY;
 
-  if(!data->state.proto.file) {
-    file = calloc(1, sizeof(struct FILEPROTO));
-    if(!file) {
-      free(real_path);
-      return CURLE_OUT_OF_MEMORY;
-    }
-    data->state.proto.file = file;
-  }
-  else {
-    /* file is not a protocol that can deal with "persistancy" */
-    file = data->state.proto.file;
-    Curl_safefree(file->freepath);
-    file->path = NULL;
-    if(file->fd != -1)
-      close(file->fd);
-    file->fd = -1;
+  file = calloc(1, sizeof(struct FILEPROTO));
+  if(!file) {
+    free(real_path);
+    return CURLE_OUT_OF_MEMORY;
   }
+  data->state.proto.file = file;
 
 #ifdef DOS_FILESYSTEM
   /* If the first character is a slash, and there's
@@ -450,7 +435,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     return file_upload(conn);
 
   /* get the fd from the connection phase */
-  fd = conn->data->state.proto.file->fd;
+  fd = data->state.proto.file->fd;
 
   /* VMS: This only works reliable for STREAMLF files */
   if(-1 != fstat(fd, &statbuf)) {
diff --git a/lib/ftp.c b/lib/ftp.c
index c9b97ddb51376c26a6c763bfb9dfb85ce4dff13a..6a969099249df65d71c8d48dc05776307cc32da2 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -225,7 +225,7 @@ const struct Curl_handler Curl_handler_ftps = {
 
 static const struct Curl_handler Curl_handler_ftp_proxy = {
   "FTP",                                /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -251,7 +251,7 @@ static const struct Curl_handler Curl_handler_ftp_proxy = {
 
 static const struct Curl_handler Curl_handler_ftps_proxy = {
   "FTPS",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -3158,56 +3158,6 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
   return result;
 }
 
-/*
- * Allocate and initialize the struct FTP for the current SessionHandle.  If
- * need be.
- */
-
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
-    defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
-  /* workaround icc 9.1 optimizer issue */
-#pragma optimize("", off)
-#endif
-
-static CURLcode ftp_init(struct connectdata *conn)
-{
-  struct FTP *ftp;
-
-  if(NULL == conn->data->state.proto.ftp) {
-    conn->data->state.proto.ftp = malloc(sizeof(struct FTP));
-    if(NULL == conn->data->state.proto.ftp)
-      return CURLE_OUT_OF_MEMORY;
-  }
-
-  ftp = conn->data->state.proto.ftp;
-
-  /* get some initial data into the ftp struct */
-  ftp->bytecountp = &conn->data->req.bytecount;
-  ftp->transfer = FTPTRANSFER_BODY;
-  ftp->downloadsize = 0;
-
-  /* No need to duplicate user+password, the connectdata struct won't change
-     during a session, but we re-init them here since on subsequent inits
-     since the conn struct may have changed or been replaced.
-  */
-  ftp->user = conn->user;
-  ftp->passwd = conn->passwd;
-  if(isBadFtpString(ftp->user))
-    return CURLE_URL_MALFORMAT;
-  if(isBadFtpString(ftp->passwd))
-    return CURLE_URL_MALFORMAT;
-
-  conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
-
-  return CURLE_OK;
-}
-
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
-    defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
-  /* workaround icc 9.1 optimizer issue */
-#pragma optimize("", on)
-#endif
-
 /*
  * ftp_connect() should do everything that is to be considered a part of
  * the connection phase.
@@ -3225,14 +3175,6 @@ static CURLcode ftp_connect(struct connectdata *conn,
 
   *done = FALSE; /* default to not done yet */
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  result = ftp_init(conn);
-  if(CURLE_OK != result)
-    return result;
-
   /* We always support persistent connections on ftp */
   conn->bits.close = FALSE;
 
@@ -4099,17 +4041,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
   *done = FALSE; /* default to false */
   ftpc->wait_data_conn = FALSE; /* default to no such wait */
 
-  /*
-    Since connections can be re-used between SessionHandles, this might be a
-    connection already existing but on a fresh SessionHandle struct so we must
-    make sure we have a good 'struct FTP' to play with. For new connections,
-    the struct FTP is allocated and setup in the ftp_connect() function.
-  */
-  Curl_reset_reqproto(conn);
-  retcode = ftp_init(conn);
-  if(retcode)
-    return retcode;
-
   if(conn->data->set.wildcardmatch) {
     retcode = wc_statemach(conn);
     if(conn->data->wildcard.state == CURLWC_SKIP ||
@@ -4572,11 +4503,12 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
   return result;
 }
 
-static CURLcode ftp_setup_connection(struct connectdata * conn)
+static CURLcode ftp_setup_connection(struct connectdata *conn)
 {
   struct SessionHandle *data = conn->data;
-  char * type;
+  char *type;
   char command;
+  struct FTP *ftp;
 
   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
     /* Unless we have asked to tunnel ftp operations through the proxy, we
@@ -4592,18 +4524,18 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
       return CURLE_UNSUPPORTED_PROTOCOL;
 #endif
     }
-    /*
-     * We explicitly mark this connection as persistent here as we're doing
-     * FTP over HTTP and thus we accidentally avoid setting this value
-     * otherwise.
-     */
-    conn->bits.close = FALSE;
+    /* set it up as a HTTP connection instead */
+    return conn->handler->setup_connection(conn);
 #else
     failf(data, "FTP over http proxy requires HTTP support built-in!");
     return CURLE_UNSUPPORTED_PROTOCOL;
 #endif
   }
 
+  conn->data->state.proto.ftp =  ftp = malloc(sizeof(struct FTP));
+  if(NULL == ftp)
+    return CURLE_OUT_OF_MEMORY;
+
   data->state.path++;   /* don't include the initial slash */
   data->state.slash_removed = TRUE; /* we've skipped the slash */
 
@@ -4636,6 +4568,24 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
     }
   }
 
+  /* get some initial data into the ftp struct */
+  ftp->bytecountp = &conn->data->req.bytecount;
+  ftp->transfer = FTPTRANSFER_BODY;
+  ftp->downloadsize = 0;
+
+  /* No need to duplicate user+password, the connectdata struct won't change
+     during a session, but we re-init them here since on subsequent inits
+     since the conn struct may have changed or been replaced.
+  */
+  ftp->user = conn->user;
+  ftp->passwd = conn->passwd;
+  if(isBadFtpString(ftp->user))
+    return CURLE_URL_MALFORMAT;
+  if(isBadFtpString(ftp->passwd))
+    return CURLE_URL_MALFORMAT;
+
+  conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
+
   return CURLE_OK;
 }
 
diff --git a/lib/http.c b/lib/http.c
index f4b7a48e7172b28cdfb21d76fa67c4b24aff7397..8913c5a6d40074cb08292227c5452b8d83267a07 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -105,7 +105,7 @@ static int https_getsock(struct connectdata *conn,
  */
 const struct Curl_handler Curl_handler_http = {
   "HTTP",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -129,7 +129,7 @@ const struct Curl_handler Curl_handler_http = {
  */
 const struct Curl_handler Curl_handler_https = {
   "HTTPS",                              /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -149,6 +149,21 @@ const struct Curl_handler Curl_handler_https = {
 #endif
 
 
+CURLcode Curl_http_setup_conn(struct connectdata *conn)
+{
+  /* allocate the HTTP-specific struct for the SessionHandle, only to survive
+     during this request */
+  struct HTTP *http;
+
+  DEBUGASSERT(conn->data->state.proto.http == NULL);
+
+  conn->data->state.proto.http = http = calloc(1, sizeof(struct HTTP));
+  if(!http)
+    return CURLE_OUT_OF_MEMORY;
+
+  return CURLE_OK;
+}
+
 /*
  * checkheaders() checks the linked list of custom HTTP headers for a
  * particular header (prefix).
@@ -1442,6 +1457,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
   if(!premature && /* this check is pointless when DONE is called before the
                       entire operation is complete */
      !conn->bits.retry &&
+     !data->set.connect_only &&
      ((http->readbytecount +
        data->req.headerbytecount -
        data->req.deductheadercount)) <= 0) {
@@ -1655,20 +1671,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      the rest of the request in the PERFORM phase. */
   *done = TRUE;
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  if(!data->state.proto.http) {
-    /* Only allocate this struct if we don't already have it! */
-
-    http = calloc(1, sizeof(struct HTTP));
-    if(!http)
-      return CURLE_OUT_OF_MEMORY;
-    data->state.proto.http = http;
-  }
-  else
-    http = data->state.proto.http;
+  http = data->state.proto.http;
 
   if(!data->state.this_is_a_follow) {
     /* this is not a followed location, get the original host name */
diff --git a/lib/http.h b/lib/http.h
index 7236dd88cacb825c05010e080b85e6d342855442..ad2def81bc7efd4811c0e7785de478581805670d 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
@@ -66,6 +66,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
 CURLcode Curl_http(struct connectdata *conn, bool *done);
 CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
 CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
+CURLcode Curl_http_setup_conn(struct connectdata *conn);
 
 /* The following functions are defined in http_chunks.c */
 void Curl_httpchunk_init(struct connectdata *conn);
diff --git a/lib/imap.c b/lib/imap.c
index 13e9784a4a1bb4b856852661974814be22057fb6..c1dffb41dc55d958e342b619f15013742481d08e 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -163,7 +163,7 @@ const struct Curl_handler Curl_handler_imaps = {
 
 static const struct Curl_handler Curl_handler_imap_proxy = {
   "IMAP",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -188,7 +188,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = {
 
 static const struct Curl_handler Curl_handler_imaps_proxy = {
   "IMAPS",                              /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -1669,13 +1669,11 @@ static CURLcode imap_init(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
-  struct IMAP *imap = data->state.proto.imap;
+  struct IMAP *imap;
 
-  if(!imap) {
-    imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1);
-    if(!imap)
-      result = CURLE_OUT_OF_MEMORY;
-  }
+  imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1);
+  if(!imap)
+    result = CURLE_OUT_OF_MEMORY;
 
   return result;
 }
@@ -1705,15 +1703,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to not done yet */
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  /* Initialise the IMAP layer */
-  result = imap_init(conn);
-  if(result)
-    return result;
-
   /* We always support persistent connections in IMAP */
   conn->bits.close = FALSE;
 
@@ -1891,15 +1880,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to false */
 
-  /* Since connections can be re-used between SessionHandles, there might be a
-     connection already existing but on a fresh SessionHandle struct. As such
-     we make sure we have a good IMAP struct to play with. For new connections
-     the IMAP struct is allocated and setup in the imap_connect() function. */
-  Curl_reset_reqproto(conn);
-  result = imap_init(conn);
-  if(result)
-    return result;
-
   /* Parse the URL path */
   result = imap_parse_url_path(conn);
   if(result)
@@ -2018,6 +1998,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
 {
   struct SessionHandle *data = conn->data;
 
+  /* Initialise the IMAP layer */
+  CURLcode result = imap_init(conn);
+  if(result)
+    return result;
+
   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
     /* Unless we have asked to tunnel IMAP operations through the proxy, we
        switch and use HTTP operations only */
@@ -2033,10 +2018,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
 #endif
     }
 
-    /* We explicitly mark this connection as persistent here as we're doing
-       IMAP over HTTP and thus we accidentally avoid setting this value
-       otherwise */
-    conn->bits.close = FALSE;
+    /* set it up as an HTTP connection instead */
+    return conn->handler->setup_connection(conn);
 #else
     failf(data, "IMAP over http proxy requires HTTP support built-in!");
     return CURLE_UNSUPPORTED_PROTOCOL;
diff --git a/lib/pop3.c b/lib/pop3.c
index 876987f11aacb0c0b7187a2c6ba2e39cb85d6077..813414ebcdb452e9bcd45e96569d209b39a6b7ba 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -163,7 +163,7 @@ const struct Curl_handler Curl_handler_pop3s = {
 
 static const struct Curl_handler Curl_handler_pop3_proxy = {
   "POP3",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -188,7 +188,7 @@ static const struct Curl_handler Curl_handler_pop3_proxy = {
 
 static const struct Curl_handler Curl_handler_pop3s_proxy = {
   "POP3S",                              /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -1395,13 +1395,11 @@ static CURLcode pop3_init(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
-  struct POP3 *pop3 = data->state.proto.pop3;
+  struct POP3 *pop3;
 
-  if(!pop3) {
-    pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1);
-    if(!pop3)
-      result = CURLE_OUT_OF_MEMORY;
-  }
+  pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1);
+  if(!pop3)
+    result = CURLE_OUT_OF_MEMORY;
 
   return result;
 }
@@ -1431,15 +1429,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to not done yet */
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  /* Initialise the POP3 layer */
-  result = pop3_init(conn);
-  if(result)
-    return result;
-
   /* We always support persistent connections in POP3 */
   conn->bits.close = FALSE;
 
@@ -1563,15 +1552,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to false */
 
-  /* Since connections can be re-used between SessionHandles, there might be a
-     connection already existing but on a fresh SessionHandle struct. As such
-     we make sure we have a good POP3 struct to play with. For new connections
-     the POP3 struct is allocated and setup in the pop3_connect() function. */
-  Curl_reset_reqproto(conn);
-  result = pop3_init(conn);
-  if(result)
-    return result;
-
   /* Parse the URL path */
   result = pop3_parse_url_path(conn);
   if(result)
@@ -1685,6 +1665,11 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
 {
   struct SessionHandle *data = conn->data;
 
+  /* Initialise the POP3 layer */
+  CURLcode result = pop3_init(conn);
+  if(result)
+    return result;
+
   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
     /* Unless we have asked to tunnel POP3 operations through the proxy, we
        switch and use HTTP operations only */
@@ -1700,10 +1685,8 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
 #endif
     }
 
-    /* We explicitly mark this connection as persistent here as we're doing
-       POP3 over HTTP and thus we accidentally avoid setting this value
-       otherwise */
-    conn->bits.close = FALSE;
+    /* set it up as an HTTP connection instead */
+    return conn->handler->setup_connection(conn);
 #else
     failf(data, "POP3 over http proxy requires HTTP support built-in!");
     return CURLE_UNSUPPORTED_PROTOCOL;
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 3dc14901b2646d99de840e5f00f16c1d1ee2ebbf..eac12904d463ba8eea8cf2ca2a0ccab053232999 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
@@ -81,6 +81,8 @@ static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
                                    ssize_t *nread,
                                    bool *readmore);
 
+static CURLcode rtsp_setup_connection(struct connectdata *conn);
+
 
 /* this returns the socket to wait for in the DO and DOING state for the multi
    interface and then we're always _sending_ a request and thus we wait for
@@ -104,7 +106,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
  */
 const struct Curl_handler Curl_handler_rtsp = {
   "RTSP",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  rtsp_setup_connection,                /* setup_connection */
   rtsp_do,                              /* do_it */
   rtsp_done,                            /* done */
   ZERO_NULL,                            /* do_more */
@@ -122,6 +124,19 @@ const struct Curl_handler Curl_handler_rtsp = {
   PROTOPT_NONE                          /* flags */
 };
 
+
+static CURLcode rtsp_setup_connection(struct connectdata *conn)
+{
+  struct RTSP *rtsp;
+
+  conn->data->state.proto.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
+  if(!rtsp)
+    return CURLE_OUT_OF_MEMORY;
+
+  return CURLE_OK;
+}
+
+
 /*
  * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
  * want to block the application forever while receiving a stream. Therefore,
@@ -221,7 +236,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   struct SessionHandle *data = conn->data;
   CURLcode result=CURLE_OK;
   Curl_RtspReq rtspreq = data->set.rtspreq;
-  struct RTSP *rtsp;
+  struct RTSP *rtsp = data->state.proto.rtsp;
   struct HTTP *http;
   Curl_send_buffer *req_buffer;
   curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -239,20 +254,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
 
   *done = TRUE;
 
-  Curl_reset_reqproto(conn);
-
-  if(!data->state.proto.rtsp) {
-    /* Only allocate this struct if we don't already have it! */
-
-    rtsp = calloc(1, sizeof(struct RTSP));
-    if(!rtsp)
-      return CURLE_OUT_OF_MEMORY;
-    data->state.proto.rtsp = rtsp;
-  }
-  else {
-    rtsp = data->state.proto.rtsp;
-  }
-
   http = &(rtsp->http_wrapper);
   /* Assert that no one has changed the RTSP struct in an evil way */
   DEBUGASSERT((void *)http == (void *)rtsp);
diff --git a/lib/smtp.c b/lib/smtp.c
index 83fb9ec440363312e3e56b9e8fb8026f8482c864..c1816e824c5aa1f42517320d9a8b00f2331f952d 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -161,7 +161,7 @@ const struct Curl_handler Curl_handler_smtps = {
 
 static const struct Curl_handler Curl_handler_smtp_proxy = {
   "SMTP",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -186,7 +186,7 @@ static const struct Curl_handler Curl_handler_smtp_proxy = {
 
 static const struct Curl_handler Curl_handler_smtps_proxy = {
   "SMTPS",                              /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -1361,13 +1361,11 @@ static CURLcode smtp_init(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
-  struct SMTP *smtp = data->state.proto.smtp;
+  struct SMTP *smtp;
 
-  if(!smtp) {
-    smtp = data->state.proto.smtp = calloc(sizeof(struct SMTP), 1);
-    if(!smtp)
-      result = CURLE_OUT_OF_MEMORY;
-  }
+  smtp = data->state.proto.smtp = calloc(sizeof(struct SMTP), 1);
+  if(!smtp)
+    result = CURLE_OUT_OF_MEMORY;
 
   return result;
 }
@@ -1397,15 +1395,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to not done yet */
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  /* Initialise the SMTP layer */
-  result = smtp_init(conn);
-  if(result)
-    return result;
-
   /* We always support persistent connections in SMTP */
   conn->bits.close = FALSE;
 
@@ -1571,15 +1560,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
 
   *done = FALSE; /* default to false */
 
-  /* Since connections can be re-used between SessionHandles, there might be a
-     connection already existing but on a fresh SessionHandle struct. As such
-     we make sure we have a good SMTP struct to play with. For new connections
-     the SMTP struct is allocated and setup in the smtp_connect() function. */
-  Curl_reset_reqproto(conn);
-  result = smtp_init(conn);
-  if(result)
-    return result;
-
   result = smtp_regular_transfer(conn, done);
 
   return result;
@@ -1687,6 +1667,7 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
 static CURLcode smtp_setup_connection(struct connectdata *conn)
 {
   struct SessionHandle *data = conn->data;
+  CURLcode result;
 
   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
     /* Unless we have asked to tunnel SMTP operations through the proxy, we
@@ -1702,17 +1683,20 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
       return CURLE_UNSUPPORTED_PROTOCOL;
 #endif
     }
+    /* set it up as a HTTP connection instead */
+    return conn->handler->setup_connection(conn);
 
-    /* We explicitly mark this connection as persistent here as we're doing
-       SMTP over HTTP and thus we accidentally avoid setting this value
-       otherwise */
-    conn->bits.close = FALSE;
 #else
     failf(data, "SMTP over http proxy requires HTTP support built-in!");
     return CURLE_UNSUPPORTED_PROTOCOL;
 #endif
   }
 
+  /* Initialise the SMTP layer */
+  result = smtp_init(conn);
+  if(result)
+    return result;
+
   data->state.path++;   /* don't include the initial slash */
 
   return CURLE_OK;
diff --git a/lib/ssh.c b/lib/ssh.c
index 422357be9848085f549c9acad77e53f61993368e..6f0923b52f7307013f4e4a05ef6aeea355621984 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -149,13 +149,15 @@ static int ssh_perform_getsock(const struct connectdata *conn,
                                                        number of sockets */
                                int numsocks);
 
+static CURLcode ssh_setup_connection(struct connectdata *conn);
+
 /*
  * SCP protocol handler.
  */
 
 const struct Curl_handler Curl_handler_scp = {
   "SCP",                                /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  ssh_setup_connection,                 /* setup_connection */
   ssh_do,                               /* do_it */
   scp_done,                             /* done */
   ZERO_NULL,                            /* do_more */
@@ -181,7 +183,7 @@ const struct Curl_handler Curl_handler_scp = {
 
 const struct Curl_handler Curl_handler_sftp = {
   "SFTP",                               /* scheme */
-  ZERO_NULL,                            /* setup_connection */
+  ssh_setup_connection,                 /* setup_connection */
   ssh_do,                               /* do_it */
   sftp_done,                            /* done */
   ZERO_NULL,                            /* do_more */
@@ -200,7 +202,6 @@ const struct Curl_handler Curl_handler_sftp = {
   | PROTOPT_NOURLQUERY                  /* flags */
 };
 
-
 static void
 kbd_callback(const char *name, int name_len, const char *instruction,
              int instruction_len, int num_prompts,
@@ -2689,25 +2690,14 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
 /*
  * SSH setup and connection
  */
-static CURLcode ssh_init(struct connectdata *conn)
+static CURLcode ssh_setup_connection(struct connectdata *conn)
 {
-  struct SessionHandle *data = conn->data;
   struct SSHPROTO *ssh;
-  struct ssh_conn *sshc = &conn->proto.sshc;
-
-  sshc->actualcode = CURLE_OK; /* reset error code */
-  sshc->secondCreateDirs =0;   /* reset the create dir attempt state
-                                  variable */
-
-  if(data->state.proto.ssh)
-    return CURLE_OK;
 
-  ssh = calloc(1, sizeof(struct SSHPROTO));
+  conn->data->state.proto.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
   if(!ssh)
     return CURLE_OUT_OF_MEMORY;
 
-  data->state.proto.ssh = ssh;
-
   return CURLE_OK;
 }
 
@@ -2731,14 +2721,6 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
      function to make the re-use checks properly be able to check this bit. */
   conn->bits.close = FALSE;
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
-  result = ssh_init(conn);
-  if(result)
-    return result;
-
   if(conn->handler->protocol & CURLPROTO_SCP) {
     conn->recv[FIRSTSOCKET] = scp_recv;
     conn->send[FIRSTSOCKET] = scp_send;
@@ -2856,23 +2838,16 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
   CURLcode res;
   bool connected = 0;
   struct SessionHandle *data = conn->data;
+  struct ssh_conn *sshc = &conn->proto.sshc;
 
   *done = FALSE; /* default to false */
 
-  /*
-    Since connections can be re-used between SessionHandles, this might be a
-    connection already existing but on a fresh SessionHandle struct so we must
-    make sure we have a good 'struct SSHPROTO' to play with. For new
-    connections, the struct SSHPROTO is allocated and setup in the
-    ssh_connect() function.
-  */
-  Curl_reset_reqproto(conn);
-  res = ssh_init(conn);
-  if(res)
-    return res;
-
   data->req.size = -1; /* make sure this is unknown at this point */
 
+  sshc->actualcode = CURLE_OK; /* reset error code */
+  sshc->secondCreateDirs =0;   /* reset the create dir attempt state
+                                  variable */
+
   Curl_pgrsSetUploadCounter(data, 0);
   Curl_pgrsSetDownloadCounter(data, 0);
   Curl_pgrsSetUploadSize(data, 0);
diff --git a/lib/tftp.c b/lib/tftp.c
index ef740b856986c99d21eee9c635a4d74d9c04fd40..b582ab31944da9543c3e5a812d763321f0efe2ef 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -947,10 +947,6 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
 
   blksize = TFTP_BLKSIZE_DEFAULT;
 
-  /* If there already is a protocol-specific struct allocated for this
-     sessionhandle, deal with it */
-  Curl_reset_reqproto(conn);
-
   state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
   if(!state)
     return CURLE_OUT_OF_MEMORY;
@@ -1307,14 +1303,6 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
 
   *done = FALSE;
 
-  /*
-    Since connections can be re-used between SessionHandles, this might be a
-    connection already existing but on a fresh SessionHandle struct so we must
-    make sure we have a good 'struct TFTP' to play with. For new connections,
-    the struct TFTP is allocated and setup in the tftp_connect() function.
-  */
-  Curl_reset_reqproto(conn);
-
   if(!conn->proto.tftpc) {
     code = tftp_connect(conn, done);
     if(code)
diff --git a/lib/url.c b/lib/url.c
index 7cec5bccd1b90b7ceb2bf446f9b14e195ad4c7df..246b1429349ffe59a1915f3d353dbe222ed239d9 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -148,6 +148,7 @@ static CURLcode parse_url_login(struct SessionHandle *data,
 static CURLcode parse_login_details(const char *login, const size_t len,
                                     char **userptr, char **passwdptr,
                                     char **optionsptr);
+static void free_connection_internals(struct SessionHandle *data);
 /*
  * Protocol table.
  */
@@ -417,7 +418,8 @@ CURLcode Curl_close(struct SessionHandle *data)
   Curl_safefree(data->state.pathbuffer);
   data->state.path = NULL;
 
-  Curl_safefree(data->state.proto.generic);
+  /* freed here just in case DONE wasn't called */
+  free_connection_internals(data);
 
   /* Close down all open SSL info and sessions */
   Curl_ssl_close_all(data);
@@ -4016,18 +4018,28 @@ static CURLcode setup_range(struct SessionHandle *data)
 }
 
 
-/***************************************************************
-* Setup connection internals specific to the requested protocol.
-* This MUST get called after proxy magic has been figured out.
-***************************************************************/
+/*
+ * setup_connection_internals() -
+ *
+ * Setup connection internals specific to the requested protocol in the
+ * SessionHandle. This is inited and setup before the connection is made but
+ * is about the particular protocol that is to be used.
+ *
+ * This MUST get called after proxy magic has been figured out.
+ */
 static CURLcode setup_connection_internals(struct connectdata *conn)
 {
   const struct Curl_handler * p;
   CURLcode result;
 
-  conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
+  /* in some case in the multi state-machine, we go back to the CONNECT state
+     and then a second (or third or...) call to this function will be made
+     without doing a DISCONNECT or DONE in between (since the connection is
+     yet in place) and therefore this function needs to first make sure
+     there's no lingering previous data allocated. */
+  free_connection_internals(conn->data);
 
-  /* Scan protocol handler table. */
+  conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
 
   /* Perform setup complement if some. */
   p = conn->handler;
@@ -4045,11 +4057,21 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
     /* we check for -1 here since if proxy was detected already, this
        was very likely already set to the proxy port */
     conn->port = p->defport;
-  conn->remote_port = (unsigned short)conn->given->defport;
+
+  /* only if remote_port was not already parsed off the URL we use the
+     default port number */
+  if(!conn->remote_port)
+    conn->remote_port = (unsigned short)conn->given->defport;
 
   return CURLE_OK;
 }
 
+static void free_connection_internals(struct SessionHandle *data)
+{
+  Curl_safefree(data->state.proto.generic);
+}
+
+
 #ifndef CURL_DISABLE_PROXY
 /****************************************************************
 * Checks if the host is in the noproxy list. returns true if it matches
@@ -5217,6 +5239,27 @@ static CURLcode create_conn(struct SessionHandle *data,
 
 #endif /* CURL_DISABLE_PROXY */
 
+  /*************************************************************
+   * If the protocol is using SSL and HTTP proxy is used, we set
+   * the tunnel_proxy bit.
+   *************************************************************/
+  if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
+    conn->bits.tunnel_proxy = TRUE;
+
+  /*************************************************************
+   * Figure out the remote port number and fix it in the URL
+   *************************************************************/
+  result = parse_remote_port(data, conn);
+  if(result != CURLE_OK)
+    return result;
+
+  /* Check for overridden login details and set them accordingly so they
+     they are known when protocol->setup_connection is called! */
+  override_login(data, conn, user, passwd, options);
+  result = set_login(conn, user, passwd, options);
+  if(result != CURLE_OK)
+    return result;
+
   /*************************************************************
    * Setup internals depending on protocol. Needs to be done after
    * we figured out what/if proxy to use.
@@ -5266,32 +5309,12 @@ static CURLcode create_conn(struct SessionHandle *data,
     }
 
     /* since we skip do_init() */
-    Curl_speedinit(data);
+    do_init(conn);
 
     return result;
   }
 #endif
 
-  /*************************************************************
-   * If the protocol is using SSL and HTTP proxy is used, we set
-   * the tunnel_proxy bit.
-   *************************************************************/
-  if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
-    conn->bits.tunnel_proxy = TRUE;
-
-  /*************************************************************
-   * Figure out the remote port number and fix it in the URL
-   *************************************************************/
-  result = parse_remote_port(data, conn);
-  if(result != CURLE_OK)
-    return result;
-
-  /* Check for overridden login details and set them accordingly */
-  override_login(data, conn, user, passwd, options);
-  result = set_login(conn, user, passwd, options);
-  if(result != CURLE_OK)
-    return result;
-
   /* Get a cloned copy of the SSL config situation stored in the
      connection struct. But to get this going nicely, we must first make
      sure that the strings in the master copy are pointing to the correct
@@ -5728,6 +5751,7 @@ CURLcode Curl_done(struct connectdata **connp,
                     this was either closed or handed over to the connection
                     cache here, and therefore cannot be used from this point on
                  */
+  free_connection_internals(data);
 
   return result;
 }
@@ -5861,13 +5885,3 @@ CURLcode Curl_do_more(struct connectdata *conn, int *complete)
   return result;
 }
 
-/* Called on connect, and if there's already a protocol-specific struct
-   allocated for a different connection, this frees it that it can be setup
-   properly later on. */
-void Curl_reset_reqproto(struct connectdata *conn)
-{
-  struct SessionHandle *data = conn->data;
-
-  Curl_safefree(data->state.proto.generic);
-  data->state.proto.generic = NULL;
-}
diff --git a/lib/url.h b/lib/url.h
index c0d9c38dc874808778b5b78b99020291cd2f5b9c..3fc635bdbfe5399880fb4b9fdbe89cfd56b77921 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -65,11 +65,6 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data,
 
 void Curl_close_connections(struct SessionHandle *data);
 
-/* Called on connect, and if there's already a protocol-specific struct
-   allocated for a different connection, this frees it that it can be setup
-   properly later on. */
-void Curl_reset_reqproto(struct connectdata *conn);
-
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
 #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
                                                      service */
diff --git a/lib/urldata.h b/lib/urldata.h
index d597c67448b65a5bb86c2d3d5b3db4bbfa891db2..7c150a55c8c14095a430f06f1108a0be2b3e0f62 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1277,9 +1277,10 @@ struct UrlState {
   /* Protocol specific data.
    *
    *************************************************************************
-   * Note that this data will be REMOVED after each request, so anything that
-   * should be kept/stored on a per-connection basis and thus live for the
-   * next request on the same connection MUST be put in the connectdata struct!
+   * Note that this data will be freed after each request is DONE, so anything
+   * that should be kept/stored on a per-connection basis and thus live for
+   * the next request on the same connection MUST be put in the connectdata
+   * struct!
    *************************************************************************/
   union {
     struct HTTP *http;