diff -ur curl-7.16.1/lib/http.c mycurl-7.16.1/lib/http.c
--- curl-7.16.1/lib/http.c	2007-01-29 09:26:37.000000000 +0000
+++ mycurl-7.16.1/lib/http.c	2007-02-13 15:44:21.000000000 +0000
@@ -1115,17 +1115,9 @@
   struct Curl_transfer_keeper *k = &data->reqdata.keep;
   CURLcode result;
   int res;
-  size_t nread;   /* total size read */
-  int perline; /* count bytes per line */
-  int keepon=TRUE;
-  ssize_t gotbytes;
-  char *ptr;
   long timeout =
     data->set.timeout?data->set.timeout:3600; /* in seconds */
-  char *line_start;
-  char *host_port;
   curl_socket_t tunnelsocket = conn->sock[sockindex];
-  send_buffer *req_buffer;
   curl_off_t cl=0;
   bool closeConnection = FALSE;
 
@@ -1134,239 +1126,290 @@
 #define SELECT_TIMEOUT 2
   int error = SELECT_OK;
 
-  infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
   conn->bits.proxy_connect_closed = FALSE;
 
   do {
-    if(data->reqdata.newurl) {
-      /* This only happens if we've looped here due to authentication reasons,
-         and we don't really use the newly cloned URL here then. Just free()
-         it. */
-      free(data->reqdata.newurl);
-      data->reqdata.newurl = NULL;
-    }
-
-    /* initialize a dynamic send-buffer */
-    req_buffer = add_buffer_init();
-
-    if(!req_buffer)
-      return CURLE_OUT_OF_MEMORY;
-
-    host_port = aprintf("%s:%d", hostname, remote_port);
-    if(!host_port)
-      return CURLE_OUT_OF_MEMORY;
-
-    /* Setup the proxy-authorization header, if any */
-    result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
+    if (!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
+      char *host_port;
+      send_buffer *req_buffer;
+ 
+      infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
+
+      if(data->reqdata.newurl) {
+	/* This only happens if we've looped here due to authentication reasons,
+	   and we don't really use the newly cloned URL here then. Just free()
+	   it. */
+	free(data->reqdata.newurl);
+	data->reqdata.newurl = NULL;
+      }
+
+      /* initialize a dynamic send-buffer */
+      req_buffer = add_buffer_init();
+
+      if(!req_buffer)
+	return CURLE_OUT_OF_MEMORY;
+
+      host_port = aprintf("%s:%d", hostname, remote_port);
+      if(!host_port)
+	return CURLE_OUT_OF_MEMORY;
 
-    if(CURLE_OK == result) {
-      char *host=(char *)"";
-      const char *proxyconn="";
-      const char *useragent="";
-
-      if(!checkheaders(data, "Host:")) {
-        host = aprintf("Host: %s\r\n", host_port);
-        if(!host)
-          result = CURLE_OUT_OF_MEMORY;
-      }
-      if(!checkheaders(data, "Proxy-Connection:"))
-        proxyconn = "Proxy-Connection: Keep-Alive\r\n";
-
-      if(!checkheaders(data, "User-Agent:") && data->set.useragent)
-        useragent = conn->allocptr.uagent;
+      /* Setup the proxy-authorization header, if any */
+      result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
 
       if(CURLE_OK == result) {
-        /* Send the connect request to the proxy */
-        /* BLOCKING */
-        result =
-          add_bufferf(req_buffer,
-                      "CONNECT %s:%d HTTP/1.0\r\n"
-                      "%s"  /* Host: */
-                      "%s"  /* Proxy-Authorization */
-                      "%s"  /* User-Agent */
-                      "%s", /* Proxy-Connection */
-                      hostname, remote_port,
-                      host,
-                      conn->allocptr.proxyuserpwd?
-                      conn->allocptr.proxyuserpwd:"",
-                      useragent,
-                      proxyconn);
-
-        if(CURLE_OK == result)
-          result = add_custom_headers(conn, req_buffer);
-
-        if(host && *host)
-          free(host);
-
-        if(CURLE_OK == result)
-          /* CRLF terminate the request */
-          result = add_bufferf(req_buffer, "\r\n");
-
-        if(CURLE_OK == result)
-          /* Now send off the request */
-          result = add_buffer_send(req_buffer, conn,
-                                   &data->info.request_size, 0, sockindex);
+	char *host=(char *)"";
+	const char *proxyconn="";
+	const char *useragent="";
+
+	if(!checkheaders(data, "Host:")) {
+	  host = aprintf("Host: %s\r\n", host_port);
+	  if(!host)
+	    result = CURLE_OUT_OF_MEMORY;
+	}
+	if(!checkheaders(data, "Proxy-Connection:"))
+	  proxyconn = "Proxy-Connection: Keep-Alive\r\n";
+
+	if(!checkheaders(data, "User-Agent:") && data->set.useragent)
+	  useragent = conn->allocptr.uagent;
+
+	if(CURLE_OK == result) {
+	  /* Send the connect request to the proxy */
+	  /* BLOCKING */
+	  result =
+	    add_bufferf(req_buffer,
+			"CONNECT %s:%d HTTP/1.0\r\n"
+			"%s"  /* Host: */
+			"%s"  /* Proxy-Authorization */
+			"%s"  /* User-Agent */
+			"%s", /* Proxy-Connection */
+			hostname, remote_port,
+			host,
+			conn->allocptr.proxyuserpwd?
+			conn->allocptr.proxyuserpwd:"",
+			useragent,
+			proxyconn);
+
+	  if(CURLE_OK == result)
+	    result = add_custom_headers(conn, req_buffer);
+
+	  if(host && *host)
+	    free(host);
+
+	  if(CURLE_OK == result)
+	    /* CRLF terminate the request */
+	    result = add_bufferf(req_buffer, "\r\n");
+
+	  if(CURLE_OK == result)
+	    /* Now send off the request */
+	    result = add_buffer_send(req_buffer, conn,
+				     &data->info.request_size, 0, sockindex);
+	}
+	if(result)
+	  failf(data, "Failed sending CONNECT to proxy");
       }
+      free(host_port);
       if(result)
-        failf(data, "Failed sending CONNECT to proxy");
-    }
-    free(host_port);
-    if(result)
-      return result;
-
-    ptr=data->state.buffer;
-    line_start = ptr;
-
-    nread=0;
-    perline=0;
-    keepon=TRUE;
-
-    while((nread<BUFSIZE) && (keepon && !error)) {
-
-      /* if timeout is requested, find out how much remaining time we have */
-      long check = timeout - /* timeout time */
-        Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
-      if(check <=0 ) {
-        failf(data, "Proxy CONNECT aborted due to timeout");
-        error = SELECT_TIMEOUT; /* already too little time */
-        break;
-      }
-
-      /* timeout each second and check the timeout */
-      switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, 1000)) {
-      case -1: /* select() error, stop reading */
-        error = SELECT_ERROR;
-        failf(data, "Proxy CONNECT aborted due to select() error");
-        break;
-      case 0: /* timeout */
-        break;
-      default:
-        res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
-        if(res< 0)
-          /* EWOULDBLOCK */
-          continue; /* go loop yourself */
-        else if(res)
-          keepon = FALSE;
-        else if(gotbytes <= 0) {
-          keepon = FALSE;
-          error = SELECT_ERROR;
-          failf(data, "Proxy CONNECT aborted");
-        }
-        else {
-          /*
-           * We got a whole chunk of data, which can be anything from one byte
-           * to a set of lines and possibly just a piece of the last line.
-           */
-          int i;
-
-          nread += gotbytes;
-
-          if(keepon > TRUE) {
-            /* This means we are currently ignoring a response-body, so we
-               simply count down our counter and make sure to break out of the
-               loop when we're done! */
-            cl -= gotbytes;
-            if(cl<=0) {
-              keepon = FALSE;
-              break;
-            }
-          }
-          else
-          for(i = 0; i < gotbytes; ptr++, i++) {
-            perline++; /* amount of bytes in this line so far */
-            if(*ptr=='\n') {
-              char letter;
-              int writetype;
-
-              /* output debug if that is requested */
-              if(data->set.verbose)
-                Curl_debug(data, CURLINFO_HEADER_IN,
-                           line_start, (size_t)perline, conn);
-
-              /* send the header to the callback */
-              writetype = CLIENTWRITE_HEADER;
-              if(data->set.include_header)
-                writetype |= CLIENTWRITE_BODY;
-
-              result = Curl_client_write(conn, writetype, line_start, perline);
-              if(result)
-                return result;
+	return result;
 
-              /* Newlines are CRLF, so the CR is ignored as the line isn't
-                 really terminated until the LF comes. Treat a following CR
-                 as end-of-headers as well.*/
-
-              if(('\r' == line_start[0]) ||
-                 ('\n' == line_start[0])) {
-                /* end of response-headers from the proxy */
-                if(cl && (407 == k->httpcode) && !data->state.authproblem) {
-                  /* If we get a 407 response code with content length when we
-                   * have no auth problem, we must ignore the whole
-                   * response-body */
-                  keepon = 2;
-                  infof(data, "Ignore %" FORMAT_OFF_T
-                        " bytes of response-body\n", cl);
-                  cl -= (gotbytes - i);/* remove the remaining chunk of what
-                                          we already read */
-                  if(cl<=0)
-                    /* if the whole thing was already read, we are done! */
-                    keepon=FALSE;
-                }
-                else
-                  keepon = FALSE;
-                break; /* breaks out of for-loop, not switch() */
-              }
-
-              /* keep a backup of the position we are about to blank */
-              letter = line_start[perline];
-              line_start[perline]=0; /* zero terminate the buffer */
-              if((checkprefix("WWW-Authenticate:", line_start) &&
-                  (401 == k->httpcode)) ||
-                 (checkprefix("Proxy-authenticate:", line_start) &&
-                  (407 == k->httpcode))) {
-                result = Curl_http_input_auth(conn, k->httpcode, line_start);
-                if(result)
-                  return result;
-              }
-              else if(checkprefix("Content-Length:", line_start)) {
-                cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
-                                     NULL, 10);
-              }
-              else if(Curl_compareheader(line_start,
-                                         "Connection:", "close"))
-                closeConnection = TRUE;
-              else if(2 == sscanf(line_start, "HTTP/1.%d %d",
-                                  &subversion,
-                                  &k->httpcode)) {
-                /* store the HTTP code from the proxy */
-                data->info.httpproxycode = k->httpcode;
-              }
-              /* put back the letter we blanked out before */
-              line_start[perline]= letter;
+      conn->bits.tunnel_connecting = TRUE;
+    } /* END CONNECT PHASE */
 
-              perline=0; /* line starts over here */
-              line_start = ptr+1; /* this skips the zero byte we wrote */
-            }
-          }
-        }
-        break;
-      } /* switch */
-    } /* while there's buffer left and loop is requested */
-
-    if(error)
-      return CURLE_RECV_ERROR;
-
-    if(data->info.httpproxycode != 200)
-      /* Deal with the possibly already received authenticate
-         headers. 'newurl' is set to a new URL if we must loop. */
-      Curl_http_auth_act(conn);
-
-    if (closeConnection && data->reqdata.newurl) {
-      /* Connection closed by server. Don't use it anymore */
-      sclose(conn->sock[sockindex]);
-      conn->sock[sockindex] = CURL_SOCKET_BAD;
+    /* now we've issued the CONNECT and we're waiting to hear back -
+       we try not to block here in multi-mode because that might be a LONG
+       wait if the proxy cannot connect-through to the remote host. */
+
+    /* if timeout is requested, find out how much remaining time we have */
+    long check = timeout - /* timeout time */
+      Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
+    if(check <=0 ) {
+      failf(data, "Proxy CONNECT aborted due to timeout");
+      error = SELECT_TIMEOUT; /* already too little time */
       break;
     }
+
+    /* if we're in multi-mode and we would block, return instead for a retry */
+    if (Curl_if_multi == data->state.used_interface) {
+      if (0 == Curl_select(tunnelsocket, CURL_SOCKET_BAD, 0)) {
+        /* return so we'll be called again polling-style */
+	return CURLE_OK;
+      } else {
+        infof(data,
+	      "Multi mode finished polling for response from proxy CONNECT.");
+      }
+    } else {
+        infof(data, "Easy mode waiting for response from proxy CONNECT.");
+    }
+
+    /* at this point, either:
+       1) we're in easy-mode and so it's okay to block waiting for a CONNECT
+          response
+       2) we're in multi-mode and we didn't block - it's either an error or we
+          now have some data waiting.
+       In any case, the tunnel_connecting phase is over. */
+    conn->bits.tunnel_connecting = FALSE;
+
+    { /* BEGIN NEGOTIATION PHASE */
+      size_t nread;   /* total size read */
+      int perline; /* count bytes per line */
+      int keepon=TRUE;
+      ssize_t gotbytes;
+      char *ptr;
+      char *line_start;
+
+      ptr=data->state.buffer;
+      line_start = ptr;
+
+      nread=0;
+      perline=0;
+      keepon=TRUE;
+
+      while((nread<BUFSIZE) && (keepon && !error)) {
+
+	/* if timeout is requested, find out how much remaining time we have */
+	long check = timeout - /* timeout time */
+	  Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
+	if(check <=0 ) {
+	  failf(data, "Proxy CONNECT aborted due to timeout");
+	  error = SELECT_TIMEOUT; /* already too little time */
+	  break;
+	}
+
+	/* timeout each second and check the timeout */
+	switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, 1000)) {
+	case -1: /* select() error, stop reading */
+	  error = SELECT_ERROR;
+	  failf(data, "Proxy CONNECT aborted due to select() error");
+	  break;
+	case 0: /* timeout */
+	  break;
+	default:
+	  res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
+	  if(res< 0)
+	    /* EWOULDBLOCK */
+	    continue; /* go loop yourself */
+	  else if(res)
+	    keepon = FALSE;
+	  else if(gotbytes <= 0) {
+	    keepon = FALSE;
+	    error = SELECT_ERROR;
+	    failf(data, "Proxy CONNECT aborted");
+	  }
+	  else {
+	    /*
+	     * We got a whole chunk of data, which can be anything from one byte
+	     * to a set of lines and possibly just a piece of the last line.
+	     */
+	    int i;
+
+	    nread += gotbytes;
+
+	    if(keepon > TRUE) {
+	      /* This means we are currently ignoring a response-body, so we
+		 simply count down our counter and make sure to break out of the
+		 loop when we're done! */
+	      cl -= gotbytes;
+	      if(cl<=0) {
+		keepon = FALSE;
+		break;
+	      }
+	    }
+	    else
+	      for(i = 0; i < gotbytes; ptr++, i++) {
+		perline++; /* amount of bytes in this line so far */
+		if(*ptr=='\n') {
+		  char letter;
+		  int writetype;
+
+		  /* output debug if that is requested */
+		  if(data->set.verbose)
+		    Curl_debug(data, CURLINFO_HEADER_IN,
+			       line_start, (size_t)perline, conn);
+
+		  /* send the header to the callback */
+		  writetype = CLIENTWRITE_HEADER;
+		  if(data->set.include_header)
+		    writetype |= CLIENTWRITE_BODY;
+
+		  result = Curl_client_write(conn, writetype, line_start, perline);
+		  if(result)
+		    return result;
+
+		  /* Newlines are CRLF, so the CR is ignored as the line isn't
+		     really terminated until the LF comes. Treat a following CR
+		     as end-of-headers as well.*/
+
+		  if(('\r' == line_start[0]) ||
+		     ('\n' == line_start[0])) {
+		    /* end of response-headers from the proxy */
+		    if(cl && (407 == k->httpcode) && !data->state.authproblem) {
+		      /* If we get a 407 response code with content length when we
+		       * have no auth problem, we must ignore the whole
+		       * response-body */
+		      keepon = 2;
+		      infof(data, "Ignore %" FORMAT_OFF_T
+			    " bytes of response-body\n", cl);
+		      cl -= (gotbytes - i);/* remove the remaining chunk of what
+					      we already read */
+		      if(cl<=0)
+			/* if the whole thing was already read, we are done! */
+			keepon=FALSE;
+		    }
+		    else
+		      keepon = FALSE;
+		    break; /* breaks out of for-loop, not switch() */
+		  }
+
+		  /* keep a backup of the position we are about to blank */
+		  letter = line_start[perline];
+		  line_start[perline]=0; /* zero terminate the buffer */
+		  if((checkprefix("WWW-Authenticate:", line_start) &&
+		      (401 == k->httpcode)) ||
+		     (checkprefix("Proxy-authenticate:", line_start) &&
+		      (407 == k->httpcode))) {
+		    result = Curl_http_input_auth(conn, k->httpcode, line_start);
+		    if(result)
+		      return result;
+		  }
+		  else if(checkprefix("Content-Length:", line_start)) {
+		    cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
+					 NULL, 10);
+		  }
+		  else if(Curl_compareheader(line_start,
+					     "Connection:", "close"))
+		    closeConnection = TRUE;
+		  else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+				      &subversion,
+				      &k->httpcode)) {
+		    /* store the HTTP code from the proxy */
+		    data->info.httpproxycode = k->httpcode;
+		  }
+		  /* put back the letter we blanked out before */
+		  line_start[perline]= letter;
+
+		  perline=0; /* line starts over here */
+		  line_start = ptr+1; /* this skips the zero byte we wrote */
+		}
+	      }
+	  }
+	  break;
+	} /* switch */
+      } /* while there's buffer left and loop is requested */
+
+      if(error)
+	return CURLE_RECV_ERROR;
+
+      if(data->info.httpproxycode != 200)
+	/* Deal with the possibly already received authenticate
+	   headers. 'newurl' is set to a new URL if we must loop. */
+	Curl_http_auth_act(conn);
+
+      if (closeConnection && data->reqdata.newurl) {
+	/* Connection closed by server. Don't use it anymore */
+	sclose(conn->sock[sockindex]);
+	conn->sock[sockindex] = CURL_SOCKET_BAD;
+	break;
+      }
+    } /* END NEGOTIATION PHASE */
   } while(data->reqdata.newurl);
 
   if(200 != k->httpcode) {
@@ -1418,6 +1461,11 @@
       return result;
   }
 
