struct httprequest {
char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */
+ bool connect_request; /* if a CONNECT */
+ unsigned short connect_port; /* the port number CONNECT used */
size_t checkindex; /* where to start checking of the request */
size_t offset; /* size of the incoming request */
long testno; /* test number found in the request */
int prot_version; /* HTTP version * 10 */
bool pipelining; /* true if request is pipelined */
int callcount; /* times ProcessRequest() gets called */
- unsigned short connect_port; /* the port number CONNECT used */
bool connmon; /* monitor the state of the connection, log disconnects */
int done_processing;
};
#define END_OF_HEADERS "\r\n\r\n"
enum {
- DOCNUMBER_NOTHING = -7,
- DOCNUMBER_QUIT = -6,
- DOCNUMBER_BADCONNECT = -5,
- DOCNUMBER_INTERNAL= -4,
- DOCNUMBER_CONNECT = -3,
+ DOCNUMBER_NOTHING = -4,
+ DOCNUMBER_QUIT = -3,
DOCNUMBER_WERULEZ = -2,
DOCNUMBER_404 = -1
};
static const char *docquit =
"HTTP/1.1 200 Goodbye" END_OF_HEADERS;
-/* sent as reply to a CONNECT */
-static const char *docconnect =
-"HTTP/1.1 200 Mighty fine indeed" END_OF_HEADERS;
-
-/* sent as reply to a "bad" CONNECT */
-static const char *docbadconnect =
-"HTTP/1.1 501 Forbidden you fool" END_OF_HEADERS;
-
/* send back this on 404 file not found */
static const char *doc404 = "HTTP/1.1 404 Not Found\r\n"
"Server: " SWSVERSION "\r\n"
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", filename);
- logmsg("Couldn't open test file %ld", req->testno);
+ logmsg(" [1] Error opening file: %s", filename);
+ logmsg(" Couldn't open test file %ld", req->testno);
req->open = FALSE; /* closes connection */
return 1; /* done */
}
else
req->partno = 0;
- sprintf(logbuf, "Requested test number %ld part %ld",
- req->testno, req->partno);
- logmsg("%s", logbuf);
+ if(req->testno) {
+
+ sprintf(logbuf, "Requested test number %ld part %ld",
+ req->testno, req->partno);
+ logmsg("%s", logbuf);
- /* find and parse <servercmd> for this test */
- parse_servercmd(req);
+ /* find and parse <servercmd> for this test */
+ parse_servercmd(req);
+ }
+ else
+ req->testno = DOCNUMBER_NOTHING;
}
- else {
+
+ if(req->testno == DOCNUMBER_NOTHING) {
+ /* didn't find any in the first scan, try alternative test case
+ number placements */
+
if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
doc, &prot_major, &prot_minor) == 3) {
char *portp = NULL;
+ unsigned long part=0;
sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request",
doc, prot_major, prot_minor);
logmsg("%s", logbuf);
+ req->connect_request = TRUE;
+
if(req->prot_version == 10)
req->open = FALSE; /* HTTP 1.0 closes connection by default */
if(doc[0] == '[') {
char *p = &doc[1];
- while(*p && (ISXDIGIT(*p) || (*p == ':') || (*p == '.')))
- p++;
+ /* scan through the hexgroups and store the value of the last group
+ in the 'part' variable and use as test case number!! */
+ while(*p && (ISXDIGIT(*p) || (*p == ':') || (*p == '.'))) {
+ char *endp;
+ part = strtoul(p, &endp, 16);
+ if(ISXDIGIT(*p))
+ p = endp;
+ else
+ p++;
+ }
if(*p != ']')
logmsg("Invalid CONNECT IPv6 address format");
else if (*(p+1) != ':')
logmsg("Invalid CONNECT IPv6 port format");
else
portp = p+1;
+
+ req->testno = part;
}
else
portp = strchr(doc, ':');
logmsg("Invalid CONNECT port received");
else
req->connect_port = curlx_ultous(ulnum);
+
}
+ logmsg("Port number: %d, test case number: %ld",
+ req->connect_port, req->testno);
+ }
+ }
+
+ if(req->testno == DOCNUMBER_NOTHING) {
+ /* Still no test case number. Try to get the the number off the last dot
+ instead, IE we consider the TLD to be the test number. Test 123 can
+ then be written as "example.com.123". */
+
+ /* find the last dot */
+ ptr = strrchr(doc, '.');
+
+ /* get the number after it */
+ if(ptr) {
+ ptr++; /* skip the dot */
- if(!strncmp(doc, "bad", 3))
- /* if the host name starts with bad, we fake an error here */
- req->testno = DOCNUMBER_BADCONNECT;
- else if(!strncmp(doc, "test", 4))
- /* if the host name starts with test, the port number used in the
- CONNECT line will be used as test number! */
- req->testno = req->connect_port?req->connect_port:DOCNUMBER_CONNECT;
+ req->testno = strtol(ptr, &ptr, 10);
+
+ if(req->testno > 10000) {
+ req->partno = req->testno % 10000;
+ req->testno /= 10000;
+
+ logmsg("found test %d in requested host name", req->testno);
+
+ }
else
- req->testno = req->connect_port?DOCNUMBER_CONNECT:DOCNUMBER_BADCONNECT;
+ req->partno = 0;
+
+ sprintf(logbuf, "Requested test number %ld part %ld (from host name)",
+ req->testno, req->partno);
+ logmsg("%s", logbuf);
- /* find and parse <servercmd> for this test */
- parse_servercmd(req);
}
- else {
+
+ if(!req->testno) {
logmsg("Did not find test number in PATH");
req->testno = DOCNUMBER_404;
}
+ else
+ parse_servercmd(req);
}
}
else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
dump = fopen(dumpfile, "ab");
} while ((dump == NULL) && ((error = errno) == EINTR));
if (dump == NULL) {
- logmsg("Error opening file %s error: %d %s",
+ logmsg("[2] Error opening file %s error: %d %s",
dumpfile, error, strerror(error));
logmsg("Failed to write request input ");
return;
}
req->testno = DOCNUMBER_NOTHING;
req->partno = 0;
+ req->connect_request = FALSE;
req->open = TRUE;
req->auth_req = FALSE;
req->auth = FALSE;
const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP;
static char weare[256];
- char partbuf[80]="data";
-
- logmsg("Send response test%ld section <data%ld>", req->testno, req->partno);
-
switch(req->rcmd) {
default:
case RCMD_NORMALREQ:
msglen, msgbuf);
buffer = weare;
break;
- case DOCNUMBER_INTERNAL:
- logmsg("Bailing out due to internal error");
- return -1;
- case DOCNUMBER_CONNECT:
- logmsg("Replying to CONNECT");
- buffer = docconnect;
- break;
- case DOCNUMBER_BADCONNECT:
- logmsg("Replying to a bad CONNECT");
- buffer = docbadconnect;
- break;
case DOCNUMBER_404:
default:
logmsg("Replying to with a 404");
count = strlen(buffer);
}
else {
+ char partbuf[80];
char *filename = test2file(req->testno);
- if(0 != req->partno)
- sprintf(partbuf, "data%ld", req->partno);
+ /* select the <data> tag for "normal" requests and the <connect> one
+ for CONNECT requests (within the <reply> section) */
+ const char *section= req->connect_request?"connect":"data";
+
+ if(req->partno)
+ sprintf(partbuf, "%s%ld", section, req->partno);
+ else
+ sprintf(partbuf, "%s", section);
+
+ logmsg("Send response test%ld section <%s>", req->testno, partbuf);
stream=fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", filename);
- logmsg("Couldn't open test file");
+ logmsg(" [3] Error opening file: %s", filename);
return 0;
}
else {
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", filename);
- logmsg("Couldn't open test file");
+ logmsg(" [4] Error opening file: %s", filename);
if(ptr)
free(ptr);
return 0;
if(!dump) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", responsedump);
+ logmsg(" [5] Error opening file: %s", responsedump);
if(ptr)
free(ptr);
if(cmd)
static void http_connect(curl_socket_t *infdp,
curl_socket_t rootfd,
- struct httprequest *req,
- const char *ipaddr)
+ const char *ipaddr,
+ unsigned short ipport)
{
curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
if(got_exit_signal)
goto http_connect_cleanup;
- serverfd[CTRL] = connect_to(ipaddr, req->connect_port);
+ serverfd[CTRL] = connect_to(ipaddr, ipport);
if(serverfd[CTRL] == CURL_SOCKET_BAD)
goto http_connect_cleanup;
/* skip this and close the socket if err < 0 */
if(err >= 0) {
err = send_doc(datafd, &req2);
- if(!err && (req2.testno == DOCNUMBER_CONNECT)) {
+ if(!err && req2.connect_request) {
/* sleep to prevent triggering libcurl known bug #39. */
for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
wait_ms(250);
/* returns 1 if the connection should be serviced again immediately, 0 if there
is no data waiting, or < 0 if it should be closed */
static int service_connection(curl_socket_t msgsock, struct httprequest *req,
- curl_socket_t listensock, const char *hostport)
+ curl_socket_t listensock,
+ const char *connecthost)
{
if(got_exit_signal)
return -1;
if(got_exit_signal)
return -1;
- if(DOCNUMBER_CONNECT == req->testno) {
- /* a CONNECT request, setup and talk the tunnel */
- if(!is_proxy) {
- logmsg("received CONNECT but isn't running as proxy! EXIT");
- }
- else
- http_connect(&msgsock, listensock, req, hostport);
- return -1;
- }
-
- if((req->testno < 0) && (req->testno != DOCNUMBER_CONNECT)) {
+ if(req->testno < 0) {
logmsg("special request received, no persistency");
return -1;
}
return -1;
}
+ if(req->connect_request) {
+ /* a CONNECT request, setup and talk the tunnel */
+ if(!is_proxy) {
+ logmsg("received CONNECT but isn't running as proxy!");
+ return 1;
+ }
+ else {
+ http_connect(&msgsock, listensock, connecthost, req->connect_port);
+ return -1;
+ }
+ }
+
/* if we got a CONNECT, loop and get another request as well! */
if(req->open) {
return 1;
}
- if(req->testno == DOCNUMBER_CONNECT)
- return 1;
-
return -1;
}
int error;
int arg=1;
long pid;
- const char *hostport = "127.0.0.1";
+ const char *connecthost = "127.0.0.1";
+
+ /* a default CONNECT port is basically pointless but still ... */
size_t socket_idx;
memset(&req, 0, sizeof(req));
}
}
else if(!strcmp("--connect", argv[arg])) {
- /* store the connect host, but also use this as a hint that we
- run as a proxy and do a few different internal choices */
+ /* The connect host IP number that the proxy will connect to no matter
+ what the client asks for, but also use this as a hint that we run as
+ a proxy and do a few different internal choices */
arg++;
if(argc>arg) {
- hostport = argv[arg];
+ connecthost = argv[arg];
arg++;
is_proxy = TRUE;
- logmsg("Run as proxy, CONNECT to %s", hostport);
+ logmsg("Run as proxy, CONNECT to host %s", connecthost);
}
}
else {
/* Service this connection until it has nothing available */
do {
- rc = service_connection(all_sockets[socket_idx], &req, sock, hostport);
+ rc = service_connection(all_sockets[socket_idx], &req, sock,
+ connecthost);
if(got_exit_signal)
goto sws_cleanup;