working version
This commit is contained in:
parent
1eb9d49ae6
commit
b602d7c17f
105
connection.c
105
connection.c
@ -18,8 +18,9 @@ struct connection {
|
|||||||
struct sockaddr_in src_addr;
|
struct sockaddr_in src_addr;
|
||||||
struct sockaddr_in dst_addr;
|
struct sockaddr_in dst_addr;
|
||||||
|
|
||||||
int src_fd;
|
struct event_entry *src_event;
|
||||||
int dst_fd;
|
struct event_entry *dst_event;
|
||||||
|
struct event_entry *timeout;
|
||||||
|
|
||||||
time_t login_time;
|
time_t login_time;
|
||||||
};
|
};
|
||||||
@ -34,26 +35,26 @@ static struct connection * create_connection()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
con->src_fd = con->dst_fd = -1;
|
memset(con, 0, sizeof(struct connection));
|
||||||
con->src_addr.sin_addr.s_addr = con->src_addr.sin_addr.s_addr = 0;
|
|
||||||
con->src_addr.sin_port = con->src_addr.sin_port = 0;
|
|
||||||
con->login_time = time(NULL);
|
con->login_time = time(NULL);
|
||||||
|
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int destroy_connection(struct connection *con)
|
static int destroy_connection(struct connection *con)
|
||||||
{
|
{
|
||||||
// TODO: detroy connect-timeout?
|
if (con->timeout != NULL)
|
||||||
|
event_remove(con->timeout);
|
||||||
|
|
||||||
if (con->src_fd != -1) {
|
int src_fd = event_get_fd(con->src_event);
|
||||||
close(con->src_fd);
|
if (src_fd != -1) {
|
||||||
event_remove_fd(con->src_fd);
|
close(src_fd);
|
||||||
|
event_remove(con->src_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con->dst_fd != -1) {
|
int dst_fd = event_get_fd(con->dst_event);
|
||||||
close(con->dst_fd);
|
if (dst_fd != -1) {
|
||||||
event_remove_fd(con->dst_fd);
|
close(dst_fd);
|
||||||
|
event_remove(con->dst_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(con);
|
free(con);
|
||||||
@ -72,13 +73,16 @@ static int forward_handler(int fd, void *privdata)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int src_fd = event_get_fd(con->src_event);
|
||||||
|
int dst_fd = event_get_fd(con->dst_event);
|
||||||
|
|
||||||
/* client -> device */
|
/* client -> device */
|
||||||
if (con->src_fd == fd)
|
if (src_fd == fd && dst_fd != -1)
|
||||||
write(con->dst_fd, buf, len);
|
write(dst_fd, buf, len);
|
||||||
|
|
||||||
/* device -> client */
|
/* device -> client */
|
||||||
else if (con->dst_fd == fd)
|
if (dst_fd == fd && src_fd != -1)
|
||||||
write(con->src_fd, buf, len);
|
write(src_fd, buf, len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -94,10 +98,32 @@ static int connect_handler(int fd, void *privdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&con->dst_addr));
|
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 connect_handler */
|
/* everything from dst will be forwarded */
|
||||||
|
event_add_readfd(con->dst_event, 0, forward_handler, con);
|
||||||
|
|
||||||
|
/* remove connect_handler */
|
||||||
|
event_add_writefd(con->dst_event, 0, NULL, NULL);
|
||||||
|
|
||||||
|
/* remove timeout */
|
||||||
|
event_remove(con->timeout);
|
||||||
|
con->timeout = NULL;
|
||||||
|
|
||||||
|
log_print(LOG_DEBUG, "connect_handler(): exit");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int connect_timeout(void *privdata)
|
||||||
|
{
|
||||||
|
struct connection *con = (struct connection *)privdata;
|
||||||
|
|
||||||
|
log_print(LOG_INFO, "connect to %s timed out", get_sockaddr_buf(&con->dst_addr));
|
||||||
|
|
||||||
|
list_del(&con->list);
|
||||||
|
destroy_connection(con);
|
||||||
|
|
||||||
|
/* singleshot timer */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,21 +145,29 @@ static int client_handler(int fd, void *privdata)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check destination
|
// TODO: check destination
|
||||||
con->dst_fd = tcp_connect_socket(&con->dst_addr);
|
|
||||||
if (con->dst_fd < 0) {
|
int dst_fd = tcp_connect_socket(&con->dst_addr);
|
||||||
|
if (dst_fd < 0) {
|
||||||
list_del(&con->list);
|
list_del(&con->list);
|
||||||
destroy_connection(con);
|
destroy_connection(con);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: start connect timeout, callback destroys connection
|
|
||||||
|
|
||||||
log_print(LOG_INFO, "connecting to %s", get_sockaddr_buf(&con->dst_addr));
|
log_print(LOG_INFO, "connecting to %s", get_sockaddr_buf(&con->dst_addr));
|
||||||
event_add_writefd(con->dst_fd, connect_handler, con);
|
|
||||||
|
|
||||||
/* dismiss client_handler */
|
struct timeval tv;
|
||||||
return -1;
|
tv.tv_sec = 5;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
con->timeout = event_add_timeout(&tv, connect_timeout, con);
|
||||||
|
|
||||||
|
/* wait for connect() (non-blocking) */
|
||||||
|
con->dst_event = event_add_writefd(NULL, dst_fd, connect_handler, con);
|
||||||
|
|
||||||
|
/* everything from src will be forwarded */
|
||||||
|
event_add_readfd(con->src_event, 0, forward_handler, con);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int admin_handler(int fd, void *privdata)
|
static int admin_handler(int fd, void *privdata)
|
||||||
@ -151,9 +185,9 @@ static int admin_handler(int fd, void *privdata)
|
|||||||
if (strncmp(buf, "list", 4) == 0) {
|
if (strncmp(buf, "list", 4) == 0) {
|
||||||
struct connection *entry;
|
struct connection *entry;
|
||||||
list_for_each_entry(entry, &connection_list, list) {
|
list_for_each_entry(entry, &connection_list, list) {
|
||||||
len = snprintf(buf, sizeof(buf), "%d,", entry->src_fd);
|
len = snprintf(buf, sizeof(buf), "%d,", event_get_fd(entry->src_event));
|
||||||
len += get_sockaddr(&entry->src_addr, buf + len, sizeof(buf) - len);
|
len += get_sockaddr(&entry->src_addr, buf + len, sizeof(buf) - len);
|
||||||
len += snprintf(buf + len, sizeof(buf) - len, ",%d,", entry->dst_fd);
|
len += snprintf(buf + len, sizeof(buf) - len, ",%d,", event_get_fd(entry->dst_event));
|
||||||
len += get_sockaddr(&entry->dst_addr, buf + len, sizeof(buf) - len);
|
len += get_sockaddr(&entry->dst_addr, buf + len, sizeof(buf) - len);
|
||||||
len += snprintf(buf + len, sizeof(buf) - len, ",%ld\n", (time(NULL) - entry->login_time));
|
len += snprintf(buf + len, sizeof(buf) - len, ",%ld\n", (time(NULL) - entry->login_time));
|
||||||
write(fd, buf, len);
|
write(fd, buf, len);
|
||||||
@ -182,8 +216,8 @@ int listen_handler(int fd, void *privdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int i = sizeof(con->src_addr);
|
unsigned int i = sizeof(con->src_addr);
|
||||||
con->src_fd = accept(fd, (struct sockaddr *)&con->src_addr, &i);
|
int src_fd = accept(fd, (struct sockaddr *)&con->src_addr, &i);
|
||||||
if (con->src_fd < 0) {
|
if (src_fd < 0) {
|
||||||
free(con);
|
free(con);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -193,9 +227,10 @@ int listen_handler(int fd, void *privdata)
|
|||||||
list_add_tail(&con->list, &connection_list);
|
list_add_tail(&con->list, &connection_list);
|
||||||
|
|
||||||
if (mode == CON_ADMIN)
|
if (mode == CON_ADMIN)
|
||||||
event_add_readfd(con->src_fd, admin_handler, con);
|
con->src_event = event_add_readfd(NULL, src_fd, admin_handler, con);
|
||||||
else
|
|
||||||
event_add_readfd(con->src_fd, client_handler, con);
|
else if (mode == CON_NORMAL)
|
||||||
|
con->src_event = event_add_readfd(NULL, src_fd, client_handler, con);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
261
event.c
261
event.c
@ -29,58 +29,103 @@
|
|||||||
|
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
#define FD_TYPE (FD_READ | FD_WRITE | FD_EXCEPT)
|
static LIST_HEAD(event_fd_list);
|
||||||
#define FD_NEW 0x10
|
static LIST_HEAD(event_timeout_list);
|
||||||
#define FD_DELETE 0x20
|
|
||||||
|
|
||||||
static LIST_HEAD(fd_list);
|
struct event_entry {
|
||||||
static LIST_HEAD(timeout_list);
|
|
||||||
|
|
||||||
struct fd_entry {
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
int fd;
|
unsigned int flags;
|
||||||
int flags;
|
|
||||||
int (*callback)(int fd, void *privdata);
|
union {
|
||||||
void *privdata;
|
struct {
|
||||||
|
int fd;
|
||||||
|
int (*read_cb)(int fd, void *privdata);
|
||||||
|
int (*write_cb)(int fd, void *privdata);
|
||||||
|
void *read_priv;
|
||||||
|
void *write_priv;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
struct timeval intervall;
|
||||||
|
struct timeval nextrun;
|
||||||
|
int (*callback)(void *privdata);
|
||||||
|
void *privdata;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct timeout_entry {
|
struct event_entry * event_add_fd(
|
||||||
struct list_head list;
|
struct event_entry *entry,
|
||||||
struct timeval intervall;
|
int fd,
|
||||||
struct timeval nextrun;
|
int type,
|
||||||
int (*callback)(void *privdata);
|
int (*callback)(int fd, void *privdata),
|
||||||
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 || type == 0)
|
/* check valid filediskriptor */
|
||||||
return -1;
|
if (fd < 0 || fd > FD_SETSIZE) {
|
||||||
|
log_print(LOG_ERROR, "event_add_fd(): invalid fd");
|
||||||
struct fd_entry *entry;
|
return NULL;
|
||||||
entry = malloc(sizeof(struct fd_entry));
|
|
||||||
if (entry == NULL) {
|
|
||||||
log_print(LOG_ERROR, "event_add_fd(): out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->fd = fd;
|
/* check valid type (read/write) */
|
||||||
entry->flags = (type & FD_TYPE) | FD_NEW;
|
if (!(type & FD_TYPES)) {
|
||||||
entry->callback = callback;
|
log_print(LOG_ERROR, "event_add_fd(): invalid type");
|
||||||
entry->privdata = privdata;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
list_add_tail(&entry->list, &fd_list);
|
/* create new entry */
|
||||||
return 0;
|
if (entry == NULL) {
|
||||||
|
entry = malloc(sizeof(struct event_entry));
|
||||||
|
if (entry == NULL) {
|
||||||
|
log_print(LOG_ERROR, "event_add_fd(): out of memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->flags = EVENT_FD_CB;
|
||||||
|
entry->fd = fd;
|
||||||
|
|
||||||
|
/* put it on the list */
|
||||||
|
list_add_tail(&entry->list, &event_fd_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type & FD_READ) {
|
||||||
|
entry->flags = (callback != NULL) ? (entry->flags | FD_READ) : (entry->flags & ~FD_READ);
|
||||||
|
entry->read_cb = callback;
|
||||||
|
entry->read_priv = privdata;
|
||||||
|
|
||||||
|
} else if (type & FD_WRITE) {
|
||||||
|
entry->flags = (callback != NULL) ? (entry->flags | FD_WRITE) : (entry->flags & ~FD_WRITE);
|
||||||
|
entry->write_cb = callback;
|
||||||
|
entry->write_priv = privdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->flags |= EVENT_NEW;
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_remove_fd(int fd)
|
int event_get_fd(struct event_entry *entry)
|
||||||
{
|
{
|
||||||
struct fd_entry *entry, *tmp;
|
if (entry == NULL || !(entry->flags & EVENT_FD_CB))
|
||||||
list_for_each_entry_safe(entry, tmp, &fd_list, list) {
|
return -1;
|
||||||
if (entry->fd == fd)
|
|
||||||
entry->flags |= FD_DELETE;
|
return entry->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_remove_fd(int fd)
|
||||||
|
{
|
||||||
|
struct event_entry *entry, *tmp;
|
||||||
|
list_for_each_entry_safe(entry, tmp, &event_fd_list, list) {
|
||||||
|
if (entry->fd == fd) {
|
||||||
|
entry->flags |= EVENT_DELETE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_remove(struct event_entry *entry)
|
||||||
|
{
|
||||||
|
/* mark the event as deleted -> remove in select() loop */
|
||||||
|
entry->flags |= EVENT_DELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
|
static void add_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
|
||||||
@ -105,12 +150,29 @@ static void sub_timeval(struct timeval *ret, struct timeval *a, struct timeval *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void schedule_nextrun(struct timeout_entry *entry, struct timeval *now)
|
static int cmp_timeval(struct timeval *a, struct timeval *b)
|
||||||
|
{
|
||||||
|
if (a->tv_sec > b->tv_sec)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (a->tv_sec < b->tv_sec)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (a->tv_usec > b->tv_usec)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (a->tv_usec < b->tv_usec)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void schedule_nextrun(struct event_entry *entry, struct timeval *now)
|
||||||
{
|
{
|
||||||
add_timeval(&entry->nextrun, now, &entry->intervall);
|
add_timeval(&entry->nextrun, now, &entry->intervall);
|
||||||
|
|
||||||
struct timeout_entry *search;
|
struct event_entry *search;
|
||||||
list_for_each_entry(search, &timeout_list, list) {
|
list_for_each_entry(search, &event_timeout_list, list) {
|
||||||
if (search->nextrun.tv_sec > entry->nextrun.tv_sec) {
|
if (search->nextrun.tv_sec > entry->nextrun.tv_sec) {
|
||||||
list_add_tail(&entry->list, &search->list);
|
list_add_tail(&entry->list, &search->list);
|
||||||
return;
|
return;
|
||||||
@ -121,106 +183,108 @@ static void schedule_nextrun(struct timeout_entry *entry, struct timeval *now)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list_add_tail(&entry->list, &timeout_list);
|
list_add_tail(&entry->list, &event_timeout_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_add_timeout(struct timeval *timeout, int (*callback)(void *privdata), void *privdata)
|
struct event_entry * event_add_timeout(
|
||||||
|
struct timeval *timeout,
|
||||||
|
int (*callback)(void *privdata),
|
||||||
|
void *privdata)
|
||||||
{
|
{
|
||||||
struct timeout_entry *entry;
|
struct event_entry *entry;
|
||||||
entry = malloc(sizeof(struct timeout_entry));
|
entry = malloc(sizeof(struct event_entry));
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
log_print(LOG_ERROR, "event_add_timeout(): out of memory");
|
log_print(LOG_ERROR, "event_add_timeout(): out of memory");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry->flags = EVENT_TIMEOUT;
|
||||||
memcpy(&entry->intervall, timeout, sizeof(entry->intervall));
|
memcpy(&entry->intervall, timeout, sizeof(entry->intervall));
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
entry->privdata = privdata;
|
entry->privdata = privdata;
|
||||||
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
schedule_nextrun(entry, &now);
|
schedule_nextrun(entry, &now);
|
||||||
return 0;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_remove_timeout(int id)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int event_loop(void)
|
int event_loop(void)
|
||||||
{
|
{
|
||||||
fd_set *fdsets = malloc(sizeof(fd_set) * 3);
|
fd_set *fdsets = malloc(sizeof(fd_set) * 2);
|
||||||
if (fdsets == NULL) {
|
if (fdsets == NULL) {
|
||||||
log_print(LOG_ERROR, "event_loop(): out of memory");
|
log_print(LOG_ERROR, "event_loop(): out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
|
fd_set *readfds = NULL, *writefds = NULL;
|
||||||
struct fd_entry *entry, *tmp;
|
struct event_entry *entry, *tmp;
|
||||||
list_for_each_entry_safe(entry, tmp, &fd_list, list) {
|
|
||||||
entry->flags &= ~FD_NEW;
|
|
||||||
|
|
||||||
if (entry->flags & FD_DELETE) {
|
list_for_each_entry_safe(entry, tmp, &event_fd_list, list) {
|
||||||
|
entry->flags &= ~EVENT_NEW;
|
||||||
|
|
||||||
|
if (entry->flags & EVENT_DELETE) {
|
||||||
list_del(&entry->list);
|
list_del(&entry->list);
|
||||||
free(entry);
|
free(entry);
|
||||||
|
|
||||||
} else if ((entry->flags & FD_READ) != 0) {
|
} else if (entry->flags & FD_READ) {
|
||||||
if (readfds == NULL) {
|
if (readfds == NULL) {
|
||||||
readfds = &fdsets[0];
|
readfds = &fdsets[0];
|
||||||
FD_ZERO(readfds);
|
FD_ZERO(readfds);
|
||||||
}
|
}
|
||||||
FD_SET(entry->fd, readfds);
|
FD_SET(entry->fd, readfds);
|
||||||
|
|
||||||
} else if ((entry->flags & FD_WRITE) != 0) {
|
} else if (entry->flags & FD_WRITE) {
|
||||||
if (writefds == NULL) {
|
if (writefds == NULL) {
|
||||||
writefds = &fdsets[1];
|
writefds = &fdsets[1];
|
||||||
FD_ZERO(writefds);
|
FD_ZERO(writefds);
|
||||||
}
|
}
|
||||||
FD_SET(entry->fd, writefds);
|
FD_SET(entry->fd, writefds);
|
||||||
|
|
||||||
} else if ((entry->flags & FD_EXCEPT) != 0) {
|
|
||||||
if (exceptfds == NULL) {
|
|
||||||
exceptfds = &fdsets[2];
|
|
||||||
FD_ZERO(exceptfds);
|
|
||||||
}
|
|
||||||
FD_SET(entry->fd, exceptfds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeval timeout, *timeout_p = NULL;
|
struct timeval timeout, *timeout_p = NULL;
|
||||||
if (!list_empty(&timeout_list)) {
|
if (!list_empty(&event_timeout_list)) {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
struct timeout_entry *entry, *tmp;
|
struct event_entry *entry, *tmp;
|
||||||
list_for_each_entry_safe(entry, tmp, &timeout_list, list) {
|
list_for_each_entry_safe(entry, tmp, &event_timeout_list, list) {
|
||||||
/* timeout elapsed */
|
if (entry->flags & EVENT_DELETE) {
|
||||||
if (entry->nextrun.tv_sec < now.tv_sec ||
|
|
||||||
(entry->nextrun.tv_sec == now.tv_sec && entry->nextrun.tv_usec < now.tv_usec)) {
|
|
||||||
|
|
||||||
list_del(&entry->list);
|
list_del(&entry->list);
|
||||||
if (entry->callback(entry->privdata)) {
|
free(entry);
|
||||||
free(entry);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
/* timeout not elapsed, exit search (since list is sorted) */
|
||||||
schedule_nextrun(entry, &now);
|
if (cmp_timeval(&entry->nextrun, &now) == -1)
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
/* remove event from list */
|
||||||
|
list_del(&entry->list);
|
||||||
|
|
||||||
|
/* execute callback, when callback returns 0 -> schedule event again */
|
||||||
|
if (entry->callback(entry->privdata)) {
|
||||||
|
free(entry);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
schedule_nextrun(entry, &now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = list_entry(timeout_list.next, typeof(*entry), list);
|
if (!list_empty(&event_timeout_list)) {
|
||||||
|
entry = list_entry(event_timeout_list.next, typeof(*entry), list);
|
||||||
|
|
||||||
/* calc select() timeout */
|
/* calc select() timeout */
|
||||||
sub_timeval(&timeout, &entry->nextrun, &now);
|
sub_timeval(&timeout, &entry->nextrun, &now);
|
||||||
timeout_p = &timeout;
|
timeout_p = &timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = select(FD_SETSIZE, readfds, writefds, exceptfds, timeout_p);
|
int i = select(FD_SETSIZE, readfds, writefds, NULL, 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
|
||||||
@ -230,26 +294,19 @@ int event_loop(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
list_for_each_entry(entry, &fd_list, list) {
|
list_for_each_entry(entry, &event_fd_list, list) {
|
||||||
if ((entry->flags & FD_NEW) != 0) {
|
if ((entry->flags & EVENT_NEW) != 0) {
|
||||||
/* entry has just been added, execute it next round */
|
/* entry has just been added, execute it next round */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if ((entry->flags & FD_READ) != 0) {
|
|
||||||
if (!FD_ISSET(entry->fd, readfds))
|
|
||||||
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 (entry->callback(entry->fd, entry->privdata) != 0)
|
if ((entry->flags & FD_READ) && FD_ISSET(entry->fd, readfds))
|
||||||
entry->flags |= FD_DELETE;
|
if (entry->read_cb(entry->fd, entry->read_priv) != 0)
|
||||||
|
entry->flags |= EVENT_DELETE;
|
||||||
|
|
||||||
|
if ((entry->flags & FD_WRITE) && FD_ISSET(entry->fd, writefds))
|
||||||
|
if (entry->write_cb(entry->fd, entry->write_priv) != 0)
|
||||||
|
entry->flags |= EVENT_DELETE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
event.h
35
event.h
@ -3,23 +3,38 @@
|
|||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define EVENT_FD_CB 0x10000000
|
||||||
|
#define EVENT_TIMEOUT 0x20000000
|
||||||
|
|
||||||
|
#define EVENT_NEW 0x01000000
|
||||||
|
#define EVENT_DELETE 0x02000000
|
||||||
|
|
||||||
#define FD_READ 0x01
|
#define FD_READ 0x01
|
||||||
#define FD_WRITE 0x02
|
#define FD_WRITE 0x02
|
||||||
#define FD_EXCEPT 0x04
|
#define FD_TYPES (FD_READ | FD_WRITE)
|
||||||
|
|
||||||
#define event_add_readfd(fd, callback, privdata) \
|
#define event_add_readfd(entry, fd, callback, privdata) \
|
||||||
event_add_fd(fd, FD_READ, callback, privdata)
|
event_add_fd(entry, fd, FD_READ, callback, privdata)
|
||||||
|
|
||||||
#define event_add_writefd(fd, callback, privdata) \
|
#define event_add_writefd(entry, fd, callback, privdata) \
|
||||||
event_add_fd(fd, FD_WRITE, callback, privdata)
|
event_add_fd(entry, fd, FD_WRITE, callback, privdata)
|
||||||
|
|
||||||
#define event_add_exceptfd(fd, callback, privdata) \
|
struct event_entry * event_add_fd(
|
||||||
event_add_fd(fd, FD_EXCEPT, callback, privdata)
|
struct event_entry *entry,
|
||||||
|
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);
|
struct event_entry * event_add_timeout(
|
||||||
int event_add_timeout(struct timeval *timeout, int (*callback)(void *privdata), void *privdata);
|
struct timeval *timeout,
|
||||||
|
int (*callback)(void *privdata),
|
||||||
|
void *privdata);
|
||||||
|
|
||||||
int event_remove_fd(int fd);
|
int event_get_fd(struct event_entry *entry);
|
||||||
|
|
||||||
|
void event_remove_fd(int fd);
|
||||||
|
void event_remove(struct event_entry *entry);
|
||||||
|
|
||||||
int event_loop(void);
|
int event_loop(void);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ int tcp_connect_socket(struct sockaddr_in *sa)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non-blocking */
|
/* non-blocking connect() */
|
||||||
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK)) {
|
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK)) {
|
||||||
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
||||||
close(sock);
|
close(sock);
|
||||||
@ -111,7 +111,7 @@ int tcp_connect_socket(struct sockaddr_in *sa)
|
|||||||
/* reset EINPROGRESS */
|
/* reset EINPROGRESS */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
/* blocking */
|
/* all further actions are blocking */
|
||||||
if (fcntl(sock, F_SETFL, flags)) {
|
if (fcntl(sock, F_SETFL, flags)) {
|
||||||
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
log_print(LOG_ERROR, "tcp_connect_socket(): fcntl(F_SETFL)");
|
||||||
close(sock);
|
close(sock);
|
||||||
|
@ -24,20 +24,13 @@ static int listen_init(const char *value, void *privdata)
|
|||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
event_add_readfd(sock, listen_handler, privdata);
|
event_add_readfd(NULL, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int trigger(void *privdata)
|
|
||||||
{
|
|
||||||
log_print(LOG_DEBUG, "%s", (char *)privdata);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
if (config_parse("telnetproxy.conf") == -1)
|
if (config_parse("telnetproxy.conf") == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -52,16 +45,6 @@ int main(int argc, char *argv[])
|
|||||||
log_print(LOG_ERROR, "no admin_listen sockets defined!");
|
log_print(LOG_ERROR, "no admin_listen sockets defined!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
|
|
||||||
tv.tv_sec = 1;
|
|
||||||
event_add_timeout(&tv, trigger, "trigger 1");
|
|
||||||
tv.tv_sec = 2;
|
|
||||||
event_add_timeout(&tv, trigger, "trigger 2");
|
|
||||||
tv.tv_sec = 3;
|
|
||||||
event_add_timeout(&tv, trigger, "trigger 3");
|
|
||||||
|
|
||||||
event_loop();
|
event_loop();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user