diff lib/irccd/irccd.c @ 958:533639ec5e9c

misc: use sys/queue.h
author David Demelier <markand@malikania.fr>
date Thu, 21 Jan 2021 23:15:20 +0100
parents 3167c51f0c84
children 32f93ef20122
line wrap: on
line diff
--- a/lib/irccd/irccd.c	Thu Jan 21 15:34:25 2021 +0100
+++ b/lib/irccd/irccd.c	Thu Jan 21 23:15:20 2021 +0100
@@ -27,13 +27,11 @@
 
 #include "event.h"
 #include "irccd.h"
-#include "list.h"
 #include "log.h"
 #include "peer.h"
 #include "plugin.h"
 #include "rule.h"
 #include "server.h"
-#include "set.h"
 #include "transport.h"
 #include "util.h"
 
@@ -47,22 +45,15 @@
 	void *data;
 };
 
-struct irc irc;
+struct irc irc = {
+	.servers = LIST_HEAD_INITIALIZER(),
+	.peers = LIST_HEAD_INITIALIZER(),
+	.plugins = LIST_HEAD_INITIALIZER(),
+	.rules = TAILQ_HEAD_INITIALIZER(irc.rules)
+};
 
 static int pipes[2];
 
-static int
-cmp_plugin(const struct irc_plugin *p1, const struct irc_plugin *p2)
-{
-	return strcmp(p1->name, p2->name);
-}
-
-static int
-cmp_peer(const struct irc_peer *p1, const struct irc_peer *p2)
-{
-	return p1->fd - p2->fd;
-}
-
 static bool
 is_command(const struct irc_plugin *p, const struct irc_event *ev)
 {
@@ -105,67 +96,80 @@
 {
 	switch (ev->type) {
 	case IRC_EVENT_COMMAND:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->message.channel, ev->message.origin, p->name, "onCommand");
 	case IRC_EVENT_CONNECT:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    NULL, NULL, p->name, "onConnect");
 	case IRC_EVENT_DISCONNECT:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    NULL, NULL, p->name, "onDisconnect");
 	case IRC_EVENT_INVITE:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->invite.channel, ev->invite.origin, p->name, "onInvite");
 	case IRC_EVENT_JOIN:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->join.channel, ev->join.origin, p->name, "onJoin");
 	case IRC_EVENT_KICK:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->kick.channel, ev->kick.origin, p->name, "onKick");
 		break;
 	case IRC_EVENT_ME:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->message.channel, ev->message.origin, p->name, "onMe");
 	case IRC_EVENT_MESSAGE:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->message.channel, ev->message.origin, p->name, "onMessage");
 	case IRC_EVENT_MODE:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->mode.channel, ev->mode.origin, p->name, "onMode");
 	case IRC_EVENT_NAMES:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->names.channel, NULL, p->name, "onNames");
 	case IRC_EVENT_NICK:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    NULL, ev->nick.origin, p->name, "onNick");
 	case IRC_EVENT_NOTICE:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->notice.channel, ev->notice.origin, p->name, "onNotice");
 	case IRC_EVENT_PART:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->part.channel, ev->part.origin, p->name, "onPart");
 	case IRC_EVENT_TOPIC:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    ev->topic.channel, ev->topic.origin, p->name, "onTopic");
 	case IRC_EVENT_WHOIS:
-		return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name,
+		return irc_rule_matchlist(&irc.rules, ev->server->name,
 		    NULL, NULL, p->name, "onWhois");
 	default:
 		return true;
 	}
 }
 
