Destroy unused link after sighup
This commit is contained in:
parent
0abd8a386d
commit
664ebb68a7
1
TODO
1
TODO
|
@ -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
|
||||
|
|
61
src/bip.c
61
src/bip.c
|
@ -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:
|
||||
|
|
39
src/irc.c
39
src/irc.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
93
src/util.c
93
src/util.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue