* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* 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.
+ * are also available at https://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
const char *serverlogfile = DEFAULT_LOGFILE;
-#define SWSVERSION "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"
{
#ifdef SIGHUP
/* ignore SIGHUP signal */
- if((old_sighup_handler = signal(SIGHUP, SIG_IGN)) == SIG_ERR)
+ old_sighup_handler = signal(SIGHUP, SIG_IGN);
+ if(old_sighup_handler == 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)
+ old_sigpipe_handler = signal(SIGPIPE, SIG_IGN);
+ if(old_sigpipe_handler == 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)
+ old_sigalrm_handler = signal(SIGALRM, SIG_IGN);
+ if(old_sigalrm_handler == 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)
+ old_sigint_handler = signal(SIGINT, exit_signal_handler);
+ if(old_sigint_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)
+ old_sigterm_handler = signal(SIGTERM, exit_signal_handler);
+ if(old_sigterm_handler == SIG_ERR)
logmsg("cannot install SIGTERM handler: %s", strerror(errno));
else
siginterrupt(SIGTERM, 1);
#endif
#if defined(SIGBREAK) && defined(WIN32)
/* handle SIGBREAK signal with our exit_signal_handler */
- if((old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler)) == SIG_ERR)
+ old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler);
+ if(old_sigbreak_handler == SIG_ERR)
logmsg("cannot install SIGBREAK handler: %s", strerror(errno));
else
siginterrupt(SIGBREAK, 1);
else
break;
}
- if(orgcmd)
- free(orgcmd);
+ free(orgcmd);
}
return 0; /* OK! */
/* get the number after it */
if(ptr) {
if((strlen(doc) + strlen(request)) < 400)
- sprintf(logbuf, "Got request: %s %s HTTP/%d.%d",
- request, doc, prot_major, prot_minor);
+ snprintf(logbuf, sizeof(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);
+ snprintf(logbuf, sizeof(logbuf), "Got a *HUGE* request HTTP/%d.%d",
+ prot_major, prot_minor);
logmsg("%s", logbuf);
if(!strncmp("/verifiedserver", ptr, 15)) {
if(req->testno) {
- sprintf(logbuf, "Requested test number %ld part %ld",
- req->testno, req->partno);
+ snprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld",
+ req->testno, req->partno);
logmsg("%s", logbuf);
/* find and parse <servercmd> for this test */
char *portp = NULL;
unsigned long part=0;
- sprintf(logbuf, "Received a CONNECT %s HTTP/%d.%d request",
- doc, prot_major, prot_minor);
+ snprintf(logbuf, sizeof(logbuf),
+ "Received a CONNECT %s HTTP/%d.%d request",
+ doc, prot_major, prot_minor);
logmsg("%s", logbuf);
req->connect_request = TRUE;
}
if(*p != ']')
logmsg("Invalid CONNECT IPv6 address format");
- else if (*(p+1) != ':')
+ else if(*(p+1) != ':')
logmsg("Invalid CONNECT IPv6 port format");
else
portp = p+1;
else
req->partno = 0;
- sprintf(logbuf, "Requested test number %ld part %ld (from host name)",
- req->testno, req->partno);
+ snprintf(logbuf, sizeof(logbuf),
+ "Requested test number %ld part %ld (from host name)",
+ req->testno, req->partno);
logmsg("%s", logbuf);
}
else
req->partno = 0;
- sprintf(logbuf, "Requested GOPHER test number %ld part %ld",
- req->testno, req->partno);
+ snprintf(logbuf, sizeof(logbuf),
+ "Requested GOPHER test number %ld part %ld",
+ req->testno, req->partno);
logmsg("%s", logbuf);
}
}
if(got_exit_signal)
return 1; /* done */
- if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
+ if((req->cl==0) && strncasecompare("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
logmsg("... but will abort after %zu bytes", req->cl);
break;
}
- else if(curlx_strnequal("Transfer-Encoding: chunked", line,
+ else if(strncasecompare("Transfer-Encoding: chunked", line,
strlen("Transfer-Encoding: chunked"))) {
/* chunked data coming in */
chunked = TRUE;
FILE *dump;
const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
- if (reqbuf == NULL)
+ if(reqbuf == NULL)
return;
- if (totalsize == 0)
+ if(totalsize == 0)
return;
do {
dump = fopen(dumpfile, "ab");
- } while ((dump == NULL) && ((error = errno) == EINTR));
- if (dump == NULL) {
+ } while((dump == NULL) && ((error = errno) == EINTR));
+ if(dump == NULL) {
logmsg("[2] Error opening file %s error: %d %s",
dumpfile, error, strerror(error));
logmsg("Failed to write request input ");
goto storerequest_cleanup;
if(written > 0)
writeleft -= written;
- } while ((writeleft > 0) && ((error = errno) == EINTR));
+ } while((writeleft > 0) && ((error = errno) == EINTR));
if(writeleft == 0)
logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
req->callcount = 0;
req->connect_port = 0;
req->done_processing = 0;
+ req->upgrade = 0;
+ req->upgrade_request = 0;
}
/* returns 1 if the connection should be serviced again immediately, 0 if there
}
else if(got < 0) {
error = SOCKERRNO;
- if (EAGAIN == error || EWOULDBLOCK == error) {
+ if(EAGAIN == error || EWOULDBLOCK == error) {
/* nothing to read at the moment */
return 0;
}
reqbuf[req->offset] = '\0';
/* at the end of a request dump it to an external file */
- if (fail || req->done_processing)
+ if(fail || req->done_processing)
storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
if(got_exit_signal)
return -1;
case RCMD_STREAM:
#define STREAMTHIS "a string to stream 01234567890\n"
count = strlen(STREAMTHIS);
- for (;;) {
+ for(;;) {
written = swrite(sock, STREAMTHIS, count);
if(got_exit_signal)
return -1;
case DOCNUMBER_WERULEZ:
/* we got a "friends?" question, reply back that we sure are */
logmsg("Identifying ourselves as friends");
- sprintf(msgbuf, "WE ROOLZ: %ld\r\n", (long)getpid());
+ snprintf(msgbuf, sizeof(msgbuf), "WE ROOLZ: %ld\r\n", (long)getpid());
msglen = strlen(msgbuf);
if(use_gopher)
- sprintf(weare, "%s", msgbuf);
+ snprintf(weare, sizeof(weare), "%s", msgbuf);
else
- sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
- msglen, msgbuf);
+ snprintf(weare, sizeof(weare),
+ "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
+ msglen, msgbuf);
buffer = weare;
break;
case DOCNUMBER_404:
const char *section= req->connect_request?"connect":"data";
if(req->partno)
- sprintf(partbuf, "%s%ld", section, req->partno);
+ snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno);
else
- sprintf(partbuf, "%s", section);
+ snprintf(partbuf, sizeof(partbuf), "%s", section);
logmsg("Send response test%ld section <%s>", req->testno, partbuf);
}
if(got_exit_signal) {
- if(ptr)
- free(ptr);
+ free(ptr);
return -1;
}
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
logmsg(" [4] Error opening file: %s", filename);
- if(ptr)
- free(ptr);
+ free(ptr);
return 0;
}
else {
fclose(stream);
if(error) {
logmsg("getpart() failed with error: %d", error);
- if(ptr)
- free(ptr);
+ free(ptr);
return 0;
}
}
}
if(got_exit_signal) {
- if(ptr)
- free(ptr);
- if(cmd)
- free(cmd);
+ free(ptr);
+ free(cmd);
return -1;
}
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
logmsg(" [5] Error opening file: %s", responsedump);
- if(ptr)
- free(ptr);
- if(cmd)
- free(cmd);
+ free(ptr);
+ free(cmd);
return -1;
}
size_t num = count;
if(num > 200)
num = 200;
+
+ retry:
written = swrite(sock, buffer, num);
- if (written < 0) {
+ if(written < 0) {
+ if((EWOULDBLOCK == SOCKERRNO) || (EAGAIN == SOCKERRNO)) {
+ wait_ms(10);
+ goto retry;
+ }
sendfailure = TRUE;
break;
}
else {
logmsg("Sent off %zd bytes", written);
}
+
/* write to file as well */
fwrite(buffer, 1, (size_t)written, dump);
responsedump, error, strerror(error));
if(got_exit_signal) {
- if(ptr)
- free(ptr);
- if(cmd)
- free(cmd);
+ free(ptr);
+ free(cmd);
return -1;
}
if(sendfailure) {
- logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) were sent",
+ logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) "
+ "were sent",
responsesize-count, responsesize);
- if(ptr)
- free(ptr);
- if(cmd)
- free(cmd);
+ free(ptr);
+ free(cmd);
return -1;
}
logmsg("Response sent (%zu bytes) and written to %s",
responsesize, responsedump);
+ free(ptr);
- if(ptr)
- free(ptr);
-
- if(cmdsize > 0 ) {
+ if(cmdsize > 0) {
char command[32];
int quarters;
int num;
ptr = NULL;
} while(ptr && *ptr);
}
- if(cmd)
- free(cmd);
-
+ free(cmd);
req->open = use_gopher?FALSE:persistant;
prevtestno = req->testno;
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
int max_tunnel_idx; /* CTRL or DATA */
int loop;
int i;
+ int timeout_count=0;
/* primary tunnel client endpoint already connected */
clientfd[CTRL] = *infdp;
fd_set input;
fd_set output;
- struct timeval timeout = {0, 250000L}; /* 250 ms */
+ struct timeval timeout = {1, 0}; /* 1000 ms */
ssize_t rc;
curl_socket_t maxfd = (curl_socket_t)-1;
if(rc > 0) {
/* socket action */
bool tcp_fin_wr;
+ timeout_count=0;
if(got_exit_signal)
break;
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;
/* 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 */
+ /* secondary tunnel established, now we have two
+ connections */
poll_client_rd[DATA] = TRUE;
poll_client_wr[DATA] = TRUE;
poll_server_rd[DATA] = TRUE;
break;
} /* (rc > 0) */
-
+ else {
+ timeout_count++;
+ if(timeout_count > 5) {
+ logmsg("CONNECT proxy timeout after %d idle seconds!", timeout_count);
+ break;
+ }
+ }
}
http_connect_cleanup:
if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
(void *)&flag, sizeof(flag)))
logmsg("====> TCP_NODELAY failed");
- else
- logmsg("TCP_NODELAY set");
}
#endif
while(!req->done_processing) {
int rc = get_request(msgsock, req);
- if (rc <= 0) {
+ if(rc <= 0) {
/* Nothing further to read now (possibly because the socket was closed */
return rc;
}
/* socket server is not alive, now check if it was actually a socket.
* Systems which have Unix sockets will also have lstat */
rc = lstat(unix_socket, &statbuf);
- if (0 != rc) {
+ if(0 != rc) {
logmsg("Error binding socket, failed to stat %s: (%d) %s",
unix_socket, errno, strerror(errno));
goto sws_cleanup;
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]) {
- char* dst = (char *) (all_sockets + socket_idx);
- char* src = (char *) (all_sockets + socket_idx + 1);
- char* end = (char *) (all_sockets + num_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);
memmove(dst, src, end - src);
num_sockets -= 1;
}
FD_ZERO(&input);
FD_ZERO(&output);
- for (socket_idx = 0; socket_idx < num_sockets; ++socket_idx) {
+ 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)
goto sws_cleanup;
rc = select((int)maxfd + 1, &input, &output, NULL, &timeout);
- if (rc < 0) {
+ if(rc < 0) {
error = SOCKERRNO;
logmsg("select() failed with error: (%d) %s",
error, strerror(error));
if(got_exit_signal)
goto sws_cleanup;
- if (rc == 0) {
+ if(rc == 0) {
/* Timed out - try again*/
continue;
}
/* Check if the listening socket is ready to accept */
- if (FD_ISSET(all_sockets[0], &input)) {
+ if(FD_ISSET(all_sockets[0], &input)) {
/* 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)
+ if(CURL_SOCKET_BAD == msgsock)
goto sws_cleanup;
- } while (msgsock > 0);
+ } while(msgsock > 0);
}
/* Service all connections that are ready */
- for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
- if (FD_ISSET(all_sockets[socket_idx], &input)) {
+ for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
+ if(FD_ISSET(all_sockets[socket_idx], &input)) {
if(got_exit_signal)
goto sws_cleanup;
if(got_exit_signal)
goto sws_cleanup;
- if (rc < 0) {
+ if(rc < 0) {
logmsg("====> Client disconnect %d", req.connmon);
if(req.connmon) {
if(!serverlogslocked)
clear_advisor_read_lock(SERVERLOGS_LOCK);
- if (req.testno == DOCNUMBER_QUIT)
+ if(req.testno == DOCNUMBER_QUIT)
goto sws_cleanup;
}
/* Reset the request, unless we're still in the middle of reading */
- if (rc != 0)
+ if(rc != 0)
init_httprequest(&req);
- } while (rc > 0);
+ } while(rc > 0);
}
}
sws_cleanup:
- for (socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
+ for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx)
if((all_sockets[socket_idx] != sock) &&
(all_sockets[socket_idx] != CURL_SOCKET_BAD))
sclose(all_sockets[socket_idx]);