+  if (conn->bits.tunnel_connecting) {
+    /* nothing else to do except wait right now - we're not done here. */
+    return CURLE_OK;
+  }
+
   if(!data->state.this_is_a_follow) {
     /* this is not a followed location, get the original host name */
     if (data->state.first_host)
Only in mycurl-7.16.1/lib: http.c.orig
Only in mycurl-7.16.1/lib: http.c.rej
diff -ur curl-7.16.1/lib/multi.c mycurl-7.16.1/lib/multi.c
--- curl-7.16.1/lib/multi.c	2007-01-27 21:22:02.000000000 +0000
+++ mycurl-7.16.1/lib/multi.c	2007-02-13 15:47:03.000000000 +0000
@@ -62,6 +62,7 @@
   CURLM_STATE_CONNECT,     /* resolve/connect has been sent off */
   CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
   CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
+  CURLM_STATE_WAITPROXYCONNECT, /* awaiting the proxy connect to finalize */
   CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect
                                phase */
   CURLM_STATE_WAITDO,      /* wait for our turn to send the request */
@@ -865,7 +866,11 @@
           if(protocol_connect) {
             multistate(easy, CURLM_STATE_WAITDO);
           } else {
-            multistate(easy, CURLM_STATE_WAITCONNECT);
+            if (easy->easy_conn->bits.tunnel_connecting) {
+              multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
+	    } else {
+              multistate(easy, CURLM_STATE_WAITCONNECT);
+	    }
           }
         }
       }
