23#ifdef FREECIV_HAVE_SYS_TYPES_H
26#ifdef HAVE_SYS_SOCKET_H
27#include <sys/socket.h>
29#ifdef HAVE_NETINET_IN_H
30#include <netinet/in.h>
32#ifdef HAVE_ARPA_INET_H
41#ifdef HAVE_SYS_SELECT_H
42#include <sys/select.h>
90#ifdef FREECIV_META_ENABLED
108#ifdef FREECIV_META_ENABLED
109static bool begin_metaserver_scan(
struct server_scan *scan);
120 const char *latest_ver;
125#define QUALIFIED_FOLLOWTAG "?vertag:" FOLLOWTAG
135 if (latest_ver == NULL && comment == NULL) {
142 _(
"There's no %s release yet."),
Q_(QUALIFIED_FOLLOWTAG));
146 if (latest_ver != NULL) {
150 log_verbose(
"Metaserver says latest '" FOLLOWTAG
"' version is '%s'; we have '%s'",
151 latest_ver, my_comparable);
152 if (cvercmp_greater(latest_ver, my_comparable)) {
158 _(
"Latest %s release of Freeciv is %s, this is %s."),
159 Q_(QUALIFIED_FOLLOWTAG), latest_ver, my_comparable);
162 }
else if (comment == NULL) {
164 _(
"There is no newer %s release of Freeciv available."),
171 if (comment != NULL) {
172 log_verbose(
"Mesaserver comment about '" FOLLOWTAG
"': %s", comment);
180 for (i = 0; i < nservers; i++) {
181 const char *host, *port, *version, *state, *
message, *nplayers, *nhumans;
214 for (j = 0; j < pserver->
nplayers ; j++) {
215 const char *
name, *nation, *
type, *plrhost;
218 "server%d.player%d.name", i, j);
222 "server%d.player%d.type", i, j);
226 "server%d.player%d.host", i, j);
230 "server%d.player%d.nation", i, j);
245static bool meta_read_response(
struct server_scan *scan)
254 _(
"Failed to read the metaserver data from %s."),
263 srvrs = parse_metaserver_data(f);
268 scan->meta.mem.mem = NULL;
272 _(
"Failed to parse the metaserver data from %s:\n"
286static void metaserver_scan(
void *arg)
290 if (!begin_metaserver_scan(scan)) {
294 if (!meta_read_response(scan)) {
314static bool begin_metaserver_scan(
struct server_scan *scan)
323 scan->
error_func(scan,
_(
"Error connecting to metaserver"));
346 int n = ptmp->nplayers;
354 for (i = 0; i <
n; i++) {
355 free(ptmp->players[i].name);
356 free(ptmp->players[i].type);
357 free(ptmp->players[i].host);
358 free(ptmp->players[i].nation);
378 int send_sock, opt = 1;
379#ifndef FREECIV_HAVE_WINSOCK
385 struct ip_mreqn mreq4;
387 struct ip_mreq mreq4;
393#ifdef FREECIV_IPV6_SUPPORT
394 struct ipv6_mreq mreq6;
397#ifndef FREECIV_HAVE_WINSOCK
406#ifdef FREECIV_IPV6_SUPPORT
419 if ((scan->
sock = socket(family, SOCK_DGRAM, 0)) < 0) {
423 _(
"Opening socket to listen LAN announcements failed:\n%s"),
432 if (setsockopt(scan->
sock, SOL_SOCKET, SO_REUSEADDR,
433 (
char *)&opt,
sizeof(opt)) == -1) {
437 memset(&addr, 0,
sizeof(addr));
439#ifdef FREECIV_IPV6_SUPPORT
440 if (family == AF_INET6) {
441 addr.
saddr.sa_family = AF_INET6;
443 addr.saddr_in6.sin6_addr = in6addr_any;
446 if (family == AF_INET) {
447 addr.
saddr.sa_family = AF_INET;
449 addr.
saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
463 _(
"Binding socket to listen LAN announcements failed:\n%s"),
470#ifdef FREECIV_IPV6_SUPPORT
471 if (family == AF_INET6) {
472 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
473 mreq6.ipv6mr_interface = 0;
476 (
const char*)&mreq6,
sizeof(mreq6)) < 0) {
480 _(
"Adding membership for IPv6 LAN announcement group failed:\n%s"),
489 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
490 mreq4.imr_ifindex = 0;
492 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
495 if (setsockopt(scan->
sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
496 (
const char*)&mreq4,
sizeof(mreq4)) < 0) {
500 _(
"Adding membership for IPv4 LAN announcement group failed:\n%s"),
509 if ((send_sock = socket(family, SOCK_DGRAM, 0)) < 0) {
513 _(
"Opening socket for sending LAN announcement request failed:\n%s"),
520 memset(&addr, 0,
sizeof(addr));
522#ifdef FREECIV_IPV6_SUPPORT
523 if (family == AF_INET6) {
524 addr.
saddr.sa_family = AF_INET6;
525 inet_pton(AF_INET6, group, &addr.saddr_in6.sin6_addr);
529 if (family == AF_INET) {
531 addr.
saddr.sa_family = AF_INET;
536 log_error(
"Unsupported address family in begin_lanserver_scan()");
543#ifndef FREECIV_HAVE_WINSOCK
546 if (setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (
const char*)&ttl,
551 _(
"Setting Time-to-Live failed:\n%s"),
561 if (setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (
const char*)&opt,
566 _(
"Setting Broadcast option failed:\n%s"),
578 if (sendto(send_sock, buffer,
size, 0, &addr.
saddr,
584 _(
"Sending LAN announcement request failed:\n%s"),
590 log_debug(
"Sending request for server announcement on LAN.");
614 char servername[512];
622 bool found_new =
FALSE;
626 bool duplicate =
FALSE;
629 fromlen =
sizeof(fromend);
633 if (recvfrom(scan->
sock, msgbuf,
sizeof(msgbuf), 0,
634 &fromend.
saddr, &fromlen) < 0) {
644 port = atoi(portstr);
652 bool nameinfo =
FALSE;
653#ifdef FREECIV_IPV6_SUPPORT
654 char dst[INET6_ADDRSTRLEN];
655 char host[NI_MAXHOST], service[NI_MAXSERV];
657 if (!getnameinfo(&fromend.
saddr, fromlen,
host, NI_MAXHOST,
658 service, NI_MAXSERV, NI_NUMERICSERV)) {
662 if (fromend.
saddr.sa_family == AF_INET6) {
663 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
665 }
else if (fromend.
saddr.sa_family == AF_INET) {
666 inet_ntop(AF_INET, &fromend.
saddr_in4.sin_addr, dst,
sizeof(dst));;
670 log_error(
"Unsupported address family in get_lan_server_list()");
676 const char *dst = NULL;
677 struct hostent *from;
678 const char *host = NULL;
680 from = gethostbyaddr((
char *) &fromend.
saddr_in4.sin_addr,
681 sizeof(fromend.
saddr_in4.sin_addr), AF_INET);
687 dst = inet_ntoa(fromend.
saddr_in4.sin_addr);
691 sz_strlcpy(servername, nameinfo ? host : dst);
698 && aserver->port == port) {
709 log_debug(
"Received a valid announcement from a server on the LAN.");
713 pserver->
port = port;
717 pserver->
humans = atoi(humans);
750#ifndef FREECIV_META_ENABLED
765#ifdef FREECIV_META_ENABLED
827 switch (scan->
type) {
829#ifdef FREECIV_META_ENABLED
834 status = scan->meta.status;
875#ifdef FREECIV_META_ENABLED
888 if (scan->
sock >= 0) {
900 if (scan->meta.mem.mem) {
902 scan->meta.mem.mem = NULL;
906 if (scan->
sock >= 0) {
const char *const our_capability
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
bool dio_get_uint8_raw(struct data_in *din, int *dest)
size_t dio_output_used(struct raw_data_out *dout)
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
bool dio_get_string_raw(struct data_in *din, char *dest, size_t max_dest_size)
int fc_thread_start(fc_thread *thread, void(*function)(void *arg), void *arg)
void fc_allocate_mutex(fc_mutex *mutex)
void fc_release_mutex(fc_mutex *mutex)
void fc_thread_wait(fc_thread *thread)
void fc_destroy_mutex(fc_mutex *mutex)
void fc_init_mutex(fc_mutex *mutex)
void version_message(const char *vertext)
static struct server_list * server_list
fz_FILE * fz_from_memory(char *buffer, int size, bool control)
#define log_verbose(message,...)
#define fc_assert(condition)
#define log_debug(message,...)
#define log_error(message,...)
#define fc_calloc(n, esz)
void netfile_close_post(struct netfile_post *post)
struct netfile_post * netfile_start_post(void)
bool netfile_send_post(const char *URL, struct netfile_post *post, FILE *reply_fp, struct netfile_write_cb_data *mem_data, const char *addr)
void netfile_add_form_str(struct netfile_post *post, const char *name, const char *val)
bool fc_inet_aton(const char *cp, struct in_addr *inp, bool addr_none_ok)
void fc_closesocket(int sock)
int sockaddr_size(union fc_sockaddr *addr)
void fc_nonblock(int sockfd)
#define FC_IPV6_ADD_MEMBERSHIP
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_VERSION
static void delete_server_list(struct server_list *server_list)
struct srv_list * server_scan_get_list(struct server_scan *scan)
enum announce_type announce
static enum server_scan_status get_lan_server_list(struct server_scan *scan)
void server_scan_finish(struct server_scan *scan)
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
static bool begin_lanserver_scan(struct server_scan *scan)
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
enum server_scan_status server_scan_poll(struct server_scan *scan)
#define server_list_iterate_end
#define server_list_iterate(serverlist, pserver)
void(* ServerScanErrorFunc)(struct server_scan *scan, const char *message)
char * get_multicast_group(bool ipv6_preferred)
ServerScanErrorFunc error_func
enum server_scan_type type
struct server::players * players
struct server_list * servers
int fc_snprintf(char *str, size_t n, const char *format,...)
int fc_strcasecmp(const char *str0, const char *str1)
const char * fc_strerror(fc_errno err)
fc_errno fc_get_errno(void)
#define sz_strlcpy(dest, src)
struct sockaddr_in saddr_in4
const char * fc_comparable_version(void)