[mw-devel] MW3 r1324 - in branches/wbhandlers/src: . server

welshbyte at sucs.org welshbyte at sucs.org
Sat Jan 19 16:27:15 GMT 2013


Author: welshbyte
Date: 2013-01-19 16:27:14 +0000 (Sat, 19 Jan 2013)
New Revision: 1324

Added:
   branches/wbhandlers/src/server/handlers.c
   branches/wbhandlers/src/server/handlers.h
Modified:
   branches/wbhandlers/src/ipc.c
   branches/wbhandlers/src/ipc.h
   branches/wbhandlers/src/server/Makefile
   branches/wbhandlers/src/server/servsock.c
   branches/wbhandlers/src/socket.c
   branches/wbhandlers/src/socket.h
   branches/wbhandlers/src/talker.c
Log:
- Don't use FOURCC for message types so the ipc_types enum can be sequential.
- Add a message handler lookup table with a clean api.
- Split out the message handling from servsock.c.


Modified: branches/wbhandlers/src/ipc.c
===================================================================
--- branches/wbhandlers/src/ipc.c	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/ipc.c	2013-01-19 16:27:14 UTC (rev 1324)
@@ -65,7 +65,7 @@
 	ipcsock->state = IPCSTATE_CONNECTED;
 
 	pid_t mypid = getpid();
-	ipc_message_t * msg = ipcmsg_create(FOURCC("HELO"), mypid);
+	ipc_message_t * msg = ipcmsg_create(IPC_HELO, mypid);
 	ipcmsg_append(msg, &userposn, sizeof(userposn));
 	const char *nonce = get_nonce();
 	ipcmsg_append(msg, nonce, strlen(nonce));

Modified: branches/wbhandlers/src/ipc.h
===================================================================
--- branches/wbhandlers/src/ipc.h	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/ipc.h	2013-01-19 16:27:14 UTC (rev 1324)
@@ -6,42 +6,38 @@
 #include "user.h"
 #include "socket.h"
 
-#define MKFOURCC(a,b,c,d) \
-	( ((uint32_t)a) | ( ((uint32_t)b) << 8 ) \
-	| ( ((uint32_t)c) << 16 ) | ( ((uint32_t)d) << 24 ) )
-
-
 enum ipc_types {
-	IPC_NOOP	= 0,	// Just go through the motions, don't actually write anything to the FIFO
-	IPC_NEWMAIL	= 1,
-	IPC_STATUS	= 2,
-	IPC_GROUPS	= 3,
-	IPC_REALNAME	= 4,
-	IPC_CONTACT	= 5,
-	IPC_LASTREAD	= 6,
-	IPC_SPECIAL	= 7,
-	IPC_TIMEOUT	= 8,
-	IPC_USERNAME	= 9,
-	IPC_TEXT	= 11,
-	IPC_CHATPRIVS	= 12,
-	IPC_CHATMODE	= 13,
-	IPC_KICK	= 14,
-	IPC_PASSWD	= 15,
-	IPC_CHANNEL	= 16,
-	IPC_WIZ		= 17,
-	IPC_GAG		= 18,
-	IPC_CLEARIGN	= 19,
-	IPC_SCRIPTIPC	= 21,
-	IPC_SCRIPTRPC	= 22,
-	IPC_CHECKONOFF	= 23,
-	IPC_PROTLEVEL	= 24,
-	IPC_PROTPOWER	= 25,
-	IPC_DOING	= 26,
-	IPC_UPTIME	= MKFOURCC('U','P','T','M'),
-	IPC_SAYTOROOM	= MKFOURCC('S','A','Y','R'),
-	IPC_SAYTOUSER	= MKFOURCC('S','A','Y','U'),
-	IPC_SAYTOALL	= MKFOURCC('W','A','L','L'),
-	IPC_TALKERROR	= MKFOURCC('T','E','R','R')
+	IPC_NOOP = 0, // Just go through the motions, don't actually write anything to the FIFO
+	IPC_NEWMAIL,
+	IPC_STATUS,
+	IPC_GROUPS,
+	IPC_REALNAME,
+	IPC_CONTACT,
+	IPC_LASTREAD,
+	IPC_SPECIAL,
+	IPC_TIMEOUT,
+	IPC_USERNAME,
+	IPC_TEXT,
+	IPC_CHATPRIVS,
+	IPC_CHATMODE,
+	IPC_KICK,
+	IPC_PASSWD,
+	IPC_CHANNEL,
+	IPC_WIZ,
+	IPC_GAG,
+	IPC_CLEARIGN,
+	IPC_SCRIPTIPC,
+	IPC_SCRIPTRPC,
+	IPC_CHECKONOFF,
+	IPC_PROTLEVEL,
+	IPC_PROTPOWER,
+	IPC_DOING,
+	IPC_HELO,
+	IPC_UPTIME,
+	IPC_SAYTOROOM,
+	IPC_SAYTOUSER,
+	IPC_SAYTOALL,
+	IPC_TALKERROR,
 };
 
 typedef int (send_filter)(const struct person * usr, const struct who * who, const void * info);

