[mw-devel] MW3 r1390 - in trunk/src: . client server

arthur at sucs.org arthur at sucs.org
Tue Sep 22 17:31:17 BST 2015


Author: arthur
Date: 2015-09-22 17:31:15 +0100 (Tue, 22 Sep 2015)
New Revision: 1390

Modified:
   trunk/src/client/chattable.c
   trunk/src/client/talker.c
   trunk/src/client/talker.h
   trunk/src/ipc.h
   trunk/src/server/replay.c
   trunk/src/server/replay.h
   trunk/src/server/servsock.c
Log:
Store all past messages and replay them.

Needs work: message head is currently pid of sender, 
      needs to be userposn of sender instead/aswell


Modified: trunk/src/client/chattable.c
===================================================================
--- trunk/src/client/chattable.c	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/client/chattable.c	2015-09-22 16:31:15 UTC (rev 1390)
@@ -56,6 +56,7 @@
 {"quit"		,0x0000	,0, "Usage: quit", "Leave Talker", t_quit, 1},
 {"raw"		,0x0001	,1, "Usage: raw <message>", "Send raw message", t_raw, 1},
 {"remove"	,0x0808	,1, "Usage: remove <user> [reason]", "Eject user from BBS, ignoring protection", t_remove, 1},
+{"replay"	,0x0000	,2, "Usage: replay {since|serial|count} <number>", "Replay previous messages", t_replay, 1},
 {"restart"	,0x0200	,0, "Usage: restart", "Reload and restart all scripts exactly as at logon", t_restart, 1},
 {"room"		,0x0000	,1, "Usage: room <room>", "Change rooms", t_room, 1},
 {"runaway"	,0x0200	,1, "Usage: runaway <number>", "Set the number of lines before script runaway", t_runaway, 1},

Modified: trunk/src/client/talker.c
===================================================================
--- trunk/src/client/talker.c	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/client/talker.c	2015-09-22 16:31:15 UTC (rev 1390)
@@ -1689,6 +1689,21 @@
 	}
 }
 
