X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jbsockets.c;h=02e5c75987aa1c54d372f68efb344a8943634e6b;hp=57e9f1ac6d4f37e2541637fb36c11b8eff5ccc70;hb=d58604122bfff897a0ab92da9d3667dfecc9611e;hpb=1e870385ec3de74c0d560b14caee81e47a53fdf8 diff --git a/jbsockets.c b/jbsockets.c index 57e9f1ac..02e5c759 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1,4 +1,4 @@ -const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.58 2009/05/19 17:20:35 fabiankeil Exp $"; +const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.78 2010/07/26 11:28:11 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $ @@ -8,7 +8,7 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.58 2009/05/19 17:20:35 fabian * OS-independent. Contains #ifdefs to make this work * on many platforms. * - * Copyright : Written by and Copyright (C) 2001-2009 the + * Copyright : Written by and Copyright (C) 2001-2010 the * Privoxy team. http://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -95,15 +95,17 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.58 2009/05/19 17:20:35 fabian #include "project.h" -#ifdef FEATURE_PTHREAD +/* For mutex semaphores only */ #include "jcc.h" -/* jcc.h is for mutex semaphores only */ -#endif /* def FEATURE_PTHREAD */ #include "jbsockets.h" #include "filters.h" #include "errlog.h" -#include "miscutil.h" + +/* Mac OSX doesn't define AI_NUMERICSESRV */ +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 +#endif const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; @@ -144,9 +146,9 @@ jb_socket connect_to(const char *host, int portnum, struct client_state *csp) jb_socket fd; fd_set wfds; struct timeval tv[1]; -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) int flags; -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */ +#endif int connect_failed; #ifdef FEATURE_ACL @@ -166,11 +168,16 @@ jb_socket connect_to(const char *host, int portnum, struct client_state *csp) memset((char *)&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; /* avoid service look-up */ + hints.ai_flags = AI_NUMERICSERV; /* avoid service look-up */ +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif if ((retval = getaddrinfo(host, service, &hints, &result))) { log_error(LOG_LEVEL_INFO, "Can not resolve %s: %s", host, gai_strerror(retval)); + /* XXX: Should find a better way to propagate this error. */ + errno = EINVAL; csp->http->host_ip_addr_str = strdup("unknown"); return(JB_INVALID_SOCKET); } @@ -193,6 +200,12 @@ jb_socket connect_to(const char *host, int portnum, struct client_state *csp) #endif /* def FEATURE_ACL */ csp->http->host_ip_addr_str = malloc(NI_MAXHOST); + if (NULL == csp->http->host_ip_addr_str) + { + log_error(LOG_LEVEL_ERROR, + "Out of memory while getting the server IP address."); + return JB_INVALID_SOCKET; + } retval = getnameinfo(rp->ai_addr, rp->ai_addrlen, csp->http->host_ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (!csp->http->host_ip_addr_str || retval) @@ -331,9 +344,9 @@ jb_socket connect_to(const char *host, int portnum, struct client_state *csp) unsigned int addr; fd_set wfds; struct timeval tv[1]; -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) int flags; -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */ +#endif #ifdef FEATURE_ACL struct access_control_addr dst[1]; @@ -485,7 +498,7 @@ int write_socket(jb_socket fd, const char *buf, size_t len) return 1; } - log_error(LOG_LEVEL_LOG, "%N", len, buf); + log_error(LOG_LEVEL_WRITING, "to socket %d: %N", fd, len, buf); #if defined(_WIN32) return (send(fd, buf, (int)len, 0) != (int)len); @@ -498,7 +511,7 @@ int write_socket(jb_socket fd, const char *buf, size_t len) */ #define SOCKET_SEND_MAX 65000 { - int write_len = 0, send_len, send_rc = 0, i = 0; + int send_len, send_rc = 0, i = 0; while ((i < len) && (send_rc != -1)) { if ((i + SOCKET_SEND_MAX) > len) @@ -546,18 +559,27 @@ int write_socket(jb_socket fd, const char *buf, size_t len) *********************************************************************/ int read_socket(jb_socket fd, char *buf, int len) { + int ret; + if (len <= 0) { return(0); } #if defined(_WIN32) - return(recv(fd, buf, len, 0)); + ret = recv(fd, buf, len, 0); #elif defined(__BEOS__) || defined(AMIGA) || defined(__OS2__) - return(recv(fd, buf, (size_t)len, 0)); + ret = recv(fd, buf, (size_t)len, 0); #else - return(read(fd, buf, (size_t)len)); + ret = (int)read(fd, buf, (size_t)len); #endif + + if (ret > 0) + { + log_error(LOG_LEVEL_RECEIVED, "from socket %d: %N", fd, ret, buf); + } + + return ret; } @@ -577,6 +599,7 @@ int read_socket(jb_socket fd, char *buf, int len) *********************************************************************/ int data_is_available(jb_socket fd, int seconds_to_wait) { + char buf[10]; fd_set rfds; struct timeval timeout; int n; @@ -597,7 +620,7 @@ int data_is_available(jb_socket fd, int seconds_to_wait) /* * XXX: Do we care about the different error conditions? */ - return (n == 1); + return ((n == 1) && (1 == recv(fd, buf, 1, MSG_PEEK))); } @@ -678,7 +701,7 @@ int bind_port(const char *hostnam, int portnum, jb_socket *pfd) } memset(&hints, 0, sizeof(struct addrinfo)); - if ((hostnam == NULL) || !strcmpic(hostnam, "localhost")) + if (hostnam == NULL) { /* * XXX: This is a hack. The right thing to do @@ -693,7 +716,10 @@ int bind_port(const char *hostnam, int portnum, jb_socket *pfd) hints.ai_family = AF_UNSPEC; } hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_flags = AI_PASSIVE; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif hints.ai_protocol = 0; /* Realy any stream protocol or TCP only */ hints.ai_canonname = NULL; hints.ai_addr = NULL; @@ -895,6 +921,12 @@ void get_host_information(jb_socket afd, char **ip_address, char **hostname) } #ifdef HAVE_RFC2553 *ip_address = malloc(NI_MAXHOST); + if (NULL == *ip_address) + { + log_error(LOG_LEVEL_ERROR, + "Out of memory while getting the client's IP address."); + return; + } retval = getnameinfo((struct sockaddr *) &server, s_length, *ip_address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (retval) @@ -918,6 +950,12 @@ void get_host_information(jb_socket afd, char **ip_address, char **hostname) #ifdef HAVE_RFC2553 *hostname = malloc(NI_MAXHOST); + if (NULL == *hostname) + { + log_error(LOG_LEVEL_ERROR, + "Out of memory while getting the client's hostname."); + return; + } retval = getnameinfo((struct sockaddr *) &server, s_length, *hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD); if (retval) @@ -947,7 +985,7 @@ void get_host_information(jb_socket afd, char **ip_address, char **hostname) { host = NULL; } -#elif FEATURE_PTHREAD +#elif defined(MUTEX_LOCKS_AVAILABLE) privoxy_mutex_lock(&resolver_mutex); host = gethostbyaddr((const char *)&server.sin_addr, sizeof(server.sin_addr), AF_INET); @@ -1015,6 +1053,12 @@ int accept_connection(struct client_state * csp, jb_socket fd) #else do { +#if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER) + struct accept_filter_arg af_options; + bzero(&af_options, sizeof(af_options)); + strlcpy(af_options.af_name, "httpready", sizeof(af_options.af_name)); + setsockopt(fd, SOL_SOCKET, SO_ACCEPTFILTER, &af_options, sizeof(af_options)); +#endif afd = accept (fd, (struct sockaddr *) &client, &c_length); } while (afd < 1 && errno == EINTR); if (afd < 0) @@ -1026,6 +1070,12 @@ int accept_connection(struct client_state * csp, jb_socket fd) csp->cfd = afd; #ifdef HAVE_RFC2553 csp->ip_addr_str = malloc(NI_MAXHOST); + if (NULL == csp->ip_addr_str) + { + log_error(LOG_LEVEL_ERROR, + "Out of memory while getting the client's IP address."); + return 0; + } retval = getnameinfo((struct sockaddr *) &client, c_length, csp->ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (!csp->ip_addr_str || retval) @@ -1062,7 +1112,6 @@ unsigned long resolve_hostname_to_ip(const char *host) { struct sockaddr_in inaddr; struct hostent *hostp; - unsigned int dns_retries = 0; #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) || defined(HAVE_GETHOSTBYNAME_R_3_ARGS) struct hostent result; #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) @@ -1082,6 +1131,7 @@ unsigned long resolve_hostname_to_ip(const char *host) if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1) { + unsigned int dns_retries = 0; #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) while (gethostbyname_r(host, &result, hbuf, HOSTENT_BUFFER_SIZE, &hostp, &thd_err) @@ -1113,7 +1163,7 @@ unsigned long resolve_hostname_to_ip(const char *host) { hostp = NULL; } -#elif FEATURE_PTHREAD +#elif defined(MUTEX_LOCKS_AVAILABLE) privoxy_mutex_lock(&resolver_mutex); while (NULL == (hostp = gethostbyname(host)) && (h_errno == TRY_AGAIN) && (dns_retries++ < MAX_DNS_RETRIES)) @@ -1168,9 +1218,9 @@ unsigned long resolve_hostname_to_ip(const char *host) #ifdef FEATURE_CONNECTION_KEEP_ALIVE /********************************************************************* * - * Function : socket_is_still_usable + * Function : socket_is_still_alive * - * Description : Decides whether or not an open socket is still usable. + * Description : Figures out whether or not a socket is still alive. * * Parameters : * 1 : sfd = The socket to check. @@ -1178,8 +1228,11 @@ unsigned long resolve_hostname_to_ip(const char *host) * Returns : TRUE for yes, otherwise FALSE. * *********************************************************************/ -int socket_is_still_usable(jb_socket sfd) +int socket_is_still_alive(jb_socket sfd) { + char buf[10]; + int no_data_waiting; + #ifdef HAVE_POLL int poll_result; struct pollfd poll_fd[1]; @@ -1190,20 +1243,16 @@ int socket_is_still_usable(jb_socket sfd) poll_result = poll(poll_fd, 1, 0); - if (-1 != poll_result) - { - return !(poll_fd[0].revents & POLLIN); - } - else + if (-1 == poll_result) { log_error(LOG_LEVEL_CONNECT, "Polling socket %d failed.", sfd); return FALSE; } + no_data_waiting = !(poll_fd[0].revents & POLLIN); #else fd_set readable_fds; struct timeval timeout; int ret; - int socket_is_alive = 0; memset(&timeout, '\0', sizeof(timeout)); FD_ZERO(&readable_fds); @@ -1212,17 +1261,13 @@ int socket_is_still_usable(jb_socket sfd) ret = select((int)sfd+1, &readable_fds, NULL, NULL, &timeout); if (ret < 0) { - log_error(LOG_LEVEL_ERROR, "select() failed!: %E"); + log_error(LOG_LEVEL_CONNECT, "select() on socket %d failed: %E", sfd); + return FALSE; } - - /* - * XXX: I'm not sure why !FD_ISSET() works, - * but apparently it does. - */ - socket_is_alive = !FD_ISSET(sfd, &readable_fds); - - return socket_is_alive; + no_data_waiting = !FD_ISSET(sfd, &readable_fds); #endif /* def HAVE_POLL */ + + return (no_data_waiting || (1 == recv(sfd, buf, 1, MSG_PEEK))); } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */