/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2008, 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>
* 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", set the player's eof flag and 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.
- * FIXME caller needs to know whether a line was consumed, to prompt correctly
*/
int
recvclient(char *cmd, int size)
{
int count;
- if (player->eof)
- return -1;
- if (player->aborted)
- return -2;
-
- count = io_gets(player->iop, cmd, size);
-
- while (!player->aborted && !player->eof && count < 0) {
- /* Sleep for input */
+ 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);
* abortion, we must return without blocking in io_input().
*/
if (player->aborted)
- return -2;
+ break;
- io_input(player->iop, IO_WAIT);
- if (io_error(player->iop))
- player->aborted = 1;
- else if (io_eof(player->iop))
- player->eof = 1;
- else
- count = io_gets(player->iop, cmd, size);
+ 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)
- player->eof = 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->eof)
- return -1;
- if (player->aborted)
- return -2;
-
- journal_input(cmd);
+ player->recvfail = 0;
return count;
}