summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-27 05:39:07 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-27 05:39:07 +0000
commitdf849a6ae44fe40ac67a649cccbdb5af5af1bf23 (patch)
tree1df1379ba06a91b47a689ffc18edb85fd6781365
parentlistening on tcp sockets works now (diff)
added REUSEADDR to listen sockets
added accept handler git-svn-id: https://svn.spreadspace.org/tcpproxy/trunk@9 e61f0598-a718-4e21-a8f0-0aadfa62ad6b
-rw-r--r--src/listener.c56
-rw-r--r--src/listener.h5
-rw-r--r--src/tcpproxy.c23
3 files changed, 73 insertions, 11 deletions
diff --git a/src/listener.c b/src/listener.c
index 07428bc..b607bdf 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -35,6 +35,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <sys/select.h>
#include "listener.h"
#include "tcp.h"
@@ -99,8 +100,15 @@ int listener_add(listeners_t* list, const char* laddr, const char* lport, const
break;
}
+ int on = 1;
+ ret = setsockopt(element->fd_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ if(ret) {
+ log_printf(ERROR, "Error on setsockopt(): %s", strerror(errno));
+ close(element->fd_);
+ free(element);
+ break;
+ }
if(l->ai_family == AF_INET6) {
- int on = 1;
if(setsockopt(element->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
log_printf(WARNING, "failed to set IPV6_V6ONLY socket option: %s", strerror(errno));
}
@@ -181,3 +189,49 @@ void listener_print(listeners_t* list)
tmp = tmp->next_;
}
}
+
+void listener_read_fds(listeners_t* list, fd_set* set, int* max_fd)
+{
+ if(!list)
+ return;
+
+ slist_element_t* tmp = list->first_;
+ while(tmp) {
+ listener_t* l = (listener_t*)tmp->data_;
+ if(l) {
+ FD_SET(l->fd_, set);
+ *max_fd = *max_fd > l->fd_ ? *max_fd : l->fd_;
+ }
+ tmp = tmp->next_;
+ }
+}
+
+int listener_handle_accept(listeners_t* list, fd_set* set)
+{
+ if(!list)
+ return -1;
+
+ slist_element_t* tmp = list->first_;
+ while(tmp) {
+ listener_t* l = (listener_t*)tmp->data_;
+ if(l && FD_ISSET(l->fd_, set)) {
+ tcp_endpoint_t remote_addr;
+ int alen = sizeof(remote_addr);
+ int new_client = accept(l->fd_, (struct sockaddr *)&remote_addr, &alen);
+ if(new_client == -1) {
+ log_printf(ERROR, "Error on accept(): %s", strerror(errno));
+ return -1;
+ }
+ char* rs = tcp_endpoint_to_string(remote_addr);
+ log_printf(INFO, "new client from %s (fd=%d)", rs ? rs:"(null)", new_client);
+ if(rs) free(rs);
+ FD_CLR(l->fd_, set);
+
+ // TODO add client to client list
+ close(new_client);
+ }
+ tmp = tmp->next_;
+ }
+
+ return 0;
+}
diff --git a/src/listener.h b/src/listener.h
index 2bd5dc8..475af83 100644
--- a/src/listener.h
+++ b/src/listener.h
@@ -28,6 +28,8 @@
#ifndef TCPPROXY_listener_h_INCLUDED
#define TCPPROXY_listener_h_INCLUDED
+#include <sys/select.h>
+
#include "slist.h"
#include "tcp.h"
@@ -48,4 +50,7 @@ void listener_remove(listeners_t* list, int fd);
listener_t* listener_find(listeners_t* list, int fd);
void listener_print(listeners_t* list);
+void listener_read_fds(listeners_t* list, fd_set* set, int* max_fd);
+int listener_handle_accept(listeners_t* list, fd_set* set);
+
#endif
diff --git a/src/tcpproxy.c b/src/tcpproxy.c
index d55277e..d82b057 100644
--- a/src/tcpproxy.c
+++ b/src/tcpproxy.c
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <sys/select.h>
#include "datatypes.h"
#include "options.h"
@@ -38,7 +39,7 @@
#include "listener.h"
-int main_loop(options_t* opt)
+int main_loop(options_t* opt, listeners_t* listeners)
{
log_printf(INFO, "entering main loop");
@@ -47,14 +48,13 @@ int main_loop(options_t* opt)
if(sig_fd < 0)
return_value -1;
- fd_set readfds, readyfds;
- FD_ZERO(&readfds);
- FD_SET(sig_fd, &readfds);
- int nfds = (nfds < sig_fd) ? sig_fd : nfds;
-
while(!return_value) {
- memcpy(&readyfds, &readfds, sizeof(readyfds));
- int ret = select(nfds + 1, &readyfds, NULL, NULL, NULL);
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(sig_fd, &readfds);
+ int nfds = sig_fd;
+ listener_read_fds(listeners, &readfds, &nfds);
+ int ret = select(nfds + 1, &readfds, NULL, NULL, NULL);
if(ret == -1 && errno != EINTR) {
log_printf(ERROR, "select returned with error: %s", strerror(errno));
return_value = -1;
@@ -63,12 +63,15 @@ int main_loop(options_t* opt)
if(!ret || ret == -1)
continue;
- if(FD_ISSET(sig_fd, &readyfds)) {
+ if(FD_ISSET(sig_fd, &readfds)) {
if(signal_handle()) {
return_value = 1;
break;
}
}
+
+ return_value = listener_handle_accept(listeners, &readfds);
+ if(return_value) break;
}
signal_stop();
@@ -182,7 +185,7 @@ int main(int argc, char* argv[])
fclose(pid_file);
}
- ret = main_loop(&opt);
+ ret = main_loop(&opt, &listeners);
listener_clear(&listeners);
options_clear(&opt);