/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2005, 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: Receive input from the client
- *
+ *
* Known contributors to this file:
* Dave Pare, 1986
+ * Markus Armbruster, 2006-2008
*/
#include <config.h>
-#include "prototypes.h"
-#include <stdio.h>
-#include "misc.h"
#include "empio.h"
+#include "journal.h"
#include "player.h"
-#include "empthread.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 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.
*/
{
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;
+
+ player->recvfail = 0;
return count;
}