+void t_replay(CommandList *cm, int argc, const char **argv, char *args)
+{
+	if (argc < 2) {
+		printf("Insufficient arguments.\n");
+		return;
+	}
+
+	ipc_message_t * msg = ipcmsg_create(IPC_REPLAY, getpid());
+	json_t * j = json_init(NULL);
+	json_addint(j, argv[1], atoll(argv[2]));
+	ipcmsg_json_encode(msg, j);
+	json_decref(j);
+	ipcmsg_transmit(msg);
+}
+
 /* changes room, returning error code on failure
  * 0 - ok
  * 1 - hidden/locked

Modified: trunk/src/client/talker.h
===================================================================
--- trunk/src/client/talker.h	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/client/talker.h	2015-09-22 16:31:15 UTC (rev 1390)
@@ -42,6 +42,7 @@
 void t_mrod(CommandList *cm, int argc, const char **argv, char *args);
 void t_kick(CommandList *cm, int argc, const char **argv, char *args);
 void t_remove(CommandList *cm, int argc, const char **argv, char *args);
+void t_replay(CommandList *cm, int argc, const char **argv, char *args);
 void t_ignore(CommandList *cm, int argc, const char **argv, char *args);
 void t_unignore(CommandList *cm, int argc, const char **argv, char *args);
 void t_ignorelist(CommandList *cm, int argc, const char **argv, char *args);

Modified: trunk/src/ipc.h
===================================================================
--- trunk/src/ipc.h	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/ipc.h	2015-09-22 16:31:15 UTC (rev 1390)
@@ -48,7 +48,8 @@
 	IPC_SAYTOROOM	= FCC('SAYR'),
 	IPC_SAYTOUSER	= FCC('SAYU'),
 	IPC_SAYTOALL	= FCC('WALL'),
-	IPC_TALKERROR	= FCC('TERR')
+	IPC_TALKERROR	= FCC('TERR'),
+	IPC_REPLAY      = FCC('PLAY')
 };
 
 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))

Modified: trunk/src/server/replay.c
===================================================================
--- trunk/src/server/replay.c	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/server/replay.c	2015-09-22 16:31:15 UTC (rev 1390)
@@ -19,10 +19,16 @@
 #include <talker_privs.h>
 #include <ipc.h>
 
+#include "servsock.h"
 #include "replay.h"
 
+#define STORE_SIZE 1000
+
 static uint64_t serial = 0;
 
+static ipc_message_t ** store = NULL;
+static int store_next = 0;
+static int store_len = 0;
 
 /* look at the history and set the serial number
  * appropriately.
@@ -32,9 +38,38 @@
 	serial = 1;
 }
 
+static int store_wrap(int index)
+{
+	while (index < 0) index += STORE_SIZE;
+	while (index >= STORE_SIZE) index -= STORE_SIZE;
+	return index;
+}
+
 /* store the message for later replay */
 void store_message(ipc_message_t *msg)
 {
+	if (store == NULL) {
+		/* create the store */
+		store = calloc(STORE_SIZE, sizeof(ipc_message_t *));
+		store_next = 0;
+		store_len = 0;
+	}
+
+	if (store_len >= STORE_SIZE) {
+		/* store is full, discard oldest, 
+		 * it will have wrapped, so store_next is the last one */
+		ipcmsg_destroy(store[store_next]);
+		store_len--;
+		store[store_next] = NULL;
+	}
+
+	/* add to ref count so it wont get cleaned away yet
+	 * insert it at the current location and bump pointers
+	 */
+	msg->refcount++;
+	store[store_next] = msg;
+	store_len++;
+	store_next = store_wrap( store_next + 1 );
 }
 
 /* assign a unique serial number to each message
@@ -46,6 +81,122 @@
 	if (serial == 0) load_serial();
 	msg->head.serial = serial++;
 	msg->head.when = time(NULL);
+}
 
-	store_message(msg);
+void replay(ipc_connection_t *conn, ipc_message_t *msg)
+{
+	/* unpack the command */
+	json_t *cmd = json_init(msg);
+
+	/* find a pointer to the start/oldest item in store */
+	int idx = store_wrap( store_next - store_len );
+
+	/* which type did they say */
+	if (json_object_get(cmd, "serial")!=NULL) {
+		/* everything after serial # */
+		uint64_t want = json_getint(cmd, "serial");
+		for (int i=idx;i!=store_next;i=store_wrap(i+1)) {
+			if ( store[i] == NULL) continue;
+			if ( store[i]->head.serial >= want) {
+				idx = i;
+				break;
+			}
+		}
+		/* if it fails, you get everything
+		 * as it maybe got reset whilst you were away */
+	}else
+	if (json_object_get(cmd, "since")!=NULL) {
+		/* everything after {unixtime} */
+		int64_t want = json_getint(cmd, "since");
+		for (;idx != store_next;idx=store_wrap(idx+1)) {
+			if (store[idx]==NULL) continue;
+			/* list will be in date order */
+			if (store[idx]->head.when >= want) break;
+		}
+		/* if it fails you get nothing as there is
+		 * nothing newer (larger) than the date you gave */
+	}else
+	if (json_object_get(cmd, "count")!=NULL) {
+		int want = json_getint(cmd, "count");
+		if (want < store_len) {
+			idx -= store_len - want;
+			idx = store_wrap( idx );
+		}
+	} else {
+		json_decref(cmd);
+		send_error(conn, msg, "Invalid replay command");
+		return;
+	}
+	json_decref(cmd);
+
+	/* who are we doing this for */
+	struct who who;
+	who.posn = conn->user;
+	who.pid = conn->addr;
+
+	struct person user;
+	int users_fd = userdb_open(O_RDONLY);
+	lseek(users_fd, who.posn, SEEK_SET);
+	if (read(users_fd, &user, sizeof(user)) <= 0) {
+		close(users_fd);
+		send_error(conn, msg, "Error cannot find your user record");
+		return;
+	}
+	close(users_fd);
+
+	struct room room;
+	RoomInit(&room);
+	LoadRoom(&room, user.room);
+
+	/* now, go and replay those messages that are appropriate */
+	for (;idx != store_next; idx = store_wrap( idx + 1 )) {
+		if (store[idx] == NULL) continue;
+
+		/* this will be a subset of what you see in process_msg() */
+
+		if (store[idx]->head.type == IPC_SAYTOROOM) {
+			json_t * j = json_init( store[idx] );
+			if (j == NULL) continue;
+
+			const char * exclude = json_getstring(j, "exclude");
+
+			if (exclude != NULL && strcasecmp(exclude, user.name)==0) {
+				/* thats us ! shhh... */
+				json_decref(j);
+				continue;
+			}
+			json_decref(j);
+
+			if (user.room == store[idx]->head.dst) {
+				/* right room, send it */
+				msg_attach(store[idx], conn);
+			} else
+			if (room.sproof < 1 && (user.chatmode & CM_GLOBAL)) {
+			/* room not soundproof, and user has global on */
+				msg_attach(store[idx], conn);
+			}
+			/* couldnt have been for us */
+			continue;
+		}
+		if (store[idx]->head.type == IPC_SAYTOUSER) {
+			json_t * j = json_init( store[idx] );
+			if (j == NULL) continue;
+
+			const char * target = json_getstring(j, "target");
+
+			if (target!=NULL && strcasecmp(target, user.name)==0) {
+				/* yes, its for us */
+				msg_attach(store[idx], conn);
+			}
+			json_decref(j);
+			continue;
+		}
+
+		/* send them everything else */
+		msg_attach(store[idx], conn);
+	}
+
+	RoomDestroy(&room);
+
+	return;
 }

Modified: trunk/src/server/replay.h
===================================================================
--- trunk/src/server/replay.h	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/server/replay.h	2015-09-22 16:31:15 UTC (rev 1390)
@@ -1,3 +1,5 @@
 /* replay.c */
 void load_serial(void);
+void store_message(ipc_message_t *msg);
 void assign_serial(ipc_message_t *msg);
+void replay(ipc_connection_t *conn, ipc_message_t *msg);

Modified: trunk/src/server/servsock.c
===================================================================
--- trunk/src/server/servsock.c	2015-09-21 15:52:39 UTC (rev 1389)
+++ trunk/src/server/servsock.c	2015-09-22 16:31:15 UTC (rev 1390)
@@ -309,12 +309,19 @@
 		return;
 	}
 
+	if (msg->head.type == IPC_REPLAY) {
+		replay(conn, msg);
+		ipcmsg_destroy(msg);
+		return;
+	}
+
 	/**** end of messages to the server
 	 *    all below this point are intended to be retransmitted
 	 */
 
 	/* set the unique serial number and timestamp */
 	assign_serial(msg);
+	store_message(msg);
 
 	/* send message to everyone in the room */
 	if (msg->head.type == IPC_SAYTOROOM) {
@@ -436,6 +443,13 @@
 				printf("Shout to %s in %d\n", user.name, user.room);
 			}
 		}
+
+		if (room.sproof) {
+			/* nobble the stored message to act correctly */
+			/* shout in sproof room is just a say to that room */
+			msg->head.type = IPC_SAYTOROOM;
+			msg->head.dst = from.room;
+		}
 		RoomDestroy(&room);
 		close(who_fd);
 		close(users_fd);




More information about the mw-devel mailing list