diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index aa43ef9b22da0e0007c713a83a3c701229cc2b12..fd8ccee31ee2edee8e320f5e77b5bdbd437f7949 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -72,6 +72,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
     conn->data->req.protop = prot_save;
     if(CURLE_OK != result)
       return result;
+    Curl_safefree(conn->allocptr.proxyuserpwd);
 #else
     return CURLE_NOT_BUILT_IN;
 #endif
diff --git a/lib/multi.c b/lib/multi.c
index caf51de7710c3fac7f75d37584623f89310eee37..6d21b138d39e21ff7de901c9b8520137455147d3 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -86,6 +86,7 @@ static const char * const statename[]={
   "WAITRESOLVE",
   "WAITCONNECT",
   "WAITPROXYCONNECT",
+  "SENDPROTOCONNECT",
   "PROTOCONNECT",
   "WAITDO",
   "DO",
@@ -646,14 +647,24 @@ static int waitconnect_getsock(struct connectdata *conn,
     }
   }
 
+  return rc;
+}
+
+static int waitproxyconnect_getsock(struct connectdata *conn,
+                                    curl_socket_t *sock,
+                                    int numsocks)
+{
+  if(!numsocks)
+    return GETSOCK_BLANK;
+
+  sock[0] = conn->sock[FIRSTSOCKET];
+
   /* when we've sent a CONNECT to a proxy, we should rather wait for the
      socket to become readable to be able to get the response headers */
-  if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
-    sock[0] = conn->sock[FIRSTSOCKET];
-    rc = GETSOCK_READSOCK(0);
-  }
+  if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+    return GETSOCK_READSOCK(0);
 