@@ -894,8 +899,13 @@
           result = CURLM_CALL_MULTI_PERFORM;
           if(protocol_connect)
             multistate(easy, CURLM_STATE_DO);
-          else
-            multistate(easy, CURLM_STATE_WAITCONNECT);
+          else {
+            if (easy->easy_conn->bits.tunnel_connecting) {
+              multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
+	    } else {
+              multistate(easy, CURLM_STATE_WAITCONNECT);
+	    }
+	  }
         }
       }
 
@@ -908,6 +918,14 @@
     }
     break;
 
+    case CURLM_STATE_WAITPROXYCONNECT:      
+      easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
+
+      if(CURLE_OK == easy->result)
+        if (!easy->easy_conn->bits.tunnel_connecting)
+	  multistate(easy, CURLM_STATE_WAITCONNECT);
+    break;
+
     case CURLM_STATE_WAITCONNECT:
       /* awaiting a completion of an asynch connect */
       easy->result = Curl_is_connected(easy->easy_conn,
Only in mycurl-7.16.1/lib: multi.c.orig
diff -ur curl-7.16.1/lib/urldata.h mycurl-7.16.1/lib/urldata.h
--- curl-7.16.1/lib/urldata.h	2007-01-23 22:46:31.000000000 +0000
+++ mycurl-7.16.1/lib/urldata.h	2007-02-09 14:56:08.000000000 +0000
@@ -462,6 +462,8 @@
                          This is implicit when SSL-protocols are used through
                          proxies, but can also be enabled explicitly by
                          apps */
+  bool tunnel_connecting; /* TRUE while we're still waiting for a proxy CONNECT
+			   */
   bool authneg;       /* TRUE when the auth phase has started, which means
                          that we are creating a request with an auth header,
                          but it is not the final request in the auth
Only in mycurl-7.16.1/lib: urldata.h.orig

