[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