Destroy unused link after sighup

This commit is contained in:
Arnaud Cornet 2007-10-21 19:35:22 +02:00
parent 0abd8a386d
commit 664ebb68a7
7 changed files with 148 additions and 64 deletions

1
TODO
View File

@ -1,3 +1,4 @@
- check conn_list usage: esp wrt list_remove and closes
- uid, gid
- keep invites when detached ?
- allow global (or per net ?) IP filtering

View File

@ -377,7 +377,6 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
l->untrusted_certs = sk_X509_new_null();
#endif
} else {
#warning "CODEME (user switch..)"
l->network = NULL;
log_reinit_all(l->log);
}
@ -497,6 +496,8 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
conf_die("No realname set and no default realname.");
l->realname = strdup(user->default_realname);
}
l->in_use = 1;
return 1;
}
@ -644,6 +645,7 @@ static int add_user(bip_t *bip, list_t *data, struct historical_directives *hds)
return 0;
}
u->in_use = 1;
return 1;
}
@ -705,6 +707,61 @@ static int validate_config(bip_t *bip)
return r;
}
void clear_marks(bip_t *bip)
{
list_iterator_t lit;
hash_iterator_t hit;
for (list_it_init(&bip->link_list, &lit); list_it_item(&lit);
list_it_next(&lit))
((struct link *)list_it_item(&lit))->in_use = 0;
for (hash_it_init(&bip->users, &hit); hash_it_item(&hit);
hash_it_next(&hit))
((struct user *)hash_it_item(&hit))->in_use = 0;
}
void user_kill(bip_t *bip, struct user *user)
{
if (!hash_is_empty(&user->connections))
fatal("user_kill, user still has connections");
free(user->name);
free(user->password);
MAYFREE(user->default_nick);
MAYFREE(user->default_username);
MAYFREE(user->default_realname);
#ifdef HAVE_LIBSSL
MAYFREE(ssl_check_store);
#endif
free(user);
}
void sweep(bip_t *bip)
{
list_iterator_t lit;
hash_iterator_t hit;
for (list_it_init(&bip->link_list, &lit); list_it_item(&lit);
list_it_next(&lit)) {
struct link *l = ((struct link *)list_it_item(&lit));
if (!l->in_use) {
mylog(LOG_INFO, "Administratively killing %s/%s",
l->user->name, l->name);
link_kill(bip, l);
list_remove_if_exists(&bip->conn_list, l);
list_it_remove(&lit);
}
}
for (hash_it_init(&bip->users, &hit); hash_it_item(&hit);
hash_it_next(&hit)) {
struct user *u = (struct user *)hash_it_item(&hit);
if (!u->in_use) {
hash_it_remove(&hit);
user_kill(bip, u);
}
}
}
int fireup(bip_t *bip, FILE *conf)
{
int r;
@ -712,6 +769,7 @@ int fireup(bip_t *bip, FILE *conf)
int err = 0;
struct historical_directives hds;
clear_marks(bip);
parse_conf(conf, &err);
if (err) {
free_conf(root_list);
@ -790,6 +848,7 @@ int fireup(bip_t *bip, FILE *conf)
root_list = NULL;
validate_config(bip);
sweep(bip);
return 1;
out_conf_error:

View File

@ -1423,11 +1423,6 @@ static void channel_free(struct channel *c)
if (c->create_ts)
free(c->create_ts);
/*
char *l;
while ((l = (char *)list_remove_first(&c->bans)))
free(l);
*/
hash_iterator_t hi;
for (hash_it_init(&c->nicks, &hi); hash_it_item(&hi); hash_it_next(&hi))
nick_free(hash_it_item(&hi));
@ -1892,7 +1887,6 @@ void server_cleanup(struct link_server *server)
CONN(server) = NULL;
}
irc_lag_init(server);
}
void irc_client_close(struct link_client *ic)
@ -1989,10 +1983,21 @@ struct link_server *irc_server_new(struct link *link, connection_t *conn)
void irc_server_free(struct link_server *s)
{
if (CONN(s))
connection_free(CONN(s));
if (s->nick)
free(s->nick);
if (s->user_mode)
free(s->user_mode);
hash_iterator_t hi;
for (hash_it_init(&s->channels, &hi); hash_it_item(&hi);
hash_it_next(&hi)) {
struct channel *chan = hash_it_item(&hi);
channel_free(chan);
}
free(s);
}
@ -2413,8 +2418,6 @@ void irc_main(bip_t *bip)
bip_on_event(bip, conn);
list_free(ready);
}
while (list_remove_first(&bip->link_list))
;
while (list_remove_first(&bip->connecting_client_list))
;
return;
@ -2431,12 +2434,6 @@ void irc_client_free(struct link_client *cli)
free(cli);
}
/*
void irc_server_free(struct link_server *is)
{
free(is);
}
*/
struct link *irc_link_new()
{
struct link *link;
@ -2453,11 +2450,18 @@ struct link *irc_link_new()
void link_kill(bip_t *bip, struct link *link)
{
list_remove(&bip->conn_list, CONN(link->l_server));
server_cleanup(link->l_server);
irc_server_free(link->l_server);
while (link->l_clientc) {
struct link_client *lc = link->l_clientv[0];
list_remove(&bip->conn_list, CONN(lc));
unbind_from_link(lc);
irc_client_free(lc);
}
hash_remove(&link->user->connections, link->name);
free(link->name);
irc_close((struct link_any *)link->l_server);
while (link->l_clientc)
irc_close((struct link_any *)link->l_clientv[0]);
log_free(link->log);
MAYFREE(link->prev_nick);
MAYFREE(link->cli_nick);
@ -2483,5 +2487,6 @@ void link_kill(bip_t *bip, struct link *link)
#ifdef HAVE_LIBSSL
sk_X509_free(link->untrusted_certs);
#endif
free(link);
}

View File

@ -90,6 +90,7 @@ struct user {
#endif
hash_t connections;
int in_use; /* for mark and sweep on reload */
};
struct network
@ -157,6 +158,7 @@ struct link {
int ssl_check_mode;
STACK_OF(X509) *untrusted_certs;
#endif
int in_use; /* for mark and sweep on reload */
};
struct link_connection {

View File

@ -1171,7 +1171,7 @@ log_t *log_new(struct user *user, char *network)
fatal("out of memory");
logdata->connected = 0;
if (!log_all_logs)
log_all_logs = list_new(NULL);
log_all_logs = list_new(list_ptr_cmp);
list_add_last(log_all_logs, logdata);
return logdata;
}
@ -1182,12 +1182,16 @@ void log_free(log_t *log)
logfilegroup_t *lfg;
logfile_t *lf;
list_remove(log_all_logs, log);
free(log->network);
free(log->buffer);
for (hash_it_init(&log->logfgs, &it); (lfg = hash_it_item(&it));
hash_it_next(&it)) {
log_reset(lfg);
if ((lf = list_remove_first(&lfg->file_group)))
logfile_free(lf);
free(lf);
}
hash_clean(&log->logfgs);
free(log);

View File

@ -308,28 +308,6 @@ void *list_remove_last(list_t *list)
return ptr;
}
/*
static void *list_remove_item(list_t *l, struct list_item *li)
{
void *ret = li->ptr;
if (!li->prev) {
if (l->first != li)
fatal("list_remove_item");
l->first = li->next;
} else
li->prev->next = li->next;
if (!li->next) {
if (l->last != li)
fatal("list_remove_item");
l->last = li->prev;
} else
li->next->prev = li->prev;
free(li);
return ret;
}
*/
void *list_remove_if_exists(list_t *list, void *ptr)
{
list_iterator_t li;
@ -383,12 +361,19 @@ void list_it_init(list_t *list, list_iterator_t *ti)
{
ti->list = list;
ti->cur = list->first;
ti->next = NULL;
}
void list_it_next(list_iterator_t *ti)
{
if (ti->cur)
if (ti->cur) {
if (ti->next)
fatal("list_it_next: inconsistent interator state");
ti->cur = ti->cur->next;
} else if (ti->next) {
ti->cur = ti->next;
ti->next = NULL;
}
}
void *list_it_item(list_iterator_t *ti)
@ -415,7 +400,8 @@ void *list_it_remove(list_iterator_t *li)
void *ptr = li->cur->ptr;
struct list_item *item = li->cur;
li->cur = li->cur->next;
li->next = li->cur->next;
li->cur = NULL;
free(item);
return ptr;
}
@ -555,50 +541,73 @@ void *hash_remove(hash_t *hash, char *key)
return ptr;
}
int hash_is_empty(hash_t *h)
{
int i;
for (i = 0; i < 256; i++) {
if (!list_is_empty(&h->lists[i]))
return 0;
}
return 1;
}
void hash_it_init(hash_t *h, hash_iterator_t *hi)
{
memset(hi, 0, sizeof(hash_iterator_t));
hi->hash = h;
while (list_is_empty(&h->lists[hi->list]) && hi->list < 256)
while (hi->list < 256 && list_is_empty(&h->lists[hi->list]))
hi->list++;
if (hi->list < 256)
hi->cur = h->lists[hi->list].first;
else
hi->cur = NULL;
list_it_init(&h->lists[hi->list], &hi->lit);
}
void hash_it_next(hash_iterator_t *hi)
{
hash_t *hash = hi->hash;
hi->cur = hi->cur->next;
while (!hi->cur) {
hi->list++;
if (hi->list == 256) {
hi->cur = NULL;
return;
}
hi->cur = hash->lists[hi->list].first;
list_it_next(&hi->lit);
if (!list_it_item(&hi->lit)) {
do {
hi->list++;
if (hi->list == 256)
return;
} while (list_is_empty(&hi->hash->lists[hi->list]));
list_it_init(&hi->hash->lists[hi->list], &hi->lit);
}
}
void *hash_it_item(hash_iterator_t *h)
{
if (!h->cur)
struct hash_item *hi;
hi = list_it_item(&h->lit);
if (!hi)
return NULL;
struct hash_item *hi = h->cur->ptr;
return hi->item;
}
char *hash_it_key(hash_iterator_t *h)
{
if (!h->cur)
struct hash_item *hi;
hi = list_it_item(&h->lit);
if (!hi)
return NULL;
struct hash_item *hi = h->cur->ptr;
return hi->key;
}
void *hash_it_remove(hash_iterator_t *hi)
{
struct hash_item *hitem;
void *ptr;
hitem = list_it_remove(&hi->lit);
ptr = hitem->item;
free(hitem->key);
free(hitem);
return ptr;
}
void hash_dump(hash_t *h)
{
hash_iterator_t it;

View File

@ -35,6 +35,7 @@ void _mylog(int level, char *fmt, va_list ap);
void fatal(char *fmt, ...);
char *timestamp(void);
struct list_item;
struct hash_item;
typedef struct list {
struct list_item *first;
@ -45,16 +46,17 @@ typedef struct list {
typedef struct list_iterator {
list_t *list;
struct list_item *cur;
struct list_item *next;
} list_iterator_t;
/* our hash is also a list */
typedef struct hash {
list_t lists[256];
} hash_t;
typedef struct hash_iterator {
int list;
struct list_item *cur;
list_iterator_t lit;
struct hash_item *cur;
hash_t *hash;
} hash_iterator_t;
@ -104,10 +106,12 @@ void hash_insert(hash_t *hash, char *key, void *ptr);
void *hash_get(hash_t *, char *key);
void *hash_remove(hash_t *hash, char *key);
void *hash_remove_if_exists(hash_t *hash, char *key);
int hash_is_empty(hash_t *h);
void hash_it_init(hash_t *hash, hash_iterator_t *i);
void hash_it_next(hash_iterator_t *hi);
void *hash_it_item(hash_iterator_t *h);
char *hash_it_key(hash_iterator_t *h);
void *hash_it_remove(hash_iterator_t *li);
int is_valid_nick(char *str);
int is_valid_username(char *str);