about summary refs log tree commit diff
path: root/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'channel.c')
-rw-r--r--channel.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/channel.c b/channel.c
new file mode 100644
index 0000000..0cf0b30
--- /dev/null
+++ b/channel.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2026 Nakidai Perumenei <nakidai at disroot dot org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ircd.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#include <err.h>
+
+
+struct Channel channels[CHANNELS_MAX];
+size_t channels_c;
+
+int
+channel_join(struct Channel *channel, struct Peer *peer)
+{
+	if (channel->users_c == lengthof(channel->users)
+	 || peer->channels_c == lengthof(peer->channels))
+		return 1;
+
+	peer->channels[peer->channels_c++] = channel;
+	channel->users[channel->users_c++] = peer;
+	writechanf(
+		0,
+		channel,
+		":%s!%s@%s JOIN %s",
+		getnick(peer),
+		peer->user,
+		peer->host,
+		channel->name
+	);
+	return 0;
+}
+
+int
+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)
+			break;
+	ensure(i != channel->users_c, (void)0, 1);
+	channel->users[i] = channel->users[--channel->users_c];
+
+	for (i = 0; i < peer->channels_c; ++i)
+		if (!strcmp(peer->channels[i]->name, channel->name))
+			break;
+	ensure(i != peer->channels_c, warnx(
+		"channel_exit(): channel had user, but user hadn't channel"
+	), 1)
+	peer->channels[i] = peer->channels[--peer->channels_c];
+
+	if (!channel->users_c)
+	{
+		for (i = 0; i < channels_c; ++i)
+			if (!strcmp(channels[i].name, channel->name))
+				break;
+		ensure(i != channels_c, warnx(
+			"channel_exit(): couldn't find empty channel"
+		), 1);
+		channels[i] = channels[--channels_c];
+	}
+
+	return 0;
+}