Freeciv21
Develop your civilization from humble roots to a global empire
connection.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 // Qt
15 #include <QLocalSocket>
16 #include <QTcpSocket>
17 
18 // utility
19 #include "fcintl.h"
20 #include "genhash.h"
21 #include "log.h"
22 #include "support.h" // fc_str(n)casecmp
23 
24 // common
25 #include "game.h" // game.all_connections
26 #include "packets.h"
27 
28 #include "connection.h"
29 
30 static void default_conn_close_callback(struct connection *pconn);
31 
32 /* String used for connection.addr and related cases to indicate
33  * blank/unknown/not-applicable address:
34  */
35 const char blank_addr_str[] = "---.---.---.---";
36 
46 
50 static void default_conn_close_callback(struct connection *pconn)
51 {
53  "Closing a socket (%s) before calling "
54  "connections_set_close_callback().",
55  conn_description(pconn));
56 }
57 
62 {
64 }
65 
69 void connection_close(struct connection *pconn, const QString &reason)
70 {
71  fc_assert_ret(nullptr != pconn);
72 
73  if (nullptr != reason && pconn->closing_reason.isEmpty()) {
74  // NB: we don't overwrite the original reason.
75  pconn->closing_reason = reason;
76  }
77 
78  (*conn_close_callback)(pconn);
79 }
80 
86  int extra_space)
87 {
88  // room for more?
89  if (buf->nsize - buf->ndata < extra_space) {
90  // added this check so we don't gobble up too much mem
91  if (buf->ndata + extra_space > MAX_LEN_BUFFER) {
92  return false;
93  }
94  buf->nsize = buf->ndata + extra_space;
95  buf->data =
96  static_cast<unsigned char *>(fc_realloc(buf->data, buf->nsize));
97  }
98 
99  return true;
100 }
101 
110 int read_socket_data(QIODevice *sock, struct socket_packet_buffer *buffer)
111 {
112  int didget;
113 
115  // Let's first process the packets in the buffer
116  return 0;
117  }
118 
119  log_debug("try reading %lu bytes", buffer->nsize - buffer->ndata);
120  didget = sock->read(reinterpret_cast<char *>(buffer->data + buffer->ndata),
121  buffer->nsize - buffer->ndata);
122 
123  if (didget > 0) {
124  buffer->ndata += didget;
125  log_debug("didget:%d", didget);
126  return didget;
127  } else if (didget == 0) {
128  log_debug("EOF on socket read");
129  return -2;
130  }
131 
132  return -1;
133 }
134 
138 static int write_socket_data(struct connection *pc,
139  struct socket_packet_buffer *buf, int limit)
140 {
141  int start, nput, nblock;
142 
143  if (is_server() && pc->server.is_closing) {
144  return 0;
145  }
146 
147  for (start = 0; buf->ndata - start > limit;) {
148  if (!pc->sock->isOpen()) {
149  connection_close(pc, _("network exception"));
150  return -1;
151  }
152 
153  nblock = MIN(buf->ndata - start, MAX_LEN_PACKET);
154  log_debug("trying to write %d limit=%d", nblock, limit);
155  if ((nput = pc->sock->write(
156  reinterpret_cast<const char *>(buf->data) + start, nblock))
157  == -1) {
158  connection_close(pc, pc->sock->errorString().toUtf8().data());
159  return -1;
160  }
161  start += nput;
162  }
163 
164  if (start > 0) {
165  buf->ndata -= start;
166  memmove(buf->data, buf->data + start, buf->ndata);
168  timer_start(pc->last_write);
169  }
170 
171  return 0;
172 }
173 
178 {
179  if (pc && pc->used && pc->send_buffer->ndata > 0) {
180  write_socket_data(pc, pc->send_buffer, 0);
181  if (pc->notify_of_writable_data) {
183  && pc->send_buffer->ndata > 0);
184  }
185  }
186  if (pc && pc->sock) {
187  if (auto socket = qobject_cast<QLocalSocket *>(pc->sock)) {
188  socket->flush();
189  } else if (auto socket = qobject_cast<QTcpSocket *>(pc->sock)) {
190  socket->flush();
191  }
192  }
193 }
194 
199 {
200  if (pc && pc->used && pc->send_buffer->ndata >= MAX_LEN_PACKET) {
202  if (pc->notify_of_writable_data) {
204  && pc->send_buffer->ndata > 0);
205  }
206  }
207  if (pc && pc->sock) {
208  if (auto socket = qobject_cast<QLocalSocket *>(pc->sock)) {
209  socket->flush();
210  } else if (auto socket = qobject_cast<QTcpSocket *>(pc->sock)) {
211  socket->flush();
212  }
213  }
214 }
215 
219 static bool add_connection_data(struct connection *pconn,
220  const unsigned char *data, int len)
221 {
222  struct socket_packet_buffer *buf;
223 
224  if (nullptr == pconn || !pconn->used
225  || (is_server() && pconn->server.is_closing)) {
226  return true;
227  }
228 
229  buf = pconn->send_buffer;
230  log_debug("add %d bytes to %lu (space =%lu)", len, buf->ndata, buf->nsize);
231  if (!buffer_ensure_free_extra_space(buf, len)) {
232  connection_close(pconn, _("buffer overflow"));
233  return false;
234  }
235 
236  memcpy(buf->data + buf->ndata, data, len);
237  buf->ndata += len;
238 
239  return true;
240 }
241 
245 bool connection_send_data(struct connection *pconn,
246  const unsigned char *data, int len)
247 {
248  if (nullptr == pconn || !pconn->used
249  || (is_server() && pconn->server.is_closing)) {
250  return true;
251  }
252 
253  pconn->statistics.bytes_send += len;
254 
255  if (0 < pconn->send_buffer->do_buffer_sends) {
257  if (!add_connection_data(pconn, data, len)) {
258  qDebug("cut connection %s due to huge send buffer (1)",
259  conn_description(pconn));
260  return false;
261  }
263  } else {
265  if (!add_connection_data(pconn, data, len)) {
266  qDebug("cut connection %s due to huge send buffer (2)",
267  conn_description(pconn));
268  return false;
269  }
271  }
272  return true;
273 }
274 
279 {
280  if (pc && pc->used) {
282  }
283 }
284 
291 {
292  if (nullptr == pc || !pc->used || (is_server() && pc->server.is_closing)) {
293  return;
294  }
295 
297  if (0 > pc->send_buffer->do_buffer_sends) {
298  qCritical("Too many calls to unbuffer %s!", pc->username);
299  pc->send_buffer->do_buffer_sends = 0;
300  }
301 
302  if (0 == pc->send_buffer->do_buffer_sends) {
304  }
305 }
306 
310 void conn_list_do_buffer(struct conn_list *dest)
311 {
312  conn_list_iterate(dest, pconn) { connection_do_buffer(pconn); }
314 }
315 
319 void conn_list_do_unbuffer(struct conn_list *dest)
320 {
321  conn_list_iterate(dest, pconn) { connection_do_unbuffer(pconn); }
323 }
324 
329 struct connection *conn_by_user(const char *user_name)
330 {
332  {
333  if (fc_strcasecmp(user_name, pconn->username) == 0) {
334  return pconn;
335  }
336  }
338 
339  return nullptr;
340 }
341 
348 static const char *connection_accessor(int i)
349 {
350  return conn_list_get(game.all_connections, i)->username;
351 }
352 
353 struct connection *conn_by_user_prefix(const char *user_name,
354  enum m_pre_result *result)
355 {
356  int ind;
357 
358  *result =
361  effectivestrlenquote, user_name, &ind);
362 
363  if (*result < M_PRE_AMBIGUOUS) {
364  return conn_list_get(game.all_connections, ind);
365  } else {
366  return nullptr;
367  }
368 }
369 
376 struct connection *conn_by_number(int id)
377 {
379  {
380  fc_assert_msg(pconn != nullptr,
381  "Trying to look at the id of a non existing connection");
382 
383  if (pconn->id == id) {
384  return pconn;
385  }
386  }
388 
389  return nullptr;
390 }
391 
396 {
397  auto *buf = new socket_packet_buffer;
398  buf->ndata = 0;
399  buf->do_buffer_sends = 0;
400  buf->nsize = 10 * MAX_LEN_PACKET;
401  buf->data = static_cast<unsigned char *>(fc_malloc(buf->nsize));
402 
403  return buf;
404 }
405 
410 {
411  if (buf) {
412  if (buf->data) {
413  free(buf->data);
414  }
415  delete buf;
416  buf = nullptr;
417  }
418 }
419 
431 const char *conn_description(const struct connection *pconn, bool is_private)
432 {
433  static char buffer[MAX_LEN_NAME * 2 + MAX_LEN_ADDR + 128];
434  buffer[0] = '\0';
435 
436  if (*pconn->username != '\0') {
437  if (is_private) {
438  fc_snprintf(buffer, sizeof(buffer), _("%s from %s"), pconn->username,
439  qUtf8Printable(pconn->addr));
440  } else {
441  fc_snprintf(buffer, sizeof(buffer), "%s", pconn->username);
442  }
443  } else {
444  sz_strlcpy(buffer, "server");
445  }
446  if (!pconn->closing_reason.isEmpty()) {
447  /* TRANS: Appending the reason why a connection has closed.
448  * Preserve leading space. */
449  cat_snprintf(buffer, sizeof(buffer), _(" (%s)"),
450  qUtf8Printable(pconn->closing_reason));
451  } else if (!pconn->established) {
452  // TRANS: preserve leading space.
453  sz_strlcat(buffer, _(" (connection incomplete)"));
454  return buffer;
455  }
456  if (nullptr != pconn->playing) {
457  // TRANS: preserve leading space.
458  cat_snprintf(buffer, sizeof(buffer), _(" (player %s)"),
459  player_name(pconn->playing));
460  }
461  if (pconn->observer) {
462  // TRANS: preserve leading space.
463  sz_strlcat(buffer, _(" (observer)"));
464  }
465 
466  return buffer;
467 }
468 
472 bool can_conn_edit(const struct connection *pconn)
473 {
474  return (can_conn_enable_editing(pconn) && game.info.is_edit_mode
475  && (nullptr != pconn->playing || pconn->observer));
476 }
477 
481 bool can_conn_enable_editing(const struct connection *pconn)
482 {
483  return pconn->access_level == ALLOW_HACK;
484 }
485 
490 int get_next_request_id(int old_request_id)
491 {
492  int result = old_request_id + 1;
493 
494  if ((result & 0xffff) == 0) {
495  log_packet("INFORMATION: request_id has wrapped around; "
496  "setting from %d to 2",
497  result);
498  result = 2;
499  }
500  fc_assert(0 != result);
501 
502  return result;
503 }
504 
509 {
510  byte_vector_free(&pc->compression.queue);
511 }
512 
516 static void init_packet_hashs(struct connection *pc)
517 {
518  pc->phs.sent = new genhash *[PACKET_LAST] {};
519  pc->phs.received = new genhash *[PACKET_LAST] {};
521 }
522 
526 static void free_packet_hashes(struct connection *pc)
527 {
528  int i;
529 
530  if (pc->phs.sent) {
531  for (i = 0; i < PACKET_LAST; i++) {
532  if (pc->phs.sent[i] != nullptr) {
533  genhash_destroy(pc->phs.sent[i]);
534  }
535  }
536  delete[] pc->phs.sent;
537  pc->phs.sent = nullptr;
538  }
539 
540  if (pc->phs.received) {
541  for (i = 0; i < PACKET_LAST; i++) {
542  if (pc->phs.received[i] != nullptr) {
543  genhash_destroy(pc->phs.received[i]);
544  }
545  }
546  delete[] pc->phs.received;
547  pc->phs.received = nullptr;
548  }
549 }
550 
556 {
557  pconn->established = false;
558  pconn->used = true;
560  pconn->last_write = nullptr;
561  pconn->buffer = new_socket_packet_buffer();
563  pconn->statistics.bytes_send = 0;
564 
565  init_packet_hashs(pconn);
566 
567  byte_vector_init(&pconn->compression.queue);
568  pconn->compression.frozen_level = 0;
569 }
570 
575 {
576  if (!pconn->used) {
577  qCritical("WARNING: Trying to close already closed connection");
578  } else {
579  pconn->sock->deleteLater();
580  pconn->sock = nullptr;
581  pconn->used = false;
582  pconn->established = false;
583 
585  pconn->buffer = nullptr;
586 
588  pconn->send_buffer = nullptr;
589 
590  if (pconn->last_write) {
591  timer_destroy(pconn->last_write);
592  pconn->last_write = nullptr;
593  }
594 
595  free_compression_queue(pconn);
596  free_packet_hashes(pconn);
597  }
598 }
599 
603 void conn_set_capability(struct connection *pconn, const char *capability)
604 {
605  fc_assert(strlen(capability) < sizeof(pconn->capability));
606 
607  sz_strlcpy(pconn->capability, capability);
608  pconn->phs.handlers = packet_handlers_get(capability);
609 }
610 
616 {
617  int i;
618 
619  for (i = 0; i < PACKET_LAST; i++) {
620  if (packet_has_game_info_flag(packet_type(i))) {
621  if (nullptr != pc->phs.sent && nullptr != pc->phs.sent[i]) {
622  genhash_clear(pc->phs.sent[i]);
623  }
624  if (nullptr != pc->phs.received && nullptr != pc->phs.received[i]) {
625  genhash_clear(pc->phs.received[i]);
626  }
627  }
628  }
629 }
630 
637 {
638  if (0 == pconn->compression.frozen_level) {
639  byte_vector_reserve(&pconn->compression.queue, 0);
640  }
641  pconn->compression.frozen_level++;
642 }
643 
648 bool conn_compression_frozen(const struct connection *pconn)
649 {
650  return 0 < pconn->compression.frozen_level;
651 }
652 
656 void conn_list_compression_freeze(const struct conn_list *pconn_list)
657 {
658  conn_list_iterate(pconn_list, pconn) { conn_compression_freeze(pconn); }
660 }
661 
665 void conn_list_compression_thaw(const struct conn_list *pconn_list)
666 {
667  conn_list_iterate(pconn_list, pconn) { conn_compression_thaw(pconn); }
669 }
670 
675 bool conn_controls_player(const struct connection *pconn)
676 {
677  return pconn && pconn->playing && !pconn->observer;
678 }
679 
683 bool conn_is_global_observer(const struct connection *pconn)
684 {
685  return pconn && !pconn->playing && pconn->observer;
686 }
687 
693 struct player *conn_get_player(const struct connection *pconn)
694 {
695  if (!pconn) {
696  return nullptr;
697  }
698  return pconn->playing;
699 }
700 
705 enum cmdlevel conn_get_access(const struct connection *pconn)
706 {
707  if (!pconn) {
708  return ALLOW_NONE; // Would not want to give hack on error...
709  }
710  return pconn->access_level;
711 }
712 
716 struct conn_pattern {
717  enum conn_pattern_type type;
718  char *wildcard;
719 };
720 
724 struct conn_pattern *conn_pattern_new(enum conn_pattern_type type,
725  const char *wildcard)
726 {
727  auto *ppattern = new conn_pattern;
728 
729  ppattern->type = type;
730  ppattern->wildcard = fc_strdup(wildcard);
731 
732  return ppattern;
733 }
734 
738 void conn_pattern_destroy(struct conn_pattern *ppattern)
739 {
740  fc_assert_ret(nullptr != ppattern);
741  delete ppattern->wildcard;
742  delete ppattern;
743 }
744 
748 bool conn_pattern_match(const struct conn_pattern *ppattern,
749  const struct connection *pconn)
750 {
751  QString test;
752 
753  switch (ppattern->type) {
754  case CPT_USER:
755  test = pconn->username;
756  break;
757  case CPT_HOST:
758  test = pconn->addr;
759  break;
760  case CPT_IP:
761  if (is_server()) {
762  test = pconn->server.ipaddr;
763  }
764  break;
765  }
766 
767  if (!test.isEmpty()) {
768  return wildcard_fit_string(ppattern->wildcard, qUtf8Printable(test));
769  } else {
770  qCritical("%s(): Invalid pattern type (%d)", __FUNCTION__,
771  ppattern->type);
772  return false;
773  }
774 }
775 
779 bool conn_pattern_list_match(const struct conn_pattern_list *plist,
780  const struct connection *pconn)
781 {
782  conn_pattern_list_iterate(plist, ppattern)
783  {
784  if (conn_pattern_match(ppattern, pconn)) {
785  return true;
786  }
787  }
789 
790  return false;
791 }
792 
796 size_t conn_pattern_to_string(const struct conn_pattern *ppattern, char *buf,
797  size_t buf_len)
798 {
799  return fc_snprintf(buf, buf_len, "<%s=%s>",
800  conn_pattern_type_name(ppattern->type),
801  ppattern->wildcard);
802 }
803 
809 struct conn_pattern *conn_pattern_from_string(const char *pattern,
810  enum conn_pattern_type prefer,
811  char *error_buf,
812  size_t error_buf_len)
813 {
814  enum conn_pattern_type type = conn_pattern_type_invalid();
815  const char *p;
816 
817  // Determine pattern type.
818  if ((p = strchr(pattern, '='))) {
819  // Special character to separate the type of the pattern.
820  QString pattern_type;
821 
822  pattern_type = QString(pattern).trimmed();
823  type = conn_pattern_type_by_name(qUtf8Printable(pattern_type),
824  fc_strcasecmp);
825  if (!conn_pattern_type_is_valid(type)) {
826  if (nullptr != error_buf) {
827  fc_snprintf(error_buf, error_buf_len,
828  _("\"%s\" is not a valid pattern type"),
829  qUtf8Printable(pattern_type));
830  }
831  return nullptr;
832  }
833  } else {
834  // Use 'prefer' type.
835  p = pattern;
836  type = prefer;
837  if (!conn_pattern_type_is_valid(type)) {
838  if (nullptr != error_buf) {
839  fc_strlcpy(error_buf, _("Missing pattern type"), error_buf_len);
840  }
841  return nullptr;
842  }
843  }
844 
845  // Remove leading spaces.
846  while (QChar::isSpace(*p)) {
847  p++;
848  }
849 
850  if ('\0' == *p) {
851  if (nullptr != error_buf) {
852  fc_strlcpy(error_buf, _("Missing pattern"), error_buf_len);
853  }
854  return nullptr;
855  }
856 
857  return conn_pattern_new(type, p);
858 }
859 
864 bool conn_is_valid(const struct connection *pconn)
865 {
866  return (pconn && pconn->used && !pconn->server.is_closing);
867 }
size_t conn_pattern_to_string(const struct conn_pattern *ppattern, char *buf, size_t buf_len)
Put a string reprentation of the pattern in 'buf'.
Definition: connection.cpp:796
static conn_close_fn_t conn_close_callback
This callback is used when an error occurs trying to write to the connection.
Definition: connection.cpp:45
void conn_list_do_unbuffer(struct conn_list *dest)
Convenience functions to unbuffer a list of connections.
Definition: connection.cpp:319
static void default_conn_close_callback(struct connection *pconn)
Default 'conn_close_fn_t' to close a connection.
Definition: connection.cpp:50
bool can_conn_edit(const struct connection *pconn)
Return TRUE iff the connection is currently allowed to edit.
Definition: connection.cpp:472
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Thaw a connection list.
Definition: connection.cpp:665
void connections_set_close_callback(conn_close_fn_t func)
Register the close_callback.
Definition: connection.cpp:61
static void flush_connection_send_buffer_packets(struct connection *pc)
Flush'em.
Definition: connection.cpp:198
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
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
static const char * connection_accessor(int i)
Like conn_by_username(), but allow unambigous prefix (i.e.
Definition: connection.cpp:348
bool can_conn_enable_editing(const struct connection *pconn)
Return TRUE iff the connection is allowed to start editing.
Definition: connection.cpp:481
void connection_do_buffer(struct connection *pc)
Turn on buffering, using a counter so that calls may be nested.
Definition: connection.cpp:278
static bool add_connection_data(struct connection *pconn, const unsigned char *data, int len)
Add data to send to the connection.
Definition: connection.cpp:219
bool conn_pattern_match(const struct conn_pattern *ppattern, const struct connection *pconn)
Returns TRUE whether the connection fits the connection pattern.
Definition: connection.cpp:748
static bool buffer_ensure_free_extra_space(struct socket_packet_buffer *buf, int extra_space)
Make sure that there is at least extra_space bytes free space in buffer, allocating more memory if ne...
Definition: connection.cpp:85
void conn_set_capability(struct connection *pconn, const char *capability)
Set the network capability string for 'pconn'.
Definition: connection.cpp:603
void conn_pattern_destroy(struct conn_pattern *ppattern)
Free a connection pattern.
Definition: connection.cpp:738
void conn_reset_delta_state(struct connection *pc)
Remove all is-game-info cached packets from the connection.
Definition: connection.cpp:615
void connection_common_init(struct connection *pconn)
Initialize common part of connection structure.
Definition: connection.cpp:555
static void init_packet_hashs(struct connection *pc)
Allocate and initialize packet hashs for given connection.
Definition: connection.cpp:516
void conn_list_compression_freeze(const struct conn_list *pconn_list)
Freeze a connection list.
Definition: connection.cpp:656
bool conn_controls_player(const struct connection *pconn)
Returns TRUE if the given connection is attached to a player which it also controls (i....
Definition: connection.cpp:675
bool conn_is_global_observer(const struct connection *pconn)
Returns TRUE if the given connection is a global observer.
Definition: connection.cpp:683
void connection_close(struct connection *pconn, const QString &reason)
Call the conn_close_callback.
Definition: connection.cpp:69
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
static void free_packet_hashes(struct connection *pc)
Free packet hash resources from given connection.
Definition: connection.cpp:526
static void free_socket_packet_buffer(struct socket_packet_buffer *buf)
Free malloced struct.
Definition: connection.cpp:409
void free_compression_queue(struct connection *pc)
Free compression queue for given connection.
Definition: connection.cpp:508
const char blank_addr_str[]
Definition: connection.cpp:35
bool connection_send_data(struct connection *pconn, const unsigned char *data, int len)
Write data to socket.
Definition: connection.cpp:245
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
static int write_socket_data(struct connection *pc, struct socket_packet_buffer *buf, int limit)
Write wrapper function -vasc.
Definition: connection.cpp:138
enum cmdlevel conn_get_access(const struct connection *pconn)
Returns the current access level of the given connection.
Definition: connection.cpp:705
bool conn_is_valid(const struct connection *pconn)
Returns TRUE if the connection is valid, i.e.
Definition: connection.cpp:864
bool conn_compression_frozen(const struct connection *pconn)
Returns TRUE if the connection is frozen.
Definition: connection.cpp:648
struct connection * conn_by_user_prefix(const char *user_name, enum m_pre_result *result)
Definition: connection.cpp:353
struct conn_pattern * conn_pattern_from_string(const char *pattern, enum conn_pattern_type prefer, char *error_buf, size_t error_buf_len)
Creates a new connection pattern from the string.
Definition: connection.cpp:809
struct socket_packet_buffer * new_socket_packet_buffer()
Return malloced struct, appropriately initialized.
Definition: connection.cpp:395
struct conn_pattern * conn_pattern_new(enum conn_pattern_type type, const char *wildcard)
Creates a new connection pattern.
Definition: connection.cpp:724
bool conn_pattern_list_match(const struct conn_pattern_list *plist, const struct connection *pconn)
Returns TRUE whether the connection fits one of the connection patterns.
Definition: connection.cpp:779
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
#define conn_pattern_list_iterate_end
Definition: connection.h:317
void(* conn_close_fn_t)(struct connection *pconn)
Definition: connection.h:260
bool conn_compression_thaw(struct connection *pconn)
Thaw the connection.
Definition: packets.cpp:160
#define MAX_LEN_PACKET
Definition: connection.h:41
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define MAX_LEN_BUFFER
Definition: connection.h:47
#define conn_pattern_list_iterate(plist, ppatern)
Definition: connection.h:315
#define conn_list_iterate_end
Definition: connection.h:101
#define MAX_LEN_NAME
Definition: fc_types.h:61
#define _(String)
Definition: fcintl.h:50
struct civ_game game
Definition: game.cpp:47
bool is_server()
Is program type server?
Definition: game.cpp:57
void genhash_destroy(struct genhash *pgenhash)
Destructor: free internal memory.
Definition: genhash.cpp:284
void genhash_clear(struct genhash *pgenhash)
Remove all entries of the genhash table.
Definition: genhash.cpp:575
get_token_fn_t func
Definition: inputfile.cpp:119
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert_ret(condition)
Definition: log.h:112
#define log_packet
Definition: log.h:72
#define fc_assert(condition)
Definition: log.h:89
#define log_debug(message,...)
Definition: log.h:65
const struct packet_handlers * packet_handlers_get(const char *capability)
Returns the packet handlers variant for 'capability'.
Definition: packets.cpp:766
void packet_header_init(struct packet_header *packet_header)
Set the packet header field lengths used for the login protocol, before the capability of the connect...
Definition: packets.cpp:572
const struct packet_handlers * packet_handlers_initial()
Returns the packet handlers variant with no special capability.
Definition: packets.cpp:749
bool packet_has_game_info_flag(enum packet_type type)
int len
Definition: packhand.cpp:127
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
bool wildcard_fit_string(const char *pattern, const char *test)
Returns TRUE if test fit the pattern.
Definition: shared.cpp:1372
enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, size_t n_names, size_t max_len_name, m_pre_strncmp_fn_t cmp_fn, m_strlen_fn_t len_fn, const char *prefix, int *ind_result)
See match_prefix_full().
Definition: shared.cpp:986
#define MIN(x, y)
Definition: shared.h:49
m_pre_result
Definition: shared.h:152
@ M_PRE_AMBIGUOUS
Definition: shared.h:155
#define MAX_LEN_ADDR
Definition: shared.h:27
struct packet_game_info info
Definition: game.h:80
struct conn_list * all_connections
Definition: game.h:87
Connection patterns.
Definition: connection.cpp:716
char * wildcard
Definition: connection.cpp:718
enum conn_pattern_type type
Definition: connection.cpp:717
class civtimer * last_write
Definition: connection.h:146
struct genhash ** received
Definition: connection.h:246
bool established
Definition: connection.h:131
struct player * playing
Definition: connection.h:142
enum cmdlevel access_level
Definition: connection.h:164
const struct packet_handlers * handlers
Definition: connection.h:247
QString closing_reason
Definition: connection.h:133
struct connection::@55::@61 server
struct connection::@58 compression
struct connection::@59 statistics
struct connection::@57 phs
QIODevice * sock
Definition: connection.h:129
bool observer
Definition: connection.h:138
struct packet_header packet_header
Definition: connection.h:132
char username[MAX_LEN_NAME]
Definition: connection.h:151
int bytes_send
Definition: connection.h:256
struct socket_packet_buffer * send_buffer
Definition: connection.h:145
struct byte_vector queue
Definition: connection.h:253
char capability[MAX_LEN_CAPSTR]
Definition: connection.h:158
int frozen_level
Definition: connection.h:251
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition: connection.h:166
struct genhash ** sent
Definition: connection.h:245
struct socket_packet_buffer * buffer
Definition: connection.h:144
QString addr
Definition: connection.h:152
Definition: player.h:231
unsigned long ndata
Definition: connection.h:108
unsigned long nsize
Definition: connection.h:110
unsigned char * data
Definition: connection.h:111
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
size_t fc_strlcpy(char *dest, const char *src, size_t n)
fc_strlcpy() provides utf-8 version of (non-standard) function strlcpy() It is intended as more user-...
Definition: support.cpp:412
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
int cat_snprintf(char *str, size_t n, const char *format,...)
cat_snprintf is like a combination of fc_snprintf and fc_strlcat; it does snprintf to the end of an e...
Definition: support.cpp:564
int fc_strncasequotecmp(const char *str0, const char *str1, size_t n)
Compare strings like strncasecmp() but ignoring surrounding quotes in either string.
Definition: support.cpp:209
size_t effectivestrlenquote(const char *str)
Count length of string without possible surrounding quotes.
Definition: support.cpp:189
#define sz_strlcpy(dest, src)
Definition: support.h:140
#define fc_strdup(str)
Definition: support.h:111
#define fc_realloc(ptr, sz)
Definition: support.h:59
#define fc_malloc(sz)
Definition: support.h:58
#define sz_strlcat(dest, src)
Definition: support.h:142
void timer_destroy(civtimer *t)
Deletes timer.
Definition: timing.cpp:66
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