src/server.c

changeset 129
189c7c77aaab
parent 128
ce38ee9bc3af
child 130
3fc6b1d6cbe9
equal deleted inserted replaced
128:ce38ee9bc3af 129:189c7c77aaab
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2016 Mike Becker. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include "network.h"
31 #include "game.h"
32 #include "chess/pgn.h"
33 #include <ncurses.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <signal.h>
39
40 static int server_fd = -1;
41 static void interrupt_listen(int sig) {
42 if (server_fd > -1) {
43 // this interrupts
44 close(server_fd);
45 }
46 }
47
48 static int server_open(Server *server, Settings *settings) {
49 printw("\nListening for client...\n");
50 refresh();
51 if (settings->usedomainsocket
52 ? net_create_sock(server, settings->serverhost)
53 : net_create_tcp(server, settings->port)) {
54 addstr("Server creation failed");
55 return 1;
56 }
57
58 // allow Ctrl+C to interrupt the listening process
59 server_fd = server->fd;
60 signal(SIGINT, interrupt_listen);
61
62 if (net_listen(server)) {
63 addstr("Listening for client failed or interrupted");
64 return 1;
65 }
66
67 // restore default action
68 signal(SIGINT, SIG_DFL);
69
70 return 0;
71 }
72
73 static int server_handshake(Client *client) {
74 net_send_code(client->fd, NETCODE_VERSION);
75 if (net_recieve_code(client->fd) != NETCODE_VERSION) {
76 addstr("Client uses an incompatible software version.");
77 return 1;
78 }
79
80 addstr("Client connected - transmitting gameinfo...");
81 refresh();
82
83 return 0;
84 }
85
86 int server_run(Settings *settings) {
87 Server server;
88
89 dump_gameinfo(&(settings->gameinfo));
90 GameState gamestate;
91 gamestate_init(&gamestate);
92 if (settings->continuepgn) {
93 /* preload PGN data before handshake */
94 FILE *pgnfile = fopen(settings->continuepgn, "r");
95 if (pgnfile) {
96 int result = read_pgn(pgnfile, &gamestate,
97 &(settings->gameinfo));
98 long position = ftell(pgnfile);
99 fclose(pgnfile);
100 if (result) {
101 printw("Invalid PGN file content at position %ld:\n%s\n",
102 position, pgn_error_str(result));
103 return 1;
104 }
105 if (!is_game_running(&gamestate)) {
106 addstr("Game has ended. Use -s to analyze it locally.\n");
107 return 1;
108 }
109 addch('\n');
110 dump_moveinfo(&gamestate);
111 addch('\n');
112 } else {
113 printw("Can't read PGN file (%s)\n", strerror(errno));
114 return 1;
115 }
116 }
117
118 if (server_open(&server, settings)) {
119 net_destroy(&server);
120 return 1;
121 }
122
123 if (server_handshake(server.client)) {
124 net_destroy(&server);
125 return 1;
126 }
127
128 int fd = server.client->fd;
129 if (settings->continuepgn) {
130 /* Continue game, send PGN data */
131 uint16_t mc = gamestate.movecount;
132 size_t pgndata_size = sizeof(GameInfo)+sizeof(mc)+mc*sizeof(Move);
133 char *pgndata = malloc(pgndata_size);
134 memcpy(pgndata, &(settings->gameinfo), sizeof(GameInfo));
135 unsigned offset = sizeof(GameInfo);
136 memcpy(pgndata+offset, &mc, sizeof(mc));
137 offset += sizeof(mc);
138 memcpy(pgndata+offset, gamestate.moves, mc*sizeof(Move));
139 net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size);
140 free(pgndata);
141 } else {
142 /* Start new game */
143 net_send_data(fd, NETCODE_GAMEINFO,
144 &(settings->gameinfo), sizeof(GameInfo));
145 }
146 addstr("\rClient connected - awaiting challenge acceptance...");
147 refresh();
148 int code = net_recieve_code(fd);
149 int exitcode = 0;
150 if (code == NETCODE_ACCEPT) {
151 addstr("\rClient connected - challenge accepted.");
152 clrtoeol();
153 game_play(settings, &gamestate, fd);
154 net_destroy(&server);
155 game_review(settings, &gamestate);
156 } else if (code == NETCODE_DECLINE) {
157 addstr("\rClient connected - challenge declined.");
158 clrtoeol();
159 net_destroy(&server);
160 } else if (code == NETCODE_CONNLOST) {
161 addstr("\rClient connected - but gave no response.");
162 clrtoeol();
163 net_destroy(&server);
164 } else {
165 addstr("\rInvalid client response");
166 clrtoeol();
167
168 net_destroy(&server);
169 exitcode = 1;
170 }
171 gamestate_cleanup(&gamestate);
172 return exitcode;
173 }

mercurial