1 /*
2  * Biloba
3  * Copyright (C) 2004-2008 Guillaume Demougeot, Colin Leroy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 /**
21  * Biloba - Q1 2005
22  * Game by Guillaume Demougeot <dmgt@wanadoo.fr>
23  * Code by Colin Leroy <colin@colino.net>
24  *
25  * This file contains all the network client code.
26  */
27 
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <time.h>
34 #ifndef __MINGW32__
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39 #else
40 #include <winsock2.h>
41 #endif
42 
43 #include <SDL.h>
44 #include <SDL_thread.h>
45 #include <SDL_mutex.h>
46 #include <string.h>
47 
48 #include "utils.h"
49 #include "player.h"
50 #include "net.h"
51 #include "netops.h"
52 #include "font.h"
53 #include "game.h"
54 #include "msg.h"
55 #include "server.h"
56 #include "options.h"
57 
58 #undef NET_DEBUG
59 
60 static int net_magic_number = 0;
61 
net_init(void)62 void net_init(void)
63 {
64 #ifdef __MINGW32__
65 	WSADATA wsaData;
66 	WSAStartup(MAKEWORD(2,0),&wsaData);
67 #endif
68 }
69 
net_stop(void)70 void net_stop(void)
71 {
72 #ifdef __MINGW32__
73 	WSACleanup();
74 #endif
75 }
76 
77 #ifdef __MINGW32__
78 #define INVSOCK INVALID_SOCKET
79 #else
80 #define INVSOCK -1
81 #endif
82 
83 static int game_running = FALSE;
84 static int main_sock = INVSOCK;
85 static int32_t mygameid = -1;
86 static int32_t mygameplayer = -1;
87 
88 #ifdef __MINGW32__
debug_err(int y,int err)89 void debug_err(int y, int err)
90 {
91 	switch(err) {
92 	case WSANOTINITIALISED:
93 		draw_message("WSANOTINITIALISED", 300, y, -1, FALSE);
94 		break;
95 	case WSAENETDOWN:
96 		draw_message("WSAENETDOWN", 300, y, -1, FALSE);
97 		break;
98 	case WSAEAFNOSUPPORT:
99 		draw_message("WSAEAFNOSUPPORT", 300, y, -1, FALSE);
100 		break;
101 	case WSAEINPROGRESS:
102 		draw_message("WSAEINPROGRESS", 300, y, -1, FALSE);
103 		break;
104 	case WSAEMFILE:
105 		draw_message("WSAEMFILE", 300, y, -1, FALSE);
106 		break;
107 	case WSAENOBUFS:
108 		draw_message("WSAENOBUFS", 300, y, -1, FALSE);
109 		break;
110 	case WSAEPROTONOSUPPORT:
111 		draw_message("WSAEPROTONOSUPPORT", 300, y, -1, FALSE);
112 		break;
113 	case WSAEPROTOTYPE:
114 		draw_message("WSAEPROTOTYPE", 300, y, -1, FALSE);
115 		break;
116 	case WSAESOCKTNOSUPPORT:
117 		draw_message("WSAESOCKTNOSUPPORT", 300, y, -1, FALSE);
118 		break;
119 	default:
120 		draw_message("UNKNOWN", 300, y, -1, FALSE);
121 
122 	}
123 }
124 #endif
125 
126 static char *server = NULL;
127 
net_get_server(void)128 static const char *net_get_server(void)
129 {
130 	return server ? server:NET_HOST;
131 }
132 
sock_connect(const char * hostname,unsigned short port)133 static int sock_connect(const char *hostname, unsigned short port)
134 {
135 	int sockfd = INVSOCK;
136 	struct hostent *server;
137 	struct sockaddr_in serv_addr;
138 	int err;
139 
140 	sockfd = socket(AF_INET, SOCK_STREAM, 0);
141 #ifndef __MINGW32__
142 	if (sockfd < 0) {
143 #else
144 	if (sockfd == INVALID_SOCKET) {
145 #endif
146 #ifdef NET_DEBUG
147 		draw_message("socket error", 10, 10, -1, FALSE);
148 #ifdef __MINGW32__
149 		err = WSAGetLastError();
150 		debug_err(10, err);
151 #endif
152 		SDL_Delay(200);
153 #endif
154 		return INVSOCK;
155 	} else {
156 #ifdef NET_DEBUG
157 		draw_message("socket ok", 10, 10, -1, FALSE);
158 		SDL_Delay(200);
159 #endif
160 	}
161 
162 	if (hostname == NULL)
163 		return INVSOCK;
164 
165 	printf("\nConnecting to %s...\n", hostname);
166 	server = gethostbyname(hostname);
167 	if (server == NULL) {
168 #ifdef NET_DEBUG
169 		draw_message("gethostbyname error", 10, 42, -1, FALSE);
170 #ifdef __MINGW32__
171 		err = WSAGetLastError();
172 		debug_err(42, err);
173 #endif
174 		SDL_Delay(200);
175 #endif
176 		return INVSOCK;
177 	} else {
178 #ifdef NET_DEBUG
179 		draw_message("gethostbyname ok", 10, 42, -1, FALSE);
180 		SDL_Delay(200);
181 #endif
182 	}
183 
184 	memset((char *) &serv_addr, 0, sizeof(serv_addr));
185 	serv_addr.sin_family = AF_INET;
186 	memcpy(&serv_addr.sin_addr, server->h_addr,
187 		server->h_length);
188 	serv_addr.sin_port = htons(port);
189 
190 	err = connect(sockfd, (struct sockaddr *)&serv_addr,
191 		      sizeof(serv_addr));
192 #ifndef __MINGW32__
193 	if (err < 0) {
194 #else
195 	if (err == SOCKET_ERROR) {
196 #endif
197 #ifdef NET_DEBUG
198 		draw_message("connect error", 10, 74, -1, FALSE);
199 #ifdef __MINGW32__
200 		err = WSAGetLastError();
201 		debug_err(74, err);
202 #endif
203 		SDL_Delay(200);
204 #endif
205 		printf("Connection error: %d\n", err);
206 		return INVSOCK;
207 	} else {
208 #ifdef NET_DEBUG
209 		draw_message("connect ok", 10, 74, -1, FALSE);
210 		SDL_Delay(200);
211 #endif
212 	}
213 	printf("Connected.\n");
214 	return (sockfd);
215 }
216 
217 #define CHECK_MSG(s, str) {				\
218 	r = read_str(s, buf, 255);			\
219 	if (r <= 0 || strncmp(buf, str, strlen(str))) {	\
220 		printf("Unexpected reply \"%s\", "	\
221 			"expected \"%s\"\n",		\
222 			buf, str);			\
223 		goto err_protocol;			\
224 	}						\
225 }
226 
227 int net_init_game(const char *gamename, int numplayers,
228 		  InputSystemMethod methods[], char *names[])
229 {
230 	char buf[255];
231 	int i = 0, n, r;
232 	assert(game_running == FALSE);
233 
234 	SDL_FillRect(screen, NULL, 0x00000000);
235 	SDL_UpdateRect(screen, 0, 0, 0, 0);
236 
237 	main_sock = sock_connect(net_get_server(), NET_PORT);
238 	if (main_sock == INVSOCK)
239 		return -1;
240 
241 	printf("\n");
242 
243 	/* init connection */
244 	r = send_str(main_sock, "NEWGAME");
245 	if (r < 0) {
246 		printf("Error sending NEWGAME: %s(%d)\n", net_err_str(r), r);
247 		goto err_protocol;
248 	}
249 	printf("> Sending game creation command\n");
250 	CHECK_MSG(main_sock, "OK");
251 
252 	/* send name */
253 	assert(strlen(gamename) < 255);
254 	r = send_str(main_sock, gamename);
255 	if (r < 0) {
256 		printf("Error sending game name: %s(%d)\n", net_err_str(r), r);
257 		goto err_protocol;
258 	}
259 	printf("> Sending game name '%s'\n", gamename);
260 
261 	/* get id */
262 	r = read_int(main_sock, &mygameid);
263 	if (r < 0) {
264 		printf("Error reading game ID: %s(%d)\n", net_err_str(r), r);
265 		goto err_protocol;
266 	}
267 	printf("< Received assigned game ID %d\n", mygameid);
268 
269 	/* send nump, methods and names */
270 	buf[i] = (unsigned char)numplayers; i++;
271 
272 	for (n = 0; n < numplayers; n++) {
273 		buf[i] = (unsigned char)methods[n];
274 		i++;
275 		strcpy(buf+i, names[n]);
276 		i+=strlen(names[n])+1;
277 		printf("> Sending player %d (%s) name '%s'\n",
278 			n, input_system_names(methods[n]),
279 			names[n]);
280 	}
281 	r = send_msg(main_sock, buf, i);
282 	if (r < 0) {
283 		printf("Error sending player details: %s(%d)\n", net_err_str(r), r);
284 		goto err_protocol;
285 	}
286 	CHECK_MSG(main_sock, "READY");
287 	printf("< Received ack, now waiting for other players\n");
288 
289 	mygameplayer = 0;
290 	return mygameid;
291 
292 err_protocol:
293 	printf("Closing connection.\n");
294 	net_close();
295 	mygameid = -1;
296 	return -1;
297 }
298 
299 static int talk_sock = INVSOCK;
300 static SDL_Thread *net_talk_thread = NULL;
301 static int talk_thread_run = 1;
302 
303 static int msg_available_for_send = FALSE;
304 static char waiting_send_msg[256];
305 static int msg_available_for_recv = FALSE;
306 static char waiting_recv_msg[256];
307 static SDL_mutex *msg_mutex = NULL;
308 
309 static int typing_msg = FALSE;
310 static char msg[MAX_MSG_LEN] = "";
311 static int msg_len = 0;
312 
313 int net_is_typing_msg(void)
314 {
315 	return typing_msg;
316 }
317 
318 static void net_talk_push_send_msg(const char *buf)
319 {
320 	if (net_talk_thread == NULL)
321 		return;
322 
323 	SDL_LockMutex(msg_mutex);
324 
325 	printf("> Sending message '%s'\n", buf);
326 	strncpy(waiting_send_msg, buf, sizeof(waiting_send_msg));
327 	waiting_send_msg[sizeof(waiting_send_msg) - 1] = '\0';
328 
329 	msg_available_for_send = TRUE;
330 
331 	SDL_UnlockMutex(msg_mutex);
332 }
333 
334 void net_set_typing_msg(int typing)
335 {
336 	if (!options_using_net())
337 		return;
338 
339 	typing_msg = typing;
340 	if (!typing_msg && msg_len > 0) {
341 		/* Send pending message */
342 		net_talk_push_send_msg(msg);
343 	}
344 	printf("  %s typing message...\n", typing_msg ? "Started":"Stopped");
345 	/* Reset buffer */
346 	msg_len = 0;
347 	msg[msg_len] = '\0';
348 
349 	if (typing) {
350 		char talk_str[256];
351 		clear_text(-1, G_TALK_X, G_TALK_Y);
352 		snprintf(talk_str, sizeof(talk_str), "%s: ",
353 			 options_get_player_name(mygameplayer));
354 		draw_message(talk_str, G_TALK_X, G_TALK_Y,
355 			     MAX_MSG_LEN * CHARWIDTH, TRUE);
356 	} else {
357 		clear_text(-1, G_TALK_X, G_TALK_Y);
358 	}
359 }
360 
361 const char *net_get_pending_msg(void)
362 {
363 	if (!typing_msg)
364 		return NULL;
365 	return msg;
366 }
367 
368 void net_type_msg(unsigned char c)
369 {
370 	char talk_str[MAX_MSG_LEN + 1];
371 
372 	if (c == SDLK_ESCAPE) {
373 		msg_len = 0;
374 		net_set_typing_msg(FALSE);
375 		return;
376 	} else if (c == SDLK_BACKSPACE) {
377 		c='\0';
378 	} else if (c < 0x20 || c == 0x7f)
379 		return;
380 
381 	assert(typing_msg == TRUE);
382 
383 	if (msg_len >= MAX_MSG_LEN
384 		- strlen(options_get_player_name(mygameplayer))
385 		- strlen(": ")
386 		- 1)
387 		return;
388 
389 	if (c != '\0') {
390 		msg[msg_len] = c;
391 		msg_len++;
392 		msg[msg_len] = '\0';
393 	} else if (msg_len > 0) {
394 		msg_len--;
395 		msg[msg_len] = '\0';
396 	}
397 
398 
399 	snprintf(talk_str, sizeof(talk_str), "%s: %s",
400 		 options_get_player_name(mygameplayer), msg);
401 
402 	clear_text(-1, G_TALK_X, G_TALK_Y);
403 	draw_message(talk_str, G_TALK_X, G_TALK_Y, MAX_MSG_LEN * CHARWIDTH, TRUE);
404 }
405 
406 static void net_talk_push_recv_msg(const char *player, const char *msg)
407 {
408 	if (player == NULL || msg == NULL)
409 
410 	SDL_LockMutex(msg_mutex);
411 
412 	if (player != NULL && msg != NULL)
413 		snprintf(waiting_recv_msg, sizeof(waiting_recv_msg), "%s: %s", player, msg);
414 	else
415 		waiting_recv_msg[0] = '\0';
416 
417 	waiting_recv_msg[sizeof(waiting_recv_msg) - 1] = '\0';
418 
419 	msg_available_for_recv = TRUE;
420 
421 	SDL_UnlockMutex(msg_mutex);
422 }
423 
424 void net_pull_recv_msg(void)
425 {
426 	char *msg = NULL;
427 
428 	SDL_LockMutex(msg_mutex);
429 
430 	if (msg_available_for_recv) {
431 		msg_available_for_recv = FALSE;
432 		msg = strdup(waiting_recv_msg);
433 	}
434 	SDL_UnlockMutex(msg_mutex);
435 
436 	if (msg) {
437 		printf("> Pulled message '%s'\n", msg);
438 		clear_text(-1, G_TALK_X, G_TALK_Y);
439 		draw_message(msg, G_TALK_X, G_TALK_Y, MAX_MSG_LEN * CHARWIDTH, FALSE);
440 		free(msg);
441 	}
442 }
443 
444 int net_talk_thread_func(void *data)
445 {
446 	char buf[256];
447 	int r;
448 	time_t last_displayed_message = time(NULL);
449 	int should_clear = FALSE;
450 
451 	if (talk_sock != INVSOCK) {
452 		sock_close(talk_sock);
453 		talk_sock = INVSOCK;
454 	}
455 
456 	talk_sock = sock_connect(net_get_server(), NET_PORT);
457 
458 	if (send_str(talk_sock, "TALK_MODE") < 0 ||
459 	    send_int(talk_sock, mygameid) < 0 ||
460 	    send_int(talk_sock, mygameplayer) < 0)
461 		goto err_protocol;
462 
463 	CHECK_MSG(talk_sock, "OK");
464 
465 	while (talk_thread_run) {
466 		Game *game;
467 		if (talk_sock == INVSOCK)
468 			break;
469 
470 		SDL_LockMutex(msg_mutex);
471 		if (msg_available_for_send) {
472 			printf("< Message available\n");
473 			msg_available_for_send = FALSE;
474 			if (send_str(talk_sock, waiting_send_msg) < 0) {
475 				SDL_UnlockMutex(msg_mutex);
476 				printf("can't send message\n");
477 				break;
478 			}
479 			printf("> Sent message '%s'\n", waiting_send_msg);
480 		}
481 		SDL_UnlockMutex(msg_mutex);
482 		if (sock_select(talk_sock, 500) >= 0) {
483 			int32_t player;
484 			char buf[256];
485 
486 			if (read_int(talk_sock, &player) < 0 ||
487 			    read_str(talk_sock, buf, 255) < 0) {
488 				break;
489 			}
490 			printf("< Got message from player %d: %s\n", player, buf);
491 
492 			options_game_lock();
493 			game = options_get_game();
494 			if (!game) {
495 				options_game_unlock();
496 				printf("can't get game\n");
497 				break;
498 			}
499 			game_push_message(game, player, buf);
500 			options_game_unlock();
501 		}
502 
503 		options_game_lock();
504 		game = options_get_game();
505 		if (!game) {
506 			options_game_unlock();
507 			printf("can't get game\n");
508 			break;
509 		}
510 		if (game->message_id > game->players_msg_id[mygameplayer]
511                     && !net_is_typing_msg()) {
512 			/* Display first available message. */
513 			int msg_id = game->players_msg_id[mygameplayer] + 1;
514 			const Message *msg = &game->messages[msg_id];
515 			const char *player_name = game->player_name[msg->player];
516 
517 			if (msg->player != mygameplayer) {
518 				last_displayed_message = time(NULL);
519 				should_clear = TRUE;
520 				net_talk_push_recv_msg(player_name, msg->message);
521 			}
522 
523 			game->players_msg_id[mygameplayer]++;
524 		} else if (game->message_id == game->players_msg_id[mygameplayer]
525 			   && !net_is_typing_msg() && should_clear
526 			   && time(NULL) - last_displayed_message > 60) {
527 			net_talk_push_recv_msg(NULL, NULL);
528 			should_clear = FALSE;
529 		}
530 		options_game_unlock();
531 	}
532 
533 err_protocol:
534 	sock_close(talk_sock);
535 	talk_sock = INVSOCK;
536 	return 0;
537 }
538 
539 int net_open_talk_socket(void)
540 {
541 	if (net_talk_thread) {
542 		int tmp;
543 		talk_thread_run = 0;
544 		SDL_WaitThread(net_talk_thread, &tmp);
545 	}
546 
547 	if (msg_mutex == NULL)
548 		msg_mutex = SDL_CreateMutex();
549 
550 	talk_thread_run = 1;
551 	net_talk_thread = SDL_CreateThread(net_talk_thread_func, NULL);
552 
553 	return 0;
554 }
555 
556 int net_wait_ready(int num_players, char **player_names)
557 {
558 	int missing_players = 0, prev_missing_players = 0;
559 	char buf[255], player[255];
560 	int nplayer, i;
561 
562 	if (main_sock == INVSOCK)
563 		return -1;
564 
565 	do {
566 		if (event_poll() < 0)
567 			goto err_out;
568 
569 		if (send_str(main_sock, "READY?") < 0)
570 			goto err_out;
571 		if (read_int(main_sock, &missing_players) < 0)
572 			goto err_out;
573 		sprintf(buf, get_msg(M_WAITING),
574 				missing_players, missing_players > 1 ? "s":"");
575 		SDL_FillRect(screen, NULL, 0x00000000);
576 		SDL_UpdateRect(screen, 0, 0, 0, 0);
577 		draw_message(buf, 150, 284, -1, FALSE);
578 
579 		if (read_int(main_sock, &nplayer) < 0)
580 			goto err_out;
581 
582 		if (read_str(main_sock, player, 255) < 0)
583 			goto err_out;
584 
585 		if (prev_missing_players > missing_players) {
586 			Game *game;
587 			sprintf(buf, get_msg(M_JOINED),
588 					player);
589 			draw_message(buf, 150, 284 + 40, -1, FALSE);
590 			printf("< Received a new player join: %d '%s'\n",
591 				nplayer, player);
592 
593 			/* Fixme the two player names overlap. */
594 			strcpy(player_names[nplayer], player);
595 			options_game_lock();
596 			game = options_get_game();
597 			if (game) {
598 				free(game->player_name[nplayer]);
599 				game->player_name[nplayer] = strdup(player);
600 			}
601 			options_game_unlock();
602 			if (delay_with_event_poll(1000) < 0)
603 				goto err_out;
604 		}
605 
606 		prev_missing_players = missing_players;
607 
608 		if (delay_with_event_poll(1000) < 0)
609 			goto err_out;
610 	} while (missing_players > 0);
611 
612 	printf("\n");
613 
614 	for (i = 0; i < num_players; i++) {
615 		if (read_str(main_sock, player, 255) < 0)
616 			return -1;
617 		strcpy(player_names[i], player);
618 	}
619 
620 	return net_open_talk_socket();
621 err_out:
622 	net_close();
623 	return -1;
624 }
625 
626 LList *net_get_games(int numplayer)
627 {
628 	char buf[255];
629 	int i = 0, numgames = 0, r;
630 	LList *games = NULL;
631 	assert(game_running == FALSE);
632 
633 	/* We reconnect each time. Suboptimal. */
634 	if (main_sock != INVSOCK)
635 		net_close();
636 
637 	main_sock = sock_connect(net_get_server(), NET_PORT);
638 	if (main_sock == INVSOCK)
639 		return NULL;
640 
641 	printf("\n");
642 
643 	/* init connection */
644 	r = send_str(main_sock, "LISTGAME");
645 	if (r < 0) {
646 		printf("Sending list games command failed: %s(%d)\n",
647 			net_err_str(r), r);
648 		goto err_protocol;
649 	}
650 	printf("> Asking for games list\n");
651 	CHECK_MSG(main_sock, "NUMP");
652 
653 	/* send num players */
654 	r = send_int(main_sock, numplayer);
655 	if (r < 0) {
656 		printf("Sending number of players failed: %s(%d)\n",
657 			net_err_str(r), r);
658 		goto err_protocol;
659 	}
660 	printf("> Asking for games with %d players\n", numplayer);
661 
662 	/* read number of games */
663 	r = read_int(main_sock, &numgames);
664 	if (r < 0) {
665 		printf("Getting number of games failed: %s(%d)\n",
666 			net_err_str(r), r);
667 		goto err_protocol;
668 	}
669 	printf("< Will receive %d available games\n", numgames);
670 
671 	for (i = 0; i < numgames; i++) {
672 		Game *game = malloc(sizeof(Game));
673 
674 		memset(game, 0, sizeof(Game));
675 
676 		game->num_players = numplayer;
677 
678 		r = read_int(main_sock, &game->id);
679 		if (r < 0) {
680 			printf("Getting game ID failed: %s(%d)\n",
681 				net_err_str(r), r);
682 			free(game);
683 			goto err_protocol;
684 		}
685 
686 		r = read_str(main_sock, buf, 255);
687 		if (r < 0) {
688 			printf("Getting game name failed: %s(%d)\n",
689 				net_err_str(r), r);
690 			free(game);
691 			goto err_protocol;
692 		}
693 		game->name = strdup(buf);
694 		printf("< Received game ID %d, '%s'\n", game->id, game->name);
695 		games = llist_append(games, game);
696 	}
697 
698 	return games;
699 
700 err_protocol:
701 	net_close();
702 	return NULL;
703 }
704 
705 int net_get_info(Game *game)
706 {
707 	char buf[255];
708 	int i, r;
709 
710 	if (main_sock == INVSOCK)
711 		return -1;
712 
713 	printf("\n");
714 
715 	r = send_str(main_sock, "PRELJOIN");
716 	if (r < 0) {
717 		printf("Sending preliminary join command failed: %s(%d)\n",
718 			net_err_str(r), r);
719 		goto err_protocol;
720 	}
721 
722 	r = send_int(main_sock, game->id);
723 	if (r < 0) {
724 		printf("Sending game ID failed: %s(%d)\n", net_err_str(r), r);
725 		goto err_protocol;
726 	}
727 	printf("> Asking for game ID %d details\n", game->id);
728 
729 	memset(buf, 0, 255);
730 	r = read_str(main_sock, buf, 255);
731 	if (r < 0) {
732 		printf("Getting anwser failed: %s(%d)\n", net_err_str(r), r);
733 		goto err_protocol;
734 	}
735 
736 	if (!strncmp(buf, "ERROR1", 6)) {
737 		printf("Error getting information (game %d doesn't exist)\n",
738 			game->id);
739 		goto err_protocol;
740 	}
741 
742 	for (i = 0; i < game->num_players; i++) {
743 		r = read_str(main_sock, buf, 255);
744 		if (r < 0) {
745 			printf("Failed getting player %d's name: %s(%d)\n", i,
746 				net_err_str(r), r);
747 			goto err_protocol;
748 		}
749 		printf("< Received player %d's name '%s')\n", i, buf);
750 		game->player_name[i] = strdup(buf);
751 		game->player_type[i] = INPUT_NETWORK;
752 	}
753 
754 	r = read_int(main_sock, &game->first_avail_spot);
755 	if (r < 0) {
756 		printf("Getting first available spot failed: %s(%d)\n",
757 			net_err_str(r), r);
758 		goto err_protocol;
759 	}
760 	printf("< Received first available spot %d)\n", game->first_avail_spot);
761 
762 	return 0;
763 
764 err_protocol:
765 	net_close();
766 	return -1;
767 }
768 
769 int net_join(int id, int nump, const char *my_player_name)
770 {
771 	char buf[255];
772 	int r;
773 
774 	if (main_sock == INVSOCK)
775 		return -1;
776 
777 	printf("\n");
778 
779 	r = send_str(main_sock, "JOIN");
780 	if (r < 0) {
781 		printf("Sending join command failed: %s(%d)\n", net_err_str(r), r);
782 		goto err_protocol;
783 	}
784 	printf("> Sending join command\n");
785 	r = send_int(main_sock, nump);
786 	if (r < 0) {
787 		printf("Sending player number failed: %s(%d)\n", net_err_str(r), r);
788 		goto err_protocol;
789 	}
790 	printf("> Sending my player number %d\n", nump);
791 
792 	r = read_str(main_sock, buf, 255);
793 	if (r < 0) {
794 		printf("Reading join reply failed: %s(%d)\n", net_err_str(r), r);
795 		goto err_protocol;
796 	}
797 
798 	if (strncmp(buf, "OK", 2)) {
799 		printf("Join refused.\n");
800 		goto err_protocol;
801 	}
802 
803 	r = send_str(main_sock, my_player_name);
804 	if (r < 0) {
805 		printf("Sending player name failed: %s(%d)\n", net_err_str(r), r);
806 		goto err_protocol;
807 	}
808 	printf("> Sending my player name '%s'\n", my_player_name);
809 
810 	printf("\n");
811 
812 	mygameid = id;
813 	mygameplayer = nump;
814 
815 	return 0;
816 
817 err_protocol:
818 	net_close();
819 	return -1;
820 }
821 
822 void net_send_event(int player, int x, int y)
823 {
824 	int r;
825 
826 	if(main_sock == INVSOCK)
827 		return;
828 
829 	if ((r = send_char(main_sock, 'p')) < 0 ||
830 	    (r = send_int(main_sock, player)) < 0 ||
831 	    (r = send_int(main_sock, x)) < 0 ||
832 	    (r = send_int(main_sock, y)) < 0) {
833 		printf("> Error sending event: %s (%d)\n", net_err_str(r), r);
834 		net_close();
835 		return;
836 	}
837 
838 	printf("> Sending player %d event x %d, y %d\n", player, x, y);
839 }
840 
841 static SDL_Thread *net_event_thread = NULL;
842 static SDL_sem *net_event_thread_sem = NULL;
843 static SDL_mutex *net_event_thread_mutex = NULL;
844 
845 typedef struct {
846 	int player;
847 	int x;
848 	int y;
849 } NetData;
850 
851 static int net_event_thread_func(void *data)
852 {
853 	NetData *vals = data;
854 	int r;
855 	int32_t x = -1, y = -1;
856 
857 	if(main_sock == INVSOCK) {
858 		vals->x = -2;
859 		vals->y = -2;
860 		SDL_SemPost(net_event_thread_sem);
861 		return -1;
862 	}
863 again:
864 	printf("< Asking for player event\n");
865 	if ((r = send_char(main_sock, 'r')) < 0 ||
866 	    (r = send_int(main_sock, vals->player)) < 0 ||
867 	    (r = read_int(main_sock, &x)) < 0 ||
868 	    (r = read_int(main_sock, &y)) < 0) {
869 		SDL_LockMutex(net_event_thread_mutex);
870 		vals->x = -2;
871 		vals->y = -2;
872 		printf("< Error getting player %d event: %s(%d)\n",
873 			vals->player, net_err_str(r), r);
874 		SDL_UnlockMutex(net_event_thread_mutex);
875 		SDL_SemPost(net_event_thread_sem);
876 		return -1;
877 	} else {
878 		if (x == -1 && y == -1)
879 			goto again;
880 		SDL_LockMutex(net_event_thread_mutex);
881 		vals->x = x;
882 		vals->y = y;
883 		printf("> Got player %d event x %d, y %d\n", vals->player,
884 			vals->x, vals->y);
885 		SDL_UnlockMutex(net_event_thread_mutex);
886 		SDL_SemPost(net_event_thread_sem);
887 	}
888 
889 	return 0;
890 }
891 
892 void net_get_event(int player, int *x, int *y)
893 {
894 	NetData data;
895 	int tmp;
896 
897 	data.player = player;
898 	data.x = *x = -1;
899 	data.y = *y = -1;
900 
901 	net_event_thread_sem = SDL_CreateSemaphore(0);
902 	net_event_thread_mutex = SDL_CreateMutex();
903 	net_event_thread = SDL_CreateThread(net_event_thread_func, &data);
904 
905 	SDL_LockMutex(net_event_thread_mutex);
906 	while (data.x == -1 && data.y == -1) {
907 		SDL_UnlockMutex(net_event_thread_mutex);
908 		SDL_UpdateRect(screen, 0, 0, 0, 0);
909 		SDL_SemWaitTimeout(net_event_thread_sem, 50);
910 		if (event_poll() < 0) {
911 			SDL_KillThread(net_event_thread);
912 			net_event_thread = NULL;
913 			data.x = -2;
914 			data.y = -2;
915 			net_close();
916 			break;
917 		}
918 		SDL_LockMutex(net_event_thread_mutex);
919 	}
920 	SDL_UnlockMutex(net_event_thread_mutex);
921 
922 	if (net_event_thread)
923 		SDL_WaitThread(net_event_thread, &tmp);
924 	SDL_DestroySemaphore(net_event_thread_sem);
925 	SDL_DestroyMutex(net_event_thread_mutex);
926 
927 	*x = data.x;
928 	*y = data.y;
929 }
930 
931 void net_end_game(int player)
932 {
933 	int r;
934 
935 	if(main_sock == INVSOCK)
936 		return;
937 
938 	if ((r = send_char(main_sock, 'q')) < 0 ||
939 	    (r = send_int(main_sock, player)) < 0) {
940 		printf("> Error sending quit event: %s (%d)\n", net_err_str(r), r);
941 		net_close();
942 	}
943 
944 	printf("> Sending quit event for player %d\n", player);
945 }
946 
947 void net_close(void)
948 {
949 	if(main_sock == INVSOCK)
950 		return;
951 
952 	sock_close(main_sock);
953 	main_sock = INVSOCK;
954 }
955 
956 static SDL_Thread *server_thread = NULL;
957 
958 static int server_main_thread(void *data)
959 {
960 	server_set_select_interval(1);
961 	server_set_do_broadcast(1, net_magic_number);
962 	return server_start(NULL, NULL);
963 }
964 
965 void net_set_server(const char *srv)
966 {
967 	int was_local;
968 
969 	was_local = server && !strcmp(server, "127.0.0.1");
970 
971 	free(server);
972 	server = srv ? strdup(srv):NULL ;
973 
974 	if (server && !strcmp(server, "127.0.0.1")) {
975 		if (server_thread == NULL) {
976 			net_magic_number = rand();
977 			server_thread = SDL_CreateThread(server_main_thread, NULL);
978 		}
979 	} else if (was_local) {
980 		int res;
981 		server_stop();
982 		SDL_WaitThread(server_thread, &res);
983 		net_magic_number = 0;
984 		server_thread = NULL;
985 	}
986 }
987 
988 static SDL_mutex *server_scan_mutex = NULL;
989 static SDL_Thread *server_scan_thread = NULL;
990 static int server_scan_running = 0;
991 static int n_servers_found = 0;
992 static char **server_found = NULL;
993 
994 static int server_is_ok(const char *srv, char **servers, int n_servers)
995 {
996 	int i;
997 
998 	if (!srv)
999 		return FALSE;
1000 
1001 	if (!strcmp(srv, "0.0.0.0"))
1002 		return FALSE;
1003 
1004 	for (i = 0; i < n_servers; i++)
1005 		if (!strcmp(srv, servers[i]))
1006 			return FALSE;
1007 
1008 	return TRUE;
1009 }
1010 
1011 static int scan_for_servers(void *data)
1012 {
1013 	int sock = 0, i;
1014 	struct sockaddr_in addr;
1015 	char mybuf[512];
1016 #ifndef __MINGW32__
1017 	socklen_t sock_len;
1018 	static int optOn = 1;
1019 #else
1020 	int sock_len;
1021 	static const char optOn = 1;
1022 #endif
1023 	int ret;
1024 	static int first_run = 1;
1025 
1026 	sock = socket(AF_INET, SOCK_DGRAM, 0);
1027 	if (sock < 0)
1028 		return 0;
1029 
1030 	memset((char *) &addr, 0, sizeof(addr));
1031 	addr.sin_family = AF_INET;
1032 	addr.sin_addr.s_addr = INADDR_ANY;
1033 	addr.sin_port = htons(BCAST_PORT);
1034 	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1035 			&optOn, sizeof(optOn));
1036 	setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
1037 			&optOn, sizeof(optOn));
1038 	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
1039 		return 0;
1040 
1041 	while (server_scan_running) {
1042 		char own_id[BCAST_LEN];
1043 
1044 		get_bcast_msg(own_id, BCAST_LEN, net_magic_number);
1045 
1046 		if (sock_select(sock, first_run ? 1100:100) == -1) {
1047 			if (!first_run) {
1048 				SDL_Event user_event;
1049 				user_event.type=SDL_USEREVENT_REFRESH;
1050 				user_event.user.code=2;
1051 				user_event.user.data1=NULL;
1052 				user_event.user.data2=NULL;
1053 				SDL_PushEvent(&user_event);
1054 				sleep(2);
1055 			}
1056 			SDL_LockMutex(server_scan_mutex);
1057 
1058 			for (i = 0; i < n_servers_found; i++) {
1059 				free(server_found[i]);
1060 			}
1061 			free(server_found);
1062 			server_found = NULL;
1063 			n_servers_found = 0;
1064 
1065 			SDL_UnlockMutex(server_scan_mutex);
1066 			first_run = 1;
1067 			continue;
1068 		}
1069 		first_run = 0;
1070 
1071 		memset(mybuf, 0, sizeof(mybuf));
1072 		sock_len = sizeof(addr);
1073 		ret = recvfrom(sock, mybuf, sizeof(mybuf), 0,
1074 					(struct sockaddr *)&addr,
1075 					&sock_len);
1076 		if (ret < 0) {
1077 			ret = get_net_error();
1078 			printf("error %s (%d)\n", net_err_str(ret), ret);
1079 		}
1080 
1081 		if (ret == BCAST_LEN && !strncmp(mybuf, "Biloba", 6)
1082 		 && strcmp(mybuf, own_id)) {
1083 			const char *hostname = get_hostname(&addr);
1084 
1085 			SDL_LockMutex(server_scan_mutex);
1086 
1087 			if (server_is_ok(hostname,
1088 					  server_found, n_servers_found)) {
1089 				n_servers_found++;
1090 				server_found = realloc(server_found,
1091 					n_servers_found * sizeof(char *));
1092 				server_found[n_servers_found - 1] =
1093 					strdup(hostname);
1094 			}
1095 			SDL_UnlockMutex(server_scan_mutex);
1096 		}
1097 	}
1098 	sock_close(sock);
1099 	return 0;
1100 }
1101 
1102 int net_get_servers(char ***distant_servers)
1103 {
1104 	int r, i;
1105 
1106 	if (server_scan_thread == NULL) {
1107 		server_scan_mutex = SDL_CreateMutex();
1108 		server_scan_running = 1;
1109 		server_scan_thread = SDL_CreateThread(
1110 			scan_for_servers, NULL);
1111 	}
1112 
1113 	(*distant_servers) = NULL;
1114 
1115 	SDL_LockMutex(server_scan_mutex);
1116 
1117 	r = n_servers_found;
1118 
1119 	(*distant_servers) = malloc(r * sizeof(char *));
1120 
1121 	for (i = 0; i < r; i++)
1122 		(*distant_servers)[i] = strdup(server_found[i]);
1123 
1124 	SDL_UnlockMutex(server_scan_mutex);
1125 
1126 	return r;
1127 }
1128 
1129 void net_stop_getting_servers(void)
1130 {
1131 	if (server_scan_thread != NULL) {
1132 		server_scan_running = 0;
1133 		SDL_KillThread(server_scan_thread);
1134 		SDL_DestroyMutex(server_scan_mutex);
1135 	}
1136 	server_scan_thread = NULL;
1137 	server_scan_mutex = NULL;
1138 }
1139