Freeciv21
Develop your civilization from humble roots to a global empire
server.cpp
Go to the documentation of this file.
1 /*
2  * (c) Copyright 2021 The Freeciv21 contributors
3  *
4  * This file is part of Freeciv21.
5  *
6  * Freeciv21 is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Freeciv21 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Freeciv21. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "server.h"
21 #include "unittools.h"
22 
23 // Qt
24 #include <QCoreApplication>
25 #include <QDir>
26 #include <QFile>
27 #include <QHostInfo>
28 #include <QLocalSocket>
29 #include <QTcpSocket>
30 #include <QTimer>
31 
32 // Stuff to wait for input on stdin.
33 #ifdef Q_OS_WIN
34 #include <QMutexLocker>
35 #include <io.h>
36 #else
37 #include <QtCore/QSocketNotifier>
38 #include <unistd.h>
39 #endif
40 #include <cstdio>
41 
42 // Readline
43 #include <readline/history.h>
44 #include <readline/readline.h>
45 
46 // utility
47 #include "fciconv.h" // local_to_internal_string_malloc
48 #include "rand.h"
49 
50 // common
51 #include "fc_interface.h"
52 
53 // server
54 #include "ai.h"
55 #include "aiiface.h"
56 #include "auth.h"
57 #include "connecthand.h"
58 #include "console.h"
59 #include "diplhand.h"
60 #include "edithand.h"
61 #include "fcdb.h"
62 #include "maphand.h"
63 #include "mapimg.h"
64 #include "meta.h"
65 #include "notify.h"
66 #include "ruleset.h"
67 #include "sanitycheck.h"
68 #include "savemain.h"
69 #include "score.h"
70 #include "script_server.h" // scripting
71 #include "sernet.h"
72 #include "settings.h"
73 #include "srv_main.h"
74 #include "stdinhand.h"
75 #include "timing.h"
76 #include "voting.h"
77 
78 using namespace freeciv;
79 
80 static const char *HISTORY_FILENAME = "freeciv-server_history";
81 static const int HISTORY_LENGTH = 100;
82 
83 namespace {
84 #ifndef Q_OS_WIN
88 void handle_readline_input_callback(char *line)
89 {
90  if (line == nullptr) {
91  return;
92  }
93 
94  if (line[0] != '\0') {
95  add_history(line);
96  }
97 
98  con_prompt_enter(); // just got an 'Enter' hit
99  auto *line_internal = local_to_internal_string_malloc(line);
100  (void) handle_stdin_input(nullptr, line_internal);
101  delete[] line_internal;
102  free(line);
103 }
104 #endif // !Q_OS_WIN
105 
109 void fc_interface_init_server()
110 {
111  struct functions *funcs = fc_interface_funcs();
112 
119  funcs->create_extra = create_extra;
120  funcs->destroy_extra = destroy_extra;
123 
124  // Keep this function call at the end. It checks if all required functions
125  // are defined.
127 }
128 
132 std::optional<socket_server> srv_prepare()
133 {
134  // make sure it's initialized
135  srv_init();
136 
137  // must be before con_log_init()
140  // logging available after this point
141 
142  auto server = server_open_socket();
143  if (!server) {
144  return std::nullopt;
145  }
146 
147  con_flush();
148 
149  settings_init(true);
150  stdinhand_init();
151  edithand_init();
152  voting_init();
153  diplhand_init();
154  voting_init();
155  ai_timer_init();
156 
157  server_game_init(false);
162 
163  if (srvarg.fcdb_enabled) {
164  bool success;
165 
166  success = fcdb_init(qUtf8Printable(srvarg.fcdb_conf));
167  if (!success) {
168  return std::nullopt;
169  }
170  }
171 
172  if (srvarg.ruleset != nullptr) {
173  QString testfilename;
174 
175  testfilename =
176  fileinfoname(get_data_dirs(), qUtf8Printable(srvarg.ruleset));
177  if (testfilename.isEmpty()) {
178  qFatal(_("Ruleset directory \"%s\" not found"),
179  qUtf8Printable(srvarg.ruleset));
180  return std::nullopt;
181  }
182  sz_strlcpy(game.server.rulesetdir, qUtf8Printable(srvarg.ruleset));
183  }
184 
185  // load a saved game
186  if (srvarg.load_filename.isEmpty()
187  || !load_command(nullptr, qUtf8Printable(srvarg.load_filename), false,
188  true)) {
189  /* Rulesets are loaded on game initialization, but may be changed later
190  * if /load or /rulesetdir is done. */
191  load_rulesets(nullptr, nullptr, false, nullptr, true, false, true);
192  }
193 
195 
196  if (!(srvarg.metaserver_no_send)) {
197  qInfo(_("Sending info to metaserver <%s>."),
198  qUtf8Printable(meta_addr_port()));
199  // Open socket for meta server
202  con_write(C_FAIL, _("Not starting without explicitly requested "
203  "metaserver connection."));
204  return std::nullopt;
205  }
206  }
207 
208  return server;
209 }
210 
211 } // anonymous namespace
212 
213 #ifdef Q_OS_WIN
217 detail::async_readline_wrapper::async_readline_wrapper(bool interactive,
218  QObject *parent)
219  : QThread(parent), m_interactive(interactive), m_stop{}
220 {
221 }
222 
226 void detail::async_readline_wrapper::stop() { m_stop = true; }
227 
232 void detail::async_readline_wrapper::wait_for_input()
233 {
234  // Loop until we get a non-trivial line
235  QString line;
236  while (line.isEmpty()) {
237  if (m_stop) {
238  return;
239  }
240 
241  if (m_interactive) {
242  char *buffer = readline("> ");
243  if (buffer == nullptr) {
244  break;
245  }
246 
247  if (buffer && buffer[0] != '\0') {
248  add_history(buffer);
249  }
250 
251  line = QString::fromLocal8Bit(buffer);
252  } else {
253  QFile f;
254  f.open(stdin, QIODevice::ReadOnly);
255  line = QString::fromLocal8Bit(f.readLine());
256  }
257  }
258 
259  emit line_available(line);
260 }
261 
263 QRecursiveMutex server::s_stdin_mutex = QRecursiveMutex();
264 #endif // Q_OS_WIN
265 
270 {
271 #ifdef Q_OS_WIN
272  QMutexLocker lock(&s_stdin_mutex);
273 #endif
274 
275  // Are we running an interactive session?
276 #ifdef Q_OS_WIN
277  // isatty and fileno are deprecated on Windows
278  m_interactive = _isatty(_fileno(stdin));
279 #else
280  m_interactive = isatty(fileno(stdin));
281 #endif
282 
283  // Get notifications when there's some input on stdin. This is OS-dependent
284  // and Qt doesn't have a wrapper. Maybe it should be split to a separate
285  // class.
286 #ifdef Q_OS_WIN
287  {
288  // Spawn a thread from where we can afford to do blocking calls
289  auto wrapper = new detail::async_readline_wrapper(m_interactive);
290  wrapper->moveToThread(wrapper);
291  connect(wrapper, &detail::async_readline_wrapper::line_available, this,
293  connect(this, &server::input_requested, wrapper,
294  &detail::async_readline_wrapper::wait_for_input);
295  wrapper->start();
296  m_stdin_notifier = wrapper;
297  }
298 #else
299  {
300  // Unix-like
301  auto *notifier =
302  new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this);
303  connect(notifier, &QSocketNotifier::activated, this,
305  m_stdin_notifier = notifier;
306  }
307 #endif
308 
309  // Now init the old C API
310  fc_interface_init_server();
311  auto server = srv_prepare();
312  if (!server) {
313  // Could not listen on the specified port. Rely on the caller checking
314  // our state and not starting the event loop.
315  return;
316  }
317  m_server = std::move(*server);
318  if (std::holds_alternative<std::unique_ptr<QTcpServer>>(m_server)) {
319  auto &tcp = std::get<std::unique_ptr<QTcpServer>>(m_server);
320  connect(tcp.get(), &QTcpServer::newConnection, this,
322  connect(tcp.get(), &QTcpServer::acceptError,
323  [](QAbstractSocket::SocketError error) {
324  qCritical("Error accepting connection: %d", error);
325  });
326  } else if (std::holds_alternative<std::unique_ptr<QLocalServer>>(
327  m_server)) {
328  auto &local = std::get<std::unique_ptr<QLocalServer>>(m_server);
329  connect(local.get(), &QLocalServer::newConnection, this,
331  }
332 
334 
335  // Prepare a game
336  if (!prepare_game()) {
337  // Unable to start the game. Rely on the caller checking our state and
338  // not starting the event loop.
339  return;
340  }
341  con_prompt_init();
342  if (m_interactive) {
344  }
345  // Start pulsing
346  m_pulse_timer = new QTimer(this);
347  m_pulse_timer->start(1000);
348  connect(m_pulse_timer, &QTimer::timeout, this, &server::pulse);
349 
350  m_ready = true;
351 
352 #ifdef Q_OS_WIN
353  // Ask the stdin worker thread to start looking at imput.
354  emit input_requested();
355 #endif // Q_OS_WIN
356 }
357 
362 {
363 #ifdef Q_OS_WIN
364  QMutexLocker lock(&s_stdin_mutex);
365 #endif
366 
367 #ifdef Q_OS_WIN
368  {
369  auto notifier =
370  qobject_cast<detail::async_readline_wrapper *>(m_stdin_notifier);
371  if (notifier) {
372  notifier->stop();
373  notifier->quit();
374  notifier->wait();
375  delete notifier;
376  m_stdin_notifier = nullptr;
377  }
378  }
379 #endif // Q_OS_WIN
380 
381  if (m_interactive) {
382  // Save history
383  auto history_file = freeciv_storage_dir() + QStringLiteral("/")
384  + QLatin1String(HISTORY_FILENAME);
385  auto history_file_encoded = history_file.toLocal8Bit();
386  write_history(history_file_encoded.constData());
387  history_truncate_file(history_file_encoded.constData(), HISTORY_LENGTH);
388  clear_history();
389 
390  // Power down readline
391  rl_callback_handler_remove();
392  }
393 
394  if (m_eot_timer != nullptr) {
396  }
397  if (m_between_turns_timer != nullptr) {
399  }
400  server_quit();
401 }
402 
407 {
408  // Read the history file
409  auto storage_dir = freeciv_storage_dir();
410  if (QDir().mkpath(storage_dir)) {
411  auto history_file =
412  storage_dir + QStringLiteral("/") + QLatin1String(HISTORY_FILENAME);
413  using_history();
414  read_history(history_file.toLocal8Bit().constData());
415  }
416 
417  // Initialize readline
418  rl_initialize();
419 #ifdef Q_OS_WIN
420  rl_attempted_completion_function = synchronized_completion;
421 #else
422  rl_callback_handler_install((char *) "> ", handle_readline_input_callback);
423  rl_attempted_completion_function = freeciv_completion;
424 #endif
425 }
426 
431 bool server::is_ready() const { return m_ready; }
432 
438 {
439  // We know it's safe: this method is only called for local connections
440  auto &server = std::get<std::unique_ptr<QLocalServer>>(m_server);
441 
442  // There may be several connections available.
443  while (server->hasPendingConnections()) {
444  auto *socket = server->nextPendingConnection();
445  socket->setParent(this);
446 
447  if (server_make_connection(socket, QStringLiteral("local"),
448  QStringLiteral("local"))
449  == 0) {
450  // Success making the connection, connect signals
451  connect(socket, &QIODevice::readyRead, this, &server::input_on_socket);
452  connect(socket, &QLocalSocket::errorOccurred, this,
454 
455  // Prevents quitidle from firing immediately
457 
458  // Turn off the quitidle timeout if it's running
459  if (m_quitidle_timer != nullptr) {
460  m_quitidle_timer->stop();
461  m_quitidle_timer->deleteLater();
462  m_quitidle_timer = nullptr;
463  }
464  } else {
465  socket->deleteLater();
466  }
467  }
468 }
469 
475 {
476 #ifdef Q_OS_WIN
477  QMutexLocker lock(&s_stdin_mutex);
478 #endif
479 
480  // We know it's safe: this method is only called for TCP connections
481  auto &server = std::get<std::unique_ptr<QTcpServer>>(m_server);
482 
483  // There may be several connections available.
484  while (server->hasPendingConnections()) {
485  auto *socket = server->nextPendingConnection();
486  socket->setParent(this);
487 
488  // Lookup the host name of the remote end.
489  // The IP address will always work
490  auto remote = socket->peerAddress().toString();
491  // Try a remote DNS lookup
492  auto host_info = QHostInfo::fromName(remote); // FIXME Blocking call
493  if (host_info.error() == QHostInfo::NoError) {
494  remote = host_info.hostName();
495  }
496 
497  // Reject the connection if we have reached the hard-coded limit
498  if (conn_list_size(game.all_connections) >= MAX_NUM_CONNECTIONS) {
499  qDebug("Rejecting new connection from %s: maximum number of "
500  "connections exceeded (%d).",
501  qUtf8Printable(remote), MAX_NUM_CONNECTIONS);
502  socket->deleteLater();
503  continue;
504  }
505 
506  // Reject the connection if we have reached the limit for this host
507  if (0 != game.server.maxconnectionsperhost) {
508  bool success = true;
509  int count = 0;
510 
512  {
513  // Use TolerantConversion so one connections from the same address on
514  // IPv4 and IPv6 are rejected as well.
515  if (const auto *other = qobject_cast<QTcpSocket *>(pconn->sock);
516  socket->peerAddress().isEqual(
517  other->peerAddress(), QHostAddress::TolerantConversion)) {
518  continue;
519  }
520  if (++count >= game.server.maxconnectionsperhost) {
521  qWarning("Rejecting new connection from %s: maximum number of "
522  "connections for this address exceeded (%d).",
523  qUtf8Printable(remote),
524  game.server.maxconnectionsperhost);
525 
526  success = false;
527  socket->deleteLater();
528  }
529  }
531 
532  if (!success) {
533  socket->deleteLater();
534  continue;
535  }
536  }
537 
538  if (server_make_connection(socket, remote,
539  socket->peerAddress().toString())
540  == 0) {
541  // Success making the connection, connect signals
542  connect(socket, &QIODevice::readyRead, this, &server::input_on_socket);
543  connect(socket, &QAbstractSocket::errorOccurred, this,
545 
546  // Prevents quitidle from firing immediately
548 
549  // Turn off the quitidle timeout if it's running
550  if (m_quitidle_timer != nullptr) {
551  m_quitidle_timer->stop();
552  m_quitidle_timer->deleteLater();
553  m_quitidle_timer = nullptr;
554  }
555  }
556  }
557 }
558 
563 {
564 #ifdef Q_OS_WIN
565  QMutexLocker lock(&s_stdin_mutex);
566 #endif
567 
568  // Pinging around for statistics
569  if (time(nullptr) > (game.server.last_ping + game.server.pingtime)) {
571  {
572  if ((!pconn->server.is_closing && 0 < pconn->server.ping_timers->size()
573  && timer_read_seconds(pconn->server.ping_timers->front())
574  > game.server.pingtimeout)
575  || pconn->ping_time > game.server.pingtimeout) {
576  // cut mute players, except for hack-level ones
577  if (pconn->access_level == ALLOW_HACK) {
578  qDebug("connection (%s) [hack-level] ping timeout ignored",
579  conn_description(pconn));
580  } else {
581  qDebug("connection (%s) cut due to ping timeout",
582  conn_description(pconn));
583  connection_close_server(pconn, _("ping timeout"));
584  }
585  } else if (pconn->established) {
586  // We don't send ping to connection not established, because we
587  // wouldn't be able to handle asynchronous ping/pong with different
588  // packet header size.
589  connection_ping(pconn);
590  }
591  }
593  game.server.last_ping = time(nullptr);
594  }
595 }
596 
601 {
602 #ifdef Q_OS_WIN
603  QMutexLocker lock(&s_stdin_mutex);
604 #endif
605 
606  // Get the socket
607  auto *socket = dynamic_cast<QTcpSocket *>(sender());
608  if (socket == nullptr) {
609  return;
610  }
611 
612  // Find the corresponding connection
614  {
615  if (pconn->sock == socket) {
616  connection_close_server(pconn, socket->errorString());
617  break;
618  }
619  }
621 
624 }
625 
630 {
631 #ifdef Q_OS_WIN
632  QMutexLocker lock(&s_stdin_mutex);
633 #endif
634 
635  // Get the socket
636  auto *socket = dynamic_cast<QIODevice *>(sender());
637  if (socket == nullptr) {
638  return;
639  }
640 
641  // Find the corresponding connection
643  {
644  if (pconn->sock == socket && !pconn->server.is_closing) {
645  auto nb = read_socket_data(pconn->sock, pconn->buffer);
646  if (0 <= nb) {
647  // We read packets; now handle them.
649  } else if (-2 == nb) {
650  connection_close_server(pconn, _("client disconnected"));
651  } else {
652  // Read failure; the connection is closed.
653  connection_close_server(pconn, _("read error"));
654  }
655  break;
656  }
657  }
659 
662 }
663 
664 #ifdef Q_OS_WIN
665 
669 void server::input_on_stdin(const QString &line)
670 {
671  QMutexLocker lock(&s_stdin_mutex);
672 
673  auto buffer = line.toUtf8();
674  handle_stdin_input(nullptr, buffer.data());
675  if (should_quit()) {
676  // Stop the worker thread
677  auto notifier =
678  qobject_cast<detail::async_readline_wrapper *>(m_stdin_notifier);
679  if (notifier) {
680  notifier->quit();
681  }
682  } else {
683  // Ask the notifier to block until it reads the next line
684  emit input_requested();
685  }
686 
688 }
689 
693 char **server::synchronized_completion(const char *text, int start, int end)
694 {
695  QMutexLocker lock(&s_stdin_mutex);
696  return freeciv_completion(text, start, end);
697 }
698 
699 #else // !Q_OS_WIN
700 
705 {
706  if (m_interactive) {
707  // Readline does everything nicely in interactive sessions
708  rl_callback_read_char();
709  } else {
710  QFile f;
711  f.open(stdin, QIODevice::ReadOnly);
712  // Force it to try and read something
713  f.peek(1);
714  // Read from the input
715  if (f.atEnd() && m_stdin_notifier != nullptr) {
716  // QSocketNotifier gets mad after EOF. Turn it off.
717  m_stdin_notifier->deleteLater();
718  m_stdin_notifier = nullptr;
719  qInfo(_("Reached end of standard input."));
720  } else if (f.canReadLine()) {
721  // Got something to read. Hopefully there's even a complete line and
722  // we can process it.
723  auto line = f.readLine();
724  auto *non_const_line =
725  local_to_internal_string_malloc(line.constData());
726  (void) handle_stdin_input(nullptr, non_const_line);
727  free(non_const_line);
728  }
729  }
730 
732 }
733 
734 #endif
735 
740 {
741 #ifdef Q_OS_WIN
742  QMutexLocker lock(&s_stdin_mutex);
743 #endif
744 
745  set_server_state(S_S_INITIAL);
746 
747  // Load a script file.
748  if (!srvarg.script_filename.isEmpty()) {
749  // Adding an error message more here will duplicate them.
750  auto ok = read_init_script(NULL, qUtf8Printable(srvarg.script_filename),
751  true, false);
752  if (!ok) {
753  return false;
754  }
755  }
756 
757  (void) aifill(game.info.aifill);
758  if (!game_was_started()) {
760  }
761 
762  qInfo(_("Now accepting new client connections on port %d."), srvarg.port);
763 
764  if (game.info.timeout == -1) {
765  // Autogame, start as soon as the event loop allows
766  QTimer::singleShot(0, this, &server::update_game_state);
767  }
768 
769  return true;
770 }
771 
776 {
777 #ifdef Q_OS_WIN
778  QMutexLocker lock(&s_stdin_mutex);
779 #endif
780 
782 
783  // Start the first phase
784  begin_phase();
785 }
786 
791 {
792 #ifdef Q_OS_WIN
793  QMutexLocker lock(&s_stdin_mutex);
794 #endif
795 
796  log_debug("Starting phase %d/%d.", game.info.phase,
797  game.server.num_phases);
800  // When loading a savegame, we need to send loaded events, after
801  // the clients switched to the game page (after the first
802  // packet_start_phase is received).
804  {
805  send_pending_events(pconn, true);
806  }
809  }
810 
811  m_is_new_turn = true;
812 
813  // This will thaw the reports and agents at the client.
814  lsend_packet_thaw_client(game.est_connections);
815 
816  log_time(QStringLiteral("End/start-turn server/ai activities: %1 seconds")
818 
819  // Do auto-saves just before starting server_sniff_all_input(), so that
820  // autosave happens effectively "at the same time" as manual
821  // saves, from the point of view of restarting and AI players.
822  // Post-increment so we don't count the first loop.
823  if (game.info.phase == 0) {
824  // Create autosaves if requested.
825  if (m_save_counter >= game.server.save_nturns
826  && game.server.save_nturns > 0) {
827  m_save_counter = 0;
828  save_game_auto("Autosave", AS_TURN);
829  }
830  m_save_counter++;
831 
832  if (!m_skip_mapimg) {
833  // Save map image(s).
834  for (int i = 0; i < mapimg_count(); i++) {
835  struct mapdef *pmapdef = mapimg_isvalid(i);
836  if (pmapdef != nullptr) {
837  mapimg_create(pmapdef, false, game.server.save_name,
838  qUtf8Printable(srvarg.saves_pathname));
839  } else {
840  qCritical("%s", mapimg_error());
841  }
842  }
843  } else {
844  m_skip_mapimg = false;
845  }
846  }
847 
848  log_debug("sniffingpackets");
849  if (game.info.timeout >= 0) {
850  check_for_full_turn_done(); // HACK: don't wait during AI phases
851  } else {
852  force_end_of_sniff = true;
853  }
854 
855  if (m_between_turns_timer != nullptr) {
857  log_debug("Inresponsive between turns %g seconds",
858  game.server.turn_change_time);
859  }
860 
861  QTimer::singleShot(0, this, &server::update_game_state);
862 }
863 
868 {
869 #ifdef Q_OS_WIN
870  QMutexLocker lock(&s_stdin_mutex);
871 #endif
872 
876 
877  // After sniff, re-zero the timer: (read-out above on next loop)
880 
882 
883  sanity_check();
884 
885  // This will freeze the reports and agents at the client.
886  lsend_packet_freeze_client(game.est_connections);
887 
888  ::end_phase();
889 
891 
892  if (S_S_OVER == server_state()) {
893  end_turn();
894  return;
895  }
896  game.server.additional_phase_seconds = 0;
897 
898  game.info.phase++;
899  if (server_state() == S_S_RUNNING
900  && game.info.phase < game.server.num_phases) {
901  begin_phase();
902  } else {
903  end_turn();
904  }
905 }
906 
911 {
912 #ifdef Q_OS_WIN
913  QMutexLocker lock(&s_stdin_mutex);
914 #endif
915 
916  ::end_turn();
917  log_debug("Sendinfotometaserver");
919 
920  if (S_S_OVER != server_state() && check_for_game_over()) {
921  set_server_state(S_S_OVER);
922  if (game.info.turn > game.server.end_turn) {
923  // endturn was reached - rank users based on team scores
924  rank_users(true);
925  } else {
926  // game ended for victory conditions - rank users based on survival
927  rank_users(false);
928  }
929  } else if (S_S_OVER == server_state()) {
930  // game terminated by /endgame command - calculate team scores
931  rank_users(true);
932  }
933 
934  if (server_state() == S_S_RUNNING) {
935  // Still running, start the next turn!
936  begin_turn();
937  } else {
938  // Game over
939  // This will thaw the reports and agents at the client.
940  lsend_packet_thaw_client(game.est_connections);
941 
942  if (game.server.save_timer != nullptr) {
943  timer_destroy(game.server.save_timer);
944  game.server.save_timer = nullptr;
945  }
946  if (m_between_turns_timer != nullptr) {
948  m_between_turns_timer = nullptr;
949  }
951 
952  srv_scores();
953 
954  if (game.info.timeout == -1) {
955  // Autogame, end game immediately if nobody is connected
957  }
958  }
959 }
960 
965 {
966 #ifdef Q_OS_WIN
967  QMutexLocker lock(&s_stdin_mutex);
968 #endif
969 
970  // Set in the following cases:
971  // - in pregame: game start
972  // - during the game: turn done, end game and any other command affecting
973  // game speed
974  // It basically says: I got a command that requires to get out of the usual
975  // "wait for clients to send stuff" mode.
976  if (force_end_of_sniff) {
977  force_end_of_sniff = false;
978 
979  if (server_state() < S_S_RUNNING) {
980  // Pregame: start the game
981  // If restarting for lack of players, the state is S_S_OVER,
982  // so don't try to start the game.
983  srv_ready(); // srv_ready() sets server state to S_S_RUNNING.
984 
986 
987  // This will freeze the reports and agents at the client.
988  //
989  // Do this before the starting the turn so that the PACKET_THAW_CLIENT
990  // packet in begin_turn is balanced.
991  lsend_packet_freeze_client(game.est_connections);
992 
993  // Start the first turn
994  m_need_send_pending_events = !game.info.is_new_game;
995  m_is_new_turn = game.info.is_new_game;
996  m_save_counter = game.info.is_new_game ? 1 : 0;
997  m_skip_mapimg = !game.info.is_new_game;
998 
999  // We may as well reset is_new_game now.
1000  game.info.is_new_game = false;
1001 
1002  begin_turn();
1003  } else {
1004  end_phase(); // Will end game if needed
1005  }
1006  }
1007 
1008  // Game over and all clients disconnected; restart if needed
1009  if (server_state() == S_S_OVER
1010  && conn_list_size(game.est_connections) == 0) {
1011  if (shut_game_down()) {
1012  prepare_game();
1013  }
1014  }
1015 
1016  // Set up the quitidle timer if not done already
1017  if (m_someone_ever_connected && m_quitidle_timer == nullptr
1018  && srvarg.quitidle != 0 && conn_list_size(game.all_connections) == 0) {
1019  if (srvarg.exit_on_end) {
1020  qInfo(_("Shutting down in %d seconds for lack of players."),
1021  srvarg.quitidle);
1022 
1023  set_meta_message_string(N_("shutting down soon for lack of players"));
1024  } else {
1025  qInfo(_("Restarting in %d seconds for lack of players."),
1026  srvarg.quitidle);
1027 
1028  set_meta_message_string(N_("restarting soon for lack of players"));
1029  }
1031 
1032  m_quitidle_timer = new QTimer(this);
1033  m_quitidle_timer->setSingleShot(true);
1034  m_quitidle_timer->start(1000 * srvarg.quitidle);
1035  connect(m_quitidle_timer, &QTimer::timeout, this, &server::quit_idle);
1036  }
1037 }
1038 
1044 {
1045 #ifdef Q_OS_WIN
1046  QMutexLocker lock(&s_stdin_mutex);
1047 #endif
1048 
1049  // Close it even between games.
1051 
1052  if (game.info.timeout == -1 || srvarg.exit_on_end) {
1053  // For autogames or if the -e option is specified, exit the server.
1054  deleteLater();
1055  return false;
1056  }
1057 
1058  // Reset server
1059  server_game_free();
1060  fc_rand_set_init(false);
1061  server_game_init(false);
1062  mapimg_reset();
1063  load_rulesets(nullptr, nullptr, false, nullptr, true, false, true);
1064  game.info.is_new_game = true;
1065  return true;
1066 }
1067 
1073 {
1074 #ifdef Q_OS_WIN
1075  QMutexLocker lock(&s_stdin_mutex);
1076 #endif
1077 
1078  m_quitidle_timer = nullptr;
1079 
1080  if (conn_list_size(game.est_connections) > 0) {
1081  qDebug("Quitidle timer fired but someone is connected; not quitting");
1082  return;
1083  }
1084 
1085  if (srvarg.exit_on_end) {
1086  qInfo(_("Shutting down for lack of players."));
1087  set_meta_message_string("shutting down for lack of players");
1088  } else {
1089  qInfo(_("Restarting for lack of players."));
1090  set_meta_message_string("restarting for lack of players");
1091  }
1092 
1094 
1095  set_server_state(S_S_OVER);
1096 
1097  if (srvarg.exit_on_end) {
1098  // No need for anything more; just quit.
1099  deleteLater();
1100  } else {
1101  force_end_of_sniff = true;
1103  }
1104 }
1105 
1110 {
1111 #ifdef Q_OS_WIN
1112  QMutexLocker lock(&s_stdin_mutex);
1113 #endif
1114 
1115  send_pings();
1116 
1118 
1119  // if we've waited long enough after a failure, respond to the client
1121  {
1122  if (srvarg.auth_enabled && !pconn->server.is_closing
1123  && pconn->server.status != AS_ESTABLISHED) {
1124  auth_process_status(pconn);
1125  }
1126  }
1128 
1130 
1131  call_ai_refresh();
1132  script_server_signal_emit("pulse");
1134  if (current_turn_timeout() > 0 && S_S_RUNNING == server_state()
1135  && game.server.phase_timer
1136  && (timer_read_seconds(game.server.phase_timer)
1137  + game.server.additional_phase_seconds
1138  > game.tinfo.seconds_to_phasedone)) {
1139  con_prompt_off();
1140  // This will be interpreted as "end phase"
1141  force_end_of_sniff = true;
1143  }
1144  if ((game.server.autosaves & (1 << AS_TIMER))
1145  && S_S_RUNNING == server_state()
1146  && (timer_read_seconds(game.server.save_timer)
1147  >= game.server.save_frequency * 60)) {
1148  save_game_auto("Timer", AS_TIMER);
1149  game.server.save_timer =
1151  timer_start(game.server.save_timer);
1152  }
1153 }
#define ai_timer_init(...)
Definition: ai.h:361
void call_ai_refresh()
Call ai refresh() callback for all players.
Definition: aiiface.cpp:256
void auth_process_status(struct connection *pconn)
Checks on where in the authentication process we are.
Definition: auth.cpp:197
A Freeciv21 server.
Definition: server.h:68
~server() override
Shut down a server.
Definition: server.cpp:361
bool m_skip_mapimg
Definition: server.h:129
socket_server m_server
Definition: server.h:124
void accept_local_connections()
Server accepts connections over local socket: Low level socket stuff, and basic-initialize the connec...
Definition: server.cpp:437
void init_interactive()
Initializes interactive handling of stdin with libreadline.
Definition: server.cpp:406
void begin_phase()
Do everything needed to start a new phase on top of calling begin_phase.
Definition: server.cpp:790
bool prepare_game()
Prepares for a new game.
Definition: server.cpp:739
civtimer * m_between_turns_timer
Definition: server.h:126
void pulse()
Called every second.
Definition: server.cpp:1109
void error_on_socket()
Called when there was an error on a socket.
Definition: server.cpp:600
void end_turn()
Do everything needed to end a turn on top of calling end_turn.
Definition: server.cpp:910
int m_save_counter
Definition: server.h:130
QObject * m_stdin_notifier
Definition: server.h:122
void input_on_socket()
Called when there's something to read on a socket.
Definition: server.cpp:629
bool m_interactive
Definition: server.h:121
QTimer * m_pulse_timer
Definition: server.h:135
bool shut_game_down()
Shuts a game down when all players have left.
Definition: server.cpp:1043
bool m_need_send_pending_events
Definition: server.h:128
bool m_ready
Definition: server.h:119
civtimer * m_eot_timer
Definition: server.h:126
void input_on_stdin()
Called when there's something to read on stdin.
Definition: server.cpp:704
bool m_someone_ever_connected
Definition: server.h:132
bool m_is_new_turn
Definition: server.h:128
void quit_idle()
Quit because we're idle (ie no one was connected in the last srvarg.quitidle seconds).
Definition: server.cpp:1072
void update_game_state()
Checks if the game state has changed and take action if appropriate.
Definition: server.cpp:964
void end_phase()
Do everything needed to end a phase on top of calling end_phase.
Definition: server.cpp:867
void send_pings()
Sends pings to clients if needed.
Definition: server.cpp:562
void accept_tcp_connections()
Server accepts connections from client: Low level socket stuff, and basic-initialize the connection s...
Definition: server.cpp:474
void begin_turn()
Do everything needed to start a new turn on top of calling begin_turn.
Definition: server.cpp:775
bool is_ready() const
Checks if the server is ready for the event loop to start.
Definition: server.cpp:431
QTimer * m_quitidle_timer
Definition: server.h:133
void connection_close_server(struct connection *pconn, const QString &reason)
Close a connection.
void conn_list_do_unbuffer(struct conn_list *dest)
Convenience functions to unbuffer a list of connections.
Definition: connection.cpp:319
int read_socket_data(QIODevice *sock, struct socket_packet_buffer *buffer)
Read data from socket, and check if a packet is ready.
Definition: connection.cpp:110
const char * conn_description(const struct connection *pconn, bool is_private)
° Return pointer to static string containing a description for this ° connection, based on pconn->nam...
Definition: connection.cpp:431
void conn_list_do_buffer(struct conn_list *dest)
Convenience functions to buffer a list of connections.
Definition: connection.cpp:310
@ AS_ESTABLISHED
Definition: connection.h:88
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
void con_log_init(const QString &log_filename)
Initialize logging via console.
Definition: console.cpp:111
void con_prompt_off()
Do not print a prompt after log messages.
Definition: console.cpp:220
void con_flush()
Ensure timely update.
Definition: console.cpp:183
void con_prompt_init()
Initialize prompt; display initial message.
Definition: console.cpp:206
void con_write(enum rfc_status rfc_status, const char *message,...)
Write to console and add line-break, and show prompt if required.
Definition: console.cpp:139
void con_prompt_enter()
User pressed enter: will need a new prompt.
Definition: console.cpp:225
@ C_FAIL
Definition: console.h:43
void diplhand_init()
Initialize diplhand module.
Definition: diplhand.cpp:73
void edithand_init()
Initialize data structures required for edit mode.
Definition: edithand.cpp:72
struct functions * fc_interface_funcs()
Return the function pointer.
void fc_interface_init()
Test and initialize the functions.
#define MAX_NUM_CONNECTIONS
Definition: fc_types.h:30
bool fcdb_init(const char *conf_file)
Initialize freeciv database system.
Definition: fcdb.cpp:117
char * local_to_internal_string_malloc(const char *text)
Definition: fciconv.cpp:113
#define _(String)
Definition: fcintl.h:50
#define N_(String)
Definition: fcintl.h:52
struct civ_game game
Definition: game.cpp:47
int current_turn_timeout()
Return timeout value for the current turn.
Definition: game.cpp:808
@ AS_TIMER
Definition: game.h:59
@ AS_TURN
Definition: game.h:55
void log_time(const QString &msg, bool log)
Definition: log.cpp:253
#define log_debug(message,...)
Definition: log.h:65
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Remove extra from tile.
Definition: maphand.cpp:2478
void create_extra(struct tile *ptile, const extra_type *pextra, struct player *pplayer)
Create extra to tile.
Definition: maphand.cpp:2405
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Returns whether the layer 'vlayer' of the tile 'ptile' is known and seen by the player 'pplayer'.
Definition: maphand.cpp:894
void mapimg_reset()
Reset the map image subsystem.
Definition: mapimg.cpp:386
int mapimg_count()
Return the number of map image definitions.
Definition: mapimg.cpp:420
const char * mapimg_error()
Returns the last error.
Definition: mapimg.cpp:585
struct mapdef * mapimg_isvalid(int id)
Check if a map image definition is valid.
Definition: mapimg.cpp:886
void mapimg_init(mapimg_tile_known_func mapimg_tile_known, mapimg_tile_terrain_func mapimg_tile_terrain, mapimg_tile_player_func mapimg_tile_owner, mapimg_tile_player_func mapimg_tile_city, mapimg_tile_player_func mapimg_tile_unit, mapimg_plrcolor_count_func mapimg_plrcolor_count, mapimg_plrcolor_get_func mapimg_plrcolor_get)
Initialisation of the map image subsystem.
Definition: mapimg.cpp:351
bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename, const char *path)
Create the requested map image.
Definition: mapimg.cpp:1050
void maybe_automatic_meta_message(const char *automatic)
Update meta message.
Definition: meta.cpp:112
const char * default_meta_message_string()
Return static string with default info line to send to metaserver.
Definition: meta.cpp:63
void set_meta_message_string(const char *string)
Set the metaserver message string.
Definition: meta.cpp:140
QString meta_addr_port()
Return string describing both metaserver name and port.
Definition: meta.cpp:163
bool send_server_info_to_metaserver(enum meta_flag flag)
Control when we send info to the metaserver.
Definition: meta.cpp:469
bool server_open_meta(bool persistent)
Lookup the correct address for the metaserver.
Definition: meta.cpp:445
@ META_INFO
Definition: meta.h:25
@ META_REFRESH
Definition: meta.h:25
Definition: path.cpp:10
void event_cache_clear()
Remove all events from the cache.
Definition: notify.cpp:586
void send_pending_events(struct connection *pconn, bool include_public)
Send all available events.
Definition: notify.cpp:742
void fc_rand_set_init(bool init)
Sets whether the current state has been initialized.
Definition: rand.cpp:83
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Loads the rulesets.
Definition: ruleset.cpp:8582
#define sanity_check()
Definition: sanitycheck.h:37
void save_system_close()
Close saving system.
Definition: savemain.cpp:286
void rank_users(bool interrupt)
At the end of a game, figure the winners and losers of the game and output to a suitable place.
Definition: score.cpp:440
void script_server_signal_emit(const char *signal_name,...)
Invoke all the callback functions attached to a given signal.
void connection_ping(struct connection *pconn)
Ping a connection.
Definition: sernet.cpp:527
void init_connections()
Initialize connection related stuff.
Definition: sernet.cpp:452
void get_lanserver_announcement()
Listen for UDP packets multicasted from clients requesting announcement of servers on the LAN.
Definition: sernet.cpp:572
void incoming_client_packets(struct connection *pconn)
Handle all incoming packets on a client connection.
Definition: sernet.cpp:229
void really_close_connections()
Now really close connections marked as 'is_closing'.
Definition: sernet.cpp:140
int server_make_connection(QIODevice *new_sock, const QString &client_addr, const QString &ip_addr)
Server accepts connection from client: Low level socket stuff, and basic-initialize the connection st...
Definition: sernet.cpp:310
std::optional< socket_server > server_open_socket()
Open server socket to be used to accept client connections and open a server socket for server LAN an...
Definition: sernet.cpp:370
void finish_unit_waits()
Process all unit waits that are expired.
Definition: sernet.cpp:503
static const int HISTORY_LENGTH
Definition: server.cpp:81
static const char * HISTORY_FILENAME
Definition: server.cpp:80
void settings_init(bool act)
Initialize stuff related to this code module.
Definition: settings.cpp:4761
const QStringList & get_data_dirs()
Returns a list of data directory paths, in the order in which they should be searched.
Definition: shared.cpp:533
QString fileinfoname(const QStringList &dirs, const QString &filename)
Returns a filename to access the specified file from a directory by searching all specified directori...
Definition: shared.cpp:661
QString freeciv_storage_dir()
Returns string which gives freeciv storage dir.
Definition: shared.cpp:419
void server_game_init(bool keep_ruleset_value)
Initialize game data for the server (corresponds to server_game_free).
Definition: srv_main.cpp:3179
void srv_scores()
Score calculation.
Definition: srv_main.cpp:2834
void srv_ready()
Set up one game.
Definition: srv_main.cpp:2888
const char * aifill(int amount)
Fill or remove players to meet the given aifill.
Definition: srv_main.cpp:2440
void check_for_full_turn_done()
Check if turn is really done.
Definition: srv_main.cpp:2179
int mapimg_server_plrcolor_count()
Helper function for the mapimg module - number of player colors.
Definition: srv_main.cpp:3446
int server_plr_tile_city_id_get(const struct tile *ptile, const struct player *pplayer)
Returns the id of the city the player map of 'pplayer' has at 'ptile' or IDENTITY_NUMBER_ZERO if the ...
Definition: srv_main.cpp:3254
void server_game_free()
Free game data that we reinitialize as part of a server soft restart.
Definition: srv_main.cpp:3204
struct civserver server
Definition: srv_main.cpp:121
player * mapimg_server_tile_owner(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Helper function for the mapimg module - tile owner.
Definition: srv_main.cpp:3385
bool force_end_of_sniff
Definition: srv_main.cpp:130
void save_game_auto(const char *save_reason, enum autosave_type type)
Save game with autosave filename.
Definition: srv_main.cpp:1788
const char * server_ss_name_get(server_setting_id id)
Returns the name of the server setting with the specified id.
Definition: srv_main.cpp:3281
bool check_for_game_over()
Returns TRUE if any one game end condition is fulfilled, FALSE otherwise.
Definition: srv_main.cpp:265
player * mapimg_server_tile_unit(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Helper function for the mapimg module - unit owner.
Definition: srv_main.cpp:3426
void set_server_state(enum server_states newstate)
Set current server state.
Definition: srv_main.cpp:243
void server_quit()
Quit the server and exit.
Definition: srv_main.cpp:1869
struct server_arguments srvarg
Definition: srv_main.cpp:118
known_type mapimg_server_tile_known(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Helper function for the mapimg module - tile knowledge.
Definition: srv_main.cpp:3356
bool game_was_started()
Returns iff the game was started once upon a time.
Definition: srv_main.cpp:251
bool server_ss_val_bool_get(server_setting_id id)
Returns the value of the boolean server setting with the specified id.
Definition: srv_main.cpp:3311
server_setting_id server_ss_by_name(const char *name)
Returns the id of the server setting with the specified name.
Definition: srv_main.cpp:3266
enum server_states server_state()
Return current server state.
Definition: srv_main.cpp:238
rgbcolor * mapimg_server_plrcolor_get(int i)
Helper function for the mapimg module - one player color.
Definition: srv_main.cpp:3451
void srv_init()
Initialize freeciv server.
Definition: srv_main.cpp:162
int server_ss_val_int_get(server_setting_id id)
Returns the value of the integer server setting with the specified id.
Definition: srv_main.cpp:3326
unsigned int server_ss_val_bitwise_get(server_setting_id id)
Returns the value of the bitwise server setting with the specified id.
Definition: srv_main.cpp:3341
enum sset_type server_ss_type_get(server_setting_id id)
Returns the type of the server setting with the specified id.
Definition: srv_main.cpp:3296
terrain * mapimg_server_tile_terrain(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Helper function for the mapimg module - tile terrain.
Definition: srv_main.cpp:3370
player * mapimg_server_tile_city(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Helper function for the mapimg module - city owner.
Definition: srv_main.cpp:3401
char ** freeciv_completion(const char *text, int start, int end)
Attempt to complete on the contents of TEXT.
Definition: stdinhand.cpp:7767
void stdinhand_init()
Initialize stuff related to this code module.
Definition: stdinhand.cpp:231
bool handle_stdin_input(struct connection *caller, char *str)
Main entry point for "command input".
Definition: stdinhand.cpp:4445
bool read_init_script(struct connection *caller, const char *script_filename, bool from_cmdline, bool check)
Main entry point for reading an init script.
Definition: stdinhand.cpp:1114
bool load_command(struct connection *caller, const char *filename, bool check, bool cmdline_load)
Loads a file, complete with access checks and error messages sent back to the caller on failure.
Definition: stdinhand.cpp:3780
bool should_quit()
Returns whether the server should exit after a command.
Definition: stdinhand.cpp:4440
struct civ_game::@28::@32 server
struct conn_list * est_connections
Definition: game.h:88
struct packet_game_info info
Definition: game.h:80
struct conn_list * all_connections
Definition: game.h:87
struct packet_timeout_info tinfo
Definition: game.h:82
int(* player_tile_city_id_get)(const struct tile *ptile, const struct player *pplayer)
Definition: fc_interface.h:42
int(* server_setting_val_int_get)(server_setting_id id)
Definition: fc_interface.h:29
void(* create_extra)(struct tile *ptile, const extra_type *pextra, struct player *pplayer)
Definition: fc_interface.h:31
bool(* player_tile_vision_get)(const struct tile *ptile, const struct player *pplayer, enum vision_layer vision)
Definition: fc_interface.h:36
const char *(* server_setting_name_get)(server_setting_id id)
Definition: fc_interface.h:26
bool(* server_setting_val_bool_get)(server_setting_id id)
Definition: fc_interface.h:28
void(* destroy_extra)(struct tile *ptile, struct extra_type *pextra)
Definition: fc_interface.h:33
server_setting_id(* server_setting_by_name)(const char *name)
Definition: fc_interface.h:25
unsigned int(* server_setting_val_bitwise_get)(server_setting_id id)
Definition: fc_interface.h:30
enum sset_type(* server_setting_type_get)(server_setting_id id)
Definition: fc_interface.h:27
bool metaconnection_persistent
Definition: srv_main.h:32
QString log_filename
Definition: srv_main.h:45
bool exit_on_end
Definition: srv_main.h:56
QString script_filename
Definition: srv_main.h:48
bool fcdb_enabled
Definition: srv_main.h:59
bool metaserver_no_send
Definition: srv_main.h:30
QString fcdb_conf
Definition: srv_main.h:60
QString saves_pathname
Definition: srv_main.h:49
QString ruleset
Definition: srv_main.h:51
QString load_filename
Definition: srv_main.h:47
bool auth_enabled
Definition: srv_main.h:61
#define sz_strlcpy(dest, src)
Definition: support.h:140
void timer_destroy(civtimer *t)
Deletes timer.
Definition: timing.cpp:66
double timer_read_seconds(civtimer *t)
Read value from timer.
Definition: timing.cpp:137
civtimer * timer_new(enum timer_timetype type, enum timer_use use)
Allocate a new timer with specified "type" and "use".
Definition: timing.cpp:43
void timer_start(civtimer *t)
Start timing, adding to previous accumulated time if timer has not been cleared.
Definition: timing.cpp:95
void timer_clear(civtimer *t)
Reset accumulated time to zero, and stop timer if going.
Definition: timing.cpp:83
civtimer * timer_renew(civtimer *t, enum timer_timetype type, enum timer_use use)
Allocate a new timer, or reuse t, with specified "type" and "use".
Definition: timing.cpp:51
@ TIMER_ACTIVE
Definition: timing.h:25
@ TIMER_CPU
Definition: timing.h:20
@ TIMER_USER
Definition: timing.h:21
void voting_init()
Initialize data structures used by this module.
Definition: voting.cpp:720