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