summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-06 17:04:09 +0300
committerNakidai <nakidai@disroot.org>2026-02-06 17:04:09 +0300
commit9ae659fd6c792407f3d80ea4d313bf850c2332ec (patch)
tree9bd14003e61c4d6a66216e50f4deddb266898118
parentb7e7843214ba36ca06289d1925c05e6586acac41 (diff)
downloadlibreircd-9ae659fd6c792407f3d80ea4d313bf850c2332ec.tar.gz
libreircd-9ae659fd6c792407f3d80ea4d313bf850c2332ec.zip
Change way to deal with modes in channels
I thought it'd be fine to store modes as an array. But using this is
awful experience. Take a look at simple NAMES command: it just needs
to check whether some user is oper or voice or not, and with that
approach it will need to iterate over an array of users, and for each
user iterate over an array of modes. Or it is possible to optimize it,
saving all interesting modes to a local buffer and then iterating over
it. But those are attempts to fix broken design

So, instead of array of modes there'll be lots of fields regarding each
mode or kind of mode

From now on (struct Channel).peers is not a simple array of peers, but
the one with metainformation. This is done by making an array of
structures, so there are renames throughout the code

Also, I didn't like that it was users and not peers and this is a nice
opportunity to rename it: in first place this was done to avoid thing
that compiler somehow could silently ignore type change, but this is
also a stylistic change reflecting my view on naming
-rw-r--r--channel.c28
-rw-r--r--config.h2
-rw-r--r--handle.c4
-rw-r--r--ircd.h12
-rw-r--r--user.c12
-rw-r--r--writef.c10
6 files changed, 36 insertions, 32 deletions
diff --git a/channel.c b/channel.c
index 94b0d6c..21a777a 100644
--- a/channel.c
+++ b/channel.c
@@ -28,12 +28,12 @@ size_t channels_c;
 int
 channel_join(struct Channel *channel, struct Peer *peer)
 {
-	if (channel->users_c == lengthof(channel->users)
+	if (channel->peers_c == lengthof(channel->peers)
 	 || peer->channels_c == lengthof(peer->channels))
 		return 1;
 
 	peer->channels[peer->channels_c++] = channel;
-	channel->users[channel->users_c++] = peer;
+	channel->peers[channel->peers_c++].p = peer;
 	writechanf(
 		0,
 		channel,
@@ -51,11 +51,11 @@ channel_exit(struct Channel *channel, struct Peer *peer)
 {
 	size_t i;
 
-	for (i = 0; i < channel->users_c; ++i)
-		if (channel->users[i]->fd == peer->fd)
+	for (i = 0; i < channel->peers_c; ++i)
+		if (channel->peers[i].p->fd == peer->fd)
 			break;
-	ensure(i != channel->users_c, (void)0, 1);
-	channel->users[i] = channel->users[--channel->users_c];
+	ensure(i != channel->peers_c, (void)0, 1);
+	channel->peers[i] = channel->peers[--channel->peers_c];
 
 	for (i = 0; i < peer->channels_c; ++i)
 		if (!strcmp(peer->channels[i]->name, channel->name))
@@ -65,7 +65,7 @@ channel_exit(struct Channel *channel, struct Peer *peer)
 	), 1)
 	peer->channels[i] = peer->channels[--peer->channels_c];
 
-	if (!channel->users_c)
+	if (!channel->peers_c)
 	{
 		for (i = 0; i < channels_c; ++i)
 			if (!strcmp(channels[i].name, channel->name))
@@ -86,24 +86,24 @@ channel_remove(size_t cid)
 	size_t i, j;
 
 	tofix = &channels[channels_c-1];
-	for (i = 0; i < tofix->users_c; ++i)
+	for (i = 0; i < tofix->peers_c; ++i)
 	{
-		for (j = 0; j < tofix->users[i]->channels_c; ++j)
-			if (!strcmp(tofix->users[i]->channels[j]->name, tofix->name))
+		for (j = 0; j < tofix->peers[i].p->channels_c; ++j)
+			if (!strcmp(tofix->peers[i].p->channels[j]->name, tofix->name))
 				break;
-		if (j == tofix->users[i]->channels_c)
+		if (j == tofix->peers[i].p->channels_c)
 		{
 			warnx(
 				"channel_remove(): %s doesn't belong to %s@%s, "
 				"though they believe in the opposite",
 				tofix->name,
-				getnick(tofix->users[i]),
-				tofix->users[i]->host
+				getnick(tofix->peers[i].p),
+				tofix->peers[i].p->host
 			);
 			continue;
 		}
 
-		tofix->users[i]->channels[j] = &channels[cid];
+		tofix->peers[i].p->channels[j] = &channels[cid];
 	}
 
 	channels[cid] = channels[--channels_c];
diff --git a/config.h b/config.h
index 965d835..ec49704 100644
--- a/config.h
+++ b/config.h
@@ -27,7 +27,7 @@
 #define OPERS_MAX 8
 #define CHANNELS_MAX 100
 
-#define CHANNEL_USERS_MAX 100
+#define CHANNEL_PEERS_MAX 100
 #define CHANNEL_MODES_MAX 50
 #define CHANNEL_NAME_MAX 64
 
diff --git a/handle.c b/handle.c
index c760144..75d42a9 100644
--- a/handle.c
+++ b/handle.c
@@ -124,9 +124,9 @@ names(struct Message *msg, struct Peer *peer)
 			continue;
 
 		memset(buf, 0, sizeof(buf));
-		for (j = 0; j < peer->channels[i]->users_c; ++j)
+		for (j = 0; j < peer->channels[i]->peers_c; ++j)
 		{
-			strlcat(buf, peer->channels[i]->users[j]->nick, sizeof(buf));
+			strlcat(buf, peer->channels[i]->peers[j].p->nick, sizeof(buf));
 			if (strlen(buf) >= MESSAGE_MAX - 4*PEER_NICK_MAX)
 			{
 				reply(peer, 353, peer->channels[i]->name, buf);
diff --git a/ircd.h b/ircd.h
index d05614c..0959d12 100644
--- a/ircd.h
+++ b/ircd.h
@@ -66,11 +66,13 @@ struct Channel
 	enum { GLOBAL, LOCAL, MODELESS, SAFE } type;
 	char name[CHANNEL_NAME_MAX];
 	struct {
-		char mode;
-		char param[MESSAGE_MAX - 1];
-	} modes[CHANNEL_MODES_MAX];
-	struct Peer *users[CHANNEL_USERS_MAX];
-	size_t modes_c, users_c;
+		struct Peer *p;
+		enum ChannelPeerMode {
+			BIT(CHANNEL_OPER),
+			BIT(CHANNEL_VOICE),
+		} modes;
+	} peers[CHANNEL_PEERS_MAX];
+	size_t modes_c, peers_c;
 };
 
 struct Oper
diff --git a/user.c b/user.c
index 719c60e..5d9bc15 100644
--- a/user.c
+++ b/user.c
@@ -88,17 +88,19 @@ skip:
 void
 user_remove(size_t pid)
 {
+	struct Peer *last;
 	size_t i, j;
 
 	for (i = 0; i < peers[pid].channels_c; ++i)
 		channel_exit(peers[pid].channels[i], &peers[pid]);
 
-	for (i = 0; i < peers[peers_c-1].channels_c; ++i)
+	last = &peers[peers_c-1];
+	for (i = 0; i < last->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)
+		for (j = 0; j < last->channels[i]->peers_c; ++j)
+			if (last->channels[i]->peers[j].p->fd == last->fd)
 				break;
-		if (j == peers[peers_c-1].channels[i]->users_c)
+		if (j == last->channels[i]->peers_c)
 		{
 			warnx(
 				"user_unlink(): %s@%s doesn't belong to %s, "
@@ -110,7 +112,7 @@ user_remove(size_t pid)
 			continue;
 		}
 
-		peers[peers_c-1].channels[i]->users[j] = &peers[pid];
+		last->channels[i]->peers[j].p = &peers[pid];
 	}
 
 	peers[pid] = peers[--peers_c];
diff --git a/writef.c b/writef.c
index 51346d9..a2283b9 100644
--- a/writef.c
+++ b/writef.c
@@ -59,9 +59,9 @@ writechanf(const struct Peer *except, const struct Channel *channel, const char
 	va_end(args);
 
 	count = 0;
-	for (i = 0; i < channel->users_c; ++i)
-		if (!except || channel->users[i]->fd != except->fd)
-			count += write(channel->users[i]->fd, buf, written) == written;
+	for (i = 0; i < channel->peers_c; ++i)
+		if (!except || channel->peers[i].p->fd != except->fd)
+			count += write(channel->peers[i].p->fd, buf, written) == written;
 
 	return count;
 }
@@ -83,8 +83,8 @@ announce(struct Peer *peer, const char *fmt, ...)
 	}
 
 	for (i = 0; i < peer->channels_c; ++i)
-		for (j = 0; j < peer->channels[i]->users_c; ++j)
-			peer->channels[i]->users[j]->flags |= ANNOUNCE;
+		for (j = 0; j < peer->channels[i]->peers_c; ++j)
+			peer->channels[i]->peers[j].p->flags |= ANNOUNCE;
 
 	for (i = 0; i < peers_c; ++i)
 		if (peers[i].flags & ANNOUNCE)