Lot's of cleanups.

This commit is contained in:
nohar 2007-05-26 10:31:44 +00:00
parent ad9c4d7021
commit 56fd224916
6 changed files with 245 additions and 241 deletions

View File

@ -1,3 +1,8 @@
2007-05-26 Arnaud Cornet <arnaud.cornet@gmail.com>
* src: lot's of code cleanup and refactoring. Open door to better
dynamic config support.
2007-02-27 Arnaud Cornet <arnaud.cornet@gmail.com>
* bip: Release 0.6.0.

View File

@ -285,18 +285,17 @@ void reload_config(int i)
sighup = 1;
}
extern list_t *_connections;
bip_t *_bip;
void bad_quit(int i)
{
list_iterator_t it;
for (list_it_init(_connections, &it); list_it_item(&it);
for (list_it_init(&_bip->link_list, &it); list_it_item(&it);
list_it_next(&it)) {
connection_t *c = list_it_item(&it);
struct link_any *la = c->user_data;
if (c->connected == CONN_OK && la &&
TYPE(la) == IRC_TYPE_SERVER) {
write_line_fast(CONN(la), "QUIT :Coyote finally "
struct link *l = list_it_item(&it);
struct link_server *ls = l->l_server;
if (ls && l->s_state == IRCS_CONNECTED) {
write_line_fast(CONN(ls), "QUIT :Coyote finally "
"caught me\r\n");
}
}
@ -749,7 +748,7 @@ int fireup(FILE *conf)
return 1;
}
void ircize(list_t *ll)
void ircize(bip_t *bip)
{
hash_iterator_t it;
for (hash_it_init(&conf_users, &it); hash_it_item(&it);
@ -806,7 +805,7 @@ void ircize(list_t *ll)
list_add_last(&link->chan_infos_order,
ci);
}
list_add_last(ll, link);
list_add_last(&bip->link_list, link);
} else {
mylog(LOG_DEBUGVERB, "old connection: \"%s\"",
c->name);
@ -909,17 +908,19 @@ int main(int argc, char **argv)
{
FILE *conf = NULL;
char *confpath = NULL;
list_t *ll = list_new(NULL);
int ch;
int r,fd;
char buf[30];
bip_t bip;
bip_init(&bip);
_bip = &bip;
conf_ip = strdup("0.0.0.0");
conf_port = 7778;
conf_css = 0;
hash_init(&adm_users, HASH_NOCASE);
hash_init(&conf_users, HASH_NOCASE);
hash_init(&conf_networks, HASH_NOCASE);
@ -996,18 +997,17 @@ int main(int argc, char **argv)
write(fd, buf, strlen(buf));
close(fd);
connection_t *inc;
inc = listen_new(conf_ip, conf_port, conf_css);
if (!inc)
bip.listener = listen_new(conf_ip, conf_port, conf_css);
if (!bip.listener)
fatal("Could not create listening socket");
for (;;) {
if (r)
ircize(ll);
ircize(&bip);
if (conf_error)
mylog(LOG_ERROR, "conf error: %s", conf_errstr);
irc_main(inc, ll);
irc_main(&bip);
sighup = 0;

View File

@ -1383,7 +1383,6 @@ connection_t *connection_new(char *dsthostname, int dstport, char *srchostname,
tmp = srcportbuf;
} else
tmp = NULL;
#ifdef HAVE_LIBSSL
if (ssl)
return _connection_new_SSL(dsthostname, dstportbuf, srchostname,

423
src/irc.c
View File

@ -338,9 +338,12 @@ void rotate_who_client(struct link *link)
* parses:join part mode kick kill privmsg quit nick names
* returns: -1 invalid protocol
*/
int irc_dispatch_server(struct link_server *server, struct line *line)
int irc_dispatch_server(bip_t *bip, struct link_server *server,
struct line *line)
{
int ret = OK_COPY;
/* shut gcc up */
(void)bip;
if (line->elemc == 0)
return ERR_PROTOCOL;
@ -568,14 +571,9 @@ void unbind_from_link(struct link_client *ic)
fatal("unbind_from_link");
if (l->who_client == ic) {
mylog(LOG_DEBUG, "unbind_from_link: %p: %d",
l->who_client, ic->who_count);
l->who_client = NULL;
} else {
mylog(LOG_DEBUG,
"unbind_from_link: nothing to do %p != %p: %d",
ic, l->who_client,
mylog(LOG_DEBUG, "unbind_from_link: %p: %d", l->who_client,
ic->who_count);
l->who_client = NULL;
}
for (i = i + 1; i < l->l_clientc; i++)
@ -667,8 +665,8 @@ static void irc_cli_make_join(struct link_client *ic)
}
}
static int irc_cli_startup(struct link_client *ic, struct line *line,
list_t *linkl)
static int irc_cli_startup(bip_t *bip, struct link_client *ic,
struct line *line)
{
char *init_nick;
char *user, *pass, *connname;
@ -693,10 +691,11 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
}
list_iterator_t it;
for (list_it_init(linkl, &it); list_it_item(&it); list_it_next(&it)) {
for (list_it_init(&bip->link_list, &it); list_it_item(&it);
list_it_next(&it)) {
struct link *l = list_it_item(&it);
if (strcmp(user, l->username) == 0
&& strcmp(connname, l->name) == 0) {
if (strcmp(user, l->username) == 0 &&
strcmp(connname, l->name) == 0) {
if (chash_cmp(pass, l->password, l->seed) == 0) {
bind_to_link(l, ic);
break;
@ -743,6 +742,7 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
return OK_CLOSE;
}
list_remove(&bip->connecting_client_list, ic);
TYPE(ic) = IRC_TYPE_CLIENT;
for (list_it_init(&LINK(ic)->init_strings, &it);
@ -779,7 +779,7 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
return OK_FORGET;
}
static int irc_cli_nick(struct link_client *ic, struct line *line, list_t *cl)
static int irc_cli_nick(bip_t *bip, struct link_client *ic, struct line *line)
{
if (line->elemc != 2)
return ERR_PROTOCOL;
@ -793,16 +793,17 @@ static int irc_cli_nick(struct link_client *ic, struct line *line, list_t *cl)
ic->init_nick = strdup(line->elemv[1]);
if ((ic->state & IRCC_READY) == IRCC_READY)
return irc_cli_startup(ic, line, cl);
return irc_cli_startup(bip, ic, line);
if ((ic->state & IRCC_PASS) != IRCC_PASS)
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", ic->init_nick,
"You should type /QUOTE PASS your_username:your_password:your_connection_name");
"You should type /QUOTE PASS your_username:"
"your_password:your_connection_name");
return OK_FORGET;
}
static int irc_cli_user(struct link_client *ic, struct line *line, list_t *cl)
static int irc_cli_user(bip_t *bip, struct link_client *ic, struct line *line)
{
if (line->elemc != 5)
return ERR_PROTOCOL;
@ -812,11 +813,11 @@ static int irc_cli_user(struct link_client *ic, struct line *line, list_t *cl)
ic->state |= IRCC_USER;
if ((ic->state & IRCC_READY) == IRCC_READY)
return irc_cli_startup(ic, line, cl);
return irc_cli_startup(bip, ic, line);
return OK_FORGET;
}
static int irc_cli_pass(struct link_client *ic, struct line *line, list_t *cl)
static int irc_cli_pass(bip_t *bip, struct link_client *ic, struct line *line)
{
if (line->elemc != 2)
return ERR_PROTOCOL;
@ -829,7 +830,7 @@ static int irc_cli_pass(struct link_client *ic, struct line *line, list_t *cl)
free(ic->init_pass);
ic->init_pass = strdup(line->elemv[1]);
if ((ic->state & IRCC_READY) == IRCC_READY)
return irc_cli_startup(ic, line, cl);
return irc_cli_startup(bip, ic, line);
return OK_FORGET;
}
@ -1036,7 +1037,8 @@ static int irc_dispatch_trust_client(struct link_client *ic, struct line *line)
#endif
int irc_cli_bip(struct link_client *ic, struct line *line);
static int irc_dispatch_client(struct link_client *ic, struct line *line)
static int irc_dispatch_client(bip_t *bip, struct link_client *ic,
struct line *line)
{
int r = OK_COPY;
if (line->elemc == 0)
@ -1059,7 +1061,7 @@ static int irc_dispatch_client(struct link_client *ic, struct line *line)
} else if (strcmp(line->elemv[0], "PART") == 0) {
r = irc_cli_part(ic, line);
} else if (strcmp(line->elemv[0], "NICK") == 0) {
r = irc_cli_nick(ic, line, NULL);
r = irc_cli_nick(bip, ic, line);
} else if (strcmp(line->elemv[0], "QUIT") == 0) {
r = irc_cli_quit(ic, line);
} else if (strcmp(line->elemv[0], "PRIVMSG") == 0) {
@ -1145,34 +1147,34 @@ static void irc_copy_cli(struct link_client *src, struct link_client *dest,
return;
}
static int irc_dispatch_loging_client(struct link_client *ic, struct line *line,
list_t *linkl)
static int irc_dispatch_loging_client(bip_t *bip, struct link_client *ic,
struct line *line)
{
if (line->elemc == 0)
return ERR_PROTOCOL;
if (strcmp(line->elemv[0], "NICK") == 0) {
return irc_cli_nick(ic, line, linkl);
return irc_cli_nick(bip, ic, line);
} else if (strcmp(line->elemv[0], "USER") == 0) {
return irc_cli_user(ic, line, linkl);
return irc_cli_user(bip, ic, line);
} else if (strcmp(line->elemv[0], "PASS") == 0) {
return irc_cli_pass(ic, line, linkl);
return irc_cli_pass(bip, ic, line);
}
return OK_FORGET;
}
int irc_dispatch(struct link_any *l, struct line *line, list_t *linkl)
int irc_dispatch(bip_t *bip, struct link_any *l, struct line *line)
{
switch (TYPE(l)) {
case IRC_TYPE_SERVER:
return irc_dispatch_server((struct link_server*)l, line);
return irc_dispatch_server(bip, (struct link_server*)l, line);
break;
case IRC_TYPE_CLIENT:
return irc_dispatch_client((struct link_client*)l, line);
return irc_dispatch_client(bip, (struct link_client*)l, line);
break;
case IRC_TYPE_LOGING_CLIENT:
return irc_dispatch_loging_client((struct link_client*)l,
line, linkl);
return irc_dispatch_loging_client(bip, (struct link_client*)l,
line);
break;
#ifdef HAVE_LIBSSL
case IRC_TYPE_TRUST_CLIENT:
@ -1909,13 +1911,14 @@ static void irc_close(struct link_any *l)
irc_notify_disconnection(is);
else
LINK(is)->s_conn_attempt++;
printf("%d\n", LINK(is)->s_conn_attempt);
irc_server_shutdown(is);
log_disconnected(LINK(is)->log);
server_next(LINK(is));
server_cleanup(is);
if (LINK(is)->last_connection &&
time(NULL) - LINK(is)->last_connection
if (LINK(is)->last_connection_attempt &&
time(NULL) - LINK(is)->last_connection_attempt
< CONN_INTERVAL)
timer = RECONN_TIMER * (LINK(is)->s_conn_attempt);
mylog(LOG_ERROR, "%s dead, reconnecting in %d seconds",
@ -2166,9 +2169,6 @@ clean_oidentd:
}
#endif
/* do not use */
list_t *_connections = NULL;
void timeout_clean_who_counts(list_t *conns)
{
list_iterator_t it;
@ -2192,36 +2192,21 @@ void timeout_clean_who_counts(list_t *conns)
}
}
struct link_client *reloading_client;
/*
* The main loop
* inc is the incoming connection, clientl list a list of client struct that
* represent the accepcted credentials
*/
void irc_main(connection_t *inc, list_t *ll)
void bip_init(bip_t *bip)
{
list_t reconnectl;
list_t timerwaitl;
list_t connl;
list_t connecting_c;
list_t connected_c;
int timeleft = 1000;
int logflush_timer = conf_log_sync_interval;
list_init(&reconnectl, NULL);
list_init(&timerwaitl, NULL);
list_init(&connl, list_ptr_cmp);
list_init(&connecting_c, list_ptr_cmp);
list_init(&connected_c, list_ptr_cmp);
_connections = &connl;
/* XXX: This one MUST be first */
list_add_first(&connl, inc);
memset(bip, 0, sizeof(bip_t));
list_init(&bip->link_list, list_ptr_cmp);
list_init(&bip->conn_list, list_ptr_cmp);
}
void bip_recover_sighup(bip_t *bip)
{
/* gcc */
(void)bip;
/*
* Merge with already connected data, happens on SIGHUP
*/
#if 0
list_iterator_t it;
for (list_it_init(ll, &it); list_it_item(&it); list_it_next(&it)) {
struct link *link = list_it_item(&it);
@ -2252,191 +2237,185 @@ void irc_main(connection_t *inc, list_t *ll)
conf_errstr);
reloading_client = NULL;
}
#endif
}
/* Called each second. */
void bip_tick(bip_t *bip)
{
static int logflush_timer = 0;
struct link *link;
list_iterator_t li;
/* log flushs */
if (logflush_timer-- <= 0) {
logflush_timer = conf_log_sync_interval;
log_flush_all();
}
/* handle tick for links: detect lags or start a reconnection */
for (list_it_init(&bip->link_list, &li); (link = list_it_item(&li));
list_it_next(&li)) {
if (link->l_server) {
if (irc_server_lag_compute(link)) {
log_ping_timeout(link->log);
list_remove(&bip->conn_list,
CONN(link->l_server));
irc_close((struct link_any *) link->l_server);
}
} else {
if (link->recon_timer == 0) {
connection_t *conn;
conn = irc_server_connect(link);
list_add_last(&bip->conn_list, conn);
link->last_connection_attempt = time(NULL);
} else {
link->recon_timer--;
}
}
}
/* drop lagging connecting client */
for (list_it_init(&bip->connecting_client_list, &li); list_it_item(&li);
list_it_next(&li)) {
struct link_client *ic = list_it_item(&li);
ic->logging_timer++;
if (ic->logging_timer > LOGGING_TIMEOUT) {
list_remove(&bip->conn_list, CONN(ic));
irc_close((struct link_any *)ic);
list_it_remove(&li);
}
}
/*
* Cleanup lagging or dangling who_count buffers
*/
timeout_clean_who_counts(&bip->link_list);
}
void bip_on_event(bip_t *bip, connection_t *conn)
{
struct link_any *lc = (struct link_any *)conn->user_data;
if (conn == bip->listener) {
struct link_client *n = irc_accept_new(conn);
if (!n)
fatal("Problem while binding local socket");
list_add_last(&bip->conn_list, CONN(n));
list_add_last(&bip->connecting_client_list, n);
return;
}
/* reached only if socket is not listening */
int err;
list_t *linel = read_lines(conn, &err);
if (err) {
if (TYPE(lc) == IRC_TYPE_SERVER) {
mylog(LOG_ERROR, "read_lines error, closing %s ...",
LINK(lc)->name);
irc_server_shutdown(LINK(lc)->l_server);
} else {
mylog(LOG_ERROR, "read_lines error, closing...");
}
goto prot_err;
}
if (!linel)
return;
char *line_s;
while ((line_s = list_remove_first(linel))) {
struct line *line;
mylog(LOG_DEBUG, "\"%s\"", line_s);
if (*line_s == 0) { /* irssi does that.*/
free(line_s);
continue;
}
line = irc_line(line_s);
if (!line) {
mylog(LOG_ERROR, "Error in protocol, closing...");
free(line_s);
goto prot_err_lines;
}
int r;
r = irc_dispatch(bip, lc, line);
irc_line_free(line);
free(line_s);
if (r == ERR_PROTOCOL) {
mylog(LOG_ERROR, "Error in protocol, "
"closing...");
goto prot_err_lines;
}
if (r == ERR_AUTH)
goto prot_err_lines;
/* XXX: not real error */
if (r == OK_CLOSE)
goto prot_err_lines;
}
list_free(linel);
return;
prot_err_lines:
while ((line_s = list_remove_first(linel)))
free(line_s);
prot_err:
list_remove(&bip->conn_list, conn);
if (linel)
list_free(linel);
if (lc) {
if (TYPE(lc) == IRC_TYPE_LOGING_CLIENT)
list_remove(&bip->connecting_client_list, lc);
irc_close(lc);
}
}
struct link_client *reloading_client;
/*
* The main loop
* inc is the incoming connection, clientl list a list of client struct that
* represent the accepcted credentials
*/
void irc_main(bip_t *bip)
{
int timeleft = 1000;
/* XXX: This one MUST be first */
/* TODO: maybe not anymore, check */
printf("%p\n", bip->listener);
list_add_first(&bip->conn_list, bip->listener);
bip_recover_sighup(bip);
while (!sighup) {
struct link *link;
connection_t *conn;
if (timeleft == 0) {
/*
* Compute timeouts for next reconnections and lagouts
*/
static int throttle_prot = S_CONN_DELAY - 1;
timeleft = 1000;
if (++throttle_prot == S_CONN_DELAY) {
throttle_prot = 0;
/* Lauch one reconnection at a time */
if ((link = list_remove_first(&reconnectl))) {
conn = irc_server_connect(link);
list_add_last(&connl, conn);
link->last_connection = time(NULL);
}
}
/* log flushs */
if (logflush_timer-- <= 0) {
logflush_timer = conf_log_sync_interval;
log_flush_all();
}
/* reconnects */
list_iterator_t li;
for (list_it_init(&timerwaitl, &li); list_it_item(&li);
list_it_next(&li)) {
struct link *l = list_it_item(&li);
if (l->recon_timer <= 0) {
list_it_remove(&li);
list_add_last(&reconnectl, l);
} else {
l->recon_timer--;
}
}
/* server lags */
for (list_it_init(ll, &li); list_it_item(&li);
list_it_next(&li)) {
struct link *l = list_it_item(&li);
if(l->l_server && irc_server_lag_compute(l)) {
log_ping_timeout(l->log);
list_remove(&connl, CONN(l->l_server));
irc_close((struct link_any *)
l->l_server);
list_add_last(&timerwaitl, l);
}
}
/* drop lagging connecting client */
for (list_it_init(&connecting_c, &li);
list_it_item(&li); list_it_next(&li)) {
struct link_client *ic = list_it_item(&li);
ic->logging_timer++;
if (ic->logging_timer > LOGGING_TIMEOUT) {
list_remove(&connl, CONN(ic));
irc_close((struct link_any *)ic);
list_it_remove(&li);
}
}
/*
* Cleanup lagging or dangling who_count buffers
*/
timeout_clean_who_counts(ll);
bip_tick(bip);
}
int nc;
/* Da main loop */
list_t *ready = wait_event(&connl, &timeleft, &nc);
list_t *ready = wait_event(&bip->conn_list, &timeleft, &nc);
#ifdef HAVE_OIDENTD
if (nc)
oidentd_dump(&connl);
oidentd_dump(&bip->connl);
#endif
while ((conn = list_remove_first(ready))) {
struct link_any *lc =
(struct link_any *)conn->user_data;
if (conn == inc) {
struct link_client *n = irc_accept_new(conn);
if (!n)
fatal("Problem while binding local"
" socket");
list_add_last(&connl, CONN(n));
list_add_last(&connecting_c, n);
continue;
}
/* reached only if socket is not listening */
int err;
list_t *linel = read_lines(conn, &err);
if (err) {
if (TYPE(lc) == IRC_TYPE_SERVER) {
mylog(LOG_ERROR, "read_lines error, "
"closing %s ...",
LINK(lc)->name);
irc_server_shutdown(LINK(lc)->l_server);
} else {
mylog(LOG_ERROR, "read_lines error, "
"closing...");
}
goto prot_err;
}
if (!linel)
continue;
char *line_s;
while ((line_s = list_remove_first(linel))) {
struct line *line;
mylog(LOG_DEBUG, "\"%s\"", line_s);
if (*line_s == 0) { /* irssi does that.*/
free(line_s);
continue;
}
line = irc_line(line_s);
if (!line) {
mylog(LOG_ERROR, "Error in protocol, "
"closing...");
free(line_s);
goto prot_err_lines;
}
int r;
int oldtype = TYPE(lc);
r = irc_dispatch((struct link_any*)
conn->user_data, line, ll);
irc_line_free(line);
free(line_s);
if (r == ERR_PROTOCOL) {
mylog(LOG_ERROR, "Error in protocol, "
"closing...");
goto prot_err_lines;
}
if (r == ERR_AUTH)
goto prot_err_lines;
/* XXX: not real error */
if (r == OK_CLOSE)
goto prot_err_lines;
if (oldtype == IRC_TYPE_LOGING_CLIENT &&
TYPE(lc) == IRC_TYPE_CLIENT) {
list_remove(&connecting_c, lc);
list_add_last(&connected_c, lc);
}
}
list_free(linel);
continue;
prot_err_lines:
while ((line_s = list_remove_first(linel)))
free(line_s);
prot_err:
list_remove(&connl, conn);
if (linel)
list_free(linel);
if (lc) {
if (TYPE(lc) == IRC_TYPE_CLIENT)
list_remove(&connected_c, lc);
if (TYPE(lc) == IRC_TYPE_LOGING_CLIENT)
list_remove(&connecting_c, lc);
if (TYPE(lc) == IRC_TYPE_SERVER)
list_add_last(&timerwaitl, LINK(lc));
irc_close(lc);
}
bip_on_event(bip, conn);
}
list_free(ready);
}
while (list_remove_first(&connecting_c))
while (list_remove_first(&bip->conn_list))
;
while (list_remove_first(&connected_c))
while (list_remove_first(&bip->link_list))
;
while (list_remove_first(&connl))
while (list_remove_first(&bip->connecting_client_list))
;
while (list_remove_first(&timerwaitl))
;
while (list_remove_first(&reconnectl))
;
_connections = NULL;
return;
}

View File

@ -85,7 +85,7 @@ struct link {
/* connection state (reconnecting, was_connected ...) */
int recon_timer;
time_t last_connection;
time_t last_connection_attempt;
/** link options */
@ -168,6 +168,7 @@ struct link_client {
#define IRCS_CONNECTED (2)
#define IRCS_WAS_CONNECTED (3)
#define IRCS_RECONNECTING (4)
#define IRCS_TIMER_WAIT (5)
struct log;
@ -195,14 +196,26 @@ struct link_server {
int lagtest_timeout;
};
typedef struct bip {
connection_t *listener;
/* all connected tcp connections */
list_t conn_list;
/* all links */
list_t link_list;
/* connecting clients */
list_t connecting_client_list;
} bip_t;
void bip_init(bip_t *bip);
struct link_client *irc_client_new(void);
struct link_server *irc_server_new(struct link *link, connection_t *conn);
void irc_server_free(struct link_server *is);
struct client *client_new();
void irc_main(connection_t *inc, list_t *clientl);
void irc_main(bip_t *);
int ischannel(char p);
void irc_client_close(struct link_client *);
void irc_client_free(struct link_client *);
struct link *irc_link_new();
void unbind_from_link(struct link_client *ic);
#endif

View File

@ -188,6 +188,9 @@ static struct list_item *list_item(void *ptr)
void list_add_first(list_t *list, void *ptr)
{
struct list_item *li;
if (!ptr)
fatal("Cannot add NULL ptr to list.");
li = list_item(ptr);
if (!list->first) {
list->first = list->last = li;
@ -200,6 +203,8 @@ void list_add_first(list_t *list, void *ptr)
void list_add_first_uniq(list_t *list, void *ptr)
{
if (!ptr)
fatal("Cannot add NULL ptr to list.");
if (list_get(list, ptr))
return;
list_add_first(list, ptr);
@ -208,6 +213,9 @@ void list_add_first_uniq(list_t *list, void *ptr)
void list_add_last(list_t *list, void *ptr)
{
struct list_item *li;
if (!ptr)
fatal("Cannot add NULL ptr to list.");
li = list_item(ptr);
if (!list->first) {
list->first = list->last = li;