Freeciv-3.3
Loading...
Searching...
No Matches
servers.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include "fc_prehdrs.h"
19
20#include <errno.h>
21#include <stdlib.h>
22
23#ifdef FREECIV_HAVE_SYS_TYPES_H
24#include <sys/types.h>
25#endif
26#ifdef HAVE_SYS_SOCKET_H
27#include <sys/socket.h>
28#endif
29#ifdef HAVE_NETINET_IN_H
30#include <netinet/in.h>
31#endif
32#ifdef HAVE_ARPA_INET_H
33#include <arpa/inet.h>
34#endif
35#ifdef HAVE_NETDB_H
36#include <netdb.h>
37#endif
38#ifdef HAVE_PWD_H
39#include <pwd.h>
40#endif
41#ifdef HAVE_SYS_SELECT_H
42#include <sys/select.h>
43#endif
44#ifdef HAVE_SYS_TIME_H
45#include <sys/time.h>
46#endif
47#ifdef HAVE_SYS_UIO_H
48#include <sys/uio.h>
49#endif
50#ifdef HAVE_UNISTD_H
51#include <unistd.h>
52#endif
53
54/* dependencies */
55#include "cvercmp.h"
56
57/* utility */
58#include "fcintl.h"
59#include "fcthread.h"
60#include "log.h"
61#include "mem.h"
62#include "netfile.h"
63#include "netintf.h"
64#include "rand.h" /* fc_rand() */
65#include "registry.h"
66#include "support.h"
67
68/* common */
69#include "capstr.h"
70#include "dataio.h"
71#include "game.h"
72#include "packets.h"
73#include "version.h"
74
75/* client */
76#include "chatline_common.h"
77#include "chatline_g.h"
78#include "client_main.h"
79#include "options.h"
80#include "servers.h"
81
82#include "gui_main_g.h"
83
87
89 int sock;
90
91#ifdef FREECIV_META_ENABLED
92 /* Only used for metaserver */
93 struct {
94 enum server_scan_status status;
95
97 fc_mutex mutex;
98
99 const char *urlpath;
100 struct netfile_write_cb_data mem;
101 } meta;
102#endif /* FREECIV_META_ENABLED */
103};
104
105extern enum announce_type announce;
106
107static void delete_server_list(struct server_list *server_list);
108
109#ifdef FREECIV_META_ENABLED
110static bool begin_metaserver_scan(struct server_scan *scan);
111
112/**********************************************************************/
117{
118 struct server_list *server_list;
119 struct section_file *file;
120 int nservers, i, j;
121 const char *latest_ver;
122 const char *comment;
123 char *followtag;
124 char *q_followtag;
125
126 /* Have the string outside Q_() so it won't get collected for translation here.
127 * Actual collected string lives in translations/Strings.txt */
128#define QUALIFIED_FOLLOWTAG "?vertag:" FOLLOWTAG
129
130 /* This call closes f. */
131 if (!(file = secfile_from_stream(f, TRUE))) {
132 return NULL;
133 }
134
138 } else {
141 }
142
143 latest_ver = secfile_lookup_str_default(file, NULL, "versions.%s", followtag);
144 comment = secfile_lookup_str_default(file, NULL, "version_comments.%s", followtag);
145
146 if (latest_ver == NULL && comment == NULL) {
147 char vertext[2048];
148
149 fc_snprintf(vertext, sizeof(vertext),
150 /* TRANS: Type is version tag name like "stable", "S3_2",
151 * "windows" (which can also be localised -- msgids start
152 * '?vertag:') */
153 _("There's no %s release yet."), Q_(q_followtag));
154 log_verbose("%s", vertext);
156 } else {
157 if (latest_ver != NULL) {
158 const char *my_comparable = fc_comparable_version();
159 char vertext[2048];
160
161 log_verbose("Metaserver says latest '%s' version is '%s'; we have '%s'",
164
165 fc_snprintf(vertext, sizeof(vertext),
166 /* TRANS: Type is version tag name like "stable", "S3_2",
167 * "windows" (which can also be localised -- msgids start
168 * '?vertag:') */
169 _("Latest %s release of Freeciv is %s, this is %s."),
171
173 } else if (comment == NULL) {
174 fc_snprintf(vertext, sizeof(vertext),
175 _("There is no newer %s release of Freeciv available."),
176 followtag);
177
179 }
180 }
181
182 if (comment != NULL) {
183 log_verbose("Mesaserver comment about '%s': %s", followtag, comment);
184 version_message(comment);
185 }
186 }
187
189 nservers = secfile_lookup_int_default(file, 0, "main.nservers");
190
191 for (i = 0; i < nservers; i++) {
192 const char *host, *port, *version, *state, *message, *nplayers, *nhumans;
193 int n;
194 struct server *pserver = (struct server*)fc_malloc(sizeof(struct server));
195
196 host = secfile_lookup_str_default(file, "", "server%d.host", i);
197 pserver->host = fc_strdup(host);
198
199 port = secfile_lookup_str_default(file, "", "server%d.port", i);
200 pserver->port = atoi(port);
201
202 version = secfile_lookup_str_default(file, "", "server%d.version", i);
203 pserver->version = fc_strdup(version);
204
205 state = secfile_lookup_str_default(file, "", "server%d.state", i);
206 pserver->state = fc_strdup(state);
207
208 message = secfile_lookup_str_default(file, "", "server%d.message", i);
209 pserver->message = fc_strdup(message);
210
211 nplayers = secfile_lookup_str_default(file, "0", "server%d.nplayers", i);
212 n = atoi(nplayers);
213 pserver->nplayers = n;
214
215 nhumans = secfile_lookup_str_default(file, "-1", "server%d.humans", i);
216 n = atoi(nhumans);
217 pserver->humans = n;
218
219 if (pserver->nplayers > 0) {
220 pserver->players = fc_malloc(pserver->nplayers * sizeof(*pserver->players));
221 } else {
222 pserver->players = NULL;
223 }
224
225 for (j = 0; j < pserver->nplayers ; j++) {
226 const char *name, *nation, *type, *plrhost;
227
229 "server%d.player%d.name", i, j);
230 pserver->players[j].name = fc_strdup(name);
231
233 "server%d.player%d.type", i, j);
234 pserver->players[j].type = fc_strdup(type);
235
237 "server%d.player%d.host", i, j);
238 pserver->players[j].host = fc_strdup(plrhost);
239
240 nation = secfile_lookup_str_default(file, "",
241 "server%d.player%d.nation", i, j);
242 pserver->players[j].nation = fc_strdup(nation);
243 }
244
246 }
247
248 secfile_destroy(file);
249
250 return server_list;
251}
252
253/**********************************************************************/
256static bool meta_read_response(struct server_scan *scan)
257{
258 fz_FILE *f;
259 char str[4096];
260 struct server_list *srvrs;
261
262 f = fz_from_memory(scan->meta.mem.mem, scan->meta.mem.size, TRUE);
263 if (NULL == f) {
264 fc_snprintf(str, sizeof(str),
265 _("Failed to read the metaserver data from %s."),
266 metaserver);
267 scan->error_func(scan, str);
268
269 return FALSE;
270 }
271
272 /* Parse message body */
274 srvrs = parse_metaserver_data(f);
275 scan->srvrs.servers = srvrs;
277
278 /* 'f' (hence 'meta.mem.mem') was closed in parse_metaserver_data(). */
279 scan->meta.mem.mem = NULL;
280
281 if (NULL == srvrs) {
282 fc_snprintf(str, sizeof(str),
283 _("Failed to parse the metaserver data from %s:\n"
284 "%s."),
286 scan->error_func(scan, str);
287
288 return FALSE;
289 }
290
291 return TRUE;
292}
293
294/**********************************************************************/
297static void metaserver_scan(void *arg)
298{
299 struct server_scan *scan = arg;
300
301 if (!begin_metaserver_scan(scan)) {
302 fc_mutex_allocate(&scan->meta.mutex);
303 scan->meta.status = SCAN_STATUS_ERROR;
304 } else {
305 if (!meta_read_response(scan)) {
306 fc_mutex_allocate(&scan->meta.mutex);
307 scan->meta.status = SCAN_STATUS_ERROR;
308 } else {
309 fc_mutex_allocate(&scan->meta.mutex);
310 if (scan->meta.status == SCAN_STATUS_WAITING) {
311 scan->meta.status = SCAN_STATUS_DONE;
312 }
313 }
314 }
315
316 fc_mutex_release(&scan->meta.mutex);
317}
318
319/**********************************************************************/
325static bool begin_metaserver_scan(struct server_scan *scan)
326{
327 struct netfile_post *post;
328 bool retval = TRUE;
329
332
333 if (!netfile_send_post(metaserver, post, NULL, &scan->meta.mem, NULL)) {
334 scan->error_func(scan, _("Error connecting to metaserver"));
335 retval = FALSE;
336 }
337
339
340 return retval;
341}
342#endif /* FREECIV_META_ENABLED */
343
344/**********************************************************************/
350{
351 if (!server_list) {
352 return;
353 }
354
356 int i;
357 int n = ptmp->nplayers;
358
359 free(ptmp->host);
360 free(ptmp->version);
361 free(ptmp->state);
362 free(ptmp->message);
363
364 if (ptmp->players) {
365 for (i = 0; i < n; i++) {
366 free(ptmp->players[i].name);
367 free(ptmp->players[i].type);
368 free(ptmp->players[i].host);
369 free(ptmp->players[i].nation);
370 }
371 free(ptmp->players);
372 }
373
374 free(ptmp);
376
378}
379
380/**********************************************************************/
385static bool begin_lanserver_scan(struct server_scan *scan)
386{
387 union fc_sockaddr addr;
388 struct raw_data_out dout;
389 int send_sock, opt = 1;
390#ifndef FREECIV_HAVE_WINSOCK
391 unsigned char buffer[MAX_LEN_PACKET];
392#else /* FREECIV_HAVE_WINSOCK */
393 char buffer[MAX_LEN_PACKET];
394#endif /* FREECIV_HAVE_WINSOCK */
395#ifdef HAVE_IP_MREQN
396 struct ip_mreqn mreq4;
397#else
398 struct ip_mreq mreq4;
399#endif
400 const char *group;
401 size_t size;
402 int family;
403
404#ifdef FREECIV_IPV6_SUPPORT
405 struct ipv6_mreq mreq6;
406#endif
407
408#ifndef FREECIV_HAVE_WINSOCK
409 unsigned char ttl;
410#endif
411
412 if (announce == ANNOUNCE_NONE) {
413 /* Succeeded in doing nothing */
414 return TRUE;
415 }
416
417#ifdef FREECIV_IPV6_SUPPORT
418 if (announce == ANNOUNCE_IPV6) {
420 } else
421#endif /* IPv6 support */
422 {
423 family = AF_INET;
424 }
425
426 /* Set the UDP Multicast group IP address. */
428
429 /* Create a socket for listening for server packets. */
430 if ((scan->sock = socket(family, SOCK_DGRAM, 0)) < 0) {
431 char errstr[2048];
432
433 fc_snprintf(errstr, sizeof(errstr),
434 _("Opening socket to listen LAN announcements failed:\n%s"),
436 scan->error_func(scan, errstr);
437
438 return FALSE;
439 }
440
441 fc_nonblock(scan->sock);
442
444 (char *)&opt, sizeof(opt)) == -1) {
445 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
446 }
447
448 memset(&addr, 0, sizeof(addr));
449
450#ifdef FREECIV_IPV6_SUPPORT
451 if (family == AF_INET6) {
452 addr.saddr.sa_family = AF_INET6;
453 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT + 1);
454 addr.saddr_in6.sin6_addr = in6addr_any;
455 } else
456#endif /* IPv6 support */
457 if (family == AF_INET) {
458 addr.saddr.sa_family = AF_INET;
459 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT + 1);
460 addr.saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
461 } else {
462 /* This is not only error situation worth assert() This
463 * is error situation that has check (with assert) against
464 * earlier already. */
466
467 return FALSE;
468 }
469
470 if (bind(scan->sock, &addr.saddr, sockaddr_size(&addr)) < 0) {
471 char errstr[2048];
472
473 fc_snprintf(errstr, sizeof(errstr),
474 _("Binding socket to listen LAN announcements failed:\n%s"),
476 scan->error_func(scan, errstr);
477
478 return FALSE;
479 }
480
481#ifdef FREECIV_IPV6_SUPPORT
482 if (family == AF_INET6) {
483 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
484 mreq6.ipv6mr_interface = 0; /* TODO: Interface selection */
485
487 (const char*)&mreq6, sizeof(mreq6)) < 0) {
488 char errstr[2048];
489
490 fc_snprintf(errstr, sizeof(errstr),
491 _("Adding membership for IPv6 LAN announcement group failed:\n%s"),
493 scan->error_func(scan, errstr);
494 }
495 } else
496#endif /* IPv6 support */
497 {
498 fc_inet_aton(group, &mreq4.imr_multiaddr, FALSE);
499#ifdef HAVE_IP_MREQN
500 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
501 mreq4.imr_ifindex = 0;
502#else
503 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
504#endif
505
507 (const char*)&mreq4, sizeof(mreq4)) < 0) {
508 char errstr[2048];
509
510 fc_snprintf(errstr, sizeof(errstr),
511 _("Adding membership for IPv4 LAN announcement group failed:\n%s"),
513 scan->error_func(scan, errstr);
514
515 return FALSE;
516 }
517 }
518
519 /* Create a socket for broadcasting to servers. */
520 if ((send_sock = socket(family, SOCK_DGRAM, 0)) < 0) {
521 char errstr[2048];
522
523 fc_snprintf(errstr, sizeof(errstr),
524 _("Opening socket for sending LAN announcement request failed:\n%s"),
526 scan->error_func(scan, errstr);
527
528 return FALSE;
529 }
530
531 memset(&addr, 0, sizeof(addr));
532
533#ifdef FREECIV_IPV6_SUPPORT
534 if (family == AF_INET6) {
535 addr.saddr.sa_family = AF_INET6;
536 inet_pton(AF_INET6, group, &addr.saddr_in6.sin6_addr);
537 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT);
538 } else
539#endif /* IPv6 Support */
540 if (family == AF_INET) {
541 fc_inet_aton(group, &addr.saddr_in4.sin_addr, FALSE);
542 addr.saddr.sa_family = AF_INET;
543 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT);
544 } else {
546
547 log_error("Unsupported address family in begin_lanserver_scan()");
548
549 return FALSE;
550 }
551
552/* this setsockopt call fails on Windows 98, so we stick with the default
553 * value of 1 on Windows, which should be fine in most cases */
554#ifndef FREECIV_HAVE_WINSOCK
555 /* Set the Time-to-Live field for the packet */
557 if (setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl,
558 sizeof(ttl))) {
559 char errstr[2048];
560
561 fc_snprintf(errstr, sizeof(errstr),
562 _("Setting Time-to-Live failed:\n%s"),
564 scan->error_func(scan, errstr);
565
566 /* FIXME: Is this really supposed to be an hard error, or should we
567 * just continue? After all, Windows builds do not even attempt this. */
568 return FALSE;
569 }
570#endif /* FREECIV_HAVE_WINSOCK */
571
572 if (setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (const char*)&opt,
573 sizeof(opt))) {
574 char errstr[2048];
575
576 fc_snprintf(errstr, sizeof(errstr),
577 _("Setting Broadcast option failed:\n%s"),
579 scan->error_func(scan, errstr);
580
581 return FALSE;
582 }
583
584 dio_output_init(&dout, buffer, sizeof(buffer));
587
588
589 if (sendto(send_sock, buffer, size, 0, &addr.saddr,
590 sockaddr_size(&addr)) < 0) {
591 /* This can happen when there's no network connection */
592 char errstr[2048];
593
594 fc_snprintf(errstr, sizeof(errstr),
595 _("Sending LAN announcement request failed:\n%s"),
597 scan->error_func(scan, errstr);
598
599 return FALSE;
600 } else {
601 log_debug("Sending request for server announcement on LAN.");
602 }
603
605
607 scan->srvrs.servers = server_list_new();
609
610 return TRUE;
611}
612
613/**********************************************************************/
617static enum server_scan_status
619{
621 union fc_sockaddr fromend;
622 char msgbuf[128];
623 int type;
624 struct data_in din;
625 char servername[512];
626 char portstr[256];
627 int port;
628 char version[256];
629 char status[256];
630 char players[256];
631 char humans[256];
632 char message[1024];
633 bool found_new = FALSE;
634
635 while (TRUE) {
636 struct server *pserver;
637 bool duplicate = FALSE;
638
639 dio_input_init(&din, msgbuf, sizeof(msgbuf));
640 fromlen = sizeof(fromend);
641
642 /* Try to receive a packet from a server. No select loop is needed;
643 * we just keep on reading until recvfrom returns -1. */
644 if (recvfrom(scan->sock, msgbuf, sizeof(msgbuf), 0,
645 &fromend.saddr, &fromlen) < 0) {
646 break;
647 }
648
650 if (type != SERVER_LAN_VERSION) {
651 continue;
652 }
655 port = atoi(portstr);
657 dio_get_string_raw(&din, status, sizeof(status));
658 dio_get_string_raw(&din, players, sizeof(players));
661
662 if (!fc_strcasecmp("none", servername)) {
663 bool nameinfo = FALSE;
664#ifdef FREECIV_IPV6_SUPPORT
665 char dst[INET6_ADDRSTRLEN];
667
670 nameinfo = TRUE;
671 }
672 if (!nameinfo) {
673 if (fromend.saddr.sa_family == AF_INET6) {
674 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
675 dst, sizeof(dst));
676 } else if (fromend.saddr.sa_family == AF_INET) {
677 inet_ntop(AF_INET, &fromend.saddr_in4.sin_addr, dst, sizeof(dst));
678 } else {
680
681 log_error("Unsupported address family in get_lan_server_list()");
682
683 fc_snprintf(dst, sizeof(dst), "Unknown");
684 }
685 }
686#else /* IPv6 support */
687 const char *dst = NULL;
688 struct hostent *from;
689 const char *host = NULL;
690
691 from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
692 sizeof(fromend.saddr_in4.sin_addr), AF_INET);
693 if (from) {
694 host = from->h_name;
695 nameinfo = TRUE;
696 }
697 if (!nameinfo) {
698 dst = inet_ntoa(fromend.saddr_in4.sin_addr);
699 }
700#endif /* IPv6 support */
701
702 sz_strlcpy(servername, nameinfo ? host : dst);
703 }
704
705 /* UDP can send duplicate or delayed packets. */
708 if (0 == fc_strcasecmp(aserver->host, servername)
709 && aserver->port == port) {
710 duplicate = TRUE;
711 break;
712 }
714
715 if (duplicate) {
717 continue;
718 }
719
720 log_debug("Received a valid announcement from a server on the LAN.");
721
722 pserver = fc_malloc(sizeof(*pserver));
724 pserver->port = port;
725 pserver->version = fc_strdup(version);
726 pserver->state = fc_strdup(status);
727 pserver->nplayers = atoi(players);
728 pserver->humans = atoi(humans);
729 pserver->message = fc_strdup(message);
730 pserver->players = NULL;
731 found_new = TRUE;
732
735 }
736
737 if (found_new) {
738 return SCAN_STATUS_PARTIAL;
739 }
740 return SCAN_STATUS_WAITING;
741}
742
743/**********************************************************************/
757{
758 struct server_scan *scan;
759 bool ok = FALSE;
760
761#ifndef FREECIV_META_ENABLED
762 if (type == SERVER_SCAN_GLOBAL) {
763 return NULL;
764 }
765#endif /* FREECIV_META_ENABLED */
766
767 scan = fc_calloc(1, sizeof(*scan));
768 scan->type = type;
769 scan->error_func = error_func;
770 scan->sock = -1;
771 fc_mutex_init(&scan->srvrs.mutex);
772
773 switch (type) {
775 {
776#ifdef FREECIV_META_ENABLED
777 int thr_ret;
778
779 fc_mutex_init(&scan->meta.mutex);
780 scan->meta.status = SCAN_STATUS_WAITING;
781 thr_ret = fc_thread_start(&scan->meta.thr, metaserver_scan, scan);
782 if (thr_ret) {
783 ok = FALSE;
784 } else {
785 ok = TRUE;
786 }
787#endif /* FREECIV_META_ENABLED */
788 }
789 break;
791 ok = begin_lanserver_scan(scan);
792 break;
793 case SERVER_SCAN_LAST:
794 break;
795 }
796
797 if (!ok) {
798 server_scan_finish(scan);
799 scan = NULL;
800 }
801
802 return scan;
803}
804
805/**********************************************************************/
810{
811 if (!scan) {
812 return SERVER_SCAN_LAST;
813 }
814 return scan->type;
815}
816
817/**********************************************************************/
833{
834 if (!scan) {
835 return SCAN_STATUS_ERROR;
836 }
837
838 switch (scan->type) {
840#ifdef FREECIV_META_ENABLED
841 {
842 enum server_scan_status status;
843
844 fc_mutex_allocate(&scan->meta.mutex);
845 status = scan->meta.status;
846 fc_mutex_release(&scan->meta.mutex);
847
848 return status;
849 }
850#endif /* FREECIV_META_ENABLED */
851 break;
853 return get_lan_server_list(scan);
854 break;
855 case SERVER_SCAN_LAST:
856 break;
857 }
858
859 return SCAN_STATUS_ERROR;
860}
861
862/**********************************************************************/
865struct srv_list *
867{
868 if (!scan) {
869 return NULL;
870 }
871
872 return &scan->srvrs;
873}
874
875/**********************************************************************/
880{
881 if (!scan) {
882 return;
883 }
884
885 if (scan->type == SERVER_SCAN_GLOBAL) {
886#ifdef FREECIV_META_ENABLED
887 /* Signal metaserver scan thread to stop */
888 fc_mutex_allocate(&scan->meta.mutex);
889 scan->meta.status = SCAN_STATUS_ABORT;
890 fc_mutex_release(&scan->meta.mutex);
891
892 /* Wait thread to stop */
893 fc_thread_wait(&scan->meta.thr);
894 fc_mutex_destroy(&scan->meta.mutex);
895
896 /* This mainly duplicates code from below "else" block.
897 * That's intentional, since they will be completely different in future versions.
898 * We are better prepared for that by having them separately already. */
899 if (scan->sock >= 0) {
900 fc_closesocket(scan->sock);
901 scan->sock = -1;
902 }
903
904 if (scan->srvrs.servers) {
907 scan->srvrs.servers = NULL;
909 }
910
911 if (scan->meta.mem.mem) {
912 FC_FREE(scan->meta.mem.mem);
913 scan->meta.mem.mem = NULL;
914 }
915#endif /* FREECIV_META_ENABLED */
916 } else {
917 if (scan->sock >= 0) {
918 fc_closesocket(scan->sock);
919 scan->sock = -1;
920 }
921
922 if (scan->srvrs.servers) {
924 scan->srvrs.servers = NULL;
925 }
926 }
927
929
930 free(scan);
931}
#define str
Definition astring.c:76
#define n
Definition astring.c:77
const char *const our_capability
Definition capstr.c:32
char metaserver[512]
char * incite_cost
Definition comments.c:76
#define MAX_LEN_PACKET
Definition conn_types.h:29
int dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:598
size_t dio_output_used(struct raw_data_out *dout)
Definition dataio_raw.c:184
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Definition dataio_raw.c:202
bool dio_get_string_raw(struct data_in *din, char *dest, size_t max_dest_size)
Definition dataio_raw.c:831
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
int fc_thread_start(fc_thread *thread, void(*function)(void *arg), void *arg)
void fc_mutex_init(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
void fc_thread_wait(fc_thread *thread)
void fc_mutex_destroy(fc_mutex *mutex)
void version_message(const char *vertext)
Definition chatline.c:1478
GType type
Definition repodlgs.c:1313
static struct server_list * server_list
Definition connectdlg.c:61
const char * name
Definition inputfile.c:127
fz_FILE * fz_from_memory(char *buffer, int size, bool control)
Definition ioz.c:207
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
announce_type
Definition net_types.h:53
@ ANNOUNCE_IPV6
Definition net_types.h:56
@ ANNOUNCE_NONE
Definition net_types.h:54
void netfile_close_post(struct netfile_post *post)
Definition netfile.c:246
struct netfile_post * netfile_start_post(void)
Definition netfile.c:199
bool netfile_send_post(const char *URL, struct netfile_post *post, FILE *reply_fp, struct netfile_write_cb_data *mem_data, const char *addr)
Definition netfile.c:270
void netfile_add_form_str(struct netfile_post *post, const char *name, const char *val)
Definition netfile.c:213
bool fc_inet_aton(const char *cp, struct in_addr *inp, bool addr_none_ok)
Definition netintf.c:466
void fc_closesocket(int sock)
Definition netintf.c:186
int sockaddr_size(union fc_sockaddr *addr)
Definition netintf.c:305
void fc_nonblock(int sockfd)
Definition netintf.c:227
int socklen_t
Definition netintf.h:67
#define FC_IPV6_ADD_MEMBERSHIP
Definition netintf.h:63
struct client_options gui_options
Definition options.c:71
#define DEFAULT_FOLLOWTAG_OPTION
Definition options.h:30
const char * secfile_error(void)
void secfile_destroy(struct section_file *secfile)
struct section_file * secfile_from_stream(fz_FILE *stream, bool allow_duplicates)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
#define SERVER_LAN_TTL
Definition sernet.h:25
#define SERVER_LAN_VERSION
Definition sernet.h:26
#define SERVER_LAN_PORT
Definition sernet.h:24
static void delete_server_list(struct server_list *server_list)
Definition servers.c:349
struct srv_list * server_scan_get_list(struct server_scan *scan)
Definition servers.c:866
enum announce_type announce
static enum server_scan_status get_lan_server_list(struct server_scan *scan)
Definition servers.c:618
void server_scan_finish(struct server_scan *scan)
Definition servers.c:879
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:755
static bool begin_lanserver_scan(struct server_scan *scan)
Definition servers.c:385
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:809
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:832
#define server_list_iterate_end
Definition servers.h:57
server_scan_status
Definition servers.h:79
@ SCAN_STATUS_WAITING
Definition servers.h:81
@ SCAN_STATUS_ABORT
Definition servers.h:84
@ SCAN_STATUS_PARTIAL
Definition servers.h:82
@ SCAN_STATUS_ERROR
Definition servers.h:80
@ SCAN_STATUS_DONE
Definition servers.h:83
#define server_list_iterate(serverlist, pserver)
Definition servers.h:55
server_scan_type
Definition servers.h:67
@ SERVER_SCAN_LOCAL
Definition servers.h:68
@ SERVER_SCAN_LAST
Definition servers.h:70
@ SERVER_SCAN_GLOBAL
Definition servers.h:69
void(* ServerScanErrorFunc)(struct server_scan *scan, const char *message)
Definition servers.h:73
char * get_multicast_group(bool ipv6_preferred)
Definition shared.c:1667
size_t size
Definition specvec.h:72
char followtag_override[5112]
Definition options.h:115
Definition netfile.c:39
ServerScanErrorFunc error_func
Definition servers.c:86
struct srv_list srvrs
Definition servers.c:88
enum server_scan_type type
Definition servers.c:85
int humans
Definition servers.h:48
char * host
Definition servers.h:30
char * version
Definition servers.h:34
char * state
Definition servers.h:35
int port
Definition servers.h:31
int nplayers
Definition servers.h:47
fc_mutex mutex
Definition servers.h:64
struct server_list * servers
Definition servers.h:63
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
const char * fc_strerror(fc_errno err)
Definition support.c:609
fc_errno fc_get_errno(void)
Definition support.c:592
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct sockaddr saddr
Definition netintf.h:71
struct sockaddr_in saddr_in4
Definition netintf.h:72
const char * fc_comparable_version(void)
Definition version.c:95