Freeciv-3.2
Loading...
Searching...
No Matches
meta.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 <ctype.h>
21#include <errno.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#ifdef HAVE_NETINET_IN_H
27#include <netinet/in.h>
28#endif
29#ifdef HAVE_SYS_SOCKET_H
30#include <sys/socket.h>
31#endif
32#ifdef HAVE_SYS_TYPES_H
33#include <sys/types.h>
34#endif
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38#ifdef HAVE_ARPA_INET_H
39#include <arpa/inet.h>
40#endif
41
42/* utility */
43#include "fcintl.h"
44#include "fcthread.h"
45#include "log.h"
46#include "mem.h"
47#include "netintf.h"
48#include "netfile.h"
49#include "support.h"
50#include "timing.h"
51
52/* common */
53#include "capstr.h"
54#include "connection.h"
55#include "dataio.h"
56#include "game.h"
57#include "map.h"
58#include "nation.h"
59#include "version.h"
60
61/* server */
62#include "console.h"
63#include "plrhand.h"
64#include "settings.h"
65#include "srv_main.h"
66
67#include "meta.h"
68
69static bool server_is_open = FALSE;
71static int meta_retry_wait = 0;
72
73static char meta_patches[256] = "";
74static char meta_message[256] = "";
75
76#ifdef FREECIV_META_ENABLED
78#endif /* FREECIV_META_ENABLED */
79
80/*********************************************************************/
84{
85 return "none";
86}
87
88/*********************************************************************/
92{
93#if IS_BETA_VERSION
94 return "unstable pre-" NEXT_STABLE_VERSION ": beware";
95#else /* IS_BETA_VERSION */
96#if IS_DEVEL_VERSION
97 return "development version: beware";
98#else /* IS_DEVEL_VERSION */
99 return "-";
100#endif /* IS_DEVEL_VERSION */
101#endif /* IS_BETA_VERSION */
102}
103
104/*********************************************************************/
107const char *get_meta_patches_string(void)
108{
109 return meta_patches;
110}
111
112/*********************************************************************/
115const char *get_meta_message_string(void)
116{
117 return meta_message;
118}
119
120#ifdef FREECIV_META_ENABLED
121/*********************************************************************/
124static const char *get_meta_type_string(void)
125{
126 if (game.server.meta_info.type[0] != '\0') {
127 return game.server.meta_info.type;
128 }
129
130 return NULL;
131}
132#endif /* FREECIV_META_ENABLED */
133
134/*********************************************************************/
138{
139 if (game.server.meta_info.user_message[0] != '\0') {
141 }
142
143 return NULL;
144}
145
146/*********************************************************************/
153{
154 const char *user_message;
155
156 user_message = get_user_meta_message_string();
157
158 if (user_message == NULL) {
159 /* No user message */
160 if (automatic != NULL) {
162 }
163 return;
164 }
165
166 set_meta_message_string(user_message);
167}
168
169/*********************************************************************/
172void set_meta_patches_string(const char *string)
173{
174 sz_strlcpy(meta_patches, string);
175}
176
177/*********************************************************************/
180void set_meta_message_string(const char *string)
181{
182 sz_strlcpy(meta_message, string);
183}
184
185/*********************************************************************/
188void set_user_meta_message_string(const char *string)
189{
190 if (string != NULL && string[0] != '\0') {
193 } else {
194 /* Remove user meta message. We will use automatic messages instead */
197 }
198}
199
200/*********************************************************************/
203char *meta_addr_port(void)
204{
205 return srvarg.metaserver_addr;
206}
207
208#ifdef FREECIV_META_ENABLED
209/*********************************************************************/
212static void metaserver_failed(void)
213{
215 con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
216 con_flush();
217
219 } else {
220 con_puts(C_METAERROR, _("Metaserver connection currently failing."));
221 meta_retry_wait = 1;
222 }
223}
224
225/*********************************************************************/
228static inline bool meta_insert_setting(struct netfile_post *post,
229 const char *set_name)
230{
231 const struct setting *pset = setting_by_name(set_name);
232 char buf[256];
233
235 "Setting \"%s\" not found!", set_name);
238 setting_value_name(pset, FALSE, buf, sizeof(buf)));
239 return TRUE;
240}
241
242/*********************************************************************/
245static void send_metaserver_post(void *arg)
246{
247 struct netfile_post *post = (struct netfile_post *) arg;
248 char *addr;
249
250 if (srvarg.bind_meta_addr != NULL) {
251 addr = srvarg.bind_meta_addr;
252 } else {
253 addr = srvarg.bind_addr;
254 }
255
257 con_puts(C_METAERROR, _("Error connecting to metaserver"));
259 }
260
262}
263
264/*********************************************************************/
267static bool send_to_metaserver(enum meta_flag flag)
268{
269 int players = 0;
270 int humans = 0;
271 char host[512];
272 char state[20];
273 char rs[256];
274 struct netfile_post *post;
275
276 switch (server_state()) {
277 case S_S_INITIAL:
278 sz_strlcpy(state, "Pregame");
279 break;
280 case S_S_RUNNING:
281 sz_strlcpy(state, "Running");
282 break;
283 case S_S_OVER:
284 sz_strlcpy(state, "Game Ended");
285 break;
286 }
287
288 /* Get hostname */
289 if (srvarg.identity_name[0] != '\0') {
291 } else if (fc_gethostname(host, sizeof(host)) != 0) {
292 sz_strlcpy(host, "unknown");
293 }
294
295 if (game.control.version[0] != '\0') {
296 fc_snprintf(rs, sizeof(rs), "%s %s", game.control.name, game.control.version);
297 } else {
299 }
300
301 /* Freed in metaserver thread function send_metaserver_post() */
303
304 netfile_add_form_str(post, "host", host);
306 netfile_add_form_str(post, "state", state);
307 netfile_add_form_str(post, "ruleset", rs);
308
309 if (flag == META_GOODBYE) {
310 netfile_add_form_int(post, "bye", 1);
311 } else {
312 const char *srvtype = get_meta_type_string();
313
314 if (srvtype != NULL) {
316 }
318 netfile_add_form_str(post, "patches",
321
323 netfile_add_form_str(post, "message",
325
326 /* NOTE: Send info for ALL players or none at all. */
327 if (normal_player_count() == 0) {
328 netfile_add_form_int(post, "dropplrs", 1);
329 } else {
330 players = 0; /* Counter for players_available */
331 humans = 0;
332
333 players_iterate(plr) {
335 char type[15];
336 struct connection *pconn = conn_by_user(plr->username);
337
338 if (!plr->is_alive) {
339 sz_strlcpy(type, "Dead");
340 } else if (is_barbarian(plr)) {
341 sz_strlcpy(type, "Barbarian");
342 } else if (is_ai(plr)) {
343 sz_strlcpy(type, "A.I.");
344 } else if (is_human(plr)) {
345 sz_strlcpy(type, "Human");
346 } else {
347 sz_strlcpy(type, "-");
348 }
349
350 netfile_add_form_str(post, "plu[]", plr->username);
351 netfile_add_form_str(post, "plt[]", type);
352 netfile_add_form_str(post, "pll[]", player_name(plr));
353 netfile_add_form_str(post, "pln[]",
354 plr->nation != NO_NATION_SELECTED
356 : "none");
357 netfile_add_form_str(post, "plf[]",
358 plr->nation != NO_NATION_SELECTED
359 ? nation_of_player(plr)->flag_graphic_str
360 : "none");
361 netfile_add_form_str(post, "plh[]",
362 pconn ? pconn->addr : "");
363
364 /* Is this player available to take?
365 * TODO: There's some duplication here with
366 * stdinhand.c:is_allowed_to_take() */
367 if (is_barbarian(plr) && !strchr(game.server.allow_take, 'b')) {
369 } else if (!plr->is_alive && !strchr(game.server.allow_take, 'd')) {
371 } else if (is_ai(plr)
373 (game.info.is_new_game ? 'A' : 'a'))) {
375 } else if (is_human(plr)
377 (game.info.is_new_game ? 'H' : 'h'))) {
379 }
380
381 if (pconn) {
383 }
384
386 players++;
387 }
388
389 if (is_human(plr) && plr->is_alive) {
390 humans++;
391 }
393
394 /* Send the number of available players. */
395 netfile_add_form_int(post, "available", players);
396 netfile_add_form_int(post, "humans", humans);
397 }
398
399 /* Send some variables: should be listed in inverted order? */
400 {
401 static const char *settings[] = {
402 "timeout", "endturn", "minplayers", "maxplayers",
403 "aifill", "allowtake", "generator"
404 };
405 int i;
406
407 for (i = 0; i < ARRAY_SIZE(settings); i++) {
409 }
410
411 /* HACK: Send the most determinant setting for the map size. */
412 switch (wld.map.server.mapsize) {
413 case MAPSIZE_FULLSIZE:
414 meta_insert_setting(post, "size");
415 break;
416 case MAPSIZE_PLAYER:
417 meta_insert_setting(post, "tilesperplayer");
418 break;
419 case MAPSIZE_XYSIZE:
420 meta_insert_setting(post, "xsize");
421 meta_insert_setting(post, "ysize");
422 break;
423 }
424 }
425
426 /* Turn and year. */
427 netfile_add_form_str(post, "vn[]", "turn");
429 netfile_add_form_str(post, "vn[]", "year");
430
431 if (server_state() != S_S_INITIAL) {
433 } else {
434 netfile_add_form_str(post, "vv[]", "Calendar not set up");
435 }
436 }
437
438 if (meta_srv_thread != NULL) {
439 /* Previously started thread */
441 } else {
443 }
444
445 /* Send POST in new thread */
447
448 return TRUE;
449}
450#endif /* FREECIV_META_ENABLED */
451
452/*********************************************************************/
460
461/*********************************************************************/
479
480/*********************************************************************/
484{
485 return server_is_open;
486}
487
488/*********************************************************************/
492{
493#ifndef FREECIV_META_ENABLED
494
495 return FALSE;
496
497#else /* FREECIV_META_ENABLED */
498
499 static struct timer *last_send_timer = NULL;
500 static bool want_update;
501 int since_previous;
502
503 if (!server_is_open) {
504 return FALSE;
505 }
506
507 /* Persistent connection temporary failures handling */
508 if (meta_retry_wait > 0) {
509 if (meta_retry_wait++ > 5) {
510 meta_retry_wait = 0;
511 } else {
512 return FALSE;
513 }
514 }
515
516 /* If we're bidding farewell, ignore all timers */
517 if (flag == META_GOODBYE) {
518 if (last_send_timer) {
521 }
522 send_to_metaserver(flag);
523
524 /* Wait metaserver thread to finish */
528
529 return TRUE;
530 }
531
532 if (last_send_timer != NULL) {
534
535 /* Don't allow the user to spam the metaserver with updates */
537 if (flag == META_INFO) {
538 want_update = TRUE; /* We couldn't update now, but update a.s.a.p. */
539 }
540
541 return FALSE;
542 }
543 } else {
546 }
547
548 /* If we're asking for a refresh, only do so if
549 * we've exceeded the refresh interval */
550 if ((flag == META_REFRESH) && !want_update
552 return FALSE;
553 }
554
555 /* Start a new timer if we haven't already */
556 if (last_send_timer == NULL) {
558 }
559
563
564 return send_to_metaserver(flag);
565#endif /* FREECIV_META_ENABLED */
566}
const char *const our_capability
Definition capstr.c:32
char * incite_cost
Definition comments.c:75
struct connection * conn_by_user(const char *user_name)
Definition connection.c:377
void con_flush(void)
Definition console.c:243
void con_puts(enum rfc_status rfc_status, const char *str)
Definition console.c:226
@ C_METAERROR
Definition console.h:46
#define _(String)
Definition fcintl.h:67
int fc_thread_start(fc_thread *thread, void(*function)(void *arg), void *arg)
void fc_thread_wait(fc_thread *thread)
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
static GtkWidget * persistent
GType type
Definition repodlgs.c:1313
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
@ MAPSIZE_FULLSIZE
Definition map_types.h:39
@ MAPSIZE_PLAYER
Definition map_types.h:40
@ MAPSIZE_XYSIZE
Definition map_types.h:43
#define fc_malloc(sz)
Definition mem.h:34
void maybe_automatic_meta_message(const char *automatic)
Definition meta.c:152
void set_meta_patches_string(const char *string)
Definition meta.c:172
const char * get_user_meta_message_string(void)
Definition meta.c:137
bool is_metaserver_open(void)
Definition meta.c:483
static bool persistent_meta_connection
Definition meta.c:70
char * meta_addr_port(void)
Definition meta.c:203
void set_meta_message_string(const char *string)
Definition meta.c:180
static char meta_message[256]
Definition meta.c:74
const char * default_meta_message_string(void)
Definition meta.c:91
void server_close_meta(void)
Definition meta.c:455
const char * default_meta_patches_string(void)
Definition meta.c:83
const char * get_meta_message_string(void)
Definition meta.c:115
bool send_server_info_to_metaserver(enum meta_flag flag)
Definition meta.c:491
static int meta_retry_wait
Definition meta.c:71
static bool server_is_open
Definition meta.c:69
bool server_open_meta(bool persistent)
Definition meta.c:464
const char * get_meta_patches_string(void)
Definition meta.c:107
void set_user_meta_message_string(const char *string)
Definition meta.c:188
static char meta_patches[256]
Definition meta.c:73
#define METASERVER_REFRESH_INTERVAL
Definition meta.h:22
#define METASERVER_MIN_UPDATE_INTERVAL
Definition meta.h:23
meta_flag
Definition meta.h:25
@ META_GOODBYE
Definition meta.h:28
@ META_INFO
Definition meta.h:26
@ META_REFRESH
Definition meta.h:27
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
#define NO_NATION_SELECTED
Definition nation.h:30
void netfile_close_post(struct netfile_post *post)
Definition netfile.c:244
struct netfile_post * netfile_start_post(void)
Definition netfile.c:197
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:268
void netfile_add_form_int(struct netfile_post *post, const char *name, const int val)
Definition netfile.c:232
void netfile_add_form_str(struct netfile_post *post, const char *name, const char *val)
Definition netfile.c:211
const char * player_name(const struct player *pplayer)
Definition player.c:895
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define is_ai(plr)
Definition player.h:230
#define is_human(plr)
Definition player.h:229
int normal_player_count(void)
Definition plrhand.c:3204
struct setting * setting_by_name(const char *name)
Definition settings.c:3306
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4264
static struct setting settings[]
Definition settings.c:1473
const char * setting_name(const struct setting *pset)
Definition settings.c:3330
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
struct server_arguments srvarg
Definition srv_main.c:176
enum server_states server_state(void)
Definition srv_main.c:333
char type[20]
Definition game.h:270
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
char user_message[256]
Definition game.h:269
struct civ_game::@31::@35 server
struct civ_game::@31::@35::@38 meta_info
char allow_take[MAX_LEN_ALLOW_TAKE]
Definition game.h:244
enum mapsize_type mapsize
Definition map_types.h:88
struct civ_map::@42::@44 server
Definition netfile.c:39
char version[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char * bind_addr
Definition srv_main.h:34
char metaserver_addr[256]
Definition srv_main.h:29
char * bind_meta_addr
Definition srv_main.h:38
char serverid[256]
Definition srv_main.h:49
char identity_name[256]
Definition srv_main.h:31
Definition timing.c:81
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int fc_gethostname(char *buf, size_t len)
Definition support.c:1021
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
void timer_clear(struct timer *t)
Definition timing.c:252
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:264
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:384
@ TIMER_ACTIVE
Definition timing.h:46
@ TIMER_USER
Definition timing.h:42