From 639e929021a1095208ff4d0dc0ffc931fb0efa38 Mon Sep 17 00:00:00 2001 From: Arnaud Cornet Date: Mon, 15 Feb 2010 14:06:50 +0000 Subject: [PATCH] Fix antiflood. Fixes freenode kicking us out. --- configure.ac | 2 +- src/connection.c | 95 +++++++++++++++++++++++------------------------- src/connection.h | 1 - src/irc.c | 6 ++- 4 files changed, 51 insertions(+), 53 deletions(-) diff --git a/configure.ac b/configure.ac index a442877..2ce6ce0 100644 --- a/configure.ac +++ b/configure.ac @@ -55,7 +55,7 @@ AS_IF([test "x$enable_debug" = "xyes"], [ CFLAGS="-O2 -g -W -Wall" LDFLAGS="-g" ]) -AS_IF([test "x$enable_debug" = "xyes"], [ +AS_IF([test "x$enable_oidentd" = "xyes"], [ AC_DEFINE([HAVE_OIDENTD], [], [Have bip edit ~/.oidentd.conf]) ]) AM_CONDITIONAL(OIDENTD, test x$enable_identd = xyes) diff --git a/src/connection.c b/src/connection.c index 748a8b0..e6dc0cd 100644 --- a/src/connection.c +++ b/src/connection.c @@ -32,6 +32,7 @@ int link_add_untrusted(void *ls, X509 *cert); static int connection_timedout(connection_t *cn); static int socket_set_nonblock(int s); static void connection_connected(connection_t *c); +int cn_want_write(connection_t *cn); struct connecting_data { @@ -291,6 +292,7 @@ static int real_write_all(connection_t *cn) if (cn == NULL) fatal("real_write_all: wrong arguments"); + if (cn->partial) { line = cn->partial; cn->partial = NULL; @@ -299,7 +301,10 @@ static int real_write_all(connection_t *cn) } do { - ret = write_socket(cn, line); + if (!cn_want_write(cn)) + ret = WRITE_KEEP; + else + ret = write_socket(cn, line); switch (ret) { case WRITE_ERROR: @@ -318,10 +323,6 @@ static int real_write_all(connection_t *cn) fatal("internal error 6"); break; } - - if (cn->anti_flood) - /* one line at a time */ - break; } while ((line = list_remove_first(cn->outgoing))); return 0; } @@ -720,49 +721,47 @@ static int check_event_write(fd_set *fds, connection_t *cn, int *nc) int cn_want_write(connection_t *cn) { - if (cn->anti_flood) { - struct timeval tv; - unsigned long now; + struct timeval tv; + unsigned long now; - /* fill the bucket */ - /* we do not control when we are called */ - /* now is the number of milliseconds since the Epoch, - * cn->lasttoken is the number of milliseconds when we - * last added a token to the bucket */ - if (!gettimeofday(&tv, NULL)) { - now = tv.tv_sec * 1000 + tv.tv_usec / 1000; - /* round now to TOKEN_INTERVAL multiple */ - now -= now % TOKEN_INTERVAL; - if (now < cn->lasttoken) { - /* time shift or integer overflow */ - cn->token = 1; - cn->lasttoken = now; - } else if (now > cn->lasttoken + TOKEN_INTERVAL) { - cn->token += (now - cn->lasttoken) / - TOKEN_INTERVAL; - if (cn->token > TOKEN_MAX) - cn->token = TOKEN_MAX; - if (!cn->token) - cn->token = 1; - cn->lasttoken = now; - } - } else - /* if gettimeofday() fails, juste ignore - * antiflood */ + /* fill the bucket */ + /* we do not control when we are called */ + /* now is the number of milliseconds since the Epoch, + * cn->lasttoken is the number of milliseconds when we + * last added a token to the bucket */ + if (!gettimeofday(&tv, NULL)) { + now = tv.tv_sec * 1000 + tv.tv_usec / 1000; + /* round now to TOKEN_INTERVAL multiple */ + now -= now % TOKEN_INTERVAL; + if (now < cn->lasttoken) { + /* time shift or integer overflow */ cn->token = 1; - - /* use a token if needed and available */ - if (!list_is_empty(cn->outgoing) && cn->token > 0) { - cn->token--; - return 1; + cn->lasttoken = now; + } else if (now > cn->lasttoken + TOKEN_INTERVAL) { + cn->token += (now - cn->lasttoken) / + TOKEN_INTERVAL; + if (cn->token > TOKEN_MAX) + cn->token = TOKEN_MAX; + if (!cn->token) + cn->token = 1; + cn->lasttoken = now; } - return 0; + } else + /* if gettimeofday() fails, juste ignore + * antiflood */ + cn->token = 1; + + /* use a token if needed and available */ + if (!list_is_empty(cn->outgoing) && cn->token > 0) { + cn->token--; + return 1; } - return !list_is_empty(cn->outgoing); + return 0; } list_t *wait_event(list_t *cn_list, int *msec, int *nc) { + fd_set fds_read, fds_write, fds_except; int maxfd = -1, err; list_t *cn_newdata; @@ -817,7 +816,7 @@ list_t *wait_event(list_t *cn_list, int *msec, int *nc) if (cn->listening) continue; - if (!cn_is_connected(cn) || cn_want_write(cn)) { + if (!cn_is_connected(cn) || !list_is_empty(cn->outgoing)) { FD_SET(cn->handle, &fds_write); mylog(LOG_DEBUGTOOMUCH, "Test write on fd %d %d:%d", cn->handle, cn->connected, @@ -1001,8 +1000,7 @@ static void create_listening_socket(char *hostname, char *port, cn->connected = CONN_ERROR; } -static connection_t *connection_init(int anti_flood, int ssl, int timeout, - int listen) +static connection_t *connection_init(int ssl, int timeout, int listen) { connection_t *conn; char *incoming; @@ -1012,7 +1010,6 @@ static connection_t *connection_init(int anti_flood, int ssl, int timeout, incoming = (char *)bip_malloc(CONN_BUFFER_SIZE); outgoing = list_new(NULL); - conn->anti_flood = anti_flood; conn->ssl = ssl; conn->lasttoken = 0; conn->token = TOKEN_MAX; @@ -1119,7 +1116,7 @@ connection_t *accept_new(connection_t *cn) } socket_set_nonblock(err); - conn = connection_init(cn->anti_flood, cn->ssl, cn->timeout, 0); + conn = connection_init(cn->ssl, cn->timeout, 0); conn->connect_time = time(NULL); conn->user_data = cn->user_data; conn->handle = err; @@ -1175,7 +1172,7 @@ connection_t *listen_new(char *hostname, int port, int ssl) * SSL flag is only here to tell program to convert socket to SSL after * accept(). Listening socket will NOT be SSL */ - conn = connection_init(0, ssl, 0, 1); + conn = connection_init(ssl, 0, 1); create_listening_socket(hostname, portbuf, conn); return conn; @@ -1186,7 +1183,7 @@ static connection_t *_connection_new(char *dsthostname, char *dstport, { connection_t *conn; - conn = connection_init(1, 0, timeout, 0); + conn = connection_init(0, timeout, 0); create_socket(dsthostname, dstport, srchostname, srcport, conn); return conn; @@ -1411,7 +1408,7 @@ static connection_t *_connection_new_SSL(char *dsthostname, char *dstport, { connection_t *conn; - conn = connection_init(1, 1, timeout, 0); + conn = connection_init(1, timeout, 0); if (!(conn->ssl_ctx_h = SSL_init_context())) { mylog(LOG_ERROR, "SSL context initialization failed"); return conn; @@ -1575,7 +1572,7 @@ int main(int argc,char* argv[]) fprintf(stderr,"Usage: %s host port\n",argv[0]); exit(1); } - conn = connection_init(0, 0, 0, 1); + conn = connection_init(0, 0, 1); conn->connect_time = time(NULL); create_listening_socket(argv[1],argv[2],&conn); if (s == -1) { diff --git a/src/connection.h b/src/connection.h index 5fa7d2e..ff4bab0 100644 --- a/src/connection.h +++ b/src/connection.h @@ -63,7 +63,6 @@ struct connecting_data; typedef struct connection { - int anti_flood; int ssl; unsigned long lasttoken; unsigned token; diff --git a/src/irc.c b/src/irc.c index 556bf97..bf8ebce 100644 --- a/src/irc.c +++ b/src/irc.c @@ -219,9 +219,10 @@ static void irc_server_connected(struct link_server *server) mylog(LOG_INFO, "[%s] Connected for user %s", LINK(server)->name, LINK(server)->user->name); - irc_server_join(server); log_connected(LINK(server)->log); + CONN(server)->token = 1; + if (LINK(server)->cli_nick) { /* we change nick on client */ for (i = 0; i < LINK(server)->l_clientc; i++) { @@ -252,6 +253,7 @@ static void irc_server_connected(struct link_server *server) WRITE_LINE1(CONN(server), NULL, "AWAY", LINK(server)->no_client_away_msg); } + irc_server_join(server); } /* @@ -408,7 +410,7 @@ int irc_dispatch_server(bip_t *bip, struct link_server *server, if (irc_line_elem_equals(line, 0, "376")) /* end of motd */ irc_server_connected(server); else if (irc_line_elem_equals(line, 0, "422")) /* no motd */ - irc_server_connected(server); + irc_server_connected(server); } else if (LINK(server)->s_state == IRCS_CONNECTING) { ret = OK_FORGET;