diff options
author | Daniel Stenberg <daniel@haxx.se> | 2001-11-12 09:47:09 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2001-11-12 09:47:09 +0000 |
commit | 1affbff8f92b98ca01d42ff3b9a1606ef3b51c82 (patch) | |
tree | 7fc2a39da7358a801923607d99d2d4cc31f18858 | |
parent | c55d0bb80435aef2e06a34c006da410b47982d92 (diff) |
new Curl_ConnectHTTPProxyTunnel() function, needs a **lot** of testing!!!
-rw-r--r-- | lib/http.c | 146 |
1 files changed, 113 insertions, 33 deletions
diff --git a/lib/http.c b/lib/http.c index 9526e5188..2fe8e08dd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -205,28 +205,6 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) /* ------------------------------------------------------------------------- */ /* - * 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); - - if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d", - &subversion, - &httperror)) { - ; + /* 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; + + 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 */ |