X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jbsockets.c;h=b893b0cfe3d3ff79130ce5c5a5fec5ee51771124;hp=7c3ab071f5bd07c7199f2d19d507a60d9a803525;hb=c5eea10388af058856bb8172d36174c61b6bf45d;hpb=0428133610c525457cb16f7ac6a54203a2743d6c diff --git a/jbsockets.c b/jbsockets.c index 7c3ab071..b893b0cf 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1,4 +1,4 @@ -const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.108 2011/07/30 15:12:02 fabiankeil Exp $"; +const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.121 2013/03/01 17:38:34 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $ @@ -83,7 +83,6 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.108 2011/07/30 15:12:02 fabia #endif -#ifdef FEATURE_CONNECTION_KEEP_ALIVE #ifdef HAVE_POLL #ifdef __GLIBC__ #include @@ -91,7 +90,6 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.108 2011/07/30 15:12:02 fabia #include #endif /* def __GLIBC__ */ #endif /* HAVE_POLL */ -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ #include "project.h" @@ -133,7 +131,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli * * 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 @@ -168,7 +166,7 @@ jb_socket connect_to(const char *host, int portnum, struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Attempt %d of %d to connect to %s failed. Trying again.", - forwarded_connect_retries, csp->config->forwarded_connect_retries, host); + forwarded_connect_retries, csp->config->forwarded_connect_retries + 1, host); } } while (forwarded_connect_retries < csp->config->forwarded_connect_retries); @@ -280,6 +278,17 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client 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 TCP_NODELAY { /* turn off TCP coalescence */ int mi = 1; @@ -462,6 +471,17 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli 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; @@ -703,6 +723,77 @@ void close_socket(jb_socket fd) #else close(fd); #endif +} + + +/********************************************************************* + * + * Function : drain_and_close_socket + * + * Description : Closes a TCP/IP socket after draining unread data + * + * Parameters : + * 1 : fd = file descriptor of the socket to be closed + * + * Returns : void + * + *********************************************************************/ +void drain_and_close_socket(jb_socket fd) +{ +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (socket_is_still_alive(fd)) +#endif + { + int bytes_drained_total = 0; + int bytes_drained; + +#ifdef HAVE_SHUTDOWN +/* Apparently Windows has shutdown() but not SHUT_WR. */ +#ifndef SHUT_WR +#define SHUT_WR 1 +#endif + if (0 != shutdown(fd, SHUT_WR)) + { + log_error(LOG_LEVEL_CONNECT, "Failed to shutdown socket %d: %E", fd); + } +#endif +#define ARBITRARY_DRAIN_LIMIT 10000 + do + { + 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_CONNECT, "Failed to drain socket %d: %E", fd); + } + else if (bytes_drained > 0) + { + bytes_drained_total += bytes_drained; + if (bytes_drained_total > ARBITRARY_DRAIN_LIMIT) + { + log_error(LOG_LEVEL_CONNECT, "Giving up draining socket %d", fd); + break; + } + } + } while (bytes_drained > 0); + if (bytes_drained_total != 0) + { + log_error(LOG_LEVEL_CONNECT, + "Drained %d bytes before closing socket %d", bytes_drained_total, fd); + } + } + + close_socket(fd); } @@ -976,6 +1067,16 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, log_error(LOG_LEVEL_ERROR, "getsockname() truncated server address"); return; } +/* + * XXX: Workaround for missing header on Windows when + * 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 in included unconditionally there. + */ +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif *port = malloc(NI_MAXSERV); if (NULL == *port) { @@ -1006,7 +1107,6 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, #else *ip_address = strdup(inet_ntoa(server.sin_addr)); snprintf(*port, NI_MAXSERV, "%hu", ntohs(server.sin_port)); - *port[NI_MAXSERV - 1] = '\0'; #endif /* HAVE_RFC2553 */ if (NULL == hostname) { @@ -1196,6 +1296,29 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) } #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 + csp->cfd = afd; #ifdef HAVE_RFC2553 csp->ip_addr_str = malloc(NI_MAXHOST); @@ -1333,18 +1456,13 @@ unsigned long resolve_hostname_to_ip(const char *host) log_error(LOG_LEVEL_ERROR, "hostname %s resolves to unknown address type.", host); return(INADDR_NONE); } - memcpy( - (char *) &inaddr.sin_addr, - (char *) hostp->h_addr, - sizeof(inaddr.sin_addr) - ); + memcpy((char *)&inaddr.sin_addr, (char *)hostp->h_addr, sizeof(inaddr.sin_addr)); } return(inaddr.sin_addr.s_addr); } -#ifdef FEATURE_CONNECTION_KEEP_ALIVE /********************************************************************* * * Function : socket_is_still_alive @@ -1398,7 +1516,6 @@ int socket_is_still_alive(jb_socket sfd) return (no_data_waiting || (1 == recv(sfd, buf, 1, MSG_PEEK))); } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ /*