diff options
| author | Nakidai <nakidai@disroot.org> | 2026-01-07 00:26:37 +0300 |
|---|---|---|
| committer | Nakidai <nakidai@disroot.org> | 2026-01-07 00:26:37 +0300 |
| commit | 63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e (patch) | |
| tree | e148ddc96aa7b50e3eb981eae8c9faf9de6ab2f5 | |
| parent | cfcb3b22245c779eb9d216c2909789e4368cce6a (diff) | |
| download | libreircd-63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e.tar.gz libreircd-63c0a8860459c0c9bf3b66d4d4ec631ece4bf56e.zip | |
Fix user quit
When user A leaves, last user in the peer list B is copied into the space left by leaving A. But, besides that it also important to not forget that there can be channels containing B: they store a link to every user belonging. So, it's important to adjust all links to B iterating every channel B belongs to.
| -rw-r--r-- | ircd.h | 1 | ||||
| -rw-r--r-- | loop.c | 24 | ||||
| -rw-r--r-- | user.c | 31 |
3 files changed, 43 insertions, 13 deletions
diff --git a/ircd.h b/ircd.h index 8097c26..07bdd0f 100644 --- a/ircd.h +++ b/ircd.h @@ -75,6 +75,7 @@ extern int port; const char *getnick(const struct Peer *peer); void user_reg(struct Peer *peer, const char *nick, const char *user, const char *real); +void user_remove(size_t pid); int channel_join(struct Channel *channel, struct Peer *peer); int channel_exit(struct Channel *channel, struct Peer *peer); diff --git a/loop.c b/loop.c index 81ff25d..9e91438 100644 --- a/loop.c +++ b/loop.c @@ -123,19 +123,18 @@ loop: if (!(peers[i].flags & DELETE)) continue; - if (!peers[i].type) - goto skip; - writef( - peers[i].fd, - ":%s!%s@%s QUIT", - getnick(&peers[i]), - peers[i].user, - peers[i].host - ); + if (peers[i].type) + writef( + peers[i].fd, + ":%s!%s@%s QUIT", + getnick(&peers[i]), + peers[i].user, + peers[i].host + ); for (j = 0; j < peers[i].channels_c; ++j) { channel_exit(peers[i].channels[j], &peers[i]); - for (k = 0; k < peers[i].channels[j]->users_c; ++k) + if (peers[i].type) for (k = 0; k < peers[i].channels[j]->users_c; ++k) peers[i].channels[j]->users[k]->flags |= ANNOUNCE; } for (j = 0; j < peers_c; ++j) @@ -143,17 +142,16 @@ loop: { writef( peers[j].fd, - "%s!%s@%s QUIT", + ":%s!%s@%s QUIT", getnick(&peers[i]), peers[i].user, peers[i].host ); peers[j].flags &= ~ANNOUNCE; } -skip: writef(peers[i].fd, "ERROR :Closing Link: %s", peers[i].host); close(peers[i].fd); - peers[i] = peers[--peers_c]; + user_remove(i); i = 0; } goto loop; diff --git a/user.c b/user.c index e37452b..f856f6c 100644 --- a/user.c +++ b/user.c @@ -16,8 +16,11 @@ #include "ircd.h" +#include <stddef.h> #include <string.h> +#include <err.h> + const char * getnick(const struct Peer *peer) @@ -40,3 +43,31 @@ user_reg(struct Peer *peer, const char *nick, const char *user, const char *real reply(peer, 1); } } + +void +user_remove(size_t pid) +{ + size_t i, j; + + for (i = 0; i < peers[peers_c-1].channels_c; ++i) + { + for (j = 0; j < peers[peers_c-1].channels[i]->users_c; ++j) + if (peers[peers_c-1].channels[i]->users[j]->fd == peers[peers_c-1].fd) + break; + if (j == peers[peers_c-1].channels[i]->users_c) + { + warnx( + "user_unlink(): %s@%s doesn't belong to %s, " + "though they believe in the opposite", + getnick(&peers[peers_c-1]), + peers[peers_c-1].host, + peers[peers_c-1].channels[i]->name + ); + continue; + } + + peers[peers_c-1].channels[i]->users[j] = &peers[pid]; + } + + peers[pid] = peers[--peers_c]; +} |