Modified: branches/wbhandlers/src/server/Makefile
===================================================================
--- branches/wbhandlers/src/server/Makefile	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/server/Makefile	2013-01-19 16:27:14 UTC (rev 1324)
@@ -46,7 +46,7 @@
 
 .PHONY: build install clean test
 
-mwserv: mwserv.o servsock.o ../socket.o ../files.o ../strings.o ../ipc.o ../iconv.o ../nonce.o ../rooms.o ../sqlite.o
+mwserv: mwserv.o servsock.o handlers.o ../socket.o ../files.o ../strings.o ../ipc.o ../iconv.o ../nonce.o ../rooms.o ../sqlite.o
 	$(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^
 
 clean:

Added: branches/wbhandlers/src/server/handlers.c
===================================================================
--- branches/wbhandlers/src/server/handlers.c	                        (rev 0)
+++ branches/wbhandlers/src/server/handlers.c	2013-01-19 16:27:14 UTC (rev 1324)
@@ -0,0 +1,187 @@
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "../util.h"
+#include "../rooms.h"
+#include "../nonce.h"
+#include "../files.h"
+#include "../talker_privs.h"
+#include "handlers.h"
+#include "servsock.h"
+
+extern time_t uptime;
+
+/* client just told us who they are */
+static void handle_helo(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	memcpy(&conn->addr, &msg->head.src, sizeof(conn->addr));
+	if (msg->bodylen < 4) {
+		printf("Invalid HELO from fd=%d. dropping.\n", conn->fd);
+		drop_connection(conn);
+		return;
+	}
+	if (!match_nonce(&msg->body[4])) {
+		printf("Mismatched nonce from fd=%d. dropping.\n", conn->fd);
+		drop_connection(conn);
+		return;
+	}
+	memcpy(&conn->user, msg->body, sizeof(conn->user));
+	printf("WHO Add: pid=%d posn=%d\n", conn->addr, conn->user);
+	who_add(conn->addr, conn->user);
+	conn->state = IPCSTATE_VALID;
+}
+
+/* ask the server how long it has been up */
+static void handle_uptm(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	time_t now = time(0);
+
+	msg = ipcmsg_create(IPC_UPTIME, 0);
+	ipcmsg_destination(msg, conn->addr);
+
+	json_t * j = json_init(NULL);
+	json_addint(j, "uptime", now - uptime);
+	AUTOFREE_BUFFER version = NULL;
+	asprintf(&version, "%s.%s.%s", VER_MAJ, VER_MIN, VER_TWK);
+	json_addstring(j, "version", version);
+	ipcmsg_json_encode(msg, j);
+	msg_attach(msg, conn);
+	ipcmsg_destroy(msg);
+	json_decref(j);
+}
+
+/* send message to everyone in the room */
+static void handle_sayr(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	/* eventually this should be a server maintained list */
+	int who_fd = openwhofile(O_RDONLY);
+	int users_fd = openuserfile(O_RDONLY);
+	struct who who;
+	struct person user;
+	json_t * j = json_init(msg);
+
+	const char * exclude = json_getstring(j, "exclude");
+
+	struct room room;
+	RoomInit(&room);
+	LoadRoom(&room, msg->head.dst);
+
+	while (read(who_fd, &who, sizeof(who)) > 0) {
+		if (who.posn < 0) continue;
+		if (who.pid <= 0) continue;
+
+		lseek(users_fd, who.posn, SEEK_SET);
+		if (read(users_fd, &user, sizeof(user)) <= 0) continue;
+
+		/* have we been told to exclude someone in this room */
+		if (exclude!=NULL && strcasecmp(exclude, user.name)==0) continue;
+
+		/* room matches, send them a copy */
+		if (user.room == msg->head.dst) {
+			msg_attach_to(msg, who.pid);
+		} else
+		/* room not soundproof, and user has global on */
+		if (room.sproof < 1 && (user.chatmode & CM_GLOBAL)) {
+			msg_attach_to(msg, who.pid);
+		}
+	}
+	RoomDestroy(&room);
+	json_decref(j);
+	close(who_fd);
+	close(users_fd);
+}
+
+/* message is for a specific username */
+static void handle_sayu(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	/* eventually this should be a server maintained list */
+	int who_fd = openwhofile(O_RDONLY);
+	int users_fd = openuserfile(O_RDONLY);
+	struct who who;
+	struct person user;
+	json_t * j = json_init(msg);
+	int found = 0;
+
+	const char * target = json_getstring(j, "target");
+
+	while (read(who_fd, &who, sizeof(who)) > 0) {
+		if (who.posn < 0) continue;
+		if (who.pid <= 0) continue;
+
+		lseek(users_fd, who.posn, SEEK_SET);
+		if (read(users_fd, &user, sizeof(user)) <= 0) continue;
+
+		/* is this the username we are looking for */
+		if (strcasecmp(target, user.name)==0) {
+			msg_attach_to(msg, who.pid);
+			found++;
+		}
+	}
+	if (found < 1) {
+		send_error(conn, msg, "User '%s' not found", target); 
+	}
+	json_decref(j);
+	close(who_fd);
+	close(users_fd);
+}
+
+/* send message to everyone (unless this room is soundproof) */
+static void handle_wall(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	/* eventually this should be a server maintained list */
+	int who_fd = openwhofile(O_RDONLY);
+	int users_fd = openuserfile(O_RDONLY);
+	struct who who;
+	struct person user;
+	struct person from;
+
+	/* the sender */
+	lseek(users_fd, conn->user, SEEK_SET);
+	read(users_fd, &from, sizeof(from));
+
+	/* load the senders room to see if its soundproof */
+	struct room room;
+	RoomInit(&room);
+	LoadRoom(&room, from.room);
+
+	printf("Shout from '%s' in %d (%s)\n", from.name, room.num, room.name);
+
+	while (read(who_fd, &who, sizeof(who)) > 0) {
+		if (who.posn < 0) continue;
+		if (who.pid <= 0) continue;
+
+		lseek(users_fd, who.posn, SEEK_SET);
+		if (read(users_fd, &user, sizeof(user)) <= 0) continue;
+
+		/* senders room is soundproof, act as if it was say in this room*/
+		if (room.sproof > 0) {
+			/* room matches, send them a copy */
+			if (user.room == from.room) {
+				msg_attach_to(msg, who.pid);
+				printf("Soundproof %s in %d\n", user.name, user.room);
+			} else
+				printf("Soundproof %s not in %d (is in %d)\n", user.name, from.room, user.room);
+		} else
+		/* room not soundproof, everyone gets it */
+		{
+			msg_attach_to(msg, who.pid);
+			printf("Shout to %s in %d\n", user.name, user.room);
+		}
+	}
+	RoomDestroy(&room);
+	close(who_fd);
+	close(users_fd);
+}
+
+/* Define this statically for now. For future extensions it could be changed to
+   a thing which we can add handlers to at runtime */
+const struct msg_handler_map msg_handlers[] = {
+	[IPC_HELO] = {IPCSTATE_CONNECTED, handle_helo},
+	[IPC_UPTIME] = {IPCSTATE_VALID, handle_uptm},
+	[IPC_SAYTOROOM] = {IPCSTATE_VALID, handle_sayr},
+	[IPC_SAYTOUSER] = {IPCSTATE_VALID, handle_sayu},
+	[IPC_SAYTOALL] = {IPCSTATE_VALID, handle_wall},
+};
+const unsigned int msg_handlers_size = sizeof(msg_handlers) / sizeof(msg_handlers[0]);

Added: branches/wbhandlers/src/server/handlers.h
===================================================================
--- branches/wbhandlers/src/server/handlers.h	                        (rev 0)
+++ branches/wbhandlers/src/server/handlers.h	2013-01-19 16:27:14 UTC (rev 1324)
@@ -0,0 +1,20 @@
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+#include "../ipc.h"
+
+typedef void (msg_handler_t)(ipc_connection_t *conn, ipc_message_t *msg);
+
+struct msg_handler_map {
+	enum ipcsock_state msg_state;
+	msg_handler_t *msg_handler;
+};
+
+extern const struct msg_handler_map msg_handlers[];
+extern const unsigned int msg_handlers_size;
+
+#define msg_handler_lookup_safe(ipc_type, ipc_state) \
+    ((ipc_type < msg_handlers_size && msg_handlers[ipc_type].msg_state == ipc_state) ? \
+      msg_handlers[ipc_type].msg_handler : NULL)
+
+#endif /* MESSAGES_H */

Modified: branches/wbhandlers/src/server/servsock.c
===================================================================
--- branches/wbhandlers/src/server/servsock.c	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/server/servsock.c	2013-01-19 16:27:14 UTC (rev 1324)
@@ -15,11 +15,9 @@
 #include "../socket.h"
 #include "servsock.h"
 #include "../files.h"
-#include "../nonce.h"
 #include "../util.h"
-#include "../who.h"
-#include "../rooms.h"
-#include "../talker_privs.h"
+#include "../ipc.h"
+#include "handlers.h"
 
 struct list_head connection_list;
 
@@ -224,7 +222,6 @@
 	free(mtx);
 }
 
