home · contact · privacy
Server: Restructure io_loop(), and make obey_msg() handle meta commands.
authorChristian Heller <c.heller@plomlompom.de>
Sat, 6 Dec 2014 02:42:57 +0000 (03:42 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Sat, 6 Dec 2014 02:42:57 +0000 (03:42 +0100)
src/server/init.c
src/server/run.c
src/server/run.h

index c0935a55a23bec254ce9f446b3a0e902411c46e1..1b36490947a2405912535b5516f7a427bdd0e3bb 100644 (file)
@@ -71,7 +71,7 @@ static void obey_lines_from_file(char * path, uint8_t record)
                 {
                     *nl = '\0';
                 }
-                obey_msg(line, record, 1);
+                obey_msg(line, record);
             }
             err_line_inc();
         }
@@ -91,18 +91,18 @@ static void replay_game()
     while (   world.turn < world.replay
            && try_fgets(line, linemax + 1, file, __func__))
     {
-        obey_msg(line, 0, 1);
+        obey_msg(line, 0);
         err_line_inc();
     }
     uint8_t end = 0;
-    while (!io_loop())
+    while (3 == io_loop(2))
     {
         if (!end)
         {
             end = (NULL == try_fgets(line, linemax + 1, file, __func__));
             if (!end)
             {
-                obey_msg(line, 0, 1);
+                obey_msg(line, 0);
                 err_line_inc();
             }
         }
@@ -256,10 +256,10 @@ extern void run_game()
         char * msg = try_malloc(strlen(command) + 1 + 11 + 1, __func__);
         int test = sprintf(msg, "%s %d", command, (int) time(NULL));
         exit_trouble(test < 0, __func__, s[S_FCN_SPRINTF]);
-        obey_msg(msg, 1, 1);
+        obey_msg(msg, 1);
         free(msg);
     }
     err_line_zero();
-    io_loop();
+    io_loop(1);
     record(NULL, 1);
 }
