]> git.pond.sub.org Git - empserver/blobdiff - src/lib/player/recvclient.c
Update copyright notice
[empserver] / src / lib / player / recvclient.c
index f356593de911480dc6cbc6ca100296c7f1b82ca2..838476c2d2a981dab5e7ff7d2a8e47c7faeeba6c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2006, 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
  *  ---
  *
  *  recvclient.c: Receive input from the client
- * 
+ *
  *  Known contributors to this file:
  *     Dave Pare, 1986
+ *     Markus Armbruster, 2006-2008
  */
 
 #include <config.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 indicator set, or the
- * line is "aborted", set the player's aborted flag and return -2.
- * If the player's connection has the EOF indicator set, or the line
- * is "ctld", return -1.
+ * 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.
  */
@@ -57,27 +60,52 @@ recvclient(char *cmd, int size)
 {
     int count;
 
-    if (player->aborted)
-       return -2;
-    count = io_gets(player->iop, cmd, size);
-    while (!player->aborted && count < 0) {
+    count = -1;
+    while (!player->aborted) {
+       /* Try to get a line of input */
+       count = io_gets(player->iop, cmd, size);
+       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);
-       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 io_output_all() blocked and got unblocked by command
+        * abortion, we must return without blocking in io_input().
+        */
+       if (player->aborted)
+           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 (count > 0) {
-       if (strcmp(cmd, "ctld") == 0)
-           return -1;
-       if (strcmp(cmd, "aborted") == 0)
-           player->aborted = 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;
     }
-    if (player->aborted)
-       return -2;
-    journal_input(cmd);
+
+    player->recvfail = 0;
     return count;
 }