Commit 1affbff8 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

new Curl_ConnectHTTPProxyTunnel() function, needs a **lot** of testing!!!

parent c55d0bb8
Loading
Loading
Loading
Loading
+113 −33
Original line number Diff line number Diff line
@@ -204,28 +204,6 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */

/*
 * Read everything until a newline.
 */

static
int GetLine(int sockfd, char *ptr, struct connectdata *conn)
{
  ssize_t nread;

  /* get us a full line, terminated with a newline */
  for(nread=0; (nread<BUFSIZE); nread++, ptr++) {
    if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) ||
       (nread <= 0) || (*ptr == '\n'))
      break;
  }
  *ptr=0; /* zero terminate */
  
  return nread>0?nread:0;
}



/*
 * This function checks the linked list of custom HTTP headers for a particular
 * header (prefix).
@@ -258,6 +236,22 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
  struct SessionHandle *data=conn->data;
  CURLcode result;

  int nread;   /* total size read */
  int perline; /* count bytes per line */
  bool keepon=TRUE;
  ssize_t gotbytes;
  char *ptr;
  int timeout = 3600; /* default timeout in seconds */
  struct timeval interval;
  fd_set rkeepfd;
  fd_set readfd;
  char *line_start;

#define SELECT_OK      0
#define SELECT_ERROR   1
#define SELECT_TIMEOUT 2
  int error = SELECT_OK;

  infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);

  /* OK, now send the connect request to the proxy */
@@ -276,19 +270,105 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
    return result;
  }

  /* wait for the proxy to send us a HTTP/1.0 200 OK header */
  while(GetLine(tunnelsocket, data->state.buffer, conn)) {
    if('\r' == data->state.buffer[0])
      break; /* end of headers */
    if(data->set.verbose)
      fprintf(data->set.err, "< %s\n", data->state.buffer);
  /* Now, read the full reply we get from the proxy */


  if(data->set.timeout) {
    /* if timeout is requested, find out how much remaining time we have */
    timeout = data->set.timeout - /* timeout time */
      Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
    if(timeout <=0 ) {
      failf(data, "Transfer aborted due to timeout");
      return -SELECT_TIMEOUT; /* already too little time */
    }
  }

  FD_ZERO (&readfd);		/* clear it */
  FD_SET (tunnelsocket, &readfd);     /* read socket */

  /* get this in a backup variable to be able to restore it on each lap in the
     select() loop */
  rkeepfd = readfd;

  ptr=data->state.buffer;
  line_start = ptr;

  nread=0;
  perline=0;
  keepon=TRUE;

    if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d",
  while((nread<BUFSIZE) && (keepon && !error)) {
    readfd = rkeepfd;		   /* set every lap */
    interval.tv_sec = timeout;
    interval.tv_usec = 0;

    switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) {
    case -1: /* select() error, stop reading */
      error = SELECT_ERROR;
      failf(data, "Transfer aborted due to select() error");
      break;
    case 0: /* timeout */
      error = SELECT_TIMEOUT;
      failf(data, "Transfer aborted due to timeout");
      break;
    default:
      /*
       * This code previously didn't use the kerberos sec_read() code
       * to read, but when we use Curl_read() it may do so. Do confirm
       * that this is still ok and then remove this comment!
       */
      if(CURLE_OK != Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
                               &gotbytes))
        keepon = FALSE;
      else if(gotbytes <= 0) {
        keepon = FALSE;
        error = SELECT_ERROR;
        failf(data, "Connection 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;
        for(i = 0; i < gotbytes; ptr++, i++) {
          perline++; /* amount of bytes in this line so far */
          if(*ptr=='\n') {
            /* a newline is CRLF in ftp-talk, so the CR is ignored as
               the line isn't really terminated until the LF comes */

            /* output debug output if that is requested */
            if(data->set.verbose) {
              fputs("< ", data->set.err);
              fwrite(line_start, perline, 1, data->set.err);
              /* no need to output LF here, it is part of the data */
            }
            
            if('\r' == line_start[0]) {
              /* end of headers */
              keepon=FALSE;
              break; /* breaks out of loop, not switch */
            }

            if(2 == sscanf(line_start, "HTTP/1.%d %d",
                           &subversion,
                           &httperror)) {
              ;
            }

            perline=0; /* line starts over here */
            line_start = ptr+1;
          }
        }
      }
      break;
    } /* switch */
  } /* while there's buffer left and loop is requested */

  if(error)
    return CURLE_READ_ERROR;

  if(200 != httperror) {
    if(407 == httperror)
      /* Added Nov 6 1998 */