X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jbsockets.c;h=06202a94fbdf10f1f48bda6d955c9631ed938794;hp=f502ebe8998e01c436f8fcdcdaa50b42d76cbc28;hb=08f3b18a3cb223cad6e3925ba1021206fd59d37e;hpb=b04a51574a3ddc6db9e5d340e08730cc5e659ee5 diff --git a/jbsockets.c b/jbsockets.c index f502ebe8..06202a94 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1,4 +1,3 @@ -const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.147 2017/06/26 12:12:55 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $ @@ -9,7 +8,7 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.147 2017/06/26 12:12:55 fabia * on many platforms. * * Copyright : Written by and Copyright (C) 2001-2017 the - * Privoxy team. http://www.privoxy.org/ + * Privoxy team. https://www.privoxy.org/ * * Based on the Internet Junkbuster originally written * by and Copyright (C) 1997 Anonymous Coders and @@ -57,9 +56,7 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.147 2017/06/26 12:12:55 fabia #else -#ifndef __OS2__ #include -#endif #include #include #include @@ -68,20 +65,11 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.147 2017/06/26 12:12:55 fabia #ifndef __BEOS__ #include -#ifndef __OS2__ #include -#endif #else #include #endif -#if defined(__EMX__) || defined (__OS2__) -#include /* OS/2/EMX needs a little help with select */ -#ifdef __OS2__ -#include -#endif -#endif - #endif #ifdef HAVE_POLL @@ -107,8 +95,6 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.147 2017/06/26 12:12:55 fabia #define AI_NUMERICSERV 0 #endif -const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; - /* * Maximum number of gethostbyname(_r) retries in case of * soft errors (TRY_AGAIN). @@ -210,18 +196,13 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client char service[6]; int retval; jb_socket fd; -#ifdef HAVE_POLL struct pollfd poll_fd[1]; -#else - fd_set wfds; - struct timeval timeout; -#endif -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) int flags; #endif int connect_failed; /* - * XXX: Initializeing it here is only necessary + * XXX: Initializing it here is only necessary * because not all situations are properly * covered yet. */ @@ -257,10 +238,10 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client { 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->error_message = strdup(gai_strerror(retval)); csp->http->host_ip_addr_str = strdup("unknown"); + /* XXX: Should find a better way to propagate this error. */ + errno = EINVAL; return(JB_INVALID_SOCKET); } @@ -274,11 +255,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client if (block_acl(dst, csp)) { -#ifdef __OS2__ - socket_error = errno = SOCEPERM; -#else socket_error = errno = EPERM; -#endif continue; } #endif /* def FEATURE_ACL */ @@ -303,46 +280,28 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client continue; } -#ifndef HAVE_POLL -#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); - freeaddrinfo(result); - return JB_INVALID_SOCKET; - } -#endif -#endif - #ifdef FEATURE_EXTERNAL_FILTERS mark_socket_for_close_on_execute(fd); #endif set_no_delay_flag(fd); -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) if ((flags = fcntl(fd, F_GETFL, 0)) != -1) { flags |= O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) */ connect_failed = 0; while (connect(fd, rp->ai_addr, rp->ai_addrlen) == JB_INVALID_SOCKET) { -#ifdef __OS2__ - errno = sock_errno(); -#endif /* __OS2__ */ - #ifdef _WIN32 if (errno == WSAEINPROGRESS) #else /* ifndef _WIN32 */ if (errno == EINPROGRESS) -#endif /* ndef _WIN32 || __OS2__ */ +#endif /* ndef _WIN32 */ { break; } @@ -360,15 +319,14 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client continue; } -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) if (flags != -1) { flags &= ~O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) */ -#ifdef HAVE_POLL poll_fd[0].fd = fd; poll_fd[0].events = POLLOUT; @@ -392,18 +350,6 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client } } else if (retval > 0) -#else - /* wait for connection to complete */ - FD_ZERO(&wfds); - FD_SET(fd, &wfds); - - memset(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = 30; - - /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */ - if ((select((int)fd + 1, NULL, &wfds, NULL, &timeout) > 0) - && FD_ISSET(fd, &wfds)) -#endif { socklen_t optlen = sizeof(socket_error); if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, &socket_error, &optlen)) @@ -461,13 +407,8 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli struct sockaddr_in inaddr; jb_socket fd; unsigned int addr; -#ifdef HAVE_POLL struct pollfd poll_fd[1]; -#else - fd_set wfds; - struct timeval tv[1]; -#endif -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) int flags; #endif @@ -492,11 +433,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli if (block_acl(dst, csp)) { -#ifdef __OS2__ - errno = SOCEPERM; -#else errno = EPERM; -#endif return(JB_INVALID_SOCKET); } #endif /* def FEATURE_ACL */ @@ -528,22 +465,9 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli return(JB_INVALID_SOCKET); } -#ifndef HAVE_POLL -#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 -#endif - set_no_delay_flag(fd); -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) if ((flags = fcntl(fd, F_GETFL, 0)) != -1) { flags |= O_NDELAY; @@ -552,56 +476,38 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli mark_socket_for_close_on_execute(fd); #endif } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) */ while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET) { #ifdef _WIN32 if (errno == WSAEINPROGRESS) -#elif __OS2__ - if (sock_errno() == EINPROGRESS) #else /* ifndef _WIN32 */ if (errno == EINPROGRESS) -#endif /* ndef _WIN32 || __OS2__ */ +#endif /* ndef _WIN32 */ { break; } -#ifdef __OS2__ - if (sock_errno() != EINTR) -#else if (errno != EINTR) -#endif /* __OS2__ */ { close_socket(fd); return(JB_INVALID_SOCKET); } } -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) if (flags != -1) { flags &= ~O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) */ -#ifdef HAVE_POLL poll_fd[0].fd = fd; poll_fd[0].events = POLLOUT; if (poll(poll_fd, 1, 30000) <= 0) -#else - /* wait for connection to complete */ - FD_ZERO(&wfds); - FD_SET(fd, &wfds); - - tv->tv_sec = 30; - tv->tv_usec = 0; - - /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */ - if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0) -#endif { close_socket(fd); return(JB_INVALID_SOCKET); @@ -627,11 +533,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli * nonzero on error. * *********************************************************************/ -#ifdef AMIGA -int write_socket(jb_socket fd, const char *buf, ssize_t len) -#else int write_socket(jb_socket fd, const char *buf, size_t len) -#endif { if (len == 0) { @@ -650,32 +552,65 @@ int write_socket(jb_socket fd, const char *buf, size_t len) #if defined(_WIN32) return (send(fd, buf, (int)len, 0) != (int)len); -#elif defined(__BEOS__) || defined(AMIGA) +#elif defined(__BEOS__) return (send(fd, buf, len, 0) != len); -#elif defined(__OS2__) - /* - * Break the data up into SOCKET_SEND_MAX chunks for sending... - * OS/2 seemed to complain when the chunks were too large. - */ -#define SOCKET_SEND_MAX 65000 +#else + return (write(fd, buf, len) != len); +#endif + +} + + +/********************************************************************* + * + * Function : write_socket_delayed + * + * Description : Write the contents of buf (for n bytes) to + * socket fd, optionally delaying the operation. + * + * Parameters : + * 1 : fd = File descriptor (aka. handle) of socket to write to. + * 2 : buf = Pointer to data to be written. + * 3 : len = Length of data to be written to the socket "fd". + * 4 : delay = Delay in milliseconds. + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +int write_socket_delayed(jb_socket fd, const char *buf, size_t len, unsigned int delay) +{ + size_t i = 0; + + if (delay == 0) { - int send_len, send_rc = 0, i = 0; - while ((i < len) && (send_rc != -1)) + return write_socket(fd, buf, len); + } + + while (i < len) + { + size_t write_length; + enum {MAX_WRITE_LENGTH = 10}; + + if ((i + MAX_WRITE_LENGTH) > len) { - if ((i + SOCKET_SEND_MAX) > len) - send_len = len - i; - else - send_len = SOCKET_SEND_MAX; - send_rc = send(fd,(char*)buf + i, send_len, 0); - if (send_rc == -1) - return 1; - i = i + send_len; + write_length = len - i; } - return 0; + else + { + write_length = MAX_WRITE_LENGTH; + } + + privoxy_millisleep(delay); + + if (write_socket(fd, buf + i, write_length) != 0) + { + return 1; + } + i += write_length; } -#else - return (write(fd, buf, len) != len); -#endif + + return 0; } @@ -716,7 +651,7 @@ int read_socket(jb_socket fd, char *buf, int len) #if defined(_WIN32) ret = recv(fd, buf, len, 0); -#elif defined(__BEOS__) || defined(AMIGA) || defined(__OS2__) +#elif defined(__BEOS__) ret = recv(fd, buf, (size_t)len, 0); #else ret = (int)read(fd, buf, (size_t)len); @@ -749,30 +684,12 @@ int data_is_available(jb_socket fd, int seconds_to_wait) { int n; char buf[10]; -#ifdef HAVE_POLL struct pollfd poll_fd[1]; poll_fd[0].fd = fd; poll_fd[0].events = POLLIN; n = poll(poll_fd, 1, seconds_to_wait * 1000); -#else - fd_set rfds; - struct timeval timeout; - - memset(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = seconds_to_wait; - -#ifdef __OS2__ - /* Copy and pasted from jcc.c ... */ - memset(&rfds, 0, sizeof(fd_set)); -#else - FD_ZERO(&rfds); -#endif - FD_SET(fd, &rfds); - - n = select(fd+1, &rfds, NULL, NULL, &timeout); -#endif /* * XXX: Do we care about the different error conditions? @@ -797,10 +714,6 @@ void close_socket(jb_socket fd) { #if defined(_WIN32) || defined(__BEOS__) closesocket(fd); -#elif defined(AMIGA) - CloseSocket(fd); -#elif defined(__OS2__) - soclose(fd); #else close(fd); #endif @@ -1023,6 +936,10 @@ int bind_port(const char *hostnam, int portnum, int backlog, jb_socket *pfd) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); #endif /* ndef _WIN32 */ +#ifdef IP_FREEBIND + setsockopt(fd, IPPROTO_IP, IP_FREEBIND, (char *)&one, sizeof(one)); +#endif + #ifdef HAVE_RFC2553 if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0) #else @@ -1121,7 +1038,7 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, struct sockaddr_in server; struct hostent *host = NULL; #endif /* HAVE_RFC2553 */ -#if defined(_WIN32) || defined(__OS2__) || defined(AMIGA) +#if defined(_WIN32) /* according to accept_connection() this fixes a warning. */ int s_length, s_length_provided; #else @@ -1273,8 +1190,8 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) struct sockaddr_in client; #endif jb_socket afd; -#if defined(_WIN32) || defined(__OS2__) || defined(AMIGA) - /* Wierdness - fix a warning. */ +#if defined(_WIN32) + /* Weirdness - fix a warning. */ int c_length; #else socklen_t c_length; @@ -1282,41 +1199,24 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) int retval; int i; int max_selected_socket; -#ifdef HAVE_POLL struct pollfd poll_fds[MAX_LISTENING_SOCKETS]; nfds_t polled_sockets; -#else - fd_set selected_fds; -#endif jb_socket fd; const char *host_addr; size_t listen_addr_size; c_length = sizeof(client); -#ifdef HAVE_POLL memset(poll_fds, 0, sizeof(poll_fds)); polled_sockets = 0; -#else - /* - * Wait for a connection on any socket. - * Return immediately if no socket is listening. - * XXX: Why not treat this as fatal error? - */ - FD_ZERO(&selected_fds); -#endif max_selected_socket = 0; for (i = 0; i < MAX_LISTENING_SOCKETS; i++) { if (JB_INVALID_SOCKET != fds[i]) { -#ifdef HAVE_POLL poll_fds[i].fd = fds[i]; poll_fds[i].events = POLLIN; polled_sockets++; -#else - FD_SET(fds[i], &selected_fds); -#endif if (max_selected_socket < fds[i] + 1) { max_selected_socket = fds[i] + 1; @@ -1329,38 +1229,29 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) } do { -#ifdef HAVE_POLL retval = poll(poll_fds, polled_sockets, -1); -#else - retval = select(max_selected_socket, &selected_fds, NULL, NULL, NULL); -#endif } while (retval < 0 && errno == EINTR); if (retval <= 0) { if (0 == retval) { log_error(LOG_LEVEL_ERROR, - "Waiting on new client failed because select(2) returned 0." + "Waiting on new client failed because poll(2) returned 0." " This should not happen."); } else { log_error(LOG_LEVEL_ERROR, - "Waiting on new client failed because of problems in select(2): " + "Waiting on new client failed because of problems in poll(2): " "%s.", strerror(errno)); } return 0; } -#ifdef HAVE_POLL for (i = 0; i < MAX_LISTENING_SOCKETS && (poll_fds[i].revents == 0); i++); -#else - for (i = 0; i < MAX_LISTENING_SOCKETS && !FD_ISSET(fds[i], &selected_fds); - i++); -#endif if (i >= MAX_LISTENING_SOCKETS) { log_error(LOG_LEVEL_ERROR, - "select(2) reported connected clients (number = %u, " + "poll(2) reported connected clients (number = %u, " "descriptor boundary = %u), but none found.", retval, max_selected_socket); return 0; @@ -1397,19 +1288,6 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) } #endif -#ifndef HAVE_POLL -#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 -#endif - #ifdef FEATURE_EXTERNAL_FILTERS mark_socket_for_close_on_execute(afd); #endif @@ -1448,7 +1326,7 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) { log_error(LOG_LEVEL_ERROR, "Server name (%s) and port number (%d) ASCII decimal representation" - "don't fit into %d bytes", + "don't fit into %lu bytes", host_addr, csp->config->hport[i], listen_addr_size); return 0; } @@ -1590,7 +1468,6 @@ 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]; @@ -1606,23 +1483,6 @@ int socket_is_still_alive(jb_socket sfd) return FALSE; } no_data_waiting = !(poll_fd[0].revents & POLLIN); -#else - fd_set readable_fds; - struct timeval timeout; - int ret; - - memset(&timeout, '\0', sizeof(timeout)); - FD_ZERO(&readable_fds); - FD_SET(sfd, &readable_fds); - - ret = select((int)sfd+1, &readable_fds, NULL, NULL, &timeout); - if (ret < 0) - { - log_error(LOG_LEVEL_CONNECT, "select() on socket %d failed: %E", sfd); - return FALSE; - } - no_data_waiting = !FD_ISSET(sfd, &readable_fds); -#endif /* def HAVE_POLL */ return (no_data_waiting || (1 == recv(sfd, buf, 1, MSG_PEEK))); }