Fix antiflood. Fixes freenode kicking us out.

This commit is contained in:
Arnaud Cornet 2010-02-15 14:06:50 +00:00
parent bfe14ebb20
commit 639e929021
4 changed files with 51 additions and 53 deletions

View File

@ -55,7 +55,7 @@ AS_IF([test "x$enable_debug" = "xyes"], [
CFLAGS="-O2 -g -W -Wall" CFLAGS="-O2 -g -W -Wall"
LDFLAGS="-g" 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]) AC_DEFINE([HAVE_OIDENTD], [], [Have bip edit ~/.oidentd.conf])
]) ])
AM_CONDITIONAL(OIDENTD, test x$enable_identd = xyes) AM_CONDITIONAL(OIDENTD, test x$enable_identd = xyes)

View File

@ -32,6 +32,7 @@ int link_add_untrusted(void *ls, X509 *cert);
static int connection_timedout(connection_t *cn); static int connection_timedout(connection_t *cn);
static int socket_set_nonblock(int s); static int socket_set_nonblock(int s);
static void connection_connected(connection_t *c); static void connection_connected(connection_t *c);
int cn_want_write(connection_t *cn);
struct connecting_data struct connecting_data
{ {
@ -291,6 +292,7 @@ static int real_write_all(connection_t *cn)
if (cn == NULL) if (cn == NULL)
fatal("real_write_all: wrong arguments"); fatal("real_write_all: wrong arguments");
if (cn->partial) { if (cn->partial) {
line = cn->partial; line = cn->partial;
cn->partial = NULL; cn->partial = NULL;
@ -299,7 +301,10 @@ static int real_write_all(connection_t *cn)
} }
do { do {
ret = write_socket(cn, line); if (!cn_want_write(cn))
ret = WRITE_KEEP;
else
ret = write_socket(cn, line);
switch (ret) { switch (ret) {
case WRITE_ERROR: case WRITE_ERROR:
@ -318,10 +323,6 @@ static int real_write_all(connection_t *cn)
fatal("internal error 6"); fatal("internal error 6");
break; break;
} }
if (cn->anti_flood)
/* one line at a time */
break;
} while ((line = list_remove_first(cn->outgoing))); } while ((line = list_remove_first(cn->outgoing)));
return 0; 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) int cn_want_write(connection_t *cn)
{ {
if (cn->anti_flood) { struct timeval tv;
struct timeval tv; unsigned long now;
unsigned long now;
/* fill the bucket */ /* fill the bucket */
/* we do not control when we are called */ /* we do not control when we are called */
/* now is the number of milliseconds since the Epoch, /* now is the number of milliseconds since the Epoch,
* cn->lasttoken is the number of milliseconds when we * cn->lasttoken is the number of milliseconds when we
* last added a token to the bucket */ * last added a token to the bucket */
if (!gettimeofday(&tv, NULL)) { if (!gettimeofday(&tv, NULL)) {
now = tv.tv_sec * 1000 + tv.tv_usec / 1000; now = tv.tv_sec * 1000 + tv.tv_usec / 1000;
/* round now to TOKEN_INTERVAL multiple */ /* round now to TOKEN_INTERVAL multiple */
now -= now % TOKEN_INTERVAL; now -= now % TOKEN_INTERVAL;
if (now < cn->lasttoken) { if (now < cn->lasttoken) {
/* time shift or integer overflow */ /* 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 */
cn->token = 1; cn->token = 1;
cn->lasttoken = now;
/* use a token if needed and available */ } else if (now > cn->lasttoken + TOKEN_INTERVAL) {
if (!list_is_empty(cn->outgoing) && cn->token > 0) { cn->token += (now - cn->lasttoken) /
cn->token--; TOKEN_INTERVAL;
return 1; 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) list_t *wait_event(list_t *cn_list, int *msec, int *nc)
{ {
fd_set fds_read, fds_write, fds_except; fd_set fds_read, fds_write, fds_except;
int maxfd = -1, err; int maxfd = -1, err;
list_t *cn_newdata; list_t *cn_newdata;
@ -817,7 +816,7 @@ list_t *wait_event(list_t *cn_list, int *msec, int *nc)
if (cn->listening) if (cn->listening)
continue; 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); FD_SET(cn->handle, &fds_write);
mylog(LOG_DEBUGTOOMUCH, "Test write on fd %d %d:%d", mylog(LOG_DEBUGTOOMUCH, "Test write on fd %d %d:%d",
cn->handle, cn->connected, cn->handle, cn->connected,
@ -1001,8 +1000,7 @@ static void create_listening_socket(char *hostname, char *port,
cn->connected = CONN_ERROR; cn->connected = CONN_ERROR;
} }
static connection_t *connection_init(int anti_flood, int ssl, int timeout, static connection_t *connection_init(int ssl, int timeout, int listen)
int listen)
{ {
connection_t *conn; connection_t *conn;
char *incoming; 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); incoming = (char *)bip_malloc(CONN_BUFFER_SIZE);
outgoing = list_new(NULL); outgoing = list_new(NULL);
conn->anti_flood = anti_flood;
conn->ssl = ssl; conn->ssl = ssl;
conn->lasttoken = 0; conn->lasttoken = 0;
conn->token = TOKEN_MAX; conn->token = TOKEN_MAX;
@ -1119,7 +1116,7 @@ connection_t *accept_new(connection_t *cn)
} }
socket_set_nonblock(err); 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->connect_time = time(NULL);
conn->user_data = cn->user_data; conn->user_data = cn->user_data;
conn->handle = err; 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 * SSL flag is only here to tell program to convert socket to SSL after
* accept(). Listening socket will NOT be SSL * 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); create_listening_socket(hostname, portbuf, conn);
return conn; return conn;
@ -1186,7 +1183,7 @@ static connection_t *_connection_new(char *dsthostname, char *dstport,
{ {
connection_t *conn; connection_t *conn;
conn = connection_init(1, 0, timeout, 0); conn = connection_init(0, timeout, 0);
create_socket(dsthostname, dstport, srchostname, srcport, conn); create_socket(dsthostname, dstport, srchostname, srcport, conn);
return conn; return conn;
@ -1411,7 +1408,7 @@ static connection_t *_connection_new_SSL(char *dsthostname, char *dstport,
{ {
connection_t *conn; connection_t *conn;
conn = connection_init(1, 1, timeout, 0); conn = connection_init(1, timeout, 0);
if (!(conn->ssl_ctx_h = SSL_init_context())) { if (!(conn->ssl_ctx_h = SSL_init_context())) {
mylog(LOG_ERROR, "SSL context initialization failed"); mylog(LOG_ERROR, "SSL context initialization failed");
return conn; return conn;
@ -1575,7 +1572,7 @@ int main(int argc,char* argv[])
fprintf(stderr,"Usage: %s host port\n",argv[0]); fprintf(stderr,"Usage: %s host port\n",argv[0]);
exit(1); exit(1);
} }
conn = connection_init(0, 0, 0, 1); conn = connection_init(0, 0, 1);
conn->connect_time = time(NULL); conn->connect_time = time(NULL);
create_listening_socket(argv[1],argv[2],&conn); create_listening_socket(argv[1],argv[2],&conn);
if (s == -1) { if (s == -1) {

View File

@ -63,7 +63,6 @@
struct connecting_data; struct connecting_data;
typedef struct connection { typedef struct connection {
int anti_flood;
int ssl; int ssl;
unsigned long lasttoken; unsigned long lasttoken;
unsigned token; unsigned token;

View File

@ -219,9 +219,10 @@ static void irc_server_connected(struct link_server *server)
mylog(LOG_INFO, "[%s] Connected for user %s", mylog(LOG_INFO, "[%s] Connected for user %s",
LINK(server)->name, LINK(server)->user->name); LINK(server)->name, LINK(server)->user->name);
irc_server_join(server);
log_connected(LINK(server)->log); log_connected(LINK(server)->log);
CONN(server)->token = 1;
if (LINK(server)->cli_nick) { if (LINK(server)->cli_nick) {
/* we change nick on client */ /* we change nick on client */
for (i = 0; i < LINK(server)->l_clientc; i++) { 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", WRITE_LINE1(CONN(server), NULL, "AWAY",
LINK(server)->no_client_away_msg); 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 */ if (irc_line_elem_equals(line, 0, "376")) /* end of motd */
irc_server_connected(server); irc_server_connected(server);
else if (irc_line_elem_equals(line, 0, "422")) /* no motd */ 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) { } else if (LINK(server)->s_state == IRCS_CONNECTING) {
ret = OK_FORGET; ret = OK_FORGET;