Newer
Older
Daniel Stenberg
committed
#endif
while(argc>arg) {
if(!strcmp("--version", argv[arg])) {
Daniel Stenberg
committed
printf("sws IPv4%s"
#ifdef CURL_SWS_FORK_ENABLED
" FORK"
#endif
"\n"
,
#ifdef ENABLE_IPV6
"/IPv6"
#else
""
#endif
);
return 0;
}
else if(!strcmp("--pidfile", argv[arg])) {
arg++;
if(argc>arg)
pidname = argv[arg++];
}
else if(!strcmp("--ipv6", argv[arg])) {
ipv_inuse = "IPv6";
use_ipv6 = TRUE;
Daniel Stenberg
committed
#ifdef CURL_SWS_FORK_ENABLED
else if(!strcmp("--fork", argv[arg])) {
use_fork=TRUE;
arg++;
}
#endif
else if(argc>arg) {
if(atoi(argv[arg]))
port = (unsigned short)atoi(argv[arg++]);
if(argc>arg)
path = argv[arg++];
}
}
Daniel Stenberg
committed
win32_init();
atexit(win32_cleanup);
install_signal_handlers();
#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(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
logmsg("Error creating socket: (%d) %s",
error, strerror(error));
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));
#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 {
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 */
error = SOCKERRNO;
logmsg("Error binding socket on port %hu: (%d) %s",
port, error, strerror(error));
logmsg("Running %s version on port %d", ipv_inuse, (int)port);
/* start accepting connections */
error = SOCKERRNO;
logmsg("listen() failed with error: (%d) %s",
error, strerror(error));
wrotepidfile = write_pidfile(pidname);
if(!wrotepidfile)
goto sws_cleanup;
msgsock = accept(sock, NULL, NULL);
if(got_exit_signal)
break;
error = SOCKERRNO;
logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
error, strerror(error));
break;
}
set_advisor_read_lock(SERVERLOGS_LOCK);
#ifdef CURL_SWS_FORK_ENABLED
Daniel Stenberg
committed
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;
}
Daniel Stenberg
committed
else
/* not a fork, just set rc so the following proceeds nicely */
rc = 0;
/* 0 is returned to the child */
if(0 == rc) {
#endif
#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 (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
(void *)&flag, sizeof(flag)) == -1) {
logmsg("====> TCP_NODELAY failed");
}
/* 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. */
req.pipelining = FALSE;
do {
if(got_exit_signal)
break;
Daniel Stenberg
committed
if(get_request(msgsock, &req))
/* non-zero means error, break out of loop */
break;
Daniel Stenberg
committed
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;
}
Daniel Stenberg
committed
}
Daniel Stenberg
committed
send_doc(msgsock, &req);
if(got_exit_signal)
break;
Daniel Stenberg
committed
if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
logmsg("special request received, no persistency");
break;
}
Daniel Stenberg
committed
if(!req.open) {
logmsg("instructed to close connection after server-reply");
break;
}
Daniel Stenberg
committed
if(req.open)
logmsg("=> persistant connection request ended, awaits new request");
/* if we got a CONNECT, loop and get another request as well! */
Daniel Stenberg
committed
} while(req.open || (req.testno == DOCNUMBER_CONNECT));
if(got_exit_signal)
break;
sclose(msgsock);
clear_advisor_read_lock(SERVERLOGS_LOCK);
Daniel Stenberg
committed
if (req.testno == DOCNUMBER_QUIT)
break;
#ifdef CURL_SWS_FORK_ENABLED
}
#endif
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");