* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
#define ERANGE 34 /* errno.h value */
#endif
-static enum {
- socket_domain_inet = AF_INET
#ifdef ENABLE_IPV6
- , socket_domain_inet6 = AF_INET6
+static bool use_ipv6 = FALSE;
#endif
-#ifdef USE_UNIX_SOCKETS
- , socket_domain_unix = AF_UNIX
-#endif
-} socket_domain = AF_INET;
static bool use_gopher = FALSE;
+static const char *ipv_inuse = "IPv4";
static int serverlogslocked = 0;
static bool is_proxy = FALSE;
bool pipelining; /* true if request is pipelined */
int callcount; /* times ProcessRequest() gets called */
bool connmon; /* monitor the state of the connection, log disconnects */
- bool upgrade; /* test case allows upgrade to http2 */
- bool upgrade_request; /* upgrade request found and allowed */
int done_processing;
};
proper point - like with NTLM */
#define CMD_CONNECTIONMONITOR "connection-monitor"
-/* upgrade to http2 */
-#define CMD_UPGRADE "upgrade"
-
#define END_OF_HEADERS "\r\n\r\n"
enum {
#endif
}
-/* returns true if the current socket is an IP one */
-static bool socket_domain_is_ip(void)
-{
- switch(socket_domain) {
- case AF_INET:
-#ifdef ENABLE_IPV6
- case AF_INET6:
-#endif
- return true;
- default:
- /* case AF_UNIX: */
- return false;
- }
-}
-
/* based on the testno, parse the correct server commands */
static int parse_servercmd(struct httprequest *req)
{
logmsg("enabled connection monitoring");
req->connmon = TRUE;
}
- else if(!strncmp(CMD_UPGRADE, cmd, strlen(CMD_UPGRADE))) {
- logmsg("enabled upgrade to http2");
- req->upgrade = TRUE;
- }
else if(1 == sscanf(cmd, "pipe: %d", &num)) {
logmsg("instructed to allow a pipe size of %d", num);
if(num < 0)
return 1; /* done */
}
- if(req->upgrade && strstr(req->reqbuf, "Upgrade:")) {
- /* we allow upgrade and there was one! */
- logmsg("Found Upgrade: in request and allows it");
- req->upgrade_request = TRUE;
- }
-
if(req->cl > 0) {
if(req->cl <= req->offset - (end - req->reqbuf) - strlen(end_of_headers))
return 1; /* done */
srvr_sockaddr_union_t serveraddr;
curl_socket_t serverfd;
int error;
- int rc = 0;
+ int rc;
const char *op_br = "";
const char *cl_br = "";
+#ifdef TCP_NODELAY
+ curl_socklen_t flag;
+#endif
#ifdef ENABLE_IPV6
- if(socket_domain == AF_INET6) {
+ if(use_ipv6) {
op_br = "[";
cl_br = "]";
}
logmsg("about to connect to %s%s%s:%hu",
op_br, ipaddr, cl_br, port);
-
- serverfd = socket(socket_domain, 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",
}
#ifdef TCP_NODELAY
- if(socket_domain_is_ip()) {
- /* Disable the Nagle algorithm */
- curl_socklen_t 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");
- }
+ /* Disable the Nagle algorithm */
+ 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
- switch(socket_domain) {
- case AF_INET:
+#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);
}
rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4));
- break;
#ifdef ENABLE_IPV6
- case AF_INET6:
+ }
+ else {
memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6));
serveraddr.sa6.sin6_family = AF_INET6;
serveraddr.sa6.sin6_port = htons(port);
}
rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6));
- break;
-#endif /* ENABLE_IPV6 */
-#ifdef USE_UNIX_SOCKETS
- case AF_UNIX:
- logmsg("Proxying through Unix socket is not (yet?) supported.");
- return CURL_SOCKET_BAD;
-#endif /* USE_UNIX_SOCKETS */
}
+#endif /* ENABLE_IPV6 */
if(got_exit_signal) {
sclose(serverfd);
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;
+#endif
bool primary = FALSE;
bool secondary = FALSE;
int max_tunnel_idx; /* CTRL or DATA */
memset(&req2, 0, sizeof(req2));
logmsg("====> Client connect DATA");
#ifdef TCP_NODELAY
- if(socket_domain_is_ip()) {
- /* Disable the Nagle algorithm */
- curl_socklen_t 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");
- }
+ /* Disable the Nagle algorithm */
+ 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;
init_httprequest(&req2);
*infdp = CURL_SOCKET_BAD;
}
-static void http2(struct httprequest *req)
-{
- (void)req;
- logmsg("switched to http2");
- /* left to implement */
-}
-
-
/* returns a socket handle, or 0 if there are no more waiting sockets,
or < 0 if there was an error */
static curl_socket_t accept_connection(curl_socket_t sock)
num_sockets += 1;
#ifdef TCP_NODELAY
- if(socket_domain_is_ip()) {
- /*
- * Disable the Nagle algorithm to make it easier to send out a large
- * response in many small segments to torture the clients more.
- */
- if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
- (void *)&flag, sizeof(flag)))
- logmsg("====> TCP_NODELAY failed");
- else
- logmsg("TCP_NODELAY set");
- }
+ /*
+ * Disable the Nagle algorithm to make it easier to send out a large
+ * response in many small segments to torture the clients more.
+ */
+ if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
+ (void *)&flag, sizeof(flag)))
+ logmsg("====> TCP_NODELAY failed");
+ else
+ logmsg("TCP_NODELAY set");
#endif
return msgsock;
}
}
- if(req->upgrade_request) {
- /* an upgrade request, switch to http2 here */
- http2(req);
- return -1;
- }
-
/* if we got a CONNECT, loop and get another request as well! */
if(req->open) {
int wrotepidfile = 0;
int flag;
unsigned short port = DEFAULT_PORT;
-#ifdef USE_UNIX_SOCKETS
- const char *unix_socket = NULL;
- bool unlink_socket = false;
-#endif
char *pidname= (char *)".http.pid";
struct httprequest req;
- int rc = 0;
+ int rc;
int error;
int arg=1;
long pid;
const char *connecthost = "127.0.0.1";
- const char *socket_type = "IPv4";
- char port_str[11];
- const char *location_str = port_str;
/* a default CONNECT port is basically pointless but still ... */
size_t socket_idx;
while(argc>arg) {
if(!strcmp("--version", argv[arg])) {
- puts("sws IPv4"
+ printf("sws IPv4%s"
+ "\n"
+ ,
#ifdef ENABLE_IPV6
"/IPv6"
+#else
+ ""
#endif
-#ifdef USE_UNIX_SOCKETS
- "/unix"
-#endif
- );
+ );
return 0;
}
else if(!strcmp("--pidfile", argv[arg])) {
end_of_headers = "\r\n"; /* gopher style is much simpler */
}
else if(!strcmp("--ipv4", argv[arg])) {
- socket_type = "IPv4";
- socket_domain = AF_INET;
- location_str = port_str;
+#ifdef ENABLE_IPV6
+ ipv_inuse = "IPv4";
+ use_ipv6 = FALSE;
+#endif
arg++;
}
else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
- socket_type = "IPv6";
- socket_domain = AF_INET6;
- location_str = port_str;
+ ipv_inuse = "IPv6";
+ use_ipv6 = TRUE;
#endif
arg++;
}
- else if(!strcmp("--unix-socket", argv[arg])) {
- arg++;
- if(argc>arg) {
-#ifdef USE_UNIX_SOCKETS
- unix_socket = argv[arg];
- if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) {
- fprintf(stderr, "sws: socket path must be shorter than %zu chars\n",
- sizeof(me.sau.sun_path));
- return 0;
- }
- socket_type = "unix";
- socket_domain = AF_UNIX;
- location_str = unix_socket;
-#endif
- arg++;
- }
- }
else if(!strcmp("--port", argv[arg])) {
arg++;
if(argc>arg) {
" --pidfile [file]\n"
" --ipv4\n"
" --ipv6\n"
- " --unix-socket [file]\n"
" --port [port]\n"
" --srcdir [path]\n"
" --connect [ip4-addr]\n"
}
}
- snprintf(port_str, sizeof(port_str), "port %hu", port);
-
#ifdef WIN32
win32_init();
atexit(win32_cleanup);
pid = (long)getpid();
- sock = socket(socket_domain, 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
all_sockets[0] = sock;
num_sockets = 1;
goto sws_cleanup;
}
- switch(socket_domain) {
- case AF_INET:
+#ifdef ENABLE_IPV6
+ if(!use_ipv6) {
+#endif
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));
- break;
#ifdef ENABLE_IPV6
- case AF_INET6:
+ }
+ else {
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));
- break;
-#endif /* ENABLE_IPV6 */
-#ifdef USE_UNIX_SOCKETS
- case AF_UNIX:
- memset(&me.sau, 0, sizeof(me.sau));
- me.sau.sun_family = AF_UNIX;
- strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path));
- rc = bind(sock, &me.sa, sizeof(me.sau));
- if(0 != rc && errno == EADDRINUSE) {
- struct stat statbuf;
- /* socket already exists. Perhaps it is stale? */
- int unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(CURL_SOCKET_BAD == unixfd) {
- error = SOCKERRNO;
- logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
- /* check whether the server is alive */
- rc = connect(unixfd, &me.sa, sizeof(me.sau));
- error = errno;
- close(unixfd);
- if(ECONNREFUSED != error) {
- logmsg("Error binding socket, failed to connect to %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
- /* 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) {
- logmsg("Error binding socket, failed to stat %s: (%d) %s",
- unix_socket, errno, strerror(errno));
- goto sws_cleanup;
- }
- if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
- logmsg("Error binding socket, failed to stat %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
- /* dead socket, cleanup and retry bind */
- rc = unlink(unix_socket);
- if(0 != rc) {
- logmsg("Error binding socket, failed to unlink %s: (%d) %s",
- unix_socket, errno, strerror(errno));
- goto sws_cleanup;
- }
- /* stale socket is gone, retry bind */
- rc = bind(sock, &me.sa, sizeof(me.sau));
- }
- break;
-#endif /* USE_UNIX_SOCKETS */
}
+#endif /* ENABLE_IPV6 */
if(0 != rc) {
error = SOCKERRNO;
- logmsg("Error binding socket on %s: (%d) %s",
- location_str, error, strerror(error));
+ logmsg("Error binding socket on port %hu: (%d) %s",
+ port, error, strerror(error));
goto sws_cleanup;
}
- logmsg("Running %s %s version on %s",
- use_gopher?"GOPHER":"HTTP", socket_type, location_str);
+ logmsg("Running %s %s version on port %d",
+ use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port);
/* start accepting connections */
rc = listen(sock, 5);
goto sws_cleanup;
}
-#ifdef USE_UNIX_SOCKETS
- /* listen succeeds, so let's assume a valid listening Unix socket */
- unlink_socket = true;
-#endif
-
/*
** As soon as this server writes its pid file the test harness will
** attempt to connect to this server and initiate its verification.
if(sock != CURL_SOCKET_BAD)
sclose(sock);
-#ifdef USE_UNIX_SOCKETS
- if(unlink_socket && socket_domain == AF_UNIX) {
- rc = unlink(unix_socket);
- logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc));
- }
-#endif
-
if(got_exit_signal)
logmsg("signalled to die");
restore_signal_handlers();
if(got_exit_signal) {
- logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)",
- socket_type, location_str, pid, 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