From 1e29d275c643ef6aab7948f0f55a7a9397e56b42 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 15 Mar 2013 17:28:32 +0100 Subject: test1509: verify proxy header response headers count Modified sws to support and use custom CONNECT responses instead of the previously naive hard-coded version. Made the HTTP test server able to extract test case number from the host name in a CONNECT request by finding the number after the last dot. It makes 'machine.moo.123' use test case 123. Adapted a larger amount of tests to the new style. Bug: http://curl.haxx.se/bug/view.cgi?id=1204 Reported by: Martin Jansen --- tests/server/sws.c | 183 ++++++++++++++++++++++++----------------------------- 1 file changed, 81 insertions(+), 102 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index aef55ea96..7e1c44012 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -88,6 +88,8 @@ static bool prevbounce=FALSE; /* instructs the server to increase the part struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ + bool connect_request; /* if a CONNECT */ + unsigned short connect_port; /* the port number CONNECT used */ size_t checkindex; /* where to start checking of the request */ size_t offset; /* size of the incoming request */ long testno; /* test number found in the request */ @@ -111,7 +113,6 @@ struct httprequest { int prot_version; /* HTTP version * 10 */ bool pipelining; /* true if request is pipelined */ int callcount; /* times ProcessRequest() gets called */ - unsigned short connect_port; /* the port number CONNECT used */ bool connmon; /* monitor the state of the connection, log disconnects */ int done_processing; }; @@ -166,11 +167,8 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define END_OF_HEADERS "\r\n\r\n" enum { - DOCNUMBER_NOTHING = -7, - DOCNUMBER_QUIT = -6, - DOCNUMBER_BADCONNECT = -5, - DOCNUMBER_INTERNAL= -4, - DOCNUMBER_CONNECT = -3, + DOCNUMBER_NOTHING = -4, + DOCNUMBER_QUIT = -3, DOCNUMBER_WERULEZ = -2, DOCNUMBER_404 = -1 }; @@ -181,14 +179,6 @@ static const char *end_of_headers = END_OF_HEADERS; static const char *docquit = "HTTP/1.1 200 Goodbye" END_OF_HEADERS; -/* sent as reply to a CONNECT */ -static const char *docconnect = -"HTTP/1.1 200 Mighty fine indeed" END_OF_HEADERS; - -/* sent as reply to a "bad" CONNECT */ -static const char *docbadconnect = -"HTTP/1.1 501 Forbidden you fool" END_OF_HEADERS; - /* send back this on 404 file not found */ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" "Server: " SWSVERSION "\r\n" @@ -342,8 +332,8 @@ static int parse_servercmd(struct httprequest *req) if(!stream) { error = errno; logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", filename); - logmsg("Couldn't open test file %ld", req->testno); + logmsg(" [1] Error opening file: %s", filename); + logmsg(" Couldn't open test file %ld", req->testno); req->open = FALSE; /* closes connection */ return 1; /* done */ } @@ -533,6 +523,8 @@ static int ProcessRequest(struct httprequest *req) doc, prot_major, prot_minor); logmsg("%s", logbuf); + req->connect_request = TRUE; + if(req->prot_version == 10) req->open = FALSE; /* HTTP 1.0 closes connection by default */ @@ -557,55 +549,45 @@ static int ProcessRequest(struct httprequest *req) else req->connect_port = curlx_ultous(ulnum); } - - if(!strncmp(doc, "bad", 3)) - /* if the host name starts with bad, we fake an error here */ - req->testno = DOCNUMBER_BADCONNECT; - else if(!strncmp(doc, "test", 4)) - /* if the host name starts with test, the port number used in the - CONNECT line will be used as test number! */ - req->testno = req->connect_port?req->connect_port:DOCNUMBER_CONNECT; - else - req->testno = req->connect_port?DOCNUMBER_CONNECT:DOCNUMBER_BADCONNECT; - - /* find and parse for this test */ - parse_servercmd(req); } - else { - /* there was no trailing slash and it wasn't CONNECT, then we get the - the number off the last dot instead, IE we consider the TLD to be - the test number. Test 123 can then be written as - "example.com.123". */ + } - /* find the last dot */ - ptr = strrchr(doc, '.'); + if(req->testno == DOCNUMBER_NOTHING) { + /* Still no test case number. Try to get the the number off the last dot + instead, IE we consider the TLD to be the test number. Test 123 can + then be written as "example.com.123". */ - /* get the number after it */ - if(ptr) { - ptr++; /* skip the dot */ + /* find the last dot */ + ptr = strrchr(doc, '.'); - req->testno = strtol(ptr, &ptr, 10); + /* get the number after it */ + if(ptr) { + ptr++; /* skip the dot */ - if(req->testno > 10000) { - req->partno = req->testno % 10000; - req->testno /= 10000; - } - else - req->partno = 0; + req->testno = strtol(ptr, &ptr, 10); - sprintf(logbuf, "Requested test number %ld part %ld (from host name)", - req->testno, req->partno); - logmsg("%s", logbuf); + if(req->testno > 10000) { + req->partno = req->testno % 10000; + req->testno /= 10000; - } + logmsg("found test %d in requested host name", req->testno); - if(!req->testno) { - logmsg("Did not find test number in PATH"); - req->testno = DOCNUMBER_404; } else - parse_servercmd(req); + req->partno = 0; + + sprintf(logbuf, "Requested test number %ld part %ld (from host name)", + req->testno, req->partno); + logmsg("%s", logbuf); + } + + if(!req->testno) { + logmsg("Did not find test number in PATH"); + req->testno = DOCNUMBER_404; + } + else + parse_servercmd(req); } } else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) { @@ -822,7 +804,7 @@ static void storerequest(char *reqbuf, size_t totalsize) dump = fopen(dumpfile, "ab"); } while ((dump == NULL) && ((error = errno) == EINTR)); if (dump == NULL) { - logmsg("Error opening file %s error: %d %s", + logmsg("[2] Error opening file %s error: %d %s", dumpfile, error, strerror(error)); logmsg("Failed to write request input "); return; @@ -868,6 +850,7 @@ static void init_httprequest(struct httprequest *req) } req->testno = DOCNUMBER_NOTHING; req->partno = 0; + req->connect_request = FALSE; req->open = TRUE; req->auth_req = FALSE; req->auth = FALSE; @@ -1007,10 +990,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP; static char weare[256]; - char partbuf[80]="data"; - - logmsg("Send response test%ld section ", req->testno, req->partno); - switch(req->rcmd) { default: case RCMD_NORMALREQ: @@ -1056,17 +1035,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) msglen, msgbuf); buffer = weare; break; - case DOCNUMBER_INTERNAL: - logmsg("Bailing out due to internal error"); - return -1; - case DOCNUMBER_CONNECT: - logmsg("Replying to CONNECT"); - buffer = docconnect; - break; - case DOCNUMBER_BADCONNECT: - logmsg("Replying to a bad CONNECT"); - buffer = docbadconnect; - break; case DOCNUMBER_404: default: logmsg("Replying to with a 404"); @@ -1077,17 +1045,25 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) count = strlen(buffer); } else { + char partbuf[80]; char *filename = test2file(req->testno); - if(0 != req->partno) - sprintf(partbuf, "data%ld", req->partno); + /* select the tag for "normal" requests and the one + for CONNECT requests (within the section) */ + const char *section= req->connect_request?"connect":"data"; + + if(req->partno) + sprintf(partbuf, "%s%ld", section, req->partno); + else + sprintf(partbuf, "%s", section); + + logmsg("Send response test%ld section <%s>", req->testno, partbuf); stream=fopen(filename, "rb"); if(!stream) { error = errno; logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", filename); - logmsg("Couldn't open test file"); + logmsg(" [3] Error opening file: %s", filename); return 0; } else { @@ -1111,8 +1087,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(!stream) { error = errno; logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", filename); - logmsg("Couldn't open test file"); + logmsg(" [4] Error opening file: %s", filename); if(ptr) free(ptr); return 0; @@ -1156,7 +1131,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(!dump) { error = errno; logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", responsedump); + logmsg(" [5] Error opening file: %s", responsedump); if(ptr) free(ptr); if(cmd) @@ -1389,8 +1364,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) static void http_connect(curl_socket_t *infdp, curl_socket_t rootfd, - struct httprequest *req, - const char *ipaddr) + const char *ipaddr, + unsigned short ipport) { curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; @@ -1422,7 +1397,7 @@ static void http_connect(curl_socket_t *infdp, if(got_exit_signal) goto http_connect_cleanup; - serverfd[CTRL] = connect_to(ipaddr, req->connect_port); + serverfd[CTRL] = connect_to(ipaddr, ipport); if(serverfd[CTRL] == CURL_SOCKET_BAD) goto http_connect_cleanup; @@ -1539,7 +1514,7 @@ static void http_connect(curl_socket_t *infdp, /* skip this and close the socket if err < 0 */ if(err >= 0) { err = send_doc(datafd, &req2); - if(!err && (req2.testno == DOCNUMBER_CONNECT)) { + if(!err && req2.connect_request) { /* sleep to prevent triggering libcurl known bug #39. */ for(loop = 2; (loop > 0) && !got_exit_signal; loop--) wait_ms(250); @@ -1847,7 +1822,8 @@ static curl_socket_t accept_connection(curl_socket_t sock) /* returns 1 if the connection should be serviced again immediately, 0 if there is no data waiting, or < 0 if it should be closed */ static int service_connection(curl_socket_t msgsock, struct httprequest *req, - curl_socket_t listensock, const char *hostport) + curl_socket_t listensock, + const char *connecthost) { if(got_exit_signal) return -1; @@ -1878,17 +1854,7 @@ static int service_connection(curl_socket_t msgsock, struct httprequest *req, if(got_exit_signal) return -1; - if(DOCNUMBER_CONNECT == req->testno) { - /* a CONNECT request, setup and talk the tunnel */ - if(!is_proxy) { - logmsg("received CONNECT but isn't running as proxy! EXIT"); - } - else - http_connect(&msgsock, listensock, req, hostport); - return -1; - } - - if((req->testno < 0) && (req->testno != DOCNUMBER_CONNECT)) { + if(req->testno < 0) { logmsg("special request received, no persistency"); return -1; } @@ -1897,6 +1863,18 @@ static int service_connection(curl_socket_t msgsock, struct httprequest *req, return -1; } + if(req->connect_request) { + /* a CONNECT request, setup and talk the tunnel */ + if(!is_proxy) { + logmsg("received CONNECT but isn't running as proxy!"); + return 1; + } + else { + http_connect(&msgsock, listensock, connecthost, req->connect_port); + return -1; + } + } + /* if we got a CONNECT, loop and get another request as well! */ if(req->open) { @@ -1904,9 +1882,6 @@ static int service_connection(curl_socket_t msgsock, struct httprequest *req, return 1; } - if(req->testno == DOCNUMBER_CONNECT) - return 1; - return -1; } @@ -1923,7 +1898,9 @@ int main(int argc, char *argv[]) int error; int arg=1; long pid; - const char *hostport = "127.0.0.1"; + const char *connecthost = "127.0.0.1"; + + /* a default CONNECT port is basically pointless but still ... */ size_t socket_idx; memset(&req, 0, sizeof(req)); @@ -1993,14 +1970,15 @@ int main(int argc, char *argv[]) } } else if(!strcmp("--connect", argv[arg])) { - /* store the connect host, but also use this as a hint that we - run as a proxy and do a few different internal choices */ + /* The connect host IP number that the proxy will connect to no matter + what the client asks for, but also use this as a hint that we run as + a proxy and do a few different internal choices */ arg++; if(argc>arg) { - hostport = argv[arg]; + connecthost = argv[arg]; arg++; is_proxy = TRUE; - logmsg("Run as proxy, CONNECT to %s", hostport); + logmsg("Run as proxy, CONNECT to host %s", connecthost); } } else { @@ -2184,7 +2162,8 @@ int main(int argc, char *argv[]) /* Service this connection until it has nothing available */ do { - rc = service_connection(all_sockets[socket_idx], &req, sock, hostport); + rc = service_connection(all_sockets[socket_idx], &req, sock, + connecthost); if(got_exit_signal) goto sws_cleanup; -- cgit v1.2.3