-const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.115 2012/10/12 11:17:48 fabiankeil Exp $";
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.125 2014/06/02 06:19:05 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
* OS-independent. Contains #ifdefs to make this work
* on many platforms.
*
- * Copyright : Written by and Copyright (C) 2001-2011 the
+ * Copyright : Written by and Copyright (C) 2001-2014 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
#endif
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
#ifdef HAVE_POLL
#ifdef __GLIBC__
#include <sys/poll.h>
#include <poll.h>
#endif /* def __GLIBC__ */
#endif /* HAVE_POLL */
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
#include "project.h"
*
* Parameters :
* 1 : host = hostname to connect to
- * 2 : portnum = port to connent on (XXX: should be unsigned)
+ * 2 : portnum = port to connect to (XXX: should be unsigned)
* 3 : csp = Current client state (buffers, headers, etc...)
*
* Returns : JB_INVALID_SOCKET => failure, else it is the socket
continue;
}
+#ifndef _WIN32
+ if (fd >= FD_SETSIZE)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Server socket number too high to use select(): %d >= %d",
+ fd, FD_SETSIZE);
+ close_socket(fd);
+ return JB_INVALID_SOCKET;
+ }
+#endif
+
+#ifdef FEATURE_EXTERNAL_FILTERS
+ mark_socket_for_close_on_execute(fd);
+#endif
+
#ifdef TCP_NODELAY
{ /* turn off TCP coalescence */
int mi = 1;
return(JB_INVALID_SOCKET);
}
+#ifndef _WIN32
+ if (fd >= FD_SETSIZE)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Server socket number too high to use select(): %d >= %d",
+ fd, FD_SETSIZE);
+ close_socket(fd);
+ return JB_INVALID_SOCKET;
+ }
+#endif
+
#ifdef TCP_NODELAY
{ /* turn off TCP coalescence */
int mi = 1;
{
flags |= O_NDELAY;
fcntl(fd, F_SETFL, flags);
+#ifdef FEATURE_EXTERNAL_FILTERS
+ mark_socket_for_close_on_execute(fd);
+#endif
}
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
#endif
if (0 != shutdown(fd, SHUT_WR))
{
- log_error(LOG_LEVEL_ERROR, "Failed to shutdown socket %d %E", fd);
+ log_error(LOG_LEVEL_CONNECT, "Failed to shutdown socket %d: %E", fd);
}
#endif
#define ARBITRARY_DRAIN_LIMIT 10000
{
char drainage[500];
+ if (!data_is_available(fd, 0))
+ {
+ /*
+ * If there is no data available right now, don't try
+ * to drain the socket as read_socket() could block.
+ */
+ break;
+ }
+
bytes_drained = read_socket(fd, drainage, sizeof(drainage));
if (bytes_drained < 0)
{
- log_error(LOG_LEVEL_ERROR, "Failed to drain socket %d %E", fd);
+ log_error(LOG_LEVEL_CONNECT, "Failed to drain socket %d: %E", fd);
}
else if (bytes_drained > 0)
{
fd = socket(AF_INET, SOCK_STREAM, 0);
#endif /* def HAVE_RFC2553 */
+#ifdef FEATURE_EXTERNAL_FILTERS
+ mark_socket_for_close_on_execute(fd);
+#endif
+
#ifdef _WIN32
if (fd == JB_INVALID_SOCKET)
#else
struct sockaddr_in server;
struct hostent *host = NULL;
#endif /* HAVE_RFC2553 */
-#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
+#if defined(_WIN32) || defined(__OS2__) || defined(AMIGA)
/* according to accept_connection() this fixes a warning. */
int s_length, s_length_provided;
#else
* configured with --disable-ipv6-support.
* The proper fix is to not use NI_MAXSERV in
* that case. It works by accident on other platforms
- * as <netdb.h> in included unconditionally there.
+ * as <netdb.h> is included unconditionally there.
*/
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
struct sockaddr_in client;
#endif
jb_socket afd;
-#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
+#if defined(_WIN32) || defined(__OS2__) || defined(AMIGA)
/* Wierdness - fix a warning. */
int c_length;
#else
}
#endif
+#ifdef SO_LINGER
+ {
+ struct linger linger_options;
+ linger_options.l_onoff = 1;
+ linger_options.l_linger = 5;
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_options, sizeof(linger_options)))
+ {
+ log_error(LOG_LEVEL_ERROR, "Setting SO_LINGER on socket %d failed.", afd);
+ }
+ }
+#endif
+
+#ifndef _WIN32
+ if (afd >= FD_SETSIZE)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Client socket number too high to use select(): %d >= %d",
+ afd, FD_SETSIZE);
+ close_socket(afd);
+ return 0;
+ }
+#endif
+
+#ifdef FEATURE_EXTERNAL_FILTERS
+ mark_socket_for_close_on_execute(afd);
+#endif
+
csp->cfd = afd;
#ifdef HAVE_RFC2553
csp->ip_addr_str = malloc(NI_MAXHOST);
}
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
/*********************************************************************
*
* Function : socket_is_still_alive
return (no_data_waiting || (1 == recv(sfd, buf, 1, MSG_PEEK)));
}
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+#ifdef FEATURE_EXTERNAL_FILTERS
+/*********************************************************************
+ *
+ * Function : mark_socket_for_close_on_execute
+ *
+ * Description : Marks a socket for close on execute.
+ *
+ * Used so that external filters have no direct
+ * access to sockets they shouldn't care about.
+ *
+ * Not implemented for all platforms.
+ *
+ * Parameters :
+ * 1 : fd = The socket to mark
+ *
+ * Returns : void.
+ *
+ *********************************************************************/
+void mark_socket_for_close_on_execute(jb_socket fd)
+{
+#ifdef FEATURE_PTHREAD
+ int ret;
+
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ if (ret == -1)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "fcntl(%d, F_SETFD, FD_CLOEXEC) failed", fd);
+ }
+#else
+#warning "Sockets will be visible to external filters"
+#endif
+}
+#endif /* def FEATURE_EXTERNAL_FILTERS */
+
/*
Local Variables:
tab-width: 3