get it working
This commit is contained in:
parent
78ecedcc4e
commit
5bdb9d85fb
144
connection.c
144
connection.c
@ -1,5 +1,149 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
|
struct connection {
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
struct sockaddr_in dst_addr;
|
||||||
|
|
||||||
|
int src_fd;
|
||||||
|
int dst_fd;
|
||||||
|
|
||||||
|
unsigned long login_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LIST_HEAD(connection_list);
|
||||||
|
|
||||||
|
static struct connection * create_connection()
|
||||||
|
{
|
||||||
|
struct connection *con = malloc(sizeof(struct connection));
|
||||||
|
if (con == NULL) {
|
||||||
|
log_print(LOG_WARN, "listen_handler(): out of memory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->src_fd = con->dst_fd = -1;
|
||||||
|
con->login_time = time(NULL);
|
||||||
|
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int destroy_connection(struct connection *con)
|
||||||
|
{
|
||||||
|
if (con->src_fd != -1) {
|
||||||
|
close(con->src_fd);
|
||||||
|
event_remove_fd(con->src_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->dst_fd != -1) {
|
||||||
|
close(con->dst_fd);
|
||||||
|
event_remove_fd(con->dst_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(con);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int forward_handler(int fd, void *privdata)
|
||||||
|
{
|
||||||
|
struct connection *con = (struct connection *)privdata;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
int len = read(fd, buf, sizeof(buf));
|
||||||
|
if (len <= 0) {
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client -> device */
|
||||||
|
if (con->src_fd == fd)
|
||||||
|
write(con->dst_fd, buf, len);
|
||||||
|
|
||||||
|
/* device -> client */
|
||||||
|
else if (con->dst_fd == fd)
|
||||||
|
write(con->src_fd, buf, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_handler(int fd, void *privdata)
|
||||||
|
{
|
||||||
|
struct connection *con = (struct connection *)privdata;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
int len = read(fd, buf, sizeof(buf));
|
||||||
|
if (len <= 0) {
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_saddr(buf, &con->dst_addr) != 0) {
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check destination
|
||||||
|
con->dst_fd = tcp_connect_socket(&con->dst_addr);
|
||||||
|
if (con->dst_fd < 0) {
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr));
|
||||||
|
event_add_readfd(con->dst_fd, forward_handler, con);
|
||||||
|
event_add_readfd(con->src_fd, forward_handler, con);
|
||||||
|
|
||||||
|
/* dismiss client_handler */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int admin_handler(int fd, void *privdata)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int listen_handler(int fd, void *privdata)
|
||||||
|
{
|
||||||
|
int mode = (int)privdata;
|
||||||
|
|
||||||
|
struct connection *con = create_connection();
|
||||||
|
if (con == NULL) {
|
||||||
|
log_print(LOG_WARN, "listen_handler(): out of memory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int i = sizeof(con->src_addr);
|
||||||
|
con->src_fd = accept(fd, (struct sockaddr *)&con->src_addr, &i);
|
||||||
|
if (con->src_fd < 0) {
|
||||||
|
free(con);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print(LOG_INFO, "accepted connection from %s", get_sockaddr_buf(&con->src_addr));
|
||||||
|
|
||||||
|
list_add_tail(&con->list, &connection_list);
|
||||||
|
|
||||||
|
if (mode == CON_ADMIN)
|
||||||
|
event_add_readfd(con->src_fd, client_handler, con);
|
||||||
|
else
|
||||||
|
event_add_readfd(con->src_fd, admin_handler, con);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
20
connection.h
20
connection.h
@ -1,23 +1,9 @@
|
|||||||
#ifndef _CONNECTION_H_
|
#ifndef _CONNECTION_H_
|
||||||
#define _CONNECTION_H_
|
#define _CONNECTION_H_
|
||||||
|
|
||||||
#include <netinet/ip.h>
|
#define CON_NORMAL 0x01
|
||||||
|
#define CON_ADMIN 0x02
|
||||||
|
|
||||||
#include "list.h"
|
int listen_handler(int fd, void *privdata);
|
||||||
|
|
||||||
struct connection {
|
|
||||||
struct list_head list;
|
|
||||||
|
|
||||||
struct sockaddr_in src_addr;
|
|
||||||
struct sockaddr_in dst_addr;
|
|
||||||
|
|
||||||
int src_fd;
|
|
||||||
int dst_fd;
|
|
||||||
|
|
||||||
unsigned long login_time;
|
|
||||||
unsigned long idle_time;
|
|
||||||
|
|
||||||
char user[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _CONNECTION_H_
|
#endif // _CONNECTION_H_
|
||||||
|
196
event.c
196
event.c
@ -29,15 +29,17 @@
|
|||||||
|
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
static LIST_HEAD(readfd_list);
|
#define FD_TYPE (FD_READ | FD_WRITE | FD_EXCEPT)
|
||||||
static LIST_HEAD(writefd_list);
|
#define FD_NEW 0x10
|
||||||
static LIST_HEAD(exceptfd_list);
|
#define FD_DELETE 0x20
|
||||||
|
|
||||||
|
static LIST_HEAD(fd_list);
|
||||||
static LIST_HEAD(timeout_list);
|
static LIST_HEAD(timeout_list);
|
||||||
|
|
||||||
struct fd_entry {
|
struct fd_entry {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
int fd;
|
int fd;
|
||||||
int type;
|
int flags;
|
||||||
int (*callback)(int fd, void *privdata);
|
int (*callback)(int fd, void *privdata);
|
||||||
void *privdata;
|
void *privdata;
|
||||||
};
|
};
|
||||||
@ -52,7 +54,7 @@ struct timeout_entry {
|
|||||||
|
|
||||||
int event_add_fd(int fd, int type, int (*callback)(int fd, void *privdata), void *privdata)
|
int event_add_fd(int fd, int type, int (*callback)(int fd, void *privdata), void *privdata)
|
||||||
{
|
{
|
||||||
if (fd < 0 || fd > FD_SETSIZE)
|
if (fd < 0 || fd > FD_SETSIZE || type == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
struct fd_entry *entry;
|
struct fd_entry *entry;
|
||||||
@ -63,59 +65,23 @@ int event_add_fd(int fd, int type, int (*callback)(int fd, void *privdata), void
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry->fd = fd;
|
entry->fd = fd;
|
||||||
entry->type = type;
|
entry->flags = (type & FD_TYPE) | FD_NEW;
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
entry->privdata = privdata;
|
entry->privdata = privdata;
|
||||||
|
|
||||||
switch (type) {
|
list_add_tail(&entry->list, &fd_list);
|
||||||
case FD_READ:
|
|
||||||
list_add_tail(&entry->list, &readfd_list);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FD_WRITE:
|
|
||||||
list_add_tail(&entry->list, &writefd_list);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FD_EXCEPT:
|
|
||||||
list_add_tail(&entry->list, &exceptfd_list);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log_print(LOG_ERROR, "add_fd(): unknown type");
|
|
||||||
free(entry);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_remove_fd(int fd)
|
int event_remove_fd(int fd)
|
||||||
{
|
{
|
||||||
struct fd_entry *entry, *tmp;
|
struct fd_entry *entry, *tmp;
|
||||||
list_for_each_entry_safe(entry, tmp, &readfd_list, list) {
|
list_for_each_entry_safe(entry, tmp, &fd_list, list) {
|
||||||
if (entry->fd == fd) {
|
if (entry->fd == fd) {
|
||||||
list_del(&entry->list);
|
entry->flags |= FD_DELETE;
|
||||||
free(entry);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(entry, tmp, &writefd_list, list) {
|
|
||||||
if (entry->fd == fd) {
|
|
||||||
list_del(&entry->list);
|
|
||||||
free(entry);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_safe(entry, tmp, &exceptfd_list, list) {
|
|
||||||
if (entry->fd == fd) {
|
|
||||||
list_del(&entry->list);
|
|
||||||
free(entry);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,44 +149,52 @@ int event_add_timeout(struct timeval *timeout, int (*callback)(void *privdata),
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_loop(void)
|
int event_loop(void)
|
||||||
{
|
{
|
||||||
|
fd_set *fdsets = malloc(sizeof(fd_set) * 3);
|
||||||
|
if (fdsets == NULL) {
|
||||||
|
log_print(LOG_ERROR, "event_loop(): out of memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fd_set readfds, *readfds_p = NULL;
|
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
|
||||||
fd_set writefds, *writefds_p = NULL;
|
struct fd_entry *entry, *tmp;
|
||||||
fd_set exceptfds, *exceptfds_p =NULL;
|
list_for_each_entry_safe(entry, tmp, &fd_list, list) {
|
||||||
|
entry->flags &= ~FD_NEW;
|
||||||
|
|
||||||
|
if (entry->flags & FD_DELETE) {
|
||||||
|
log_print(LOG_DEBUG, "event_loop: delete FD: %d (%p/%p)", entry->fd, entry->callback, entry->privdata);
|
||||||
|
list_del(&entry->list);
|
||||||
|
free(entry);
|
||||||
|
|
||||||
|
} else if ((entry->flags & FD_READ) != 0) {
|
||||||
|
if (readfds == NULL) {
|
||||||
|
readfds = &fdsets[0];
|
||||||
|
FD_ZERO(readfds);
|
||||||
|
}
|
||||||
|
log_print(LOG_DEBUG, "event_loop: read FD: %d (%p/%p)", entry->fd, entry->callback, entry->privdata);
|
||||||
|
FD_SET(entry->fd, readfds);
|
||||||
|
|
||||||
|
} else if ((entry->flags & FD_WRITE) != 0) {
|
||||||
|
if (writefds == NULL) {
|
||||||
|
writefds = &fdsets[1];
|
||||||
|
FD_ZERO(writefds);
|
||||||
|
}
|
||||||
|
log_print(LOG_DEBUG, "event_loop: write FD: %d (%p/%p)", entry->fd, entry->callback, entry->privdata);
|
||||||
|
FD_SET(entry->fd, writefds);
|
||||||
|
|
||||||
|
} else if ((entry->flags & FD_EXCEPT) != 0) {
|
||||||
|
if (exceptfds == NULL) {
|
||||||
|
exceptfds = &fdsets[2];
|
||||||
|
FD_ZERO(exceptfds);
|
||||||
|
}
|
||||||
|
log_print(LOG_DEBUG, "event_loop: except FD: %d (%p/%p)", entry->fd, entry->callback, entry->privdata);
|
||||||
|
FD_SET(entry->fd, exceptfds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct timeval timeout, *timeout_p = NULL;
|
struct timeval timeout, *timeout_p = NULL;
|
||||||
|
|
||||||
if (!list_empty(&readfd_list)) {
|
|
||||||
struct fd_entry *entry;
|
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
list_for_each_entry(entry, &readfd_list, list)
|
|
||||||
FD_SET(entry->fd, &readfds);
|
|
||||||
|
|
||||||
readfds_p = &readfds;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!list_empty(&writefd_list)) {
|
|
||||||
struct fd_entry *entry;
|
|
||||||
|
|
||||||
FD_ZERO(&writefds);
|
|
||||||
list_for_each_entry(entry, &writefd_list, list)
|
|
||||||
FD_SET(entry->fd, &writefds);
|
|
||||||
|
|
||||||
writefds_p = &writefds;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!list_empty(&exceptfd_list)) {
|
|
||||||
struct fd_entry *entry;
|
|
||||||
|
|
||||||
FD_ZERO(&exceptfds);
|
|
||||||
list_for_each_entry(entry, &exceptfd_list, list)
|
|
||||||
FD_SET(entry->fd, &exceptfds);
|
|
||||||
|
|
||||||
exceptfds_p = &exceptfds;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!list_empty(&timeout_list)) {
|
if (!list_empty(&timeout_list)) {
|
||||||
struct timeout_entry *entry, *tmp;
|
struct timeout_entry *entry, *tmp;
|
||||||
list_for_each_entry_safe(entry, tmp, &timeout_list, list) {
|
list_for_each_entry_safe(entry, tmp, &timeout_list, list) {
|
||||||
@ -244,13 +218,15 @@ void event_loop(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = select(FD_SETSIZE, readfds_p, writefds_p, exceptfds_p, timeout_p);
|
log_print(LOG_DEBUG, "");
|
||||||
|
|
||||||
|
int i = select(FD_SETSIZE, readfds, writefds, exceptfds, timeout_p);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
/* On error, -1 is returned, and errno is set
|
/* On error, -1 is returned, and errno is set
|
||||||
* appropriately; the sets and timeout become
|
* appropriately; the sets and timeout become
|
||||||
* undefined, so do not rely on their contents
|
* undefined, so do not rely on their contents
|
||||||
* after an error.
|
* after an error.
|
||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (i == 0 && !list_empty(&timeout_list)) {
|
} else if (i == 0 && !list_empty(&timeout_list)) {
|
||||||
@ -266,45 +242,29 @@ void event_loop(void)
|
|||||||
} else {
|
} else {
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (readfds_p) {
|
} else {
|
||||||
struct fd_entry *entry, *tmp;
|
list_for_each_entry(entry, &fd_list, list) {
|
||||||
list_for_each_entry_safe(entry, tmp, &readfd_list, list) {
|
if ((entry->flags & FD_NEW) != 0) {
|
||||||
if (!FD_ISSET(entry->fd, &readfds))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (entry->callback(entry->fd, entry->privdata) != 0) {
|
} else if ((entry->flags & FD_READ) != 0) {
|
||||||
list_del(&entry->list);
|
if (!FD_ISSET(entry->fd, readfds))
|
||||||
free(entry);
|
continue;
|
||||||
|
|
||||||
|
} else if ((entry->flags & FD_WRITE) != 0) {
|
||||||
|
if (!FD_ISSET(entry->fd, writefds))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if ((entry->flags & FD_EXCEPT) != 0) {
|
||||||
|
if (!FD_ISSET(entry->fd, exceptfds))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writefds_p) {
|
if (entry->callback(entry->fd, entry->privdata) != 0)
|
||||||
struct fd_entry *entry, *tmp;
|
entry->flags |= FD_DELETE;
|
||||||
list_for_each_entry_safe(entry, tmp, &writefd_list, list) {
|
|
||||||
if (FD_ISSET(entry->fd, &writefds))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (entry->callback(entry->fd, entry->privdata) != 0) {
|
|
||||||
list_del(&entry->list);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exceptfds_p) {
|
|
||||||
struct fd_entry *entry, *tmp;
|
|
||||||
list_for_each_entry_safe(entry, tmp, &exceptfd_list, list) {
|
|
||||||
if (FD_ISSET(entry->fd, &exceptfds))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (entry->callback(entry->fd, entry->privdata) != 0) {
|
|
||||||
list_del(&entry->list);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(fdsets);
|
||||||
}
|
}
|
||||||
|
2
event.h
2
event.h
@ -21,6 +21,6 @@ int event_add_timeout(struct timeval *timeout, int (*callback)(void *privdata),
|
|||||||
|
|
||||||
int event_remove_fd(int fd);
|
int event_remove_fd(int fd);
|
||||||
|
|
||||||
void event_loop(void);
|
int event_loop(void);
|
||||||
|
|
||||||
#endif /* _EVENT_H_ */
|
#endif /* _EVENT_H_ */
|
||||||
|
20
network.c
20
network.c
@ -48,7 +48,7 @@ char * get_sockaddr_buf(struct sockaddr_in *sa)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcp_listen_socket(struct sockaddr_in *sa, int cnt)
|
int tcp_listen_socket(struct sockaddr_in *sa)
|
||||||
{
|
{
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sock < 0 ) {
|
if (sock < 0 ) {
|
||||||
@ -69,10 +69,26 @@ int tcp_listen_socket(struct sockaddr_in *sa, int cnt)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(sock, cnt)) {
|
if (listen(sock, 8)) {
|
||||||
log_print(LOG_ERROR, "tcp_listen_socket(): listen()");
|
log_print(LOG_ERROR, "tcp_listen_socket(): listen()");
|
||||||
close(sock);
|
close(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tcp_connect_socket(struct sockaddr_in *sa)
|
||||||
|
{
|
||||||
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0 ) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): socket()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(sock, (struct sockaddr *)sa, sizeof(*sa))) {
|
||||||
|
log_print(LOG_ERROR, "tcp_connect_socket(): bind(%s)", get_sockaddr_buf(sa));
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
int parse_saddr(const char *addr, struct sockaddr_in *sa);
|
int parse_saddr(const char *addr, struct sockaddr_in *sa);
|
||||||
int tcp_listen_socket(struct sockaddr_in *sa, int cnt);
|
int tcp_listen_socket(struct sockaddr_in *sa);
|
||||||
|
int tcp_connect_socket(struct sockaddr_in *sa);
|
||||||
|
|
||||||
int get_sockaddr(struct sockaddr_in *sa, char *buf, int size);
|
int get_sockaddr(struct sockaddr_in *sa, char *buf, int size);
|
||||||
char * get_sockaddr_buf(struct sockaddr_in *sa);
|
char * get_sockaddr_buf(struct sockaddr_in *sa);
|
||||||
|
@ -5,83 +5,9 @@
|
|||||||
#include "configfile.h"
|
#include "configfile.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "list.h"
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
|
||||||
static LIST_HEAD(connection_list);
|
|
||||||
|
|
||||||
static int server_handler(int fd, void *privdata)
|
|
||||||
{
|
|
||||||
struct connection *con = (struct connection *)privdata;
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
int len = read(fd, buf, sizeof(buf));
|
|
||||||
if (len <= 0) {
|
|
||||||
list_del(&con->list);
|
|
||||||
destroy_connection(con);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
write(con->src_fd, buf, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int client_handler(int fd, void *privdata)
|
|
||||||
{
|
|
||||||
struct connection *con = (struct connection *)privdata;
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
int len = read(fd, buf, sizeof(buf));
|
|
||||||
if (len <= 0) {
|
|
||||||
list_del(&con->list);
|
|
||||||
destroy_connection(con);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (con->dst_fd != -1) {
|
|
||||||
write(con->dst_fd, buf, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check destination
|
|
||||||
int sock = tcp_connect_socket(&con->dst_addr);
|
|
||||||
if (sock < 0) {
|
|
||||||
list_del(&con->list);
|
|
||||||
destroy_connection(con);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
event_add_readfd(sock, server_handler, con);
|
|
||||||
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int listen_handler(int fd, void *privdata)
|
|
||||||
{
|
|
||||||
struct connection *con = malloc(sizeof(struct connection));
|
|
||||||
if (con == NULL) {
|
|
||||||
log_print(LOG_WARN, "listen_handler(): out of memory");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = sizeof(con->src_addr);
|
|
||||||
con->src_fd = accept(fd, (struct sockaddr *)&con->src_addr, &i);
|
|
||||||
if (con->src_fd < 0) {
|
|
||||||
free(con);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
con->dst_fd = -1;
|
|
||||||
con->login_time = con->idle_time = time(NULL);
|
|
||||||
|
|
||||||
log_print(LOG_INFO, "accepted connection from %s", get_sockaddr_buf(&con->src_addr));
|
|
||||||
|
|
||||||
list_add_tail(&con->list, &connection_list);
|
|
||||||
event_add_readfd(con->src_fd, client_handler, con);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int listen_init(const char *value, void *privdata)
|
static int listen_init(const char *value, void *privdata)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
@ -91,11 +17,11 @@ static int listen_init(const char *value, void *privdata)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sock = tcp_listen_socket(&addr, 10);
|
int sock = tcp_listen_socket(&addr);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
event_add_readfd(sock, listen_handler, NULL);
|
event_add_readfd(sock, listen_handler, privdata);
|
||||||
log_print(LOG_INFO, "listen on %s", get_sockaddr_buf(&addr));
|
log_print(LOG_INFO, "listen on %s", get_sockaddr_buf(&addr));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -105,12 +31,18 @@ int main(int argc, char *argv[])
|
|||||||
if (config_parse("telnetproxy.conf") == -1)
|
if (config_parse("telnetproxy.conf") == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int cnt = config_get_strings("global", "listen", listen_init, NULL);
|
int cnt = config_get_strings("global", "listen", listen_init, (void*)CON_NORMAL);
|
||||||
if (cnt <= 0) {
|
if (cnt <= 0) {
|
||||||
log_print(LOG_ERROR, "no listen sockets defined!");
|
log_print(LOG_ERROR, "no listen sockets defined!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cnt = config_get_strings("global", "admin_listen", listen_init, (void*)CON_ADMIN);
|
||||||
|
if (cnt <= 0) {
|
||||||
|
log_print(LOG_ERROR, "no admin_listen sockets defined!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
event_loop();
|
event_loop();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
[global]
|
[global]
|
||||||
listen 0.0.0.0:8000
|
listen 0.0.0.0:8000
|
||||||
|
admin_listen 0.0.0.0:8001
|
||||||
|
Loading…
Reference in New Issue
Block a user