summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2013-11-08 08:07:08 +0100
committerMichael Adam <obnox@samba.org>2013-11-09 13:34:33 +0100
commit2ebfd456eff002cfba45aa88dad4b2a0cb9edc1a (patch)
treebf59f92d58694bfc3a5da14fd40e7cef61db38e2
parent070d6215340379cbea7cc404ff4bb450a0ddea8b (diff)
downloadtinyproxy-2ebfd456eff002cfba45aa88dad4b2a0cb9edc1a.tar.gz
tinyproxy-2ebfd456eff002cfba45aa88dad4b2a0cb9edc1a.zip
child: use a list of listen_fds instead of one single listenfd.
This prepares listenting on multiple sockets, which will be ussed to fix listening on the wildcard (listen on both ipv6 and ipv4) and help add the support for multiple Listen statements in the config Signed-off-by: Michael Adam <obnox@samba.org>
-rw-r--r--src/child.c86
-rw-r--r--src/sock.c7
-rw-r--r--src/sock.h4
3 files changed, 90 insertions, 7 deletions
diff --git a/src/child.c b/src/child.c
index 144b032..c7490fd 100644
--- a/src/child.c
+++ b/src/child.c
@@ -32,7 +32,7 @@
#include "utils.h"
#include "conf.h"
-static int listenfd;
+static vector_t listen_fds;
/*
* Stores the internal data needed for each child (connection)
@@ -186,6 +186,10 @@ static void child_main (struct child_s *ptr)
int connfd;
struct sockaddr *cliaddr;
socklen_t clilen;
+ fd_set rfds;
+ int maxfd = 0;
+ ssize_t i;
+ int ret;
cliaddr = (struct sockaddr *)
safemalloc (sizeof(struct sockaddr_storage));
@@ -197,11 +201,65 @@ static void child_main (struct child_s *ptr)
ptr->connects = 0;
+ /*
+ * We have to wait for connections on multiple fds,
+ * so use select.
+ */
+
+ FD_ZERO(&rfds);
+
+ for (i = 0; i < vector_length(listen_fds); i++) {
+ int *fd = (int *) vector_getentry(listen_fds, i, NULL);
+
+ socket_nonblocking(*fd);
+ FD_SET(*fd, &rfds);
+ maxfd = max(maxfd, *fd);
+ }
+
while (!config.quit) {
+ int listenfd = -1;
+
ptr->status = T_WAITING;
clilen = sizeof(struct sockaddr_storage);
+ ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
+ if (ret == -1) {
+ log_message (LOG_ERR, "error calling select: %s",
+ strerror(errno));
+ exit(1);
+ } else if (ret == 0) {
+ log_message (LOG_WARNING, "Strange: select returned 0 "
+ "but we did not specify a timeout...");
+ continue;
+ }
+
+ for (i = 0; i < vector_length(listen_fds); i++) {
+ int *fd = (int *) vector_getentry(listen_fds, i, NULL);
+
+ if (FD_ISSET(*fd, &rfds)) {
+ /*
+ * only accept the connection on the first
+ * fd that we find readable. - fair?
+ */
+ listenfd = *fd;
+ break;
+ }
+ }
+
+ if (listenfd == -1) {
+ log_message(LOG_WARNING, "Strange: None of our listen "
+ "fds was readable after select");
+ continue;
+ }
+
+ socket_blocking(listenfd);
+
+ /*
+ * We have a socket that is readable.
+ * Continue handling this connection.
+ */
+
connfd = accept (listenfd, cliaddr, &clilen);
#ifndef NDEBUG
@@ -466,11 +524,31 @@ void child_kill_children (int sig)
int child_listening_sock (const char *addr, uint16_t port)
{
- listenfd = listen_sock (addr, port);
- return listenfd;
+ int ret;
+
+ if (listen_fds == NULL) {
+ listen_fds = vector_create();
+ if (listen_fds == NULL) {
+ log_message (LOG_ERR, "Could not create the list "
+ "of listening fds");
+ return -1;
+ }
+ }
+
+ ret = listen_sock (addr, port, listen_fds);
+ return ret;
}
void child_close_sock (void)
{
- close (listenfd);
+ ssize_t i;
+
+ for (i = 0; i < vector_length(listen_fds); i++) {
+ int *fd = (int *) vector_getentry(listen_fds, i, NULL);
+ close (*fd);
+ }
+
+ vector_delete(listen_fds);
+
+ listen_fds = NULL;
}
diff --git a/src/sock.c b/src/sock.c
index fe28de6..d2db37b 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -166,7 +166,7 @@ int socket_blocking (int sock)
* Start listening on a socket. Create a socket with the selected port.
* The socket fd is returned upon success, -1 upon error.
*/
-int listen_sock (const char *addr, uint16_t port)
+int listen_sock (const char *addr, uint16_t port, vector_t listen_fds)
{
struct addrinfo hints, *result, *rp;
char portstr[6];
@@ -174,6 +174,7 @@ int listen_sock (const char *addr, uint16_t port)
const int on = 1;
assert (port > 0);
+ assert (listen_fds != NULL);
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC;
@@ -224,9 +225,11 @@ int listen_sock (const char *addr, uint16_t port)
return -1;
}
+ vector_append(listen_fds, &listenfd, sizeof(int));
+
freeaddrinfo (result);
- return listenfd;
+ return 0;
}
/*
diff --git a/src/sock.h b/src/sock.h
index 5cca744..f1225ea 100644
--- a/src/sock.h
+++ b/src/sock.h
@@ -28,8 +28,10 @@
#define MAXLINE (1024 * 4)
+#include "vector.h"
+
extern int opensock (const char *host, int port, const char *bind_to);
-extern int listen_sock (const char *addr, uint16_t port);
+extern int listen_sock (const char *addr, uint16_t port, vector_t listen_fds);
extern int socket_nonblocking (int sock);
extern int socket_blocking (int sock);