diff options
author | Christian Pointner <equinox@spreadspace.org> | 2010-11-28 21:49:51 +0000 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2010-11-28 21:49:51 +0000 |
commit | 21203e393c36d9c079491fb0644b9bce32f71758 (patch) | |
tree | d65a1ff398c29e9c7fb398544c266ccafd14acc1 /src/clients.c | |
parent | one side of cleint connections works for recv (diff) |
first minial version working
git-svn-id: https://svn.spreadspace.org/tcpproxy/trunk@12 e61f0598-a718-4e21-a8f0-0aadfa62ad6b
Diffstat (limited to 'src/clients.c')
-rw-r--r-- | src/clients.c | 93 |
1 files changed, 78 insertions, 15 deletions
diff --git a/src/clients.c b/src/clients.c index a4b58b3..9e5c9fc 100644 --- a/src/clients.c +++ b/src/clients.c @@ -35,6 +35,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/select.h> +#include <netinet/in.h> #include "clients.h" #include "tcp.h" @@ -47,7 +48,7 @@ void clients_delete_element(void* e) client_t* element = (client_t*)e; close(element->fd_[0]); -// close(element->fd_[1]); + close(element->fd_[1]); free(e); } @@ -74,14 +75,35 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t* remote_end) return -2; } + element->write_buf_len_[0] = 0; + element->write_buf_len_[1] = 0; element->fd_[0] = fd; - element->fd_[1] = 0; -// TODO: open new socket -// element->fd_[1] = socket(...); + + element->fd_[1] = socket(remote_end->ss_family, SOCK_STREAM, 0); + if(element->fd_[1] < 0) { + log_printf(INFO, "Error on socket(): %s, not adding client %d", strerror(errno), element->fd_[0]); + close(element->fd_[0]); + free(element); + return -1; + } + + socklen_t socklen = sizeof(*remote_end); + if(remote_end->ss_family == AF_INET) + socklen = sizeof(struct sockaddr_in); + else if (remote_end->ss_family == AF_INET6) + socklen = sizeof(struct sockaddr_in6); + + if(connect(element->fd_[1], (struct sockaddr *)remote_end, socklen)==-1) { + log_printf(INFO, "Error on connect(): %s, not adding client %d", strerror(errno), element->fd_[0]); + close(element->fd_[0]); + close(element->fd_[1]); + free(element); + return -1; + } if(slist_add(list, element) == NULL) { close(element->fd_[0]); -// close(element->fd_[1]); + close(element->fd_[1]); free(element); return -2; } @@ -136,9 +158,9 @@ void clients_read_fds(clients_t* list, fd_set* set, int* max_fd) client_t* c = (client_t*)tmp->data_; if(c) { FD_SET(c->fd_[0], set); -// FD_SET(c->fd_[1], set); + FD_SET(c->fd_[1], set); *max_fd = *max_fd > c->fd_[0] ? *max_fd : c->fd_[0]; -// *max_fd = *max_fd > c->fd_[1] ? *max_fd : c->fd_[1]; + *max_fd = *max_fd > c->fd_[1] ? *max_fd : c->fd_[1]; } tmp = tmp->next_; } @@ -149,7 +171,21 @@ void clients_write_fds(clients_t* list, fd_set* set, int* max_fd) if(!list) return; - // TODO: add all clients with pending data + slist_element_t* tmp = list->first_; + while(tmp) { + client_t* c = (client_t*)tmp->data_; + if(c) { + if(c->write_buf_len_[0]) { + FD_SET(c->fd_[0], set); + *max_fd = *max_fd > c->fd_[0] ? *max_fd : c->fd_[0]; + } + if(c->write_buf_len_[1]) { + FD_SET(c->fd_[1], set); + *max_fd = *max_fd > c->fd_[1] ? *max_fd : c->fd_[1]; + } + } + tmp = tmp->next_; + } } int clients_read(clients_t* list, fd_set* set) @@ -173,20 +209,18 @@ int clients_read(clients_t* list, fd_set* set) } else continue; - u_int8_t* buffer[1024]; - int len = recv(c->fd_[in], buffer, sizeof(buffer), 0); + // TODO: what when buffer is full? + int len = recv(c->fd_[in], &(c->write_buf_[out][c->write_buf_len_[out]]), BUFFER_LENGTH - c->write_buf_len_[out], 0); if(len < 0) { log_printf(INFO, "Error on recv(): %s, removing client %d", strerror(errno), c->fd_[0]); slist_remove(list, c); } else if(!len) { - log_printf(INFO, "client %d closed connection", c->fd_[0]); + log_printf(INFO, "client %d closed connection, removing it", c->fd_[0]); slist_remove(list, c); } - else { - log_printf(INFO, "client %d: read %d bytes", c->fd_[0], len); - // TODO: add data to write buffer of l->fd_[out] - } + else + c->write_buf_len_[out] += len; } } @@ -195,5 +229,34 @@ int clients_read(clients_t* list, fd_set* set) int clients_write(clients_t* list, fd_set* set) { + if(!list) + return -1; + + slist_element_t* tmp = list->first_; + while(tmp) { + client_t* c = (client_t*)tmp->data_; + tmp = tmp->next_; + if(c) { + int i; + for(i=0; i<2; ++i) { + if(FD_ISSET(c->fd_[i], set)) { + int len = send(c->fd_[i], c->write_buf_[i], c->write_buf_len_[i], 0); + if(len < 0) { + log_printf(INFO, "Error on send(): %s, removing client %d", strerror(errno), c->fd_[0]); + slist_remove(list, c); + } + else { + if(c->write_buf_len_[i] > len) { + memmove(c->write_buf_[i], &c->write_buf_[i][len], c->write_buf_len_[i] - len); + c->write_buf_len_[i] -= len; + } + else + c->write_buf_len_[i] = 0; + } + } + } + } + } + return 0; } |