-extern time_t uptime;
 			
 void send_error(ipc_connection_t *conn, ipc_message_t *orig, const char *format, ...) __attribute__((format (printf, 3, 4)));
 
@@ -236,7 +233,7 @@
 	vasprintf(&text, format, va);
 	va_end(va);
 
-	ipc_message_t * msg = ipcmsg_create(FOURCC("TERR"), 0);
+	ipc_message_t * msg = ipcmsg_create(IPC_TALKERROR, 0);
 	ipcmsg_destination(msg, conn->addr);
 
 	char type[5];
@@ -255,180 +252,14 @@
 {
 	ipcmsg_summary("PROCESS", msg);
 
-	/* client just told us who they are */
-	if (msg->head.type == FOURCC("HELO")) {
-		memcpy(&conn->addr, &msg->head.src, sizeof(conn->addr));
-		if (msg->bodylen < 4) {
-			printf("Invalid HELO from fd=%d. dropping.\n", conn->fd);
-			ipcmsg_destroy(msg);
-			drop_connection(conn);
-			return;
-		}
-		if (!match_nonce(&msg->body[4])) {
-			printf("Mismatched nonce from fd=%d. dropping.\n", conn->fd);
-			ipcmsg_destroy(msg);
-			drop_connection(conn);
-			return;
-		}
-		memcpy(&conn->user, msg->body, sizeof(conn->user));
-		printf("WHO Add: pid=%d posn=%d\n", conn->addr, conn->user);
-		who_add(conn->addr, conn->user);
-		conn->state = IPCSTATE_VALID;
+	/* Find a message handler for this message type */
+	msg_handler_t *handler = msg_handler_lookup_safe(msg->head.type, conn->state);
+	if (handler) {
+		handler(conn, msg);
 		ipcmsg_destroy(msg);
 		return;
 	}
 
-	/* message types after this point are only valid if your logged in */
-	if (conn->state != IPCSTATE_VALID) return;
-
-	/* ask the server how long it has been up */
-	if (msg->head.type == FOURCC("UPTM")) {
-		time_t now = time(0);
-
-		ipcmsg_destroy(msg);
-
-		msg = ipcmsg_create(FOURCC("UPTM"), 0);
-		ipcmsg_destination(msg, conn->addr);
-
-		json_t * j = json_init(NULL);
-		json_addint(j, "uptime", now - uptime);
-		AUTOFREE_BUFFER version = NULL;
-		asprintf(&version, "%s.%s.%s", VER_MAJ, VER_MIN, VER_TWK);
-		json_addstring(j, "version", version);
-		ipcmsg_json_encode(msg, j);
-		msg_attach(msg, conn);
-		ipcmsg_destroy(msg);
-		json_decref(j);
-		return;
-	}
-
-	/* send message to everyone in the room */
-	if (msg->head.type == FOURCC("SAYR")) {
-		/* eventually this should be a server maintained list */
-		int who_fd = openwhofile(O_RDONLY);
-		int users_fd = openuserfile(O_RDONLY);
-		struct who who;
-		struct person user;
-		json_t * j = json_init(msg);
-
-		const char * exclude = json_getstring(j, "exclude");
-
-		struct room room;
-		RoomInit(&room);
-		LoadRoom(&room, msg->head.dst);
-
-		while (read(who_fd, &who, sizeof(who)) > 0) {
-			if (who.posn < 0) continue;
-			if (who.pid <= 0) continue;
-
-			lseek(users_fd, who.posn, SEEK_SET);
-			if (read(users_fd, &user, sizeof(user)) <= 0) continue;
-
-			/* have we been told to exclude someone in this room */
-			if (exclude!=NULL && strcasecmp(exclude, user.name)==0) continue;
-
-			/* room matches, send them a copy */
-			if (user.room == msg->head.dst) {
-				msg_attach_to(msg, who.pid);
-			} else
-			/* room not soundproof, and user has global on */
-			if (room.sproof < 1 && (user.chatmode & CM_GLOBAL)) {
-				msg_attach_to(msg, who.pid);
-			}
-		}
-		RoomDestroy(&room);
-		json_decref(j);
-		close(who_fd);
-		close(users_fd);
-		ipcmsg_destroy(msg);
-		return;
-	}
-
-	/* message is for a specific username */
-	if (msg->head.type == FOURCC("SAYU")) {
-		/* eventually this should be a server maintained list */
-		int who_fd = openwhofile(O_RDONLY);
-		int users_fd = openuserfile(O_RDONLY);
-		struct who who;
-		struct person user;
-		json_t * j = json_init(msg);
-		int found = 0;
-
-		const char * target = json_getstring(j, "target");
-
-		while (read(who_fd, &who, sizeof(who)) > 0) {
-			if (who.posn < 0) continue;
-			if (who.pid <= 0) continue;
-
-			lseek(users_fd, who.posn, SEEK_SET);
-			if (read(users_fd, &user, sizeof(user)) <= 0) continue;
-
-			/* is this the username we are looking for */
-			if (strcasecmp(target, user.name)==0) {
-				msg_attach_to(msg, who.pid);
-				found++;
-			}
-		}
-		if (found < 1) {
-			send_error(conn, msg, "User '%s' not found", target); 
-		}
-		json_decref(j);
-		close(who_fd);
-		close(users_fd);
-		ipcmsg_destroy(msg);
-
-		return;
-	}
-
-	/* send message to everyone (unless this room is soundproof) */
-	if (msg->head.type == FOURCC("WALL")) {
-		/* eventually this should be a server maintained list */
-		int who_fd = openwhofile(O_RDONLY);
-		int users_fd = openuserfile(O_RDONLY);
-		struct who who;
-		struct person user;
-		struct person from;
-
-		/* the sender */
-		lseek(users_fd, conn->user, SEEK_SET);
-		read(users_fd, &from, sizeof(from));
-
-		/* load the senders room to see if its soundproof */
-		struct room room;
-		RoomInit(&room);
-		LoadRoom(&room, from.room);
-
-		printf("Shout from '%s' in %d (%s)\n", from.name, room.num, room.name);
-
-		while (read(who_fd, &who, sizeof(who)) > 0) {
-			if (who.posn < 0) continue;
-			if (who.pid <= 0) continue;
-
-			lseek(users_fd, who.posn, SEEK_SET);
-			if (read(users_fd, &user, sizeof(user)) <= 0) continue;
-
-			/* senders room is soundproof, act as if it was say in this room*/
-			if (room.sproof > 0) {
-				/* room matches, send them a copy */
-				if (user.room == from.room) {
-					msg_attach_to(msg, who.pid);
-					printf("Soundproof %s in %d\n", user.name, user.room);
-				} else
-					printf("Soundproof %s not in %d (is in %d)\n", user.name, from.room, user.room);
-			} else
-			/* room not soundproof, everyone gets it */
-			{
-				msg_attach_to(msg, who.pid);
-				printf("Shout to %s in %d\n", user.name, user.room);
-			}
-		}
-		RoomDestroy(&room);
-		close(who_fd);
-		close(users_fd);
-		ipcmsg_destroy(msg);
-		return;
-	}
-
 	/* otherwise redistribute this message to intended target */
 	msg_attach_to(msg, msg->head.dst);
 	ipcmsg_destroy(msg);

Modified: branches/wbhandlers/src/socket.c
===================================================================
--- branches/wbhandlers/src/socket.c	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/socket.c	2013-01-19 16:27:14 UTC (rev 1324)
@@ -9,12 +9,6 @@
 
 #include "socket.h"
 
-/* generate FOURCC code from a string */
-inline unsigned int FOURCC(const char *a)
-{
-	return ((a[3]<<24)|(a[2]<<16)|(a[1]<<8)|a[0]);
-}
-
 /* create an empty message */
 ipc_message_t * ipcmsg_create(uint32_t type, uint32_t src)
 {

Modified: branches/wbhandlers/src/socket.h
===================================================================
--- branches/wbhandlers/src/socket.h	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/socket.h	2013-01-19 16:27:14 UTC (rev 1324)
@@ -57,7 +57,6 @@
 
 #define _MIN(a,b) (a<b)?a:b
 
-unsigned int FOURCC(const char *a);
 /* socket.c */
 ipc_message_t *ipcmsg_create(uint32_t type,uint32_t src);
 void ipcmsg_append(ipc_message_t *msg, const void *data, int len);

Modified: branches/wbhandlers/src/talker.c
===================================================================
--- branches/wbhandlers/src/talker.c	2013-01-19 16:08:01 UTC (rev 1323)
+++ branches/wbhandlers/src/talker.c	2013-01-19 16:27:14 UTC (rev 1324)
@@ -250,7 +250,7 @@
 
 void t_uptime(CommandList *cm, int argc, const const char **argv, char *args)
 {
-	ipc_message_t * msg = ipcmsg_create(FOURCC("UPTM"), getpid());
+	ipc_message_t * msg = ipcmsg_create(IPC_UPTIME, getpid());
 	ipcmsg_transmit(msg);
 }
 




More information about the mw-devel mailing list