From 3d4511daf3cc54c487af7167cf0f574d50654c9a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2002 09:39:15 +0000 Subject: the initial C code for the new HTTP test server --- tests/server/sws.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 tests/server/sws.c (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c new file mode 100644 index 000000000..854818c7b --- /dev/null +++ b/tests/server/sws.c @@ -0,0 +1,324 @@ +/* sws.c: simple (silly?) web server */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef DEFAULT_PORT +#define DEFAULT_PORT 8642 +#endif + +#ifndef DEFAULT_LOGFILE +#define DEFAULT_LOGFILE "/dev/null" +#endif + +#define DOCBUFSIZE 4 +#define BUFFERSIZE (DOCBUFSIZE * 1024) + +#define VERSION "SWS/0.1" + +#define TEST_DATA_PATH "../data/test%d" + +static char *doc404 = "HTTP/1.1 404 Not Found\n" + "Server: " VERSION "\n" + "Connection: close\n" + "Content-Type: text/html\n" + "\n" + "\n" + "\n" + "404 Not Found\n" + "\n" + "

Not Found

\n" + "The requested URL was not found on this server.\n" + "


" VERSION "
\n" "\n"; + +static volatile int sigpipe, sigterm; +static FILE *logfp; + + +static void logmsg(const char *msg) +{ + time_t t = time(NULL); + struct tm *curr_time = localtime(&t); + char loctime[80]; + + strcpy(loctime, asctime(curr_time)); + loctime[strlen(loctime) - 1] = '\0'; + fprintf(logfp, "%s: pid %d: %s\n", loctime, getpid(), msg); + fprintf(stderr, "%s: pid %d: %s\n", loctime, getpid(), msg); + fflush(logfp); +} + + +static void sigpipe_handler(int sig) +{ + sigpipe = 1; +} + + +static void sigterm_handler(int sig) +{ + char logbuf[100]; + snprintf(logbuf, 100, "Got signal %d, terminating", sig); + logmsg(logbuf); + sigterm = 1; +} + +int ProcessRequest(char *request) +{ + char *line=request; + long contentlength=-1; + +#define END_OF_HEADERS "\r\n\r\n" + + char *end; + end = strstr(request, END_OF_HEADERS); + + if(!end) + /* we don't have a complete request yet! */ + return 0; + + do { + if(!strncasecmp("Content-Length:", line, 15)) + contentlength = strtol(line, &line, 10); + + line = strchr(line, '\n'); + if(line) + line++; + } while(line); + + if(contentlength > -1 ) { + if(contentlength <= strlen(end+strlen(END_OF_HEADERS))) + return 1; /* done */ + else + return 0; /* not complete yet */ + } + return 1; /* done */ +} + + +#define REQBUFSIZ 4096 +#define MAXDOCNAMELEN 1024 +#define REQUEST_KEYWORD_SIZE 256 +static int get_request(int sock) +{ + char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; + char request[REQUEST_KEYWORD_SIZE]; + unsigned int offset = 0; + int prot_major, prot_minor; + + while (offset < REQBUFSIZ) { + int got = recv(sock, reqbuf + offset, REQBUFSIZ - offset, 0); + if (got <= 0) { + if (got < 0) { + perror("recv"); + return -1; + } + logmsg("Connection closed by client"); + return -1; + } + offset += got; + + reqbuf[offset] = 0; + + if(ProcessRequest(reqbuf)) + break; + } + + if (offset >= REQBUFSIZ) { + logmsg("Request buffer overflow, closing connection"); + return -1; + } + reqbuf[offset]=0; + + logmsg("Got request:"); + logmsg(reqbuf); + + if (sscanf(reqbuf, "%s %s HTTP/%d.%d", + request, + doc, + &prot_major, + &prot_minor) == 4) { + char *ptr; + int test_no=0; + + /* find the last slash */ + ptr = strrchr(doc, '/'); + + /* get the number after it */ + if(ptr) { + test_no = strtol(ptr+1, &ptr, 10); + + logmsg("Found test number in PATH"); + } + else + logmsg("Did not find test number in PATH"); + + return test_no; + } + + logmsg("Got illegal request"); + fprintf(stderr, "Got illegal request\n"); + return -1; +} + + +static int send_doc(int sock, int doc) +{ + int written; + int count; + char *buffer; + char *ptr; + FILE *stream; + + char filename[256]; + + if(doc < 0) { + buffer = doc404; + ptr = NULL; + stream=NULL; + } + else { + sprintf(filename, TEST_DATA_PATH, doc); + + stream=fopen(filename, "rb"); + if(!stream) { + logmsg("Couldn't open test file"); + return 0; + } + + ptr = buffer = spitout(stream, "reply", "data", &count); + } + + do { + written = send(sock, buffer, count, 0); + if (written < 0) { + fclose(stream); + return -1; + } + count -= written; + buffer += written; + } while(count>0); + + if(ptr) + free(ptr); + if(stream) + fclose(stream); + + return 0; +} + + +static void usage(const char *me) +{ + fprintf(stderr, "Usage: %s [ OPTIONS ]\n", me); + fprintf(stderr, + "-p NUM --port=NUM accept requests on port NUM (default %d)\n", + DEFAULT_PORT); + fprintf(stderr, + "-l FILE --logfile=FILE log requests to file FILE (default %s)\n", + DEFAULT_LOGFILE); + fprintf(stderr, + "-f NUM --fork=NUM fork NUM server processes (default 0)\n"); + fprintf(stderr, "-h --help this screen\n"); + exit(1); +} + + +int main(int argc, char *argv[]) +{ + struct sockaddr_in me; + int sock, msgsock, flag; + unsigned short port = DEFAULT_PORT; + char *logfile = DEFAULT_LOGFILE; + int c, longind; + + if(argc>1) + port = atoi(argv[1]); + + logfile = "logfile"; + + logfp = fopen(logfile, "a"); + if (!logfp) { + perror(logfile); + exit(1); + } + + signal(SIGPIPE, sigpipe_handler); + signal(SIGINT, sigterm_handler); + signal(SIGTERM, sigterm_handler); + + siginterrupt(SIGPIPE, 1); + siginterrupt(SIGINT, 1); + siginterrupt(SIGTERM, 1); + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("opening stream socket"); + fprintf(logfp, "Error opening socket -- aborting\n"); + fclose(logfp); + exit(1); + } + + flag = 1; + if (setsockopt + (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag, + sizeof(int)) < 0) { + perror("setsockopt(SO_REUSEADDR)"); + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(port); + if (bind(sock, (struct sockaddr *) &me, sizeof me) < 0) { + perror("binding stream socket"); + fprintf(logfp, "Error binding socket -- aborting\n"); + fclose(logfp); + exit(1); + } + + /* start accepting connections */ + listen(sock, 5); + + printf("*** %s listening on port %u ***\n", VERSION, port); + + while (!sigterm) { + int doc; + + msgsock = accept(sock, NULL, NULL); + + if (msgsock == -1) { + if (sigterm) { + break; + } + /* perror("accept"); */ + continue; + } + + logmsg("New client connected"); + + doc = get_request(msgsock); + if (doc > 0) + send_doc(msgsock, doc); + else + send_doc(msgsock, -1); + + close(msgsock); + } + + close(sock); + fclose(logfp); + + return 0; +} + -- cgit v1.2.1 From 3eead2d6c49ef6cc505b7284ca8dd371e51e4cc2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2002 12:40:06 +0000 Subject: port number fix, now stores the processed request sent to the server --- tests/server/sws.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 854818c7b..d99d244e1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -14,9 +14,7 @@ #include #include -#ifndef DEFAULT_PORT -#define DEFAULT_PORT 8642 -#endif +#define DEFAULT_PORT 8999 #ifndef DEFAULT_LOGFILE #define DEFAULT_LOGFILE "/dev/null" @@ -25,7 +23,9 @@ #define DOCBUFSIZE 4 #define BUFFERSIZE (DOCBUFSIZE * 1024) -#define VERSION "SWS/0.1" +#define VERSION "cURL test suite HTTP server/0.1" + +#define REQUEST_DUMP "http-request.dump" #define TEST_DATA_PATH "../data/test%d" @@ -106,6 +106,20 @@ int ProcessRequest(char *request) return 1; /* done */ } +/* store the entire request in a file */ +void storerequest(char *reqbuf) +{ + FILE *dump; + + dump = fopen(REQUEST_DUMP, "wb"); /* b is for windows-preparing */ + if(dump) { + fwrite(reqbuf, 1, strlen(reqbuf), dump); + + fclose(dump); + } + +} + #define REQBUFSIZ 4096 #define MAXDOCNAMELEN 1024 @@ -141,8 +155,10 @@ static int get_request(int sock) } reqbuf[offset]=0; - logmsg("Got request:"); - logmsg(reqbuf); + logmsg("Received a request"); + + /* dump the request to an external file */ + storerequest(reqbuf); if (sscanf(reqbuf, "%s %s HTTP/%d.%d", request, @@ -218,30 +234,12 @@ static int send_doc(int sock, int doc) return 0; } - -static void usage(const char *me) -{ - fprintf(stderr, "Usage: %s [ OPTIONS ]\n", me); - fprintf(stderr, - "-p NUM --port=NUM accept requests on port NUM (default %d)\n", - DEFAULT_PORT); - fprintf(stderr, - "-l FILE --logfile=FILE log requests to file FILE (default %s)\n", - DEFAULT_LOGFILE); - fprintf(stderr, - "-f NUM --fork=NUM fork NUM server processes (default 0)\n"); - fprintf(stderr, "-h --help this screen\n"); - exit(1); -} - - int main(int argc, char *argv[]) { struct sockaddr_in me; int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; char *logfile = DEFAULT_LOGFILE; - int c, longind; if(argc>1) port = atoi(argv[1]); -- cgit v1.2.1 From 818cdb879e55a52de8a1eb3774a8719b635235c4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2002 12:42:59 +0000 Subject: POSTs seems to work somewhat now --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d99d244e1..a78931b30 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -90,7 +90,7 @@ int ProcessRequest(char *request) do { if(!strncasecmp("Content-Length:", line, 15)) - contentlength = strtol(line, &line, 10); + contentlength = strtol(line+15, &line, 10); line = strchr(line, '\n'); if(line) -- cgit v1.2.1 From 83f35463f5c09346c46544f32d8e718e646f78e2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Feb 2002 12:52:04 +0000 Subject: added note about persistancy in the server --- tests/server/sws.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a78931b30..e560c6c67 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -88,6 +88,17 @@ int ProcessRequest(char *request) /* we don't have a complete request yet! */ return 0; + /* **** Persistancy **** + * + * If the request is a HTTP/1.0 one, we close the connection unconditionally + * when we're done. + * + * If the request is a HTTP/1.1 one, we MUST check for a "Connection:" + * header that might say "close". If it does, we close a connection when + * this request is processed. Otherwise, we keep the connection alive for X + * seconds. + */ + do { if(!strncasecmp("Content-Length:", line, 15)) contentlength = strtol(line+15, &line, 10); -- cgit v1.2.1 From a782c96e81f46d3d6a5f2fbf0ed91df24291a84d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Feb 2002 00:26:25 +0000 Subject: no .. in path --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e560c6c67..e2a4561cb 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -27,7 +27,7 @@ #define REQUEST_DUMP "http-request.dump" -#define TEST_DATA_PATH "../data/test%d" +#define TEST_DATA_PATH "data/test%d" static char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" -- cgit v1.2.1 From 485edb777f8ca25964eabf4a117b4aca5f89bc3f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Feb 2002 01:04:46 +0000 Subject: a minor step forwards --- tests/server/sws.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e2a4561cb..183a5b935 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -29,6 +29,7 @@ #define TEST_DATA_PATH "data/test%d" +static char *docfriends = "WE ROOLZ\r\n"; static char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" "Connection: close\n" @@ -184,12 +185,18 @@ static int get_request(int sock) /* get the number after it */ if(ptr) { + if(!strcmp("/verifiedserver", ptr)) { + logmsg("Are-we-friendly question received"); + return -2; + } test_no = strtol(ptr+1, &ptr, 10); logmsg("Found test number in PATH"); } - else + else { + logmsg("Did not find test number in PATH"); + } return test_no; } @@ -211,7 +218,11 @@ static int send_doc(int sock, int doc) char filename[256]; if(doc < 0) { - buffer = doc404; + if(-2 == doc) + /* we got a "friends?" question, reply back that we sure are */ + buffer = docfriends; + else + buffer = doc404; ptr = NULL; stream=NULL; } @@ -257,6 +268,8 @@ int main(int argc, char *argv[]) logfile = "logfile"; + /* FIX: write our pid to a file name */ + logfp = fopen(logfile, "a"); if (!logfp) { perror(logfile); @@ -317,10 +330,7 @@ int main(int argc, char *argv[]) logmsg("New client connected"); doc = get_request(msgsock); - if (doc > 0) - send_doc(msgsock, doc); - else - send_doc(msgsock, -1); + send_doc(msgsock, doc); close(msgsock); } -- cgit v1.2.1 From 7d043f46d56d07062da64c6eb32f8b1c0c301c26 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Feb 2002 10:40:05 +0000 Subject: hide debug output from screen, use log/ for logfiles --- tests/server/sws.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 183a5b935..d23368f56 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -17,7 +17,7 @@ #define DEFAULT_PORT 8999 #ifndef DEFAULT_LOGFILE -#define DEFAULT_LOGFILE "/dev/null" +#define DEFAULT_LOGFILE "log/sws.log" #endif #define DOCBUFSIZE 4 @@ -25,7 +25,7 @@ #define VERSION "cURL test suite HTTP server/0.1" -#define REQUEST_DUMP "http-request.dump" +#define REQUEST_DUMP "log/http-request.dump" #define TEST_DATA_PATH "data/test%d" @@ -56,7 +56,9 @@ static void logmsg(const char *msg) strcpy(loctime, asctime(curr_time)); loctime[strlen(loctime) - 1] = '\0'; fprintf(logfp, "%s: pid %d: %s\n", loctime, getpid(), msg); +#ifdef DEBUG fprintf(stderr, "%s: pid %d: %s\n", loctime, getpid(), msg); +#endif fflush(logfp); } @@ -266,8 +268,6 @@ int main(int argc, char *argv[]) if(argc>1) port = atoi(argv[1]); - logfile = "logfile"; - /* FIX: write our pid to a file name */ logfp = fopen(logfile, "a"); -- cgit v1.2.1 From 41dd5121f07d51588f0b29a1f04024ad158e299f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Feb 2002 13:54:06 +0000 Subject: adjusted to work on test case 11 better --- tests/server/sws.c | 161 +++++++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 72 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d23368f56..1e75ef72d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,14 +5,14 @@ #include #include #include -#include #include #include #include #include #include #include -#include + +char *spitout(FILE *stream, char *main, char *sub, int *size); #define DEFAULT_PORT 8999 @@ -80,7 +80,7 @@ static void sigterm_handler(int sig) int ProcessRequest(char *request) { char *line=request; - long contentlength=-1; + unsigned long contentlength=0; #define END_OF_HEADERS "\r\n\r\n" @@ -111,7 +111,7 @@ int ProcessRequest(char *request) line++; } while(line); - if(contentlength > -1 ) { + if(contentlength > 0 ) { if(contentlength <= strlen(end+strlen(END_OF_HEADERS))) return 1; /* done */ else @@ -138,13 +138,15 @@ void storerequest(char *reqbuf) #define REQBUFSIZ 4096 #define MAXDOCNAMELEN 1024 #define REQUEST_KEYWORD_SIZE 256 -static int get_request(int sock) +static int get_request(int sock, int *part) { char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; char request[REQUEST_KEYWORD_SIZE]; unsigned int offset = 0; int prot_major, prot_minor; + *part = 0; /* part zero equals none */ + while (offset < REQBUFSIZ) { int got = recv(sock, reqbuf + offset, REQBUFSIZ - offset, 0); if (got <= 0) { @@ -191,7 +193,15 @@ static int get_request(int sock) logmsg("Are-we-friendly question received"); return -2; } - test_no = strtol(ptr+1, &ptr, 10); + + ptr++; /* skip the slash */ + + test_no = strtol(ptr, &ptr, 10); + + if(test_no > 10000) { + *part = test_no % 10000; + test_no /= 10000; + } logmsg("Found test number in PATH"); } @@ -209,7 +219,7 @@ static int get_request(int sock) } -static int send_doc(int sock, int doc) +static int send_doc(int sock, int doc, int part_no) { int written; int count; @@ -218,6 +228,7 @@ static int send_doc(int sock, int doc) FILE *stream; char filename[256]; + char partbuf[80]="data"; if(doc < 0) { if(-2 == doc) @@ -237,7 +248,11 @@ static int send_doc(int sock, int doc) return 0; } - ptr = buffer = spitout(stream, "reply", "data", &count); + if(0 != part_no) { + sprintf(partbuf, "data%d", part_no); + } + + ptr = buffer = spitout(stream, "reply", partbuf, &count); } do { @@ -260,84 +275,86 @@ static int send_doc(int sock, int doc) int main(int argc, char *argv[]) { - struct sockaddr_in me; - int sock, msgsock, flag; - unsigned short port = DEFAULT_PORT; - char *logfile = DEFAULT_LOGFILE; - - if(argc>1) - port = atoi(argv[1]); + struct sockaddr_in me; + int sock, msgsock, flag; + unsigned short port = DEFAULT_PORT; + char *logfile = DEFAULT_LOGFILE; + int part_no; + + if(argc>1) + port = atoi(argv[1]); - /* FIX: write our pid to a file name */ + /* FIX: write our pid to a file name */ - logfp = fopen(logfile, "a"); - if (!logfp) { - perror(logfile); - exit(1); - } + logfp = fopen(logfile, "a"); + if (!logfp) { + perror(logfile); + exit(1); + } - signal(SIGPIPE, sigpipe_handler); - signal(SIGINT, sigterm_handler); - signal(SIGTERM, sigterm_handler); + /* FIX: make a more portable signal handler */ + signal(SIGPIPE, sigpipe_handler); + signal(SIGINT, sigterm_handler); + signal(SIGTERM, sigterm_handler); - siginterrupt(SIGPIPE, 1); - siginterrupt(SIGINT, 1); - siginterrupt(SIGTERM, 1); + siginterrupt(SIGPIPE, 1); + siginterrupt(SIGINT, 1); + siginterrupt(SIGTERM, 1); - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - perror("opening stream socket"); - fprintf(logfp, "Error opening socket -- aborting\n"); - fclose(logfp); - exit(1); - } + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("opening stream socket"); + fprintf(logfp, "Error opening socket -- aborting\n"); + fclose(logfp); + exit(1); + } - flag = 1; - if (setsockopt - (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag, - sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEADDR)"); - } + flag = 1; + if (setsockopt + (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag, + sizeof(int)) < 0) { + perror("setsockopt(SO_REUSEADDR)"); + } - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; - me.sin_port = htons(port); - if (bind(sock, (struct sockaddr *) &me, sizeof me) < 0) { - perror("binding stream socket"); - fprintf(logfp, "Error binding socket -- aborting\n"); - fclose(logfp); - exit(1); - } + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(port); + if (bind(sock, (struct sockaddr *) &me, sizeof me) < 0) { + perror("binding stream socket"); + fprintf(logfp, "Error binding socket -- aborting\n"); + fclose(logfp); + exit(1); + } - /* start accepting connections */ - listen(sock, 5); + /* start accepting connections */ + listen(sock, 5); - printf("*** %s listening on port %u ***\n", VERSION, port); + printf("*** %s listening on port %u ***\n", VERSION, port); - while (!sigterm) { - int doc; + while (!sigterm) { + int doc; - msgsock = accept(sock, NULL, NULL); - - if (msgsock == -1) { - if (sigterm) { - break; - } - /* perror("accept"); */ - continue; + msgsock = accept(sock, NULL, NULL); + + if (msgsock == -1) { + if (sigterm) { + break; } - - logmsg("New client connected"); - - doc = get_request(msgsock); - send_doc(msgsock, doc); - - close(msgsock); + /* perror("accept"); */ + continue; } + + logmsg("New client connected"); - close(sock); - fclose(logfp); + doc = get_request(msgsock, &part_no); + send_doc(msgsock, doc, part_no); - return 0; + close(msgsock); + } + + close(sock); + fclose(logfp); + + return 0; } -- cgit v1.2.1 From 417c8fb602fb32bb1e97ffb607aec988dfbc5df4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Feb 2002 15:40:17 +0000 Subject: 16 tests OK --- tests/server/sws.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1e75ef72d..9f3076aa5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -29,7 +29,7 @@ char *spitout(FILE *stream, char *main, char *sub, int *size); #define TEST_DATA_PATH "data/test%d" -static char *docfriends = "WE ROOLZ\r\n"; +static char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n"; static char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" "Connection: close\n" @@ -125,7 +125,7 @@ void storerequest(char *reqbuf) { FILE *dump; - dump = fopen(REQUEST_DUMP, "wb"); /* b is for windows-preparing */ + dump = fopen(REQUEST_DUMP, "ab"); /* b is for windows-preparing */ if(dump) { fwrite(reqbuf, 1, strlen(reqbuf), dump); @@ -144,6 +144,7 @@ static int get_request(int sock, int *part) char request[REQUEST_KEYWORD_SIZE]; unsigned int offset = 0; int prot_major, prot_minor; + char logbuf[256]; *part = 0; /* part zero equals none */ @@ -189,7 +190,12 @@ static int get_request(int sock, int *part) /* get the number after it */ if(ptr) { - if(!strcmp("/verifiedserver", ptr)) { + + sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", + request, doc, prot_major, prot_minor); + logmsg(logbuf); + + if(!strncmp("/verifiedserver", ptr, 15)) { logmsg("Are-we-friendly question received"); return -2; } @@ -203,7 +209,8 @@ static int get_request(int sock, int *part) test_no /= 10000; } - logmsg("Found test number in PATH"); + sprintf(logbuf, "Found test number %d in path", test_no); + logmsg(logbuf); } else { @@ -238,6 +245,8 @@ static int send_doc(int sock, int doc, int part_no) buffer = doc404; ptr = NULL; stream=NULL; + + count = strlen(buffer); } else { sprintf(filename, TEST_DATA_PATH, doc); @@ -258,7 +267,8 @@ static int send_doc(int sock, int doc, int part_no) do { written = send(sock, buffer, count, 0); if (written < 0) { - fclose(stream); + if(stream) + fclose(stream); return -1; } count -= written; -- cgit v1.2.1 From d86f9611b334f47b995d332f5900d0681fff4c3e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Feb 2002 09:42:58 +0000 Subject: support HUGE requests too --- tests/server/sws.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9f3076aa5..6b6585007 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -135,13 +135,18 @@ void storerequest(char *reqbuf) } -#define REQBUFSIZ 4096 -#define MAXDOCNAMELEN 1024 +#define REQBUFSIZ 50000 +#define REQBUFSIZ_TXT "49999" + +/* very-big-path support */ +#define MAXDOCNAMELEN 40000 +#define MAXDOCNAMELEN_TXT "39999" + #define REQUEST_KEYWORD_SIZE 256 static int get_request(int sock, int *part) { - char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; - char request[REQUEST_KEYWORD_SIZE]; + static char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; + static char request[REQUEST_KEYWORD_SIZE]; unsigned int offset = 0; int prot_major, prot_minor; char logbuf[256]; @@ -177,7 +182,7 @@ static int get_request(int sock, int *part) /* dump the request to an external file */ storerequest(reqbuf); - if (sscanf(reqbuf, "%s %s HTTP/%d.%d", + if (sscanf(reqbuf, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", request, doc, &prot_major, @@ -191,10 +196,14 @@ static int get_request(int sock, int *part) /* get the number after it */ if(ptr) { - sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", - request, doc, prot_major, prot_minor); + if((strlen(doc) + strlen(request)) < 200) + sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", + request, doc, prot_major, prot_minor); + else + sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d", + prot_major, prot_minor); logmsg(logbuf); - + if(!strncmp("/verifiedserver", ptr, 15)) { logmsg("Are-we-friendly question received"); return -2; -- cgit v1.2.1 From 2e9a798f091f9ddb4e93ab5324632a91189569e1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Feb 2002 10:27:29 +0000 Subject: create the pidfile and store the pid on invoke --- tests/server/sws.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 6b6585007..9c76b5155 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -299,6 +299,7 @@ int main(int argc, char *argv[]) unsigned short port = DEFAULT_PORT; char *logfile = DEFAULT_LOGFILE; int part_no; + FILE *pidfile; if(argc>1) port = atoi(argv[1]); @@ -345,10 +346,18 @@ int main(int argc, char *argv[]) exit(1); } + pidfile = fopen(".http.pid", "w"); + if(pidfile) { + fprintf(pidfile, "%d\n", (int)getpid()); + fclose(pidfile); + } + else + fprintf(stderr, "Couldn't write pid file\n"); + /* start accepting connections */ listen(sock, 5); - printf("*** %s listening on port %u ***\n", VERSION, port); + fprintf(stderr, "*** %s listening on port %u ***\n", VERSION, port); while (!sigterm) { int doc; -- cgit v1.2.1 From 71bb2d0b8b150456f228f69f7b8bc90486776844 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Feb 2002 11:11:03 +0000 Subject: reply/postcmd support for "wait" --- tests/server/sws.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9c76b5155..761c2f6c0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -242,6 +242,8 @@ static int send_doc(int sock, int doc, int part_no) char *buffer; char *ptr; FILE *stream; + char *cmd=NULL; + int cmdsize; char filename[256]; char partbuf[80]="data"; @@ -258,6 +260,11 @@ static int send_doc(int sock, int doc, int part_no) count = strlen(buffer); } else { + if(0 != part_no) { + sprintf(partbuf, "data%d", part_no); + } + + sprintf(filename, TEST_DATA_PATH, doc); stream=fopen(filename, "rb"); @@ -265,19 +272,27 @@ static int send_doc(int sock, int doc, int part_no) logmsg("Couldn't open test file"); return 0; } - - if(0 != part_no) { - sprintf(partbuf, "data%d", part_no); + else { + ptr = buffer = spitout(stream, "reply", partbuf, &count); + fclose(stream); } - ptr = buffer = spitout(stream, "reply", partbuf, &count); + /* re-open the same file again */ + stream=fopen(filename, "rb"); + if(!stream) { + logmsg("Couldn't open test file"); + return 0; + } + else { + /* get the custom server control "commands" */ + cmd = spitout(stream, "reply", "postcmd", &cmdsize); + fclose(stream); + } } do { written = send(sock, buffer, count, 0); if (written < 0) { - if(stream) - fclose(stream); return -1; } count -= written; @@ -286,8 +301,28 @@ static int send_doc(int sock, int doc, int part_no) if(ptr) free(ptr); - if(stream) - fclose(stream); + + if(cmdsize > 0 ) { + char command[32]; + int num; + char *ptr=cmd; + do { + if(2 == sscanf(ptr, "%31s %d", command, &num)) { + if(!strcmp("wait", command)) + sleep(num); /* wait this many seconds */ + else { + logmsg("Unknown command in reply command section"); + } + } + ptr = strchr(ptr, '\n'); + if(ptr) + ptr++; + else + ptr = NULL; + } while(ptr && *ptr); + } + if(cmd) + free(cmd); return 0; } @@ -312,6 +347,7 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef HAVE_SIGNAL /* FIX: make a more portable signal handler */ signal(SIGPIPE, sigpipe_handler); signal(SIGINT, sigterm_handler); @@ -320,6 +356,7 @@ int main(int argc, char *argv[]) siginterrupt(SIGPIPE, 1); siginterrupt(SIGINT, 1); siginterrupt(SIGTERM, 1); +#endif sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { -- cgit v1.2.1 From d9f307623c65601ae5acfea076d2c5bb9e8c608c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Feb 2002 12:14:24 +0000 Subject: use the former logfile name again since the ftp server also uses that... --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 761c2f6c0..501bf077d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -25,7 +25,7 @@ char *spitout(FILE *stream, char *main, char *sub, int *size); #define VERSION "cURL test suite HTTP server/0.1" -#define REQUEST_DUMP "log/http-request.dump" +#define REQUEST_DUMP "log/server.input" #define TEST_DATA_PATH "data/test%d" -- cgit v1.2.1 From ad3cef0fc84a8578874bbf29c54adcc41649a9b6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 6 Mar 2002 09:40:06 +0000 Subject: Ralph Mitchell's minor #include patch to prevent some warnings --- tests/server/sws.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 501bf077d..01991bbc0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 044755b30f01554a12f8d8afa2d176ca7f053d83 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 26 Apr 2002 07:48:05 +0000 Subject: handles much larger POSTs, replaced snprintf() with sprintf() since this needs to be more portable and in the test server we can skip the extra safety --- tests/server/sws.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 01991bbc0..1b0f145e5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -21,9 +21,6 @@ char *spitout(FILE *stream, char *main, char *sub, int *size); #define DEFAULT_LOGFILE "log/sws.log" #endif -#define DOCBUFSIZE 4 -#define BUFFERSIZE (DOCBUFSIZE * 1024) - #define VERSION "cURL test suite HTTP server/0.1" #define REQUEST_DUMP "log/server.input" @@ -73,7 +70,7 @@ static void sigpipe_handler(int sig) static void sigterm_handler(int sig) { char logbuf[100]; - snprintf(logbuf, 100, "Got signal %d, terminating", sig); + sprintf(logbuf, "Got signal %d, terminating", sig); logmsg(logbuf); sigterm = 1; } @@ -136,12 +133,12 @@ void storerequest(char *reqbuf) } -#define REQBUFSIZ 50000 -#define REQBUFSIZ_TXT "49999" +#define REQBUFSIZ 150000 +#define REQBUFSIZ_TXT "149999" /* very-big-path support */ -#define MAXDOCNAMELEN 40000 -#define MAXDOCNAMELEN_TXT "39999" +#define MAXDOCNAMELEN 140000 +#define MAXDOCNAMELEN_TXT "139999" #define REQUEST_KEYWORD_SIZE 256 static int get_request(int sock, int *part) -- cgit v1.2.1 From 0c00eb93a038417ac25dae1d0805887562ed8520 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 17 May 2002 08:15:33 +0000 Subject: removed compiler warnings --- tests/server/sws.c | 53 ++++++++++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1b0f145e5..d66f84ad9 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -13,7 +13,10 @@ #include #include -char *spitout(FILE *stream, char *main, char *sub, int *size); +const char * +spitout(FILE *stream, + const char *main, + const char *sub, int *size); #define DEFAULT_PORT 8999 @@ -27,8 +30,8 @@ char *spitout(FILE *stream, char *main, char *sub, int *size); #define TEST_DATA_PATH "data/test%d" -static char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n"; -static char *doc404 = "HTTP/1.1 404 Not Found\n" +static const char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n"; +static const char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" "Connection: close\n" "Content-Type: text/html\n" @@ -41,7 +44,9 @@ static char *doc404 = "HTTP/1.1 404 Not Found\n" "The requested URL was not found on this server.\n" "


" VERSION "
\n" "\n"; -static volatile int sigpipe, sigterm; +#ifdef HAVE_SIGNAL +static volatile int sigpipe; +#endif static FILE *logfp; @@ -53,27 +58,21 @@ static void logmsg(const char *msg) strcpy(loctime, asctime(curr_time)); loctime[strlen(loctime) - 1] = '\0'; - fprintf(logfp, "%s: pid %d: %s\n", loctime, getpid(), msg); + fprintf(logfp, "%s: pid %d: %s\n", loctime, (int)getpid(), msg); #ifdef DEBUG - fprintf(stderr, "%s: pid %d: %s\n", loctime, getpid(), msg); + fprintf(stderr, "%s: pid %d: %s\n", loctime, (int)getpid(), msg); #endif fflush(logfp); } +#ifdef HAVE_SIGNAL static void sigpipe_handler(int sig) { - sigpipe = 1; -} - - -static void sigterm_handler(int sig) -{ - char logbuf[100]; - sprintf(logbuf, "Got signal %d, terminating", sig); - logmsg(logbuf); - sigterm = 1; + (void)sig; /* prevent warning */ + sigpipe = 1; } +#endif int ProcessRequest(char *request) { @@ -237,7 +236,7 @@ static int send_doc(int sock, int doc, int part_no) { int written; int count; - char *buffer; + const char *buffer; char *ptr; FILE *stream; char *cmd=NULL; @@ -271,7 +270,8 @@ static int send_doc(int sock, int doc, int part_no) return 0; } else { - ptr = buffer = spitout(stream, "reply", partbuf, &count); + buffer = spitout(stream, "reply", partbuf, &count); + ptr = (char *)buffer; fclose(stream); } @@ -283,7 +283,7 @@ static int send_doc(int sock, int doc, int part_no) } else { /* get the custom server control "commands" */ - cmd = spitout(stream, "reply", "postcmd", &cmdsize); + cmd = (char *)spitout(stream, "reply", "postcmd", &cmdsize); fclose(stream); } } @@ -330,7 +330,7 @@ int main(int argc, char *argv[]) struct sockaddr_in me; int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; - char *logfile = DEFAULT_LOGFILE; + const char *logfile = DEFAULT_LOGFILE; int part_no; FILE *pidfile; @@ -348,12 +348,8 @@ int main(int argc, char *argv[]) #ifdef HAVE_SIGNAL /* FIX: make a more portable signal handler */ signal(SIGPIPE, sigpipe_handler); - signal(SIGINT, sigterm_handler); - signal(SIGTERM, sigterm_handler); siginterrupt(SIGPIPE, 1); - siginterrupt(SIGINT, 1); - siginterrupt(SIGTERM, 1); #endif sock = socket(AF_INET, SOCK_STREAM, 0); @@ -394,18 +390,13 @@ int main(int argc, char *argv[]) fprintf(stderr, "*** %s listening on port %u ***\n", VERSION, port); - while (!sigterm) { + while (1) { int doc; msgsock = accept(sock, NULL, NULL); - if (msgsock == -1) { - if (sigterm) { - break; - } - /* perror("accept"); */ + if (msgsock == -1) continue; - } logmsg("New client connected"); -- cgit v1.2.1 From 3d0969d1d1f08ffa5f8506c73112545f87c7bf73 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 21 May 2002 08:22:00 +0000 Subject: Added source header and made it clear that this code was originally donated to us by Juergen Wilke. --- tests/server/sws.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d66f84ad9..5b49e145a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1,4 +1,32 @@ -/* sws.c: simple (silly?) web server */ +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * In order to be useful for every potential user, curl and libcurl are + * dual-licensed under the MPL and the MIT/X-derivate licenses. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the MPL or the MIT/X-derivate + * licenses. You may pick one of these licenses. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + *****************************************************************************/ + +/* sws.c: simple (silly?) web server + + This code was originally graciously donated to the project Juergen + Wilke. Thanks a bunch! + + */ #include #include -- cgit v1.2.1 From ba4e69bebc8f7f32f3bc7faa1e13e7580754075b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Sep 2002 11:52:59 +0000 Subject: updated source code boilerplate/header --- tests/server/sws.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5b49e145a..11ad8a455 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1,4 +1,4 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | @@ -7,19 +7,19 @@ * * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. - * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* sws.c: simple (silly?) web server -- cgit v1.2.1 From 12cfb4f7ee29fd3646cc57e3fd35c4450e033dba Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 22 Nov 2002 13:48:24 +0000 Subject: this fix seems to make the '305 306' test case combination to run ok finally! --- tests/server/sws.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 11ad8a455..ee152ac9d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -268,7 +268,7 @@ static int send_doc(int sock, int doc, int part_no) char *ptr; FILE *stream; char *cmd=NULL; - int cmdsize; + int cmdsize=0; char filename[256]; char partbuf[80]="data"; @@ -285,10 +285,8 @@ static int send_doc(int sock, int doc, int part_no) count = strlen(buffer); } else { - if(0 != part_no) { + if(0 != part_no) sprintf(partbuf, "data%d", part_no); - } - sprintf(filename, TEST_DATA_PATH, doc); -- cgit v1.2.1 From ec7bccf67121bfcf1fb3cba5773b8d6b1ff3a47c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 10 Dec 2002 12:59:16 +0000 Subject: more logging, now logs the full response too, basic support for dealing with chunked transfer-encoding uploads added --- tests/server/sws.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ee152ac9d..ba49692cb 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -41,6 +41,13 @@ #include #include +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + const char * spitout(FILE *stream, const char *main, @@ -54,7 +61,8 @@ spitout(FILE *stream, #define VERSION "cURL test suite HTTP server/0.1" -#define REQUEST_DUMP "log/server.input" +#define REQUEST_DUMP "log/server.input" +#define RESPONSE_DUMP "log/server.response" #define TEST_DATA_PATH "data/test%d" @@ -106,6 +114,7 @@ int ProcessRequest(char *request) { char *line=request; unsigned long contentlength=0; + char chunked=FALSE; #define END_OF_HEADERS "\r\n\r\n" @@ -128,8 +137,23 @@ int ProcessRequest(char *request) */ do { - if(!strncasecmp("Content-Length:", line, 15)) + if(!strncasecmp("Content-Length:", line, 15)) { contentlength = strtol(line+15, &line, 10); + break; + } + else if(!strncasecmp("Transfer-Encoding: chunked", line, + strlen("Transfer-Encoding: chunked"))) { + /* chunked data coming in */ + chunked = TRUE; + } + + if(chunked) { + if(strstr(request, "\r\n0\r\n")) + /* end of chunks reached */ + return 1; /* done */ + else + return 0; /* not done */ + } line = strchr(line, '\n'); if(line) @@ -269,11 +293,14 @@ static int send_doc(int sock, int doc, int part_no) FILE *stream; char *cmd=NULL; int cmdsize=0; + FILE *dump; char filename[256]; char partbuf[80]="data"; if(doc < 0) { + logmsg("Negative document number received, magic reply coming up"); + if(-2 == doc) /* we got a "friends?" question, reply back that we sure are */ buffer = docfriends; @@ -285,6 +312,8 @@ static int send_doc(int sock, int doc, int part_no) count = strlen(buffer); } else { + logmsg("Fetch response data"); + if(0 != part_no) sprintf(partbuf, "data%d", part_no); @@ -314,15 +343,29 @@ static int send_doc(int sock, int doc, int part_no) } } + dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ + if(!dump) { + logmsg("couldn't create logfile: " RESPONSE_DUMP); + return -1; + } + do { written = send(sock, buffer, count, 0); if (written < 0) { + logmsg("Sending response failed and we bailed out!"); return -1; } + /* write to file as well */ + fwrite(buffer, 1, written, dump); + count -= written; buffer += written; } while(count>0); + fclose(dump); + + logmsg("Response sent!"); + if(ptr) free(ptr); @@ -334,9 +377,8 @@ static int send_doc(int sock, int doc, int part_no) if(2 == sscanf(ptr, "%31s %d", command, &num)) { if(!strcmp("wait", command)) sleep(num); /* wait this many seconds */ - else { + else logmsg("Unknown command in reply command section"); - } } ptr = strchr(ptr, '\n'); if(ptr) @@ -427,8 +469,10 @@ int main(int argc, char *argv[]) logmsg("New client connected"); doc = get_request(msgsock, &part_no); + logmsg("Received request, now send response"); send_doc(msgsock, doc, part_no); + logmsg("Closing client connection"); close(msgsock); } -- cgit v1.2.1 From da5ae565abbf51fe4d313812776e4cb77929f635 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Dec 2002 16:20:07 +0000 Subject: added support for CONNECT, both good and bad --- tests/server/sws.c | 109 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 30 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ba49692cb..cac0d345b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -23,9 +23,9 @@ /* sws.c: simple (silly?) web server - This code was originally graciously donated to the project Juergen + This code was originally graciously donated to the project by Juergen Wilke. Thanks a bunch! - + */ #include @@ -66,7 +66,29 @@ spitout(FILE *stream, #define TEST_DATA_PATH "data/test%d" +enum { + DOCNUMBER_BADCONNECT = -5, + DOCNUMBER_INTERNAL= -4, + DOCNUMBER_CONNECT = -3, + DOCNUMBER_WERULEZ = -2, + DOCNUMBER_404 = -1 +}; + +/* sent as reply to a CONNECT */ +static const char *docconnect = +"HTTP/1.1 200 Mighty fine indeed\r\n" +"\r\n"; + +/* sent as reply to a "bad" CONNECT */ +static const char *docbadconnect = +"HTTP/1.1 501 Forbidden you fool\r\n" +"\r\n"; + +/* sent as reply to the magic to find out if we are the test server or + not */ static const char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n"; + +/* send back this on 404 file not found */ static const char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" "Connection: close\n" @@ -94,10 +116,7 @@ static void logmsg(const char *msg) strcpy(loctime, asctime(curr_time)); loctime[strlen(loctime) - 1] = '\0'; - fprintf(logfp, "%s: pid %d: %s\n", loctime, (int)getpid(), msg); -#ifdef DEBUG - fprintf(stderr, "%s: pid %d: %s\n", loctime, (int)getpid(), msg); -#endif + fprintf(logfp, "%s: %d: %s\n", loctime, (int)getpid(), msg); fflush(logfp); } @@ -207,10 +226,10 @@ static int get_request(int sock, int *part) if (got <= 0) { if (got < 0) { perror("recv"); - return -1; + return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); - return -1; + return DOCNUMBER_INTERNAL; } offset += got; @@ -222,20 +241,18 @@ static int get_request(int sock, int *part) if (offset >= REQBUFSIZ) { logmsg("Request buffer overflow, closing connection"); - return -1; + return DOCNUMBER_INTERNAL; } reqbuf[offset]=0; - logmsg("Received a request"); - /* dump the request to an external file */ storerequest(reqbuf); - if (sscanf(reqbuf, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", - request, - doc, - &prot_major, - &prot_minor) == 4) { + if(sscanf(reqbuf, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + request, + doc, + &prot_major, + &prot_minor) == 4) { char *ptr; int test_no=0; @@ -255,7 +272,7 @@ static int get_request(int sock, int *part) if(!strncmp("/verifiedserver", ptr, 15)) { logmsg("Are-we-friendly question received"); - return -2; + return DOCNUMBER_WERULEZ; } ptr++; /* skip the slash */ @@ -271,8 +288,23 @@ static int get_request(int sock, int *part) logmsg(logbuf); } else { - - logmsg("Did not find test number in PATH"); + if(sscanf(reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + doc, + &prot_major, &prot_minor) == 3) { + sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", + doc, prot_major, prot_minor); + logmsg(logbuf); + + if(!strncmp(doc, "bad", 3)) + /* if the host name starts with bad, we fake an error here */ + test_no = DOCNUMBER_BADCONNECT; + else + test_no = DOCNUMBER_CONNECT; + } + else { + logmsg("Did not find test number in PATH"); + test_no = DOCNUMBER_404; + } } return test_no; @@ -299,13 +331,29 @@ static int send_doc(int sock, int doc, int part_no) char partbuf[80]="data"; if(doc < 0) { - logmsg("Negative document number received, magic reply coming up"); - - if(-2 == doc) + switch(doc) { + case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ + logmsg("Identifying ourselves as friends"); buffer = docfriends; - else + 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"); buffer = doc404; + break; + } ptr = NULL; stream=NULL; @@ -405,8 +453,6 @@ int main(int argc, char *argv[]) if(argc>1) port = atoi(argv[1]); - /* FIX: write our pid to a file name */ - logfp = fopen(logfile, "a"); if (!logfp) { perror(logfile); @@ -414,9 +460,7 @@ int main(int argc, char *argv[]) } #ifdef HAVE_SIGNAL - /* FIX: make a more portable signal handler */ signal(SIGPIPE, sigpipe_handler); - siginterrupt(SIGPIPE, 1); #endif @@ -468,9 +512,14 @@ int main(int argc, char *argv[]) logmsg("New client connected"); - doc = get_request(msgsock, &part_no); - logmsg("Received request, now send response"); - send_doc(msgsock, doc, part_no); + do { + + doc = get_request(msgsock, &part_no); + logmsg("Received request, now send response"); + send_doc(msgsock, doc, part_no); + + /* if we got a CONNECT, loop and get another request as well! */ + } while(doc == DOCNUMBER_CONNECT); logmsg("Closing client connection"); close(msgsock); -- cgit v1.2.1 From f26a338a54e04d0a6907f5d2479d8b0fa9daf297 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Jan 2003 21:08:12 +0000 Subject: copyright year update in the source header --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index cac0d345b..c93af94ee 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 065b87e949a4d4d67a4dace2429da45e2a8bc6af Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 Feb 2003 18:14:48 +0000 Subject: 7.10.4-pre2 commit --- tests/server/sws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index c93af94ee..0b1865a58 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -226,6 +226,7 @@ static int get_request(int sock, int *part) if (got <= 0) { if (got < 0) { perror("recv"); + logmsg("recv() returned error"); return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); @@ -312,7 +313,7 @@ static int get_request(int sock, int *part) logmsg("Got illegal request"); fprintf(stderr, "Got illegal request\n"); - return -1; + return DOCNUMBER_404; } -- cgit v1.2.1 From dcc2f1641625af4715f05024521d1da2d4d9c671 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 15 Mar 2003 14:47:09 +0000 Subject: Rick Jones' minor thing to build better on HPUX 11 --- tests/server/sws.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0b1865a58..f928b7a47 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -39,6 +39,10 @@ #include #include #include +#ifdef _XOPEN_SOURCE_EXTENDED +/* This define is "almost" required to build on HPUX 11 */ +#include +#endif #include #ifndef FALSE -- cgit v1.2.1 From 72673a351bd0cadeb7735c853fc542df1a56023e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 15 Mar 2003 16:05:47 +0000 Subject: removed the "banner" when the server is starting --- tests/server/sws.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f928b7a47..80a5a5546 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -505,8 +505,6 @@ int main(int argc, char *argv[]) /* start accepting connections */ listen(sock, 5); - fprintf(stderr, "*** %s listening on port %u ***\n", VERSION, port); - while (1) { int doc; -- cgit v1.2.1 From 0251563c981c2486d240ccf858cbbcf2a3ac1315 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 15 Mar 2003 16:39:15 +0000 Subject: report pid back in the WE ROOLZ message --- tests/server/sws.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 80a5a5546..8dd050efa 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -88,10 +88,6 @@ static const char *docbadconnect = "HTTP/1.1 501 Forbidden you fool\r\n" "\r\n"; -/* sent as reply to the magic to find out if we are the test server or - not */ -static const char *docfriends = "HTTP/1.1 200 Mighty fine indeed\r\n\r\nWE ROOLZ\r\n"; - /* send back this on 404 file not found */ static const char *doc404 = "HTTP/1.1 404 Not Found\n" "Server: " VERSION "\n" @@ -332,6 +328,8 @@ static int send_doc(int sock, int doc, int part_no) int cmdsize=0; FILE *dump; + static char weare[256]; + char filename[256]; char partbuf[80]="data"; @@ -340,7 +338,9 @@ static int send_doc(int sock, int doc, int part_no) case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); - buffer = docfriends; + sprintf(weare, "HTTP/1.1 200 OK\r\n\r\nWE ROOLZ: %d\r\n", + getpid()); + buffer = weare; break; case DOCNUMBER_INTERNAL: logmsg("Bailing out due to internal error"); -- cgit v1.2.1 From 9b43ade1c02b7dfa07f9667fa631a4b1e5ac73ca Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 16 Mar 2003 10:46:52 +0000 Subject: typecase getpid() to int to prevent compiler warning --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 8dd050efa..007d6b753 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -339,7 +339,7 @@ static int send_doc(int sock, int doc, int part_no) /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); sprintf(weare, "HTTP/1.1 200 OK\r\n\r\nWE ROOLZ: %d\r\n", - getpid()); + (int)getpid()); buffer = weare; break; case DOCNUMBER_INTERNAL: -- cgit v1.2.1 From df7bbcfd21909d2eb474b75a110bb2cde07c8d76 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 3 Apr 2003 13:43:15 +0000 Subject: Added log output for when the writing of the input HTTP request is successful or unsuccessful. Used to track down the recent cygwin test suite problems. --- tests/server/sws.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 007d6b753..4f9baba1b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -198,8 +198,11 @@ void storerequest(char *reqbuf) fwrite(reqbuf, 1, strlen(reqbuf), dump); fclose(dump); + logmsg("Wrote request input to " REQUEST_DUMP); + } + else { + logmsg("Failed to write request input to " REQUEST_DUMP); } - } -- cgit v1.2.1 From 0102726aeb18258105d4f41c6196cdec62711dae Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 May 2003 22:36:39 +0000 Subject: Digest support added --- tests/server/sws.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 4f9baba1b..1223e0158 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -290,6 +290,13 @@ static int get_request(int sock, int *part) sprintf(logbuf, "Found test number %d in path", test_no); logmsg(logbuf); + + if(strstr(reqbuf, "Authorization: Digest")) { + /* If the client is passing this Digest-header, we set the part number + to 1000. Not only to spice up the complexity of this, but to make + Digest stuff to work in the test suite. */ + *part = 1000; + } } else { if(sscanf(reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", -- cgit v1.2.1 From fb6a51b8fd715db2987c00f87cc1ac1aca535fee Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Jun 2003 13:44:31 +0000 Subject: basic NTLM support --- tests/server/sws.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1223e0158..07b37a25f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -297,6 +297,14 @@ static int get_request(int sock, int *part) Digest stuff to work in the test suite. */ *part = 1000; } + else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { + /* If the client is passing this type-3 NTLM header */ + *part = 1002; + } + else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { + /* If the client is passing this type-1 NTLM header */ + *part = 1001; + } } else { if(sscanf(reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", -- cgit v1.2.1 From 7968e3c2de56b035081f30ddcc9b60be2d75f396 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 1 Jul 2003 15:21:42 +0000 Subject: David Byron's patch that allows a client to make the server quit with a magic url. --- tests/server/sws.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 07b37a25f..b798a682b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -71,6 +71,7 @@ spitout(FILE *stream, #define TEST_DATA_PATH "data/test%d" enum { + DOCNUMBER_QUIT = -6, DOCNUMBER_BADCONNECT = -5, DOCNUMBER_INTERNAL= -4, DOCNUMBER_CONNECT = -3, @@ -78,6 +79,12 @@ enum { DOCNUMBER_404 = -1 }; + +/* sent as reply to a QUIT */ +static const char *docquit = +"HTTP/1.1 200 Goodbye\r\n" +"\r\n"; + /* sent as reply to a CONNECT */ static const char *docconnect = "HTTP/1.1 200 Mighty fine indeed\r\n" @@ -279,6 +286,11 @@ static int get_request(int sock, int *part) return DOCNUMBER_WERULEZ; } + if(!strncmp("/quit", ptr, 15)) { + logmsg("Request-to-quit received"); + return DOCNUMBER_QUIT; + } + ptr++; /* skip the slash */ test_no = strtol(ptr, &ptr, 10); @@ -353,6 +365,10 @@ static int send_doc(int sock, int doc, int part_no) if(doc < 0) { switch(doc) { + case DOCNUMBER_QUIT: + logmsg("Replying to QUIT"); + buffer = docquit; + break; case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); @@ -544,6 +560,9 @@ int main(int argc, char *argv[]) logmsg("Closing client connection"); close(msgsock); + + if (doc == DOCNUMBER_QUIT) + break; } close(sock); -- cgit v1.2.1 From 2c1925161eaa3a4d20e3c870a558911d96cedb5f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Jul 2003 23:44:22 +0000 Subject: If the data contents contains the word 'swsclose', then this server will disconnect the client after the response have been sent. This also happens if the respons is zero byte long. In all other cases (unless an error happens), it will now maintain the connection to allow proper persistant connection testing. This was required for the NTLM testing to work so I finally had to fix this. Of course most of the existing HTTP tests will be adjusted to work with this new rule of test file syntax for HTTP tests. Also fixed the log function to deal with varargs for better logging. --- tests/server/sws.c | 84 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 18 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b798a682b..bb29a3dc8 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -115,16 +116,22 @@ static volatile int sigpipe; static FILE *logfp; -static void logmsg(const char *msg) +static void logmsg(const char *msg, ...) { - time_t t = time(NULL); - struct tm *curr_time = localtime(&t); - char loctime[80]; - - strcpy(loctime, asctime(curr_time)); - loctime[strlen(loctime) - 1] = '\0'; - fprintf(logfp, "%s: %d: %s\n", loctime, (int)getpid(), msg); - fflush(logfp); + time_t t = time(NULL); + va_list ap; + struct tm *curr_time = localtime(&t); + char loctime[80]; + char buffer[256]; /* possible overflow if you pass in a huge string */ + + va_start(ap, msg); + vsprintf(buffer, msg, ap); + va_end(ap); + + strcpy(loctime, asctime(curr_time)); + loctime[strlen(loctime) - 1] = '\0'; + fprintf(logfp, "%s: %d: %s\n", loctime, (int)getpid(), buffer); + fflush(logfp); } @@ -221,7 +228,7 @@ void storerequest(char *reqbuf) #define MAXDOCNAMELEN_TXT "139999" #define REQUEST_KEYWORD_SIZE 256 -static int get_request(int sock, int *part) +static int get_request(int sock, int *part, int *open) { static char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; static char request[REQUEST_KEYWORD_SIZE]; @@ -231,6 +238,8 @@ static int get_request(int sock, int *part) *part = 0; /* part zero equals none */ + *open = TRUE; /* connection should remain open and wait for more commands */ + while (offset < REQBUFSIZ) { int got = recv(sock, reqbuf + offset, REQBUFSIZ - offset, 0); if (got <= 0) { @@ -307,16 +316,22 @@ static int get_request(int sock, int *part) /* If the client is passing this Digest-header, we set the part number to 1000. Not only to spice up the complexity of this, but to make Digest stuff to work in the test suite. */ + logmsg("Received Digest request, sending back data 1000"); *part = 1000; } else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { /* If the client is passing this type-3 NTLM header */ + logmsg("Received NTLM type-3, sending back data 1002"); *part = 1002; } else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { /* If the client is passing this type-1 NTLM header */ + logmsg("Received NTLM type-1, sending back data 1001"); *part = 1001; } + + if(strstr(reqbuf, "Connection: close")) + *open = FALSE; /* close connection after this request */ } else { if(sscanf(reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", @@ -326,6 +341,9 @@ static int get_request(int sock, int *part) doc, prot_major, prot_minor); logmsg(logbuf); + if(prot_major*10+prot_minor == 10) + *open = FALSE; /* HTTP 1.0 closes connection by default */ + if(!strncmp(doc, "bad", 3)) /* if the host name starts with bad, we fake an error here */ test_no = DOCNUMBER_BADCONNECT; @@ -346,8 +364,11 @@ static int get_request(int sock, int *part) return DOCNUMBER_404; } - -static int send_doc(int sock, int doc, int part_no) +/* returns -1 on failure */ +static int send_doc(int sock, + int doc, + int part_no, + int *alive) /* keep the connection alive or not */ { int written; int count; @@ -357,12 +378,15 @@ static int send_doc(int sock, int doc, int part_no) char *cmd=NULL; int cmdsize=0; FILE *dump; + int persistant = TRUE; static char weare[256]; char filename[256]; char partbuf[80]="data"; + *alive = FALSE; + if(doc < 0) { switch(doc) { case DOCNUMBER_QUIT: @@ -399,7 +423,7 @@ static int send_doc(int sock, int doc, int part_no) count = strlen(buffer); } else { - logmsg("Fetch response data"); + logmsg("Fetch response data, test %d part %d", doc, part_no); if(0 != part_no) sprintf(partbuf, "data%d", part_no); @@ -436,6 +460,14 @@ static int send_doc(int sock, int doc, int part_no) return -1; } + /* If the word 'swsclose' is present anywhere in the reply chunk, the + connection will be closed after the data has been sent to the requesting + client... */ + if(strstr(buffer, "swsclose") || !count) { + persistant = FALSE; + logmsg("connection close instruction swsclose found in response"); + } + do { written = send(sock, buffer, count, 0); if (written < 0) { @@ -477,6 +509,8 @@ static int send_doc(int sock, int doc, int part_no) if(cmd) free(cmd); + *alive = persistant; + return 0; } @@ -541,7 +575,9 @@ int main(int argc, char *argv[]) while (1) { int doc; - + int open; + int alive; + msgsock = accept(sock, NULL, NULL); if (msgsock == -1) @@ -551,12 +587,24 @@ int main(int argc, char *argv[]) do { - doc = get_request(msgsock, &part_no); - logmsg("Received request, now send response"); - send_doc(msgsock, doc, part_no); + doc = get_request(msgsock, &part_no, &open); + logmsg("Received request, now send response number %d part %d", + doc, part_no); + send_doc(msgsock, doc, part_no, &alive); + + if((doc < 0) && (doc != DOCNUMBER_CONNECT)) { + logmsg("special request received, no persistancy"); + break; + } + if(!alive) { + logmsg("instructed to close connection after server-reply"); + break; + } + if(open) + logmsg("persistant connection, awaits new request"); /* if we got a CONNECT, loop and get another request as well! */ - } while(doc == DOCNUMBER_CONNECT); + } while(open); logmsg("Closing client connection"); close(msgsock); -- cgit v1.2.1 From 5ef6520d4ed043e40876b309feb5a83808f0dc28 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 19 Jul 2003 23:54:15 +0000 Subject: fixed the CONNECT thing again --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index bb29a3dc8..0157d9e5c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -604,7 +604,7 @@ int main(int argc, char *argv[]) if(open) logmsg("persistant connection, awaits new request"); /* if we got a CONNECT, loop and get another request as well! */ - } while(open); + } while(open || (doc == DOCNUMBER_CONNECT)); logmsg("Closing client connection"); close(msgsock); -- cgit v1.2.1 From 20943292ff60b10ec6a7c8d10f42b8ee3fb766bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 15 Sep 2003 21:42:46 +0000 Subject: make the NTLM part numbers get increased instead of plainly assigned, as this then makes redirection tests work (as the new test 89) --- tests/server/sws.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0157d9e5c..147de9af4 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -308,6 +308,8 @@ static int get_request(int sock, int *part, int *open) *part = test_no % 10000; test_no /= 10000; } + else + *part = 0; sprintf(logbuf, "Found test number %d in path", test_no); logmsg(logbuf); @@ -316,18 +318,18 @@ static int get_request(int sock, int *part, int *open) /* If the client is passing this Digest-header, we set the part number to 1000. Not only to spice up the complexity of this, but to make Digest stuff to work in the test suite. */ - logmsg("Received Digest request, sending back data 1000"); - *part = 1000; + *part += 1000; + logmsg("Received Digest request, sending back data %d", *part); } else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { /* If the client is passing this type-3 NTLM header */ - logmsg("Received NTLM type-3, sending back data 1002"); - *part = 1002; + *part += 1002; + logmsg("Received NTLM type-3, sending back data %d", *part); } else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { /* If the client is passing this type-1 NTLM header */ - logmsg("Received NTLM type-1, sending back data 1001"); - *part = 1001; + *part += 1001; + logmsg("Received NTLM type-1, sending back data %d", *part); } if(strstr(reqbuf, "Connection: close")) -- cgit v1.2.1 From c29740f0d808e49e8fc1d300675be368816d0007 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 9 Oct 2003 08:12:43 +0000 Subject: portability fix by using setup.h from the lib directory --- tests/server/sws.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 147de9af4..8ee2e96ef 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -27,6 +27,7 @@ Wilke. Thanks a bunch! */ +#include "setup.h" /* portability help from the lib directory */ #include #include @@ -64,7 +65,7 @@ spitout(FILE *stream, #define DEFAULT_LOGFILE "log/sws.log" #endif -#define VERSION "cURL test suite HTTP server/0.1" +#define SWSVERSION "cURL test suite HTTP server/0.1" #define REQUEST_DUMP "log/server.input" #define RESPONSE_DUMP "log/server.response" @@ -98,7 +99,7 @@ static const char *docbadconnect = /* send back this on 404 file not found */ static const char *doc404 = "HTTP/1.1 404 Not Found\n" - "Server: " VERSION "\n" + "Server: " SWSVERSION "\n" "Connection: close\n" "Content-Type: text/html\n" "\n" @@ -108,7 +109,7 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\n" "\n" "

Not Found

\n" "The requested URL was not found on this server.\n" - "


" VERSION "
\n" "\n"; + "


" SWSVERSION "
\n" "\n"; #ifdef HAVE_SIGNAL static volatile int sigpipe; @@ -241,7 +242,7 @@ static int get_request(int sock, int *part, int *open) *open = TRUE; /* connection should remain open and wait for more commands */ while (offset < REQBUFSIZ) { - int got = recv(sock, reqbuf + offset, REQBUFSIZ - offset, 0); + int got = sread(sock, reqbuf + offset, REQBUFSIZ - offset); if (got <= 0) { if (got < 0) { perror("recv"); @@ -471,7 +472,7 @@ static int send_doc(int sock, } do { - written = send(sock, buffer, count, 0); + written = swrite(sock, buffer, count); if (written < 0) { logmsg("Sending response failed and we bailed out!"); return -1; @@ -609,13 +610,13 @@ int main(int argc, char *argv[]) } while(open || (doc == DOCNUMBER_CONNECT)); logmsg("Closing client connection"); - close(msgsock); + sclose(msgsock); if (doc == DOCNUMBER_QUIT) break; } - close(sock); + sclose(sock); fclose(logfp); return 0; -- cgit v1.2.1 From 41535eaea9e22f330f9853200140d386b44e809c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 30 Oct 2003 07:32:04 +0000 Subject: only use siginterrupt() if it really exists on the platform --- tests/server/sws.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 8ee2e96ef..b006c2b57 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -537,6 +537,8 @@ int main(int argc, char *argv[]) #ifdef HAVE_SIGNAL signal(SIGPIPE, sigpipe_handler); +#endif +#ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, 1); #endif -- cgit v1.2.1 From 2f9f843e8a96d1ea90cc721984bc7f147d910811 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 24 Nov 2003 16:12:41 +0000 Subject: new way to trick sws to return special data on CONNECT --- tests/server/sws.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b006c2b57..36975bef5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -350,6 +350,13 @@ static int get_request(int sock, int *part, int *open) if(!strncmp(doc, "bad", 3)) /* if the host name starts with bad, we fake an error here */ test_no = DOCNUMBER_BADCONNECT; + else if(!strncmp(doc, "test", 4)) { + char *ptr = strchr(doc, ':'); + if(ptr) + test_no = atoi(ptr+1); + else + test_no = DOCNUMBER_CONNECT; + } else test_no = DOCNUMBER_CONNECT; } -- cgit v1.2.1 From 053f6c85efd0bf698f73343989474d672d0563a8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Jan 2004 09:19:33 +0000 Subject: updated year in the copyright string --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 36975bef5..a23cd9f42 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2003, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From f385b1976e911f5911fcc1b1af11c774e3605771 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 30 Jan 2004 09:27:27 +0000 Subject: when we receive a request overflow, we still dump the incoming request to the dump file to make it easier to understand and debug the situation --- tests/server/sws.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a23cd9f42..796806e7f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -262,6 +262,10 @@ static int get_request(int sock, int *part, int *open) if (offset >= REQBUFSIZ) { logmsg("Request buffer overflow, closing connection"); + /* dump the request to an external file anyway */ + reqbuf[REQBUFSIZ-1]=0; + storerequest(reqbuf); + return DOCNUMBER_INTERNAL; } reqbuf[offset]=0; -- cgit v1.2.1 From 49ab1d914c0ae90f2c98f3433f4b27118b45835f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 12 Feb 2004 14:40:08 +0000 Subject: provide a source path to the servers to make them find the tests when run outside the source dir, not needing any symlinks --- tests/server/sws.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 796806e7f..f2f465003 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -70,7 +70,10 @@ spitout(FILE *stream, #define REQUEST_DUMP "log/server.input" #define RESPONSE_DUMP "log/server.response" -#define TEST_DATA_PATH "data/test%d" +#define TEST_DATA_PATH "%s/data/test%d" + +/* global variable, where to find the 'data' dir */ +char *path="."; enum { DOCNUMBER_QUIT = -6, @@ -442,7 +445,7 @@ static int send_doc(int sock, if(0 != part_no) sprintf(partbuf, "data%d", part_no); - sprintf(filename, TEST_DATA_PATH, doc); + sprintf(filename, TEST_DATA_PATH, path, doc); stream=fopen(filename, "rb"); if(!stream) { @@ -537,9 +540,14 @@ int main(int argc, char *argv[]) int part_no; FILE *pidfile; - if(argc>1) + if(argc>1) { port = atoi(argv[1]); + if(argc>2) { + path = argv[2]; + } + } + logfp = fopen(logfile, "a"); if (!logfp) { perror(logfile); -- cgit v1.2.1 From 372b141d5b062fdf020104e1bad68b37e6508122 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Feb 2004 07:05:15 +0000 Subject: make the path const --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f2f465003..770dec049 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -73,7 +73,7 @@ spitout(FILE *stream, #define TEST_DATA_PATH "%s/data/test%d" /* global variable, where to find the 'data' dir */ -char *path="."; +const char *path="."; enum { DOCNUMBER_QUIT = -6, -- cgit v1.2.1 From 236337ce86fc4ceb5dd1b185d238a9de51e85c07 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 20 Feb 2004 07:19:18 +0000 Subject: fix protos to prevent warnings --- tests/server/sws.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 770dec049..612d39b53 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -47,6 +47,8 @@ #endif #include +#include "getpart.h" + #ifndef FALSE #define FALSE 0 #endif @@ -54,10 +56,8 @@ #define TRUE 1 #endif -const char * -spitout(FILE *stream, - const char *main, - const char *sub, int *size); +int ProcessRequest(char *request); +void storerequest(char *reqbuf); #define DEFAULT_PORT 8999 -- cgit v1.2.1 From 2cd6403011847a1a7a9e6d79b40a6a7f0fecea9e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 5 Mar 2004 08:32:11 +0000 Subject: =?UTF-8?q?Major=20rewrite=20of=20the=20test=20HTTP=20server=20to?= =?UTF-8?q?=20allow=20more=20fancy=20features=20to=20make=20better=20tests?= =?UTF-8?q?=20with=20the=20issue12-patch=20applied.=20This=20change=20also?= =?UTF-8?q?=20includes=20Andr=E9s=20Garc=EDa's=20win32-fixes.=20Made=20the?= =?UTF-8?q?=20logging=20look=20better/more=20readable=20in=20sws.log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/server/sws.c | 482 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 302 insertions(+), 180 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 612d39b53..449efa96f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -38,9 +38,12 @@ #include #include #include -#include +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif #ifdef _XOPEN_SOURCE_EXTENDED /* This define is "almost" required to build on HPUX 11 */ #include @@ -56,7 +59,35 @@ #define TRUE 1 #endif -int ProcessRequest(char *request); +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#include +#include +#define EINPROGRESS WSAEINPROGRESS +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EISCONN WSAEISCONN +#define ENOTSOCK WSAENOTSOCK +#define ECONNREFUSED WSAECONNREFUSED +#endif + +#define REQBUFSIZ 150000 +#define REQBUFSIZ_TXT "149999" + +struct httprequest { + char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ + int offset; /* size of the incoming request */ + int testno; /* test number found in the request */ + int partno; /* part number found in the request */ + int open; /* keep connection open info, as found in the request */ + bool auth_req; /* authentication required, don't wait for body unless + there's an Authorization header */ + + bool auth; /* Authorization header present in the incoming request */ + size_t cl; /* Content-Length of the incoming request */ + bool digest; /* Authorization digest header found */ + bool ntlm; /* Authorization ntlm header found */ +}; + +int ProcessRequest(struct httprequest *req); void storerequest(char *reqbuf); #define DEFAULT_PORT 8999 @@ -72,10 +103,19 @@ void storerequest(char *reqbuf); #define TEST_DATA_PATH "%s/data/test%d" +/* very-big-path support */ +#define MAXDOCNAMELEN 140000 +#define MAXDOCNAMELEN_TXT "139999" + +#define REQUEST_KEYWORD_SIZE 256 + +#define CMD_AUTH_REQUIRED "auth_required" + /* global variable, where to find the 'data' dir */ const char *path="."; enum { + DOCNUMBER_NOTHING = -7, DOCNUMBER_QUIT = -6, DOCNUMBER_BADCONNECT = -5, DOCNUMBER_INTERNAL= -4, @@ -114,32 +154,31 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\n" "The requested URL was not found on this server.\n" "


" SWSVERSION "
\n" "\n"; -#ifdef HAVE_SIGNAL +#ifdef SIGPIPE static volatile int sigpipe; #endif static FILE *logfp; - static void logmsg(const char *msg, ...) { time_t t = time(NULL); va_list ap; struct tm *curr_time = localtime(&t); - char loctime[80]; char buffer[256]; /* possible overflow if you pass in a huge string */ va_start(ap, msg); vsprintf(buffer, msg, ap); va_end(ap); - strcpy(loctime, asctime(curr_time)); - loctime[strlen(loctime) - 1] = '\0'; - fprintf(logfp, "%s: %d: %s\n", loctime, (int)getpid(), buffer); + fprintf(logfp, "%02d:%02d:%02d (%d) %s\n", + curr_time->tm_hour, + curr_time->tm_min, + curr_time->tm_sec, (int)getpid(), buffer); fflush(logfp); } -#ifdef HAVE_SIGNAL +#ifdef SIGPIPE static void sigpipe_handler(int sig) { (void)sig; /* prevent warning */ @@ -147,16 +186,134 @@ static void sigpipe_handler(int sig) } #endif -int ProcessRequest(char *request) +#define END_OF_HEADERS "\r\n\r\n" + +static char *test2file(int testno) { - char *line=request; - unsigned long contentlength=0; - char chunked=FALSE; + static char filename[256]; + sprintf(filename, TEST_DATA_PATH, path, testno); + return filename; +} -#define END_OF_HEADERS "\r\n\r\n" +int ProcessRequest(struct httprequest *req) +{ + char *line=req->reqbuf; + char chunked=FALSE; + static char request[REQUEST_KEYWORD_SIZE]; + static char doc[MAXDOCNAMELEN]; + char logbuf[256]; + int prot_major, prot_minor; char *end; - end = strstr(request, END_OF_HEADERS); + end = strstr(req->reqbuf, END_OF_HEADERS); + + /* try to figure out the request characteristics as soon as possible, but + only once! */ + if((req->testno == DOCNUMBER_NOTHING) && + sscanf(line, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + request, + doc, + &prot_major, + &prot_minor) == 4) { + char *ptr; + + /* find the last slash */ + ptr = strrchr(doc, '/'); + + /* get the number after it */ + if(ptr) { + FILE *stream; + char *filename; + char *cmd = NULL; + int cmdsize = 0; + + if((strlen(doc) + strlen(request)) < 200) + sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", + request, doc, prot_major, prot_minor); + else + sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d", + prot_major, prot_minor); + logmsg(logbuf); + + if(!strncmp("/verifiedserver", ptr, 15)) { + logmsg("Are-we-friendly question received"); + req->testno = DOCNUMBER_WERULEZ; + return 1; /* done */ + } + + if(!strncmp("/quit", ptr, 15)) { + logmsg("Request-to-quit received"); + req->testno = DOCNUMBER_QUIT; + return 1; /* done */ + } + + ptr++; /* skip the slash */ + + req->testno = strtol(ptr, &ptr, 10); + + if(req->testno > 10000) { + req->partno = req->testno % 10000; + req->testno /= 10000; + } + else + req->partno = 0; + + sprintf(logbuf, "Reqested test number %d part %d", + req->testno, req->partno); + + logmsg(logbuf); + + filename = test2file(req->testno); + + stream=fopen(filename, "rb"); + if(!stream) { + logmsg("Couldn't open test file %d", req->testno); + return 0; + } + else { + /* get the custom server control "commands" */ + cmd = (char *)spitout(stream, "reply", "servercmd", &cmdsize); + fclose(stream); + + if(cmdsize) { + logmsg("Found a reply-servercmd section!"); + + if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) { + logmsg("instructed to require authorization header"); + req->auth_req = TRUE; + } + } + } + } + else { + if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + doc, &prot_major, &prot_minor) == 3) { + sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", + doc, prot_major, prot_minor); + logmsg(logbuf); + + if(prot_major*10+prot_minor == 10) + req->open = FALSE; /* HTTP 1.0 closes connection by default */ + + 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)) { + char *ptr = strchr(doc, ':'); + if(ptr) + req->testno = atoi(ptr+1); + else + req->testno = DOCNUMBER_CONNECT; + } + else + req->testno = DOCNUMBER_CONNECT; + } + else { + logmsg("Did not find test number in PATH"); + req->testno = DOCNUMBER_404; + } + } + } if(!end) /* we don't have a complete request yet! */ @@ -174,8 +331,14 @@ int ProcessRequest(char *request) */ do { - if(!strncasecmp("Content-Length:", line, 15)) { - contentlength = strtol(line+15, &line, 10); + if(!req->cl && !strncasecmp("Content-Length:", line, 15)) { + /* If we don't ignore content-length, we read it and we read the whole + request including the body before we return. If we've been told to + ignore the content-length, we will return as soon as all headers + have been received */ + req->cl = strtol(line+15, &line, 10); + + logmsg("Found Content-Legth: %d in the request", req->cl); break; } else if(!strncasecmp("Transfer-Encoding: chunked", line, @@ -185,7 +348,7 @@ int ProcessRequest(char *request) } if(chunked) { - if(strstr(request, "\r\n0\r\n")) + if(strstr(req->reqbuf, "\r\n0\r\n")) /* end of chunks reached */ return 1; /* done */ else @@ -197,8 +360,39 @@ int ProcessRequest(char *request) line++; } while(line); - if(contentlength > 0 ) { - if(contentlength <= strlen(end+strlen(END_OF_HEADERS))) + if(!req->auth && strstr(req->reqbuf, "Authorization:")) { + req->auth = TRUE; /* Authorization: header present! */ + if(req->auth_req) + logmsg("Authorization header found, as required"); + } + + if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) { + /* If the client is passing this Digest-header, we set the part number + to 1000. Not only to spice up the complexity of this, but to make + Digest stuff to work in the test suite. */ + req->partno += 1000; + req->digest = TRUE; /* header found */ + logmsg("Received Digest request, sending back data %d", req->partno); + } + else if(!req->ntlm && + strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { + /* If the client is passing this type-3 NTLM header */ + req->partno += 1002; + req->ntlm = TRUE; /* NTLM found */ + logmsg("Received NTLM type-3, sending back data %d", req->partno); + } + else if(!req->ntlm && + strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { + /* If the client is passing this type-1 NTLM header */ + req->partno += 1001; + req->ntlm = TRUE; /* NTLM found */ + logmsg("Received NTLM type-1, sending back data %d", req->partno); + } + if(strstr(req->reqbuf, "Connection: close")) + req->open = FALSE; /* close connection after this request */ + + if(req->cl && (req->auth || !req->auth_req)) { + if(req->cl <= strlen(end+strlen(END_OF_HEADERS))) return 1; /* done */ else return 0; /* not complete yet */ @@ -223,29 +417,25 @@ void storerequest(char *reqbuf) } } +/* return 0 on success, non-zero on failure */ +static int get_request(int sock, struct httprequest *req) +{ + int fail= FALSE; + char *reqbuf = req->reqbuf; -#define REQBUFSIZ 150000 -#define REQBUFSIZ_TXT "149999" - -/* very-big-path support */ -#define MAXDOCNAMELEN 140000 -#define MAXDOCNAMELEN_TXT "139999" + /*** Init the httpreqest structure properly for the upcoming request ***/ -#define REQUEST_KEYWORD_SIZE 256 -static int get_request(int sock, int *part, int *open) -{ - static char reqbuf[REQBUFSIZ], doc[MAXDOCNAMELEN]; - static char request[REQUEST_KEYWORD_SIZE]; - unsigned int offset = 0; - int prot_major, prot_minor; - char logbuf[256]; + memset(req, 0, sizeof(struct httprequest)); - *part = 0; /* part zero equals none */ + /* here's what should not be 0 from the start */ + req->testno = DOCNUMBER_NOTHING; /* safe default */ + req->open = TRUE; /* connection should remain open and wait for more + commands */ - *open = TRUE; /* connection should remain open and wait for more commands */ + /*** end of httprequest init ***/ - while (offset < REQBUFSIZ) { - int got = sread(sock, reqbuf + offset, REQBUFSIZ - offset); + while (req->offset < REQBUFSIZ) { + int got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { perror("recv"); @@ -255,137 +445,31 @@ static int get_request(int sock, int *part, int *open) logmsg("Connection closed by client"); return DOCNUMBER_INTERNAL; } - offset += got; + req->offset += got; - reqbuf[offset] = 0; + reqbuf[req->offset] = 0; - if(ProcessRequest(reqbuf)) + if(ProcessRequest(req)) break; } - if (offset >= REQBUFSIZ) { + if (req->offset >= REQBUFSIZ) { logmsg("Request buffer overflow, closing connection"); - /* dump the request to an external file anyway */ reqbuf[REQBUFSIZ-1]=0; - storerequest(reqbuf); - - return DOCNUMBER_INTERNAL; + fail = TRUE; + /* dump the request to an external file anyway */ } - reqbuf[offset]=0; + else + reqbuf[req->offset]=0; /* dump the request to an external file */ storerequest(reqbuf); - if(sscanf(reqbuf, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", - request, - doc, - &prot_major, - &prot_minor) == 4) { - char *ptr; - int test_no=0; - - /* find the last slash */ - ptr = strrchr(doc, '/'); - - /* get the number after it */ - if(ptr) { - - if((strlen(doc) + strlen(request)) < 200) - sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", - request, doc, prot_major, prot_minor); - else - sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d", - prot_major, prot_minor); - logmsg(logbuf); - - if(!strncmp("/verifiedserver", ptr, 15)) { - logmsg("Are-we-friendly question received"); - return DOCNUMBER_WERULEZ; - } - - if(!strncmp("/quit", ptr, 15)) { - logmsg("Request-to-quit received"); - return DOCNUMBER_QUIT; - } - - ptr++; /* skip the slash */ - - test_no = strtol(ptr, &ptr, 10); - - if(test_no > 10000) { - *part = test_no % 10000; - test_no /= 10000; - } - else - *part = 0; - - sprintf(logbuf, "Found test number %d in path", test_no); - logmsg(logbuf); - - if(strstr(reqbuf, "Authorization: Digest")) { - /* If the client is passing this Digest-header, we set the part number - to 1000. Not only to spice up the complexity of this, but to make - Digest stuff to work in the test suite. */ - *part += 1000; - logmsg("Received Digest request, sending back data %d", *part); - } - else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { - /* If the client is passing this type-3 NTLM header */ - *part += 1002; - logmsg("Received NTLM type-3, sending back data %d", *part); - } - else if(strstr(reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { - /* If the client is passing this type-1 NTLM header */ - *part += 1001; - logmsg("Received NTLM type-1, sending back data %d", *part); - } - - if(strstr(reqbuf, "Connection: close")) - *open = FALSE; /* close connection after this request */ - } - else { - if(sscanf(reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", - doc, - &prot_major, &prot_minor) == 3) { - sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", - doc, prot_major, prot_minor); - logmsg(logbuf); - - if(prot_major*10+prot_minor == 10) - *open = FALSE; /* HTTP 1.0 closes connection by default */ - - if(!strncmp(doc, "bad", 3)) - /* if the host name starts with bad, we fake an error here */ - test_no = DOCNUMBER_BADCONNECT; - else if(!strncmp(doc, "test", 4)) { - char *ptr = strchr(doc, ':'); - if(ptr) - test_no = atoi(ptr+1); - else - test_no = DOCNUMBER_CONNECT; - } - else - test_no = DOCNUMBER_CONNECT; - } - else { - logmsg("Did not find test number in PATH"); - test_no = DOCNUMBER_404; - } - } - - return test_no; - } - - logmsg("Got illegal request"); - fprintf(stderr, "Got illegal request\n"); - return DOCNUMBER_404; + return fail; /* success */ } /* returns -1 on failure */ -static int send_doc(int sock, - int doc, - int part_no, - int *alive) /* keep the connection alive or not */ +static int send_doc(int sock, struct httprequest *req) { int written; int count; @@ -399,13 +483,14 @@ static int send_doc(int sock, static char weare[256]; - char filename[256]; char partbuf[80]="data"; - *alive = FALSE; + req->open = FALSE; + + logmsg("Send response number %d part %d", req->testno, req->partno); - if(doc < 0) { - switch(doc) { + if(req->testno < 0) { + switch(req->testno) { case DOCNUMBER_QUIT: logmsg("Replying to QUIT"); buffer = docquit; @@ -440,12 +525,10 @@ static int send_doc(int sock, count = strlen(buffer); } else { - logmsg("Fetch response data, test %d part %d", doc, part_no); + char *filename = test2file(req->testno); - if(0 != part_no) - sprintf(partbuf, "data%d", part_no); - - sprintf(filename, TEST_DATA_PATH, path, doc); + if(0 != req->partno) + sprintf(partbuf, "data%d", req->partno); stream=fopen(filename, "rb"); if(!stream) { @@ -526,19 +609,52 @@ static int send_doc(int sock, if(cmd) free(cmd); - *alive = persistant; + req->open = persistant; return 0; } +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +static void win32_init(void) +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + + if (err != 0) { + perror("Winsock init failed"); + fprintf(logfp, "Error initializing winsock -- aborting\n"); + fclose(logfp); + exit(1); + } + + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) { + + WSACleanup(); + perror("Winsock init failed"); + fprintf(logfp, "No suitable winsock.dll found -- aborting\n"); + fclose(logfp); + exit(1); + } +} +static void win32_cleanup(void) +{ + WSACleanup(); +} +#endif + int main(int argc, char *argv[]) { struct sockaddr_in me; int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; const char *logfile = DEFAULT_LOGFILE; - int part_no; FILE *pidfile; + struct httprequest req; if(argc>1) { port = atoi(argv[1]); @@ -553,12 +669,18 @@ int main(int argc, char *argv[]) perror(logfile); exit(1); } + +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) + win32_init(); +#endif +#ifdef SIGPIPE #ifdef HAVE_SIGNAL signal(SIGPIPE, sigpipe_handler); #endif #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, 1); +#endif #endif sock = socket(AF_INET, SOCK_STREAM, 0); @@ -598,48 +720,48 @@ int main(int argc, char *argv[]) listen(sock, 5); while (1) { - int doc; - int open; - int alive; - msgsock = accept(sock, NULL, NULL); if (msgsock == -1) continue; - logmsg("New client connected"); + logmsg("** New client connected"); do { + if(get_request(msgsock, &req)) + /* non-zero means error, break out of loop */ + break; - doc = get_request(msgsock, &part_no, &open); - logmsg("Received request, now send response number %d part %d", - doc, part_no); - send_doc(msgsock, doc, part_no, &alive); + send_doc(msgsock, &req); - if((doc < 0) && (doc != DOCNUMBER_CONNECT)) { + if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { logmsg("special request received, no persistancy"); break; } - if(!alive) { + if(!req.open) { logmsg("instructed to close connection after server-reply"); break; } - if(open) + if(req.open) logmsg("persistant connection, awaits new request"); /* if we got a CONNECT, loop and get another request as well! */ - } while(open || (doc == DOCNUMBER_CONNECT)); + } while(req.open || (req.testno == DOCNUMBER_CONNECT)); - logmsg("Closing client connection"); + logmsg("** Closing client connection"); sclose(msgsock); - if (doc == DOCNUMBER_QUIT) + if (req.testno == DOCNUMBER_QUIT) break; } sclose(sock); fclose(logfp); +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) + win32_cleanup(); +#endif + return 0; } -- cgit v1.2.1 From 8cbfe5d24aaf35054d9096fae57d5490dcfcef40 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 9 Mar 2004 08:38:25 +0000 Subject: =?UTF-8?q?Andr=E9s=20Garc=EDa-fix=20to=20make=20it=20build=20with?= =?UTF-8?q?=20mingw?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/server/sws.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 449efa96f..0d86c87e6 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -48,7 +48,9 @@ /* This define is "almost" required to build on HPUX 11 */ #include #endif +#ifdef HAVE_NETDB_H #include +#endif #include "getpart.h" -- cgit v1.2.1 From 0fd88d7c8fd0c4942192e63f46f671440dfd27f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Mar 2004 08:50:28 +0000 Subject: minor variable type cleanups --- tests/server/sws.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0d86c87e6..c7d11c55e 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -77,7 +77,7 @@ struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ int offset; /* size of the incoming request */ - int testno; /* test number found in the request */ + long testno; /* test number found in the request */ int partno; /* part number found in the request */ int open; /* keep connection open info, as found in the request */ bool auth_req; /* authentication required, don't wait for body unless @@ -227,7 +227,7 @@ int ProcessRequest(struct httprequest *req) FILE *stream; char *filename; char *cmd = NULL; - int cmdsize = 0; + size_t cmdsize = 0; if((strlen(doc) + strlen(request)) < 200) sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", @@ -260,7 +260,7 @@ int ProcessRequest(struct httprequest *req) else req->partno = 0; - sprintf(logbuf, "Reqested test number %d part %d", + sprintf(logbuf, "Reqested test number %ld part %d", req->testno, req->partno); logmsg(logbuf); @@ -474,12 +474,12 @@ static int get_request(int sock, struct httprequest *req) static int send_doc(int sock, struct httprequest *req) { int written; - int count; + size_t count; const char *buffer; char *ptr; FILE *stream; char *cmd=NULL; - int cmdsize=0; + size_t cmdsize=0; FILE *dump; int persistant = TRUE; @@ -659,7 +659,7 @@ int main(int argc, char *argv[]) struct httprequest req; if(argc>1) { - port = atoi(argv[1]); + port = (unsigned short)atoi(argv[1]); if(argc>2) { path = argv[2]; -- cgit v1.2.1 From 2ff9f55001b609a72ba954af0ceb6e4d7bed1598 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 31 Mar 2004 11:50:44 +0000 Subject: Added "swsbounce" magic: if this keyword is present in a section it sets the "swsbounce" magic mode. If there follows a request for the SAME test number and the SAME part number, this mode will make the server bump the part number internally and thus return a different section than it otherwise would. Test case 153 uses this in case you need an example. It is pretty involved and hard-to-use, but then the situation is pretty special over all. Enjoy. --- tests/server/sws.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index c7d11c55e..fa93b1342 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -74,15 +74,20 @@ #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" +long prevtestno=-1; /* previous test number we served */ +long prevpartno=-1; /* previous part number we served */ +bool prevbounce; /* instructs the server to increase the part number for + a test in case the identical testno+partno request + shows up again */ + struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ int offset; /* size of the incoming request */ long testno; /* test number found in the request */ - int partno; /* part number found in the request */ + long partno; /* part number found in the request */ int open; /* keep connection open info, as found in the request */ bool auth_req; /* authentication required, don't wait for body unless there's an Authorization header */ - bool auth; /* Authorization header present in the incoming request */ size_t cl; /* Content-Length of the incoming request */ bool digest; /* Authorization digest header found */ @@ -226,8 +231,6 @@ int ProcessRequest(struct httprequest *req) if(ptr) { FILE *stream; char *filename; - char *cmd = NULL; - size_t cmdsize = 0; if((strlen(doc) + strlen(request)) < 200) sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", @@ -260,7 +263,7 @@ int ProcessRequest(struct httprequest *req) else req->partno = 0; - sprintf(logbuf, "Reqested test number %ld part %d", + sprintf(logbuf, "Reqested test number %ld part %ld", req->testno, req->partno); logmsg(logbuf); @@ -273,6 +276,9 @@ int ProcessRequest(struct httprequest *req) return 0; } else { + char *cmd = NULL; + size_t cmdsize = 0; + /* get the custom server control "commands" */ cmd = (char *)spitout(stream, "reply", "servercmd", &cmdsize); fclose(stream); @@ -284,6 +290,7 @@ int ProcessRequest(struct httprequest *req) logmsg("instructed to require authorization header"); req->auth_req = TRUE; } + free(cmd); } } } @@ -392,7 +399,7 @@ int ProcessRequest(struct httprequest *req) } if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ - + if(req->cl && (req->auth || !req->auth_req)) { if(req->cl <= strlen(end+strlen(END_OF_HEADERS))) return 1; /* done */ @@ -426,7 +433,6 @@ static int get_request(int sock, struct httprequest *req) char *reqbuf = req->reqbuf; /*** Init the httpreqest structure properly for the upcoming request ***/ - memset(req, 0, sizeof(struct httprequest)); /* here's what should not be 0 from the start */ @@ -530,7 +536,7 @@ static int send_doc(int sock, struct httprequest *req) char *filename = test2file(req->testno); if(0 != req->partno) - sprintf(partbuf, "data%d", req->partno); + sprintf(partbuf, "data%ld", req->partno); stream=fopen(filename, "rb"); if(!stream) { @@ -569,6 +575,12 @@ static int send_doc(int sock, struct httprequest *req) persistant = FALSE; logmsg("connection close instruction swsclose found in response"); } + if(strstr(buffer, "swsbounce")) { + prevbounce = TRUE; + logmsg("enable \"swsbounce\" in the next request"); + } + else + prevbounce = FALSE; do { written = swrite(sock, buffer, count); @@ -613,6 +625,9 @@ static int send_doc(int sock, struct httprequest *req) req->open = persistant; + prevtestno = req->testno; + prevpartno = req->partno; + return 0; } @@ -734,6 +749,15 @@ int main(int argc, char *argv[]) /* non-zero means error, break out of loop */ break; + if(prevbounce) { + /* bounce treatment requested */ + if((req.testno == prevtestno) && + (req.partno == prevpartno)) { + req.partno++; + logmsg("BOUNCE part number to %ld", req.partno); + } + } + send_doc(msgsock, &req); if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { -- cgit v1.2.1 From bc119293950ec371a0536b0ffab35bad11fb4016 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 16 Apr 2004 07:01:47 +0000 Subject: remade the logging function to better deal with removed logfiles during the execution of the tests --- tests/server/sws.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fa93b1342..42d3e5a82 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -164,7 +164,6 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\n" #ifdef SIGPIPE static volatile int sigpipe; #endif -static FILE *logfp; static void logmsg(const char *msg, ...) { @@ -172,16 +171,21 @@ static void logmsg(const char *msg, ...) va_list ap; struct tm *curr_time = localtime(&t); char buffer[256]; /* possible overflow if you pass in a huge string */ + FILE *logfp; va_start(ap, msg); vsprintf(buffer, msg, ap); va_end(ap); - fprintf(logfp, "%02d:%02d:%02d (%d) %s\n", + logfp = fopen(DEFAULT_LOGFILE, "a"); + + fprintf(logfp?logfp:stderr, /* write to stderr if the logfile doesn't open */ + "%02d:%02d:%02d (%d) %s\n", curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec, (int)getpid(), buffer); - fflush(logfp); + if(logfp) + fclose(logfp); } @@ -643,8 +647,7 @@ static void win32_init(void) if (err != 0) { perror("Winsock init failed"); - fprintf(logfp, "Error initializing winsock -- aborting\n"); - fclose(logfp); + logmsg("Error initializing winsock -- aborting\n"); exit(1); } @@ -653,8 +656,7 @@ static void win32_init(void) WSACleanup(); perror("Winsock init failed"); - fprintf(logfp, "No suitable winsock.dll found -- aborting\n"); - fclose(logfp); + logmsg("No suitable winsock.dll found -- aborting\n"); exit(1); } } @@ -669,7 +671,6 @@ int main(int argc, char *argv[]) struct sockaddr_in me; int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; - const char *logfile = DEFAULT_LOGFILE; FILE *pidfile; struct httprequest req; @@ -680,12 +681,6 @@ int main(int argc, char *argv[]) path = argv[2]; } } - - logfp = fopen(logfile, "a"); - if (!logfp) { - perror(logfile); - exit(1); - } #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) win32_init(); @@ -703,8 +698,7 @@ int main(int argc, char *argv[]) sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("opening stream socket"); - fprintf(logfp, "Error opening socket -- aborting\n"); - fclose(logfp); + logmsg("Error opening socket -- aborting\n"); exit(1); } @@ -720,8 +714,7 @@ int main(int argc, char *argv[]) me.sin_port = htons(port); if (bind(sock, (struct sockaddr *) &me, sizeof me) < 0) { perror("binding stream socket"); - fprintf(logfp, "Error binding socket -- aborting\n"); - fclose(logfp); + logmsg("Error binding socket -- aborting\n"); exit(1); } @@ -782,7 +775,6 @@ int main(int argc, char *argv[]) } sclose(sock); - fclose(logfp); #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) win32_cleanup(); -- cgit v1.2.1 From 25e98179be96184d733dd6b793a387b349d79287 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 17 Apr 2004 11:38:41 +0000 Subject: Gisle Vanem: patches to make sws.c compile under MingW/MSVC is attached. And some cosmetic fixes. --- tests/server/sws.c | 73 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 42d3e5a82..96a302ffd 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -33,11 +33,14 @@ #include #include #include -#include #include #include #include #include + +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -61,14 +64,23 @@ #define TRUE 1 #endif -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#if defined(WIN32) && !defined(__CYGWIN__) #include #include +#include + +#define sleep(sec) Sleep ((sec)*1000) +#ifdef _MSC_VER +#define strncasecmp strnicmp +#endif + #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EISCONN WSAEISCONN #define ENOTSOCK WSAENOTSOCK #define ECONNREFUSED WSAECONNREFUSED + +static void win32_cleanup(void); #endif #define REQBUFSIZ 150000 @@ -118,6 +130,8 @@ void storerequest(char *reqbuf); #define CMD_AUTH_REQUIRED "auth_required" +#define END_OF_HEADERS "\r\n\r\n" + /* global variable, where to find the 'data' dir */ const char *path="."; @@ -134,25 +148,22 @@ enum { /* sent as reply to a QUIT */ static const char *docquit = -"HTTP/1.1 200 Goodbye\r\n" -"\r\n"; +"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\r\n" -"\r\n"; +"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\r\n" -"\r\n"; +"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\n" - "Server: " SWSVERSION "\n" - "Connection: close\n" - "Content-Type: text/html\n" - "\n" +static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" + "Server: " SWSVERSION "\r\n" + "Connection: close\r\n" + "Content-Type: text/html" + END_OF_HEADERS "\n" "\n" "404 Not Found\n" @@ -162,7 +173,7 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\n" "


" SWSVERSION "
\n" "\n"; #ifdef SIGPIPE -static volatile int sigpipe; +static volatile int sigpipe; /* Why? It's not used */ #endif static void logmsg(const char *msg, ...) @@ -197,7 +208,23 @@ static void sigpipe_handler(int sig) } #endif -#define END_OF_HEADERS "\r\n\r\n" +#if defined(WIN32) && !defined(__CYGWIN__) +#undef perror +#define perror(m) win32_perror(m) + +static void win32_perror (const char *msg) +{ + char buf[256]; + DWORD err = WSAGetLastError(); + + if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, sizeof(buf), NULL)) + snprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err); + if (msg) + fprintf(stderr, "%s: ", msg); + fprintf(stderr, "%s\n", buf); +} +#endif static char *test2file(int testno) { @@ -267,7 +294,7 @@ int ProcessRequest(struct httprequest *req) else req->partno = 0; - sprintf(logbuf, "Reqested test number %ld part %ld", + sprintf(logbuf, "Requested test number %ld part %ld", req->testno, req->partno); logmsg(logbuf); @@ -577,7 +604,7 @@ static int send_doc(int sock, struct httprequest *req) client... */ if(strstr(buffer, "swsclose") || !count) { persistant = FALSE; - logmsg("connection close instruction swsclose found in response"); + logmsg("connection close instruction \"swsclose\" found in response"); } if(strstr(buffer, "swsbounce")) { prevbounce = TRUE; @@ -635,7 +662,7 @@ static int send_doc(int sock, struct httprequest *req) return 0; } -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#if defined(WIN32) && !defined(__CYGWIN__) static void win32_init(void) { WORD wVersionRequested; @@ -647,7 +674,7 @@ static void win32_init(void) if (err != 0) { perror("Winsock init failed"); - logmsg("Error initializing winsock -- aborting\n"); + logmsg("Error initialising winsock -- aborting\n"); exit(1); } @@ -684,7 +711,8 @@ int main(int argc, char *argv[]) #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) win32_init(); -#endif + atexit(win32_cleanup); +#else #ifdef SIGPIPE #ifdef HAVE_SIGNAL @@ -693,6 +721,7 @@ int main(int argc, char *argv[]) #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, 1); #endif +#endif #endif sock = socket(AF_INET, SOCK_STREAM, 0); @@ -776,10 +805,6 @@ int main(int argc, char *argv[]) sclose(sock); -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) - win32_cleanup(); -#endif - return 0; } -- cgit v1.2.1 From e373f1fd739e653c71fbcb19669d5a021a39ec86 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 21 Apr 2004 06:56:54 +0000 Subject: log the WAIT command --- tests/server/sws.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 96a302ffd..ebfa19759 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -639,8 +639,10 @@ static int send_doc(int sock, struct httprequest *req) char *ptr=cmd; do { if(2 == sscanf(ptr, "%31s %d", command, &num)) { - if(!strcmp("wait", command)) + if(!strcmp("wait", command)) { + logmsg("Told to sleep for %d seconds", num); sleep(num); /* wait this many seconds */ + } else logmsg("Unknown command in reply command section"); } -- cgit v1.2.1 From 15f9a93c25ac3ff26dfd1b85e3f746ef1efe0254 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 30 Apr 2004 05:51:37 +0000 Subject: include the full size of the sent response in the log --- tests/server/sws.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ebfa19759..b79b40c3e 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -519,6 +519,7 @@ static int send_doc(int sock, struct httprequest *req) size_t cmdsize=0; FILE *dump; int persistant = TRUE; + size_t responsesize; static char weare[256]; @@ -613,6 +614,8 @@ static int send_doc(int sock, struct httprequest *req) else prevbounce = FALSE; + + responsesize = count; do { written = swrite(sock, buffer, count); if (written < 0) { @@ -628,7 +631,7 @@ static int send_doc(int sock, struct httprequest *req) fclose(dump); - logmsg("Response sent!"); + logmsg("Response sent (%d bytes)!", responsesize); if(ptr) free(ptr); -- cgit v1.2.1 From 933f7cecaef4927592923de3ce649c671416881a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 6 May 2004 12:44:08 +0000 Subject: int/long fix --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b79b40c3e..dabcffa41 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -226,7 +226,7 @@ static void win32_perror (const char *msg) } #endif -static char *test2file(int testno) +static char *test2file(long testno) { static char filename[256]; sprintf(filename, TEST_DATA_PATH, path, testno); -- cgit v1.2.1 From 0aa7d11cc9cd96c50923dd45830a7baf2f6981f7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 6 May 2004 13:21:32 +0000 Subject: %ld for long --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index dabcffa41..31dea2ac5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -120,7 +120,7 @@ void storerequest(char *reqbuf); #define REQUEST_DUMP "log/server.input" #define RESPONSE_DUMP "log/server.response" -#define TEST_DATA_PATH "%s/data/test%d" +#define TEST_DATA_PATH "%s/data/test%ld" /* very-big-path support */ #define MAXDOCNAMELEN 140000 -- cgit v1.2.1 From da6eea9b38f2faf86fc11eac318042b0ac6a0969 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 28 May 2004 09:52:15 +0000 Subject: delete trailing whitespace --- tests/server/sws.c | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 31dea2ac5..7c345efba 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -49,7 +49,7 @@ #endif #ifdef _XOPEN_SOURCE_EXTENDED /* This define is "almost" required to build on HPUX 11 */ -#include +#include #endif #ifdef HAVE_NETDB_H #include @@ -183,7 +183,7 @@ static void logmsg(const char *msg, ...) struct tm *curr_time = localtime(&t); char buffer[256]; /* possible overflow if you pass in a huge string */ FILE *logfp; - + va_start(ap, msg); vsprintf(buffer, msg, ap); va_end(ap); @@ -270,7 +270,7 @@ int ProcessRequest(struct httprequest *req) sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d", prot_major, prot_minor); logmsg(logbuf); - + if(!strncmp("/verifiedserver", ptr, 15)) { logmsg("Are-we-friendly question received"); req->testno = DOCNUMBER_WERULEZ; @@ -306,7 +306,7 @@ int ProcessRequest(struct httprequest *req) logmsg("Couldn't open test file %d", req->testno); return 0; } - else { + else { char *cmd = NULL; size_t cmdsize = 0; @@ -328,7 +328,7 @@ int ProcessRequest(struct httprequest *req) else { if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", doc, &prot_major, &prot_minor) == 3) { - sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", + sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", doc, prot_major, prot_minor); logmsg(logbuf); @@ -500,7 +500,7 @@ static int get_request(int sock, struct httprequest *req) } else reqbuf[req->offset]=0; - + /* dump the request to an external file */ storerequest(reqbuf); @@ -587,7 +587,7 @@ static int send_doc(int sock, struct httprequest *req) logmsg("Couldn't open test file"); return 0; } - else { + else { /* get the custom server control "commands" */ cmd = (char *)spitout(stream, "reply", "postcmd", &cmdsize); fclose(stream); @@ -670,23 +670,23 @@ static int send_doc(int sock, struct httprequest *req) #if defined(WIN32) && !defined(__CYGWIN__) static void win32_init(void) { - WORD wVersionRequested; - WSADATA wsaData; - int err; - wVersionRequested = MAKEWORD(2, 0); - - err = WSAStartup(wVersionRequested, &wsaData); - + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { perror("Winsock init failed"); logmsg("Error initialising winsock -- aborting\n"); exit(1); } - - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 0 ) { - - WSACleanup(); + + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) { + + WSACleanup(); perror("Winsock init failed"); logmsg("No suitable winsock.dll found -- aborting\n"); exit(1); @@ -705,7 +705,7 @@ int main(int argc, char *argv[]) unsigned short port = DEFAULT_PORT; FILE *pidfile; struct httprequest req; - + if(argc>1) { port = (unsigned short)atoi(argv[1]); @@ -713,7 +713,7 @@ int main(int argc, char *argv[]) path = argv[2]; } } - + #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) win32_init(); atexit(win32_cleanup); @@ -765,10 +765,10 @@ int main(int argc, char *argv[]) while (1) { msgsock = accept(sock, NULL, NULL); - + if (msgsock == -1) continue; - + logmsg("** New client connected"); do { @@ -807,9 +807,9 @@ int main(int argc, char *argv[]) if (req.testno == DOCNUMBER_QUIT) break; } - + sclose(sock); - + return 0; } -- cgit v1.2.1 From 0a83fa90bb600220f8578569cf2aec8414a4a5e1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 15 Jun 2004 10:28:56 +0000 Subject: skip the pid from the logging --- tests/server/sws.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7c345efba..e420be855 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -191,10 +191,10 @@ static void logmsg(const char *msg, ...) logfp = fopen(DEFAULT_LOGFILE, "a"); fprintf(logfp?logfp:stderr, /* write to stderr if the logfile doesn't open */ - "%02d:%02d:%02d (%d) %s\n", + "%02d:%02d:%02d %s\n", curr_time->tm_hour, curr_time->tm_min, - curr_time->tm_sec, (int)getpid(), buffer); + curr_time->tm_sec, buffer); if(logfp) fclose(logfp); } -- cgit v1.2.1 From 67341c4cbe16f333877a366dcf1924e063c26013 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 21 Jun 2004 14:00:11 +0000 Subject: when the client disconnects prematurely, dump the request as received thus far --- tests/server/sws.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e420be855..689ef1d64 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -482,6 +482,10 @@ static int get_request(int sock, struct httprequest *req) return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); + reqbuf[req->offset]=0; + + /* dump the request receivied so far to the external file */ + storerequest(reqbuf); return DOCNUMBER_INTERNAL; } req->offset += got; -- cgit v1.2.1 From 2a701a1aac498b04f917b671291431b9b5e9cea6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 22 Jun 2004 06:44:14 +0000 Subject: modified some logging output --- tests/server/sws.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 689ef1d64..9922b09ce 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -447,10 +447,12 @@ void storerequest(char *reqbuf) dump = fopen(REQUEST_DUMP, "ab"); /* b is for windows-preparing */ if(dump) { - fwrite(reqbuf, 1, strlen(reqbuf), dump); + size_t len = strlen(reqbuf); + fwrite(reqbuf, 1, len, dump); fclose(dump); - logmsg("Wrote request input to " REQUEST_DUMP); + logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP, + (int)len); } else { logmsg("Failed to write request input to " REQUEST_DUMP); @@ -635,7 +637,8 @@ static int send_doc(int sock, struct httprequest *req) fclose(dump); - logmsg("Response sent (%d bytes)!", responsesize); + logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP, + responsesize); if(ptr) free(ptr); @@ -773,7 +776,7 @@ int main(int argc, char *argv[]) if (msgsock == -1) continue; - logmsg("** New client connected"); + logmsg("====> Client connect"); do { if(get_request(msgsock, &req)) @@ -805,7 +808,7 @@ int main(int argc, char *argv[]) /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); - logmsg("** Closing client connection"); + logmsg("====> Client disconnect"); sclose(msgsock); if (req.testno == DOCNUMBER_QUIT) -- cgit v1.2.1 From a6d4d3eeac8c6e0e8def305f3b6bcab43361a210 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 Oct 2004 22:57:24 +0000 Subject: use curlx_strnequal() from the private lib sources instead of strncasecmp() for maximum portability --- tests/server/sws.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9922b09ce..db2979175 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -55,6 +55,7 @@ #include #endif +#include "curlx.h" /* from the private lib dir */ #include "getpart.h" #ifndef FALSE @@ -70,9 +71,6 @@ #include #define sleep(sec) Sleep ((sec)*1000) -#ifdef _MSC_VER -#define strncasecmp strnicmp -#endif #define EINPROGRESS WSAEINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK @@ -371,7 +369,7 @@ int ProcessRequest(struct httprequest *req) */ do { - if(!req->cl && !strncasecmp("Content-Length:", line, 15)) { + if(!req->cl && curlx_strnequal("Content-Length:", line, 15)) { /* If we don't ignore content-length, we read it and we read the whole request including the body before we return. If we've been told to ignore the content-length, we will return as soon as all headers @@ -381,8 +379,8 @@ int ProcessRequest(struct httprequest *req) logmsg("Found Content-Legth: %d in the request", req->cl); break; } - else if(!strncasecmp("Transfer-Encoding: chunked", line, - strlen("Transfer-Encoding: chunked"))) { + else if(curlx_strnequal("Transfer-Encoding: chunked", line, + strlen("Transfer-Encoding: chunked"))) { /* chunked data coming in */ chunked = TRUE; } -- cgit v1.2.1 From 0eb8414750456a7a2584a8863b1e217e8bff88cd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 29 Nov 2004 12:10:09 +0000 Subject: Enable test cases to provide sections base64-encoded to be able to test with binary data. --- tests/server/sws.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index db2979175..a42f7ee90 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -81,6 +81,9 @@ static void win32_cleanup(void); #endif +/* include memdebug.h last */ +#include "memdebug.h" + #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" -- cgit v1.2.1 From d6c155ff476c34a908d033a014b2d052dd1f3235 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 2 Dec 2004 17:11:09 +0000 Subject: added comment about port number in CONNECT string being used as test number --- tests/server/sws.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a42f7ee90..7ca14de08 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -340,6 +340,8 @@ int ProcessRequest(struct httprequest *req) /* 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! */ char *ptr = strchr(doc, ':'); if(ptr) req->testno = atoi(ptr+1); -- cgit v1.2.1 From 18f14ae23d7b60dc25c0a08483fca443108638d7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 9 Dec 2004 09:58:25 +0000 Subject: close the connection when a bad test number was requested --- tests/server/sws.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7ca14de08..8503cf2fb 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -305,6 +305,7 @@ int ProcessRequest(struct httprequest *req) stream=fopen(filename, "rb"); if(!stream) { logmsg("Couldn't open test file %d", req->testno); + req->open = FALSE; /* closes connection */ return 0; } else { -- cgit v1.2.1 From 9b3b7ad22ea6d677e2e50f3a7d1c41214b49ae29 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 11 Dec 2004 21:41:00 +0000 Subject: HTTP IPv6 support added to the test suite --- tests/server/sws.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 10 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 8503cf2fb..269d0806c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -58,6 +58,10 @@ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" +#ifdef ENABLE_IPV6 +#define SWS_IPV6 +#endif + #ifndef FALSE #define FALSE 0 #endif @@ -709,19 +713,46 @@ static void win32_cleanup(void) } #endif +char use_ipv6=FALSE; + int main(int argc, char *argv[]) { struct sockaddr_in me; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 me6; +#endif /* ENABLE_IPV6 */ int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; FILE *pidfile; struct httprequest req; + int rc; if(argc>1) { - port = (unsigned short)atoi(argv[1]); + int arg=1; + if(!strcmp("--version", argv[arg])) { + printf("sws IPv4%s\n", +#ifdef ENABLE_IPV6 + "/IPv6" +#else + "" +#endif + ); + return 0; + } + if(!strcmp("--ipv6", argv[arg])) { +#ifdef ENABLE_IPV6 + use_ipv6=TRUE; +#endif + arg++; + } + if(argc>arg) { + + if(atoi(argv[arg])) + port = (unsigned short)atoi(argv[arg++]); + + if(argc>arg) + path = argv[arg]; - if(argc>2) { - path = argv[2]; } } @@ -740,10 +771,18 @@ int main(int argc, char *argv[]) #endif #endif - sock = socket(AF_INET, SOCK_STREAM, 0); +#ifdef ENABLE_IPV6 + if(!use_ipv6) +#endif + sock = socket(AF_INET, SOCK_STREAM, 0); +#ifdef ENABLE_IPV6 + else + sock = socket(AF_INET6, SOCK_STREAM, 0); +#endif + if (sock < 0) { perror("opening stream socket"); - logmsg("Error opening socket -- aborting\n"); + logmsg("Error opening socket"); exit(1); } @@ -754,12 +793,26 @@ int main(int argc, char *argv[]) perror("setsockopt(SO_REUSEADDR)"); } - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; - me.sin_port = htons(port); - if (bind(sock, (struct sockaddr *) &me, sizeof me) < 0) { +#ifdef ENABLE_IPV6 + if(!use_ipv6) { +#endif + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(port); + rc = bind(sock, (struct sockaddr *) &me, sizeof(me)); +#ifdef ENABLE_IPV6 + } + else { + memset(&me6, 0, sizeof(struct sockaddr_in6)); + me6.sin6_family = AF_INET6; + me6.sin6_addr = in6addr_any; + me6.sin6_port = htons(port); + rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6)); + } +#endif /* ENABLE_IPV6 */ + if(rc < 0) { perror("binding stream socket"); - logmsg("Error binding socket -- aborting\n"); + logmsg("Error binding socket"); exit(1); } @@ -771,6 +824,14 @@ int main(int argc, char *argv[]) else fprintf(stderr, "Couldn't write pid file\n"); + logmsg("Running IPv%d version", +#ifdef ENABLE_IPV6 + (use_ipv6?6:4) +#else + 4 +#endif + ); + /* start accepting connections */ listen(sock, 5); -- cgit v1.2.1 From 22a0c57746ae12506b1ba0f0fafffd26c1907d6a Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 12 Dec 2004 20:14:25 +0000 Subject: Missing 'in6addr_any' in MingW's lib. ld bug? --- tests/server/sws.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 269d0806c..b9a57aac3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -83,6 +83,10 @@ #define ECONNREFUSED WSAECONNREFUSED static void win32_cleanup(void); + +#if defined(ENABLE_IPV6) && defined(__MINGW32__) +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; +#endif #endif /* include memdebug.h last */ -- cgit v1.2.1 From d02b2c430874819c0ad6a9d8cf1e75721bc529d4 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Mon, 13 Dec 2004 11:31:01 +0000 Subject: Fixed missing braces warning. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b9a57aac3..f690ab3e1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -85,7 +85,7 @@ static void win32_cleanup(void); #if defined(ENABLE_IPV6) && defined(__MINGW32__) -const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; #endif #endif -- cgit v1.2.1 From dc28a9c0c19c324a0740669e3cc71e80b07a848e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Dec 2004 21:52:16 +0000 Subject: make sure the ipv6 http server gets its pid stored in a separate file --- tests/server/sws.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f690ab3e1..f53da9054 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -728,11 +728,12 @@ int main(int argc, char *argv[]) int sock, msgsock, flag; unsigned short port = DEFAULT_PORT; FILE *pidfile; + char *pidname= (char *)".http.pid"; struct httprequest req; int rc; + int arg=1; - if(argc>1) { - int arg=1; + while(argc>arg) { if(!strcmp("--version", argv[arg])) { printf("sws IPv4%s\n", #ifdef ENABLE_IPV6 @@ -743,20 +744,24 @@ int main(int argc, char *argv[]) ); return 0; } - if(!strcmp("--ipv6", argv[arg])) { + else if(!strcmp("--pidfile", argv[arg])) { + arg++; + if(argc>arg) + pidname = argv[arg++]; + } + else if(!strcmp("--ipv6", argv[arg])) { #ifdef ENABLE_IPV6 use_ipv6=TRUE; #endif arg++; } - if(argc>arg) { + else if(argc>arg) { if(atoi(argv[arg])) port = (unsigned short)atoi(argv[arg++]); if(argc>arg) - path = argv[arg]; - + path = argv[arg++]; } } @@ -820,7 +825,7 @@ int main(int argc, char *argv[]) exit(1); } - pidfile = fopen(".http.pid", "w"); + pidfile = fopen(pidname, "w"); if(pidfile) { fprintf(pidfile, "%d\n", (int)getpid()); fclose(pidfile); -- cgit v1.2.1 From 31443724c63d5c82b7ce9cc13528dc8388cfc0c9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 28 Mar 2005 22:15:17 +0000 Subject: modified some log outputs, added comment about auth required as used in test 154 --- tests/server/sws.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f53da9054..026874d74 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -390,7 +390,7 @@ int ProcessRequest(struct httprequest *req) have been received */ req->cl = strtol(line+15, &line, 10); - logmsg("Found Content-Legth: %d in the request", req->cl); + logmsg("Found Content-Length: %d in the request", req->cl); break; } else if(curlx_strnequal("Transfer-Encoding: chunked", line, @@ -431,7 +431,10 @@ int ProcessRequest(struct httprequest *req) /* If the client is passing this type-3 NTLM header */ req->partno += 1002; req->ntlm = TRUE; /* NTLM found */ - logmsg("Received NTLM type-3, sending back data %d", req->partno); + logmsg("Received NTLM type-3, xxxxxxxxxxxxx sending back data %d", req->partno); + if(req->cl) { + logmsg(" Expecting %d POSTed bytes", req->cl); + } } else if(!req->ntlm && strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) { @@ -443,7 +446,14 @@ int ProcessRequest(struct httprequest *req) if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ - if(req->cl && (req->auth || !req->auth_req)) { + /* If authentication is required and no auth was provided, end now. This + makes the server NOT wait for PUT/POST data and you can then make the + test case send a rejection before any such data has been sent. Test case + 154 uses this.*/ + if(req->auth_req && !req->auth) + return 1; + + if(req->cl) { if(req->cl <= strlen(end+strlen(END_OF_HEADERS))) return 1; /* done */ else @@ -878,7 +888,7 @@ int main(int argc, char *argv[]) } if(req.open) - logmsg("persistant connection, awaits new request"); + logmsg("=> persistant connection request ended, awaits new request"); /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); -- cgit v1.2.1 From ab4086bc244bf3267976e9f0193e5ed4430190d8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 31 Mar 2005 07:02:02 +0000 Subject: Updated the copyright year since changes have been this year. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 026874d74..ff24dfe83 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 3bcfe678ab8f61fc589f1a2f617eedf1f7835205 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 27 Apr 2005 12:27:23 +0000 Subject: display listening port in log --- tests/server/sws.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ff24dfe83..3000579f2 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -843,13 +843,13 @@ int main(int argc, char *argv[]) else fprintf(stderr, "Couldn't write pid file\n"); - logmsg("Running IPv%d version", + logmsg("Running IPv%d version on port %d", #ifdef ENABLE_IPV6 (use_ipv6?6:4) #else 4 #endif - ); + , port ); /* start accepting connections */ listen(sock, 5); -- cgit v1.2.1 From 23da55a9f14ff5c48f0bc297f1ff745eb3dc7554 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 30 Apr 2005 23:30:55 +0000 Subject: Moved common code to util.[ch] instead of having it duplicated in sws.c and sockfilt.c. For good-to-have functions for the servers written in C. --- tests/server/sws.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 3000579f2..852b27a2e 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -57,6 +57,7 @@ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" +#include "util.h" #ifdef ENABLE_IPV6 #define SWS_IPV6 @@ -124,6 +125,8 @@ void storerequest(char *reqbuf); #define DEFAULT_LOGFILE "log/sws.log" #endif +const char *serverlogfile = DEFAULT_LOGFILE; + #define SWSVERSION "cURL test suite HTTP server/0.1" #define REQUEST_DUMP "log/server.input" @@ -185,30 +188,6 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" static volatile int sigpipe; /* Why? It's not used */ #endif -static void logmsg(const char *msg, ...) -{ - time_t t = time(NULL); - va_list ap; - struct tm *curr_time = localtime(&t); - char buffer[256]; /* possible overflow if you pass in a huge string */ - FILE *logfp; - - va_start(ap, msg); - vsprintf(buffer, msg, ap); - va_end(ap); - - logfp = fopen(DEFAULT_LOGFILE, "a"); - - fprintf(logfp?logfp:stderr, /* write to stderr if the logfile doesn't open */ - "%02d:%02d:%02d %s\n", - curr_time->tm_hour, - curr_time->tm_min, - curr_time->tm_sec, buffer); - if(logfp) - fclose(logfp); -} - - #ifdef SIGPIPE static void sigpipe_handler(int sig) { -- cgit v1.2.1 From 366b62af2d8d0f166da75b149309228570f7d981 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 1 May 2005 12:56:09 +0000 Subject: always use the libcurl-provided *printf() functions --- tests/server/sws.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 852b27a2e..161cea678 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -55,6 +55,9 @@ #include #endif +#define ENABLE_CURLX_PRINTF +/* make the curlx header define all printf() functions to use the curlx_* + versions instead */ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" #include "util.h" -- cgit v1.2.1 From 84fd4686e2fa9dfed265cdd7a941bc0df1ce4821 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 17 May 2005 10:22:22 +0000 Subject: Moved more generic functions to util.[ch] Added resolve.c to simply resolve a given host name --- tests/server/sws.c | 80 ------------------------------------------------------ 1 file changed, 80 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 161cea678..d5a80c851 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -62,37 +62,6 @@ #include "getpart.h" #include "util.h" -#ifdef ENABLE_IPV6 -#define SWS_IPV6 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -#if defined(WIN32) && !defined(__CYGWIN__) -#include -#include -#include - -#define sleep(sec) Sleep ((sec)*1000) - -#define EINPROGRESS WSAEINPROGRESS -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EISCONN WSAEISCONN -#define ENOTSOCK WSAENOTSOCK -#define ECONNREFUSED WSAECONNREFUSED - -static void win32_cleanup(void); - -#if defined(ENABLE_IPV6) && defined(__MINGW32__) -const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; -#endif -#endif - /* include memdebug.h last */ #include "memdebug.h" @@ -199,24 +168,6 @@ static void sigpipe_handler(int sig) } #endif -#if defined(WIN32) && !defined(__CYGWIN__) -#undef perror -#define perror(m) win32_perror(m) - -static void win32_perror (const char *msg) -{ - char buf[256]; - DWORD err = WSAGetLastError(); - - if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - LANG_NEUTRAL, buf, sizeof(buf), NULL)) - snprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err); - if (msg) - fprintf(stderr, "%s: ", msg); - fprintf(stderr, "%s\n", buf); -} -#endif - static char *test2file(long testno) { static char filename[256]; @@ -678,37 +629,6 @@ static int send_doc(int sock, struct httprequest *req) return 0; } -#if defined(WIN32) && !defined(__CYGWIN__) -static void win32_init(void) -{ - WORD wVersionRequested; - WSADATA wsaData; - int err; - wVersionRequested = MAKEWORD(2, 0); - - err = WSAStartup(wVersionRequested, &wsaData); - - if (err != 0) { - perror("Winsock init failed"); - logmsg("Error initialising winsock -- aborting\n"); - exit(1); - } - - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 0 ) { - - WSACleanup(); - perror("Winsock init failed"); - logmsg("No suitable winsock.dll found -- aborting\n"); - exit(1); - } -} -static void win32_cleanup(void) -{ - WSACleanup(); -} -#endif - char use_ipv6=FALSE; int main(int argc, char *argv[]) -- cgit v1.2.1 From 4a091bbd8a30685d4f676a023c0488abb0469d3f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 18 May 2005 20:01:01 +0000 Subject: Bug report #1204435 identified a problem with malformed URLs like "http://somehost?data" as it added a slash too much in the request ("GET /?data/"...). Added test case 260 to verify. --- tests/server/sws.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d5a80c851..df0a08da8 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -227,6 +227,10 @@ int ProcessRequest(struct httprequest *req) ptr++; /* skip the slash */ + /* skip all non-numericals following the slash */ + while(*ptr && !isdigit(*ptr)) + ptr++; + req->testno = strtol(ptr, &ptr, 10); if(req->testno > 10000) { @@ -247,7 +251,7 @@ int ProcessRequest(struct httprequest *req) if(!stream) { logmsg("Couldn't open test file %d", req->testno); req->open = FALSE; /* closes connection */ - return 0; + return 1; /* done */ } else { char *cmd = NULL; -- cgit v1.2.1 From b749910e6ca4288854ea40d2e0f74602678ba72f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 19 May 2005 09:55:53 +0000 Subject: include ctype.h for isdigit() --- tests/server/sws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index df0a08da8..bf19b724a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H #include @@ -228,7 +229,7 @@ int ProcessRequest(struct httprequest *req) ptr++; /* skip the slash */ /* skip all non-numericals following the slash */ - while(*ptr && !isdigit(*ptr)) + while(*ptr && !isdigit((int)*ptr)) ptr++; req->testno = strtol(ptr, &ptr, 10); -- cgit v1.2.1 From e22ac39da439dfc883debf92ffc06d8368d012bf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 18 Aug 2005 08:47:56 +0000 Subject: detabify --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index bf19b724a..bc1f48430 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -756,7 +756,7 @@ int main(int argc, char *argv[]) #else 4 #endif - , port ); + , port ); /* start accepting connections */ listen(sock, 5); -- cgit v1.2.1 From b9c8de598beefe782e2ba7d4f346feb8b549399e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 7 Sep 2005 10:51:37 +0000 Subject: Thanks to Scott Davis' detailed reports, I found this premature detection of the end of a chunked-encoded POST request. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index bc1f48430..1e341cf0d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -338,7 +338,7 @@ int ProcessRequest(struct httprequest *req) } if(chunked) { - if(strstr(req->reqbuf, "\r\n0\r\n")) + if(strstr(req->reqbuf, "\r\n0\r\n\r\n")) /* end of chunks reached */ return 1; /* done */ else -- cgit v1.2.1 From 9542dfdcdc37773d95b5a0c402fa04c6c9f7d2e7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Sep 2005 20:22:43 +0000 Subject: moved test2file() to util.c --- tests/server/sws.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1e341cf0d..5a2a15574 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -105,8 +105,6 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define REQUEST_DUMP "log/server.input" #define RESPONSE_DUMP "log/server.response" -#define TEST_DATA_PATH "%s/data/test%ld" - /* very-big-path support */ #define MAXDOCNAMELEN 140000 #define MAXDOCNAMELEN_TXT "139999" @@ -117,9 +115,6 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define END_OF_HEADERS "\r\n\r\n" -/* global variable, where to find the 'data' dir */ -const char *path="."; - enum { DOCNUMBER_NOTHING = -7, DOCNUMBER_QUIT = -6, @@ -169,14 +164,6 @@ static void sigpipe_handler(int sig) } #endif -static char *test2file(long testno) -{ - static char filename[256]; - sprintf(filename, TEST_DATA_PATH, path, testno); - return filename; -} - - int ProcessRequest(struct httprequest *req) { char *line=req->reqbuf; @@ -642,7 +629,8 @@ int main(int argc, char *argv[]) #ifdef ENABLE_IPV6 struct sockaddr_in6 me6; #endif /* ENABLE_IPV6 */ - int sock, msgsock, flag; + curl_socket_t sock, msgsock; + int flag; unsigned short port = DEFAULT_PORT; FILE *pidfile; char *pidname= (char *)".http.pid"; -- cgit v1.2.1 From 74a299fd0844db03569381929b4d3e8851f1b578 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Jan 2006 12:19:12 +0000 Subject: 1. sws now supports two new "commands" and 2. if built with CURL_SWS_FORK_ENABLED defined it forks for each new connection and thus can support any amount of connection clients (used for hiper tests and not for the standard plain curl test suite) --- tests/server/sws.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5a2a15574..270c6a3af 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -66,6 +66,13 @@ /* include memdebug.h last */ #include "memdebug.h" +/* + * The normal sws build for the plain standard curl test suite has no use for + * fork(), but if you feel wild and crazy and want to setup some more exotic + * tests. Define this and run... + */ +/*#define CURL_SWS_FORK_ENABLED 1 */ + #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" @@ -75,6 +82,10 @@ bool prevbounce; /* instructs the server to increase the part number for a test in case the identical testno+partno request shows up again */ +#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */ +#define RCMD_IDLE 1 /* told to sit idle */ +#define RCMD_STREAM 2 /* told to stream */ + struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ int offset; /* size of the incoming request */ @@ -87,6 +98,8 @@ struct httprequest { size_t cl; /* Content-Length of the incoming request */ bool digest; /* Authorization digest header found */ bool ntlm; /* Authorization ntlm header found */ + + int rcmd; /* doing a special command, see defines above */ }; int ProcessRequest(struct httprequest *req); @@ -113,6 +126,13 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define CMD_AUTH_REQUIRED "auth_required" +/* 'idle' means that it will accept the request fine but never respond + any data. Just keep the connection alive. */ +#define CMD_IDLE "idle" + +/* 'stream' means to send a never-ending stream of data */ +#define CMD_STREAM "stream" + #define END_OF_HEADERS "\r\n\r\n" enum { @@ -256,6 +276,15 @@ int ProcessRequest(struct httprequest *req) logmsg("instructed to require authorization header"); req->auth_req = TRUE; } + else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) { + logmsg("instructed to idle"); + req->rcmd = RCMD_IDLE; + req->open = TRUE; + } + else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) { + logmsg("instructed to stream"); + req->rcmd = RCMD_STREAM; + } free(cmd); } } @@ -356,7 +385,7 @@ int ProcessRequest(struct httprequest *req) /* If the client is passing this type-3 NTLM header */ req->partno += 1002; req->ntlm = TRUE; /* NTLM found */ - logmsg("Received NTLM type-3, xxxxxxxxxxxxx sending back data %d", req->partno); + logmsg("Received NTLM type-3, sending back data %d", req->partno); if(req->cl) { logmsg(" Expecting %d POSTed bytes", req->cl); } @@ -478,10 +507,30 @@ static int send_doc(int sock, struct httprequest *req) char partbuf[80]="data"; - req->open = FALSE; - logmsg("Send response number %d part %d", req->testno, req->partno); + switch(req->rcmd) { + default: + case RCMD_NORMALREQ: + break; /* continue with business as usual */ + case RCMD_STREAM: +#define STREAMTHIS "a string to stream 01234567890\n" + count = strlen(STREAMTHIS); + while(1) { + written = swrite(sock, STREAMTHIS, count); + if(written != (int)count) { + logmsg("Stopped streaming"); + return -1; + } + } + break; + case RCMD_IDLE: + /* Do nothing. Sit idle. Pretend it rains. */ + return 0; + } + + req->open = FALSE; + if(req->testno < 0) { switch(req->testno) { case DOCNUMBER_QUIT: @@ -752,9 +801,24 @@ int main(int argc, char *argv[]) while (1) { msgsock = accept(sock, NULL, NULL); - if (msgsock == -1) - continue; + if (msgsock == -1) { + printf("MAJOR ERROR: accept() failed!\n"); + break; + } + +#ifdef CURL_SWS_FORK_ENABLED + /* The fork enabled version just forks off the child and don't care + about it anymore, so don't assume otherwise. Beware and don't do + this at home. */ + rc = fork(); + if(-1 == rc) { + printf("MAJOR ERROR: fork() failed!\n"); + break; + } + /* 0 is returned to the child */ + if(0 == rc) { +#endif logmsg("====> Client connect"); do { @@ -792,6 +856,9 @@ int main(int argc, char *argv[]) if (req.testno == DOCNUMBER_QUIT) break; +#ifdef CURL_SWS_FORK_ENABLED + } +#endif } sclose(sock); -- cgit v1.2.1 From 687cf0235e1450f88dffd8276712349849ef2c6d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Jan 2006 12:18:22 +0000 Subject: modified to hush compiler warnings --- tests/server/sws.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 270c6a3af..2a9e32dcd 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -520,10 +520,10 @@ static int send_doc(int sock, struct httprequest *req) written = swrite(sock, STREAMTHIS, count); if(written != (int)count) { logmsg("Stopped streaming"); - return -1; + break; } } - break; + return -1; case RCMD_IDLE: /* Do nothing. Sit idle. Pretend it rains. */ return 0; -- cgit v1.2.1 From bda1e9aeab019d003036a3ec24193605bc191b3a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Jan 2006 13:17:14 +0000 Subject: Made the copyright year match the latest modification's year. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 2a9e32dcd..b1904b4d3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms -- cgit v1.2.1 From 10beb36b1cd1479d14b245a922e1ab49d9a8b1f9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 18 Feb 2006 22:27:01 +0000 Subject: =?UTF-8?q?Ulf=20H=E4rnhammar=20fixed=20a=20format=20string=20(pri?= =?UTF-8?q?ntf=20style)=20problem=20in=20the=20Negotiate=20code.=20It=20sh?= =?UTF-8?q?ould=20however=20not=20be=20the=20cause=20of=20any=20troubles.?= =?UTF-8?q?=20He=20also=20fixed=20a=20few=20similar=20problems=20in=20the?= =?UTF-8?q?=20HTTP=20test=20server=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b1904b4d3..4b6735cce 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -219,7 +219,7 @@ int ProcessRequest(struct httprequest *req) else sprintf(logbuf, "Got a *HUGE* request HTTP/%d.%d", prot_major, prot_minor); - logmsg(logbuf); + logmsg("%s", logbuf); if(!strncmp("/verifiedserver", ptr, 15)) { logmsg("Are-we-friendly question received"); @@ -251,7 +251,7 @@ int ProcessRequest(struct httprequest *req) sprintf(logbuf, "Requested test number %ld part %ld", req->testno, req->partno); - logmsg(logbuf); + logmsg("%s", logbuf); filename = test2file(req->testno); @@ -294,7 +294,7 @@ int ProcessRequest(struct httprequest *req) doc, &prot_major, &prot_minor) == 3) { sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", doc, prot_major, prot_minor); - logmsg(logbuf); + logmsg("%s", logbuf); if(prot_major*10+prot_minor == 10) req->open = FALSE; /* HTTP 1.0 closes connection by default */ -- cgit v1.2.1 From f592ea6c30c375b2db0f1fbd77bcd20a07719d03 Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sat, 25 Feb 2006 18:57:20 +0000 Subject: Fix typo. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 4b6735cce..44105106b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -292,7 +292,7 @@ int ProcessRequest(struct httprequest *req) else { if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", doc, &prot_major, &prot_minor) == 3) { - sprintf(logbuf, "Receiced a CONNECT %s HTTP/%d.%d request", + sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request", doc, prot_major, prot_minor); logmsg("%s", logbuf); -- cgit v1.2.1 From e5babd086da0610eaf1c9b739dd05ff50009a471 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 Apr 2006 13:11:52 +0000 Subject: if configure found a fork(), sws supports --fork which is *NOT* used by the ordinary test suite. Also removed the perror() calls and instead made the logging output the errno code to ease error tracking using logs. --- tests/server/sws.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 44105106b..6eb89e562 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -66,12 +66,14 @@ /* include memdebug.h last */ #include "memdebug.h" +#if !defined(CURL_SWS_FORK_ENABLED) && defined(HAVE_FORK) /* * The normal sws build for the plain standard curl test suite has no use for * fork(), but if you feel wild and crazy and want to setup some more exotic * tests. Define this and run... */ -/*#define CURL_SWS_FORK_ENABLED 1 */ +#define CURL_SWS_FORK_ENABLED +#endif #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" @@ -455,8 +457,7 @@ static int get_request(int sock, struct httprequest *req) int got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { - perror("recv"); - logmsg("recv() returned error"); + logmsg("recv() returned error: %d", errno); return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); @@ -686,10 +687,18 @@ int main(int argc, char *argv[]) struct httprequest req; int rc; int arg=1; +#ifdef CURL_SWS_FORK_ENABLED + bool use_fork = FALSE; +#endif while(argc>arg) { if(!strcmp("--version", argv[arg])) { - printf("sws IPv4%s\n", + printf("sws IPv4%s" +#ifdef CURL_SWS_FORK_ENABLED + " FORK" +#endif + "\n" + , #ifdef ENABLE_IPV6 "/IPv6" #else @@ -709,6 +718,12 @@ int main(int argc, char *argv[]) #endif arg++; } +#ifdef CURL_SWS_FORK_ENABLED + else if(!strcmp("--fork", argv[arg])) { + use_fork=TRUE; + arg++; + } +#endif else if(argc>arg) { if(atoi(argv[arg])) @@ -744,8 +759,7 @@ int main(int argc, char *argv[]) #endif if (sock < 0) { - perror("opening stream socket"); - logmsg("Error opening socket"); + logmsg("Error opening socket: %d", errno); exit(1); } @@ -753,7 +767,7 @@ int main(int argc, char *argv[]) if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag, sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEADDR)"); + logmsg("setsockopt(SO_REUSEADDR) failed"); } #ifdef ENABLE_IPV6 @@ -774,8 +788,7 @@ int main(int argc, char *argv[]) } #endif /* ENABLE_IPV6 */ if(rc < 0) { - perror("binding stream socket"); - logmsg("Error binding socket"); + logmsg("Error binding socket: %d", errno); exit(1); } @@ -807,15 +820,19 @@ int main(int argc, char *argv[]) } #ifdef CURL_SWS_FORK_ENABLED - /* The fork enabled version just forks off the child and don't care - about it anymore, so don't assume otherwise. Beware and don't do - this at home. */ - rc = fork(); - if(-1 == rc) { - printf("MAJOR ERROR: fork() failed!\n"); - break; + if(use_fork) { + /* The fork enabled version just forks off the child and don't care + about it anymore, so don't assume otherwise. Beware and don't do + this at home. */ + rc = fork(); + if(-1 == rc) { + printf("MAJOR ERROR: fork() failed!\n"); + break; + } } - + else + /* not a fork, just set rc so the following proceeds nicely */ + rc = 0; /* 0 is returned to the child */ if(0 == rc) { #endif -- cgit v1.2.1 From 00312e95fefe790588ae8d80714e9002c24a04a0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 May 2006 09:53:52 +0000 Subject: removed variable declarations shadowing previously declared variables --- tests/server/sws.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 6eb89e562..95429dfcd 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -307,9 +307,9 @@ int ProcessRequest(struct httprequest *req) 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! */ - char *ptr = strchr(doc, ':'); - if(ptr) - req->testno = atoi(ptr+1); + char *portp = strchr(doc, ':'); + if(portp) + req->testno = atoi(portp+1); else req->testno = DOCNUMBER_CONNECT; } @@ -643,7 +643,7 @@ static int send_doc(int sock, struct httprequest *req) if(cmdsize > 0 ) { char command[32]; int num; - char *ptr=cmd; + ptr=cmd; do { if(2 == sscanf(ptr, "%31s %d", command, &num)) { if(!strcmp("wait", command)) { -- cgit v1.2.1 From 58176d14848f315ea74772bd9ce7edd847b2a17d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Jul 2006 05:19:00 +0000 Subject: Use platform's native types for recv() and send() arguments. --- tests/server/sws.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 95429dfcd..3eff97d45 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -493,7 +493,7 @@ static int get_request(int sock, struct httprequest *req) /* returns -1 on failure */ static int send_doc(int sock, struct httprequest *req) { - int written; + ssize_t written; size_t count; const char *buffer; char *ptr; @@ -519,7 +519,7 @@ static int send_doc(int sock, struct httprequest *req) count = strlen(STREAMTHIS); while(1) { written = swrite(sock, STREAMTHIS, count); - if(written != (int)count) { + if(written != count) { logmsg("Stopped streaming"); break; } -- cgit v1.2.1 From 624e657210edf3fea36ca9dd2b448533437d0b20 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Jul 2006 05:54:06 +0000 Subject: sread now returns ssize_t --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 3eff97d45..7d1b76ea1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -454,7 +454,7 @@ static int get_request(int sock, struct httprequest *req) /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { - int got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); + ssize_t got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", errno); -- cgit v1.2.1 From 88a1a10e6fcf024c1a5690bfa0a5b94838beebd0 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Jul 2006 06:09:53 +0000 Subject: Pay attention when typecasting an operation --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7d1b76ea1..7cc0e1cbe 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -454,7 +454,7 @@ static int get_request(int sock, struct httprequest *req) /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { - ssize_t got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); + ssize_t got = sread(sock, (reqbuf + req->offset), (REQBUFSIZ - req->offset)); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", errno); -- cgit v1.2.1 From 8272874704485b57da9c3b4ea9a2511f27cc8045 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Jul 2006 06:52:40 +0000 Subject: Place parenthesis surrounding macro parameters so that the use of sread and swrite is more intuitive. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7cc0e1cbe..7d1b76ea1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -454,7 +454,7 @@ static int get_request(int sock, struct httprequest *req) /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { - ssize_t got = sread(sock, (reqbuf + req->offset), (REQBUFSIZ - req->offset)); + ssize_t got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", errno); -- cgit v1.2.1 From 95aecc5dbbd388f8e516b135bf17346e0770c447 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 12 Jul 2006 09:03:48 +0000 Subject: Fix compiler warning: comparison between signed and unsigned --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7d1b76ea1..4868651eb 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -519,7 +519,7 @@ static int send_doc(int sock, struct httprequest *req) count = strlen(STREAMTHIS); while(1) { written = swrite(sock, STREAMTHIS, count); - if(written != count) { + if(written != (ssize_t)count) { logmsg("Stopped streaming"); break; } -- cgit v1.2.1 From 42f5a90d0963bd9d72e60d8a1d61e41e2ea0f9c8 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 17 Jul 2006 22:44:40 +0000 Subject: -Use curl_socket_t instead of int. -Log errno in message if setsockopt() fails. -Close listener socket on major errors. --- tests/server/sws.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 4868651eb..db774f62a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -438,7 +438,7 @@ void storerequest(char *reqbuf) } /* return 0 on success, non-zero on failure */ -static int get_request(int sock, struct httprequest *req) +static int get_request(curl_socket_t sock, struct httprequest *req) { int fail= FALSE; char *reqbuf = req->reqbuf; @@ -491,7 +491,7 @@ static int get_request(int sock, struct httprequest *req) } /* returns -1 on failure */ -static int send_doc(int sock, struct httprequest *req) +static int send_doc(curl_socket_t sock, struct httprequest *req) { ssize_t written; size_t count; @@ -758,21 +758,23 @@ int main(int argc, char *argv[]) sock = socket(AF_INET6, SOCK_STREAM, 0); #endif - if (sock < 0) { + if (CURL_SOCKET_BAD == sock) { logmsg("Error opening socket: %d", errno); exit(1); } flag = 1; - if (setsockopt - (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag, - sizeof(int)) < 0) { - logmsg("setsockopt(SO_REUSEADDR) failed"); + if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (void *) &flag, sizeof(flag))) { + logmsg("setsockopt(SO_REUSEADDR) failed: %d", errno); + sclose(sock); + exit(1); } #ifdef ENABLE_IPV6 if(!use_ipv6) { #endif + memset(&me, 0, sizeof(me)); me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(port); @@ -780,15 +782,16 @@ int main(int argc, char *argv[]) #ifdef ENABLE_IPV6 } else { - memset(&me6, 0, sizeof(struct sockaddr_in6)); + memset(&me6, 0, sizeof(me6)); me6.sin6_family = AF_INET6; me6.sin6_addr = in6addr_any; me6.sin6_port = htons(port); rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6)); } #endif /* ENABLE_IPV6 */ - if(rc < 0) { + if(0 != rc) { logmsg("Error binding socket: %d", errno); + sclose(sock); exit(1); } @@ -797,8 +800,9 @@ int main(int argc, char *argv[]) fprintf(pidfile, "%d\n", (int)getpid()); fclose(pidfile); } - else + else { fprintf(stderr, "Couldn't write pid file\n"); + } logmsg("Running IPv%d version on port %d", #ifdef ENABLE_IPV6 @@ -809,13 +813,18 @@ int main(int argc, char *argv[]) , port ); /* start accepting connections */ - listen(sock, 5); + rc = listen(sock, 5); + if(0 != rc) { + logmsg("listen() failed with error: %d", errno); + sclose(sock); + exit(1); + } while (1) { msgsock = accept(sock, NULL, NULL); - if (msgsock == -1) { - printf("MAJOR ERROR: accept() failed!\n"); + if (CURL_SOCKET_BAD == msgsock) { + printf("MAJOR ERROR: accept() failed with error: &d\n", errno); break; } -- cgit v1.2.1 From 46c5e562bfb5ce530f7f9d0ea9d686ca6e341d2a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 19 Jul 2006 15:26:28 +0000 Subject: Abort if unable to write pid file. --- tests/server/sws.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index db774f62a..7c3ba4f7d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -802,6 +802,8 @@ int main(int argc, char *argv[]) } else { fprintf(stderr, "Couldn't write pid file\n"); + sclose(sock); + exit(1); } logmsg("Running IPv%d version on port %d", -- cgit v1.2.1 From ee3514ccdc9325a30fea3f0a5ac0a75ab6dc85d0 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 14 Aug 2006 17:00:08 +0000 Subject: Replace exit() with return() in main() --- tests/server/sws.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7c3ba4f7d..d4e6cc996 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -760,7 +760,7 @@ int main(int argc, char *argv[]) if (CURL_SOCKET_BAD == sock) { logmsg("Error opening socket: %d", errno); - exit(1); + return 1; } flag = 1; @@ -768,7 +768,7 @@ int main(int argc, char *argv[]) (void *) &flag, sizeof(flag))) { logmsg("setsockopt(SO_REUSEADDR) failed: %d", errno); sclose(sock); - exit(1); + return 1; } #ifdef ENABLE_IPV6 @@ -792,7 +792,7 @@ int main(int argc, char *argv[]) if(0 != rc) { logmsg("Error binding socket: %d", errno); sclose(sock); - exit(1); + return 1; } pidfile = fopen(pidname, "w"); @@ -803,7 +803,7 @@ int main(int argc, char *argv[]) else { fprintf(stderr, "Couldn't write pid file\n"); sclose(sock); - exit(1); + return 1; } logmsg("Running IPv%d version on port %d", @@ -819,7 +819,7 @@ int main(int argc, char *argv[]) if(0 != rc) { logmsg("listen() failed with error: %d", errno); sclose(sock); - exit(1); + return 1; } while (1) { -- cgit v1.2.1 From e3c15fc4b9e9ebc9b5e7aa056b10ae0caeaef90d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 8 Sep 2006 11:56:56 +0000 Subject: test 530 is the first ever HTTP pipelining test for libcurl --- tests/server/sws.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d4e6cc996..525163f58 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -90,6 +90,7 @@ bool prevbounce; /* instructs the server to increase the part number for struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ + int checkindex; /* where to start checking of the request */ int offset; /* size of the incoming request */ long testno; /* test number found in the request */ long partno; /* part number found in the request */ @@ -100,7 +101,8 @@ struct httprequest { size_t cl; /* Content-Length of the incoming request */ bool digest; /* Authorization digest header found */ bool ntlm; /* Authorization ntlm header found */ - + int pipe; /* if non-zero, expect this many requests to do a "piped" + request/response */ int rcmd; /* doing a special command, see defines above */ }; @@ -188,14 +190,16 @@ static void sigpipe_handler(int sig) int ProcessRequest(struct httprequest *req) { - char *line=req->reqbuf; + char *line=&req->reqbuf[req->checkindex]; char chunked=FALSE; static char request[REQUEST_KEYWORD_SIZE]; static char doc[MAXDOCNAMELEN]; char logbuf[256]; int prot_major, prot_minor; char *end; - end = strstr(req->reqbuf, END_OF_HEADERS); + end = strstr(line, END_OF_HEADERS); + + logmsg("ProcessRequest() called"); /* try to figure out the request characteristics as soon as possible, but only once! */ @@ -266,6 +270,7 @@ int ProcessRequest(struct httprequest *req) else { char *cmd = NULL; size_t cmdsize = 0; + int num=0; /* get the custom server control "commands" */ cmd = (char *)spitout(stream, "reply", "servercmd", &cmdsize); @@ -287,6 +292,11 @@ int ProcessRequest(struct httprequest *req) logmsg("instructed to stream"); req->rcmd = RCMD_STREAM; } + else if(1 == sscanf(cmd, "pipe: %d", &num)) { + logmsg("instructed to allow a pipe size %d", num); + req->pipe = num-1; /* decrease by one since we don't count the + first request in this number */ + } free(cmd); } } @@ -323,9 +333,17 @@ int ProcessRequest(struct httprequest *req) } } - if(!end) + if(!end) { /* we don't have a complete request yet! */ + logmsg("ProcessRequest returned without a complete request"); return 0; + } + logmsg("ProcessRequest found a complete request"); + + if(req->pipe) + /* we do have a full set, advance the checkindex to after the end of the + headers, for the pipelining case mostly */ + req->checkindex += (end - line) + strlen(END_OF_HEADERS); /* **** Persistancy **** * @@ -402,6 +420,17 @@ int ProcessRequest(struct httprequest *req) if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ + while(req->pipe) { + /* scan for more header ends within this chunk */ + line = &req->reqbuf[req->checkindex]; + end = strstr(line, END_OF_HEADERS); + if(!end) + break; + req->checkindex += (end - line) + strlen(END_OF_HEADERS); + req->pipe--; + } + + /* If authentication is required and no auth was provided, end now. This makes the server NOT wait for PUT/POST data and you can then make the test case send a rejection before any such data has been sent. Test case @@ -415,6 +444,7 @@ int ProcessRequest(struct httprequest *req) else return 0; /* not complete yet */ } + return 1; /* done */ } @@ -450,6 +480,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->testno = DOCNUMBER_NOTHING; /* safe default */ req->open = TRUE; /* connection should remain open and wait for more commands */ + req->pipe = 0; /*** end of httprequest init ***/ @@ -467,12 +498,20 @@ static int get_request(curl_socket_t sock, struct httprequest *req) storerequest(reqbuf); return DOCNUMBER_INTERNAL; } + + logmsg("Read %d bytes", got); + req->offset += got; reqbuf[req->offset] = 0; - if(ProcessRequest(req)) + if(ProcessRequest(req)) { + if(req->pipe--) { + logmsg("Waiting for another piped request"); + continue; + } break; + } } if (req->offset >= REQBUFSIZ) { @@ -764,7 +803,7 @@ int main(int argc, char *argv[]) } flag = 1; - if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag))) { logmsg("setsockopt(SO_REUSEADDR) failed: %d", errno); sclose(sock); -- cgit v1.2.1 From 5a6c89661a96fa2139fa0cff07de2f2eff369127 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 12 Sep 2006 01:17:16 +0000 Subject: Cygwin preprocessor adjustments --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 525163f58..c2c681dfe 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -773,7 +773,7 @@ int main(int argc, char *argv[]) } } -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#if defined(WIN32) && !defined(__CYGWIN__) win32_init(); atexit(win32_cleanup); #else -- cgit v1.2.1 From e150150d9f1e0578c85af05de15ab6336066cec1 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 11 Oct 2006 16:01:16 +0000 Subject: Remove redundant __CYGWIN__ symbol check --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index c2c681dfe..7f9091f4a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -773,7 +773,7 @@ int main(int argc, char *argv[]) } } -#if defined(WIN32) && !defined(__CYGWIN__) +#ifdef WIN32 win32_init(); atexit(win32_cleanup); #else -- cgit v1.2.1 From 4ec931615588ea90c5690cf950c2fec468f7c237 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 23 Oct 2006 19:14:54 +0000 Subject: Replace is*() macros with our own IS*() ones. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7f9091f4a..fa0561b43 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -242,7 +242,7 @@ int ProcessRequest(struct httprequest *req) ptr++; /* skip the slash */ /* skip all non-numericals following the slash */ - while(*ptr && !isdigit((int)*ptr)) + while(*ptr && !ISDIGIT(*ptr)) ptr++; req->testno = strtol(ptr, &ptr, 10); -- cgit v1.2.1 From 13e60c55a1a635ceaaf78aa76a4f08c2bcace16f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 23 Oct 2006 19:16:19 +0000 Subject: Avoid trying to compare more than strlen bytes. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fa0561b43..f9fcd6ca5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -233,7 +233,7 @@ int ProcessRequest(struct httprequest *req) return 1; /* done */ } - if(!strncmp("/quit", ptr, 15)) { + if(!strncmp("/quit", ptr, 5)) { logmsg("Request-to-quit received"); req->testno = DOCNUMBER_QUIT; return 1; /* done */ -- cgit v1.2.1 From e264f699d4da5ffbe025bbf83e7981fd9078b660 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 13 Nov 2006 13:48:55 +0000 Subject: Tor Arntsen spotted this mistake --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f9fcd6ca5..9e63e507c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -865,7 +865,7 @@ int main(int argc, char *argv[]) msgsock = accept(sock, NULL, NULL); if (CURL_SOCKET_BAD == msgsock) { - printf("MAJOR ERROR: accept() failed with error: &d\n", errno); + printf("MAJOR ERROR: accept() failed with error: %d\n", errno); break; } -- cgit v1.2.1 From da58d03ff7be9fc5e0219d95ce2f9932e2272473 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 25 Nov 2006 13:32:04 +0000 Subject: Venkat Akella found out that libcurl did not like HTTP responses that simply responded with a single status line and no headers nor body. Starting now, a HTTP response on a persistent connection (i.e not set to be closed after the response has been taken care of) must have Content-Length or chunked encoding set, or libcurl will simply assume that there is no body. To my horror I learned that we had no less than 57(!) test cases that did bad HTTP responses like this, and even the test http server (sws) responded badly when queried by the test system if it is the test system. So although the actual fix for the problem was tiny, going through all the newly failing test cases got really painful and boring. --- tests/server/sws.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9e63e507c..a2d81c709 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -572,6 +572,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) req->open = FALSE; if(req->testno < 0) { + size_t msglen; + char msgbuf[64]; + switch(req->testno) { case DOCNUMBER_QUIT: logmsg("Replying to QUIT"); @@ -580,8 +583,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); - sprintf(weare, "HTTP/1.1 200 OK\r\n\r\nWE ROOLZ: %d\r\n", - (int)getpid()); + sprintf(msgbuf, "WE ROOLZ: %d\r\n", (int)getpid()); + msglen = strlen(msgbuf); + sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", + msglen, msgbuf); buffer = weare; break; case DOCNUMBER_INTERNAL: -- cgit v1.2.1 From 7033a1c072af505ceb94b73112ec87914935e3fa Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 14 Feb 2007 00:28:01 +0000 Subject: enhance HTTP server request input writing, retrying upon EINTR errors. --- tests/server/sws.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a2d81c709..34e5aa22f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -451,19 +451,46 @@ int ProcessRequest(struct httprequest *req) /* store the entire request in a file */ void storerequest(char *reqbuf) { + int error; + ssize_t written; + ssize_t writeleft; + ssize_t totalsize; FILE *dump; - dump = fopen(REQUEST_DUMP, "ab"); /* b is for windows-preparing */ - if(dump) { - size_t len = strlen(reqbuf); - fwrite(reqbuf, 1, len, dump); + if (reqbuf == NULL) + return; - fclose(dump); - logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP, - (int)len); + totalsize = strlen(reqbuf); + if (totalsize == 0) + return; + + do { + dump = fopen(REQUEST_DUMP, "ab"); + } while ((dump == NULL) && ((error = errno) == EINTR)); + if (dump == NULL) { + logmsg("Error opening file %s error: %d", REQUEST_DUMP, error); + logmsg("Failed to write request input to " REQUEST_DUMP); + return; + } + + writeleft = totalsize; + do { + written = fwrite((void *) &reqbuf[totalsize-writeleft], + 1, (size_t)writeleft, dump); + if (written > 0) + writeleft -= written; + } while ((writeleft > 0) && ((error = errno) == EINTR)); + + fclose(dump); /* close it ASAP */ + + if (writeleft > 0) { + logmsg("Error writing file %s error: %d", REQUEST_DUMP, error); + logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s", + totalsize-writeleft, totalsize, REQUEST_DUMP); } else { - logmsg("Failed to write request input to " REQUEST_DUMP); + logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP, + totalsize); } } -- cgit v1.2.1 From 5a267c43121761a3fe548b96abf0832cbd10901f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 14 Feb 2007 13:46:08 +0000 Subject: compiler warning fix --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 34e5aa22f..57c4b5eb5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -460,7 +460,7 @@ void storerequest(char *reqbuf) if (reqbuf == NULL) return; - totalsize = strlen(reqbuf); + totalsize = (ssize_t)strlen(reqbuf); if (totalsize == 0) return; @@ -475,8 +475,8 @@ void storerequest(char *reqbuf) writeleft = totalsize; do { - written = fwrite((void *) &reqbuf[totalsize-writeleft], - 1, (size_t)writeleft, dump); + written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft], + 1, (size_t)writeleft, dump); if (written > 0) writeleft -= written; } while ((writeleft > 0) && ((error = errno) == EINTR)); -- cgit v1.2.1 From 4894ce16fc7af89d876e2f70db4dded7e1663198 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 16 Feb 2007 16:01:19 +0000 Subject: use macros ERRNO, SET_ERRNO(), SOCKERRNO and SET_SOCKERRNO() for errno handling --- tests/server/sws.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 57c4b5eb5..88f72218f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -466,7 +466,7 @@ void storerequest(char *reqbuf) do { dump = fopen(REQUEST_DUMP, "ab"); - } while ((dump == NULL) && ((error = errno) == EINTR)); + } while ((dump == NULL) && ((error = ERRNO) == EINTR)); if (dump == NULL) { logmsg("Error opening file %s error: %d", REQUEST_DUMP, error); logmsg("Failed to write request input to " REQUEST_DUMP); @@ -479,7 +479,7 @@ void storerequest(char *reqbuf) 1, (size_t)writeleft, dump); if (written > 0) writeleft -= written; - } while ((writeleft > 0) && ((error = errno) == EINTR)); + } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); fclose(dump); /* close it ASAP */ @@ -515,7 +515,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) ssize_t got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { - logmsg("recv() returned error: %d", errno); + logmsg("recv() returned error: %d", SOCKERRNO); return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); @@ -830,14 +830,14 @@ int main(int argc, char *argv[]) #endif if (CURL_SOCKET_BAD == sock) { - logmsg("Error opening socket: %d", errno); + logmsg("Error opening socket: %d", SOCKERRNO); return 1; } flag = 1; if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag))) { - logmsg("setsockopt(SO_REUSEADDR) failed: %d", errno); + logmsg("setsockopt(SO_REUSEADDR) failed: %d", SOCKERRNO); sclose(sock); return 1; } @@ -861,7 +861,7 @@ int main(int argc, char *argv[]) } #endif /* ENABLE_IPV6 */ if(0 != rc) { - logmsg("Error binding socket: %d", errno); + logmsg("Error binding socket: %d", SOCKERRNO); sclose(sock); return 1; } @@ -888,7 +888,7 @@ int main(int argc, char *argv[]) /* start accepting connections */ rc = listen(sock, 5); if(0 != rc) { - logmsg("listen() failed with error: %d", errno); + logmsg("listen() failed with error: %d", SOCKERRNO); sclose(sock); return 1; } @@ -897,7 +897,7 @@ int main(int argc, char *argv[]) msgsock = accept(sock, NULL, NULL); if (CURL_SOCKET_BAD == msgsock) { - printf("MAJOR ERROR: accept() failed with error: %d\n", errno); + printf("MAJOR ERROR: accept() failed with error: %d\n", SOCKERRNO); break; } -- cgit v1.2.1 From 31e598d2f39e2d4afc1e6f0a0b960f378e86da31 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 19 Feb 2007 02:03:58 +0000 Subject: add debug messages for initialization failures --- tests/server/sws.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 88f72218f..2ff9eb80c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -197,6 +197,7 @@ int ProcessRequest(struct httprequest *req) char logbuf[256]; int prot_major, prot_minor; char *end; + int error; end = strstr(line, END_OF_HEADERS); logmsg("ProcessRequest() called"); @@ -263,6 +264,9 @@ int ProcessRequest(struct httprequest *req) 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 %d", req->testno); req->open = FALSE; /* closes connection */ return 1; /* done */ @@ -569,6 +573,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) FILE *dump; int persistant = TRUE; size_t responsesize; + int error; static char weare[256]; @@ -646,6 +651,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) 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"); return 0; } @@ -658,6 +666,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) /* re-open the same file again */ 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"); return 0; } @@ -670,6 +681,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ if(!dump) { + error = ERRNO; + logmsg("fopen() failed with error: %d %s", error, strerror(error)); + logmsg("Error opening file: %s", RESPONSE_DUMP); logmsg("couldn't create logfile: " RESPONSE_DUMP); return -1; } @@ -872,7 +886,10 @@ int main(int argc, char *argv[]) fclose(pidfile); } else { - fprintf(stderr, "Couldn't write pid file\n"); + error = ERRNO; + logmsg("fopen() failed with error: %d %s", error, strerror(error)); + logmsg("Error opening file: %s", pidname); + logmsg("Couldn't write pid file"); sclose(sock); return 1; } -- cgit v1.2.1 From f2cd2882a0e756277f31af19fa410ceb2bdb6472 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 19 Feb 2007 03:59:41 +0000 Subject: Oops missing var --- tests/server/sws.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 2ff9eb80c..edf42d098 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -771,6 +771,7 @@ int main(int argc, char *argv[]) char *pidname= (char *)".http.pid"; struct httprequest req; int rc; + int error; int arg=1; #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; -- cgit v1.2.1 From 8d1239c091ef61725e6ce3c53b92b45a71f6f927 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 2 Oct 2007 10:13:37 +0000 Subject: Disable the Nagle algorithm and send back responses in small chunks in an attempt to force smaller bits to get read by clients. --- tests/server/sws.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index edf42d098..1391bf93f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -55,6 +55,9 @@ #ifdef HAVE_NETDB_H #include #endif +#ifdef HAVE_NETINET_TCP_H +#include /* for TCP_NODELAY */ +#endif #define ENABLE_CURLX_PRINTF /* make the curlx header define all printf() functions to use the curlx_* @@ -705,11 +708,20 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) responsesize = count; do { - written = swrite(sock, buffer, count); + /* Ok, we send no more than 200 bytes at a time, just to make sure that + larger chunks are split up so that the client will need to do multiple + recv() calls to get it and thus we exercise that code better */ + int num = count; + if(num > 200) + num = 200; + written = swrite(sock, buffer, num); if (written < 0) { logmsg("Sending response failed and we bailed out!"); return -1; } + else { + logmsg("Sent off %d bytes", written); + } /* write to file as well */ fwrite(buffer, 1, written, dump); @@ -776,6 +788,7 @@ int main(int argc, char *argv[]) #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; #endif + int opt; while(argc>arg) { if(!strcmp("--version", argv[arg])) { @@ -938,7 +951,17 @@ int main(int argc, char *argv[]) #endif logmsg("====> Client connect"); - do { + /* + * Disable the Nagle algorithm to make it easier to send out a large + * response in many small segments to torture the clients more. + */ + opt = 1; + if (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, + (void *)&opt, sizeof(opt)) == -1) { + logmsg("====> TCP_NODELAY failed"); + } + + do { if(get_request(msgsock, &req)) /* non-zero means error, break out of loop */ break; -- cgit v1.2.1 From 0ac5fd354b87edbc926b23e2d6a065371beacfb3 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 3 Oct 2007 23:38:07 +0000 Subject: If TCP_NODELAY is not defined we can't disable the Nagle algorithm --- tests/server/sws.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1391bf93f..65b81a4c0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -788,7 +788,6 @@ int main(int argc, char *argv[]) #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; #endif - int opt; while(argc>arg) { if(!strcmp("--version", argv[arg])) { @@ -951,15 +950,17 @@ int main(int argc, char *argv[]) #endif logmsg("====> Client connect"); +#ifdef TCP_NODELAY /* * Disable the Nagle algorithm to make it easier to send out a large * response in many small segments to torture the clients more. */ - opt = 1; + flag = 1; if (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, - (void *)&opt, sizeof(opt)) == -1) { + (void *)&flag, sizeof(flag)) == -1) { logmsg("====> TCP_NODELAY failed"); } +#endif do { if(get_request(msgsock, &req)) -- cgit v1.2.1 From 06be8bc3894f332f7e7ab77095aa4bdd3d5b16a4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 4 Oct 2007 02:09:33 +0000 Subject: On error, close "log/server.response" --- tests/server/sws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 65b81a4c0..2f429edeb 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -711,11 +711,12 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) /* Ok, we send no more than 200 bytes at a time, just to make sure that larger chunks are split up so that the client will need to do multiple recv() calls to get it and thus we exercise that code better */ - int num = count; + size_t num = count; if(num > 200) num = 200; written = swrite(sock, buffer, num); if (written < 0) { + fclose(dump); logmsg("Sending response failed and we bailed out!"); return -1; } -- cgit v1.2.1 From 54bcde0a149f189a8a140e63a8e27568dfa3ee61 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 9 Oct 2007 23:24:28 +0000 Subject: also log error message string --- tests/server/sws.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 2f429edeb..e9f5f9384 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -475,7 +475,8 @@ void storerequest(char *reqbuf) dump = fopen(REQUEST_DUMP, "ab"); } while ((dump == NULL) && ((error = ERRNO) == EINTR)); if (dump == NULL) { - logmsg("Error opening file %s error: %d", REQUEST_DUMP, error); + logmsg("Error opening file %s error: %d %s", + REQUEST_DUMP, error, strerror(error)); logmsg("Failed to write request input to " REQUEST_DUMP); return; } @@ -491,7 +492,8 @@ void storerequest(char *reqbuf) fclose(dump); /* close it ASAP */ if (writeleft > 0) { - logmsg("Error writing file %s error: %d", REQUEST_DUMP, error); + logmsg("Error writing file %s error: %d %s", + REQUEST_DUMP, error, strerror(error)); logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s", totalsize-writeleft, totalsize, REQUEST_DUMP); } -- cgit v1.2.1 From 0678a51d3b8be8b24e475929fae11b95d2258da4 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Thu, 25 Oct 2007 19:40:05 +0000 Subject: Allow test server to handle binary POSTs. Tests 35, 544 545 added: binary data POSTs. --- tests/server/sws.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e9f5f9384..55c05b199 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -110,7 +110,7 @@ struct httprequest { }; int ProcessRequest(struct httprequest *req); -void storerequest(char *reqbuf); +void storerequest(char *reqbuf, ssize_t totalsize); #define DEFAULT_PORT 8999 @@ -446,7 +446,7 @@ int ProcessRequest(struct httprequest *req) return 1; if(req->cl) { - if(req->cl <= strlen(end+strlen(END_OF_HEADERS))) + if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS)) return 1; /* done */ else return 0; /* not complete yet */ @@ -456,18 +456,16 @@ int ProcessRequest(struct httprequest *req) } /* store the entire request in a file */ -void storerequest(char *reqbuf) +void storerequest(char *reqbuf, ssize_t totalsize) { int error; ssize_t written; ssize_t writeleft; - ssize_t totalsize; FILE *dump; if (reqbuf == NULL) return; - totalsize = (ssize_t)strlen(reqbuf); if (totalsize == 0) return; @@ -531,7 +529,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) reqbuf[req->offset]=0; /* dump the request receivied so far to the external file */ - storerequest(reqbuf); + storerequest(reqbuf, req->offset); return DOCNUMBER_INTERNAL; } @@ -560,7 +558,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) reqbuf[req->offset]=0; /* dump the request to an external file */ - storerequest(reqbuf); + storerequest(reqbuf, req->offset); return fail; /* success */ } -- cgit v1.2.1 From 1d49c04545ae297647ac96cbf3b3acd79c100217 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 26 Oct 2007 00:36:36 +0000 Subject: Detect, log and avoid storing a request with a negative size. --- tests/server/sws.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 55c05b199..5598328cc 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -468,6 +468,11 @@ void storerequest(char *reqbuf, ssize_t totalsize) if (totalsize == 0) return; + else if (totalsize < 0) { + logmsg("Invalid size (%d bytes) for request input. Not written to %s", + totalsize, REQUEST_DUMP); + return; + } do { dump = fopen(REQUEST_DUMP, "ab"); -- cgit v1.2.1 From 2198869eb166783336f1bf05ab656f369557415f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 25 Jan 2008 05:07:04 +0000 Subject: Dmitry Kurochkin's test harness HTTP server pipelining fix fot test 530 --- tests/server/sws.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5598328cc..f7a3f846a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -107,6 +107,8 @@ struct httprequest { int pipe; /* if non-zero, expect this many requests to do a "piped" request/response */ int rcmd; /* doing a special command, see defines above */ + int prot_version; /* HTTP version * 10 */ + bool pipelining; /* true if request is pipelined */ }; int ProcessRequest(struct httprequest *req); @@ -215,6 +217,8 @@ int ProcessRequest(struct httprequest *req) &prot_minor) == 4) { char *ptr; + req->prot_version = prot_major*10 + prot_minor; + /* find the last slash */ ptr = strrchr(doc, '/'); @@ -315,7 +319,7 @@ int ProcessRequest(struct httprequest *req) doc, prot_major, prot_minor); logmsg("%s", logbuf); - if(prot_major*10+prot_minor == 10) + if(req->prot_version == 10) req->open = FALSE; /* HTTP 1.0 closes connection by default */ if(!strncmp(doc, "bad", 3)) @@ -427,6 +431,19 @@ int ProcessRequest(struct httprequest *req) if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ + if(!req->pipe && + req->open && + req->prot_version >= 11 && + end && + req->reqbuf + req->offset > end + strlen(END_OF_HEADERS) && + (!strncmp(req->reqbuf, "GET", strlen("GET")) || + !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) { + /* If we have a persistent connection, HTTP version >= 1.1 + and GET/HEAD request, enable pipelining. */ + req->checkindex = (end - req->reqbuf) + strlen(END_OF_HEADERS); + req->pipelining = TRUE; + } + while(req->pipe) { /* scan for more header ends within this chunk */ line = &req->reqbuf[req->checkindex]; @@ -512,6 +529,15 @@ static int get_request(curl_socket_t sock, struct httprequest *req) int fail= FALSE; char *reqbuf = req->reqbuf; + char pipereq[REQBUFSIZ]; + int pipereq_length; + if(req->pipelining) { + pipereq_length = req->offset - req->checkindex; + memcpy(pipereq, reqbuf + req->checkindex, pipereq_length); + } + else + pipereq_length = 0; + /*** Init the httpreqest structure properly for the upcoming request ***/ memset(req, 0, sizeof(struct httprequest)); @@ -524,7 +550,14 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { - ssize_t got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); + ssize_t got; + if(pipereq_length) { + memcpy(reqbuf, pipereq, pipereq_length); + got = pipereq_length; + pipereq_length = 0; + } + else + got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", SOCKERRNO); @@ -563,7 +596,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) reqbuf[req->offset]=0; /* dump the request to an external file */ - storerequest(reqbuf, req->offset); + storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); return fail; /* success */ } -- cgit v1.2.1 From 69e540dfa6487701639b4b9a2d3bbd2ee6343dc2 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 25 Jan 2008 05:08:53 +0000 Subject: improve request initialization for test harness HTTP server --- tests/server/sws.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f7a3f846a..816532bd5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1001,6 +1001,16 @@ int main(int argc, char *argv[]) } #endif + /* full initialization for new request after connection */ + memset(&req, 0, sizeof(req)); + req.testno = DOCNUMBER_NOTHING; + req.open = TRUE; + req.auth_req = FALSE; + req.auth = FALSE; + req.digest = FALSE; + req.ntlm = FALSE; + req.pipelining = FALSE; + do { if(get_request(msgsock, &req)) /* non-zero means error, break out of loop */ -- cgit v1.2.1 From cd63a461d7e1cb55841311ebf2e2478fa561c510 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 5 Feb 2008 02:21:38 +0000 Subject: proper initialization of httprequest, no longer zeroing out twice the whole 150000+ bytes struct, and also removing an equally big additional buffer for pipelining treatment. --- tests/server/sws.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 816532bd5..de9fd5a4c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -529,30 +529,37 @@ static int get_request(curl_socket_t sock, struct httprequest *req) int fail= FALSE; char *reqbuf = req->reqbuf; - char pipereq[REQBUFSIZ]; - int pipereq_length; + char *pipereq; + int pipereq_length = 0; + if(req->pipelining) { + pipereq = reqbuf + req->checkindex; pipereq_length = req->offset - req->checkindex; - memcpy(pipereq, reqbuf + req->checkindex, pipereq_length); } - else - pipereq_length = 0; /*** Init the httpreqest structure properly for the upcoming request ***/ - memset(req, 0, sizeof(struct httprequest)); - /* here's what should not be 0 from the start */ - req->testno = DOCNUMBER_NOTHING; /* safe default */ - req->open = TRUE; /* connection should remain open and wait for more - commands */ + req->checkindex = 0; + req->offset = 0; + req->testno = DOCNUMBER_NOTHING; + req->partno = 0; + req->open = TRUE; + req->auth_req = FALSE; + req->auth = FALSE; + req->cl = 0; + req->digest = FALSE; + req->ntlm = FALSE; req->pipe = 0; + req->rcmd = RCMD_NORMALREQ; + req->prot_version = 0; + req->pipelining = FALSE; /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { ssize_t got; if(pipereq_length) { - memcpy(reqbuf, pipereq, pipereq_length); + memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; pipereq_length = 0; } @@ -1001,17 +1008,13 @@ int main(int argc, char *argv[]) } #endif - /* full initialization for new request after connection */ - memset(&req, 0, sizeof(req)); - req.testno = DOCNUMBER_NOTHING; - req.open = TRUE; - req.auth_req = FALSE; - req.auth = FALSE; - req.digest = FALSE; - req.ntlm = FALSE; - req.pipelining = FALSE; + /* initialization of httprequest struct is done in get_request(), but due + to pipelining treatment the pipelining struct field must be initialized + previously to FALSE every time a new connection arrives. */ - do { + req.pipelining = FALSE; + + do { if(get_request(msgsock, &req)) /* non-zero means error, break out of loop */ break; -- cgit v1.2.1 From acd9d724667a6f15c96e2b1078ea8fd45e8963d4 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 5 Feb 2008 14:43:16 +0000 Subject: Minor variable type cleanups. Disable "swsbounce" mode when the received request isn't for the same test and part number. --- tests/server/sws.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index de9fd5a4c..851c9a867 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -83,9 +83,9 @@ long prevtestno=-1; /* previous test number we served */ long prevpartno=-1; /* previous part number we served */ -bool prevbounce; /* instructs the server to increase the part number for - a test in case the identical testno+partno request - shows up again */ +bool prevbounce=FALSE; /* instructs the server to increase the part number for + a test in case the identical testno+partno request + shows up again */ #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */ #define RCMD_IDLE 1 /* told to sit idle */ @@ -97,7 +97,7 @@ struct httprequest { int offset; /* size of the incoming request */ long testno; /* test number found in the request */ long partno; /* part number found in the request */ - int open; /* keep connection open info, as found in the request */ + bool open; /* keep connection open info, as found in the request */ bool auth_req; /* authentication required, don't wait for body unless there's an Authorization header */ bool auth; /* Authorization header present in the incoming request */ @@ -196,7 +196,7 @@ static void sigpipe_handler(int sig) int ProcessRequest(struct httprequest *req) { char *line=&req->reqbuf[req->checkindex]; - char chunked=FALSE; + bool chunked = FALSE; static char request[REQUEST_KEYWORD_SIZE]; static char doc[MAXDOCNAMELEN]; char logbuf[256]; @@ -526,7 +526,7 @@ void storerequest(char *reqbuf, ssize_t totalsize) /* return 0 on success, non-zero on failure */ static int get_request(curl_socket_t sock, struct httprequest *req) { - int fail= FALSE; + int fail = 0; char *reqbuf = req->reqbuf; char *pipereq; @@ -571,7 +571,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); - reqbuf[req->offset]=0; + reqbuf[req->offset] = '\0'; /* dump the request receivied so far to the external file */ storerequest(reqbuf, req->offset); @@ -581,8 +581,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) logmsg("Read %d bytes", got); req->offset += got; - - reqbuf[req->offset] = 0; + reqbuf[req->offset] = '\0'; if(ProcessRequest(req)) { if(req->pipe--) { @@ -595,17 +594,17 @@ static int get_request(curl_socket_t sock, struct httprequest *req) if (req->offset >= REQBUFSIZ) { logmsg("Request buffer overflow, closing connection"); - reqbuf[REQBUFSIZ-1]=0; - fail = TRUE; + reqbuf[REQBUFSIZ-1] = '\0'; + fail = 1; /* dump the request to an external file anyway */ } else - reqbuf[req->offset]=0; + reqbuf[req->offset] = '\0'; /* dump the request to an external file */ storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); - return fail; /* success */ + return fail; /* return 0 on success */ } /* returns -1 on failure */ @@ -619,7 +618,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) char *cmd=NULL; size_t cmdsize=0; FILE *dump; - int persistant = TRUE; + bool persistant = TRUE; size_t responsesize; int error; @@ -814,7 +813,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } -char use_ipv6=FALSE; +bool use_ipv6=FALSE; int main(int argc, char *argv[]) { @@ -1026,6 +1025,11 @@ int main(int argc, char *argv[]) req.partno++; logmsg("BOUNCE part number to %ld", req.partno); } + else { + prevbounce = FALSE; + prevtestno = -1; + prevpartno = -1; + } } send_doc(msgsock, &req); -- cgit v1.2.1 From 2c0956200ffe6c9a42d80a6077fe172c3f7bac53 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 5 Feb 2008 18:37:53 +0000 Subject: Fix buffer size specification. Improve handling of boundary conditions for huge requests. --- tests/server/sws.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 851c9a867..0bbd124f3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -132,6 +132,7 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define MAXDOCNAMELEN_TXT "139999" #define REQUEST_KEYWORD_SIZE 256 +#define REQUEST_KEYWORD_SIZE_TXT "255" #define CMD_AUTH_REQUIRED "auth_required" @@ -210,7 +211,8 @@ int ProcessRequest(struct httprequest *req) /* try to figure out the request characteristics as soon as possible, but only once! */ if((req->testno == DOCNUMBER_NOTHING) && - sscanf(line, "%" REQBUFSIZ_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + sscanf(line, + "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", request, doc, &prot_major, @@ -528,6 +530,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) { int fail = 0; char *reqbuf = req->reqbuf; + ssize_t got = 0; char *pipereq; int pipereq_length = 0; @@ -556,15 +559,14 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /*** end of httprequest init ***/ - while (req->offset < REQBUFSIZ) { - ssize_t got; + while (req->offset < REQBUFSIZ-1) { if(pipereq_length) { memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; pipereq_length = 0; } else - got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); + got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", SOCKERRNO); @@ -592,11 +594,17 @@ static int get_request(curl_socket_t sock, struct httprequest *req) } } - if (req->offset >= REQBUFSIZ) { + if((req->offset == REQBUFSIZ-1) && (got > 0)) { + logmsg("Request would overflow buffer, closing connection"); + /* dump request received so far to external file anyway */ + reqbuf[REQBUFSIZ-1] = '\0'; + fail = 1; + } + else if(req->offset > REQBUFSIZ-1) { logmsg("Request buffer overflow, closing connection"); + /* dump request received so far to external file anyway */ reqbuf[REQBUFSIZ-1] = '\0'; fail = 1; - /* dump the request to an external file anyway */ } else reqbuf[req->offset] = '\0'; -- cgit v1.2.1 From fecb67b246a2a2dad900edaab28f4e046ef47822 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 6 Feb 2008 16:54:01 +0000 Subject: Use a long int data type to handle getpid() result --- tests/server/sws.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0bbd124f3..695c6b156 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -670,7 +670,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); - sprintf(msgbuf, "WE ROOLZ: %d\r\n", (int)getpid()); + sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid()); msglen = strlen(msgbuf); sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", msglen, msgbuf); @@ -948,8 +948,10 @@ int main(int argc, char *argv[]) pidfile = fopen(pidname, "w"); if(pidfile) { - fprintf(pidfile, "%d\n", (int)getpid()); + long pid = (long)getpid(); + fprintf(pidfile, "%ld\n", pid); fclose(pidfile); + logmsg("Wrote pid %ld to %s", pid, pidname); } else { error = ERRNO; -- cgit v1.2.1 From 0d09f342c48b0d447fd506869959986da1746838 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 26 Feb 2008 15:06:44 +0000 Subject: refactor some code out to write_pidfile() in util.c --- tests/server/sws.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 695c6b156..99f0bddbd 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -832,11 +832,9 @@ int main(int argc, char *argv[]) curl_socket_t sock, msgsock; int flag; unsigned short port = DEFAULT_PORT; - FILE *pidfile; char *pidname= (char *)".http.pid"; struct httprequest req; int rc; - int error; int arg=1; #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; @@ -946,18 +944,7 @@ int main(int argc, char *argv[]) return 1; } - pidfile = fopen(pidname, "w"); - if(pidfile) { - long pid = (long)getpid(); - fprintf(pidfile, "%ld\n", pid); - fclose(pidfile); - logmsg("Wrote pid %ld to %s", pid, pidname); - } - else { - error = ERRNO; - logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", pidname); - logmsg("Couldn't write pid file"); + if(!write_pidfile(pidname)) { sclose(sock); return 1; } -- cgit v1.2.1 From ed63d9d4de2c40ee2bb15f3f2ffed0d9bfe54c22 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 28 Feb 2008 00:55:06 +0000 Subject: header inclusion cleanup --- tests/server/sws.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 99f0bddbd..5e68a3160 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -29,16 +29,9 @@ */ #include "setup.h" /* portability help from the lib directory */ -#include -#include -#include -#include +#ifdef HAVE_SIGNAL_H #include -#include -#include -#include -#include - +#endif #ifdef HAVE_UNISTD_H #include #endif -- cgit v1.2.1 From a87c468c5cbe9699d87886e37f593820bdfda904 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 20 Apr 2008 19:15:08 +0000 Subject: accelerate the writing of server input and response request files to disk, trying to defeat file and disk write-behind algorithms --- tests/server/sws.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5e68a3160..b7c950324 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -470,6 +470,7 @@ int ProcessRequest(struct httprequest *req) /* store the entire request in a file */ void storerequest(char *reqbuf, ssize_t totalsize) { + int res; int error; ssize_t written; ssize_t writeleft; @@ -504,18 +505,41 @@ void storerequest(char *reqbuf, ssize_t totalsize) writeleft -= written; } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); - fclose(dump); /* close it ASAP */ - if (writeleft > 0) { logmsg("Error writing file %s error: %d %s", REQUEST_DUMP, error, strerror(error)); logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s", totalsize-writeleft, totalsize, REQUEST_DUMP); } - else { + +#ifdef HAVE_FFLUSH + do { + res = fflush(dump); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error flushing file %s error: %d %s", + REQUEST_DUMP, error, strerror(error)); +#endif + +#ifdef HAVE_FSYNC + do { + res = fsync(fileno(dump)); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error syncing file %s error: %d %s", + REQUEST_DUMP, error, strerror(error)); +#endif + + do { + res = fclose(dump); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error closing file %s error: %d %s", + REQUEST_DUMP, error, strerror(error)); + + if(!writeleft) logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP, totalsize); - } } /* return 0 on success, non-zero on failure */ @@ -620,8 +644,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) size_t cmdsize=0; FILE *dump; bool persistant = TRUE; + bool sendfailure = FALSE; size_t responsesize; int error; + int res; static char weare[256]; @@ -761,9 +787,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) num = 200; written = swrite(sock, buffer, num); if (written < 0) { - fclose(dump); - logmsg("Sending response failed and we bailed out!"); - return -1; + sendfailure = TRUE; + break; } else { logmsg("Sent off %d bytes", written); @@ -775,7 +800,36 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) buffer += written; } while(count>0); - fclose(dump); +#ifdef HAVE_FFLUSH + do { + res = fflush(dump); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error flushing file %s error: %d %s", + RESPONSE_DUMP, error, strerror(error)); +#endif + +#ifdef HAVE_FSYNC + do { + res = fsync(fileno(dump)); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error syncing file %s error: %d %s", + RESPONSE_DUMP, error, strerror(error)); +#endif + + do { + res = fclose(dump); + } while(res && ((error = ERRNO) == EINTR)); + if(res) + logmsg("Error closing file %s error: %d %s", + RESPONSE_DUMP, error, strerror(error)); + + if(sendfailure) { + logmsg("Sending response failed. Only (%d bytes) of (%d bytes) were sent", + responsesize-count, responsesize); + return -1; + } logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP, responsesize); -- cgit v1.2.1 From 95fd093c4a49aca1015e178a5c08ca9dd9234bef Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 22 Apr 2008 12:40:05 +0000 Subject: Remove fflush() + fsync() previously introduced accelerated writing of server input and response request files of the test harness sws server. Reintroduce, for test # 1001, the small delay. The delay is needed even with the accelerated writing of server input and response request files in test harness sws server. http://curl.haxx.se/mail/lib-2008-04/0385.html --- tests/server/sws.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b7c950324..41bac4f01 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -512,24 +512,6 @@ void storerequest(char *reqbuf, ssize_t totalsize) totalsize-writeleft, totalsize, REQUEST_DUMP); } -#ifdef HAVE_FFLUSH - do { - res = fflush(dump); - } while(res && ((error = ERRNO) == EINTR)); - if(res) - logmsg("Error flushing file %s error: %d %s", - REQUEST_DUMP, error, strerror(error)); -#endif - -#ifdef HAVE_FSYNC - do { - res = fsync(fileno(dump)); - } while(res && ((error = ERRNO) == EINTR)); - if(res) - logmsg("Error syncing file %s error: %d %s", - REQUEST_DUMP, error, strerror(error)); -#endif - do { res = fclose(dump); } while(res && ((error = ERRNO) == EINTR)); @@ -800,24 +782,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) buffer += written; } while(count>0); -#ifdef HAVE_FFLUSH - do { - res = fflush(dump); - } while(res && ((error = ERRNO) == EINTR)); - if(res) - logmsg("Error flushing file %s error: %d %s", - RESPONSE_DUMP, error, strerror(error)); -#endif - -#ifdef HAVE_FSYNC - do { - res = fsync(fileno(dump)); - } while(res && ((error = ERRNO) == EINTR)); - if(res) - logmsg("Error syncing file %s error: %d %s", - RESPONSE_DUMP, error, strerror(error)); -#endif - do { res = fclose(dump); } while(res && ((error = ERRNO) == EINTR)); -- cgit v1.2.1 From ad1dd086937138f56e5942ae0840867372c77d03 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 22 Apr 2008 13:07:27 +0000 Subject: fix minor memory leak triggered upon test failure --- tests/server/sws.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 41bac4f01..fc4123538 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -620,7 +620,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) ssize_t written; size_t count; const char *buffer; - char *ptr; + char *ptr=NULL; FILE *stream; char *cmd=NULL; size_t cmdsize=0; @@ -792,6 +792,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(sendfailure) { logmsg("Sending response failed. Only (%d bytes) of (%d bytes) were sent", responsesize-count, responsesize); + if(ptr) + free(ptr); + if(cmd) + free(cmd); return -1; } -- cgit v1.2.1 From 96edebf4d9ec656ec6ed83dca3bbc3947033c71d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 23 Apr 2008 23:55:34 +0000 Subject: improve synchronization between test harness runtests.pl script and test harness servers to minimize risk of false test failures. http://curl.haxx.se/mail/lib-2008-04/0392.html --- tests/server/sws.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fc4123538..023fe270e 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -988,6 +988,8 @@ int main(int argc, char *argv[]) break; } + set_advisor_read_lock(SERVERLOGS_LOCK); + #ifdef CURL_SWS_FORK_ENABLED if(use_fork) { /* The fork enabled version just forks off the child and don't care @@ -1063,6 +1065,8 @@ int main(int argc, char *argv[]) logmsg("====> Client disconnect"); sclose(msgsock); + clear_advisor_read_lock(SERVERLOGS_LOCK); + if (req.testno == DOCNUMBER_QUIT) break; #ifdef CURL_SWS_FORK_ENABLED @@ -1072,6 +1076,8 @@ int main(int argc, char *argv[]) sclose(sock); + clear_advisor_read_lock(SERVERLOGS_LOCK); + return 0; } -- cgit v1.2.1 From 1f26ea4a853844caf6118250abb6a4a141c87e8b Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 30 Jul 2008 07:24:59 +0000 Subject: Added test case 1051 to test Location: following with PUT, as reported by Ben Sutcliffe. The test when run manually shows a problem in curl, but the test harness web server doesn't run the test correctly so it's disabled for now. --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 023fe270e..a114cac43 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -351,7 +351,7 @@ int ProcessRequest(struct httprequest *req) headers, for the pipelining case mostly */ req->checkindex += (end - line) + strlen(END_OF_HEADERS); - /* **** Persistancy **** + /* **** Persistency **** * * If the request is a HTTP/1.0 one, we close the connection unconditionally * when we're done. @@ -539,7 +539,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) pipereq_length = req->offset - req->checkindex; } - /*** Init the httpreqest structure properly for the upcoming request ***/ + /*** Init the httprequest structure properly for the upcoming request ***/ req->checkindex = 0; req->offset = 0; @@ -1049,7 +1049,7 @@ int main(int argc, char *argv[]) send_doc(msgsock, &req); if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { - logmsg("special request received, no persistancy"); + logmsg("special request received, no persistency"); break; } if(!req.open) { -- cgit v1.2.1 From c67a99ff27036c824be15f01e21b91c3ec08da4a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 29 Aug 2008 10:47:59 +0000 Subject: - When libcurl was doing a HTTP POST and the server would respond with "Connection: close" and actually close the connection after the response-body, libcurl could still have outstanding data to send and it would not properly notice this and stop sending. This caused weirdness and sad faces. http://curl.haxx.se/bug/view.cgi?id=2080222 Note that there are still reasons to consider libcurl's behavior when getting a >= 400 response code while sending data, as Craig Perras' note "http upload: how to stop on error" specifies: http://curl.haxx.se/mail/archive-2008-08/0138.html --- tests/server/sws.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a114cac43..f658d1863 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -99,6 +99,10 @@ struct httprequest { bool ntlm; /* Authorization ntlm header found */ int pipe; /* if non-zero, expect this many requests to do a "piped" request/response */ + int skip; /* if non-zero, the server is instructed to not read this + many bytes from a PUT/POST request. Ie the client sends N + bytes said in Content-Length, but the server only reads N + - skip bytes. */ int rcmd; /* doing a special command, see defines above */ int prot_version; /* HTTP version * 10 */ bool pipelining; /* true if request is pipelined */ @@ -303,6 +307,13 @@ int ProcessRequest(struct httprequest *req) req->pipe = num-1; /* decrease by one since we don't count the first request in this number */ } + else if(1 == sscanf(cmd, "skip: %d", &num)) { + logmsg("instructed to skip this number of bytes %d", num); + req->skip = num; + } + else { + logmsg("funny instruction found: %s", cmd); + } free(cmd); } } @@ -351,7 +362,7 @@ int ProcessRequest(struct httprequest *req) headers, for the pipelining case mostly */ req->checkindex += (end - line) + strlen(END_OF_HEADERS); - /* **** Persistency **** + /* **** Persistence **** * * If the request is a HTTP/1.0 one, we close the connection unconditionally * when we're done. @@ -363,14 +374,17 @@ int ProcessRequest(struct httprequest *req) */ do { - if(!req->cl && curlx_strnequal("Content-Length:", line, 15)) { + if((req->cl<=0) && curlx_strnequal("Content-Length:", line, 15)) { /* If we don't ignore content-length, we read it and we read the whole request including the body before we return. If we've been told to ignore the content-length, we will return as soon as all headers have been received */ - req->cl = strtol(line+15, &line, 10); + size_t cl = strtol(line+15, &line, 10); + req->cl = cl - req->skip; - logmsg("Found Content-Length: %d in the request", req->cl); + logmsg("Found Content-Length: %d in the request", cl); + if(req->skip) + logmsg("... but will abort after %d bytes", req->cl); break; } else if(curlx_strnequal("Transfer-Encoding: chunked", line, @@ -457,7 +471,7 @@ int ProcessRequest(struct httprequest *req) if(req->auth_req && !req->auth) return 1; - if(req->cl) { + if(req->cl > 0) { if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS)) return 1; /* done */ else @@ -552,6 +566,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->digest = FALSE; req->ntlm = FALSE; req->pipe = 0; + req->skip = 0; req->rcmd = RCMD_NORMALREQ; req->prot_version = 0; req->pipelining = FALSE; @@ -564,8 +579,15 @@ static int get_request(curl_socket_t sock, struct httprequest *req) got = pipereq_length; pipereq_length = 0; } - else - got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); + else { + if(req->skip) + /* we are instructed to not read the entire thing, so we make sure to only + read what we're supposed to and NOT read the enire thing the client + wants to send! */ + got = sread(sock, reqbuf + req->offset, req->cl); + else + got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); + } if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", SOCKERRNO); -- cgit v1.2.1 From 8733e087d7ccfd4ce940bdd904cd0d667ecadbaa Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 4 Sep 2008 05:29:10 +0000 Subject: fix print formatting string directives --- tests/server/sws.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f658d1863..a4d7e89e0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -273,7 +273,7 @@ int ProcessRequest(struct httprequest *req) error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", filename); - logmsg("Couldn't open test file %d", req->testno); + logmsg("Couldn't open test file %ld", req->testno); req->open = FALSE; /* closes connection */ return 1; /* done */ } @@ -374,7 +374,7 @@ int ProcessRequest(struct httprequest *req) */ do { - if((req->cl<=0) && curlx_strnequal("Content-Length:", line, 15)) { + if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) { /* If we don't ignore content-length, we read it and we read the whole request including the body before we return. If we've been told to ignore the content-length, we will return as soon as all headers @@ -382,9 +382,9 @@ int ProcessRequest(struct httprequest *req) size_t cl = strtol(line+15, &line, 10); req->cl = cl - req->skip; - logmsg("Found Content-Length: %d in the request", cl); + logmsg("Found Content-Length: %zu in the request", cl); if(req->skip) - logmsg("... but will abort after %d bytes", req->cl); + logmsg("... but will abort after %zu bytes", req->cl); break; } else if(curlx_strnequal("Transfer-Encoding: chunked", line, @@ -418,16 +418,16 @@ int ProcessRequest(struct httprequest *req) Digest stuff to work in the test suite. */ req->partno += 1000; req->digest = TRUE; /* header found */ - logmsg("Received Digest request, sending back data %d", req->partno); + logmsg("Received Digest request, sending back data %ld", req->partno); } else if(!req->ntlm && strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) { /* If the client is passing this type-3 NTLM header */ req->partno += 1002; req->ntlm = TRUE; /* NTLM found */ - logmsg("Received NTLM type-3, sending back data %d", req->partno); + logmsg("Received NTLM type-3, sending back data %ld", req->partno); if(req->cl) { - logmsg(" Expecting %d POSTed bytes", req->cl); + logmsg(" Expecting %zu POSTed bytes", req->cl); } } else if(!req->ntlm && @@ -435,7 +435,7 @@ int ProcessRequest(struct httprequest *req) /* If the client is passing this type-1 NTLM header */ req->partno += 1001; req->ntlm = TRUE; /* NTLM found */ - logmsg("Received NTLM type-1, sending back data %d", req->partno); + logmsg("Received NTLM type-1, sending back data %ld", req->partno); } if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ @@ -496,7 +496,7 @@ void storerequest(char *reqbuf, ssize_t totalsize) if (totalsize == 0) return; else if (totalsize < 0) { - logmsg("Invalid size (%d bytes) for request input. Not written to %s", + logmsg("Invalid size (%zd bytes) for request input. Not written to %s", totalsize, REQUEST_DUMP); return; } @@ -522,7 +522,7 @@ void storerequest(char *reqbuf, ssize_t totalsize) if (writeleft > 0) { logmsg("Error writing file %s error: %d %s", REQUEST_DUMP, error, strerror(error)); - logmsg("Wrote only (%d bytes) of (%d bytes) request input to %s", + logmsg("Wrote only (%zd bytes) of (%zd bytes) request input to %s", totalsize-writeleft, totalsize, REQUEST_DUMP); } @@ -534,7 +534,7 @@ void storerequest(char *reqbuf, ssize_t totalsize) REQUEST_DUMP, error, strerror(error)); if(!writeleft) - logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP, + logmsg("Wrote request (%zd bytes) input to " REQUEST_DUMP, totalsize); } @@ -575,7 +575,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) while (req->offset < REQBUFSIZ-1) { if(pipereq_length) { - memmove(reqbuf, pipereq, pipereq_length); + memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; pipereq_length = 0; } @@ -601,7 +601,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) return DOCNUMBER_INTERNAL; } - logmsg("Read %d bytes", got); + logmsg("Read %zd bytes", got); req->offset += got; reqbuf[req->offset] = '\0'; @@ -657,7 +657,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) char partbuf[80]="data"; - logmsg("Send response number %d part %d", req->testno, req->partno); + logmsg("Send response number %ld part %ld", req->testno, req->partno); switch(req->rcmd) { default: @@ -695,7 +695,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("Identifying ourselves as friends"); sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid()); msglen = strlen(msgbuf); - sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", + sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s", msglen, msgbuf); buffer = weare; break; @@ -795,7 +795,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) break; } else { - logmsg("Sent off %d bytes", written); + logmsg("Sent off %zd bytes", written); } /* write to file as well */ fwrite(buffer, 1, written, dump); @@ -812,7 +812,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) RESPONSE_DUMP, error, strerror(error)); if(sendfailure) { - logmsg("Sending response failed. Only (%d bytes) of (%d bytes) were sent", + logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent", responsesize-count, responsesize); if(ptr) free(ptr); @@ -821,7 +821,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return -1; } - logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP, + logmsg("Response sent (%zu bytes) and written to " RESPONSE_DUMP, responsesize); if(ptr) @@ -986,7 +986,7 @@ int main(int argc, char *argv[]) return 1; } - logmsg("Running IPv%d version on port %d", + logmsg("Running IPv%d version on port %hu", #ifdef ENABLE_IPV6 (use_ipv6?6:4) #else -- cgit v1.2.1 From a6c915aab98a51b69a77a23ebe1ad8eaf0fd251f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 18 Sep 2008 16:21:09 +0000 Subject: fix compiler warning: external declaration in primary source file --- tests/server/sws.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a4d7e89e0..92f485954 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -108,8 +108,8 @@ struct httprequest { bool pipelining; /* true if request is pipelined */ }; -int ProcessRequest(struct httprequest *req); -void storerequest(char *reqbuf, ssize_t totalsize); +static int ProcessRequest(struct httprequest *req); +static void storerequest(char *reqbuf, ssize_t totalsize); #define DEFAULT_PORT 8999 @@ -191,7 +191,7 @@ static void sigpipe_handler(int sig) } #endif -int ProcessRequest(struct httprequest *req) +static int ProcessRequest(struct httprequest *req) { char *line=&req->reqbuf[req->checkindex]; bool chunked = FALSE; @@ -482,7 +482,7 @@ int ProcessRequest(struct httprequest *req) } /* store the entire request in a file */ -void storerequest(char *reqbuf, ssize_t totalsize) +static void storerequest(char *reqbuf, ssize_t totalsize) { int res; int error; -- cgit v1.2.1 From fe5f448015b9b1c632d8725a4dc0fe6d1ab04736 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 20 Sep 2008 12:33:02 +0000 Subject: fix compiler warning: external definition with no prior declaration --- tests/server/sws.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 92f485954..e60b8d79c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -74,11 +74,11 @@ #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" -long prevtestno=-1; /* previous test number we served */ -long prevpartno=-1; /* previous part number we served */ -bool prevbounce=FALSE; /* instructs the server to increase the part number for - a test in case the identical testno+partno request - shows up again */ +static long prevtestno=-1; /* previous test number we served */ +static long prevpartno=-1; /* previous part number we served */ +static bool prevbounce=FALSE; /* instructs the server to increase the part + number for a test in case the identical + testno+partno request shows up again */ #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */ #define RCMD_IDLE 1 /* told to sit idle */ @@ -858,7 +858,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } -bool use_ipv6=FALSE; +static bool use_ipv6=FALSE; int main(int argc, char *argv[]) { -- cgit v1.2.1 From b6f29bef06035e53d2561a3cb72db10479db4303 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 21 Sep 2008 02:35:20 +0000 Subject: fix compiler warning: defined but not used --- tests/server/sws.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e60b8d79c..3b4b63d2b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -987,12 +987,7 @@ int main(int argc, char *argv[]) } logmsg("Running IPv%d version on port %hu", -#ifdef ENABLE_IPV6 - (use_ipv6?6:4) -#else - 4 -#endif - , port ); + (use_ipv6?6:4), port); /* start accepting connections */ rc = listen(sock, 5); -- cgit v1.2.1 From 985bd18904a2184bc5c43f75a1dcbbcc1dc7256f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 26 Sep 2008 01:08:24 +0000 Subject: attempt to avoid HTTP server startup misdetection on some systems --- tests/server/sws.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 3b4b63d2b..58f951fca 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -71,6 +71,11 @@ #define CURL_SWS_FORK_ENABLED #endif +#ifdef ENABLE_IPV6 +static bool use_ipv6 = FALSE; +#endif +const char *ipv_inuse = "IPv4"; + #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" @@ -858,7 +863,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } -static bool use_ipv6=FALSE; int main(int argc, char *argv[]) { @@ -900,7 +904,8 @@ int main(int argc, char *argv[]) } else if(!strcmp("--ipv6", argv[arg])) { #ifdef ENABLE_IPV6 - use_ipv6=TRUE; + ipv_inuse = "IPv6"; + use_ipv6 = TRUE; #endif arg++; } @@ -986,8 +991,7 @@ int main(int argc, char *argv[]) return 1; } - logmsg("Running IPv%d version on port %hu", - (use_ipv6?6:4), port); + logmsg("Running %s version on port %d", ipv_inuse, (int)port); /* start accepting connections */ rc = listen(sock, 5); -- cgit v1.2.1 From 57ee847ce7e07b2744f46be990f887d067c00d44 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 26 Sep 2008 11:21:22 +0000 Subject: Avoid the use of the '? :' operator inside the call to our test-server logging function. It doesn't work on some systems. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 58f951fca..af2f94ad1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -74,7 +74,7 @@ #ifdef ENABLE_IPV6 static bool use_ipv6 = FALSE; #endif -const char *ipv_inuse = "IPv4"; +static const char *ipv_inuse = "IPv4"; #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" -- cgit v1.2.1 From 88513d2d1ad60767b2d4e41a0e3a7b42894ff973 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Wed, 1 Oct 2008 17:34:24 +0000 Subject: Fixed some compiler warnings with gcc --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index af2f94ad1..3f11b3b0c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -490,7 +490,7 @@ static int ProcessRequest(struct httprequest *req) static void storerequest(char *reqbuf, ssize_t totalsize) { int res; - int error; + int error = 0; ssize_t written; ssize_t writeleft; FILE *dump; @@ -550,7 +550,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) char *reqbuf = req->reqbuf; ssize_t got = 0; - char *pipereq; + char *pipereq = NULL; int pipereq_length = 0; if(req->pipelining) { @@ -655,7 +655,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) bool persistant = TRUE; bool sendfailure = FALSE; size_t responsesize; - int error; + int error = 0; int res; static char weare[256]; -- cgit v1.2.1 From 640974fb282733c1e9387a168ea4d5748c26fdc3 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 25 Nov 2008 23:23:47 +0000 Subject: If a HTTP request is Basic and num is already >=1000, the HTTP test server adds 1 to num to get the data section to return. This allows testing authentication negotiations using the Basic authentication method. --- tests/server/sws.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 3f11b3b0c..5e3f3abc5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -442,6 +442,13 @@ static int ProcessRequest(struct httprequest *req) req->ntlm = TRUE; /* NTLM found */ logmsg("Received NTLM type-1, sending back data %ld", req->partno); } + else if((req->partno >= 1000) && strstr(req->reqbuf, "Authorization: Basic")) { + /* If the client is passing this Basic-header and the part number is already + >=1000, we add 1 to the part number. This allows simple Basic authentication + negotiation to work in the test suite. */ + req->partno += 1; + logmsg("Received Basic request, sending back data %ld", req->partno); + } if(strstr(req->reqbuf, "Connection: close")) req->open = FALSE; /* close connection after this request */ -- cgit v1.2.1 From af41fb79b5318c74d8ce33079dcbb2f6d6c417fd Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 27 Apr 2009 23:59:41 +0000 Subject: Include if HAVE_ARPA_INET_H is defined --- tests/server/sws.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5e3f3abc5..dee1b9db6 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,8 +41,7 @@ #ifdef HAVE_NETINET_IN_H #include #endif -#ifdef _XOPEN_SOURCE_EXTENDED -/* This define is "almost" required to build on HPUX 11 */ +#ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_NETDB_H -- cgit v1.2.1 From 3ca0b9bb47f015c0de7379da46d10948e0637302 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 11 Jun 2009 17:46:33 +0000 Subject: fix compiler warning --- tests/server/sws.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index dee1b9db6..99f188017 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -183,11 +183,8 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" "The requested URL was not found on this server.\n" "


" SWSVERSION "
\n" "\n"; -#ifdef SIGPIPE +#if defined(SIGPIPE) && defined(HAVE_SIGNAL) static volatile int sigpipe; /* Why? It's not used */ -#endif - -#ifdef SIGPIPE static void sigpipe_handler(int sig) { (void)sig; /* prevent warning */ -- cgit v1.2.1 From c2ce2aa4deea21fabfc1cb6fd65a6581b41390bd Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 12 Jun 2009 09:01:41 +0000 Subject: fix compiler warning --- tests/server/sws.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 99f188017..accf5555b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -183,13 +183,15 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" "The requested URL was not found on this server.\n" "


" SWSVERSION "
\n" "\n"; -#if defined(SIGPIPE) && defined(HAVE_SIGNAL) +#ifndef WIN32 +# if defined(SIGPIPE) && defined(HAVE_SIGNAL) static volatile int sigpipe; /* Why? It's not used */ static void sigpipe_handler(int sig) { (void)sig; /* prevent warning */ sigpipe = 1; } +# endif #endif static int ProcessRequest(struct httprequest *req) -- cgit v1.2.1 From f1320d67334c59461e312b1da18e7add2ad33b1e Mon Sep 17 00:00:00 2001 From: Gunter Knauf Date: Sat, 29 Aug 2009 15:44:31 +0000 Subject: add cast to silent compiler warning with 64bit systems. --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index accf5555b..7902c035f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -613,7 +613,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) logmsg("Read %zd bytes", got); - req->offset += got; + req->offset += (int)got; reqbuf[req->offset] = '\0'; if(ProcessRequest(req)) { -- cgit v1.2.1 From 31e106ced2b37e1cb1b54f9f5f5d56df82577ede Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 17 Sep 2009 11:45:27 +0000 Subject: Attempt to silence bogus compiler warning: "Potential null pointer dereference" --- tests/server/sws.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 7902c035f..84a5b34b0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -584,6 +584,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ-1) { + if(pipereq_length && pipereq) { if(pipereq_length) { memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; -- cgit v1.2.1 From be5c815f630f47fb9d9d520f526c24a902862db5 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 17 Sep 2009 14:02:50 +0000 Subject: remove line obsoleted with previous commit --- tests/server/sws.c | 1 - 1 file changed, 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 84a5b34b0..87a697957 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -585,7 +585,6 @@ static int get_request(curl_socket_t sock, struct httprequest *req) while (req->offset < REQBUFSIZ-1) { if(pipereq_length && pipereq) { - if(pipereq_length) { memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; pipereq_length = 0; -- cgit v1.2.1 From 094afbeb56ef77236c3b22d411ae53f212e90a01 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 23 Nov 2009 16:11:50 +0000 Subject: Enhance some debug messages for initialization failures. Fix compiler warning: conditional expression is constant. --- tests/server/sws.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 87a697957..0e17d6ebd 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -676,7 +676,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) case RCMD_STREAM: #define STREAMTHIS "a string to stream 01234567890\n" count = strlen(STREAMTHIS); - while(1) { + for (;;) { written = swrite(sock, STREAMTHIS, count); if(written != (ssize_t)count) { logmsg("Stopped streaming"); @@ -875,12 +875,14 @@ int main(int argc, char *argv[]) #ifdef ENABLE_IPV6 struct sockaddr_in6 me6; #endif /* ENABLE_IPV6 */ - curl_socket_t sock, msgsock; + curl_socket_t sock = CURL_SOCKET_BAD; + curl_socket_t msgsock = CURL_SOCKET_BAD; int flag; unsigned short port = DEFAULT_PORT; char *pidname= (char *)".http.pid"; struct httprequest req; int rc; + int error; int arg=1; #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; @@ -954,15 +956,19 @@ int main(int argc, char *argv[]) sock = socket(AF_INET6, SOCK_STREAM, 0); #endif - if (CURL_SOCKET_BAD == sock) { - logmsg("Error opening socket: %d", SOCKERRNO); + if(CURL_SOCKET_BAD == sock) { + error = SOCKERRNO; + logmsg("Error creating socket: (%d) %s", + error, strerror(error)); return 1; } flag = 1; if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (void *) &flag, sizeof(flag))) { - logmsg("setsockopt(SO_REUSEADDR) failed: %d", SOCKERRNO); + (void *)&flag, sizeof(flag))) { + error = SOCKERRNO; + logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s", + error, strerror(error)); sclose(sock); return 1; } @@ -986,7 +992,9 @@ int main(int argc, char *argv[]) } #endif /* ENABLE_IPV6 */ if(0 != rc) { - logmsg("Error binding socket: %d", SOCKERRNO); + error = SOCKERRNO; + logmsg("Error binding socket on port %hu: (%d) %s", + port, error, strerror(error)); sclose(sock); return 1; } @@ -1001,16 +1009,20 @@ int main(int argc, char *argv[]) /* start accepting connections */ rc = listen(sock, 5); if(0 != rc) { - logmsg("listen() failed with error: %d", SOCKERRNO); + error = SOCKERRNO; + logmsg("listen() failed with error: (%d) %s", + error, strerror(error)); sclose(sock); return 1; } - while (1) { + for (;;) { msgsock = accept(sock, NULL, NULL); if (CURL_SOCKET_BAD == msgsock) { - printf("MAJOR ERROR: accept() failed with error: %d\n", SOCKERRNO); + error = SOCKERRNO; + logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", + error, strerror(error)); break; } -- cgit v1.2.1 From fba233bb34d768f41e8ff35af54ba637f61eef2b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 26 Nov 2009 04:38:29 +0000 Subject: signal handling to cleanup on SIGINT and SIGTERM --- tests/server/sws.c | 197 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 167 insertions(+), 30 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0e17d6ebd..fab7ae59a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -183,16 +183,116 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n" "The requested URL was not found on this server.\n" "


" SWSVERSION "
\n" "\n"; -#ifndef WIN32 -# if defined(SIGPIPE) && defined(HAVE_SIGNAL) -static volatile int sigpipe; /* Why? It's not used */ -static void sigpipe_handler(int sig) +/* do-nothing macro replacement for systems which lack siginterrupt() */ + +#ifndef HAVE_SIGINTERRUPT +#define siginterrupt(x,y) do {} while(0) +#endif + +/* vars used to keep around previous signal handlers */ + +typedef RETSIGTYPE (*SIGHANDLER_T)(int); + +#ifdef SIGHUP +static SIGHANDLER_T old_sighup_handler = SIG_ERR; +#endif + +#ifdef SIGPIPE +static SIGHANDLER_T old_sigpipe_handler = SIG_ERR; +#endif + +#ifdef SIGALRM +static SIGHANDLER_T old_sigalrm_handler = SIG_ERR; +#endif + +#ifdef SIGINT +static SIGHANDLER_T old_sigint_handler = SIG_ERR; +#endif + +#ifdef SIGTERM +static SIGHANDLER_T old_sigterm_handler = SIG_ERR; +#endif + +/* var which if set indicates that the program should finish execution */ + +SIG_ATOMIC_T got_exit_signal = 0; + +/* if next is set indicates the first signal handled in exit_signal_handler */ + +static volatile int exit_signal = 0; + +/* signal handler that will be triggered to indicate that the program + should finish its execution in a controlled manner as soon as possible. + The first time this is called it will set got_exit_signal to one and + store in exit_signal the signal that triggered its execution. */ + +static RETSIGTYPE exit_signal_handler(int signum) { - (void)sig; /* prevent warning */ - sigpipe = 1; + int old_errno = ERRNO; + if(got_exit_signal == 0) { + got_exit_signal = 1; + exit_signal = signum; + } + (void)signal(signum, exit_signal_handler); + SET_ERRNO(old_errno); +} + +static void install_signal_handlers(void) +{ +#ifdef SIGHUP + /* ignore SIGHUP signal */ + if((old_sighup_handler = signal(SIGHUP, SIG_IGN)) == SIG_ERR) + logmsg("cannot install SIGHUP handler: %s", strerror(ERRNO)); +#endif +#ifdef SIGPIPE + /* ignore SIGPIPE signal */ + if((old_sigpipe_handler = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) + logmsg("cannot install SIGPIPE handler: %s", strerror(ERRNO)); +#endif +#ifdef SIGALRM + /* ignore SIGALRM signal */ + if((old_sigalrm_handler = signal(SIGALRM, SIG_IGN)) == SIG_ERR) + logmsg("cannot install SIGALRM handler: %s", strerror(ERRNO)); +#endif +#ifdef SIGINT + /* handle SIGINT signal with our exit_signal_handler */ + if((old_sigint_handler = signal(SIGINT, exit_signal_handler)) == SIG_ERR) + logmsg("cannot install SIGINT handler: %s", strerror(ERRNO)); + else + siginterrupt(SIGINT, 1); +#endif +#ifdef SIGTERM + /* handle SIGTERM signal with our exit_signal_handler */ + if((old_sigterm_handler = signal(SIGTERM, exit_signal_handler)) == SIG_ERR) + logmsg("cannot install SIGTERM handler: %s", strerror(ERRNO)); + else + siginterrupt(SIGTERM, 1); +#endif } -# endif + +static void restore_signal_handlers(void) +{ +#ifdef SIGHUP + if(SIG_ERR != old_sighup_handler) + (void)signal(SIGHUP, old_sighup_handler); +#endif +#ifdef SIGPIPE + if(SIG_ERR != old_sigpipe_handler) + (void)signal(SIGPIPE, old_sigpipe_handler); +#endif +#ifdef SIGALRM + if(SIG_ERR != old_sigalrm_handler) + (void)signal(SIGALRM, old_sigalrm_handler); +#endif +#ifdef SIGINT + if(SIG_ERR != old_sigint_handler) + (void)signal(SIGINT, old_sigint_handler); #endif +#ifdef SIGTERM + if(SIG_ERR != old_sigterm_handler) + (void)signal(SIGTERM, old_sigterm_handler); +#endif +} static int ProcessRequest(struct httprequest *req) { @@ -525,6 +625,10 @@ static void storerequest(char *reqbuf, ssize_t totalsize) do { written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft], 1, (size_t)writeleft, dump); + if(got_exit_signal) { + res = fclose(dump); + return; + } if (written > 0) writeleft -= written; } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); @@ -598,6 +702,8 @@ static int get_request(curl_socket_t sock, struct httprequest *req) else got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); } + if(got_exit_signal) + return 1; if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", SOCKERRNO); @@ -643,6 +749,9 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /* dump the request to an external file */ storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); + if(got_exit_signal) + return 1; + return fail; /* return 0 on success */ } @@ -678,6 +787,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) count = strlen(STREAMTHIS); for (;;) { written = swrite(sock, STREAMTHIS, count); + if(got_exit_signal) + break; if(written != (ssize_t)count) { logmsg("Stopped streaming"); break; @@ -877,6 +988,7 @@ int main(int argc, char *argv[]) #endif /* ENABLE_IPV6 */ curl_socket_t sock = CURL_SOCKET_BAD; curl_socket_t msgsock = CURL_SOCKET_BAD; + int wrotepidfile = 0; int flag; unsigned short port = DEFAULT_PORT; char *pidname= (char *)".http.pid"; @@ -935,18 +1047,10 @@ int main(int argc, char *argv[]) #ifdef WIN32 win32_init(); atexit(win32_cleanup); -#else - -#ifdef SIGPIPE -#ifdef HAVE_SIGNAL - signal(SIGPIPE, sigpipe_handler); -#endif -#ifdef HAVE_SIGINTERRUPT - siginterrupt(SIGPIPE, 1); -#endif -#endif #endif + install_signal_handlers(); + #ifdef ENABLE_IPV6 if(!use_ipv6) #endif @@ -960,7 +1064,7 @@ int main(int argc, char *argv[]) error = SOCKERRNO; logmsg("Error creating socket: (%d) %s", error, strerror(error)); - return 1; + goto sws_cleanup; } flag = 1; @@ -969,8 +1073,7 @@ int main(int argc, char *argv[]) error = SOCKERRNO; logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s", error, strerror(error)); - sclose(sock); - return 1; + goto sws_cleanup; } #ifdef ENABLE_IPV6 @@ -995,13 +1098,7 @@ int main(int argc, char *argv[]) error = SOCKERRNO; logmsg("Error binding socket on port %hu: (%d) %s", port, error, strerror(error)); - sclose(sock); - return 1; - } - - if(!write_pidfile(pidname)) { - sclose(sock); - return 1; + goto sws_cleanup; } logmsg("Running %s version on port %d", ipv_inuse, (int)port); @@ -1012,13 +1109,18 @@ int main(int argc, char *argv[]) error = SOCKERRNO; logmsg("listen() failed with error: (%d) %s", error, strerror(error)); - sclose(sock); - return 1; + goto sws_cleanup; } + wrotepidfile = write_pidfile(pidname); + if(!wrotepidfile) + goto sws_cleanup; + for (;;) { msgsock = accept(sock, NULL, NULL); + if(got_exit_signal) + break; if (CURL_SOCKET_BAD == msgsock) { error = SOCKERRNO; logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", @@ -1066,6 +1168,9 @@ int main(int argc, char *argv[]) req.pipelining = FALSE; do { + if(got_exit_signal) + break; + if(get_request(msgsock, &req)) /* non-zero means error, break out of loop */ break; @@ -1086,6 +1191,9 @@ int main(int argc, char *argv[]) send_doc(msgsock, &req); + if(got_exit_signal) + break; + if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { logmsg("special request received, no persistency"); break; @@ -1100,8 +1208,12 @@ int main(int argc, char *argv[]) /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); + if(got_exit_signal) + break; + logmsg("====> Client disconnect"); sclose(msgsock); + msgsock = CURL_SOCKET_BAD; clear_advisor_read_lock(SERVERLOGS_LOCK); @@ -1112,10 +1224,35 @@ int main(int argc, char *argv[]) #endif } - sclose(sock); +sws_cleanup: + + if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD)) + sclose(msgsock); + + if(sock != CURL_SOCKET_BAD) + sclose(sock); + + if(got_exit_signal) + logmsg("signalled to die"); + + if(wrotepidfile) + unlink(pidname); clear_advisor_read_lock(SERVERLOGS_LOCK); + restore_signal_handlers(); + + if(got_exit_signal) { + logmsg("========> sws exits with signal (%d)", exit_signal); + /* + * To properly set the return status of the process we + * must raise the same signal SIGINT or SIGTERM that we + * caught and let the old handler take care of it. + */ + raise(exit_signal); + } + + logmsg("========> sws quits"); return 0; } -- cgit v1.2.1 From cbd527843b4d0d04e33bb57d99c8e6139100db80 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 26 Nov 2009 10:15:08 +0000 Subject: Only attempt to clear the server-logs lock when previously set by this same server. --- tests/server/sws.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fab7ae59a..27434606d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -74,6 +74,7 @@ static bool use_ipv6 = FALSE; #endif static const char *ipv_inuse = "IPv4"; +static int serverlogslocked = 0; #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" @@ -1112,6 +1113,11 @@ int main(int argc, char *argv[]) goto sws_cleanup; } + /* + ** As soon as this server writes its pid file the test harness will + ** attempt to connect to this server and initiate its verification. + */ + wrotepidfile = write_pidfile(pidname); if(!wrotepidfile) goto sws_cleanup; @@ -1128,7 +1134,14 @@ int main(int argc, char *argv[]) break; } + /* + ** As soon as this server acepts a connection from the test harness it + ** must set the server logs advisor read lock to indicate that server + ** logs should not be read until this lock is removed by this server. + */ + set_advisor_read_lock(SERVERLOGS_LOCK); + serverlogslocked = 1; #ifdef CURL_SWS_FORK_ENABLED if(use_fork) { @@ -1215,7 +1228,10 @@ int main(int argc, char *argv[]) sclose(msgsock); msgsock = CURL_SOCKET_BAD; - clear_advisor_read_lock(SERVERLOGS_LOCK); + if(serverlogslocked) { + serverlogslocked = 0; + clear_advisor_read_lock(SERVERLOGS_LOCK); + } if (req.testno == DOCNUMBER_QUIT) break; @@ -1238,7 +1254,10 @@ sws_cleanup: if(wrotepidfile) unlink(pidname); - clear_advisor_read_lock(SERVERLOGS_LOCK); + if(serverlogslocked) { + serverlogslocked = 0; + clear_advisor_read_lock(SERVERLOGS_LOCK); + } restore_signal_handlers(); -- cgit v1.2.1 From f07f17f2a4f108db46ad3d92d7bd6b2739e6eea9 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 27 Nov 2009 12:01:25 +0000 Subject: Log sws IPv version, port and pid when exiting due to SIGINT or SIGTERM. --- tests/server/sws.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 27434606d..de16199d2 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -997,6 +997,7 @@ int main(int argc, char *argv[]) int rc; int error; int arg=1; + long pid; #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; #endif @@ -1052,6 +1053,8 @@ int main(int argc, char *argv[]) install_signal_handlers(); + pid = (long)getpid(); + #ifdef ENABLE_IPV6 if(!use_ipv6) #endif @@ -1262,7 +1265,8 @@ sws_cleanup: restore_signal_handlers(); if(got_exit_signal) { - logmsg("========> sws exits with signal (%d)", exit_signal); + logmsg("========> %s sws (port: %d pid: %ld) exits with signal (%d)", + ipv_inuse, (int)port, pid, exit_signal); /* * To properly set the return status of the process we * must raise the same signal SIGINT or SIGTERM that we -- cgit v1.2.1 From 0653fa107f6fb03555d49da86a1fbfc659873f5b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 9 Dec 2009 18:41:43 +0000 Subject: signal handling to cleanup on SIGINT and SIGTERM, followup --- tests/server/sws.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index de16199d2..ad851db89 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -879,6 +879,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) } } + if(got_exit_signal) + return -1; + dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ if(!dump) { error = ERRNO; @@ -951,13 +954,27 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(cmdsize > 0 ) { char command[32]; + int quarters; int num; ptr=cmd; do { if(2 == sscanf(ptr, "%31s %d", command, &num)) { if(!strcmp("wait", command)) { logmsg("Told to sleep for %d seconds", num); - sleep(num); /* wait this many seconds */ + quarters = num * 4; + while(quarters > 0) { + quarters--; + res = wait_ms(250); + if(got_exit_signal) + quarters = 0; + if(res) { + /* should not happen */ + error = SOCKERRNO; + logmsg("wait_ms() failed with error: (%d) %s", + error, strerror(error)); + quarters = 0; + } + } } else logmsg("Unknown command in reply command section"); -- cgit v1.2.1 From 6e9a484ea6e51fc0475d0e95c475dedf4cb94240 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 13 Dec 2009 03:45:32 +0000 Subject: signal handling to cleanup on SIGINT and SIGTERM, followup --- tests/server/sws.c | 103 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 43 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ad851db89..0e688deb3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -407,9 +407,12 @@ static int ProcessRequest(struct httprequest *req) req->rcmd = RCMD_STREAM; } else if(1 == sscanf(cmd, "pipe: %d", &num)) { - logmsg("instructed to allow a pipe size %d", num); - req->pipe = num-1; /* decrease by one since we don't count the - first request in this number */ + logmsg("instructed to allow a pipe size of %d", num); + if(num < 0) + logmsg("negative pipe size ignored"); + else if(num > 0) + req->pipe = num-1; /* decrease by one since we don't count the + first request in this number */ } else if(1 == sscanf(cmd, "skip: %d", &num)) { logmsg("instructed to skip this number of bytes %d", num); @@ -457,7 +460,7 @@ static int ProcessRequest(struct httprequest *req) if(!end) { /* we don't have a complete request yet! */ logmsg("ProcessRequest returned without a complete request"); - return 0; + return 0; /* not complete yet */ } logmsg("ProcessRequest found a complete request"); @@ -478,6 +481,9 @@ static int ProcessRequest(struct httprequest *req) */ do { + if(got_exit_signal) + return 1; /* done */ + if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) { /* If we don't ignore content-length, we read it and we read the whole request including the body before we return. If we've been told to @@ -508,6 +514,7 @@ static int ProcessRequest(struct httprequest *req) line = strchr(line, '\n'); if(line) line++; + } while(line); if(!req->auth && strstr(req->reqbuf, "Authorization:")) { @@ -565,6 +572,8 @@ static int ProcessRequest(struct httprequest *req) } while(req->pipe) { + if(got_exit_signal) + return 1; /* done */ /* scan for more header ends within this chunk */ line = &req->reqbuf[req->checkindex]; end = strstr(line, END_OF_HEADERS); @@ -574,13 +583,12 @@ static int ProcessRequest(struct httprequest *req) req->pipe--; } - /* If authentication is required and no auth was provided, end now. This makes the server NOT wait for PUT/POST data and you can then make the test case send a rejection before any such data has been sent. Test case 154 uses this.*/ if(req->auth_req && !req->auth) - return 1; + return 1; /* done */ if(req->cl > 0) { if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS)) @@ -626,37 +634,37 @@ static void storerequest(char *reqbuf, ssize_t totalsize) do { written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft], 1, (size_t)writeleft, dump); - if(got_exit_signal) { - res = fclose(dump); - return; - } - if (written > 0) + if(got_exit_signal) + goto storerequest_cleanup; + if(written > 0) writeleft -= written; } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); - if (writeleft > 0) { + if(writeleft == 0) + logmsg("Wrote request (%zd bytes) input to " REQUEST_DUMP, totalsize); + else if(writeleft > 0) { logmsg("Error writing file %s error: %d %s", REQUEST_DUMP, error, strerror(error)); logmsg("Wrote only (%zd bytes) of (%zd bytes) request input to %s", totalsize-writeleft, totalsize, REQUEST_DUMP); } +storerequest_cleanup: + do { res = fclose(dump); } while(res && ((error = ERRNO) == EINTR)); if(res) logmsg("Error closing file %s error: %d %s", REQUEST_DUMP, error, strerror(error)); - - if(!writeleft) - logmsg("Wrote request (%zd bytes) input to " REQUEST_DUMP, - totalsize); } /* return 0 on success, non-zero on failure */ static int get_request(curl_socket_t sock, struct httprequest *req) { + int error; int fail = 0; + int done_processing = 0; char *reqbuf = req->reqbuf; ssize_t got = 0; @@ -688,7 +696,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /*** end of httprequest init ***/ - while (req->offset < REQBUFSIZ-1) { + while(!done_processing && (req->offset < REQBUFSIZ-1)) { if(pipereq_length && pipereq) { memmove(reqbuf, pipereq, pipereq_length); got = pipereq_length; @@ -705,17 +713,20 @@ static int get_request(curl_socket_t sock, struct httprequest *req) } if(got_exit_signal) return 1; - if (got <= 0) { - if (got < 0) { - logmsg("recv() returned error: %d", SOCKERRNO); - return DOCNUMBER_INTERNAL; - } + if(got == 0) { logmsg("Connection closed by client"); + fail = 1; + } + else if(got < 0) { + error = SOCKERRNO; + logmsg("recv() returned error: (%d) %s", error, strerror(error)); + fail = 1; + } + if(fail) { + /* dump the request received so far to the external file */ reqbuf[req->offset] = '\0'; - - /* dump the request receivied so far to the external file */ storerequest(reqbuf, req->offset); - return DOCNUMBER_INTERNAL; + return 1; } logmsg("Read %zd bytes", got); @@ -723,12 +734,13 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->offset += (int)got; reqbuf[req->offset] = '\0'; - if(ProcessRequest(req)) { - if(req->pipe--) { - logmsg("Waiting for another piped request"); - continue; - } - break; + done_processing = ProcessRequest(req); + if(got_exit_signal) + return 1; + if(done_processing && req->pipe) { + logmsg("Waiting for another piped request"); + done_processing = 0; + req->pipe--; } } @@ -749,7 +761,6 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /* dump the request to an external file */ storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); - if(got_exit_signal) return 1; @@ -789,7 +800,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) for (;;) { written = swrite(sock, STREAMTHIS, count); if(got_exit_signal) - break; + return -1; if(written != (ssize_t)count) { logmsg("Stopped streaming"); break; @@ -863,6 +874,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) fclose(stream); } + if(got_exit_signal) + return -1; + /* re-open the same file again */ stream=fopen(filename, "rb"); if(!stream) { @@ -882,15 +896,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(got_exit_signal) return -1; - dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ - if(!dump) { - error = ERRNO; - logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", RESPONSE_DUMP); - logmsg("couldn't create logfile: " RESPONSE_DUMP); - return -1; - } - /* If the word 'swsclose' is present anywhere in the reply chunk, the connection will be closed after the data has been sent to the requesting client... */ @@ -905,6 +910,14 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) else prevbounce = FALSE; + dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ + if(!dump) { + error = ERRNO; + logmsg("fopen() failed with error: %d %s", error, strerror(error)); + logmsg("Error opening file: %s", RESPONSE_DUMP); + logmsg("couldn't create logfile: " RESPONSE_DUMP); + return -1; + } responsesize = count; do { @@ -924,6 +937,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) } /* write to file as well */ fwrite(buffer, 1, written, dump); + if(got_exit_signal) + break; count -= written; buffer += written; @@ -936,6 +951,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("Error closing file %s error: %d %s", RESPONSE_DUMP, error, strerror(error)); + if(got_exit_signal) + return -1; + if(sendfailure) { logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent", responsesize-count, responsesize); @@ -1223,7 +1241,6 @@ int main(int argc, char *argv[]) } send_doc(msgsock, &req); - if(got_exit_signal) break; -- cgit v1.2.1 From 364d76aca717432ce40b69fd951de71efdc18d9b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 14 Dec 2009 13:27:50 +0000 Subject: Fix compiler warnings --- tests/server/sws.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 0e688deb3..00fd74fe1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -91,10 +91,10 @@ static bool prevbounce=FALSE; /* instructs the server to increase the part struct httprequest { char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */ - int checkindex; /* where to start checking of the request */ - int offset; /* size of the incoming request */ - long testno; /* test number found in the request */ - long partno; /* part number found in the request */ + 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 */ + long partno; /* part number found in the request */ bool open; /* keep connection open info, as found in the request */ bool auth_req; /* authentication required, don't wait for body unless there's an Authorization header */ @@ -109,12 +109,12 @@ struct httprequest { bytes said in Content-Length, but the server only reads N - skip bytes. */ int rcmd; /* doing a special command, see defines above */ - int prot_version; /* HTTP version * 10 */ - bool pipelining; /* true if request is pipelined */ + int prot_version; /* HTTP version * 10 */ + bool pipelining; /* true if request is pipelined */ }; static int ProcessRequest(struct httprequest *req); -static void storerequest(char *reqbuf, ssize_t totalsize); +static void storerequest(char *reqbuf, size_t totalsize); #define DEFAULT_PORT 8999 @@ -367,7 +367,6 @@ static int ProcessRequest(struct httprequest *req) sprintf(logbuf, "Requested test number %ld part %ld", req->testno, req->partno); - logmsg("%s", logbuf); filename = test2file(req->testno); @@ -601,24 +600,18 @@ static int ProcessRequest(struct httprequest *req) } /* store the entire request in a file */ -static void storerequest(char *reqbuf, ssize_t totalsize) +static void storerequest(char *reqbuf, size_t totalsize) { int res; int error = 0; - ssize_t written; - ssize_t writeleft; + size_t written; + size_t writeleft; FILE *dump; if (reqbuf == NULL) return; - if (totalsize == 0) return; - else if (totalsize < 0) { - logmsg("Invalid size (%zd bytes) for request input. Not written to %s", - totalsize, REQUEST_DUMP); - return; - } do { dump = fopen(REQUEST_DUMP, "ab"); @@ -632,8 +625,8 @@ static void storerequest(char *reqbuf, ssize_t totalsize) writeleft = totalsize; do { - written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft], - 1, (size_t)writeleft, dump); + written = fwrite(&reqbuf[totalsize-writeleft], + 1, writeleft, dump); if(got_exit_signal) goto storerequest_cleanup; if(written > 0) @@ -641,11 +634,11 @@ static void storerequest(char *reqbuf, ssize_t totalsize) } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); if(writeleft == 0) - logmsg("Wrote request (%zd bytes) input to " REQUEST_DUMP, totalsize); + logmsg("Wrote request (%zu bytes) input to " REQUEST_DUMP, totalsize); else if(writeleft > 0) { logmsg("Error writing file %s error: %d %s", REQUEST_DUMP, error, strerror(error)); - logmsg("Wrote only (%zd bytes) of (%zd bytes) request input to %s", + logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s", totalsize-writeleft, totalsize, REQUEST_DUMP); } @@ -669,7 +662,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) ssize_t got = 0; char *pipereq = NULL; - int pipereq_length = 0; + size_t pipereq_length = 0; if(req->pipelining) { pipereq = reqbuf + req->checkindex; @@ -731,7 +724,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) logmsg("Read %zd bytes", got); - req->offset += (int)got; + req->offset += (size_t)got; reqbuf[req->offset] = '\0'; done_processing = ProcessRequest(req); @@ -849,8 +842,6 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) buffer = doc404; break; } - ptr = NULL; - stream=NULL; count = strlen(buffer); } @@ -910,7 +901,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) else prevbounce = FALSE; - dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ + dump = fopen(RESPONSE_DUMP, "ab"); if(!dump) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); -- cgit v1.2.1 From 002ed5f29800282b16c2d9df8480aa7386c93dea Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 16 Dec 2009 19:55:35 +0000 Subject: Test harness process control enhancements --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 00fd74fe1..5970f470c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -927,7 +927,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("Sent off %zd bytes", written); } /* write to file as well */ - fwrite(buffer, 1, written, dump); + fwrite(buffer, 1, (size_t)written, dump); if(got_exit_signal) break; -- cgit v1.2.1 From 7bede9180dba30806d01e619a26140028143ee06 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 22 Dec 2009 13:45:01 +0000 Subject: log a message when continuing once sleep time is over --- tests/server/sws.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5970f470c..5f8900239 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -975,15 +975,17 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) quarters--; res = wait_ms(250); if(got_exit_signal) - quarters = 0; + break; if(res) { /* should not happen */ error = SOCKERRNO; logmsg("wait_ms() failed with error: (%d) %s", error, strerror(error)); - quarters = 0; + break; } } + if(!quarters) + logmsg("Continuing after sleeping %d seconds", num); } else logmsg("Unknown command in reply command section"); -- cgit v1.2.1 From a114b7b1c062e86691bfec04595153b67734b7c7 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 8 Jan 2010 01:48:54 +0000 Subject: sws and tftpd command line option naming adjustments --- tests/server/sws.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5f8900239..9b6d9da9a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1051,6 +1051,18 @@ int main(int argc, char *argv[]) if(argc>arg) pidname = argv[arg++]; } + else if(!strcmp("--logfile", argv[arg])) { + arg++; + if(argc>arg) + serverlogfile = argv[arg++]; + } + else if(!strcmp("--ipv4", argv[arg])) { +#ifdef ENABLE_IPV6 + ipv_inuse = "IPv4"; + use_ipv6 = FALSE; +#endif + arg++; + } else if(!strcmp("--ipv6", argv[arg])) { #ifdef ENABLE_IPV6 ipv_inuse = "IPv6"; @@ -1064,13 +1076,31 @@ int main(int argc, char *argv[]) arg++; } #endif - else if(argc>arg) { - - if(atoi(argv[arg])) - port = (unsigned short)atoi(argv[arg++]); - - if(argc>arg) - path = argv[arg++]; + else if(!strcmp("--port", argv[arg])) { + arg++; + if(argc>arg) { + port = (unsigned short)atoi(argv[arg]); + arg++; + } + } + else if(!strcmp("--srcdir", argv[arg])) { + arg++; + if(argc>arg) { + path = argv[arg]; + arg++; + } + } + else { + puts("Usage: sws [option]\n" + " --version\n" + " --logfile [file]\n" + " --pidfile [file]\n" + " --ipv4\n" + " --ipv6\n" + " --port [port]\n" + " --srcdir [path]\n" + " --fork"); + return 0; } } -- cgit v1.2.1 From 232d17ec6486c79c2daa6a8f613d2e3fd94ae2fc Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 2 Feb 2010 12:39:10 +0000 Subject: avoid possibility of using obsoleted stuff --- tests/server/sws.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9b6d9da9a..62721b1bc 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -27,6 +27,9 @@ Wilke. Thanks a bunch! */ + +#define CURL_NO_OLDIES + #include "setup.h" /* portability help from the lib directory */ #ifdef HAVE_SIGNAL_H -- cgit v1.2.1 From f47b84b57ff74915820d26efc30459158bbe5c9c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 4 Feb 2010 17:17:19 +0000 Subject: Validate server port argument --- tests/server/sws.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 62721b1bc..16485f2f9 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1082,7 +1082,16 @@ int main(int argc, char *argv[]) else if(!strcmp("--port", argv[arg])) { arg++; if(argc>arg) { - port = (unsigned short)atoi(argv[arg]); + char *endptr; + long lnum = -1; + lnum = strtol(argv[arg], &endptr, 10); + if((endptr != argv[arg] + strlen(argv[arg])) || + (lnum < 1025L) || (lnum > 65535L)) { + fprintf(stderr, "sws: invalid --port argument (%s)\n", + argv[arg]); + return 0; + } + port = (unsigned short)(lnum & 0xFFFFL); arg++; } } -- cgit v1.2.1 From 68d83a8142e52643cc98d692dce54a49d9e2c386 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 14 Feb 2010 13:14:17 +0000 Subject: Overhauled test suite getpart() function. Fixing potential out of bounds stack and memory overwrites triggered with huge test case definitions. --- tests/server/sws.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 16485f2f9..e1dfe45d8 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -389,8 +389,13 @@ static int ProcessRequest(struct httprequest *req) int num=0; /* get the custom server control "commands" */ - cmd = (char *)spitout(stream, "reply", "servercmd", &cmdsize); + error = getpart(&cmd, &cmdsize, "reply", "servercmd", stream); fclose(stream); + if(error) { + logmsg("getpart() failed with error: %d", error); + req->open = FALSE; /* closes connection */ + return 1; /* done */ + } if(cmdsize) { logmsg("Found a reply-servercmd section!"); @@ -423,8 +428,9 @@ static int ProcessRequest(struct httprequest *req) else { logmsg("funny instruction found: %s", cmd); } - free(cmd); } + if(cmd) + free(cmd); } } else { @@ -863,13 +869,20 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } else { - buffer = spitout(stream, "reply", partbuf, &count); - ptr = (char *)buffer; + error = getpart(&ptr, &count, "reply", partbuf, stream); fclose(stream); + if(error) { + logmsg("getpart() failed with error: %d", error); + return 0; + } + buffer = ptr; } - if(got_exit_signal) + if(got_exit_signal) { + if(ptr) + free(ptr); return -1; + } /* re-open the same file again */ stream=fopen(filename, "rb"); @@ -878,17 +891,30 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", filename); logmsg("Couldn't open test file"); + if(ptr) + free(ptr); return 0; } else { /* get the custom server control "commands" */ - cmd = (char *)spitout(stream, "reply", "postcmd", &cmdsize); + error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream); fclose(stream); + if(error) { + logmsg("getpart() failed with error: %d", error); + if(ptr) + free(ptr); + return 0; + } } } - if(got_exit_signal) + if(got_exit_signal) { + if(ptr) + free(ptr); + if(cmd) + free(cmd); return -1; + } /* If the word 'swsclose' is present anywhere in the reply chunk, the connection will be closed after the data has been sent to the requesting @@ -910,6 +936,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", RESPONSE_DUMP); logmsg("couldn't create logfile: " RESPONSE_DUMP); + if(ptr) + free(ptr); + if(cmd) + free(cmd); return -1; } @@ -945,8 +975,13 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("Error closing file %s error: %d %s", RESPONSE_DUMP, error, strerror(error)); - if(got_exit_signal) + if(got_exit_signal) { + if(ptr) + free(ptr); + if(cmd) + free(cmd); return -1; + } if(sendfailure) { logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent", -- cgit v1.2.1 From d5b2d8e0810d2f6fb6e45d583cd9dea87bf40259 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 15 Feb 2010 17:40:35 +0000 Subject: fix compiler warning: conversion from "long" to "size_t" may lose sign --- tests/server/sws.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e1dfe45d8..b12b670b5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -497,10 +497,21 @@ static int ProcessRequest(struct httprequest *req) request including the body before we return. If we've been told to ignore the content-length, we will return as soon as all headers have been received */ - size_t cl = strtol(line+15, &line, 10); - req->cl = cl - req->skip; + char *endptr; + char *ptr = line + 15; + unsigned long clen = 0; + while(*ptr && (' ' == *ptr)) + ptr++; + clen = strtoul(ptr, &endptr, 10); + if((ptr == endptr) || ERRNO) { + /* this assumes that a zero Content-Length is valid */ + logmsg("Found invalid Content-Length: (%s) in the request", ptr); + req->open = FALSE; /* closes connection */ + return 1; /* done */ + } + req->cl = clen - req->skip; - logmsg("Found Content-Length: %zu in the request", cl); + logmsg("Found Content-Length: %lu in the request", clen); if(req->skip) logmsg("... but will abort after %zu bytes", req->cl); break; -- cgit v1.2.1 From f442dd6496c8710c4000a078e8085238fdaa7545 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 16 Feb 2010 11:17:00 +0000 Subject: fix Content-Length validation --- tests/server/sws.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b12b670b5..42446a9ac 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -500,10 +500,12 @@ static int ProcessRequest(struct httprequest *req) char *endptr; char *ptr = line + 15; unsigned long clen = 0; - while(*ptr && (' ' == *ptr)) + while(*ptr && ISSPACE(*ptr)) ptr++; + endptr = ptr; + SET_ERRNO(0); clen = strtoul(ptr, &endptr, 10); - if((ptr == endptr) || ERRNO) { + if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == ERRNO)) { /* this assumes that a zero Content-Length is valid */ logmsg("Found invalid Content-Length: (%s) in the request", ptr); req->open = FALSE; /* closes connection */ -- cgit v1.2.1 From 6e461e45c3623f53c682a7d08a2c38f096cc5b17 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 18 Feb 2010 12:31:24 +0000 Subject: fix compiler warning --- tests/server/sws.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 42446a9ac..5e1b0dc70 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1131,15 +1131,14 @@ int main(int argc, char *argv[]) arg++; if(argc>arg) { char *endptr; - long lnum = -1; - lnum = strtol(argv[arg], &endptr, 10); + unsigned long ulnum = strtoul(argv[arg], &endptr, 10); if((endptr != argv[arg] + strlen(argv[arg])) || - (lnum < 1025L) || (lnum > 65535L)) { + (ulnum < 1025UL) || (ulnum > 65535UL)) { fprintf(stderr, "sws: invalid --port argument (%s)\n", argv[arg]); return 0; } - port = (unsigned short)(lnum & 0xFFFFL); + port = (unsigned short)(ulnum & 0xFFFFUL); arg++; } } -- cgit v1.2.1 From 048438345aed2acbb044e107946a804bc2d02363 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 19 Feb 2010 18:02:38 +0000 Subject: fix compiler warning --- tests/server/sws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5e1b0dc70..14058e548 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -60,6 +60,7 @@ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" #include "util.h" +#include "warnless.h" /* include memdebug.h last */ #include "memdebug.h" @@ -1138,7 +1139,7 @@ int main(int argc, char *argv[]) argv[arg]); return 0; } - port = (unsigned short)(ulnum & 0xFFFFUL); + port = Curl_ultous(ulnum); arg++; } } -- cgit v1.2.1 From 439f62bfa8fff1b6370c286f4e06775aa81661bc Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 22 Feb 2010 18:56:29 +0000 Subject: convert Curl_ultous() and Curl_ultouc() functions to curlx_ultous() and curlx_ultouc(), exposing them through curlx.h to allow proper code reuse later in our test harness. --- tests/server/sws.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 14058e548..56345c1e5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -60,7 +60,6 @@ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" #include "util.h" -#include "warnless.h" /* include memdebug.h last */ #include "memdebug.h" @@ -1139,7 +1138,7 @@ int main(int argc, char *argv[]) argv[arg]); return 0; } - port = Curl_ultous(ulnum); + port = curlx_ultous(ulnum); arg++; } } -- cgit v1.2.1 From 2309b4e330b96bc2e1f8e36b6184015e59544037 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 Mar 2010 11:02:54 +0100 Subject: remove the CVSish $Id$ lines --- tests/server/sws.c | 1 - 1 file changed, 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 56345c1e5..44a84a986 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -18,7 +18,6 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ /* sws.c: simple (silly?) web server -- cgit v1.2.1 From 6ed72fd7fa138e427ce51a95832ce9b398f67440 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 25 Aug 2010 00:45:52 +0200 Subject: sws: added basic gopher support --- tests/server/sws.c | 75 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 12 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 44a84a986..8a93b3b8d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -75,6 +75,7 @@ #ifdef ENABLE_IPV6 static bool use_ipv6 = FALSE; #endif +static bool use_gopher = FALSE; static const char *ipv_inuse = "IPv4"; static int serverlogslocked = 0; @@ -159,6 +160,7 @@ enum { DOCNUMBER_404 = -1 }; +const char *end_of_headers = END_OF_HEADERS; /* sent as reply to a QUIT */ static const char *docquit = @@ -307,13 +309,22 @@ static int ProcessRequest(struct httprequest *req) int prot_major, prot_minor; char *end; int error; - end = strstr(line, END_OF_HEADERS); + end = strstr(line, end_of_headers); logmsg("ProcessRequest() called"); /* try to figure out the request characteristics as soon as possible, but only once! */ - if((req->testno == DOCNUMBER_NOTHING) && + + if(use_gopher && + (req->testno == DOCNUMBER_NOTHING) && + !strncmp("/verifiedserver", line, 15)) { + logmsg("Are-we-friendly question received"); + req->testno = DOCNUMBER_WERULEZ; + return 1; /* done */ + } + + else if((req->testno == DOCNUMBER_NOTHING) && sscanf(line, "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", request, @@ -471,10 +482,40 @@ static int ProcessRequest(struct httprequest *req) } logmsg("ProcessRequest found a complete request"); + if(use_gopher) { + /* when using gopher we cannot check the request until the entire + thing has been received */ + char *ptr; + + /* find the last slash in the line */ + ptr = strrchr(line, '/'); + + if(ptr) { + ptr++; /* skip the slash */ + + /* skip all non-numericals following the slash */ + while(*ptr && !ISDIGIT(*ptr)) + ptr++; + + req->testno = strtol(ptr, &ptr, 10); + + if(req->testno > 10000) { + req->partno = req->testno % 10000; + req->testno /= 10000; + } + else + req->partno = 0; + + sprintf(logbuf, "Requested GOPHER test number %ld part %ld", + req->testno, req->partno); + logmsg("%s", logbuf); + } + } + if(req->pipe) /* we do have a full set, advance the checkindex to after the end of the headers, for the pipelining case mostly */ - req->checkindex += (end - line) + strlen(END_OF_HEADERS); + req->checkindex += (end - line) + strlen(end_of_headers); /* **** Persistence **** * @@ -582,12 +623,12 @@ static int ProcessRequest(struct httprequest *req) req->open && req->prot_version >= 11 && end && - req->reqbuf + req->offset > end + strlen(END_OF_HEADERS) && + req->reqbuf + req->offset > end + strlen(end_of_headers) && (!strncmp(req->reqbuf, "GET", strlen("GET")) || !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) { /* If we have a persistent connection, HTTP version >= 1.1 and GET/HEAD request, enable pipelining. */ - req->checkindex = (end - req->reqbuf) + strlen(END_OF_HEADERS); + req->checkindex = (end - req->reqbuf) + strlen(end_of_headers); req->pipelining = TRUE; } @@ -596,10 +637,10 @@ static int ProcessRequest(struct httprequest *req) return 1; /* done */ /* scan for more header ends within this chunk */ line = &req->reqbuf[req->checkindex]; - end = strstr(line, END_OF_HEADERS); + end = strstr(line, end_of_headers); if(!end) break; - req->checkindex += (end - line) + strlen(END_OF_HEADERS); + req->checkindex += (end - line) + strlen(end_of_headers); req->pipe--; } @@ -611,7 +652,7 @@ static int ProcessRequest(struct httprequest *req) return 1; /* done */ if(req->cl > 0) { - if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS)) + if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers)) return 1; /* done */ else return 0; /* not complete yet */ @@ -842,8 +883,11 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) logmsg("Identifying ourselves as friends"); sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid()); msglen = strlen(msgbuf); - sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s", - msglen, msgbuf); + if(use_gopher) + sprintf(weare, "%s", msgbuf); + else + sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s", + msglen, msgbuf); buffer = weare; break; case DOCNUMBER_INTERNAL: @@ -1050,7 +1094,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(cmd) free(cmd); - req->open = persistant; + req->open = use_gopher?FALSE:persistant; prevtestno = req->testno; prevpartno = req->partno; @@ -1106,6 +1150,11 @@ int main(int argc, char *argv[]) if(argc>arg) serverlogfile = argv[arg++]; } + else if(!strcmp("--gopher", argv[arg])) { + arg++; + use_gopher = TRUE; + end_of_headers = "\r\n"; /* gopher style is much simpler */ + } else if(!strcmp("--ipv4", argv[arg])) { #ifdef ENABLE_IPV6 ipv_inuse = "IPv4"; @@ -1157,6 +1206,7 @@ int main(int argc, char *argv[]) " --ipv6\n" " --port [port]\n" " --srcdir [path]\n" + " --gopher\n" " --fork"); return 0; } @@ -1221,7 +1271,8 @@ int main(int argc, char *argv[]) goto sws_cleanup; } - logmsg("Running %s version on port %d", ipv_inuse, (int)port); + logmsg("Running %s %s version on port %d", + use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port); /* start accepting connections */ rc = listen(sock, 5); -- cgit v1.2.1 From 15622e69a995bb4bee04bc647d86d658860914be Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sat, 2 Oct 2010 00:21:59 +0200 Subject: sws: Added writedelay HTTP server command This delays between write operations, hopefully making it easier to spot problems where libcurl doesn't flush the socket properly before waiting for the next response. --- tests/server/sws.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 8a93b3b8d..a4c040bd2 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -105,6 +105,8 @@ struct httprequest { size_t cl; /* Content-Length of the incoming request */ bool digest; /* Authorization digest header found */ bool ntlm; /* Authorization ntlm header found */ + int writedelay; /* if non-zero, delay this number of seconds between + writes in the response */ int pipe; /* if non-zero, expect this many requests to do a "piped" request/response */ int skip; /* if non-zero, the server is instructed to not read this @@ -435,6 +437,10 @@ static int ProcessRequest(struct httprequest *req) logmsg("instructed to skip this number of bytes %d", num); req->skip = num; } + else if(1 == sscanf(cmd, "writedelay: %d", &num)) { + logmsg("instructed to delay %d secs between packets", num); + req->writedelay = num; + } else { logmsg("funny instruction found: %s", cmd); } @@ -745,6 +751,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->ntlm = FALSE; req->pipe = 0; req->skip = 0; + req->writedelay = 0; req->rcmd = RCMD_NORMALREQ; req->prot_version = 0; req->pipelining = FALSE; @@ -1015,6 +1022,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) else { logmsg("Sent off %zd bytes", written); } + if (req->writedelay) { + logmsg("Pausing %d seconds", req->writedelay); + sleep(req->writedelay); + } /* write to file as well */ fwrite(buffer, 1, (size_t)written, dump); if(got_exit_signal) -- cgit v1.2.1 From a768e39b2d6bd60cbf71e983f1003b22603cb71e Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 19 Nov 2010 19:20:38 +0100 Subject: test servers: fix strict aliasing compiler warnings --- tests/server/sws.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a4c040bd2..1650226e6 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -59,6 +59,7 @@ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" #include "util.h" +#include "server_sockaddr.h" /* include memdebug.h last */ #include "memdebug.h" @@ -1116,10 +1117,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) int main(int argc, char *argv[]) { - struct sockaddr_in me; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 me6; -#endif /* ENABLE_IPV6 */ + srvr_sockaddr_union_t me; curl_socket_t sock = CURL_SOCKET_BAD; curl_socket_t msgsock = CURL_SOCKET_BAD; int wrotepidfile = 0; @@ -1260,19 +1258,19 @@ int main(int argc, char *argv[]) #ifdef ENABLE_IPV6 if(!use_ipv6) { #endif - memset(&me, 0, sizeof(me)); - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; - me.sin_port = htons(port); - rc = bind(sock, (struct sockaddr *) &me, sizeof(me)); + memset(&me.sa4, 0, sizeof(me.sa4)); + me.sa4.sin_family = AF_INET; + me.sa4.sin_addr.s_addr = INADDR_ANY; + me.sa4.sin_port = htons(port); + rc = bind(sock, &me.sa, sizeof(me.sa4)); #ifdef ENABLE_IPV6 } else { - memset(&me6, 0, sizeof(me6)); - me6.sin6_family = AF_INET6; - me6.sin6_addr = in6addr_any; - me6.sin6_port = htons(port); - rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6)); + memset(&me.sa6, 0, sizeof(me.sa6)); + me.sa6.sin6_family = AF_INET6; + me.sa6.sin6_addr = in6addr_any; + me.sa6.sin6_port = htons(port); + rc = bind(sock, &me.sa, sizeof(me.sa6)); } #endif /* ENABLE_IPV6 */ if(0 != rc) { -- cgit v1.2.1 From 5db0a412ff6972e51ccddaf1e8d6a27c8de4990f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 28 Nov 2010 23:11:14 +0100 Subject: atoi: remove atoi usage --- tests/server/sws.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1650226e6..65a61c2ce 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -467,8 +467,8 @@ static int ProcessRequest(struct httprequest *req) /* if the host name starts with test, the port number used in the CONNECT line will be used as test number! */ char *portp = strchr(doc, ':'); - if(portp) - req->testno = atoi(portp+1); + if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) + req->testno = strtol(portp+1, NULL, 10); else req->testno = DOCNUMBER_CONNECT; } -- cgit v1.2.1 From 07f60235b06a172a98082d11f065c13f7ecb1ec0 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 2 Dec 2010 18:46:13 +0100 Subject: fix compiler warning: rounding, sign extension, or loss of accuracy may result --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 65a61c2ce..fb54c209b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -762,7 +762,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) while(!done_processing && (req->offset < REQBUFSIZ-1)) { if(pipereq_length && pipereq) { memmove(reqbuf, pipereq, pipereq_length); - got = pipereq_length; + got = curlx_uztosz(pipereq_length); pipereq_length = 0; } else { -- cgit v1.2.1 From 34127c7adc1f75e8f6f6404c1e44a4170c387f11 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 6 Dec 2010 14:45:34 +0100 Subject: sws: fix compier warning: external definition with no prior declaration --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fb54c209b..949831d6c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -163,7 +163,7 @@ enum { DOCNUMBER_404 = -1 }; -const char *end_of_headers = END_OF_HEADERS; +static const char *end_of_headers = END_OF_HEADERS; /* sent as reply to a QUIT */ static const char *docquit = -- cgit v1.2.1 From c7a4df16e0b183a68de83c92b0b287439ffa11b6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Jul 2011 19:15:06 +0200 Subject: sws: allow multiple commands in --- tests/server/sws.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 949831d6c..a9561f79f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -107,7 +107,7 @@ struct httprequest { bool digest; /* Authorization digest header found */ bool ntlm; /* Authorization ntlm header found */ int writedelay; /* if non-zero, delay this number of seconds between - writes in the response */ + writes in the response */ int pipe; /* if non-zero, expect this many requests to do a "piped" request/response */ int skip; /* if non-zero, the server is instructed to not read this @@ -397,12 +397,13 @@ static int ProcessRequest(struct httprequest *req) return 1; /* done */ } else { + char *orgcmd = NULL; char *cmd = NULL; size_t cmdsize = 0; int num=0; /* get the custom server control "commands" */ - error = getpart(&cmd, &cmdsize, "reply", "servercmd", stream); + error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); fclose(stream); if(error) { logmsg("getpart() failed with error: %d", error); @@ -410,8 +411,9 @@ static int ProcessRequest(struct httprequest *req) return 1; /* done */ } - if(cmdsize) { - logmsg("Found a reply-servercmd section!"); + cmd = orgcmd; + while(cmd && cmdsize) { + char *check; if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) { logmsg("instructed to require authorization header"); @@ -445,9 +447,26 @@ static int ProcessRequest(struct httprequest *req) else { logmsg("funny instruction found: %s", cmd); } + /* try to deal with CRLF or just LF */ + check = strchr(cmd, '\r'); + if(!check) + check = strchr(cmd, '\n'); + + if(check) { + /* get to the letter following the newline */ + while((*check == '\r') || (*check == '\n')) + check++; + + if(!*check) + /* if we reached a zero, get out */ + break; + cmd = check; + } + else + break; } - if(cmd) - free(cmd); + if(orgcmd) + free(orgcmd); } } else { -- cgit v1.2.1 From 650a504b2f244ad323f1b45c2f36a2f967f7870f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 17 Jul 2011 00:39:23 +0200 Subject: sws: don't enable pipelining for requests with content-length Log texts also modified and some white space edits --- tests/server/sws.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a9561f79f..688fb9e12 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -117,6 +117,7 @@ struct httprequest { int rcmd; /* doing a special command, see defines above */ int prot_version; /* HTTP version * 10 */ bool pipelining; /* true if request is pipelined */ + int callcount; /* times ProcessRequest() gets called */ }; static int ProcessRequest(struct httprequest *req); @@ -308,13 +309,16 @@ static int ProcessRequest(struct httprequest *req) bool chunked = FALSE; static char request[REQUEST_KEYWORD_SIZE]; static char doc[MAXDOCNAMELEN]; - char logbuf[256]; + char logbuf[456]; int prot_major, prot_minor; char *end; int error; end = strstr(line, end_of_headers); - logmsg("ProcessRequest() called"); + req->callcount++; + + logmsg("Process %d bytes request%s", req->offset, + req->callcount > 1?" [CONTINUED]":""); /* try to figure out the request characteristics as soon as possible, but only once! */ @@ -346,7 +350,7 @@ static int ProcessRequest(struct httprequest *req) FILE *stream; char *filename; - if((strlen(doc) + strlen(request)) < 200) + if((strlen(doc) + strlen(request)) < 400) sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", request, doc, prot_major, prot_minor); else @@ -500,13 +504,17 @@ static int ProcessRequest(struct httprequest *req) } } } + else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) { + logmsg("** Unusual request. Starts with %02x %02x %02x", + line[0], line[1], line[2]); + } if(!end) { /* we don't have a complete request yet! */ - logmsg("ProcessRequest returned without a complete request"); + logmsg("request not complete yet"); return 0; /* not complete yet */ } - logmsg("ProcessRequest found a complete request"); + logmsg("- request found to be complete"); if(use_gopher) { /* when using gopher we cannot check the request until the entire @@ -635,10 +643,11 @@ static int ProcessRequest(struct httprequest *req) req->ntlm = TRUE; /* NTLM found */ logmsg("Received NTLM type-1, sending back data %ld", req->partno); } - else if((req->partno >= 1000) && strstr(req->reqbuf, "Authorization: Basic")) { - /* If the client is passing this Basic-header and the part number is already - >=1000, we add 1 to the part number. This allows simple Basic authentication - negotiation to work in the test suite. */ + else if((req->partno >= 1000) && + strstr(req->reqbuf, "Authorization: Basic")) { + /* If the client is passing this Basic-header and the part number is + already >=1000, we add 1 to the part number. This allows simple Basic + authentication negotiation to work in the test suite. */ req->partno += 1; logmsg("Received Basic request, sending back data %ld", req->partno); } @@ -650,6 +659,7 @@ static int ProcessRequest(struct httprequest *req) req->prot_version >= 11 && end && req->reqbuf + req->offset > end + strlen(end_of_headers) && + !req->cl && (!strncmp(req->reqbuf, "GET", strlen("GET")) || !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) { /* If we have a persistent connection, HTTP version >= 1.1 @@ -674,8 +684,10 @@ static int ProcessRequest(struct httprequest *req) makes the server NOT wait for PUT/POST data and you can then make the test case send a rejection before any such data has been sent. Test case 154 uses this.*/ - if(req->auth_req && !req->auth) + if(req->auth_req && !req->auth) { + logmsg("Return early due to auth requested by none provided"); return 1; /* done */ + } if(req->cl > 0) { if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers)) @@ -775,6 +787,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->rcmd = RCMD_NORMALREQ; req->prot_version = 0; req->pipelining = FALSE; + req->callcount = 0; /*** end of httprequest init ***/ @@ -786,9 +799,9 @@ static int get_request(curl_socket_t sock, struct httprequest *req) } else { if(req->skip) - /* we are instructed to not read the entire thing, so we make sure to only - read what we're supposed to and NOT read the enire thing the client - wants to send! */ + /* we are instructed to not read the entire thing, so we make sure to + only read what we're supposed to and NOT read the enire thing the + client wants to send! */ got = sread(sock, reqbuf + req->offset, req->cl); else got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); @@ -870,7 +883,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) char partbuf[80]="data"; - logmsg("Send response number %ld part %ld", req->testno, req->partno); + logmsg("Send response test%ld section ", req->testno, req->partno); switch(req->rcmd) { default: @@ -1413,8 +1426,13 @@ int main(int argc, char *argv[]) break; } - if(req.open) - logmsg("=> persistant connection request ended, awaits new request"); + if(req.open) { + logmsg("=> persistant connection request ended, awaits new request\n"); + /* + const char *keepopen="[KEEPING CONNECTION OPEN]"; + storerequest((char *)keepopen, strlen(keepopen)); + */ + } /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); -- cgit v1.2.1 From fd10c047df694e55abc6950391d6822cecc3000b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 14 Oct 2011 17:33:05 +0200 Subject: sws.c: HTTP and GOPHER test server-side connection closing adjustment When, for a given test, server is instructed to close connection after server reply we now wait a very small amount of time (50ms) before doing so. This is done to allow client to, at least partially, read server reply before getting an ECONNRESET. The above is required to make test cases 1070, 1200, 1201 and 1202 pass with Cygwin 1.5.X on W2K. GOPHER test server closes connection after _every_ server-reply, as such, at some point it could require a bigger time or using shutdown() before a server-side initiated disconnection. --- tests/server/sws.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 688fb9e12..b2d6df7a6 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1440,6 +1440,14 @@ int main(int argc, char *argv[]) break; logmsg("====> Client disconnect"); + + if(!req.open) + /* When instructed to close connection after server-reply we + wait a very small amount of time before doing so. If this + is not done client might get an ECONNRESET before reading + a single byte of server-reply. */ + wait_ms(50); + sclose(msgsock); msgsock = CURL_SOCKET_BAD; -- cgit v1.2.1 From 82180643f4886d47816cf654f2ee46114e9c296f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 17 Dec 2011 23:47:22 +0100 Subject: test proxy supports CONNECT There's a new 'http-proxy' server for tests that runs on a separate port and lets clients do HTTP CONNECT to other ports on the same host to allow us to test HTTP "tunneling" properly. Test cases now have a section in to check that the proxy protocol part matches correctly. Test case 80, 83, 95, 275, 503 and 1078 have been converted. Test 1316 was added. --- tests/server/sws.c | 357 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 334 insertions(+), 23 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b2d6df7a6..fd56c8e99 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -79,6 +79,7 @@ static bool use_ipv6 = FALSE; static bool use_gopher = FALSE; static const char *ipv_inuse = "IPv4"; static int serverlogslocked = 0; +static bool is_proxy = FALSE; #define REQBUFSIZ 150000 #define REQBUFSIZ_TXT "149999" @@ -118,6 +119,7 @@ struct httprequest { int prot_version; /* HTTP version * 10 */ bool pipelining; /* true if request is pipelined */ int callcount; /* times ProcessRequest() gets called */ + int connect_port; /* the port number CONNECT used */ }; static int ProcessRequest(struct httprequest *req); @@ -136,6 +138,11 @@ const char *serverlogfile = DEFAULT_LOGFILE; #define REQUEST_DUMP "log/server.input" #define RESPONSE_DUMP "log/server.response" +/* when told to run as proxy, we store the logs in different files so that + they can co-exist with the same program running as a "server" */ +#define REQUEST_PROXY_DUMP "log/proxy.input" +#define RESPONSE_PROXY_DUMP "log/proxy.response" + /* very-big-path support */ #define MAXDOCNAMELEN 140000 #define MAXDOCNAMELEN_TXT "139999" @@ -476,25 +483,28 @@ static int ProcessRequest(struct httprequest *req) else { if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", doc, &prot_major, &prot_minor) == 3) { + char *portp; + sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request", doc, prot_major, prot_minor); logmsg("%s", logbuf); + portp = strchr(doc, ':'); + if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) + req->connect_port = strtol(portp+1, NULL, 10); + else + req->connect_port = 0; + if(req->prot_version == 10) req->open = FALSE; /* HTTP 1.0 closes connection by default */ 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)) { + 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! */ - char *portp = strchr(doc, ':'); - if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) - req->testno = strtol(portp+1, NULL, 10); - else - req->testno = DOCNUMBER_CONNECT; - } + req->testno = req->connect_port?req->connect_port:DOCNUMBER_CONNECT; else req->testno = DOCNUMBER_CONNECT; } @@ -707,6 +717,7 @@ static void storerequest(char *reqbuf, size_t totalsize) size_t written; size_t writeleft; FILE *dump; + const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP; if (reqbuf == NULL) return; @@ -714,12 +725,12 @@ static void storerequest(char *reqbuf, size_t totalsize) return; do { - dump = fopen(REQUEST_DUMP, "ab"); + dump = fopen(dumpfile, "ab"); } while ((dump == NULL) && ((error = ERRNO) == EINTR)); if (dump == NULL) { logmsg("Error opening file %s error: %d %s", - REQUEST_DUMP, error, strerror(error)); - logmsg("Failed to write request input to " REQUEST_DUMP); + dumpfile, error, strerror(error)); + logmsg("Failed to write request input "); return; } @@ -734,12 +745,12 @@ static void storerequest(char *reqbuf, size_t totalsize) } while ((writeleft > 0) && ((error = ERRNO) == EINTR)); if(writeleft == 0) - logmsg("Wrote request (%zu bytes) input to " REQUEST_DUMP, totalsize); + logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile); else if(writeleft > 0) { logmsg("Error writing file %s error: %d %s", - REQUEST_DUMP, error, strerror(error)); + dumpfile, error, strerror(error)); logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s", - totalsize-writeleft, totalsize, REQUEST_DUMP); + totalsize-writeleft, totalsize, dumpfile); } storerequest_cleanup: @@ -749,7 +760,7 @@ storerequest_cleanup: } while(res && ((error = ERRNO) == EINTR)); if(res) logmsg("Error closing file %s error: %d %s", - REQUEST_DUMP, error, strerror(error)); + dumpfile, error, strerror(error)); } /* return 0 on success, non-zero on failure */ @@ -788,6 +799,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->prot_version = 0; req->pipelining = FALSE; req->callcount = 0; + req->connect_port = 0; /*** end of httprequest init ***/ @@ -878,7 +890,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) size_t responsesize; int error = 0; int res; - + const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP; static char weare[256]; char partbuf[80]="data"; @@ -1026,12 +1038,11 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) else prevbounce = FALSE; - dump = fopen(RESPONSE_DUMP, "ab"); + dump = fopen(responsedump, "ab"); if(!dump) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); - logmsg("Error opening file: %s", RESPONSE_DUMP); - logmsg("couldn't create logfile: " RESPONSE_DUMP); + logmsg("Error opening file: %s", responsedump); if(ptr) free(ptr); if(cmd) @@ -1073,7 +1084,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) } while(res && ((error = ERRNO) == EINTR)); if(res) logmsg("Error closing file %s error: %d %s", - RESPONSE_DUMP, error, strerror(error)); + responsedump, error, strerror(error)); if(got_exit_signal) { if(ptr) @@ -1093,8 +1104,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return -1; } - logmsg("Response sent (%zu bytes) and written to " RESPONSE_DUMP, - responsesize); + logmsg("Response sent (%zu bytes) and written to %s", + responsesize, responsedump); if(ptr) free(ptr); @@ -1146,6 +1157,287 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } +static curl_socket_t connect_to(const char *ipaddr, int port) +{ + int flag; + struct sockaddr_in sin; + curl_socket_t serverfd; + unsigned long hostaddr; + + hostaddr = inet_addr(ipaddr); + + if(hostaddr == ( in_addr_t)-1) + return -1; + + logmsg("about to connect to %s:%d", ipaddr, port); + + serverfd = socket(AF_INET, SOCK_STREAM, 0); + +#ifdef TCP_NODELAY + /* + * Disable the Nagle algorithm + */ + flag = 1; + if (setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, + (void *)&flag, sizeof(flag)) == -1) { + logmsg("====> TCP_NODELAY for server conection failed"); + } +#endif + + sin.sin_family = AF_INET; + sin.sin_port = htons((short)port); + sin.sin_addr.s_addr = hostaddr; + if (connect(serverfd, (struct sockaddr*)(&sin), + sizeof(struct sockaddr_in)) != 0) { + fprintf(stderr, "failed to connect!\n"); + return -1; + } + + logmsg("connected fine to %s:%d, now tunnel!", ipaddr, port); + + return serverfd; +} + +/* + * A CONNECT has been received, a CONNECT response has been sent. + * + * This function needs to connect to the server, and then pass data between + * the client and the server back and forth until the connection is closed by + * either end. + * + * When doing FTP through a CONNECT proxy, we expect that the data connection + * will be setup while the first connect is still being kept up. Therefor we + * must accept a new connection and deal with it appropriately. + */ + +#define data_or_ctrl(x) ((x)?"DATA":"CTRL") + +static int http_connect(curl_socket_t infd, + curl_socket_t rootfd, + struct httprequest *req, + const char *ipaddr) +{ + curl_socket_t serverfd[2]; + curl_socket_t clientfd[2]; + curl_socket_t datafd = CURL_SOCKET_BAD; + int toc[2] = {0, 0}; /* number of bytes to client */ + int tos[2] = {0, 0}; /* number of bytes to server */ + char readclient[2][256]; + char readserver[2][256]; + bool poll_client[2] = { TRUE, TRUE }; + bool poll_server[2] = { TRUE, TRUE }; + int control=0; + int i; + + sleep(1); /* sleep here to make sure the client gets the CONNECT response + first and separate from the data that might follow here */ + + clientfd[0] = infd; + clientfd[1] = CURL_SOCKET_BAD; + + serverfd[0] = connect_to(ipaddr, req->connect_port); + if(CURL_SOCKET_BAD == serverfd[0]) + return 1; /* failure */ + serverfd[1] = CURL_SOCKET_BAD; /* nothing there (yet) */ + + /* connected, now tunnel */ + while(1) { + fd_set input; + fd_set output; + struct timeval timeout={1,0}; + ssize_t rc; + int maxfd=0; + int used; + + FD_ZERO(&input); + FD_ZERO(&output); + + if(CURL_SOCKET_BAD != rootfd) { + FD_SET(rootfd, &input); /* monitor this for new connections */ + maxfd=rootfd; + } + + /* set sockets to wait for */ + for(i=0; i<=control; i++) { + int mostfd = clientfd[i] > serverfd[i]? clientfd[i]: serverfd[i]; + used = 0; + if(mostfd > maxfd) + maxfd = mostfd; + + if(poll_client[i]) { + FD_SET(clientfd[i], &input); + used |= 1 << (i*4); + } + + if(poll_server[i]) { + FD_SET(serverfd[i], &input); + used |= 2 << (i*4); + } + + if(toc[i]) { /* if there is data to client, wait until we can write */ + FD_SET(clientfd[i], &output); + used |= 4 << (i*4); + } + if(tos[i]) { /* if there is data to server, wait until we can write */ + FD_SET(serverfd[i], &output); + used |= 8 << (i*4); + } + } + + rc = select(maxfd+1, &input, &output, NULL, &timeout); + + if(rc > 0) { + /* socket action */ + size_t len; + int precontrol; + + if((CURL_SOCKET_BAD != rootfd) && + FD_ISSET(rootfd, &input)) { + /* a new connection! */ + struct httprequest req2; + datafd = accept(rootfd, NULL, NULL); + if(CURL_SOCKET_BAD == datafd) + return 4; /* error! */ + logmsg("====> Client connect DATA"); + if(get_request(datafd, &req2)) + /* non-zero means error, break out of loop */ + break; + + send_doc(datafd, &req2); + + if(DOCNUMBER_CONNECT != req2.testno) { + /* eeek, not a CONNECT */ + close(datafd); + break; + } + + /* deal with the new connection */ + rootfd = CURL_SOCKET_BAD; /* prevent new connections */ + clientfd[1] = datafd; + + /* connect to the server */ + serverfd[1] = connect_to(ipaddr, req2.connect_port); + if(serverfd[1] == CURL_SOCKET_BAD) { + /* BADNESS, bail out */ + break; + } + control = 1; /* now we have two connections to work with */ + } + + /* store the value before the loop starts */ + precontrol = control; + + for(i=0; i<=control; i++) { + len = sizeof(readclient[i])-tos[i]; + if(len && FD_ISSET(clientfd[i], &input)) { + /* read from client */ + rc = recv(clientfd[i], &readclient[i][tos[i]], len, 0); + if(rc <= 0) { + logmsg("[%s] got %d at %s:%d, STOP READING client", data_or_ctrl(i), + rc, __FILE__, __LINE__); + poll_client[i] = FALSE; + } + else { + logmsg("[%s] READ %d bytes from client", data_or_ctrl(i), rc); + logmsg("[%s] READ \"%s\"", data_or_ctrl(i), + data_to_hex(&readclient[i][tos[i]], rc)); + tos[i] += rc; + } + } + + len = sizeof(readserver[i])-toc[i]; + if(len && FD_ISSET(serverfd[i], &input)) { + /* read from server */ + rc = recv(serverfd[i], &readserver[i][toc[i]], len, 0); + if(rc <= 0) { + logmsg("[%s] got %d at %s:%d, STOP READING server", data_or_ctrl(i), + rc, __FILE__, __LINE__); + poll_server[i] = FALSE; + } + else { + logmsg("[%s] READ %d bytes from server", data_or_ctrl(i), rc); + logmsg("[%s] READ \"%s\"", data_or_ctrl(i), + data_to_hex(&readserver[i][toc[i]], rc)); + toc[i] += rc; + } + } + if(toc[i] && FD_ISSET(clientfd[i], &output)) { + /* write to client */ + rc = send(clientfd[i], readserver[i], toc[i], 0); + if(rc <= 0) { + logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), + rc, __FILE__, __LINE__); + control--; + break; + } + logmsg("[%s] SENT %d bytes to client", data_or_ctrl(i), rc); + logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), + data_to_hex(readserver[i], rc)); + if(toc[i] - rc) + memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc); + toc[i] -= rc; + } + if(tos[i] && FD_ISSET(serverfd[i], &output)) { + /* write to server */ + rc = send(serverfd[i], readclient[i], tos[i], 0); + if(rc <= 0) { + logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), + rc, __FILE__, __LINE__); + control--; + break; + } + logmsg("[%s] SENT %d bytes to server", data_or_ctrl(i), rc); + logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), + data_to_hex(readclient[i], rc)); + if(tos - rc) + memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc); + tos[i] -= rc; + } + + if(!toc[i] && !poll_server[i]) { + /* nothing to send to the client is left, and server polling is + switched off, bail out */ + logmsg("[%s] ENDING1", data_or_ctrl(i)); + control--; + } + if(!tos[i] && !poll_client[i]) { + /* nothing to send to the server is left, and client polling is + switched off, bail out */ + logmsg("[%s] ENDING2", data_or_ctrl(i)); + control--; + } + } + if(precontrol > control) { + /* if the value was decremented we close the "lost" sockets */ + if(serverfd[precontrol] != CURL_SOCKET_BAD) + shutdown(serverfd[precontrol], SHUT_RDWR); + if(clientfd[precontrol] != CURL_SOCKET_BAD) + shutdown(clientfd[precontrol], SHUT_RDWR); + + sleep(1); + + if(serverfd[precontrol] != CURL_SOCKET_BAD) + close(serverfd[precontrol]); + if(clientfd[precontrol] != CURL_SOCKET_BAD) + close(clientfd[precontrol]); + + } + + if(control < 0) + break; + } + } +#if 0 + /* close all sockets we created */ + for(i=0; i<2; i++) { + if(serverfd[i] != CURL_SOCKET_BAD) + close(serverfd[i]); + if(clientfd[i] != CURL_SOCKET_BAD) + close(clientfd[i]); + } +#endif + return 0; +} int main(int argc, char *argv[]) { @@ -1161,6 +1453,7 @@ int main(int argc, char *argv[]) int error; int arg=1; long pid; + const char *hostport = "127.0.0.1"; #ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE; #endif @@ -1238,6 +1531,17 @@ int main(int argc, char *argv[]) arg++; } } + 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 */ + arg++; + if(argc>arg) { + hostport = argv[arg]; + arg++; + is_proxy = TRUE; + logmsg("Run as proxy, CONNECT to %s", hostport); + } + } else { puts("Usage: sws [option]\n" " --version\n" @@ -1247,6 +1551,7 @@ int main(int argc, char *argv[]) " --ipv6\n" " --port [port]\n" " --srcdir [path]\n" + " --connect [ip4-addr]\n" " --gopher\n" " --fork"); return 0; @@ -1316,7 +1621,7 @@ int main(int argc, char *argv[]) use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port); /* start accepting connections */ - rc = listen(sock, 5); + rc = listen(sock, 2); if(0 != rc) { error = SOCKERRNO; logmsg("listen() failed with error: (%d) %s", @@ -1417,6 +1722,12 @@ int main(int argc, char *argv[]) if(got_exit_signal) break; + if(DOCNUMBER_CONNECT == req.testno) { + /* a CONNECT request, setup and talk the tunnel */ + http_connect(msgsock, sock, &req, hostport); + break; + } + if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { logmsg("special request received, no persistency"); break; -- cgit v1.2.1 From 4bc6c1a026ea6890cdddd0e26926d545b44950c6 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 4 Jan 2012 19:14:19 +0100 Subject: sws.c: fix proxy mode segfault --- tests/server/sws.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fd56c8e99..9f0556f76 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1299,6 +1299,7 @@ static int http_connect(curl_socket_t infd, if(CURL_SOCKET_BAD == datafd) return 4; /* error! */ logmsg("====> Client connect DATA"); + req2.pipelining = FALSE; if(get_request(datafd, &req2)) /* non-zero means error, break out of loop */ break; -- cgit v1.2.1 From 812fa73057612a064e31041b0393aebb279c99b0 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 5 Jan 2012 20:51:23 +0100 Subject: sws.c: some IPv6 proxy mode peparatory adjustments --- tests/server/sws.c | 133 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 33 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 9f0556f76..e33fc2b97 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -58,6 +58,7 @@ versions instead */ #include "curlx.h" /* from the private lib dir */ #include "getpart.h" +#include "inet_pton.h" #include "util.h" #include "server_sockaddr.h" @@ -119,7 +120,7 @@ struct httprequest { int prot_version; /* HTTP version * 10 */ bool pipelining; /* true if request is pipelined */ int callcount; /* times ProcessRequest() gets called */ - int connect_port; /* the port number CONNECT used */ + unsigned short connect_port; /* the port number CONNECT used */ }; static int ProcessRequest(struct httprequest *req); @@ -483,21 +484,37 @@ static int ProcessRequest(struct httprequest *req) else { if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", doc, &prot_major, &prot_minor) == 3) { - char *portp; + char *portp = NULL; sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request", doc, prot_major, prot_minor); logmsg("%s", logbuf); - portp = strchr(doc, ':'); - if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) - req->connect_port = strtol(portp+1, NULL, 10); - else - req->connect_port = 0; - if(req->prot_version == 10) req->open = FALSE; /* HTTP 1.0 closes connection by default */ + if(doc[0] == '[') { + char *p = &doc[1]; + while(*p && (ISXDIGIT(*p) || (*p == ':') || (*p == '.'))) + p++; + if(*p != ']') + logmsg("Invalid CONNECT IPv6 address format"); + else if (*(p+1) != ':') + logmsg("Invalid CONNECT IPv6 port format"); + else + portp = p+1; + } + else + portp = strchr(doc, ':'); + + if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) { + unsigned long ulnum = strtoul(portp+1, NULL, 10); + if(!ulnum || (ulnum > 65535UL)) + logmsg("Invalid CONNECT port received"); + 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; @@ -506,7 +523,7 @@ static int ProcessRequest(struct httprequest *req) CONNECT line will be used as test number! */ req->testno = req->connect_port?req->connect_port:DOCNUMBER_CONNECT; else - req->testno = DOCNUMBER_CONNECT; + req->testno = req->connect_port?DOCNUMBER_CONNECT:DOCNUMBER_BADCONNECT; } else { logmsg("Did not find test number in PATH"); @@ -1157,43 +1174,93 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) return 0; } -static curl_socket_t connect_to(const char *ipaddr, int port) +static curl_socket_t connect_to(const char *ipaddr, unsigned short port) { - int flag; - struct sockaddr_in sin; + srvr_sockaddr_union_t serveraddr; curl_socket_t serverfd; - unsigned long hostaddr; + int error; + int rc; + const char *op_br = ""; + const char *cl_br = ""; +#ifdef TCP_NODELAY + curl_socklen_t flag = 1; + int level = IPPROTO_TCP; +#endif - hostaddr = inet_addr(ipaddr); +#ifdef ENABLE_IPV6 + if(use_ipv6) { + op_br = "["; + cl_br = "]"; + } +#endif - if(hostaddr == ( in_addr_t)-1) - return -1; + if(!ipaddr) + return CURL_SOCKET_BAD; - logmsg("about to connect to %s:%d", ipaddr, port); + logmsg("about to connect to %s%s%s:%hu", + op_br, ipaddr, cl_br, port); - serverfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef ENABLE_IPV6 + if(!use_ipv6) +#endif + serverfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef ENABLE_IPV6 + else + serverfd = socket(AF_INET6, SOCK_STREAM, 0); +#endif + if(CURL_SOCKET_BAD == serverfd) { + error = SOCKERRNO; + logmsg("Error creating socket for server conection: (%d) %s", + error, strerror(error)); + return CURL_SOCKET_BAD; + } #ifdef TCP_NODELAY - /* - * Disable the Nagle algorithm - */ - flag = 1; - if (setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, - (void *)&flag, sizeof(flag)) == -1) { + /* Disable the Nagle algorithm */ + if(setsockopt(serverfd, level, TCP_NODELAY, (void *)&flag, sizeof(flag)) < 0) logmsg("====> TCP_NODELAY for server conection failed"); - } #endif - sin.sin_family = AF_INET; - sin.sin_port = htons((short)port); - sin.sin_addr.s_addr = hostaddr; - if (connect(serverfd, (struct sockaddr*)(&sin), - sizeof(struct sockaddr_in)) != 0) { - fprintf(stderr, "failed to connect!\n"); - return -1; +#ifdef ENABLE_IPV6 + if(!use_ipv6) { +#endif + memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4)); + serveraddr.sa4.sin_family = AF_INET; + serveraddr.sa4.sin_port = htons(port); + serveraddr.sa4.sin_addr.s_addr = INADDR_ANY; + if(Curl_inet_pton(AF_INET, ipaddr, &serveraddr.sa4.sin_addr) < 1) { + logmsg("Error inet_pton failed AF_INET conversion of '%s'", ipaddr); + sclose(serverfd); + return CURL_SOCKET_BAD; + } + + rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4)); +#ifdef ENABLE_IPV6 + } + else { + memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6)); + serveraddr.sa6.sin6_family = AF_INET6; + serveraddr.sa6.sin6_port = htons(port); + if(Curl_inet_pton(AF_INET6, ipaddr, &serveraddr.sa6.sin6_addr) < 1) { + logmsg("Error inet_pton failed AF_INET6 conversion of '%s'", ipaddr); + sclose(serverfd); + return CURL_SOCKET_BAD; + } + + rc = connect(serverfd, &serveraddr.sa, sizeof(me.sa6)); + } +#endif /* ENABLE_IPV6 */ + + if(rc) { + error = SOCKERRNO; + logmsg("Error connecting to server port %hu: (%d) %s", + port, error, strerror(error)); + sclose(serverfd); + return CURL_SOCKET_BAD; } - logmsg("connected fine to %s:%d, now tunnel!", ipaddr, port); + logmsg("connected fine to %s%s%s:%hu, now tunnel", + op_br, ipaddr, cl_br, port); return serverfd; } -- cgit v1.2.1 From dd69a3e868ccb7aa911a0ddcf2b79d87fc5cd293 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 6 Jan 2012 01:52:45 +0100 Subject: sws.c: 812fa73057 follow-up --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e33fc2b97..323e08a63 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1247,7 +1247,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) return CURL_SOCKET_BAD; } - rc = connect(serverfd, &serveraddr.sa, sizeof(me.sa6)); + rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6)); } #endif /* ENABLE_IPV6 */ -- cgit v1.2.1 From 2705af626795cc966ca94ca72529119911c61f1f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 8 Jan 2012 19:28:46 +0100 Subject: sws.c: some compiler warning fixes --- tests/server/sws.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 323e08a63..1429b0d66 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1227,7 +1227,6 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4)); serveraddr.sa4.sin_family = AF_INET; serveraddr.sa4.sin_port = htons(port); - serveraddr.sa4.sin_addr.s_addr = INADDR_ANY; if(Curl_inet_pton(AF_INET, ipaddr, &serveraddr.sa4.sin_addr) < 1) { logmsg("Error inet_pton failed AF_INET conversion of '%s'", ipaddr); sclose(serverfd); @@ -1287,8 +1286,8 @@ static int http_connect(curl_socket_t infd, curl_socket_t serverfd[2]; curl_socket_t clientfd[2]; curl_socket_t datafd = CURL_SOCKET_BAD; - int toc[2] = {0, 0}; /* number of bytes to client */ - int tos[2] = {0, 0}; /* number of bytes to server */ + ssize_t toc[2] = {0, 0}; /* number of bytes to client */ + ssize_t tos[2] = {0, 0}; /* number of bytes to server */ char readclient[2][256]; char readserver[2][256]; bool poll_client[2] = { TRUE, TRUE }; @@ -1311,9 +1310,9 @@ static int http_connect(curl_socket_t infd, while(1) { fd_set input; fd_set output; - struct timeval timeout={1,0}; + struct timeval timeout = {1,0}; ssize_t rc; - int maxfd=0; + curl_socket_t maxfd = (curl_socket_t)-1; int used; FD_ZERO(&input); @@ -1321,12 +1320,13 @@ static int http_connect(curl_socket_t infd, if(CURL_SOCKET_BAD != rootfd) { FD_SET(rootfd, &input); /* monitor this for new connections */ - maxfd=rootfd; + maxfd = rootfd; } /* set sockets to wait for */ for(i=0; i<=control; i++) { - int mostfd = clientfd[i] > serverfd[i]? clientfd[i]: serverfd[i]; + curl_socket_t mostfd = clientfd[i] > serverfd[i] ? + clientfd[i] : serverfd[i]; used = 0; if(mostfd > maxfd) maxfd = mostfd; @@ -1351,7 +1351,7 @@ static int http_connect(curl_socket_t infd, } } - rc = select(maxfd+1, &input, &output, NULL, &timeout); + rc = select((int)maxfd + 1, &input, &output, NULL, &timeout); if(rc > 0) { /* socket action */ @@ -1375,7 +1375,7 @@ static int http_connect(curl_socket_t infd, if(DOCNUMBER_CONNECT != req2.testno) { /* eeek, not a CONNECT */ - close(datafd); + sclose(datafd); break; } @@ -1399,7 +1399,7 @@ static int http_connect(curl_socket_t infd, len = sizeof(readclient[i])-tos[i]; if(len && FD_ISSET(clientfd[i], &input)) { /* read from client */ - rc = recv(clientfd[i], &readclient[i][tos[i]], len, 0); + rc = sread(clientfd[i], &readclient[i][tos[i]], len); if(rc <= 0) { logmsg("[%s] got %d at %s:%d, STOP READING client", data_or_ctrl(i), rc, __FILE__, __LINE__); @@ -1416,7 +1416,7 @@ static int http_connect(curl_socket_t infd, len = sizeof(readserver[i])-toc[i]; if(len && FD_ISSET(serverfd[i], &input)) { /* read from server */ - rc = recv(serverfd[i], &readserver[i][toc[i]], len, 0); + rc = sread(serverfd[i], &readserver[i][toc[i]], len); if(rc <= 0) { logmsg("[%s] got %d at %s:%d, STOP READING server", data_or_ctrl(i), rc, __FILE__, __LINE__); @@ -1431,7 +1431,7 @@ static int http_connect(curl_socket_t infd, } if(toc[i] && FD_ISSET(clientfd[i], &output)) { /* write to client */ - rc = send(clientfd[i], readserver[i], toc[i], 0); + rc = swrite(clientfd[i], readserver[i], toc[i]); if(rc <= 0) { logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), rc, __FILE__, __LINE__); @@ -1447,7 +1447,7 @@ static int http_connect(curl_socket_t infd, } if(tos[i] && FD_ISSET(serverfd[i], &output)) { /* write to server */ - rc = send(serverfd[i], readclient[i], tos[i], 0); + rc = swrite(serverfd[i], readclient[i], tos[i]); if(rc <= 0) { logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), rc, __FILE__, __LINE__); @@ -1485,9 +1485,9 @@ static int http_connect(curl_socket_t infd, sleep(1); if(serverfd[precontrol] != CURL_SOCKET_BAD) - close(serverfd[precontrol]); + sclose(serverfd[precontrol]); if(clientfd[precontrol] != CURL_SOCKET_BAD) - close(clientfd[precontrol]); + sclose(clientfd[precontrol]); } @@ -1499,9 +1499,9 @@ static int http_connect(curl_socket_t infd, /* close all sockets we created */ for(i=0; i<2; i++) { if(serverfd[i] != CURL_SOCKET_BAD) - close(serverfd[i]); + sclose(serverfd[i]); if(clientfd[i] != CURL_SOCKET_BAD) - close(clientfd[i]); + sclose(clientfd[i]); } #endif return 0; -- cgit v1.2.1 From 123c92c904b2f258ae69e211aa2663e80cb5429a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 9 Jan 2012 22:49:28 +0100 Subject: sws.c: replace sleep() usage with wait_ms() --- tests/server/sws.c | 58 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 20 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1429b0d66..1ec63f2b0 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1083,18 +1083,21 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) else { logmsg("Sent off %zd bytes", written); } - if (req->writedelay) { - logmsg("Pausing %d seconds", req->writedelay); - sleep(req->writedelay); - } /* write to file as well */ fwrite(buffer, 1, (size_t)written, dump); - if(got_exit_signal) - break; count -= written; buffer += written; - } while(count>0); + + if(req->writedelay) { + int quarters = req->writedelay * 4; + logmsg("Pausing %d seconds", req->writedelay); + while((quarters > 0) && !got_exit_signal) { + quarters--; + wait_ms(250); + } + } + } while((count > 0) && !got_exit_signal); do { res = fclose(dump); @@ -1137,11 +1140,9 @@ static int send_doc(curl_socket_t sock, struct httprequest *req) if(!strcmp("wait", command)) { logmsg("Told to sleep for %d seconds", num); quarters = num * 4; - while(quarters > 0) { + while((quarters > 0) && !got_exit_signal) { quarters--; res = wait_ms(250); - if(got_exit_signal) - break; if(res) { /* should not happen */ error = SOCKERRNO; @@ -1250,6 +1251,11 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) } #endif /* ENABLE_IPV6 */ + if(got_exit_signal) { + sclose(serverfd); + return CURL_SOCKET_BAD; + } + if(rc) { error = SOCKERRNO; logmsg("Error connecting to server port %hu: (%d) %s", @@ -1278,10 +1284,10 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) #define data_or_ctrl(x) ((x)?"DATA":"CTRL") -static int http_connect(curl_socket_t infd, - curl_socket_t rootfd, - struct httprequest *req, - const char *ipaddr) +static void http_connect(curl_socket_t infd, + curl_socket_t rootfd, + struct httprequest *req, + const char *ipaddr) { curl_socket_t serverfd[2]; curl_socket_t clientfd[2]; @@ -1293,17 +1299,25 @@ static int http_connect(curl_socket_t infd, bool poll_client[2] = { TRUE, TRUE }; bool poll_server[2] = { TRUE, TRUE }; int control=0; + int quarters; int i; - sleep(1); /* sleep here to make sure the client gets the CONNECT response - first and separate from the data that might follow here */ + /* sleep here to make sure the client gets the CONNECT response + first and separate from the data that might follow here */ + quarters = 4; + while((quarters > 0) && !got_exit_signal) { + quarters--; + wait_ms(250); + } + if(got_exit_signal) + return; clientfd[0] = infd; clientfd[1] = CURL_SOCKET_BAD; serverfd[0] = connect_to(ipaddr, req->connect_port); if(CURL_SOCKET_BAD == serverfd[0]) - return 1; /* failure */ + return; serverfd[1] = CURL_SOCKET_BAD; /* nothing there (yet) */ /* connected, now tunnel */ @@ -1364,7 +1378,8 @@ static int http_connect(curl_socket_t infd, struct httprequest req2; datafd = accept(rootfd, NULL, NULL); if(CURL_SOCKET_BAD == datafd) - return 4; /* error! */ + return; + logmsg("====> Client connect DATA"); req2.pipelining = FALSE; if(get_request(datafd, &req2)) @@ -1482,7 +1497,11 @@ static int http_connect(curl_socket_t infd, if(clientfd[precontrol] != CURL_SOCKET_BAD) shutdown(clientfd[precontrol], SHUT_RDWR); - sleep(1); + quarters = 4; + while((quarters > 0) && !got_exit_signal) { + quarters--; + wait_ms(250); + } if(serverfd[precontrol] != CURL_SOCKET_BAD) sclose(serverfd[precontrol]); @@ -1504,7 +1523,6 @@ static int http_connect(curl_socket_t infd, sclose(clientfd[i]); } #endif - return 0; } int main(int argc, char *argv[]) -- cgit v1.2.1 From d4bf87dc0e1362c4a4aba5ff56548d0be2c6015a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 13 Jan 2012 05:13:48 +0100 Subject: sws.c: improve proxy mode torture testing support --- tests/server/sws.c | 463 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 286 insertions(+), 177 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 1ec63f2b0..5f6346e8c 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1218,7 +1218,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) #ifdef TCP_NODELAY /* Disable the Nagle algorithm */ - if(setsockopt(serverfd, level, TCP_NODELAY, (void *)&flag, sizeof(flag)) < 0) + if(setsockopt(serverfd, level, TCP_NODELAY, + (void *)&flag, sizeof(flag)) < 0) logmsg("====> TCP_NODELAY for server conection failed"); #endif @@ -1284,24 +1285,40 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) #define data_or_ctrl(x) ((x)?"DATA":"CTRL") -static void http_connect(curl_socket_t infd, +#define CTRL 0 +#define DATA 1 + +static void http_connect(curl_socket_t *infdp, curl_socket_t rootfd, struct httprequest *req, const char *ipaddr) { - curl_socket_t serverfd[2]; - curl_socket_t clientfd[2]; - curl_socket_t datafd = CURL_SOCKET_BAD; + curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; + curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD}; ssize_t toc[2] = {0, 0}; /* number of bytes to client */ ssize_t tos[2] = {0, 0}; /* number of bytes to server */ char readclient[2][256]; char readserver[2][256]; - bool poll_client[2] = { TRUE, TRUE }; - bool poll_server[2] = { TRUE, TRUE }; - int control=0; + bool poll_client_rd[2] = { TRUE, TRUE }; + bool poll_server_rd[2] = { TRUE, TRUE }; + bool poll_client_wr[2] = { TRUE, TRUE }; + bool poll_server_wr[2] = { TRUE, TRUE }; +#ifdef TCP_NODELAY + curl_socklen_t flag = 1; + int level = IPPROTO_TCP; +#endif + bool primary = FALSE; + bool secondary = FALSE; + int max_tunnel_idx; /* CTRL or DATA */ +#if 0 int quarters; +#endif int i; + /* primary tunnel client endpoint already connected */ + clientfd[CTRL] = *infdp; + +#if 0 /* sleep here to make sure the client gets the CONNECT response first and separate from the data that might follow here */ quarters = 4; @@ -1309,220 +1326,310 @@ static void http_connect(curl_socket_t infd, quarters--; wait_ms(250); } +#endif if(got_exit_signal) - return; + goto http_connect_cleanup; - clientfd[0] = infd; - clientfd[1] = CURL_SOCKET_BAD; + serverfd[CTRL] = connect_to(ipaddr, req->connect_port); + if(serverfd[CTRL] == CURL_SOCKET_BAD) + goto http_connect_cleanup; - serverfd[0] = connect_to(ipaddr, req->connect_port); - if(CURL_SOCKET_BAD == serverfd[0]) - return; - serverfd[1] = CURL_SOCKET_BAD; /* nothing there (yet) */ + /* Primary tunnel socket endpoints are now connected. Tunnel data back and + forth over the primary tunnel until client or server breaks the primary + tunnel, simultaneously allowing establishment, operation and teardown of + a secondary tunnel that may be used for passive FTP data connection. */ + + max_tunnel_idx = CTRL; + primary = TRUE; + + while(!got_exit_signal) { - /* connected, now tunnel */ - while(1) { fd_set input; fd_set output; - struct timeval timeout = {1,0}; + struct timeval timeout = {0, 250000L}; /* 250 ms */ ssize_t rc; curl_socket_t maxfd = (curl_socket_t)-1; - int used; FD_ZERO(&input); FD_ZERO(&output); - if(CURL_SOCKET_BAD != rootfd) { - FD_SET(rootfd, &input); /* monitor this for new connections */ + if((clientfd[DATA] == CURL_SOCKET_BAD) && + (serverfd[DATA] == CURL_SOCKET_BAD)) { + /* when secondary tunnel is not established the listener socket + is monitored to allow client to establish the secondary tunnel */ + FD_SET(rootfd, &input); maxfd = rootfd; } - /* set sockets to wait for */ - for(i=0; i<=control; i++) { - curl_socket_t mostfd = clientfd[i] > serverfd[i] ? - clientfd[i] : serverfd[i]; - used = 0; - if(mostfd > maxfd) - maxfd = mostfd; - - if(poll_client[i]) { - FD_SET(clientfd[i], &input); - used |= 1 << (i*4); - } - - if(poll_server[i]) { - FD_SET(serverfd[i], &input); - used |= 2 << (i*4); - } - - if(toc[i]) { /* if there is data to client, wait until we can write */ - FD_SET(clientfd[i], &output); - used |= 4 << (i*4); + /* set tunnel sockets to wait for */ + for(i = 0; i <= max_tunnel_idx; i++) { + /* client side socket monitoring */ + if(clientfd[i] != CURL_SOCKET_BAD) { + if(poll_client_rd[i]) { + /* unless told not to do so, monitor readability */ + FD_SET(clientfd[i], &input); + if(clientfd[i] > maxfd) + maxfd = clientfd[i]; + } + if(poll_client_wr[i] && toc[i]) { + /* unless told not to do so, monitor writeability + if there is data ready to be sent to client */ + FD_SET(clientfd[i], &output); + if(clientfd[i] > maxfd) + maxfd = clientfd[i]; + } } - if(tos[i]) { /* if there is data to server, wait until we can write */ - FD_SET(serverfd[i], &output); - used |= 8 << (i*4); + /* server side socket monitoring */ + if(serverfd[i] != CURL_SOCKET_BAD) { + if(poll_server_rd[i]) { + /* unless told not to do so, monitor readability */ + FD_SET(serverfd[i], &input); + if(serverfd[i] > maxfd) + maxfd = serverfd[i]; + } + if(poll_server_wr[i] && tos[i]) { + /* unless told not to do so, monitor writeability + if there is data ready to be sent to server */ + FD_SET(serverfd[i], &output); + if(serverfd[i] > maxfd) + maxfd = serverfd[i]; + } } } + if(got_exit_signal) + break; rc = select((int)maxfd + 1, &input, &output, NULL, &timeout); if(rc > 0) { /* socket action */ - size_t len; - int precontrol; - - if((CURL_SOCKET_BAD != rootfd) && - FD_ISSET(rootfd, &input)) { - /* a new connection! */ - struct httprequest req2; - datafd = accept(rootfd, NULL, NULL); - if(CURL_SOCKET_BAD == datafd) - return; - - logmsg("====> Client connect DATA"); - req2.pipelining = FALSE; - if(get_request(datafd, &req2)) - /* non-zero means error, break out of loop */ - break; - send_doc(datafd, &req2); + if(got_exit_signal) + break; - if(DOCNUMBER_CONNECT != req2.testno) { - /* eeek, not a CONNECT */ - sclose(datafd); - break; + /* ---------------------------------------------------------- */ + + /* passive mode FTP may establish a secondary tunnel */ + if((clientfd[DATA] == CURL_SOCKET_BAD) && + (serverfd[DATA] == CURL_SOCKET_BAD) && FD_ISSET(rootfd, &input)) { + /* a new connection on listener socket (most likely from client) */ + curl_socket_t datafd = accept(rootfd, NULL, NULL); + if(datafd != CURL_SOCKET_BAD) { + struct httprequest req2; + int err; + logmsg("====> Client connect DATA"); +#ifdef TCP_NODELAY + /* Disable the Nagle algorithm */ + if(setsockopt(datafd, level, TCP_NODELAY, + (void *)&flag, sizeof(flag)) < 0) + logmsg("====> TCP_NODELAY for client conection failed"); +#endif + req2.pipelining = FALSE; + err = get_request(datafd, &req2); + if(!err) { + err = send_doc(datafd, &req2); + if(!err && (req2.testno == DOCNUMBER_CONNECT)) { + /* connect to the server */ + serverfd[DATA] = connect_to(ipaddr, req2.connect_port); + if(serverfd[DATA] != CURL_SOCKET_BAD) { + /* secondary tunnel established, now we have two connections */ + poll_client_rd[DATA] = TRUE; + poll_client_wr[DATA] = TRUE; + poll_server_rd[DATA] = TRUE; + poll_server_wr[DATA] = TRUE; + max_tunnel_idx = DATA; + secondary = TRUE; + toc[DATA] = 0; + tos[DATA] = 0; + clientfd[DATA] = datafd; + datafd = CURL_SOCKET_BAD; + } + } + } + if(datafd != CURL_SOCKET_BAD) { + /* secondary tunnel not established */ + shutdown(datafd, SHUT_RDWR); + sclose(datafd); + } } - - /* deal with the new connection */ - rootfd = CURL_SOCKET_BAD; /* prevent new connections */ - clientfd[1] = datafd; - - /* connect to the server */ - serverfd[1] = connect_to(ipaddr, req2.connect_port); - if(serverfd[1] == CURL_SOCKET_BAD) { - /* BADNESS, bail out */ + if(got_exit_signal) break; - } - control = 1; /* now we have two connections to work with */ } - /* store the value before the loop starts */ - precontrol = control; - - for(i=0; i<=control; i++) { - len = sizeof(readclient[i])-tos[i]; - if(len && FD_ISSET(clientfd[i], &input)) { - /* read from client */ - rc = sread(clientfd[i], &readclient[i][tos[i]], len); - if(rc <= 0) { - logmsg("[%s] got %d at %s:%d, STOP READING client", data_or_ctrl(i), - rc, __FILE__, __LINE__); - poll_client[i] = FALSE; - } - else { - logmsg("[%s] READ %d bytes from client", data_or_ctrl(i), rc); - logmsg("[%s] READ \"%s\"", data_or_ctrl(i), - data_to_hex(&readclient[i][tos[i]], rc)); - tos[i] += rc; + /* ---------------------------------------------------------- */ + + /* react to tunnel endpoint readable/writeable notifications */ + for(i = 0; i <= max_tunnel_idx; i++) { + size_t len; + if(clientfd[i] != CURL_SOCKET_BAD) { + len = sizeof(readclient[i]) - tos[i]; + if(len && FD_ISSET(clientfd[i], &input)) { + /* read from client */ + rc = sread(clientfd[i], &readclient[i][tos[i]], len); + if(rc <= 0) { + logmsg("[%s] got %zd, STOP READING client", data_or_ctrl(i), rc); + shutdown(clientfd[i], SHUT_RD); + poll_client_rd[i] = FALSE; + } + else { + logmsg("[%s] READ %zd bytes from client", data_or_ctrl(i), rc); + logmsg("[%s] READ \"%s\"", data_or_ctrl(i), + data_to_hex(&readclient[i][tos[i]], rc)); + tos[i] += rc; + } } } - - len = sizeof(readserver[i])-toc[i]; - if(len && FD_ISSET(serverfd[i], &input)) { - /* read from server */ - rc = sread(serverfd[i], &readserver[i][toc[i]], len); - if(rc <= 0) { - logmsg("[%s] got %d at %s:%d, STOP READING server", data_or_ctrl(i), - rc, __FILE__, __LINE__); - poll_server[i] = FALSE; - } - else { - logmsg("[%s] READ %d bytes from server", data_or_ctrl(i), rc); - logmsg("[%s] READ \"%s\"", data_or_ctrl(i), - data_to_hex(&readserver[i][toc[i]], rc)); - toc[i] += rc; + if(serverfd[i] != CURL_SOCKET_BAD) { + len = sizeof(readserver[i])-toc[i]; + if(len && FD_ISSET(serverfd[i], &input)) { + /* read from server */ + rc = sread(serverfd[i], &readserver[i][toc[i]], len); + if(rc <= 0) { + logmsg("[%s] got %zd, STOP READING server", data_or_ctrl(i), rc); + shutdown(serverfd[i], SHUT_RD); + poll_server_rd[i] = FALSE; + } + else { + logmsg("[%s] READ %zd bytes from server", data_or_ctrl(i), rc); + logmsg("[%s] READ \"%s\"", data_or_ctrl(i), + data_to_hex(&readserver[i][toc[i]], rc)); + toc[i] += rc; + } } } - if(toc[i] && FD_ISSET(clientfd[i], &output)) { - /* write to client */ - rc = swrite(clientfd[i], readserver[i], toc[i]); - if(rc <= 0) { - logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), - rc, __FILE__, __LINE__); - control--; - break; + if(clientfd[i] != CURL_SOCKET_BAD) { + if(toc[i] && FD_ISSET(clientfd[i], &output)) { + /* write to client */ + rc = swrite(clientfd[i], readserver[i], toc[i]); + if(rc <= 0) { + logmsg("[%s] got %zd, STOP WRITING client", data_or_ctrl(i), rc); + shutdown(clientfd[i], SHUT_WR); + poll_client_wr[i] = FALSE; + } + else { + logmsg("[%s] SENT %zd bytes to client", data_or_ctrl(i), rc); + logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), + data_to_hex(readserver[i], rc)); + if(toc[i] - rc) + memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc); + toc[i] -= rc; + } } - logmsg("[%s] SENT %d bytes to client", data_or_ctrl(i), rc); - logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), - data_to_hex(readserver[i], rc)); - if(toc[i] - rc) - memmove(&readserver[i][0], &readserver[i][rc], toc[i]-rc); - toc[i] -= rc; } - if(tos[i] && FD_ISSET(serverfd[i], &output)) { - /* write to server */ - rc = swrite(serverfd[i], readclient[i], tos[i]); - if(rc <= 0) { - logmsg("[%s] got %d at %s:%d", data_or_ctrl(i), - rc, __FILE__, __LINE__); - control--; - break; + if(serverfd[i] != CURL_SOCKET_BAD) { + if(tos[i] && FD_ISSET(serverfd[i], &output)) { + /* write to server */ + rc = swrite(serverfd[i], readclient[i], tos[i]); + if(rc <= 0) { + logmsg("[%s] got %zd, STOP WRITING server", data_or_ctrl(i), rc); + shutdown(serverfd[i], SHUT_WR); + poll_server_wr[i] = FALSE; + } + else { + logmsg("[%s] SENT %zd bytes to server", data_or_ctrl(i), rc); + logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), + data_to_hex(readclient[i], rc)); + if(tos[i] - rc) + memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc); + tos[i] -= rc; + } } - logmsg("[%s] SENT %d bytes to server", data_or_ctrl(i), rc); - logmsg("[%s] SENT \"%s\"", data_or_ctrl(i), - data_to_hex(readclient[i], rc)); - if(tos - rc) - memmove(&readclient[i][0], &readclient[i][rc], tos[i]-rc); - tos[i] -= rc; } + } + if(got_exit_signal) + break; - if(!toc[i] && !poll_server[i]) { - /* nothing to send to the client is left, and server polling is - switched off, bail out */ - logmsg("[%s] ENDING1", data_or_ctrl(i)); - control--; - } - if(!tos[i] && !poll_client[i]) { - /* nothing to send to the server is left, and client polling is - switched off, bail out */ - logmsg("[%s] ENDING2", data_or_ctrl(i)); - control--; + /* ---------------------------------------------------------- */ + + /* endpoint read/write disabling, endpoint closing and tunnel teardown */ + for(i = 0; i <= max_tunnel_idx; i++) { + int loop; + for(loop = 2; loop; loop--) { + /* loop twice to satisfy condition interdependencies without + having to await select timeout or another socket event */ + if(clientfd[i] != CURL_SOCKET_BAD) { + if(poll_client_rd[i] && !poll_server_wr[i]) { + logmsg("[%s] DISABLED READING client", data_or_ctrl(i)); + shutdown(clientfd[i], SHUT_RD); + poll_client_rd[i] = FALSE; + } + if(poll_client_wr[i] && !poll_server_rd[i] && !toc[i]) { + logmsg("[%s] DISABLED WRITING client", data_or_ctrl(i)); + shutdown(clientfd[i], SHUT_WR); + poll_client_wr[i] = FALSE; + } + if(!poll_client_wr[i] && !poll_client_rd[i]) { + logmsg("[%s] CLOSING client socket", data_or_ctrl(i)); + sclose(clientfd[i]); + clientfd[i] = CURL_SOCKET_BAD; + if(serverfd[i] == CURL_SOCKET_BAD) { + logmsg("[%s] ENDING", data_or_ctrl(i)); + if(i == DATA) + secondary = FALSE; + else + primary = FALSE; + } + } + } + if(serverfd[i] != CURL_SOCKET_BAD) { + if(poll_server_rd[i] && !poll_client_wr[i]) { + logmsg("[%s] DISABLED READING server", data_or_ctrl(i)); + shutdown(serverfd[i], SHUT_RD); + poll_server_rd[i] = FALSE; + } + if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) { + logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i)); + shutdown(serverfd[i], SHUT_WR); + poll_server_wr[i] = FALSE; + } + if(!poll_server_wr[i] && !poll_server_rd[i]) { + logmsg("[%s] CLOSING server socket", data_or_ctrl(i)); + sclose(serverfd[i]); + serverfd[i] = CURL_SOCKET_BAD; + if(clientfd[i] == CURL_SOCKET_BAD) { + logmsg("[%s] ENDING", data_or_ctrl(i)); + if(i == DATA) + secondary = FALSE; + else + primary = FALSE; + } + } + } } } - if(precontrol > control) { - /* if the value was decremented we close the "lost" sockets */ - if(serverfd[precontrol] != CURL_SOCKET_BAD) - shutdown(serverfd[precontrol], SHUT_RDWR); - if(clientfd[precontrol] != CURL_SOCKET_BAD) - shutdown(clientfd[precontrol], SHUT_RDWR); - - quarters = 4; - while((quarters > 0) && !got_exit_signal) { - quarters--; - wait_ms(250); - } - if(serverfd[precontrol] != CURL_SOCKET_BAD) - sclose(serverfd[precontrol]); - if(clientfd[precontrol] != CURL_SOCKET_BAD) - sclose(clientfd[precontrol]); + /* ---------------------------------------------------------- */ - } + max_tunnel_idx = secondary ? DATA : CTRL; - if(control < 0) + if(!primary) + /* exit loop upon primary tunnel teardown */ break; - } + + } /* (rc > 0) */ + } -#if 0 - /* close all sockets we created */ - for(i=0; i<2; i++) { - if(serverfd[i] != CURL_SOCKET_BAD) + +http_connect_cleanup: + + for(i = DATA; i >= CTRL; i--) { + if(serverfd[i] != CURL_SOCKET_BAD) { + logmsg("[%s] CLOSING server socket (cleanup)", data_or_ctrl(i)); + shutdown(serverfd[i], SHUT_RDWR); sclose(serverfd[i]); - if(clientfd[i] != CURL_SOCKET_BAD) + } + if(clientfd[i] != CURL_SOCKET_BAD) { + logmsg("[%s] CLOSING client socket (cleanup)", data_or_ctrl(i)); + shutdown(clientfd[i], SHUT_RDWR); sclose(clientfd[i]); + } + if((serverfd[i] != CURL_SOCKET_BAD) || + (clientfd[i] != CURL_SOCKET_BAD)) { + logmsg("[%s] ABORTING", data_or_ctrl(i)); + } } -#endif + + *infdp = CURL_SOCKET_BAD; } int main(int argc, char *argv[]) @@ -1810,7 +1917,7 @@ int main(int argc, char *argv[]) if(DOCNUMBER_CONNECT == req.testno) { /* a CONNECT request, setup and talk the tunnel */ - http_connect(msgsock, sock, &req, hostport); + http_connect(&msgsock, sock, &req, hostport); break; } @@ -1845,8 +1952,10 @@ int main(int argc, char *argv[]) a single byte of server-reply. */ wait_ms(50); - sclose(msgsock); - msgsock = CURL_SOCKET_BAD; + if(msgsock != CURL_SOCKET_BAD) { + sclose(msgsock); + msgsock = CURL_SOCKET_BAD; + } if(serverlogslocked) { serverlogslocked = 0; -- cgit v1.2.1 From c731fc58ea3350f083d938687b088920c8ef981b Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 15 Jan 2012 20:13:32 +0100 Subject: sws.c: improve proxy mode torture testing support - followup to d4bf87dc --- tests/server/sws.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 5f6346e8c..42fd2035a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1403,10 +1403,13 @@ static void http_connect(curl_socket_t *infdp, if(rc > 0) { /* socket action */ + bool tcp_fin_wr; if(got_exit_signal) break; + tcp_fin_wr = FALSE; + /* ---------------------------------------------------------- */ /* passive mode FTP may establish a secondary tunnel */ @@ -1505,6 +1508,7 @@ static void http_connect(curl_socket_t *infdp, logmsg("[%s] got %zd, STOP WRITING client", data_or_ctrl(i), rc); shutdown(clientfd[i], SHUT_WR); poll_client_wr[i] = FALSE; + tcp_fin_wr = TRUE; } else { logmsg("[%s] SENT %zd bytes to client", data_or_ctrl(i), rc); @@ -1524,6 +1528,7 @@ static void http_connect(curl_socket_t *infdp, logmsg("[%s] got %zd, STOP WRITING server", data_or_ctrl(i), rc); shutdown(serverfd[i], SHUT_WR); poll_server_wr[i] = FALSE; + tcp_fin_wr = TRUE; } else { logmsg("[%s] SENT %zd bytes to server", data_or_ctrl(i), rc); @@ -1557,7 +1562,34 @@ static void http_connect(curl_socket_t *infdp, logmsg("[%s] DISABLED WRITING client", data_or_ctrl(i)); shutdown(clientfd[i], SHUT_WR); poll_client_wr[i] = FALSE; + tcp_fin_wr = TRUE; } + } + if(serverfd[i] != CURL_SOCKET_BAD) { + if(poll_server_rd[i] && !poll_client_wr[i]) { + logmsg("[%s] DISABLED READING server", data_or_ctrl(i)); + shutdown(serverfd[i], SHUT_RD); + poll_server_rd[i] = FALSE; + } + if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) { + logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i)); + shutdown(serverfd[i], SHUT_WR); + poll_server_wr[i] = FALSE; + tcp_fin_wr = TRUE; + } + } + } + } + + if(tcp_fin_wr) + /* allow kernel to place FIN bit packet on the wire */ + wait_ms(250); + + /* socket clearing */ + for(i = 0; i <= max_tunnel_idx; i++) { + int loop; + for(loop = 2; loop; loop--) { + if(clientfd[i] != CURL_SOCKET_BAD) { if(!poll_client_wr[i] && !poll_client_rd[i]) { logmsg("[%s] CLOSING client socket", data_or_ctrl(i)); sclose(clientfd[i]); @@ -1572,16 +1604,6 @@ static void http_connect(curl_socket_t *infdp, } } if(serverfd[i] != CURL_SOCKET_BAD) { - if(poll_server_rd[i] && !poll_client_wr[i]) { - logmsg("[%s] DISABLED READING server", data_or_ctrl(i)); - shutdown(serverfd[i], SHUT_RD); - poll_server_rd[i] = FALSE; - } - if(poll_server_wr[i] && !poll_client_rd[i] && !tos[i]) { - logmsg("[%s] DISABLED WRITING server", data_or_ctrl(i)); - shutdown(serverfd[i], SHUT_WR); - poll_server_wr[i] = FALSE; - } if(!poll_server_wr[i] && !poll_server_rd[i]) { logmsg("[%s] CLOSING server socket", data_or_ctrl(i)); sclose(serverfd[i]); -- cgit v1.2.1 From 18c6c8a5e79e63186b854bd888d1e9fbf264e4ce Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 16 Jan 2012 12:30:03 +0100 Subject: sws.c: improve proxy mode torture testing support - followup to c731fc58 --- tests/server/sws.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 42fd2035a..dff4b218d 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1310,23 +1310,17 @@ static void http_connect(curl_socket_t *infdp, bool primary = FALSE; bool secondary = FALSE; int max_tunnel_idx; /* CTRL or DATA */ -#if 0 - int quarters; -#endif + int loop; int i; /* primary tunnel client endpoint already connected */ clientfd[CTRL] = *infdp; -#if 0 - /* sleep here to make sure the client gets the CONNECT response - first and separate from the data that might follow here */ - quarters = 4; - while((quarters > 0) && !got_exit_signal) { - quarters--; + /* Sleep here to make sure the client reads CONNECT response's + 'end of headers' separate from the server data that follows. + This is done to prevent triggering libcurl known bug #39. */ + for(loop = 2; loop && !got_exit_signal; loop--) wait_ms(250); - } -#endif if(got_exit_signal) goto http_connect_cleanup; @@ -1548,7 +1542,6 @@ static void http_connect(curl_socket_t *infdp, /* endpoint read/write disabling, endpoint closing and tunnel teardown */ for(i = 0; i <= max_tunnel_idx; i++) { - int loop; for(loop = 2; loop; loop--) { /* loop twice to satisfy condition interdependencies without having to await select timeout or another socket event */ @@ -1587,7 +1580,6 @@ static void http_connect(curl_socket_t *infdp, /* socket clearing */ for(i = 0; i <= max_tunnel_idx; i++) { - int loop; for(loop = 2; loop; loop--) { if(clientfd[i] != CURL_SOCKET_BAD) { if(!poll_client_wr[i] && !poll_client_rd[i]) { -- cgit v1.2.1 From b15024be4d768a4ea4345bbfb768dcf5fbcd01a7 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 16 Jan 2012 19:00:57 +0100 Subject: sws.c: improve proxy mode torture testing support - followup to 18c6c8a5 --- tests/server/sws.c | 72 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 31 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index dff4b218d..244f91b75 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1184,8 +1184,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) const char *op_br = ""; const char *cl_br = ""; #ifdef TCP_NODELAY - curl_socklen_t flag = 1; - int level = IPPROTO_TCP; + curl_socklen_t flag; #endif #ifdef ENABLE_IPV6 @@ -1218,9 +1217,12 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) #ifdef TCP_NODELAY /* Disable the Nagle algorithm */ - if(setsockopt(serverfd, level, TCP_NODELAY, - (void *)&flag, sizeof(flag)) < 0) + flag = 1; + if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, + (void *)&flag, sizeof(flag))) logmsg("====> TCP_NODELAY for server conection failed"); + else + logmsg("TCP_NODELAY set for server conection"); #endif #ifdef ENABLE_IPV6 @@ -1304,8 +1306,7 @@ static void http_connect(curl_socket_t *infdp, bool poll_client_wr[2] = { TRUE, TRUE }; bool poll_server_wr[2] = { TRUE, TRUE }; #ifdef TCP_NODELAY - curl_socklen_t flag = 1; - int level = IPPROTO_TCP; + curl_socklen_t flag; #endif bool primary = FALSE; bool secondary = FALSE; @@ -1319,7 +1320,7 @@ static void http_connect(curl_socket_t *infdp, /* Sleep here to make sure the client reads CONNECT response's 'end of headers' separate from the server data that follows. This is done to prevent triggering libcurl known bug #39. */ - for(loop = 2; loop && !got_exit_signal; loop--) + for(loop = 2; (loop > 0) && !got_exit_signal; loop--) wait_ms(250); if(got_exit_signal) goto http_connect_cleanup; @@ -1417,29 +1418,37 @@ static void http_connect(curl_socket_t *infdp, logmsg("====> Client connect DATA"); #ifdef TCP_NODELAY /* Disable the Nagle algorithm */ - if(setsockopt(datafd, level, TCP_NODELAY, - (void *)&flag, sizeof(flag)) < 0) - logmsg("====> TCP_NODELAY for client conection failed"); + flag = 1; + if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY, + (void *)&flag, sizeof(flag))) + logmsg("====> TCP_NODELAY for client DATA conection failed"); + else + logmsg("TCP_NODELAY set for client DATA conection"); #endif req2.pipelining = FALSE; err = get_request(datafd, &req2); if(!err) { err = send_doc(datafd, &req2); if(!err && (req2.testno == DOCNUMBER_CONNECT)) { - /* connect to the server */ - serverfd[DATA] = connect_to(ipaddr, req2.connect_port); - if(serverfd[DATA] != CURL_SOCKET_BAD) { - /* secondary tunnel established, now we have two connections */ - poll_client_rd[DATA] = TRUE; - poll_client_wr[DATA] = TRUE; - poll_server_rd[DATA] = TRUE; - poll_server_wr[DATA] = TRUE; - max_tunnel_idx = DATA; - secondary = TRUE; - toc[DATA] = 0; - tos[DATA] = 0; - clientfd[DATA] = datafd; - datafd = CURL_SOCKET_BAD; + /* sleep to prevent triggering libcurl known bug #39. */ + for(loop = 2; (loop > 0) && !got_exit_signal; loop--) + wait_ms(250); + if(!got_exit_signal) { + /* connect to the server */ + serverfd[DATA] = connect_to(ipaddr, req2.connect_port); + if(serverfd[DATA] != CURL_SOCKET_BAD) { + /* secondary tunnel established, now we have two connections */ + poll_client_rd[DATA] = TRUE; + poll_client_wr[DATA] = TRUE; + poll_server_rd[DATA] = TRUE; + poll_server_wr[DATA] = TRUE; + max_tunnel_idx = DATA; + secondary = TRUE; + toc[DATA] = 0; + tos[DATA] = 0; + clientfd[DATA] = datafd; + datafd = CURL_SOCKET_BAD; + } } } } @@ -1542,7 +1551,7 @@ static void http_connect(curl_socket_t *infdp, /* endpoint read/write disabling, endpoint closing and tunnel teardown */ for(i = 0; i <= max_tunnel_idx; i++) { - for(loop = 2; loop; loop--) { + for(loop = 2; loop > 0; loop--) { /* loop twice to satisfy condition interdependencies without having to await select timeout or another socket event */ if(clientfd[i] != CURL_SOCKET_BAD) { @@ -1580,7 +1589,7 @@ static void http_connect(curl_socket_t *infdp, /* socket clearing */ for(i = 0; i <= max_tunnel_idx; i++) { - for(loop = 2; loop; loop--) { + for(loop = 2; loop > 0; loop--) { if(clientfd[i] != CURL_SOCKET_BAD) { if(!poll_client_wr[i] && !poll_client_rd[i]) { logmsg("[%s] CLOSING client socket", data_or_ctrl(i)); @@ -1791,8 +1800,8 @@ int main(int argc, char *argv[]) } flag = 1; - if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (void *)&flag, sizeof(flag))) { + if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (void *)&flag, sizeof(flag))) { error = SOCKERRNO; logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s", error, strerror(error)); @@ -1891,10 +1900,11 @@ int main(int argc, char *argv[]) * response in many small segments to torture the clients more. */ flag = 1; - if (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, - (void *)&flag, sizeof(flag)) == -1) { + if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, + (void *)&flag, sizeof(flag))) logmsg("====> TCP_NODELAY failed"); - } + else + logmsg("TCP_NODELAY set"); #endif /* initialization of httprequest struct is done in get_request(), but due -- cgit v1.2.1 From 2b9fafd6226448458995fc6c60c3de3552722c2a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 17 Jan 2012 12:28:28 +0100 Subject: sws.c: fix proxy mode secondary connection monitoring condition --- tests/server/sws.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 244f91b75..dddc606db 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1349,9 +1349,12 @@ static void http_connect(curl_socket_t *infdp, FD_ZERO(&output); if((clientfd[DATA] == CURL_SOCKET_BAD) && - (serverfd[DATA] == CURL_SOCKET_BAD)) { - /* when secondary tunnel is not established the listener socket - is monitored to allow client to establish the secondary tunnel */ + (serverfd[DATA] == CURL_SOCKET_BAD) && + poll_client_rd[CTRL] && poll_client_wr[CTRL] && + poll_server_rd[CTRL] && poll_server_wr[CTRL]) { + /* listener socket is monitored to allow client to establish + secondary tunnel only when this tunnel is not established + and primary one is fully operational */ FD_SET(rootfd, &input); maxfd = rootfd; } @@ -1837,7 +1840,7 @@ int main(int argc, char *argv[]) use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port); /* start accepting connections */ - rc = listen(sock, 2); + rc = listen(sock, 5); if(0 != rc) { error = SOCKERRNO; logmsg("listen() failed with error: (%d) %s", -- cgit v1.2.1 From 805788e0434f4f09d8049c51000af604efb800ed Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 21 Mar 2012 23:21:52 +0100 Subject: SWS: refuse to serve CONNECT unless running as proxy --- tests/server/sws.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index dddc606db..ef54bc65e 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1944,7 +1944,11 @@ int main(int argc, char *argv[]) if(DOCNUMBER_CONNECT == req.testno) { /* a CONNECT request, setup and talk the tunnel */ - http_connect(&msgsock, sock, &req, hostport); + if(!is_proxy) { + logmsg("received CONNECT but isn't running as proxy! EXIT"); + } + else + http_connect(&msgsock, sock, &req, hostport); break; } -- cgit v1.2.1 From 4d3fb91fb45ca404322d5146f43cae93d918a9a8 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Tue, 10 Apr 2012 17:32:06 +0200 Subject: test servers: build adjustment Undefine CURL_HIDDEN_SYMBOLS libcurl private preprocessor macro that might leak from lib/setup.h into source files where this should not be defined. --- tests/server/sws.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index ef54bc65e..14369e1d5 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -19,6 +19,7 @@ * KIND, either express or implied. * ***************************************************************************/ +#include "server_setup.h" /* sws.c: simple (silly?) web server @@ -27,10 +28,6 @@ */ -#define CURL_NO_OLDIES - -#include "setup.h" /* portability help from the lib directory */ - #ifdef HAVE_SIGNAL_H #include #endif -- cgit v1.2.1 From 28dc509dde13e0f8da1b5dca2979d936609a4698 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 Jul 2012 09:31:04 +0200 Subject: sws: add 'connection-monitor' command support Using this, the server will output in the protocol log when the connection gets disconnected and thus we will verify correctly in the test cases that the connection doesn't get closed prematurely. This is important for example NTLM to work. Documentation added to FILEFORMAT, test 503 updated to use this. --- tests/server/sws.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 14369e1d5..21e3bf57a 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -118,6 +118,7 @@ struct httprequest { 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 */ }; static int ProcessRequest(struct httprequest *req); @@ -157,6 +158,11 @@ const char *serverlogfile = DEFAULT_LOGFILE; /* 'stream' means to send a never-ending stream of data */ #define CMD_STREAM "stream" +/* 'connection-monitor' will output when a server/proxy connection gets + disconnected as for some cases it is important that it gets done at the + proper point - like with NTLM */ +#define CMD_CONNECTIONMONITOR "connection-monitor" + #define END_OF_HEADERS "\r\n\r\n" enum { @@ -437,6 +443,11 @@ static int ProcessRequest(struct httprequest *req) logmsg("instructed to stream"); req->rcmd = RCMD_STREAM; } + else if(!strncmp(CMD_CONNECTIONMONITOR, cmd, + strlen(CMD_CONNECTIONMONITOR))) { + logmsg("enabled connection monitoring"); + req->connmon = TRUE; + } else if(1 == sscanf(cmd, "pipe: %d", &num)) { logmsg("instructed to allow a pipe size of %d", num); if(num < 0) @@ -814,6 +825,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->pipelining = FALSE; req->callcount = 0; req->connect_port = 0; + req->connmon = FALSE; /*** end of httprequest init ***/ @@ -1960,10 +1972,6 @@ int main(int argc, char *argv[]) if(req.open) { logmsg("=> persistant connection request ended, awaits new request\n"); - /* - const char *keepopen="[KEEPING CONNECTION OPEN]"; - storerequest((char *)keepopen, strlen(keepopen)); - */ } /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); @@ -1973,6 +1981,11 @@ int main(int argc, char *argv[]) logmsg("====> Client disconnect"); + if(req.connmon) { + const char *keepopen="[DISCONNECT]\n"; + storerequest((char *)keepopen, strlen(keepopen)); + } + if(!req.open) /* When instructed to close connection after server-reply we wait a very small amount of time before doing so. If this -- cgit v1.2.1 From 176f7ea3bbaaf2f638f0596b47c40e782dd961c7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 Jul 2012 09:49:58 +0200 Subject: sws: support for CONNECT requests I moved out the servercmd parsing into a its own function called parse_servercmd() and made sure it gets used also when the test number is extracted from CONNECT requests. It turned out sws didn't do that previously! --- tests/server/sws.c | 200 ++++++++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 94 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 21e3bf57a..e1abed613 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -314,6 +314,105 @@ static void restore_signal_handlers(void) #endif } +/* based on the testno, parse the correct server commands */ +static int parse_servercmd(struct httprequest *req) +{ + FILE *stream; + char *filename; + int error; + + filename = test2file(req->testno); + + 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 %ld", req->testno); + req->open = FALSE; /* closes connection */ + return 1; /* done */ + } + else { + char *orgcmd = NULL; + char *cmd = NULL; + size_t cmdsize = 0; + int num=0; + + /* get the custom server control "commands" */ + error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); + fclose(stream); + if(error) { + logmsg("getpart() failed with error: %d", error); + req->open = FALSE; /* closes connection */ + return 1; /* done */ + } + + cmd = orgcmd; + while(cmd && cmdsize) { + char *check; + + if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) { + logmsg("instructed to require authorization header"); + req->auth_req = TRUE; + } + else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) { + logmsg("instructed to idle"); + req->rcmd = RCMD_IDLE; + req->open = TRUE; + } + else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) { + logmsg("instructed to stream"); + req->rcmd = RCMD_STREAM; + } + else if(!strncmp(CMD_CONNECTIONMONITOR, cmd, + strlen(CMD_CONNECTIONMONITOR))) { + logmsg("enabled connection monitoring"); + req->connmon = TRUE; + } + else if(1 == sscanf(cmd, "pipe: %d", &num)) { + logmsg("instructed to allow a pipe size of %d", num); + if(num < 0) + logmsg("negative pipe size ignored"); + else if(num > 0) + req->pipe = num-1; /* decrease by one since we don't count the + first request in this number */ + } + else if(1 == sscanf(cmd, "skip: %d", &num)) { + logmsg("instructed to skip this number of bytes %d", num); + req->skip = num; + } + else if(1 == sscanf(cmd, "writedelay: %d", &num)) { + logmsg("instructed to delay %d secs between packets", num); + req->writedelay = num; + } + else { + logmsg("Unknown instruction found: %s", cmd); + } + /* try to deal with CRLF or just LF */ + check = strchr(cmd, '\r'); + if(!check) + check = strchr(cmd, '\n'); + + if(check) { + /* get to the letter following the newline */ + while((*check == '\r') || (*check == '\n')) + check++; + + if(!*check) + /* if we reached a zero, get out */ + break; + cmd = check; + } + else + break; + } + if(orgcmd) + free(orgcmd); + } + + return 0; /* OK! */ +} + static int ProcessRequest(struct httprequest *req) { char *line=&req->reqbuf[req->checkindex]; @@ -322,9 +421,7 @@ static int ProcessRequest(struct httprequest *req) static char doc[MAXDOCNAMELEN]; char logbuf[456]; int prot_major, prot_minor; - char *end; - int error; - end = strstr(line, end_of_headers); + char *end = strstr(line, end_of_headers); req->callcount++; @@ -358,9 +455,6 @@ static int ProcessRequest(struct httprequest *req) /* get the number after it */ if(ptr) { - FILE *stream; - char *filename; - if((strlen(doc) + strlen(request)) < 400) sprintf(logbuf, "Got request: %s %s HTTP/%d.%d", request, doc, prot_major, prot_minor); @@ -400,94 +494,9 @@ static int ProcessRequest(struct httprequest *req) req->testno, req->partno); logmsg("%s", logbuf); - filename = test2file(req->testno); - - 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 %ld", req->testno); - req->open = FALSE; /* closes connection */ - return 1; /* done */ - } - else { - char *orgcmd = NULL; - char *cmd = NULL; - size_t cmdsize = 0; - int num=0; - - /* get the custom server control "commands" */ - error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); - fclose(stream); - if(error) { - logmsg("getpart() failed with error: %d", error); - req->open = FALSE; /* closes connection */ - return 1; /* done */ - } - - cmd = orgcmd; - while(cmd && cmdsize) { - char *check; + /* find and parse for this test */ + parse_servercmd(req); - if(!strncmp(CMD_AUTH_REQUIRED, cmd, strlen(CMD_AUTH_REQUIRED))) { - logmsg("instructed to require authorization header"); - req->auth_req = TRUE; - } - else if(!strncmp(CMD_IDLE, cmd, strlen(CMD_IDLE))) { - logmsg("instructed to idle"); - req->rcmd = RCMD_IDLE; - req->open = TRUE; - } - else if(!strncmp(CMD_STREAM, cmd, strlen(CMD_STREAM))) { - logmsg("instructed to stream"); - req->rcmd = RCMD_STREAM; - } - else if(!strncmp(CMD_CONNECTIONMONITOR, cmd, - strlen(CMD_CONNECTIONMONITOR))) { - logmsg("enabled connection monitoring"); - req->connmon = TRUE; - } - else if(1 == sscanf(cmd, "pipe: %d", &num)) { - logmsg("instructed to allow a pipe size of %d", num); - if(num < 0) - logmsg("negative pipe size ignored"); - else if(num > 0) - req->pipe = num-1; /* decrease by one since we don't count the - first request in this number */ - } - else if(1 == sscanf(cmd, "skip: %d", &num)) { - logmsg("instructed to skip this number of bytes %d", num); - req->skip = num; - } - else if(1 == sscanf(cmd, "writedelay: %d", &num)) { - logmsg("instructed to delay %d secs between packets", num); - req->writedelay = num; - } - else { - logmsg("funny instruction found: %s", cmd); - } - /* try to deal with CRLF or just LF */ - check = strchr(cmd, '\r'); - if(!check) - check = strchr(cmd, '\n'); - - if(check) { - /* get to the letter following the newline */ - while((*check == '\r') || (*check == '\n')) - check++; - - if(!*check) - /* if we reached a zero, get out */ - break; - cmd = check; - } - else - break; - } - if(orgcmd) - free(orgcmd); - } } else { if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", @@ -532,6 +541,9 @@ static int ProcessRequest(struct httprequest *req) 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 { logmsg("Did not find test number in PATH"); @@ -1979,7 +1991,7 @@ int main(int argc, char *argv[]) if(got_exit_signal) break; - logmsg("====> Client disconnect"); + logmsg("====> Client disconnect %d", req.connmon); if(req.connmon) { const char *keepopen="[DISCONNECT]\n"; -- cgit v1.2.1 From 685366006ccff2b4817d2b3b806e62ebdae90a60 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 11 Jul 2012 23:49:01 +0200 Subject: connection-monitor: always log disconnect when enabled This makes verifying easier and makes us more sure curl closes the connection only at the correct point in time. Adjusted test 206 and 1008 accordingly and updated the docs for it. --- tests/server/sws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index e1abed613..aaacb3546 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -347,6 +347,8 @@ static int parse_servercmd(struct httprequest *req) return 1; /* done */ } + req->connmon = FALSE; + cmd = orgcmd; while(cmd && cmdsize) { char *check; @@ -837,7 +839,6 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->pipelining = FALSE; req->callcount = 0; req->connect_port = 0; - req->connmon = FALSE; /*** end of httprequest init ***/ -- cgit v1.2.1 From d759a70db88205dd0629d6de602b9b60ede24f2d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 12 Jul 2012 00:07:16 +0200 Subject: SWS: use of uninitialized memory fix I made "connmon" not get initialized properly before use, and I use the big hammer and make sure we always clear the entire struct to avoid any problem like this in the future. --- tests/server/sws.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index aaacb3546..b4961a5ed 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1440,6 +1440,7 @@ static void http_connect(curl_socket_t *infdp, if(datafd != CURL_SOCKET_BAD) { struct httprequest req2; int err; + memset(&req2, 0, sizeof(req2)); logmsg("====> Client connect DATA"); #ifdef TCP_NODELAY /* Disable the Nagle algorithm */ @@ -1699,6 +1700,8 @@ int main(int argc, char *argv[]) bool use_fork = FALSE; #endif + memset(&req, 0, sizeof(req)); + while(argc>arg) { if(!strcmp("--version", argv[arg])) { printf("sws IPv4%s" -- cgit v1.2.1 From 76ba5919573c1f75ebae60c6e6fa5d7d6f5cf98d Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Wed, 1 Aug 2012 13:22:02 -0400 Subject: Remove the --fork option of sws, since it makes refactoring to use poll more complicated and should be redundant once we poll --- tests/server/sws.c | 44 +------------------------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index b4961a5ed..208d3377b 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -62,15 +62,6 @@ /* include memdebug.h last */ #include "memdebug.h" -#if !defined(CURL_SWS_FORK_ENABLED) && defined(HAVE_FORK) -/* - * The normal sws build for the plain standard curl test suite has no use for - * fork(), but if you feel wild and crazy and want to setup some more exotic - * tests. Define this and run... - */ -#define CURL_SWS_FORK_ENABLED -#endif - #ifdef ENABLE_IPV6 static bool use_ipv6 = FALSE; #endif @@ -1696,18 +1687,12 @@ int main(int argc, char *argv[]) int arg=1; long pid; const char *hostport = "127.0.0.1"; -#ifdef CURL_SWS_FORK_ENABLED - bool use_fork = FALSE; -#endif memset(&req, 0, sizeof(req)); while(argc>arg) { if(!strcmp("--version", argv[arg])) { printf("sws IPv4%s" -#ifdef CURL_SWS_FORK_ENABLED - " FORK" -#endif "\n" , #ifdef ENABLE_IPV6 @@ -1747,12 +1732,6 @@ int main(int argc, char *argv[]) #endif arg++; } -#ifdef CURL_SWS_FORK_ENABLED - else if(!strcmp("--fork", argv[arg])) { - use_fork=TRUE; - arg++; - } -#endif else if(!strcmp("--port", argv[arg])) { arg++; if(argc>arg) { @@ -1796,8 +1775,7 @@ int main(int argc, char *argv[]) " --port [port]\n" " --srcdir [path]\n" " --connect [ip4-addr]\n" - " --gopher\n" - " --fork"); + " --gopher"); return 0; } } @@ -1903,23 +1881,6 @@ int main(int argc, char *argv[]) set_advisor_read_lock(SERVERLOGS_LOCK); serverlogslocked = 1; -#ifdef CURL_SWS_FORK_ENABLED - if(use_fork) { - /* The fork enabled version just forks off the child and don't care - about it anymore, so don't assume otherwise. Beware and don't do - this at home. */ - rc = fork(); - if(-1 == rc) { - printf("MAJOR ERROR: fork() failed!\n"); - break; - } - } - else - /* not a fork, just set rc so the following proceeds nicely */ - rc = 0; - /* 0 is returned to the child */ - if(0 == rc) { -#endif logmsg("====> Client connect"); #ifdef TCP_NODELAY @@ -2021,9 +1982,6 @@ int main(int argc, char *argv[]) if (req.testno == DOCNUMBER_QUIT) break; -#ifdef CURL_SWS_FORK_ENABLED - } -#endif } sws_cleanup: -- cgit v1.2.1 From 81656a84669ef2fffafeb7e5db796958666538db Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Wed, 1 Aug 2012 13:30:46 -0400 Subject: Move blocks of code from the sws main loop into their own functions for easier refactoring later. The next step will be to call the correct function after a poll, rather than looping unconditionally --- tests/server/sws.c | 238 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 135 insertions(+), 103 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 208d3377b..05f7215c1 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1672,6 +1672,115 @@ http_connect_cleanup: *infdp = CURL_SOCKET_BAD; } +static int accept_connection(int sock) +{ + curl_socket_t msgsock = CURL_SOCKET_BAD; + int error; + int flag; + + msgsock = accept(sock, NULL, NULL); + + if(got_exit_signal) { + if(CURL_SOCKET_BAD != msgsock) + sclose(msgsock); + return CURL_SOCKET_BAD; + } + + if(CURL_SOCKET_BAD == msgsock) { + error = SOCKERRNO; + logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", + error, strerror(error)); + return CURL_SOCKET_BAD; + } + + /* + ** As soon as this server acepts a connection from the test harness it + ** must set the server logs advisor read lock to indicate that server + ** logs should not be read until this lock is removed by this server. + */ + + set_advisor_read_lock(SERVERLOGS_LOCK); + serverlogslocked = 1; + + logmsg("====> Client connect"); + +#ifdef TCP_NODELAY + /* + * Disable the Nagle algorithm to make it easier to send out a large + * response in many small segments to torture the clients more. + */ + flag = 1; + if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, + (void *)&flag, sizeof(flag))) + logmsg("====> TCP_NODELAY failed"); + else + logmsg("TCP_NODELAY set"); +#endif + + return msgsock; +} + +/* returns 0 if the connection should be serviced again, non-zero if it is done */ +static int service_connection(int msgsock, struct httprequest *req, + int listensock, const char *hostport) +{ + if(got_exit_signal) + return 1; + + if(get_request(msgsock, req)) + /* non-zero means error, break out of loop */ + return 1; + + if(prevbounce) { + /* bounce treatment requested */ + if((req->testno == prevtestno) && + (req->partno == prevpartno)) { + req->partno++; + logmsg("BOUNCE part number to %ld", req->partno); + } + else { + prevbounce = FALSE; + prevtestno = -1; + prevpartno = -1; + } + } + + send_doc(msgsock, 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)) { + logmsg("special request received, no persistency"); + return 1; + } + if(!req->open) { + logmsg("instructed to close connection after server-reply"); + return 1; + } + + /* if we got a CONNECT, loop and get another request as well! */ + + if(req->open) { + logmsg("=> persistant connection request ended, awaits new request\n"); + return 0; + } + + if(req->testno == DOCNUMBER_CONNECT) + return 0; + + return 1; +} + int main(int argc, char *argv[]) { srvr_sockaddr_union_t me; @@ -1861,40 +1970,9 @@ int main(int argc, char *argv[]) goto sws_cleanup; for (;;) { - msgsock = accept(sock, NULL, NULL); - - if(got_exit_signal) - break; - if (CURL_SOCKET_BAD == msgsock) { - error = SOCKERRNO; - logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", - error, strerror(error)); - break; - } - - /* - ** As soon as this server acepts a connection from the test harness it - ** must set the server logs advisor read lock to indicate that server - ** logs should not be read until this lock is removed by this server. - */ - - set_advisor_read_lock(SERVERLOGS_LOCK); - serverlogslocked = 1; - - logmsg("====> Client connect"); - -#ifdef TCP_NODELAY - /* - * Disable the Nagle algorithm to make it easier to send out a large - * response in many small segments to torture the clients more. - */ - flag = 1; - if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, - (void *)&flag, sizeof(flag))) - logmsg("====> TCP_NODELAY failed"); - else - logmsg("TCP_NODELAY set"); -#endif + msgsock = accept_connection(sock); + if (CURL_SOCKET_BAD == msgsock) + goto sws_cleanup; /* initialization of httprequest struct is done in get_request(), but due to pipelining treatment the pipelining struct field must be initialized @@ -1903,85 +1981,39 @@ int main(int argc, char *argv[]) req.pipelining = FALSE; do { + rc = service_connection(msgsock, &req, sock, hostport); if(got_exit_signal) - break; + goto sws_cleanup; - if(get_request(msgsock, &req)) - /* non-zero means error, break out of loop */ - break; + if (!rc) { + logmsg("====> Client disconnect %d", req.connmon); - if(prevbounce) { - /* bounce treatment requested */ - if((req.testno == prevtestno) && - (req.partno == prevpartno)) { - req.partno++; - logmsg("BOUNCE part number to %ld", req.partno); + if(req.connmon) { + const char *keepopen="[DISCONNECT]\n"; + storerequest((char *)keepopen, strlen(keepopen)); } - else { - prevbounce = FALSE; - prevtestno = -1; - prevpartno = -1; - } - } - send_doc(msgsock, &req); - if(got_exit_signal) - break; + if(!req.open) + /* When instructed to close connection after server-reply we + wait a very small amount of time before doing so. If this + is not done client might get an ECONNRESET before reading + a single byte of server-reply. */ + wait_ms(50); - 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"); + if(msgsock != CURL_SOCKET_BAD) { + sclose(msgsock); + msgsock = CURL_SOCKET_BAD; } - else - http_connect(&msgsock, sock, &req, hostport); - break; - } - if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { - logmsg("special request received, no persistency"); - break; - } - if(!req.open) { - logmsg("instructed to close connection after server-reply"); - break; - } + if(serverlogslocked) { + serverlogslocked = 0; + clear_advisor_read_lock(SERVERLOGS_LOCK); + } - if(req.open) { - logmsg("=> persistant connection request ended, awaits new request\n"); + if (req.testno == DOCNUMBER_QUIT) + goto sws_cleanup; } - /* if we got a CONNECT, loop and get another request as well! */ - } while(req.open || (req.testno == DOCNUMBER_CONNECT)); - - if(got_exit_signal) - break; - - logmsg("====> Client disconnect %d", req.connmon); - - if(req.connmon) { - const char *keepopen="[DISCONNECT]\n"; - storerequest((char *)keepopen, strlen(keepopen)); - } - - if(!req.open) - /* When instructed to close connection after server-reply we - wait a very small amount of time before doing so. If this - is not done client might get an ECONNRESET before reading - a single byte of server-reply. */ - wait_ms(50); - - if(msgsock != CURL_SOCKET_BAD) { - sclose(msgsock); - msgsock = CURL_SOCKET_BAD; - } - - if(serverlogslocked) { - serverlogslocked = 0; - clear_advisor_read_lock(SERVERLOGS_LOCK); - } - - if (req.testno == DOCNUMBER_QUIT) - break; + } while (rc); } sws_cleanup: -- cgit v1.2.1 From 19035292d0982bd8b5f0464302d7d1c5a33e8e02 Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Wed, 1 Aug 2012 17:09:38 -0400 Subject: Hoist the loop out of get_request, and make sure that it can be reentered when a request is half-finished. Note the the req struct used to be re-initialized AFTER reading pipeline data, so now that we initialize it from the caller we must be careful not to overwrite the pipeline data. Also we now need to handle the case where the buffer is already full when get_request is called - previously this never happened as it was always called with an empty buffer and looped until done. Now get_request is called in a loop, so the next step is to run the loop on a socket only when poll signals it is readable. --- tests/server/sws.c | 95 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 35 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 05f7215c1..a5a0b6334 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -110,6 +110,7 @@ struct httprequest { 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; }; static int ProcessRequest(struct httprequest *req); @@ -793,27 +794,15 @@ storerequest_cleanup: dumpfile, error, strerror(error)); } -/* return 0 on success, non-zero on failure */ -static int get_request(curl_socket_t sock, struct httprequest *req) +static void init_httprequest(struct httprequest *req) { - int error; - int fail = 0; - int done_processing = 0; - char *reqbuf = req->reqbuf; - ssize_t got = 0; - - char *pipereq = NULL; - size_t pipereq_length = 0; - - if(req->pipelining) { - pipereq = reqbuf + req->checkindex; - pipereq_length = req->offset - req->checkindex; + /* Pipelining is already set, so do not initialize it here. Only initialize + checkindex and offset if pipelining is not set, since in a pipeline they + need to be inherited from the previous request. */ + if(!req->pipelining) { + req->checkindex = 0; + req->offset = 0; } - - /*** Init the httprequest structure properly for the upcoming request ***/ - - req->checkindex = 0; - req->offset = 0; req->testno = DOCNUMBER_NOTHING; req->partno = 0; req->open = TRUE; @@ -827,13 +816,39 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->writedelay = 0; req->rcmd = RCMD_NORMALREQ; req->prot_version = 0; - req->pipelining = FALSE; req->callcount = 0; req->connect_port = 0; + req->done_processing = 0; +} + +/* return 0 on success, non-zero on failure */ +static int get_request(curl_socket_t sock, struct httprequest *req) +{ + int error; + int fail = 0; + char *reqbuf = req->reqbuf; + ssize_t got = 0; + int overflow = 0; + + char *pipereq = NULL; + size_t pipereq_length = 0; + + if(req->pipelining) { + pipereq = reqbuf + req->checkindex; + pipereq_length = req->offset - req->checkindex; - /*** end of httprequest init ***/ + /* Now that we've got the pipelining info we can reset the + pipelining-related vars which were skipped in init_httprequest */ + req->pipelining = FALSE; + req->checkindex = 0; + req->offset = 0; + } - while(!done_processing && (req->offset < REQBUFSIZ-1)) { + if(req->offset >= REQBUFSIZ-1) { + /* buffer is already full; do nothing */ + overflow = 1; + } + else { if(pipereq_length && pipereq) { memmove(reqbuf, pipereq, pipereq_length); got = curlx_uztosz(pipereq_length); @@ -871,17 +886,17 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->offset += (size_t)got; reqbuf[req->offset] = '\0'; - done_processing = ProcessRequest(req); + req->done_processing = ProcessRequest(req); if(got_exit_signal) return 1; - if(done_processing && req->pipe) { + if(req->done_processing && req->pipe) { logmsg("Waiting for another piped request"); - done_processing = 0; + req->done_processing = 0; req->pipe--; } } - if((req->offset == REQBUFSIZ-1) && (got > 0)) { + if(overflow || (req->offset == REQBUFSIZ-1 && got > 0)) { logmsg("Request would overflow buffer, closing connection"); /* dump request received so far to external file anyway */ reqbuf[REQBUFSIZ-1] = '\0'; @@ -896,8 +911,9 @@ static int get_request(curl_socket_t sock, struct httprequest *req) else reqbuf[req->offset] = '\0'; - /* dump the request to an external file */ - storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); + /* at the end of a request dump it to an external file */ + if (fail || req->done_processing) + storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); if(got_exit_signal) return 1; @@ -1443,7 +1459,12 @@ static void http_connect(curl_socket_t *infdp, logmsg("TCP_NODELAY set for client DATA conection"); #endif req2.pipelining = FALSE; - err = get_request(datafd, &req2); + init_httprequest(&req2); + while(!req2.done_processing) { + err = get_request(datafd, &req2); + if(err) + break; + } if(!err) { err = send_doc(datafd, &req2); if(!err && (req2.testno == DOCNUMBER_CONNECT)) { @@ -1727,9 +1748,13 @@ static int service_connection(int msgsock, struct httprequest *req, if(got_exit_signal) return 1; - if(get_request(msgsock, req)) - /* non-zero means error, break out of loop */ - return 1; + init_httprequest(req); + while(!req->done_processing) { + if (get_request(msgsock, req)) { + /* non-zero means error, break out of loop */ + return 1; + } + } if(prevbounce) { /* bounce treatment requested */ @@ -1974,9 +1999,9 @@ int main(int argc, char *argv[]) if (CURL_SOCKET_BAD == msgsock) goto sws_cleanup; - /* initialization of httprequest struct is done in get_request(), but due - to pipelining treatment the pipelining struct field must be initialized - previously to FALSE every time a new connection arrives. */ + /* initialization of httprequest struct is done before get_request(), but + the pipelining struct field must be initialized previously to FALSE + every time a new connection arrives. */ req.pipelining = FALSE; -- cgit v1.2.1 From 84490052d45bb55dd12e82b1874d7bbb2897c0d1 Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Thu, 2 Aug 2012 17:11:05 -0400 Subject: Change return values of get_request, accept_connection and service_connection to add a return code for non-blocking sockets: now -1 means error or connection finished, 1 means data was read, and 0 means there is no data available now so need to wait for poll (new return value) --- tests/server/sws.c | 69 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 25 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index a5a0b6334..d60a52a54 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -821,7 +821,8 @@ static void init_httprequest(struct httprequest *req) req->done_processing = 0; } -/* return 0 on success, non-zero on failure */ +/* 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 get_request(curl_socket_t sock, struct httprequest *req) { int error; @@ -864,13 +865,17 @@ static int get_request(curl_socket_t sock, struct httprequest *req) got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset); } if(got_exit_signal) - return 1; + return -1; if(got == 0) { logmsg("Connection closed by client"); fail = 1; } else if(got < 0) { error = SOCKERRNO; + if (EAGAIN == error || EWOULDBLOCK == error) { + /* nothing to read at the moment */ + return 0; + } logmsg("recv() returned error: (%d) %s", error, strerror(error)); fail = 1; } @@ -878,7 +883,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) /* dump the request received so far to the external file */ reqbuf[req->offset] = '\0'; storerequest(reqbuf, req->offset); - return 1; + return -1; } logmsg("Read %zd bytes", got); @@ -888,7 +893,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req) req->done_processing = ProcessRequest(req); if(got_exit_signal) - return 1; + return -1; if(req->done_processing && req->pipe) { logmsg("Waiting for another piped request"); req->done_processing = 0; @@ -915,9 +920,9 @@ static int get_request(curl_socket_t sock, struct httprequest *req) if (fail || req->done_processing) storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); if(got_exit_signal) - return 1; + return -1; - return fail; /* return 0 on success */ + return fail ? -1 : 1; } /* returns -1 on failure */ @@ -1462,10 +1467,14 @@ static void http_connect(curl_socket_t *infdp, init_httprequest(&req2); while(!req2.done_processing) { err = get_request(datafd, &req2); - if(err) + if(err < 0) { + /* this socket must be closed, done or not */ break; + } } - if(!err) { + + /* skip this and close the socket if err < 0 */ + if(err >= 0) { err = send_doc(datafd, &req2); if(!err && (req2.testno == DOCNUMBER_CONNECT)) { /* sleep to prevent triggering libcurl known bug #39. */ @@ -1693,6 +1702,8 @@ http_connect_cleanup: *infdp = CURL_SOCKET_BAD; } +/* returns a socket handle, or 0 if there are no more waiting sockets, + or < 0 if there was an error */ static int accept_connection(int sock) { curl_socket_t msgsock = CURL_SOCKET_BAD; @@ -1709,6 +1720,10 @@ static int accept_connection(int sock) if(CURL_SOCKET_BAD == msgsock) { error = SOCKERRNO; + if(EAGAIN == error || EWOULDBLOCK == error) { + /* nothing to accept */ + return 0; + } logmsg("MAJOR ERROR: accept() failed with error: (%d) %s", error, strerror(error)); return CURL_SOCKET_BAD; @@ -1741,18 +1756,20 @@ static int accept_connection(int sock) return msgsock; } -/* returns 0 if the connection should be serviced again, non-zero if it is done */ +/* 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(int msgsock, struct httprequest *req, int listensock, const char *hostport) { if(got_exit_signal) - return 1; + return -1; init_httprequest(req); while(!req->done_processing) { - if (get_request(msgsock, req)) { - /* non-zero means error, break out of loop */ - return 1; + int rc = get_request(msgsock, req); + if (rc <= 0) { + /* Nothing further to read now (possibly because the socket was closed */ + return rc; } } @@ -1772,7 +1789,7 @@ static int service_connection(int msgsock, struct httprequest *req, send_doc(msgsock, req); if(got_exit_signal) - return 1; + return -1; if(DOCNUMBER_CONNECT == req->testno) { /* a CONNECT request, setup and talk the tunnel */ @@ -1781,29 +1798,29 @@ static int service_connection(int msgsock, struct httprequest *req, } else http_connect(&msgsock, listensock, req, hostport); - return 1; + return -1; } if((req->testno < 0) && (req->testno != DOCNUMBER_CONNECT)) { logmsg("special request received, no persistency"); - return 1; + return -1; } if(!req->open) { logmsg("instructed to close connection after server-reply"); - return 1; + return -1; } /* if we got a CONNECT, loop and get another request as well! */ if(req->open) { logmsg("=> persistant connection request ended, awaits new request\n"); - return 0; + return 1; } if(req->testno == DOCNUMBER_CONNECT) - return 0; + return 1; - return 1; + return -1; } int main(int argc, char *argv[]) @@ -1995,9 +2012,11 @@ int main(int argc, char *argv[]) goto sws_cleanup; for (;;) { - msgsock = accept_connection(sock); - if (CURL_SOCKET_BAD == msgsock) - goto sws_cleanup; + do { + msgsock = accept_connection(sock); + if (CURL_SOCKET_BAD == msgsock) + goto sws_cleanup; + } while (msgsock >= 0); /* initialization of httprequest struct is done before get_request(), but the pipelining struct field must be initialized previously to FALSE @@ -2010,7 +2029,7 @@ int main(int argc, char *argv[]) if(got_exit_signal) goto sws_cleanup; - if (!rc) { + if (rc < 0) { logmsg("====> Client disconnect %d", req.connmon); if(req.connmon) { @@ -2038,7 +2057,7 @@ int main(int argc, char *argv[]) if (req.testno == DOCNUMBER_QUIT) goto sws_cleanup; } - } while (rc); + } while (rc > = 0); } sws_cleanup: -- cgit v1.2.1 From 674da8ae07e3780b393bd1aebb7b7f973433c29f Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Thu, 2 Aug 2012 17:22:46 -0400 Subject: Add a polling loop in main to read from more than one socket at once. Add the O_NONBLOCK and SO_KEEPALIVE flag to all sockets. Note that several loops which used to continue on a return value of 0 (theoretical since 0 would never be returned without O_NONBLOCK) now break on 0 so that they won't continue reading until after poll is called again. --- tests/server/sws.c | 193 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 147 insertions(+), 46 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index d60a52a54..fc0d0ddf3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -50,6 +50,9 @@ #include /* for TCP_NODELAY */ #endif +#include +#include + #define ENABLE_CURLX_PRINTF /* make the curlx header define all printf() functions to use the curlx_* versions instead */ @@ -113,6 +116,11 @@ struct httprequest { int done_processing; }; +#define MAX_SOCKETS 1024 + +static struct pollfd all_sockets[MAX_SOCKETS]; +static nfds_t num_sockets = 0; + static int ProcessRequest(struct httprequest *req); static void storerequest(char *reqbuf, size_t totalsize); @@ -1708,7 +1716,12 @@ static int accept_connection(int sock) { curl_socket_t msgsock = CURL_SOCKET_BAD; int error; - int flag; + int flag = 1; + + if(MAX_SOCKETS == num_sockets) { + logmsg("Too many open sockets!"); + return CURL_SOCKET_BAD; + } msgsock = accept(sock, NULL, NULL); @@ -1729,23 +1742,45 @@ static int accept_connection(int sock) return CURL_SOCKET_BAD; } + if(0 != fcntl(msgsock, F_SETFL, O_NONBLOCK)) { + error = SOCKERRNO; + logmsg("fcntl(O_NONBLOCK) failed with error: (%d) %s", + error, strerror(error)); + sclose(msgsock); + return CURL_SOCKET_BAD; + } + + if(0 != setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, + (void *)&flag, sizeof(flag))) { + error = SOCKERRNO; + logmsg("setsockopt(SO_KEEPALIVE) failed with error: (%d) %s", + error, strerror(error)); + sclose(msgsock); + return CURL_SOCKET_BAD; + } + /* - ** As soon as this server acepts a connection from the test harness it + ** As soon as this server accepts a connection from the test harness it ** must set the server logs advisor read lock to indicate that server ** logs should not be read until this lock is removed by this server. */ - set_advisor_read_lock(SERVERLOGS_LOCK); - serverlogslocked = 1; + if(!serverlogslocked) + set_advisor_read_lock(SERVERLOGS_LOCK); + serverlogslocked += 1; logmsg("====> Client connect"); + all_sockets[num_sockets].fd = msgsock; + all_sockets[num_sockets].events = POLLIN; + all_sockets[num_sockets].revents = 0; + num_sockets += 1; + #ifdef TCP_NODELAY /* * Disable the Nagle algorithm to make it easier to send out a large * response in many small segments to torture the clients more. */ - flag = 1; if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, (void *)&flag, sizeof(flag))) logmsg("====> TCP_NODELAY failed"); @@ -1764,9 +1799,9 @@ static int service_connection(int msgsock, struct httprequest *req, if(got_exit_signal) return -1; - init_httprequest(req); while(!req->done_processing) { int rc = get_request(msgsock, req); + logmsg("get_request %d returned %d", msgsock, rc); if (rc <= 0) { /* Nothing further to read now (possibly because the socket was closed */ return rc; @@ -1827,7 +1862,6 @@ int main(int argc, char *argv[]) { srvr_sockaddr_union_t me; curl_socket_t sock = CURL_SOCKET_BAD; - curl_socket_t msgsock = CURL_SOCKET_BAD; int wrotepidfile = 0; int flag; unsigned short port = DEFAULT_PORT; @@ -1838,6 +1872,7 @@ int main(int argc, char *argv[]) int arg=1; long pid; const char *hostport = "127.0.0.1"; + nfds_t socket_idx; memset(&req, 0, sizeof(req)); @@ -1949,6 +1984,11 @@ int main(int argc, char *argv[]) sock = socket(AF_INET6, SOCK_STREAM, 0); #endif + all_sockets[0].fd = sock; + all_sockets[0].events = POLLIN; + all_sockets[0].revents = 0; + num_sockets = 1; + if(CURL_SOCKET_BAD == sock) { error = SOCKERRNO; logmsg("Error creating socket: (%d) %s", @@ -1964,6 +2004,12 @@ int main(int argc, char *argv[]) error, strerror(error)); goto sws_cleanup; } + if(0 != fcntl(sock, F_SETFL, O_NONBLOCK)) { + error = SOCKERRNO; + logmsg("fcntl(O_NONBLOCK) failed with error: (%d) %s", + error, strerror(error)); + goto sws_cleanup; + } #ifdef ENABLE_IPV6 if(!use_ipv6) { @@ -2011,59 +2057,114 @@ int main(int argc, char *argv[]) if(!wrotepidfile) goto sws_cleanup; - for (;;) { - do { - msgsock = accept_connection(sock); - if (CURL_SOCKET_BAD == msgsock) - goto sws_cleanup; - } while (msgsock >= 0); + /* initialization of httprequest struct is done before get_request(), but + the pipelining struct field must be initialized previously to FALSE + every time a new connection arrives. */ + + req.pipelining = FALSE; + init_httprequest(&req); + + for(;;) { + /* Clear out closed sockets */ + for (socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) { + if (CURL_SOCKET_BAD == all_sockets[socket_idx].fd) { + char* dst = (char *) all_sockets + socket_idx; + char* src = (char *) all_sockets + socket_idx + 1; + char* end = (char *) all_sockets + num_sockets; + memmove(dst, src, end - src); + num_sockets -= 1; + } + } - /* initialization of httprequest struct is done before get_request(), but - the pipelining struct field must be initialized previously to FALSE - every time a new connection arrives. */ + rc = poll(all_sockets, num_sockets, -1); - req.pipelining = FALSE; + if (rc < 0) { + error = SOCKERRNO; + logmsg("poll() failed with error: (%d) %s", + error, strerror(error)); + goto sws_cleanup; + } - do { - rc = service_connection(msgsock, &req, sock, hostport); - if(got_exit_signal) - goto sws_cleanup; + /* Check if the listening socket is ready to accept */ + if ((all_sockets[0].revents & POLLIN) == POLLIN) { + /* Service all queued connections */ + curl_socket_t msgsock; + do { + msgsock = accept_connection(sock); + logmsg("accept_connection %d returned %d", sock, msgsock); + if (CURL_SOCKET_BAD == msgsock) + goto sws_cleanup; + } while (msgsock > 0); + } + else if (all_sockets[0].revents != 0) { + logmsg("unexpected poll event on listening socket: %d", + all_sockets[0].revents); + goto sws_cleanup; + } - if (rc < 0) { - logmsg("====> Client disconnect %d", req.connmon); + /* Service all connections that are ready */ + for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) { + if ((all_sockets[socket_idx].revents & POLLIN) == POLLIN) { + if(got_exit_signal) + goto sws_cleanup; - if(req.connmon) { - const char *keepopen="[DISCONNECT]\n"; - storerequest((char *)keepopen, strlen(keepopen)); - } + /* Service this connection until it has nothing available */ + do { + rc = service_connection(all_sockets[socket_idx].fd, &req, sock, hostport); + logmsg("service_connection %d returned %d", all_sockets[socket_idx].fd, rc); + if(got_exit_signal) + goto sws_cleanup; - if(!req.open) - /* When instructed to close connection after server-reply we - wait a very small amount of time before doing so. If this - is not done client might get an ECONNRESET before reading - a single byte of server-reply. */ - wait_ms(50); + if (rc < 0) { + logmsg("====> Client disconnect %d", req.connmon); - if(msgsock != CURL_SOCKET_BAD) { - sclose(msgsock); - msgsock = CURL_SOCKET_BAD; - } + if(req.connmon) { + const char *keepopen="[DISCONNECT]\n"; + storerequest((char *)keepopen, strlen(keepopen)); + } - if(serverlogslocked) { - serverlogslocked = 0; - clear_advisor_read_lock(SERVERLOGS_LOCK); - } + if(!req.open) + /* When instructed to close connection after server-reply we + wait a very small amount of time before doing so. If this + is not done client might get an ECONNRESET before reading + a single byte of server-reply. */ + wait_ms(50); - if (req.testno == DOCNUMBER_QUIT) - goto sws_cleanup; + if(all_sockets[socket_idx].fd != CURL_SOCKET_BAD) { + sclose(all_sockets[socket_idx].fd); + all_sockets[socket_idx].fd = CURL_SOCKET_BAD; + } + + serverlogslocked -= 1; + if(!serverlogslocked) + clear_advisor_read_lock(SERVERLOGS_LOCK); + + if (req.testno == DOCNUMBER_QUIT) + goto sws_cleanup; + } + + /* Reset the request, unless we're still in the middle of reading */ + if (rc != 0) + init_httprequest(&req); + } while (rc > 0); + } + else if (all_sockets[socket_idx].revents != 0) { + logmsg("unexpected poll event on socket %d: %d", + socket_idx, all_sockets[socket_idx].revents); + goto sws_cleanup; } - } while (rc > = 0); + } + + if(got_exit_signal) + goto sws_cleanup; } sws_cleanup: - if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD)) - sclose(msgsock); + for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) + if((all_sockets[socket_idx].fd != sock) && + (all_sockets[socket_idx].fd != CURL_SOCKET_BAD)) + sclose(all_sockets[socket_idx].fd); if(sock != CURL_SOCKET_BAD) sclose(sock); -- cgit v1.2.1 From 66a77a9b4904deafc308f152842329eccf9b2ad4 Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Mon, 6 Aug 2012 12:36:08 -0400 Subject: Use cross-platform curlx_nonblock instead of fcntl in sws --- tests/server/sws.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index fc0d0ddf3..f01e75744 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -50,7 +50,6 @@ #include /* for TCP_NODELAY */ #endif -#include #include #define ENABLE_CURLX_PRINTF @@ -1742,9 +1741,9 @@ static int accept_connection(int sock) return CURL_SOCKET_BAD; } - if(0 != fcntl(msgsock, F_SETFL, O_NONBLOCK)) { + if(0 != curlx_nonblock(msgsock, TRUE)) { error = SOCKERRNO; - logmsg("fcntl(O_NONBLOCK) failed with error: (%d) %s", + logmsg("curlx_nonblock failed with error: (%d) %s", error, strerror(error)); sclose(msgsock); return CURL_SOCKET_BAD; @@ -2004,9 +2003,9 @@ int main(int argc, char *argv[]) error, strerror(error)); goto sws_cleanup; } - if(0 != fcntl(sock, F_SETFL, O_NONBLOCK)) { + if(0 != curlx_nonblock(sock, TRUE)) { error = SOCKERRNO; - logmsg("fcntl(O_NONBLOCK) failed with error: (%d) %s", + logmsg("curlx_nonblock failed with error: (%d) %s", error, strerror(error)); goto sws_cleanup; } -- cgit v1.2.1 From 60a2ee88a5680b3f0f18adfc996f9ed83017bf38 Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Mon, 6 Aug 2012 13:01:46 -0400 Subject: Use select in sws, which has better cross-platform support than poll --- tests/server/sws.c | 81 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 34 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index f01e75744..47e18d834 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -50,8 +50,6 @@ #include /* for TCP_NODELAY */ #endif -#include - #define ENABLE_CURLX_PRINTF /* make the curlx header define all printf() functions to use the curlx_* versions instead */ @@ -117,8 +115,8 @@ struct httprequest { #define MAX_SOCKETS 1024 -static struct pollfd all_sockets[MAX_SOCKETS]; -static nfds_t num_sockets = 0; +static curl_socket_t all_sockets[MAX_SOCKETS]; +static size_t num_sockets = 0; static int ProcessRequest(struct httprequest *req); static void storerequest(char *reqbuf, size_t totalsize); @@ -1770,9 +1768,7 @@ static int accept_connection(int sock) logmsg("====> Client connect"); - all_sockets[num_sockets].fd = msgsock; - all_sockets[num_sockets].events = POLLIN; - all_sockets[num_sockets].revents = 0; + all_sockets[num_sockets] = msgsock; num_sockets += 1; #ifdef TCP_NODELAY @@ -1871,7 +1867,7 @@ int main(int argc, char *argv[]) int arg=1; long pid; const char *hostport = "127.0.0.1"; - nfds_t socket_idx; + size_t socket_idx; memset(&req, 0, sizeof(req)); @@ -1983,9 +1979,7 @@ int main(int argc, char *argv[]) sock = socket(AF_INET6, SOCK_STREAM, 0); #endif - all_sockets[0].fd = sock; - all_sockets[0].events = POLLIN; - all_sockets[0].revents = 0; + all_sockets[0] = sock; num_sockets = 1; if(CURL_SOCKET_BAD == sock) { @@ -2064,9 +2058,14 @@ int main(int argc, char *argv[]) init_httprequest(&req); for(;;) { + fd_set input; + fd_set output; + struct timeval timeout = {0, 250000L}; /* 250 ms */ + curl_socket_t maxfd = (curl_socket_t)-1; + /* Clear out closed sockets */ for (socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) { - if (CURL_SOCKET_BAD == all_sockets[socket_idx].fd) { + if (CURL_SOCKET_BAD == all_sockets[socket_idx]) { char* dst = (char *) all_sockets + socket_idx; char* src = (char *) all_sockets + socket_idx + 1; char* end = (char *) all_sockets + num_sockets; @@ -2075,17 +2074,41 @@ int main(int argc, char *argv[]) } } - rc = poll(all_sockets, num_sockets, -1); + if(got_exit_signal) + goto sws_cleanup; + + /* Set up for select*/ + FD_ZERO(&input); + FD_ZERO(&output); + + for (socket_idx = 0; socket_idx < num_sockets; ++socket_idx) { + /* Listen on all sockets */ + FD_SET(all_sockets[socket_idx], &input); + if(all_sockets[socket_idx] > maxfd) + maxfd = all_sockets[socket_idx]; + } + if(got_exit_signal) + goto sws_cleanup; + + rc = select((int)maxfd + 1, &input, &output, NULL, &timeout); if (rc < 0) { error = SOCKERRNO; - logmsg("poll() failed with error: (%d) %s", + logmsg("select() failed with error: (%d) %s", error, strerror(error)); goto sws_cleanup; } + if(got_exit_signal) + goto sws_cleanup; + + if (rc == 0) { + /* Timed out - try again*/ + continue; + } + /* Check if the listening socket is ready to accept */ - if ((all_sockets[0].revents & POLLIN) == POLLIN) { + if (FD_ISSET(all_sockets[0], &input)) { /* Service all queued connections */ curl_socket_t msgsock; do { @@ -2095,22 +2118,17 @@ int main(int argc, char *argv[]) goto sws_cleanup; } while (msgsock > 0); } - else if (all_sockets[0].revents != 0) { - logmsg("unexpected poll event on listening socket: %d", - all_sockets[0].revents); - goto sws_cleanup; - } /* Service all connections that are ready */ for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) { - if ((all_sockets[socket_idx].revents & POLLIN) == POLLIN) { + if (FD_ISSET(all_sockets[socket_idx], &input)) { if(got_exit_signal) goto sws_cleanup; /* Service this connection until it has nothing available */ do { - rc = service_connection(all_sockets[socket_idx].fd, &req, sock, hostport); - logmsg("service_connection %d returned %d", all_sockets[socket_idx].fd, rc); + rc = service_connection(all_sockets[socket_idx], &req, sock, hostport); + logmsg("service_connection %d returned %d", all_sockets[socket_idx], rc); if(got_exit_signal) goto sws_cleanup; @@ -2129,9 +2147,9 @@ int main(int argc, char *argv[]) a single byte of server-reply. */ wait_ms(50); - if(all_sockets[socket_idx].fd != CURL_SOCKET_BAD) { - sclose(all_sockets[socket_idx].fd); - all_sockets[socket_idx].fd = CURL_SOCKET_BAD; + if(all_sockets[socket_idx] != CURL_SOCKET_BAD) { + sclose(all_sockets[socket_idx]); + all_sockets[socket_idx] = CURL_SOCKET_BAD; } serverlogslocked -= 1; @@ -2147,11 +2165,6 @@ int main(int argc, char *argv[]) init_httprequest(&req); } while (rc > 0); } - else if (all_sockets[socket_idx].revents != 0) { - logmsg("unexpected poll event on socket %d: %d", - socket_idx, all_sockets[socket_idx].revents); - goto sws_cleanup; - } } if(got_exit_signal) @@ -2161,9 +2174,9 @@ int main(int argc, char *argv[]) sws_cleanup: for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) - if((all_sockets[socket_idx].fd != sock) && - (all_sockets[socket_idx].fd != CURL_SOCKET_BAD)) - sclose(all_sockets[socket_idx].fd); + if((all_sockets[socket_idx] != sock) && + (all_sockets[socket_idx] != CURL_SOCKET_BAD)) + sclose(all_sockets[socket_idx]); if(sock != CURL_SOCKET_BAD) sclose(sock); -- cgit v1.2.1 From 0df14c83932b2022c3f424985d8e1fe51f7fb8f5 Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Mon, 6 Aug 2012 13:43:52 -0400 Subject: Remove debug logs that were accidentally checked in --- tests/server/sws.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 47e18d834..bff4a8771 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1796,7 +1796,6 @@ static int service_connection(int msgsock, struct httprequest *req, while(!req->done_processing) { int rc = get_request(msgsock, req); - logmsg("get_request %d returned %d", msgsock, rc); if (rc <= 0) { /* Nothing further to read now (possibly because the socket was closed */ return rc; @@ -2128,7 +2127,6 @@ 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); - logmsg("service_connection %d returned %d", all_sockets[socket_idx], rc); if(got_exit_signal) goto sws_cleanup; -- cgit v1.2.1 From 42e4c34ff37c259ff26e78aab22c0bccf06d1bcb Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Mon, 6 Aug 2012 13:44:38 -0400 Subject: sws: close sockets properly Fix a bug where closed sockets (fd -1) were left in the all_sockets list, because of missing parens in a pointer arithmetic expression Reenable the tests that were locking up due to this bug. --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index bff4a8771..151e0647f 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -2065,9 +2065,9 @@ int main(int argc, char *argv[]) /* Clear out closed sockets */ for (socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) { if (CURL_SOCKET_BAD == all_sockets[socket_idx]) { - char* dst = (char *) all_sockets + socket_idx; - char* src = (char *) all_sockets + socket_idx + 1; - char* end = (char *) all_sockets + num_sockets; + char* dst = (char *) (all_sockets + socket_idx); + char* src = (char *) (all_sockets + socket_idx + 1); + char* end = (char *) (all_sockets + num_sockets); memmove(dst, src, end - src); num_sockets -= 1; } -- cgit v1.2.1 From 154fc29f589f1b5b1503a14c2afe591f7c9edb71 Mon Sep 17 00:00:00 2001 From: Guenter Knauf Date: Wed, 8 Aug 2012 05:03:16 +0200 Subject: Fix some compiler warnings. --- tests/server/sws.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index 151e0647f..af867bdb3 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1709,7 +1709,7 @@ http_connect_cleanup: /* returns a socket handle, or 0 if there are no more waiting sockets, or < 0 if there was an error */ -static int accept_connection(int sock) +static curl_socket_t accept_connection(curl_socket_t sock) { curl_socket_t msgsock = CURL_SOCKET_BAD; int error; @@ -1788,8 +1788,8 @@ static int accept_connection(int 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(int msgsock, struct httprequest *req, - int listensock, const char *hostport) +static int service_connection(curl_socket_t msgsock, struct httprequest *req, + curl_socket_t listensock, const char *hostport) { if(got_exit_signal) return -1; -- cgit v1.2.1 From 6372144be0aef3bb8aac5561941d986e1129f5ee Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Tue, 11 Sep 2012 11:48:27 +0200 Subject: sws.c: Fixed warning: 'err' may be used uninitialized in this function --- tests/server/sws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/server/sws.c') diff --git a/tests/server/sws.c b/tests/server/sws.c index af867bdb3..291027481 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1456,7 +1456,7 @@ static void http_connect(curl_socket_t *infdp, curl_socket_t datafd = accept(rootfd, NULL, NULL); if(datafd != CURL_SOCKET_BAD) { struct httprequest req2; - int err; + int err = 0; memset(&req2, 0, sizeof(req2)); logmsg("====> Client connect DATA"); #ifdef TCP_NODELAY -- cgit v1.2.1