index 55376313e99a347d596b43e83012916deac958c6..a1bf343b57599b9c66b384caf2351ce66273180f 100644 (file)
@@ -42,19 +42,21 @@ static uint8_t set_char_by_string_comparison(char * string, char * comparand,
 /* Return 1 on world.exists, else 0 and err_line() appropriate error message. */
 static uint8_t player_commands_allowed();
 
-/* Parse player command "tok0" with no argument to player action. */
+/* Parse player commands "tok0" with optional argument "tok1" to player action.
+ * Return 1 on success, 0 on failure.
+ */
 static uint8_t parse_player_command_0arg(char * tok0);
-
-/* Parse player command "tok0" with one argument "tok1" to player action. */
 static uint8_t parse_player_command_1arg(char * tok0, char * tok1);
 
-/* Parse/apply command "tok0" (read further tokens as necessary). */
-static uint8_t parse_command(char * tok0);
+/* Parse/apply (non-)meta command "tok0" (read further tokens as necessary).
+ * Return 0 on failure, 1 on success, 2 on QUIT meta command.
+ */
+static uint8_t parse_command_nonmeta(char * tok0);
+static uint8_t parse_command_meta(char * tok0);
 
-/* Compares first line of server out file to world.server_test, aborts if they
- * don't match, but not before unsetting the flags deleting files in the server
- * directory, for in that case those must be assumed to belong to another server
- * process.
+/* Compare 1st line of server out file to world.server_test, abort if they don't
+ * match, but not before unsetting flags deleting files in the server directory,
+ * for in that case those must be assumed to belong to another server process.
  */
 static void server_test();
 
@@ -71,9 +73,6 @@ static uint8_t thing_in_whitelist(uint8_t id, int16_t * whitelist);
  */
 static void turn_over();
 
-/* Try to read "msg" as meta command, act accordingly; on success, free it. */
-static uint8_t meta_commands(char * msg);
-
 
 
 static uint8_t set_char_by_string_comparison(char * string, char * comparand,
@@ -161,7 +160,7 @@ static uint8_t parse_player_command_1arg(char * tok0, char * tok1)
 
 
 
-static uint8_t parse_command(char * tok0)
+static uint8_t parse_command_nonmeta(char * tok0)
 {
     if (parse_player_command_0arg(tok0))
     {
@@ -197,6 +196,40 @@ static uint8_t parse_command(char * tok0)
 
 
 
+static uint8_t parse_command_meta(char * tok0)
+{
+    if (!strcmp("QUIT", tok0))
+    {
+        return 2;
+    }
+    if (!strcmp("PING", tok0))
+    {
+        send_to_outfile("PONG\n", 1);
+        return 1;
+    }
+    if (!strcmp("STACK", tok0))
+    {
+        send_to_outfile("THINGS_BELOW_PLAYER START\n", 1);
+        struct Thing * player = get_player();
+        struct Thing * t;
+        for (t = world.things; t; t = t->next)
+        {
+            if (   t->pos.y == player->pos.y && t->pos.x == player->pos.x
+                && t != player)
+            {
+                struct ThingType * tt = get_thing_type(t->type);
+                send_to_outfile(tt->name, 0);
+                send_to_outfile("\n", 1);
+            }
+        }
+        send_to_outfile("THINGS_BELOW_PLAYER END\n", 1);
+        return 1;
+    }
+    return 0;
+}
+
+
+
 static void server_test()
 {
     char test[10 + 1 + 10 + 1 + 1];
@@ -290,43 +323,6 @@ static void turn_over()
 
 
 
-static uint8_t meta_commands(char * msg)
-{
-    if (!strcmp("QUIT", msg))
-    {
-        free(msg);
-        return 2;
-    }
-    if (!strcmp("PING", msg))
-    {
-        free(msg);
-        send_to_outfile("PONG\n", 1);
-        return 1;
-    }
-    if (!strcmp("STACK", msg))
-    {
-        free(msg);
-        send_to_outfile("THINGS_BELOW_PLAYER START\n", 1);
-        struct Thing * player = get_player();
-        struct Thing * t;
-        for (t = world.things; t; t = t->next)
-        {
-            if (   t->pos.y == player->pos.y && t->pos.x == player->pos.x
-                && t != player)
-            {
-                struct ThingType * tt = get_thing_type(t->type);
-                send_to_outfile(tt->name, 0);
-                send_to_outfile("\n", 1);
-            }
-        }
-        send_to_outfile("THINGS_BELOW_PLAYER END\n", 1);
-        return 1;
-    }
-    return 0;
-}
-
-
-
 extern void send_to_outfile(char * answer, uint8_t flush)
 {
     try_fwrite(answer, strlen(answer), 1, world.file_out, __func__);
@@ -376,69 +372,65 @@ extern void record(char * msg, uint8_t force)
 
 
 
-extern void obey_msg(char * msg, uint8_t do_record, uint8_t do_verbose)
+extern uint8_t obey_msg(char * msg, uint8_t obey_state)
 {
-    if (world.is_verbose && do_verbose)
+    if (world.is_verbose)
     {
         exit_trouble(-1 == printf("Input: %s\n", msg), __func__, "printf");
     }
     set_err_line_options("Trouble with message: ", msg, 0);
     char * msg_copy = strdup(msg);
     char * tok0 = token_from_line(msg_copy);
+    uint8_t ret = 0;
     if (tok0)
     {
-
-        if (parse_command(tok0))
+        ret = parse_command_meta(tok0);
+        if (ret || (obey_state < 2 && parse_command_nonmeta(tok0)))
         {
-            if (world.exists)
-            {
-                world.do_update = 1;
-            }
-            if (do_record)
+            if (!ret)
             {
-                record(msg, 0);
+                if (world.exists)
+                {
+                    world.do_update = 1;
+                }
+                if (1 == obey_state)
+                {
+                   record(msg, 0);
+                }
             }
             char * tokplus = token_from_line(NULL);
             err_line(!(!tokplus), "Too many arguments, ignoring overflow.");
-            free(msg_copy);
-            return;
+        }
+        else if (world.replay)
+        {
+            ret = 3;
+        }
+        else if (!world.replay)
+        {
+            err_line(1, "Unknown command/argument or bad number of tokens.");
         }
     }
-    err_line(1, "Unknown command/argument or bad number of tokens.");
     free(msg_copy);
+    return ret;
 }
 
 
 
-extern uint8_t io_loop()
+extern uint8_t io_loop(uint8_t obey_state)
 {
     while (1)
     {
         char * msg = io_round();
         server_test();
-        if (!msg)
+        if (msg)
         {
-            continue;
-        }
-        if (world.is_verbose)
-        {
-            exit_trouble(-1 == printf("Input: %s\n", msg), __func__, "printf");
-        }
-        uint8_t test = meta_commands(msg);
-        if (test)
-        {
-            if (2 == test)
+            uint8_t ret = obey_msg(msg, obey_state);
+            free(msg);
+            if (   (!world.replay && 2 == ret)
+                || ( world.replay && 2 <= ret))
             {
-                return 1;
+                return ret;
             }
-            continue;
-        }
-        if (world.replay)
-        {
-            free(msg);
-            return 0;
         }
-        obey_msg(msg, 1, 0);
-        free(msg);
     }
 }
index 26a0c2f7108ae8390897a8e0301ccd173f0d0b37..414df1b3e684efb4d9152040e629d04852871318 100644 (file)
@@ -23,20 +23,23 @@ extern void send_to_outfile(char * answer, uint8_t flush);
  */
 extern void record(char * msg, uint8_t force);
 
-/* Try parsing "msg" into a command to apply, and apply it. Output commands to
- * stdout if "do_verbose" and world.is_verbose are set. If "do_record" is set,
- * record commands to record file, and run save_world() if the last call to it
- * via this function has not happened yet or is at least one minute in the past.
+/* Try parsing "msg" into a command to apply. Output "msg" if world.is_verbose.
+ * If "obey_state" is > 1 and world.replay is set, any non-meta command message
+ * is not executed, but merely returns 3. The QUIT meta command (if well-formed)
+ * always returns 2. Other meta commands and (with "obey_state" < 2) non-meta
+ * commands return 1 if well-formed. Malformed or empty command messages return
+ * 0. If "obey_state" is 1, "msg" is recorded via a non-forced record(). If a
+ * non-meta command is executed and world.exists, world.do_update is set.
  */
-extern void obey_msg(char * msg, uint8_t do_record, uint8_t do_verbose);
+extern uint8_t obey_msg(char * msg, uint8_t obey_state);
 
-/* Loop for receiving commands via io_round(), and acting on them. Exits with 1
- * on "QUIT" command. In replay mode, exits with 0 on each non-"QUIT" command.
- * In play mode, processes incomming god and player commands via obey_msg().
- * Compares the first line of the server out file with world.server_test to
- * ensure that the current server process has not been superseded by a new one.
+/* Loop to read commands via io_round() and call obey_msg() with "obey_state"
+ * set on them. If latter returns 2 and world.replay is not set, or returns > 1
+ * and world.replay is set, abort loop to return that result. After io_round(),
+ * compares 1st line of the server out file is compared with world.server_test
+ * to ensure the server process hasn't been superseded by a new one.
  */
-extern uint8_t io_loop();
+extern uint8_t io_loop(uint8_t obey_state);