+static inline size_t
+pollable(void)
+{
+	const struct irc_server *s;
+	const struct irc_peer *p;
+	size_t i = 2;                   /* pipe + transport. */
+
+	LIST_FOREACH(s, &irc.servers, link)
+		++i;
+	LIST_FOREACH(p, &irc.peers, link)
+		++i;
+
+	return i;
+}
+
 static struct pkg
 prepare(void)
 {
+	struct irc_peer *p;
+	struct irc_server *s;
 	struct pkg pkg = {0};
 	size_t i = 0;
 
-	pkg.fdsz += 1;                  /* pipe  */
-	pkg.fdsz += 1;                  /* transport fd */
-	pkg.fdsz += irc.serversz;       /* servers */
-	pkg.fdsz += irc.peersz;         /* transport peers */
-
+	pkg.fdsz = pollable();
 	pkg.fds = irc_util_calloc(pkg.fdsz, sizeof (*pkg.fds));
 
 	/* pipe */
@@ -175,9 +179,9 @@
 	/* transport */
 	irc_transport_prepare(&pkg.fds[i++]);
 
-	for (size_t p = 0; p < irc.peersz; ++p)
-		irc_peer_prepare(&irc.peers[p], &pkg.fds[i++]);
-	for (struct irc_server *s = irc.servers; s; s = s->next)
+	LIST_FOREACH(p, &irc.peers, link)
+		irc_peer_prepare(p, &pkg.fds[i++]);
+	LIST_FOREACH(s, &irc.servers, link)
 		irc_server_prepare(s, &pkg.fds[i++]);
 
 	return pkg;
@@ -186,20 +190,21 @@
 static inline void
 broadcast(const struct irc_event *ev)
 {
-	char buf[IRC_MESSAGE_MAX];
+	char buf[IRC_BUF_LEN];
+	struct irc_peer *p;
 
 	if (!irc_event_str(ev, buf, sizeof (buf)))
 		return;
 
-	for (size_t i = 0; i < irc.peersz; ++i)
-		if (irc.peers[i].is_watching)
-			irc_peer_send(&irc.peers[i], buf);
+	LIST_FOREACH(p, &irc.peers, link)
+		if (p->is_watching)
+			irc_peer_send(p, buf);
 }
 
 static void
 invoke(struct irc_event *ev)
 {
-	struct irc_plugin *plgcmd = NULL;
+	struct irc_plugin *p, *tmp, *plgcmd = NULL;
 
 	/*
 	 * Invoke for every plugin the event verbatim. Then, the event may match
@@ -215,11 +220,11 @@
 	 * onMessage for hangman and logger but onCommand for ask. As such call
 	 * hangman and logger first and modify event before ask.
 	 */
-	for (size_t i = 0; i < irc.pluginsz; ++i) {
-		if (is_command(&irc.plugins[i], ev))
-			plgcmd = &irc.plugins[i];
-		else if (invokable(&irc.plugins[i], ev))
-			irc_plugin_handle(&irc.plugins[i], ev);
+	LIST_FOREACH_SAFE(p, &irc.plugins, link, tmp) {
+		if (is_command(p, ev))
+			plgcmd = p;
+		else if (invokable(p, ev))
+			irc_plugin_handle(p, ev);
 	}
 
 	if (plgcmd && invokable(plgcmd, ev))
@@ -244,7 +249,7 @@
 process(struct pkg *pkg)
 {
 	struct irc_server *s;
-	struct irc_peer peer;
+	struct irc_peer *p, *ptmp;
 	struct irc_event ev;
 
 	if (poll(pkg->fds, pkg->fdsz, 1000) < 0 && errno != EINTR)
@@ -258,20 +263,19 @@
 	for (size_t i = 0; i < pkg->fdsz; ++i) {
 		pipe_flush(&pkg->fds[i]);
 
-		IRC_LIST_FOREACH(irc.servers, s)
+		LIST_FOREACH(s, &irc.servers, link)
 			irc_server_flush(s, &pkg->fds[i]);
 
 		/* Accept new transport client. */
-		if (irc_transport_flush(&pkg->fds[i], &peer))
-			IRC_SET_ALLOC_PUSH(&irc.peers, &irc.peersz, &peer, cmp_peer);
+		if ((p = irc_transport_flush(&pkg->fds[i])))
+			LIST_INSERT_HEAD(&irc.peers, p, link);
 
 		/* Flush clients. */
-		for (size_t p = 0; p < irc.peersz; ) {
-			if (!irc_peer_flush(&irc.peers[p], &pkg->fds[i])) {
-				irc_peer_finish(&irc.peers[p]);
-				IRC_SET_ALLOC_REMOVE(&irc.peers, &irc.peersz, &irc.peers[p]);
-			} else
-				++p;
+		LIST_FOREACH_SAFE(p, &irc.peers, link, ptmp) {
+			if (!irc_peer_flush(p, &pkg->fds[i])) {
+				irc_peer_finish(p);
+				LIST_REMOVE(p, link);
+			}
 		}
 	}
 
@@ -279,7 +283,7 @@
 	 * For every server, poll any kind of new event and pass them to the
 	 * plugin unless the rules explicitly disallow us to do so.
 	 */
-	IRC_LIST_FOREACH(irc.servers, s) {
+	LIST_FOREACH(s, &irc.servers, link) {
 		while (irc_server_poll(s, &ev)) {
 			broadcast(&ev);
 			invoke(&ev);
@@ -294,6 +298,18 @@
 	free(pkg->fds);
 }
 
+static inline size_t
+rulescount(void)
+{
+	const struct irc_rule *r;
+	size_t total = 0;
+
+	TAILQ_FOREACH(r, &irc.rules, link)
+		total++;
+
+	return total;
+}
+
 void
 irc_bot_init(void)
 {
@@ -304,24 +320,22 @@
 }
 
 void
-irc_bot_add_server(struct irc_server *s)
+irc_bot_server_add(struct irc_server *s)
 {
 	assert(s);
 
 	irc_server_incref(s);
 	irc_server_connect(s);
 
-	IRC_LIST_ADD(irc.servers, s);
-
-	irc.serversz++;
+	LIST_INSERT_HEAD(&irc.servers, s, link);
 }
 
 struct irc_server *
-irc_bot_find_server(const char *name)
+irc_bot_server_find(const char *name)
 {
 	struct irc_server *s;
 
-	for (s = irc.servers; s; s = s->next)
+	LIST_FOREACH(s, &irc.servers, link)
 		if (strcmp(s->name, name) == 0)
 			return s;
 
@@ -329,11 +343,11 @@
 }
 
 void
-irc_bot_remove_server(const char *name)
+irc_bot_server_remove(const char *name)
 {
 	struct irc_server *s;
 
-	if (!(s = irc_bot_find_server(name)))
+	if (!(s = irc_bot_server_find(name)))
 		return;
 
 	irc_server_disconnect(s);
@@ -344,43 +358,43 @@
 		.server = s
 	});
 
-	IRC_LIST_REMOVE(irc.servers, s);
-
+	LIST_REMOVE(s, link);
 	irc_server_decref(s);
-	irc.serversz--;
 }
 
 void
-irc_bot_clear_servers(void)
+irc_bot_server_clear(void)
 {
-	struct irc_server *s, *next;
+	struct irc_server *s, *tmp;
 
-	IRC_LIST_FOREACH_SAFE(irc.servers, s, next)
-		irc_bot_remove_server(s->name);
+	LIST_FOREACH_SAFE(s, &irc.servers, link, tmp)
+		irc_bot_server_remove(s->name);
 }
 
 void
-irc_bot_add_plugin(const struct irc_plugin *p)
+irc_bot_add_plugin(struct irc_plugin *p)
 {
 	assert(p);
 
-	IRC_SET_ALLOC_PUSH(&irc.plugins, &irc.pluginsz, p, cmp_plugin);
+	LIST_INSERT_HEAD(&irc.plugins, p, link);
 
 	irc_log_info("plugin %s: %s", p->name, p->description);
 	irc_log_info("plugin %s: version %s, from %s (%s license)", p->name,
 	    p->version, p->author, p->license);
 
-	irc_plugin_load(&irc.plugins[irc.pluginsz - 1]);
+	irc_plugin_load(p);
 }
 
 struct irc_plugin *
 irc_bot_find_plugin(const char *name)
 {
-	struct irc_plugin key = {0};
+	struct irc_plugin *p;
 
-	strlcpy(key.name, name, sizeof (key.name));
+	LIST_FOREACH(p, &irc.plugins, link)
+		if (strcmp(p->name, name) == 0)
+			return p;
 
-	return IRC_SET_FIND(irc.plugins, irc.pluginsz, &key, cmp_plugin);
+	return NULL;
 }
 
 void
@@ -394,37 +408,49 @@
 	irc_plugin_unload(p);
 	irc_plugin_finish(p);
 
-	IRC_SET_ALLOC_REMOVE(&irc.plugins, &irc.pluginsz, p);
+	LIST_REMOVE(p, link);
 }
 
-bool
-irc_bot_insert_rule(const struct irc_rule *rule, size_t i)
+void
+irc_bot_rule_insert(struct irc_rule *rule, size_t index)
 {
 	assert(rule);
 
-	if (irc.rulesz >= IRC_RULE_MAX) {
-		errno = ENOMEM;
-		return false;
-	}
+	if (index == 0)
+		TAILQ_INSERT_HEAD(&irc.rules, rule, link);
+	else if (index >= rulescount())
+		TAILQ_INSERT_TAIL(&irc.rules, rule, link);
+	else {
+		struct irc_rule *pos = TAILQ_FIRST(&irc.rules);
 
-	if (i >= irc.rulesz)
-		i = irc.rulesz;
+		for (size_t i = 0; i < index; ++i)
+			pos = TAILQ_NEXT(pos, link);
 
-	memmove(&irc.rules[i + 1], &irc.rules[i], sizeof (*irc.rules) * (irc.rulesz++ - i));
-	memcpy(&irc.rules[i], rule, sizeof (*rule));
-
-	return true;
+		TAILQ_INSERT_AFTER(&irc.rules, pos, rule, link);
+	}
 }
 
 void
-irc_bot_remove_rule(size_t i)
+irc_bot_rule_remove(size_t index)
 {
-	assert(i < irc.rulesz);
+	assert(index < rulescount());
+
+	struct irc_rule *pos = TAILQ_FIRST(&irc.rules);
+
+	for (size_t i = 0; i < index; ++i)
+		pos = TAILQ_NEXT(pos, link);
 
-	if (i + 1 >= irc.rulesz)
-		irc.rulesz--;
-	else
-		memmove(&irc.rules[i], &irc.rules[i + 1], sizeof (*irc.rules) * (irc.rulesz-- - i));
+	TAILQ_REMOVE(&irc.rules, pos, link);
+}
+
+void
+irc_bot_rule_clear(void)
+{
+	struct irc_rule *r, *tmp;
+
+	TAILQ_FOREACH_SAFE(r, &irc.rules, link, tmp)
+		irc_rule_finish(r);
+	TAILQ_INIT(&irc.rules);
 }
 
 void