Wed, 09 Apr 2014 12:07:47 +0200
added nonblocking read for network games + minor build system fixes
src/Makefile | file | annotate | diff | comparison | revisions | |
src/chess/Makefile | file | annotate | diff | comparison | revisions | |
src/client.c | file | annotate | diff | comparison | revisions | |
src/game.c | file | annotate | diff | comparison | revisions | |
src/main.c | file | annotate | diff | comparison | revisions | |
src/network.c | file | annotate | diff | comparison | revisions | |
src/network.h | file | annotate | diff | comparison | revisions | |
src/server.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/Makefile Wed Apr 09 11:12:04 2014 +0200 1.2 +++ b/src/Makefile Wed Apr 09 12:07:47 2014 +0200 1.3 @@ -38,18 +38,18 @@ 1.4 OBJ = $(SRC:%.c=../build/release/%$(OBJ_EXT)) 1.5 OBJ_D = $(SRC:%.c=../build/debug/%$(OBJ_EXT)) 1.6 1.7 -all: $(OBJ) 1.8 - $(LD) -o ../build/release/$(BIN) $^ \ 1.9 +all: ../build/release $(OBJ) 1.10 + $(LD) -o ../build/release/$(BIN) $(OBJ) \ 1.11 ../build/release/chess$(LIB_EXT) $(LDFLAGS) 1.12 1.13 -debug: $(OBJ_D) 1.14 - $(LD) -o ../build/debug/$(BIN) $^ \ 1.15 +debug: ../build/debug $(OBJ_D) 1.16 + $(LD) -o ../build/debug/$(BIN) $(OBJ_D) \ 1.17 ../build/debug/chess$(LIB_EXT) $(LDFLAGS) 1.18 1.19 -../build/release/%$(OBJ_EXT): %.c ../build/release 1.20 +../build/release/%$(OBJ_EXT): %.c 1.21 $(CC) -o $@ $(CFLAGS) -c $< 1.22 1.23 -../build/debug/%$(OBJ_EXT): %.c ../build/debug 1.24 +../build/debug/%$(OBJ_EXT): %.c 1.25 $(CC) -o $@ $(CFLAGS_D) -c $< 1.26 1.27 ../build/release:
2.1 --- a/src/chess/Makefile Wed Apr 09 11:12:04 2014 +0200 2.2 +++ b/src/chess/Makefile Wed Apr 09 12:07:47 2014 +0200 2.3 @@ -42,16 +42,16 @@ 2.4 OBJ = $(SRC:%.c=$(BUILDDIR)/release/%$(OBJ_EXT)) 2.5 OBJ_D = $(SRC:%.c=$(BUILDDIR)/debug/%$(OBJ_EXT)) 2.6 2.7 -all: $(OBJ) 2.8 +all: $(BUILDDIR)/release $(OBJ) 2.9 $(AR) $(ARFLAGS) $(BUILDDIR)/release/chess$(LIB_EXT) $(OBJ) 2.10 2.11 -debug: $(OBJ_D) 2.12 +debug: $(BUILDDIR)/debug $(OBJ_D) 2.13 $(AR) $(ARFLAGS) $(BUILDDIR)/debug/chess$(LIB_EXT) $(OBJ_D) 2.14 2.15 -$(BUILDDIR)/release/%$(OBJ_EXT): %.c $(BUILDDIR)/release 2.16 +$(BUILDDIR)/release/%$(OBJ_EXT): %.c 2.17 $(CC) -o $@ $(CFLAGS) -c $< 2.18 2.19 -$(BUILDDIR)/debug/%$(OBJ_EXT): %.c $(BUILDDIR)/debug 2.20 +$(BUILDDIR)/debug/%$(OBJ_EXT): %.c 2.21 $(CC) -o $@ $(CFLAGS_D) -c $< 2.22 2.23 $(BUILDDIR):
3.1 --- a/src/client.c Wed Apr 09 11:12:04 2014 +0200 3.2 +++ b/src/client.c Wed Apr 09 12:07:47 2014 +0200 3.3 @@ -34,12 +34,12 @@ 3.4 3.5 static int client_connect(Server *server, char *host, char *port) { 3.6 if (net_find(server, host, port)) { 3.7 - fprintf(stderr, "Can't find server\n"); 3.8 + addstr("Can't find server"); 3.9 return 1; 3.10 } 3.11 3.12 if (net_connect(server)) { 3.13 - perror("Can't connect to server"); 3.14 + addstr("Can't connect to server"); 3.15 return 1; 3.16 } 3.17 3.18 @@ -48,7 +48,7 @@ 3.19 3.20 static int client_handshake(Server *server) { 3.21 if (net_recieve_code(server->fd) != NETCODE_VERSION) { 3.22 - fprintf(stderr, "Server uses an incompatible software version.\n"); 3.23 + addstr("Server uses an incompatible software version."); 3.24 return 1; 3.25 } else { 3.26 net_send_code(server->fd, NETCODE_VERSION); 3.27 @@ -84,7 +84,7 @@ 3.28 net_send_code(server.fd, NETCODE_DECLINE); 3.29 } 3.30 } else { 3.31 - fprintf(stderr, "Server sent invalid gameinfo.\n"); 3.32 + addstr("Server sent invalid gameinfo."); 3.33 net_destroy(&server); 3.34 return EXIT_FAILURE; 3.35 }
4.1 --- a/src/game.c Wed Apr 09 11:12:04 2014 +0200 4.2 +++ b/src/game.c Wed Apr 09 12:07:47 2014 +0200 4.3 @@ -33,6 +33,7 @@ 4.4 #include <ncurses.h> 4.5 #include <string.h> 4.6 #include <inttypes.h> 4.7 +#include <sys/select.h> 4.8 4.9 static const uint8_t boardx = 10, boardy = 10; 4.10 static int inputy = 21; /* should be overridden on game startup */ 4.11 @@ -315,6 +316,13 @@ 4.12 4.13 static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { 4.14 4.15 + if (net_setnonblocking(opponent, 1)) { 4.16 + printw("Cannot setup nonblocking IO on network socket"); 4.17 + cbreak(); getch(); 4.18 + exit(EXIT_FAILURE); 4.19 + } 4.20 + 4.21 + struct timeval timeout; 4.22 while (1) { 4.23 timecontrol(gamestate, gameinfo); 4.24 4.25 @@ -323,52 +331,66 @@ 4.26 clrtoeol(); 4.27 refresh(); 4.28 4.29 - // TODO: nonblocking 4.30 - uint32_t code = net_recieve_code(opponent); 4.31 + fd_set readfds; 4.32 4.33 - Move move; 4.34 - switch (code) { 4.35 - case NETCODE_TIMEOVER: 4.36 - printw("\rYour opponent's time ran out - you win!"); 4.37 - clrtoeol(); 4.38 - return 1; 4.39 - case NETCODE_SURRENDER: 4.40 - printw("\rYour opponent surrendered!"); 4.41 - clrtoeol(); 4.42 - return 1; 4.43 - case NETCODE_REMIS: 4.44 - if (prompt_yesno( 4.45 - "\rYour opponent offers remis - do you accept")) { 4.46 - printw("\rRemis accepted!"); 4.47 + FD_ZERO(&readfds); 4.48 + FD_SET(opponent, &readfds); 4.49 + timeout.tv_sec = 0; 4.50 + timeout.tv_usec = 1e5; 4.51 + 4.52 + int result = select(opponent+1, &readfds, NULL, NULL, &timeout); 4.53 + if (result == -1) { 4.54 + printw("\rCannot perform asynchronous network IO"); 4.55 + cbreak(); getch(); 4.56 + exit(EXIT_FAILURE); 4.57 + } 4.58 + if (result > 0) { 4.59 + uint32_t code = net_recieve_code(opponent); 4.60 + 4.61 + Move move; 4.62 + switch (code) { 4.63 + case NETCODE_TIMEOVER: 4.64 + printw("\rYour opponent's time ran out - you win!"); 4.65 clrtoeol(); 4.66 - net_send_code(opponent, NETCODE_ACCEPT); 4.67 return 1; 4.68 - } else { 4.69 - net_send_code(opponent, NETCODE_DECLINE); 4.70 - } 4.71 - break; 4.72 - case NETCODE_MOVE: 4.73 - net_recieve_data(opponent, &move, sizeof(Move)); 4.74 - if (validate_move(gamestate, &move)) { 4.75 - apply_move(gamestate, &move); 4.76 - if (move.check) { 4.77 - net_send_code(opponent, NETCODE_CHECK); 4.78 - } else if (gamestate->checkmate) { 4.79 - net_send_code(opponent, NETCODE_CHECKMATE); 4.80 - printw("\rCheckmate!"); 4.81 + case NETCODE_SURRENDER: 4.82 + printw("\rYour opponent surrendered!"); 4.83 + clrtoeol(); 4.84 + return 1; 4.85 + case NETCODE_REMIS: 4.86 + if (prompt_yesno( 4.87 + "\rYour opponent offers remis - do you accept")) { 4.88 + printw("\rRemis accepted!"); 4.89 clrtoeol(); 4.90 - return 1; 4.91 - } else if (gamestate->stalemate) { 4.92 - net_send_code(opponent, NETCODE_STALEMATE); 4.93 - printw("\rStalemate!"); 4.94 - clrtoeol(); 4.95 + net_send_code(opponent, NETCODE_ACCEPT); 4.96 return 1; 4.97 } else { 4.98 - net_send_code(opponent, NETCODE_ACCEPT); 4.99 + net_send_code(opponent, NETCODE_DECLINE); 4.100 } 4.101 - return 0; 4.102 - } else { 4.103 - net_send_code(opponent, NETCODE_DECLINE); 4.104 + break; 4.105 + case NETCODE_MOVE: 4.106 + net_recieve_data(opponent, &move, sizeof(Move)); 4.107 + if (validate_move(gamestate, &move)) { 4.108 + apply_move(gamestate, &move); 4.109 + if (move.check) { 4.110 + net_send_code(opponent, NETCODE_CHECK); 4.111 + } else if (gamestate->checkmate) { 4.112 + net_send_code(opponent, NETCODE_CHECKMATE); 4.113 + printw("\rCheckmate!"); 4.114 + clrtoeol(); 4.115 + return 1; 4.116 + } else if (gamestate->stalemate) { 4.117 + net_send_code(opponent, NETCODE_STALEMATE); 4.118 + printw("\rStalemate!"); 4.119 + clrtoeol(); 4.120 + return 1; 4.121 + } else { 4.122 + net_send_code(opponent, NETCODE_ACCEPT); 4.123 + } 4.124 + return 0; 4.125 + } else { 4.126 + net_send_code(opponent, NETCODE_DECLINE); 4.127 + } 4.128 } 4.129 } 4.130 }
5.1 --- a/src/main.c Wed Apr 09 11:12:04 2014 +0200 5.2 +++ b/src/main.c Wed Apr 09 12:07:47 2014 +0200 5.3 @@ -165,7 +165,7 @@ 5.4 return EXIT_SUCCESS; 5.5 } 5.6 initscr(); 5.7 - halfdelay(10); 5.8 + halfdelay(1); 5.9 keypad(stdscr, TRUE); 5.10 if (has_colors()) { 5.11 start_color(); 5.12 @@ -181,8 +181,12 @@ 5.13 if (settings.singlemachine) { 5.14 game_start_singlemachine(&settings); 5.15 } else { 5.16 - return is_server(&settings) ? 5.17 + int exitcode = is_server(&settings) ? 5.18 server_run(&settings) : client_run(&settings); 5.19 + 5.20 + if (exitcode != EXIT_SUCCESS) { 5.21 + cbreak(); getch(); 5.22 + } 5.23 } 5.24 } 5.25
6.1 --- a/src/network.c Wed Apr 09 11:12:04 2014 +0200 6.2 +++ b/src/network.c Wed Apr 09 12:07:47 2014 +0200 6.3 @@ -29,6 +29,7 @@ 6.4 6.5 #include <stdlib.h> 6.6 #include <string.h> 6.7 +#include <fcntl.h> 6.8 #include "network.h" 6.9 6.10 #define new_socket() socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 6.11 @@ -133,3 +134,21 @@ 6.12 void net_recieve_data(int socket, void *data, size_t len) { 6.13 recv(socket, data, len, 0); 6.14 } 6.15 + 6.16 +int net_setnonblocking(int socket, _Bool nonblocking) { 6.17 + int opts = fcntl(socket, F_GETFL); 6.18 + if (opts < 0) { 6.19 + return 1; 6.20 + } 6.21 + 6.22 + if (nonblocking) { 6.23 + opts |= O_NONBLOCK; 6.24 + } else { 6.25 + opts &= ~O_NONBLOCK; 6.26 + } 6.27 + if (fcntl(socket, F_SETFL, opts) < 0) { 6.28 + return 1; 6.29 + } 6.30 + 6.31 + return 0; 6.32 +}
7.1 --- a/src/network.h Wed Apr 09 11:12:04 2014 +0200 7.2 +++ b/src/network.h Wed Apr 09 12:07:47 2014 +0200 7.3 @@ -74,6 +74,7 @@ 7.4 uint8_t net_recieve_code(int socket); 7.5 void net_recieve_data(int socket, void *data, size_t len); 7.6 7.7 +int net_setnonblocking(int socket, _Bool nonblocking); 7.8 7.9 #ifdef __cplusplus 7.10 }
8.1 --- a/src/server.c Wed Apr 09 11:12:04 2014 +0200 8.2 +++ b/src/server.c Wed Apr 09 12:07:47 2014 +0200 8.3 @@ -35,12 +35,12 @@ 8.4 printw("\nListening for client...\n"); 8.5 refresh(); 8.6 if (net_create(server, port)) { 8.7 - perror("Server creation failed"); 8.8 + addstr("Server creation failed"); 8.9 return 1; 8.10 } 8.11 8.12 if (net_listen(server)) { 8.13 - perror("Listening for client failed"); 8.14 + addstr("Listening for client failed"); 8.15 return 1; 8.16 } 8.17 8.18 @@ -50,7 +50,7 @@ 8.19 static int server_handshake(Client *client) { 8.20 net_send_code(client->fd, NETCODE_VERSION); 8.21 if (net_recieve_code(client->fd) != NETCODE_VERSION) { 8.22 - fprintf(stderr, "Client uses an incompatible software version.\n"); 8.23 + addstr("Client uses an incompatible software version."); 8.24 return 1; 8.25 } 8.26 8.27 @@ -90,7 +90,9 @@ 8.28 printw("\rClient connected - challenge declined."); 8.29 clrtoeol(); 8.30 } else { 8.31 - fprintf(stderr, "Invalid client response\n"); 8.32 + addstr("\rInvalid client response"); 8.33 + clrtoeol(); 8.34 + 8.35 net_destroy(&server); 8.36 return EXIT_FAILURE; 8.37 }