-  return rc;
+  return GETSOCK_WRITESOCK(0);
 }
 
 static int domore_getsock(struct connectdata *conn,
@@ -706,6 +717,7 @@ static int multi_getsock(struct SessionHandle *data,
     return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
 
   case CURLM_STATE_PROTOCONNECT:
+  case CURLM_STATE_SENDPROTOCONNECT:
     return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
 
   case CURLM_STATE_DO:
@@ -713,6 +725,8 @@ static int multi_getsock(struct SessionHandle *data,
     return Curl_doing_getsock(data->easy_conn, socks, numsocks);
 
   case CURLM_STATE_WAITPROXYCONNECT:
+    return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
+
   case CURLM_STATE_WAITCONNECT:
     return waitconnect_getsock(data->easy_conn, socks, numsocks);
 
@@ -1164,40 +1178,28 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
       result = Curl_http_connect(data->easy_conn, &protocol_connect);
 
+      rc = CURLM_CALL_MULTI_PERFORM;
       if(data->easy_conn->bits.proxy_connect_closed) {
         /* connect back to proxy again */
         result = CURLE_OK;
-        rc = CURLM_CALL_MULTI_PERFORM;
         multistate(data, CURLM_STATE_CONNECT);
       }
       else if(!result) {
         if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
-          multistate(data, CURLM_STATE_WAITCONNECT);
+          /* initiate protocol connect phase */
+          multistate(data, CURLM_STATE_SENDPROTOCONNECT);
       }
       break;
 #endif
 
     case CURLM_STATE_WAITCONNECT:
-      /* awaiting a completion of an asynch connect */
-      result = Curl_is_connected(data->easy_conn,
-                                 FIRSTSOCKET,
-                                 &connected);
-      if(connected) {
-
-        if(!result)
-          /* if everything is still fine we do the protocol-specific connect
-             setup */
-          result = Curl_protocol_connect(data->easy_conn,
-                                         &protocol_connect);
-      }
-
-      if(data->easy_conn->bits.proxy_connect_closed) {
-        /* connect back to proxy again since it was closed in a proxy CONNECT
-           setup */
-        result = CURLE_OK;
+      /* awaiting a completion of an asynch TCP connect */
+      result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
+      if(connected && !result) {
         rc = CURLM_CALL_MULTI_PERFORM;
-        multistate(data, CURLM_STATE_CONNECT);
-        break;
+        multistate(data, data->easy_conn->bits.tunnel_proxy?
+                   CURLM_STATE_WAITPROXYCONNECT:
+                   CURLM_STATE_SENDPROTOCONNECT);
       }
       else if(result) {
         /* failure detected */
@@ -1205,29 +1207,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         disconnect_conn = TRUE;
         break;
       }
+      break;
 
-      if(connected) {
-        if(!protocol_connect) {
-          /* We have a TCP connection, but 'protocol_connect' may be false
-             and then we continue to 'STATE_PROTOCONNECT'. If protocol
-             connect is TRUE, we move on to STATE_DO.
-             BUT if we are using a proxy we must change to WAITPROXYCONNECT
-          */
-#ifndef CURL_DISABLE_HTTP
-          if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
-            multistate(data, CURLM_STATE_WAITPROXYCONNECT);
-          else
-#endif
-            multistate(data, CURLM_STATE_PROTOCONNECT);
-
-        }
-        else
-          /* after the connect has completed, go WAITDO or DO */
-          multistate(data, multi->pipelining_enabled?
-                     CURLM_STATE_WAITDO:CURLM_STATE_DO);
-
+    case CURLM_STATE_SENDPROTOCONNECT:
+      result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
+      if(!protocol_connect)
+        /* switch to waiting state */
+        multistate(data, CURLM_STATE_PROTOCONNECT);
+      else if(!result) {
+        /* protocol connect has completed, go WAITDO or DO */
+        multistate(data, multi->pipelining_enabled?
+                   CURLM_STATE_WAITDO:CURLM_STATE_DO);
         rc = CURLM_CALL_MULTI_PERFORM;
       }
+      else if(result) {
+        /* failure detected */
+        Curl_posttransfer(data);
+        Curl_done(&data->easy_conn, result, TRUE);
+        disconnect_conn = TRUE;
+      }
       break;
 
     case CURLM_STATE_PROTOCONNECT:
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 1a4b1d96681262dc83a884ef93a1e980f061432d..d8b9d8892cea8e7bee51228863d6827966d9617e 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 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
@@ -35,22 +35,23 @@ typedef enum {
   CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */
   CURLM_STATE_CONNECT,      /* 2 - resolve/connect has been sent off */
   CURLM_STATE_WAITRESOLVE,  /* 3 - awaiting the resolve to finalize */
-  CURLM_STATE_WAITCONNECT,  /* 4 - awaiting the connect to finalize */
+  CURLM_STATE_WAITCONNECT,  /* 4 - awaiting the TCP connect to finalize */
   CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
-  CURLM_STATE_PROTOCONNECT, /* 6 - completing the protocol-specific connect
+  CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
+  CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
                                    phase */
-  CURLM_STATE_WAITDO,       /* 7 - wait for our turn to send the request */
-  CURLM_STATE_DO,           /* 8 - start send off the request (part 1) */
-  CURLM_STATE_DOING,        /* 9 - sending off the request (part 1) */
-  CURLM_STATE_DO_MORE,      /* 10 - send off the request (part 2) */
-  CURLM_STATE_DO_DONE,      /* 11 - done sending off request */
-  CURLM_STATE_WAITPERFORM,  /* 12 - wait for our turn to read the response */
-  CURLM_STATE_PERFORM,      /* 13 - transfer data */
-  CURLM_STATE_TOOFAST,      /* 14 - wait because limit-rate exceeded */
-  CURLM_STATE_DONE,         /* 15 - post data transfer operation */
-  CURLM_STATE_COMPLETED,    /* 16 - operation complete */
-  CURLM_STATE_MSGSENT,      /* 17 - the operation complete message is sent */
-  CURLM_STATE_LAST          /* 18 - not a true state, never use this */
+  CURLM_STATE_WAITDO,       /* 8 - wait for our turn to send the request */
+  CURLM_STATE_DO,           /* 9 - start send off the request (part 1) */
+  CURLM_STATE_DOING,        /* 10 - sending off the request (part 1) */
+  CURLM_STATE_DO_MORE,      /* 11 - send off the request (part 2) */
+  CURLM_STATE_DO_DONE,      /* 12 - done sending off request */
+  CURLM_STATE_WAITPERFORM,  /* 13 - wait for our turn to read the response */
+  CURLM_STATE_PERFORM,      /* 14 - transfer data */
+  CURLM_STATE_TOOFAST,      /* 15 - wait because limit-rate exceeded */
+  CURLM_STATE_DONE,         /* 16 - post data transfer operation */
+  CURLM_STATE_COMPLETED,    /* 17 - operation complete */
+  CURLM_STATE_MSGSENT,      /* 18 - the operation complete message is sent */
+  CURLM_STATE_LAST          /* 19 - not a true state, never use this */
 } CURLMstate;
 
 /* we support N sockets per easy handle. Set the corresponding bit to what