]> git.pond.sub.org Git - empserver/blobdiff - src/lib/player/recvclient.c
Update copyright notice
[empserver] / src / lib / player / recvclient.c
index fa8baa5339c1c0148b55fb311ef6f56bcc203a30..838476c2d2a981dab5e7ff7d2a8e47c7faeeba6c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
- *  recvclient.c: Send and receive commands from the client
- * 
+ *  recvclient.c: Receive input from the client
+ *
  *  Known contributors to this file:
  *     Dave Pare, 1986
+ *     Markus Armbruster, 2006-2008
  */
 
-#include "prototypes.h"
-#include <stdio.h>
-#include "misc.h"
-#include "bit.h"
+#include <config.h>
+
 #include "empio.h"
+#include "journal.h"
 #include "player.h"
-#include "empthread.h"
-
-#include <errno.h>
+#include "prototypes.h"
 
+/*
+ * Receive a line of input from the current player.
+ * If the player's eof flag is set, return -1 without receiving input.
+ * If the player's aborted flag is set, return -2 without receiving
+ * input.
+ * Else receive one line and store it in CMD[SIZE].
+ * This may block for input, yielding the processor.  Flush buffered
+ * output when blocking, to make sure player sees the prompt.
+ * If the player's connection has the I/O error or EOF indicator set,
+ * or the line is "ctld", set the player's eof and aborted flag and
+ * return -1.
+ * If the line is "aborted", set the player's aborted flag and return
+ * -2.
+ * Else return the length of the line.
+ * Design bug: there is no way to indicate truncation of a long line.
+ */
 int
-recvclient(s_char *cmd, int size)
+recvclient(char *cmd, int size)
 {
-       extern  int errno;
-       int     count;
+    int count;
 
-       if (player->aborted)
-               return -2; 
+    count = -1;
+    while (!player->aborted) {
+       /* Try to get a line of input */
        count = io_gets(player->iop, cmd, size);
-       while (!player->aborted && count < 0) {
-               io_output_all(player->iop);
-               io_input(player->iop, IO_WAIT);
-               if (io_error(player->iop))
-                       player->aborted++;
-               else if (io_eof(player->iop))
-                       return -1;
-               else
-                       count = io_gets(player->iop, cmd, size);
-       }
-       if (count > 0) {
-               if (strcmp(cmd, "ctld") == 0)
-                       return -1;
-               if (strcmp(cmd, "aborted") == 0)
-                       player->aborted = 1;
+       if (count >= 0) {
+           /* got it */
+           if (strcmp(cmd, "ctld") == 0)
+               player->aborted = player->eof = 1;
+           if (strcmp(cmd, "aborted") == 0)
+               player->aborted = 1;
+           journal_input(cmd);
+           break;
        }
+
+       /* Make sure player sees prompt */
+       io_output_all(player->iop);
+
+       /*
+        * If io_output_all() blocked and got unblocked by command
+        * abortion, we must return without blocking in io_input().
+        */
        if (player->aborted)
-               return -2;
-       return count;
+           break;
+
+       if (io_input(player->iop, IO_WAIT) <= 0) {
+           if (!io_error(player->iop) && !io_eof(player->iop)) {
+               pr_flash(player, "idle connection terminated\n");
+               player->state = PS_SHUTDOWN;
+           }
+           player->aborted = player->eof = 1;
+       }
+    }
+
+    if (player->aborted) {
+       player->recvfail++;
+       if (player->recvfail > 255) {
+           /*
+            * Looks like the thread is stuck in a loop that fails to
+            * check errors; oops once, then slow it down drastically.
+            */
+           CANT_HAPPEN(player->recvfail == 256);
+           empth_sleep(time(NULL) + 60);
+       }
+       return player->eof ? -1 : -2;
+    }
+
+    player->recvfail = 0;
+    return count;
 }