diff options
author | Christian Pointner <equinox@spreadspace.org> | 2010-11-27 05:39:07 +0000 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2010-11-27 05:39:07 +0000 |
commit | df849a6ae44fe40ac67a649cccbdb5af5af1bf23 (patch) | |
tree | 1df1379ba06a91b47a689ffc18edb85fd6781365 /src | |
parent | listening 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
Diffstat (limited to 'src')
-rw-r--r-- | src/listener.c | 56 | ||||
-rw-r--r-- | src/listener.h | 5 | ||||
-rw-r--r-- | src/tcpproxy.c | 23 |
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); |