X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jbsockets.c;h=45b57a9ea24eaede6394257d0374fa62ef70733f;hb=dadd1f7c43c43b4a1d9a3f4d50acc542b122556e;hp=76eddf4780451bc0a48117189668f2fcfa4d1daf;hpb=c19d6c89f0b349ec9d31d2a2853f4c08fb31b506;p=privoxy.git diff --git a/jbsockets.c b/jbsockets.c index 76eddf47..45b57a9e 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1,4 +1,4 @@ -const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.111 2011/12/10 17:26:30 fabiankeil Exp $"; +const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.117 2012/10/17 18:01:34 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $ @@ -703,6 +703,68 @@ 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]; + + 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); } @@ -1205,6 +1267,18 @@ 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 + csp->cfd = afd; #ifdef HAVE_RFC2553 csp->ip_addr_str = malloc(NI_MAXHOST); @@ -1342,11 +1416,7 @@ 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);