Freeciv21
Develop your civilization from humble roots to a global empire
sernet.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <fc_config.h>
15 
16 #include <cstring>
17 
18 // Qt
19 #include <QCoreApplication>
20 #include <QHostInfo>
21 #include <QLocalServer>
22 #include <QNetworkDatagram>
23 #include <QTcpServer>
24 #include <QTcpSocket>
25 #include <QUdpSocket>
26 
27 // utility
28 #include "log.h"
29 #include "shared.h"
30 #include "support.h"
31 #include "timing.h"
32 
33 // generated
34 #include "fc_version.h"
35 
36 // common
37 #include "dataio.h"
38 #include "events.h"
39 #include "game.h"
40 #include "packets.h"
41 
42 /* server/scripting */
43 #include "script_server.h"
44 
45 // server
46 #include "aiiface.h"
47 #include "connecthand.h"
48 #include "meta.h"
49 #include "plrhand.h"
50 #include "srv_main.h"
51 #include "stdinhand.h"
52 #include "unittools.h"
53 #include "voting.h"
54 
55 #include "sernet.h"
56 
58 
59 static QUdpSocket *udp_socket = nullptr;
60 
61 #define PROCESSING_TIME_STATISTICS 0
62 
63 static void start_processing_request(struct connection *pconn,
64  int request_id);
65 static void finish_processing_request(struct connection *pconn);
66 
67 static void send_lanserver_response();
68 
73 static void close_connection(struct connection *pconn)
74 {
75  if (!pconn) {
76  return;
77  }
78 
79  if (pconn->server.ping_timers != nullptr) {
80  while (!pconn->server.ping_timers->isEmpty()) {
81  timer_destroy(pconn->server.ping_timers->takeFirst());
82  }
83  delete pconn->server.ping_timers;
84  pconn->server.ping_timers = nullptr;
85  }
86 
87  conn_pattern_list_destroy(pconn->server.ignore_list);
88  pconn->server.ignore_list = nullptr;
89 
90  // safe to do these even if not in lists:
91  conn_list_remove(game.glob_observers, pconn);
92  conn_list_remove(game.all_connections, pconn);
93  conn_list_remove(game.est_connections, pconn);
94 
95  pconn->playing = nullptr;
96  pconn->access_level = ALLOW_NONE;
98 
99  send_updated_vote_totals(nullptr);
100 }
101 
107 {
108  int i;
109 
110  lsend_packet_server_shutdown(game.all_connections);
111 
112  for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
113  if (connections[i].used) {
115  }
116  conn_list_destroy(connections[i].self);
117  }
118 
119  // Remove the game connection lists and make sure they are empty.
120  conn_list_destroy(game.glob_observers);
121  conn_list_destroy(game.all_connections);
122  conn_list_destroy(game.est_connections);
123 
125  udp_socket->close();
126  delete udp_socket;
127  udp_socket = nullptr;
128  }
129 
132 
133  packets_deinit();
134 }
135 
141 {
142  struct connection *closing[MAX_NUM_CONNECTIONS];
143  struct connection *pconn;
144  int i, num;
145 
146  do {
147  num = 0;
148 
149  for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
150  pconn = connections + i;
151  if (pconn->used && pconn->server.is_closing) {
152  closing[num++] = pconn;
153  /* Remove closing connections from the lists (hard detach)
154  * to avoid sending to closing connections. */
155  conn_list_remove(game.glob_observers, pconn);
156  conn_list_remove(game.est_connections, pconn);
157  conn_list_remove(game.all_connections, pconn);
158  if (nullptr != conn_get_player(pconn)) {
159  conn_list_remove(conn_get_player(pconn)->connections, pconn);
160  }
161  }
162  }
163 
164  for (i = 0; i < num; i++) {
165  // Now really close them.
166  pconn = closing[i];
168  close_connection(pconn);
169  }
170  } while (0 < num); // May some errors occurred, let's check.
171 }
172 
177 static void server_conn_close_callback(struct connection *pconn)
178 {
179  // Do as little as possible here to avoid recursive evil.
180  pconn->server.is_closing = true;
181 }
182 
188 {
189  for (auto &i : connections) { // check for freaky players
190  struct connection *pconn = &i;
191 
192  if (pconn->used && !pconn->server.is_closing) {
193  if (!pconn->sock->isOpen()) {
194  qDebug("connection (%s) cut due to exception data",
195  conn_description(pconn));
196  connection_close_server(pconn, _("network exception"));
197  } else {
198  if (pconn->send_buffer && pconn->send_buffer->ndata > 0) {
200  }
201  // FIXME Handle connections not taking writes
202  // They should be cut instead of filling their buffer
203  }
204  }
205  }
206 }
207 
209  void *data;
210  enum packet_type type;
211 };
212 
216 static bool get_packet(struct connection *pconn,
217  struct packet_to_handle *ppacket)
218 {
219  ppacket->data = get_packet_from_connection(pconn, &ppacket->type);
220 
221  return nullptr != ppacket->data;
222 }
223 
230 {
231  struct packet_to_handle packet;
232 #if PROCESSING_TIME_STATISTICS
233  civtimer *request_time = nullptr;
234 #endif
235 
236  while (get_packet(pconn, &packet)) {
237  bool command_ok;
238 
239 #if PROCESSING_TIME_STATISTICS
240  int request_id;
241 
242  request_time = timer_renew(request_time, TIMER_USER, TIMER_ACTIVE);
243  timer_start(request_time);
244 #endif // PROCESSING_TIME_STATISTICS
245 
246  pconn->server.last_request_id_seen =
247  get_next_request_id(pconn->server.last_request_id_seen);
248 
249 #if PROCESSING_TIME_STATISTICS
250  request_id = pconn->server.last_request_id_seen;
251 #endif // PROCESSING_TIME_STATISTICS
252 
253  connection_do_buffer(pconn);
254  start_processing_request(pconn, pconn->server.last_request_id_seen);
255 
256  command_ok = server_packet_input(pconn, packet.data, packet.type);
257  ::operator delete(packet.data);
258 
260  connection_do_unbuffer(pconn);
261 
262 #if PROCESSING_TIME_STATISTICS
263  qDebug("processed request %d in %gms", request_id,
264  timer_read_seconds(request_time) * 1000.0);
265 #endif // PROCESSING_TIME_STATISTICS
266 
267  if (!command_ok) {
268  connection_close_server(pconn, _("rejected"));
269  }
270  }
271 
272 #if PROCESSING_TIME_STATISTICS
273  timer_destroy(request_time);
274 #endif // PROCESSING_TIME_STATISTICS
275 }
276 
285 static const char *makeup_connection_name(int *id)
286 {
287  static unsigned short i = 0;
288  static char name[MAX_LEN_NAME];
289 
290  for (;;) {
291  if (i == static_cast<unsigned short>(-1)) {
292  // don't use 0
293  i++;
294  }
295  fc_snprintf(name, sizeof(name), "c%u", static_cast<unsigned int>(++i));
296  if (nullptr == player_by_name(name) && nullptr == player_by_user(name)
297  && nullptr == conn_by_number(i) && nullptr == conn_by_user(name)) {
298  *id = i;
299  return name;
300  }
301  }
302 }
303 
310 int server_make_connection(QIODevice *new_sock, const QString &client_addr,
311  const QString &ip_addr)
312 {
313  civtimer *timer;
314  int i;
315 
316  for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
317  struct connection *pconn = &connections[i];
318 
319  if (!pconn->used) {
320  connection_common_init(pconn);
321  pconn->sock = new_sock;
322  pconn->closing_reason.clear();
323  pconn->observer = false;
324  pconn->playing = nullptr;
325  pconn->capability[0] = '\0';
327  pconn->notify_of_writable_data = nullptr;
328  pconn->server.currently_processed_request_id = 0;
329  pconn->server.last_request_id_seen = 0;
330  pconn->server.auth_tries = 0;
331  pconn->server.auth_settime = 0;
332  pconn->server.status = AS_NOT_ESTABLISHED;
333  pconn->server.ping_timers = new QList<civtimer *>;
334  pconn->server.granted_access_level = pconn->access_level;
335  pconn->server.ignore_list =
336  conn_pattern_list_new_full(conn_pattern_destroy);
337  pconn->server.is_closing = false;
338  pconn->ping_time = -1.0;
339  pconn->incoming_packet_notify = nullptr;
340  pconn->outgoing_packet_notify = nullptr;
341 
342  sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
343  pconn->addr = client_addr;
344  sz_strlcpy(pconn->server.ipaddr, qUtf8Printable(ip_addr));
345 
346  conn_list_append(game.all_connections, pconn);
347 
348  qDebug("connection (%s) from %s (%s)", pconn->username,
349  qUtf8Printable(pconn->addr), pconn->server.ipaddr);
350  /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
351  * the mute connection. This timer will be canceled into
352  * connecthand.c:handle_login_request(). */
354  timer_start(timer);
355  pconn->server.ping_timers->append(timer);
356  return 0;
357  }
358  }
359 
360  // Should not happen as per the check earlier in server_attempt_connection
361  qCritical("maximum number of connections reached");
362  new_sock->deleteLater();
363  return -1;
364 }
365 
370 std::optional<socket_server> server_open_socket()
371 {
372  // Local socket mode
373  if (!srvarg.local_addr.isEmpty()) {
374  auto server = std::make_unique<QLocalServer>();
375  server->setSocketOptions(QLocalServer::UserAccessOption);
376  if (server->listen(srvarg.local_addr)) {
378 
379  // Don't do LAN announcements
380  return server;
381  } else {
382  qCritical().noquote()
383  << QString(_("Server: cannot listen on local socket %1: %2"))
384  .arg(srvarg.local_addr)
385  .arg(server->errorString());
386  return std::nullopt;
387  }
388  }
389 
390  // TCP socket mode
391  auto server = std::make_unique<QTcpServer>();
392 
393  int max = srvarg.port + 100;
394  for (; srvarg.port < max; ++srvarg.port) {
395  qInfo("Server attempting to listen on %s:%d",
396  qUtf8Printable(srvarg.bind_addr.toString()), srvarg.port);
397  if (server->listen(srvarg.bind_addr, srvarg.port)) {
398  break;
399  }
400 
401  // Failed
403  // Failure to meet user expectations.
404  qFatal("%s",
405  qUtf8Printable(
406  QString::fromUtf8(
407  // TRANS: %1 is a port number, %2 is the error message
408  _("Server: cannot listen on port %1: %2"))
409  .arg(srvarg.port)
410  .arg(server->errorString())));
411  return std::nullopt;
412  }
413  }
414 
416 
417  if (srvarg.announce == ANNOUNCE_NONE) {
418  return server;
419  }
420 
421  enum QHostAddress::SpecialAddress address_type;
422  switch (srvarg.announce) {
423  case ANNOUNCE_IPV6:
424  address_type = QHostAddress::AnyIPv6;
425  break;
426  case ANNOUNCE_IPV4:
427  default:
428  address_type = QHostAddress::AnyIPv4;
429  }
430  // Create socket for server LAN announcements
431  udp_socket = new QUdpSocket();
432 
433  if (!udp_socket->bind(address_type, SERVER_LAN_PORT,
434  QAbstractSocket::ReuseAddressHint)) {
435  qCritical("SO_REUSEADDR failed: %s",
436  udp_socket->errorString().toLocal8Bit().data());
437  return server;
438  }
440  if (!udp_socket->joinMulticastGroup(QHostAddress(group))) {
441  qCritical("Announcement socket binding failed: %s",
442  udp_socket->errorString().toLocal8Bit().data());
443  }
444 
445  return server;
446 }
447 
453 {
454  int i;
455 
456  game.all_connections = conn_list_new();
457  game.est_connections = conn_list_new();
458  game.glob_observers = conn_list_new();
459 
460  for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
461  struct connection *pconn = &connections[i];
462 
463  pconn->used = false;
464  pconn->self = conn_list_new();
465  conn_list_prepend(pconn->self, pconn);
466  }
467 }
468 
472 static void start_processing_request(struct connection *pconn,
473  int request_id)
474 {
475  fc_assert_ret(request_id);
476  fc_assert_ret(pconn->server.currently_processed_request_id == 0);
477  log_debug("start processing packet %d from connection %d", request_id,
478  pconn->id);
480  send_packet_processing_started(pconn);
481  pconn->server.currently_processed_request_id = request_id;
482 }
483 
487 static void finish_processing_request(struct connection *pconn)
488 {
489  if (!pconn || !pconn->used) {
490  return;
491  }
492  fc_assert_ret(pconn->server.currently_processed_request_id);
493  log_debug("finish processing packet %d from connection %d",
494  pconn->server.currently_processed_request_id, pconn->id);
495  send_packet_processing_finished(pconn);
496  pconn->server.currently_processed_request_id = 0;
497  conn_compression_thaw(pconn);
498 }
499 
504 {
505  time_t now = time(NULL);
506  struct unit *punit;
507  struct unit_wait *head;
508 
509  while ((head = unit_wait_list_front(server.unit_waits))
510  && head->wake_up < now) {
511 
512  punit = game_unit_by_number(head->id);
513  if (!punit) {
514  /* Unit doesn't exist anymore. */
515  continue;
516  }
517  if (head->activity == punit->activity) {
518  finish_unit_wait(punit, head->activity_count);
519  }
520  unit_wait_list_pop_front(server.unit_waits);
521  }
522 }
523 
527 void connection_ping(struct connection *pconn)
528 {
530 
531  log_debug("sending ping to %s (open=%d)", conn_description(pconn),
532  pconn->server.ping_timers->size());
533  timer_start(timer);
534  pconn->server.ping_timers->append(timer);
535  send_packet_conn_ping(pconn);
536 }
537 
541 void handle_conn_pong(struct connection *pconn)
542 {
543  civtimer *timer;
544 
545  if (pconn->server.ping_timers->size() == 0) {
546  qCritical("got unexpected pong from %s", conn_description(pconn));
547  return;
548  }
549 
550  timer = pconn->server.ping_timers->front();
551  pconn->ping_time = timer_read_seconds(timer);
552  timer_destroy(pconn->server.ping_timers->takeFirst());
553 
554  log_time(QStringLiteral("got pong from %1 (open=%2); ping time = %3s")
555  .arg(conn_description(pconn))
556  .arg(pconn->server.ping_timers->size())
557  .arg(pconn->ping_time));
558 }
559 
564 {
565  log_debug("Received heartbeat");
566 }
567 
573 {
574  struct data_in din;
575  int type;
576 
577  if (srvarg.announce == ANNOUNCE_NONE) {
578  return;
579  }
580 
581  if (udp_socket && udp_socket->hasPendingDatagrams()) {
582  QNetworkDatagram qnd = udp_socket->receiveDatagram();
583  auto data = qnd.data();
584  dio_input_init(&din, data.constData(), 1);
585  fc_assert_ret_msg(dio_get_uint8_raw(&din, &type), "dio error");
586  if (type == SERVER_LAN_VERSION) {
587  log_debug("Received request for server LAN announcement.");
589  } else {
590  log_debug("Received invalid request for server LAN announcement.");
591  }
592  }
593 }
594 
599 // We would need a raw network connection for broadcast messages
601 {
602  char buffer[MAX_LEN_PACKET];
603  char hostname[512];
604  char port[256];
605  char version[256];
606  char players[256];
607  int nhumans;
608  char humans[256];
609  char status[256];
610  struct raw_data_out dout;
611  const char *group;
612  size_t size;
613  enum QHostAddress::SpecialAddress address_type;
614  QUdpSocket lockal_udpsock;
615 
616  // Set the UDP Multicast group IP address of the packet.
618  switch (srvarg.announce) {
619  case ANNOUNCE_IPV6:
620  address_type = QHostAddress::AnyIPv6;
621  break;
622  case ANNOUNCE_IPV4:
623  default:
624  address_type = QHostAddress::AnyIPv4;
625  }
626  lockal_udpsock.bind(address_type, SERVER_LAN_PORT + 1,
627  QAbstractSocket::ReuseAddressHint);
628 
629  lockal_udpsock.joinMulticastGroup(QHostAddress(group));
630  // Create a description of server state to send to clients.
631  if (!srvarg.identity_name.isEmpty()) {
632  sz_strlcpy(hostname, qUtf8Printable(srvarg.identity_name));
633  } else if (fc_gethostname(hostname, sizeof(hostname)) != 0) {
634  sz_strlcpy(hostname, "none");
635  }
636 
637  fc_snprintf(version, sizeof(version), "%d.%d.%d%s", MAJOR_VERSION,
638  MINOR_VERSION, PATCH_VERSION, VERSION_LABEL);
639 
640  switch (server_state()) {
641  case S_S_INITIAL:
642  // TRANS: Game state for local server
643  fc_snprintf(status, sizeof(status), _("Pregame"));
644  break;
645  case S_S_RUNNING:
646  // TRANS: Game state for local server
647  fc_snprintf(status, sizeof(status), _("Running"));
648  break;
649  case S_S_OVER:
650  // TRANS: Game state for local server
651  fc_snprintf(status, sizeof(status), _("Game over"));
652  break;
653  }
654 
655  fc_snprintf(players, sizeof(players), "%d", normal_player_count());
656 
657  nhumans = 0;
658  players_iterate(pplayer)
659  {
660  if (pplayer->is_alive && is_human(pplayer)) {
661  nhumans++;
662  }
663  }
665  fc_snprintf(humans, sizeof(humans), "%d", nhumans);
666 
667  fc_snprintf(port, sizeof(port), "%d", srvarg.port);
668 
669  dio_output_init(&dout, buffer, sizeof(buffer));
671  dio_put_string_raw(&dout, hostname);
672  dio_put_string_raw(&dout, port);
673  dio_put_string_raw(&dout, version);
674  dio_put_string_raw(&dout, status);
675  dio_put_string_raw(&dout, players);
676  dio_put_string_raw(&dout, humans);
678  size = dio_output_used(&dout);
679  lockal_udpsock.writeDatagram(QByteArray(buffer, size), QHostAddress(group),
680  SERVER_LAN_PORT + 1);
681  lockal_udpsock.close();
682 }
void lost_connection_to_client(struct connection *pconn)
High-level server stuff when connection to client is closed or lost.
void connection_close_server(struct connection *pconn, const QString &reason)
Close a connection.
void connections_set_close_callback(conn_close_fn_t func)
Register the close_callback.
Definition: connection.cpp:61
void flush_connection_send_buffer_all(struct connection *pc)
Flush'em.
Definition: connection.cpp:177
int get_next_request_id(int old_request_id)
Get next request id.
Definition: connection.cpp:490
struct player * conn_get_player(const struct connection *pconn)
Returns the player that this connection is attached to, or nullptr.
Definition: connection.cpp:693
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 connection_do_buffer(struct connection *pc)
Turn on buffering, using a counter so that calls may be nested.
Definition: connection.cpp:278
void conn_pattern_destroy(struct conn_pattern *ppattern)
Free a connection pattern.
Definition: connection.cpp:738
void connection_common_init(struct connection *pconn)
Initialize common part of connection structure.
Definition: connection.cpp:555
void connection_common_close(struct connection *pconn)
Connection closing part common to server and client.
Definition: connection.cpp:574
void conn_compression_freeze(struct connection *pconn)
Freeze the connection.
Definition: connection.cpp:636
struct connection * conn_by_number(int id)
Find connection by id, from game.all_connections.
Definition: connection.cpp:376
struct connection * conn_by_user(const char *user_name)
Find connection by exact user name, from game.all_connections, case-insensitve.
Definition: connection.cpp:329
void connection_do_unbuffer(struct connection *pc)
Turn off buffering if internal counter of number of times buffering was turned on falls to zero,...
Definition: connection.cpp:290
@ AS_NOT_ESTABLISHED
Definition: connection.h:84
bool conn_compression_thaw(struct connection *pconn)
Thaw the connection.
Definition: packets.cpp:160
#define MAX_LEN_PACKET
Definition: connection.h:41
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Initializes the output to the given output buffer and the given buffer size.
Definition: dataio_raw.cpp:144
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
Insert value using 8 bits.
Definition: dataio_raw.cpp:229
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Receive uint8 value to dest.
Definition: dataio_raw.cpp:492
void dio_put_string_raw(struct raw_data_out *dout, const char *value)
Insert nullptr-terminated string.
Definition: dataio_raw.cpp:418
size_t dio_output_used(struct raw_data_out *dout)
Return the maximum number of bytes used.
Definition: dataio_raw.cpp:157
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Initializes the input to the given input buffer and the given number of valid input bytes.
Definition: dataio_raw.cpp:169
#define MAX_NUM_CONNECTIONS
Definition: fc_types.h:30
#define MAX_LEN_NAME
Definition: fc_types.h:61
#define _(String)
Definition: fcintl.h:50
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct civ_game game
Definition: game.cpp:47
const char * name
Definition: inputfile.cpp:118
void log_time(const QString &msg, bool log)
Definition: log.cpp:253
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert_ret_msg(condition, message,...)
Definition: log.h:129
#define log_debug(message,...)
Definition: log.h:65
const char * get_meta_message_string()
The metaserver message.
Definition: meta.cpp:80
void server_close_meta()
Stop sending updates to metaserver.
Definition: meta.cpp:436
bool send_server_info_to_metaserver(enum meta_flag flag)
Control when we send info to the metaserver.
Definition: meta.cpp:469
@ META_GOODBYE
Definition: meta.h:25
@ ANNOUNCE_IPV6
Definition: net_types.h:19
@ ANNOUNCE_IPV4
Definition: net_types.h:19
@ ANNOUNCE_NONE
Definition: net_types.h:19
void packets_deinit()
Call when there is no longer a requirement for protocol processing.
Definition: packets.cpp:804
#define get_packet_from_connection(pc, ptype)
Definition: packets.h:90
struct player * player_by_name(const char *name)
Find player by given name.
Definition: player.cpp:800
struct player * player_by_user(const char *name)
Find player by its user name (not player/leader name)
Definition: player.cpp:860
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
#define is_human(plr)
Definition: player.h:226
int normal_player_count()
Return the number of non-barbarian players.
Definition: plrhand.cpp:3140
void connection_ping(struct connection *pconn)
Ping a connection.
Definition: sernet.cpp:527
void init_connections()
Initialize connection related stuff.
Definition: sernet.cpp:452
static void server_conn_close_callback(struct connection *pconn)
Break a client connection.
Definition: sernet.cpp:177
static struct connection connections[MAX_NUM_CONNECTIONS]
Definition: sernet.cpp:57
static const char * makeup_connection_name(int *id)
Make up a name for the connection, before we get any data from it to use as a sensible name.
Definition: sernet.cpp:285
void handle_conn_pong(struct connection *pconn)
Handle response to ping.
Definition: sernet.cpp:541
static void send_lanserver_response()
This function broadcasts an UDP packet to clients with that requests information about the server sta...
Definition: sernet.cpp:600
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
static bool get_packet(struct connection *pconn, struct packet_to_handle *ppacket)
Simplify a loop by wrapping get_packet_from_connection.
Definition: sernet.cpp:216
void close_connections_and_socket()
Close all network stuff: connections, listening sockets, metaserver connection...
Definition: sernet.cpp:106
static void close_connection(struct connection *pconn)
Close the connection (very low-level).
Definition: sernet.cpp:73
void really_close_connections()
Now really close connections marked as 'is_closing'.
Definition: sernet.cpp:140
static QUdpSocket * udp_socket
Definition: sernet.cpp:59
void handle_client_heartbeat(struct connection *pconn)
Handle client's regular hearbeat.
Definition: sernet.cpp:563
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
static void finish_processing_request(struct connection *pconn)
Finish processing of request packet from client.
Definition: sernet.cpp:487
void flush_packets()
Attempt to flush all information in the send buffers for upto 'netwait' seconds.
Definition: sernet.cpp:187
static void start_processing_request(struct connection *pconn, int request_id)
Starts processing of request packet from client.
Definition: sernet.cpp:472
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
#define SERVER_LAN_VERSION
Definition: sernet.h:29
#define SERVER_LAN_PORT
Definition: sernet.h:27
char * get_multicast_group(bool ipv6_preferred)
Returns string which gives the multicast group IP address for finding servers on the LAN,...
Definition: shared.cpp:1065
size_t size
Definition: specvec.h:64
struct civserver server
Definition: srv_main.cpp:121
struct server_arguments srvarg
Definition: srv_main.cpp:118
enum server_states server_state()
Return current server state.
Definition: srv_main.cpp:238
bool server_packet_input(struct connection *pconn, void *packet, int type)
Returns FALSE if connection should be closed (because the clients was rejected).
Definition: srv_main.cpp:2024
enum cmdlevel access_level_for_next_connection()
Return access level for next connection.
Definition: stdinhand.cpp:1368
struct conn_list * glob_observers
Definition: game.h:89
struct conn_list * est_connections
Definition: game.h:88
struct conn_list * all_connections
Definition: game.h:87
struct player * playing
Definition: connection.h:142
enum cmdlevel access_level
Definition: connection.h:164
struct conn_list * self
Definition: connection.h:150
QString closing_reason
Definition: connection.h:133
struct connection::@55::@61 server
QIODevice * sock
Definition: connection.h:129
bool observer
Definition: connection.h:138
char username[MAX_LEN_NAME]
Definition: connection.h:151
void(* incoming_packet_notify)(struct connection *pc, int packet_type, int size)
Definition: connection.h:234
void(* outgoing_packet_notify)(struct connection *pc, int packet_type, int size, int request_id)
Definition: connection.h:242
struct socket_packet_buffer * send_buffer
Definition: connection.h:145
char capability[MAX_LEN_CAPSTR]
Definition: connection.h:158
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition: connection.h:166
double ping_time
Definition: connection.h:148
QString addr
Definition: connection.h:152
enum packet_type type
Definition: sernet.cpp:210
enum announce_type announce
Definition: srv_main.h:64
QString local_addr
Definition: srv_main.h:36
bool user_specified_port
Definition: srv_main.h:41
QString identity_name
Definition: srv_main.h:33
QHostAddress bind_addr
Definition: srv_main.h:38
Definition: servers.h:55
unsigned long ndata
Definition: connection.h:108
time_t wake_up
Definition: unit.h:121
enum unit_activity activity
Definition: unit.h:122
int id
Definition: unit.h:120
int activity_count
Definition: unit.h:123
Definition: unit.h:134
enum unit_activity activity
Definition: unit.h:154
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_gethostname(char *buf, size_t len)
Call gethostname() if supported, else just returns -1.
Definition: support.cpp:586
#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
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_USER
Definition: timing.h:21
void finish_unit_wait(struct unit *punit, int activity_count)
Finish activity of a unit that was deferred by unitwaittime.
Definition: unittools.cpp:1063
void send_updated_vote_totals(struct conn_list *dest)
Sends a packet_vote_update to every conn in dest.
Definition: voting.cpp:884