# HG changeset patch # User Mike Becker # Date 1397038067 -7200 # Node ID c4d4b8a8f9023229370f2ef19e9b26aa7fd4ea20 # Parent 866025982aa9e56fea4f445f90534c6fd89cb1a8 added nonblocking read for network games + minor build system fixes diff -r 866025982aa9 -r c4d4b8a8f902 src/Makefile --- a/src/Makefile Wed Apr 09 11:12:04 2014 +0200 +++ b/src/Makefile Wed Apr 09 12:07:47 2014 +0200 @@ -38,18 +38,18 @@ OBJ = $(SRC:%.c=../build/release/%$(OBJ_EXT)) OBJ_D = $(SRC:%.c=../build/debug/%$(OBJ_EXT)) -all: $(OBJ) - $(LD) -o ../build/release/$(BIN) $^ \ +all: ../build/release $(OBJ) + $(LD) -o ../build/release/$(BIN) $(OBJ) \ ../build/release/chess$(LIB_EXT) $(LDFLAGS) -debug: $(OBJ_D) - $(LD) -o ../build/debug/$(BIN) $^ \ +debug: ../build/debug $(OBJ_D) + $(LD) -o ../build/debug/$(BIN) $(OBJ_D) \ ../build/debug/chess$(LIB_EXT) $(LDFLAGS) -../build/release/%$(OBJ_EXT): %.c ../build/release +../build/release/%$(OBJ_EXT): %.c $(CC) -o $@ $(CFLAGS) -c $< -../build/debug/%$(OBJ_EXT): %.c ../build/debug +../build/debug/%$(OBJ_EXT): %.c $(CC) -o $@ $(CFLAGS_D) -c $< ../build/release: diff -r 866025982aa9 -r c4d4b8a8f902 src/chess/Makefile --- a/src/chess/Makefile Wed Apr 09 11:12:04 2014 +0200 +++ b/src/chess/Makefile Wed Apr 09 12:07:47 2014 +0200 @@ -42,16 +42,16 @@ OBJ = $(SRC:%.c=$(BUILDDIR)/release/%$(OBJ_EXT)) OBJ_D = $(SRC:%.c=$(BUILDDIR)/debug/%$(OBJ_EXT)) -all: $(OBJ) +all: $(BUILDDIR)/release $(OBJ) $(AR) $(ARFLAGS) $(BUILDDIR)/release/chess$(LIB_EXT) $(OBJ) -debug: $(OBJ_D) +debug: $(BUILDDIR)/debug $(OBJ_D) $(AR) $(ARFLAGS) $(BUILDDIR)/debug/chess$(LIB_EXT) $(OBJ_D) -$(BUILDDIR)/release/%$(OBJ_EXT): %.c $(BUILDDIR)/release +$(BUILDDIR)/release/%$(OBJ_EXT): %.c $(CC) -o $@ $(CFLAGS) -c $< -$(BUILDDIR)/debug/%$(OBJ_EXT): %.c $(BUILDDIR)/debug +$(BUILDDIR)/debug/%$(OBJ_EXT): %.c $(CC) -o $@ $(CFLAGS_D) -c $< $(BUILDDIR): diff -r 866025982aa9 -r c4d4b8a8f902 src/client.c --- a/src/client.c Wed Apr 09 11:12:04 2014 +0200 +++ b/src/client.c Wed Apr 09 12:07:47 2014 +0200 @@ -34,12 +34,12 @@ static int client_connect(Server *server, char *host, char *port) { if (net_find(server, host, port)) { - fprintf(stderr, "Can't find server\n"); + addstr("Can't find server"); return 1; } if (net_connect(server)) { - perror("Can't connect to server"); + addstr("Can't connect to server"); return 1; } @@ -48,7 +48,7 @@ static int client_handshake(Server *server) { if (net_recieve_code(server->fd) != NETCODE_VERSION) { - fprintf(stderr, "Server uses an incompatible software version.\n"); + addstr("Server uses an incompatible software version."); return 1; } else { net_send_code(server->fd, NETCODE_VERSION); @@ -84,7 +84,7 @@ net_send_code(server.fd, NETCODE_DECLINE); } } else { - fprintf(stderr, "Server sent invalid gameinfo.\n"); + addstr("Server sent invalid gameinfo."); net_destroy(&server); return EXIT_FAILURE; } diff -r 866025982aa9 -r c4d4b8a8f902 src/game.c --- a/src/game.c Wed Apr 09 11:12:04 2014 +0200 +++ b/src/game.c Wed Apr 09 12:07:47 2014 +0200 @@ -33,6 +33,7 @@ #include #include #include +#include static const uint8_t boardx = 10, boardy = 10; static int inputy = 21; /* should be overridden on game startup */ @@ -315,6 +316,13 @@ static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { + if (net_setnonblocking(opponent, 1)) { + printw("Cannot setup nonblocking IO on network socket"); + cbreak(); getch(); + exit(EXIT_FAILURE); + } + + struct timeval timeout; while (1) { timecontrol(gamestate, gameinfo); @@ -323,52 +331,66 @@ clrtoeol(); refresh(); - // TODO: nonblocking - uint32_t code = net_recieve_code(opponent); + fd_set readfds; - Move move; - switch (code) { - case NETCODE_TIMEOVER: - printw("\rYour opponent's time ran out - you win!"); - clrtoeol(); - return 1; - case NETCODE_SURRENDER: - printw("\rYour opponent surrendered!"); - clrtoeol(); - return 1; - case NETCODE_REMIS: - if (prompt_yesno( - "\rYour opponent offers remis - do you accept")) { - printw("\rRemis accepted!"); + FD_ZERO(&readfds); + FD_SET(opponent, &readfds); + timeout.tv_sec = 0; + timeout.tv_usec = 1e5; + + int result = select(opponent+1, &readfds, NULL, NULL, &timeout); + if (result == -1) { + printw("\rCannot perform asynchronous network IO"); + cbreak(); getch(); + exit(EXIT_FAILURE); + } + if (result > 0) { + uint32_t code = net_recieve_code(opponent); + + Move move; + switch (code) { + case NETCODE_TIMEOVER: + printw("\rYour opponent's time ran out - you win!"); clrtoeol(); - net_send_code(opponent, NETCODE_ACCEPT); return 1; - } else { - net_send_code(opponent, NETCODE_DECLINE); - } - break; - case NETCODE_MOVE: - net_recieve_data(opponent, &move, sizeof(Move)); - if (validate_move(gamestate, &move)) { - apply_move(gamestate, &move); - if (move.check) { - net_send_code(opponent, NETCODE_CHECK); - } else if (gamestate->checkmate) { - net_send_code(opponent, NETCODE_CHECKMATE); - printw("\rCheckmate!"); + case NETCODE_SURRENDER: + printw("\rYour opponent surrendered!"); + clrtoeol(); + return 1; + case NETCODE_REMIS: + if (prompt_yesno( + "\rYour opponent offers remis - do you accept")) { + printw("\rRemis accepted!"); clrtoeol(); - return 1; - } else if (gamestate->stalemate) { - net_send_code(opponent, NETCODE_STALEMATE); - printw("\rStalemate!"); - clrtoeol(); + net_send_code(opponent, NETCODE_ACCEPT); return 1; } else { - net_send_code(opponent, NETCODE_ACCEPT); + net_send_code(opponent, NETCODE_DECLINE); } - return 0; - } else { - net_send_code(opponent, NETCODE_DECLINE); + break; + case NETCODE_MOVE: + net_recieve_data(opponent, &move, sizeof(Move)); + if (validate_move(gamestate, &move)) { + apply_move(gamestate, &move); + if (move.check) { + net_send_code(opponent, NETCODE_CHECK); + } else if (gamestate->checkmate) { + net_send_code(opponent, NETCODE_CHECKMATE); + printw("\rCheckmate!"); + clrtoeol(); + return 1; + } else if (gamestate->stalemate) { + net_send_code(opponent, NETCODE_STALEMATE); + printw("\rStalemate!"); + clrtoeol(); + return 1; + } else { + net_send_code(opponent, NETCODE_ACCEPT); + } + return 0; + } else { + net_send_code(opponent, NETCODE_DECLINE); + } } } } diff -r 866025982aa9 -r c4d4b8a8f902 src/main.c --- a/src/main.c Wed Apr 09 11:12:04 2014 +0200 +++ b/src/main.c Wed Apr 09 12:07:47 2014 +0200 @@ -165,7 +165,7 @@ return EXIT_SUCCESS; } initscr(); - halfdelay(10); + halfdelay(1); keypad(stdscr, TRUE); if (has_colors()) { start_color(); @@ -181,8 +181,12 @@ if (settings.singlemachine) { game_start_singlemachine(&settings); } else { - return is_server(&settings) ? + int exitcode = is_server(&settings) ? server_run(&settings) : client_run(&settings); + + if (exitcode != EXIT_SUCCESS) { + cbreak(); getch(); + } } } diff -r 866025982aa9 -r c4d4b8a8f902 src/network.c --- a/src/network.c Wed Apr 09 11:12:04 2014 +0200 +++ b/src/network.c Wed Apr 09 12:07:47 2014 +0200 @@ -29,6 +29,7 @@ #include #include +#include #include "network.h" #define new_socket() socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -133,3 +134,21 @@ void net_recieve_data(int socket, void *data, size_t len) { recv(socket, data, len, 0); } + +int net_setnonblocking(int socket, _Bool nonblocking) { + int opts = fcntl(socket, F_GETFL); + if (opts < 0) { + return 1; + } + + if (nonblocking) { + opts |= O_NONBLOCK; + } else { + opts &= ~O_NONBLOCK; + } + if (fcntl(socket, F_SETFL, opts) < 0) { + return 1; + } + + return 0; +} diff -r 866025982aa9 -r c4d4b8a8f902 src/network.h --- a/src/network.h Wed Apr 09 11:12:04 2014 +0200 +++ b/src/network.h Wed Apr 09 12:07:47 2014 +0200 @@ -74,6 +74,7 @@ uint8_t net_recieve_code(int socket); void net_recieve_data(int socket, void *data, size_t len); +int net_setnonblocking(int socket, _Bool nonblocking); #ifdef __cplusplus } diff -r 866025982aa9 -r c4d4b8a8f902 src/server.c --- a/src/server.c Wed Apr 09 11:12:04 2014 +0200 +++ b/src/server.c Wed Apr 09 12:07:47 2014 +0200 @@ -35,12 +35,12 @@ printw("\nListening for client...\n"); refresh(); if (net_create(server, port)) { - perror("Server creation failed"); + addstr("Server creation failed"); return 1; } if (net_listen(server)) { - perror("Listening for client failed"); + addstr("Listening for client failed"); return 1; } @@ -50,7 +50,7 @@ static int server_handshake(Client *client) { net_send_code(client->fd, NETCODE_VERSION); if (net_recieve_code(client->fd) != NETCODE_VERSION) { - fprintf(stderr, "Client uses an incompatible software version.\n"); + addstr("Client uses an incompatible software version."); return 1; } @@ -90,7 +90,9 @@ printw("\rClient connected - challenge declined."); clrtoeol(); } else { - fprintf(stderr, "Invalid client response\n"); + addstr("\rInvalid client response"); + clrtoeol(); + net_destroy(&server); return EXIT_FAILURE; }