[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