Freeciv-3.1
Loading...
Searching...
No Matches
connection.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include "fc_prehdrs.h"
19
20#include <errno.h>
21#include <string.h>
22#include <time.h>
23
24#ifdef FREECIV_HAVE_SYS_TYPES_H
25#include <sys/types.h>
26#endif
27#ifdef HAVE_SYS_SELECT_H
28/* For some platforms this must be below sys/types.h. */
29#include <sys/select.h>
30#endif
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34
35/* utility */
36#include "fcintl.h"
37#include "genhash.h"
38#include "log.h"
39#include "mem.h"
40#include "netintf.h"
41#include "support.h" /* fc_str(n)casecmp */
42
43/* common */
44#include "game.h" /* game.all_connections */
45#include "packets.h"
46
47#include "connection.h"
48
49
50static void default_conn_close_callback(struct connection *pconn);
51
52/* String used for connection.addr and related cases to indicate
53 * blank/unknown/not-applicable address:
54 */
55const char blank_addr_str[] = "---.---.---.---";
56
57/****************************************************************************
58 This callback is used when an error occurs trying to write to the
59 connection. The effect of the callback should be to close the connection.
60 This is here so that the server and client can take appropriate
61 (different) actions: server lost a client, client lost connection to
62 server. Never attempt to call this function directly, call
63 connection_close() instead.
64****************************************************************************/
66
67/************************************************************************/
70static void default_conn_close_callback(struct connection *pconn)
71{
73 "Closing a socket (%s) before calling "
74 "close_socket_set_callback().", conn_description(pconn));
75}
76
77/**********************************************************************/
84
85/**********************************************************************/
88void connection_close(struct connection *pconn, const char *reason)
89{
90 fc_assert_ret(NULL != pconn);
91
92 if (NULL != reason && NULL == pconn->closing_reason) {
93 /* NB: we don't overwrite the original reason. */
94 pconn->closing_reason = fc_strdup(reason);
95 }
96
97 (*conn_close_callback) (pconn);
98}
99
100/**********************************************************************/
105 int extra_space)
106{
107 /* room for more? */
108 if (buf->nsize - buf->ndata < extra_space) {
109 buf->nsize = buf->ndata + extra_space;
110
111 /* added this check so we don't gobble up too much mem */
112 if (buf->nsize > MAX_LEN_BUFFER) {
113 return FALSE;
114 }
115 buf->data = (unsigned char *) fc_realloc(buf->data, buf->nsize);
116 }
117
118 return TRUE;
119}
120
121/**********************************************************************/
129int read_socket_data(int sock, struct socket_packet_buffer *buffer)
130{
131 int didget;
132
134 log_error("can't grow buffer");
135 return -1;
136 }
137
138 log_debug("try reading %d bytes", buffer->nsize - buffer->ndata);
139 didget = fc_readsocket(sock, (char *) (buffer->data + buffer->ndata),
140 buffer->nsize - buffer->ndata);
141
142 if (didget > 0) {
143 buffer->ndata += didget;
144 log_debug("didget:%d", didget);
145 return didget;
146 } else if (didget == 0) {
147 log_debug("EOF on socket read");
148 return -2;
149 }
150
151#ifdef NONBLOCKING_SOCKETS
152 else if (errno == EWOULDBLOCK || errno == EAGAIN) {
153 log_debug("EGAIN on socket read");
154 return 0;
155 }
156#endif /* NONBLOCKING_SOCKETS */
157
158 return -1;
159}
160
161/**********************************************************************/
164static int write_socket_data(struct connection *pc,
165 struct socket_packet_buffer *buf, int limit)
166{
167 int start, nput, nblock;
168
169 if (is_server() && pc->server.is_closing) {
170 return 0;
171 }
172
173 for (start = 0; buf->ndata-start > limit;) {
174 fd_set writefs, exceptfs;
175 fc_timeval tv;
176
177 FC_FD_ZERO(&writefs);
178 FC_FD_ZERO(&exceptfs);
179 FD_SET(pc->sock, &writefs);
180 FD_SET(pc->sock, &exceptfs);
181
182 tv.tv_sec = 0; tv.tv_usec = 0;
183
184 if (fc_select(pc->sock + 1, NULL, &writefs, &exceptfs, &tv) <= 0) {
185 if (errno != EINTR) {
186 break;
187 } else {
188 /* EINTR can happen sometimes, especially when compiling with -pg.
189 * Generally we just want to run select again. */
190 continue;
191 }
192 }
193
194 if (FD_ISSET(pc->sock, &exceptfs)) {
195 connection_close(pc, _("network exception"));
196 return -1;
197 }
198
199 if (FD_ISSET(pc->sock, &writefs)) {
200 nblock=MIN(buf->ndata-start, MAX_LEN_PACKET);
201 log_debug("trying to write %d limit=%d", nblock, limit);
202 if ((nput = fc_writesocket(pc->sock,
203 (const char *)buf->data+start, nblock)) == -1) {
204#ifdef NONBLOCKING_SOCKETS
205 if (errno == EWOULDBLOCK || errno == EAGAIN) {
206 break;
207 }
208#endif /* NONBLOCKING_SOCKETS */
209 connection_close(pc, _("lagging connection"));
210 return -1;
211 }
212 start += nput;
213 }
214 }
215
216 if (start > 0) {
217 buf->ndata -= start;
218 memmove(buf->data, buf->data+start, buf->ndata);
221 }
222
223 return 0;
224}
225
226/**********************************************************************/
230{
231 if (pc && pc->used && pc->send_buffer->ndata > 0) {
232 write_socket_data(pc, pc->send_buffer, 0);
233 if (pc->notify_of_writable_data) {
235 && pc->send_buffer->ndata > 0);
236 }
237 }
238}
239
240/**********************************************************************/
243#ifndef FREECIV_JSON_CONNECTION
245{
246 if (pc && pc->used && pc->send_buffer->ndata >= MAX_LEN_PACKET) {
248 if (pc->notify_of_writable_data) {
250 && pc->send_buffer->ndata > 0);
251 }
252 }
253}
254#endif /* FREECIV_JSON_CONNECTION */
255
256/**********************************************************************/
259static bool add_connection_data(struct connection *pconn,
260 const unsigned char *data, int len)
261{
262 struct socket_packet_buffer *buf;
263
264 if (NULL == pconn
265 || !pconn->used
266 || (is_server() && pconn->server.is_closing)) {
267 return TRUE;
268 }
269
270 buf = pconn->send_buffer;
271 log_debug("add %d bytes to %d (space =%d)", len, buf->ndata, buf->nsize);
273 connection_close(pconn, _("buffer overflow"));
274 return FALSE;
275 }
276
277 memcpy(buf->data + buf->ndata, data, len);
278 buf->ndata += len;
279
280 return TRUE;
281}
282
283/**********************************************************************/
287 const unsigned char *data, int len)
288{
289 if (NULL == pconn
290 || !pconn->used
291 || (is_server() && pconn->server.is_closing)) {
292 return TRUE;
293 }
294
295 pconn->statistics.bytes_send += len;
296
297#ifndef FREECIV_JSON_CONNECTION
298 if (0 < pconn->send_buffer->do_buffer_sends) {
300 if (!add_connection_data(pconn, data, len)) {
301 log_verbose("cut connection %s due to huge send buffer (1)",
302 conn_description(pconn));
303 return FALSE;
304 }
306 } else
307#endif /* FREECIV_JSON_CONNECTION */
308 {
310 if (!add_connection_data(pconn, data, len)) {
311 log_verbose("cut connection %s due to huge send buffer (2)",
312 conn_description(pconn));
313 return FALSE;
314 }
316 }
317 return TRUE;
318}
319
320/**********************************************************************/
324{
325 if (pc && pc->used) {
327 }
328}
329
330/**********************************************************************/
336{
337 if (NULL == pc || !pc->used || (is_server() && pc->server.is_closing)) {
338 return;
339 }
340
342 if (0 > pc->send_buffer->do_buffer_sends) {
343 log_error("Too many calls to unbuffer %s!", pc->username);
345 }
346
347 if (0 == pc->send_buffer->do_buffer_sends) {
349 }
350}
351
352/**********************************************************************/
355void conn_list_do_buffer(struct conn_list *dest)
356{
357 conn_list_iterate(dest, pconn) {
360}
361
362/**********************************************************************/
365void conn_list_do_unbuffer(struct conn_list *dest)
366{
367 conn_list_iterate(dest, pconn) {
370}
371
372/**********************************************************************/
377{
379 if (fc_strcasecmp(user_name, pconn->username) == 0) {
380 return pconn;
381 }
383
384 return NULL;
385}
386
387/**********************************************************************/
393static const char *connection_accessor(int i) {
394 return conn_list_get(game.all_connections, i)->username;
395}
396
398 enum m_pre_result *result)
399{
400 int ind;
401
403 conn_list_size(game.all_connections),
406
407 if (*result < M_PRE_AMBIGUOUS) {
408 return conn_list_get(game.all_connections, ind);
409 } else {
410 return NULL;
411 }
412}
413
414/**********************************************************************/
421{
423 fc_assert_msg(pconn != NULL,
424 "Trying to look at the id of a non existing connection");
425
426 if (pconn->id == id) {
427 return pconn;
428 }
429 }
431
432 return NULL;
433}
434
435/**********************************************************************/
439{
440 struct socket_packet_buffer *buf;
441
442 buf = fc_malloc(sizeof(*buf));
443 buf->ndata = 0;
444 buf->do_buffer_sends = 0;
445 buf->nsize = 10*MAX_LEN_PACKET;
446 buf->data = (unsigned char *)fc_malloc(buf->nsize);
447
448 return buf;
449}
450
451/**********************************************************************/
455{
456 if (buf) {
457 if (buf->data) {
458 free(buf->data);
459 }
460 free(buf);
461 }
462}
463
464/**********************************************************************/
473const char *conn_description(const struct connection *pconn)
474{
475 static char buffer[MAX_LEN_NAME*2 + MAX_LEN_ADDR + 128];
476
477 buffer[0] = '\0';
478
479 if (*pconn->username != '\0') {
480 fc_snprintf(buffer, sizeof(buffer), _("%s from %s"),
481 pconn->username, pconn->addr);
482 } else {
483 sz_strlcpy(buffer, "server");
484 }
485 if (NULL != pconn->closing_reason) {
486 /* TRANS: Appending the reason why a connection has closed.
487 * Preserve leading space. */
488 cat_snprintf(buffer, sizeof(buffer), _(" (%s)"), pconn->closing_reason);
489 } else if (!pconn->established) {
490 /* TRANS: preserve leading space. */
491 sz_strlcat(buffer, _(" (connection incomplete)"));
492 return buffer;
493 }
494 if (NULL != pconn->playing) {
495 /* TRANS: preserve leading space. */
496 cat_snprintf(buffer, sizeof(buffer), _(" (player %s)"),
497 player_name(pconn->playing));
498 }
499 if (pconn->observer) {
500 /* TRANS: preserve leading space. */
501 sz_strlcat(buffer, _(" (observer)"));
502 }
503
504 return buffer;
505}
506
507/**********************************************************************/
510bool can_conn_edit(const struct connection *pconn)
511{
512 return (can_conn_enable_editing(pconn)
514 && (NULL != pconn->playing || pconn->observer));
515}
516
517/**********************************************************************/
520bool can_conn_enable_editing(const struct connection *pconn)
521{
522 return pconn->access_level == ALLOW_HACK;
523}
524
525/**********************************************************************/
529int get_next_request_id(int old_request_id)
530{
531 int result = old_request_id + 1;
532
533 if ((result & 0xffff) == 0) {
534 log_packet("INFORMATION: request_id has wrapped around; "
535 "setting from %d to 2", result);
536 result = 2;
537 }
538 fc_assert(0 != result);
539
540 return result;
541}
542
543/**********************************************************************/
547{
548#ifdef USE_COMPRESSION
549 byte_vector_free(&pc->compression.queue);
550#endif /* USE_COMPRESSION */
551}
552
553/**********************************************************************/
556static void init_packet_hashes(struct connection *pc)
557{
558 enum packet_type i;
559
560 pc->phs.sent = fc_malloc(sizeof(*pc->phs.sent) * PACKET_LAST);
561 pc->phs.received = fc_malloc(sizeof(*pc->phs.received) * PACKET_LAST);
563
564 for (i = 0; i < PACKET_LAST; i++) {
565 pc->phs.sent[i] = NULL;
566 pc->phs.received[i] = NULL;
567 }
568}
569
570/**********************************************************************/
573static void free_packet_hashes(struct connection *pc)
574{
575 int i;
576
577 if (pc->phs.sent) {
578 for (i = 0; i < PACKET_LAST; i++) {
579 if (pc->phs.sent[i] != NULL) {
580 genhash_destroy(pc->phs.sent[i]);
581 }
582 }
583 free(pc->phs.sent);
584 pc->phs.sent = NULL;
585 }
586
587 if (pc->phs.received) {
588 for (i = 0; i < PACKET_LAST; i++) {
589 if (pc->phs.received[i] != NULL) {
591 }
592 }
593 free(pc->phs.received);
594 pc->phs.received = NULL;
595 }
596}
597
598/**********************************************************************/
603{
604 pconn->established = FALSE;
605 pconn->used = TRUE;
607 pconn->closing_reason = NULL;
608 pconn->last_write = NULL;
611 pconn->statistics.bytes_send = 0;
612#ifdef FREECIV_JSON_CONNECTION
613 pconn->json_mode = TRUE;
614#endif /* FREECIV_JSON_CONNECTION */
615
616 init_packet_hashes(pconn);
617
618#ifdef USE_COMPRESSION
619 byte_vector_init(&pconn->compression.queue);
620 pconn->compression.frozen_level = 0;
621#endif /* USE_COMPRESSION */
622}
623
624/**********************************************************************/
628{
629 if (!pconn->used) {
630 log_error("WARNING: Trying to close already closed connection");
631 } else {
632 fc_closesocket(pconn->sock);
633 pconn->used = FALSE;
634 pconn->established = FALSE;
635 if (NULL != pconn->closing_reason) {
636 free(pconn->closing_reason);
637 }
638
640 pconn->buffer = NULL;
641
643 pconn->send_buffer = NULL;
644
645 if (pconn->last_write) {
647 pconn->last_write = NULL;
648 }
649
651 free_packet_hashes(pconn);
652 }
653}
654
655/**********************************************************************/
658void conn_set_capability(struct connection *pconn, const char *capability)
659{
660 fc_assert(strlen(capability) < sizeof(pconn->capability));
661
662 sz_strlcpy(pconn->capability, capability);
663 pconn->phs.handlers = packet_handlers_get(capability);
664}
665
666/**********************************************************************/
671{
672 int i;
673
674 for (i = 0; i < PACKET_LAST; i++) {
676 if (NULL != pc->phs.sent && NULL != pc->phs.sent[i]) {
677 genhash_clear(pc->phs.sent[i]);
678 }
679 if (NULL != pc->phs.received && NULL != pc->phs.received[i]) {
680 genhash_clear(pc->phs.received[i]);
681 }
682 }
683 }
684}
685
686/**********************************************************************/
692{
693#ifdef USE_COMPRESSION
694 if (0 == pconn->compression.frozen_level) {
695 byte_vector_reserve(&pconn->compression.queue, 0);
696 }
697 pconn->compression.frozen_level++;
698#endif /* USE_COMPRESSION */
699}
700
701/**********************************************************************/
705bool conn_compression_frozen(const struct connection *pconn)
706{
707#ifdef USE_COMPRESSION
708 return 0 < pconn->compression.frozen_level;
709#else /* USE_COMPRESSION */
710 return FALSE;
711#endif /* USE_COMPRESSION */
712}
713
714/**********************************************************************/
717void conn_list_compression_freeze(const struct conn_list *pconn_list)
718{
719#ifdef USE_COMPRESSION
720 conn_list_iterate(pconn_list, pconn) {
723#endif /* USE_COMPRESSION */
724}
725
726/**********************************************************************/
729void conn_list_compression_thaw(const struct conn_list *pconn_list)
730{
731#ifdef USE_COMPRESSION
732 conn_list_iterate(pconn_list, pconn) {
735#endif /* USE_COMPRESSION */
736}
737
738/**********************************************************************/
742bool conn_controls_player(const struct connection *pconn)
743{
744 return pconn && pconn->playing && !pconn->observer;
745}
746
747/**********************************************************************/
750bool conn_is_global_observer(const struct connection *pconn)
751{
752 return pconn && !pconn->playing && pconn->observer;
753}
754
755/**********************************************************************/
760struct player *conn_get_player(const struct connection *pconn)
761{
762 if (!pconn) {
763 return NULL;
764 }
765 return pconn->playing;
766}
767
768/**********************************************************************/
772enum cmdlevel conn_get_access(const struct connection *pconn)
773{
774 if (!pconn) {
775 return ALLOW_NONE; /* Would not want to give hack on error... */
776 }
777 return pconn->access_level;
778}
779
780
781/**************************************************************************
782 Connection patterns.
783**************************************************************************/
785 enum conn_pattern_type type;
786 char *wildcard;
787};
788
789/**********************************************************************/
792struct conn_pattern *conn_pattern_new(enum conn_pattern_type type,
793 const char *wildcard)
794{
795 struct conn_pattern *ppattern = fc_malloc(sizeof(*ppattern));
796
797 ppattern->type = type;
798 ppattern->wildcard = fc_strdup(wildcard);
799
800 return ppattern;
801}
802
803/**********************************************************************/
806void conn_pattern_destroy(struct conn_pattern *ppattern)
807{
808 fc_assert_ret(NULL != ppattern);
809 free(ppattern->wildcard);
810 free(ppattern);
811}
812
813/**********************************************************************/
816bool conn_pattern_match(const struct conn_pattern *ppattern,
817 const struct connection *pconn)
818{
819 const char *test = NULL;
820
821 switch (ppattern->type) {
822 case CPT_USER:
823 test = pconn->username;
824 break;
825 case CPT_HOST:
826 test = pconn->addr;
827 break;
828 case CPT_IP:
829 if (is_server()) {
830 test = pconn->server.ipaddr;
831 }
832 break;
833 }
834
835 if (NULL != test) {
836 return wildcard_fit_string(ppattern->wildcard, test);
837 } else {
838 log_error("%s(): Invalid pattern type (%d)",
839 __FUNCTION__, ppattern->type);
840 return FALSE;
841 }
842}
843
844/**********************************************************************/
847bool conn_pattern_list_match(const struct conn_pattern_list *plist,
848 const struct connection *pconn)
849{
850 conn_pattern_list_iterate(plist, ppattern) {
851 if (conn_pattern_match(ppattern, pconn)) {
852 return TRUE;
853 }
855
856 return FALSE;
857}
858
859/**********************************************************************/
862size_t conn_pattern_to_string(const struct conn_pattern *ppattern,
863 char *buf, size_t buf_len)
864{
865 return fc_snprintf(buf, buf_len, "<%s=%s>",
866 conn_pattern_type_name(ppattern->type),
867 ppattern->wildcard);
868}
869
870/**********************************************************************/
875struct conn_pattern *conn_pattern_from_string(const char *pattern,
876 enum conn_pattern_type prefer,
877 char *error_buf,
878 size_t error_buf_len)
879{
880 enum conn_pattern_type type;
881 const char *p;
882
883 /* Determine pattern type. */
884 if ((p = strchr(pattern, '='))) {
885 /* Special character to separate the type of the pattern. */
886 const size_t pattern_type_len = ++p - pattern;
887 char pattern_type[pattern_type_len];
888
889 fc_strlcpy(pattern_type, pattern, pattern_type_len);
890 remove_leading_trailing_spaces(pattern_type);
891 type = conn_pattern_type_by_name(pattern_type, fc_strcasecmp);
892 if (!conn_pattern_type_is_valid(type)) {
893 if (NULL != error_buf) {
894 fc_snprintf(error_buf, error_buf_len,
895 _("\"%s\" is not a valid pattern type"),
896 pattern_type);
897 }
898 return NULL;
899 }
900 } else {
901 /* Use 'prefer' type. */
902 p = pattern;
903 type = prefer;
904 if (!conn_pattern_type_is_valid(type)) {
905 if (NULL != error_buf) {
906 fc_strlcpy(error_buf, _("Missing pattern type"), error_buf_len);
907 }
908 return NULL;
909 }
910 }
911
912 /* Remove leading spaces. */
913 while (fc_isspace(*p)) {
914 p++;
915 }
916
917 if ('\0' == *p) {
918 if (NULL != error_buf) {
919 fc_strlcpy(error_buf, _("Missing pattern"), error_buf_len);
920 }
921 return NULL;
922 }
923
924 return conn_pattern_new(type, p);
925}
926
927/**********************************************************************/
931bool conn_is_valid(const struct connection *pconn)
932{
933 return (pconn && pconn->used && !pconn->server.is_closing);
934}
char user_name[512]
size_t conn_pattern_to_string(const struct conn_pattern *ppattern, char *buf, size_t buf_len)
Definition connection.c:862
static conn_close_fn_t conn_close_callback
Definition connection.c:65
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:365
static void default_conn_close_callback(struct connection *pconn)
Definition connection.c:70
struct connection * conn_by_user_prefix(const char *user_name, enum m_pre_result *result)
Definition connection.c:397
bool can_conn_edit(const struct connection *pconn)
Definition connection.c:510
struct connection * conn_by_user(const char *user_name)
Definition connection.c:376
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c:729
void connections_set_close_callback(conn_close_fn_t func)
Definition connection.c:80
static void flush_connection_send_buffer_packets(struct connection *pc)
Definition connection.c:244
static const char * connection_accessor(int i)
Definition connection.c:393
void flush_connection_send_buffer_all(struct connection *pc)
Definition connection.c:229
int get_next_request_id(int old_request_id)
Definition connection.c:529
struct socket_packet_buffer * new_socket_packet_buffer(void)
Definition connection.c:438
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:355
bool can_conn_enable_editing(const struct connection *pconn)
Definition connection.c:520
void connection_do_buffer(struct connection *pc)
Definition connection.c:323
static bool add_connection_data(struct connection *pconn, const unsigned char *data, int len)
Definition connection.c:259
bool conn_pattern_match(const struct conn_pattern *ppattern, const struct connection *pconn)
Definition connection.c:816
static bool buffer_ensure_free_extra_space(struct socket_packet_buffer *buf, int extra_space)
Definition connection.c:104
void conn_set_capability(struct connection *pconn, const char *capability)
Definition connection.c:658
static void init_packet_hashes(struct connection *pc)
Definition connection.c:556
void conn_pattern_destroy(struct conn_pattern *ppattern)
Definition connection.c:806
void conn_reset_delta_state(struct connection *pc)
Definition connection.c:670
void connection_common_init(struct connection *pconn)
Definition connection.c:602
void connection_close(struct connection *pconn, const char *reason)
Definition connection.c:88
void conn_list_compression_freeze(const struct conn_list *pconn_list)
Definition connection.c:717
struct conn_pattern * conn_pattern_new(enum conn_pattern_type type, const char *wildcard)
Definition connection.c:792
bool conn_controls_player(const struct connection *pconn)
Definition connection.c:742
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:750
const char * conn_description(const struct connection *pconn)
Definition connection.c:473
void connection_common_close(struct connection *pconn)
Definition connection.c:627
struct conn_pattern * conn_pattern_from_string(const char *pattern, enum conn_pattern_type prefer, char *error_buf, size_t error_buf_len)
Definition connection.c:875
void conn_compression_freeze(struct connection *pconn)
Definition connection.c:691
static void free_packet_hashes(struct connection *pc)
Definition connection.c:573
static void free_socket_packet_buffer(struct socket_packet_buffer *buf)
Definition connection.c:454
struct connection * conn_by_number(int id)
Definition connection.c:420
void free_compression_queue(struct connection *pc)
Definition connection.c:546
const char blank_addr_str[]
Definition connection.c:55
int read_socket_data(int sock, struct socket_packet_buffer *buffer)
Definition connection.c:129
bool connection_send_data(struct connection *pconn, const unsigned char *data, int len)
Definition connection.c:286
static int write_socket_data(struct connection *pc, struct socket_packet_buffer *buf, int limit)
Definition connection.c:164
enum cmdlevel conn_get_access(const struct connection *pconn)
Definition connection.c:772
bool conn_is_valid(const struct connection *pconn)
Definition connection.c:931
bool conn_compression_frozen(const struct connection *pconn)
Definition connection.c:705
bool conn_pattern_list_match(const struct conn_pattern_list *plist, const struct connection *pconn)
Definition connection.c:847
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:335
#define conn_pattern_list_iterate_end
Definition connection.h:340
void(* conn_close_fn_t)(struct connection *pconn)
Definition connection.h:283
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
#define MAX_LEN_PACKET
Definition connection.h:56
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define MAX_LEN_BUFFER
Definition connection.h:61
#define conn_pattern_list_iterate(plist, ppatern)
Definition connection.h:338
#define conn_list_iterate_end
Definition connection.h:115
static bool is_server(void)
#define MAX_LEN_NAME
Definition fc_types.h:66
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:57
void genhash_destroy(struct genhash *pgenhash)
Definition genhash.c:293
void genhash_clear(struct genhash *pgenhash)
Definition genhash.c:582
GType type
Definition repodlgs.c:1312
get_token_fn_t func
Definition inputfile.c:128
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_packet
Definition log.h:137
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#define fc_strdup(str)
Definition mem.h:43
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
void fc_closesocket(int sock)
Definition netintf.c:186
int fc_readsocket(int sock, void *buf, size_t size)
Definition netintf.c:144
int fc_writesocket(int sock, const void *buf, size_t size)
Definition netintf.c:163
int fc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fc_timeval *timeout)
Definition netintf.c:125
struct timeval fc_timeval
Definition netintf.h:90
#define FC_FD_ZERO(p)
Definition netintf.h:57
void packet_header_init(struct packet_header *packet_header)
Definition packets.c:617
const struct packet_handlers * packet_handlers_initial(void)
Definition packets.c:823
const struct packet_handlers * packet_handlers_get(const char *capability)
Definition packets.c:840
bool packet_has_game_info_flag(enum packet_type type)
packet_type
@ PACKET_LAST
int len
Definition packhand.c:125
const char * player_name(const struct player *pplayer)
Definition player.c:886
bool wildcard_fit_string(const char *pattern, const char *test)
Definition shared.c:2144
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)
Definition shared.c:1581
void remove_leading_trailing_spaces(char *s)
Definition shared.c:443
#define MIN(x, y)
Definition shared.h:55
m_pre_result
Definition shared.h:207
@ M_PRE_AMBIGUOUS
Definition shared.h:210
#define MAX_LEN_ADDR
Definition shared.h:31
struct packet_game_info info
Definition game.h:89
struct conn_list * all_connections
Definition game.h:96
char * wildcard
Definition connection.c:786
enum conn_pattern_type type
Definition connection.c:785
struct genhash ** received
Definition connection.h:266
bool established
Definition connection.h:145
struct connection::@61 statistics
struct player * playing
Definition connection.h:156
char * closing_reason
Definition connection.h:147
enum cmdlevel access_level
Definition connection.h:182
const struct packet_handlers * handlers
Definition connection.h:267
bool is_closing
Definition connection.h:236
struct connection::@59 phs
bool observer
Definition connection.h:152
struct packet_header packet_header
Definition connection.h:146
char username[MAX_LEN_NAME]
Definition connection.h:169
struct connection::@57::@63 server
struct timer * last_write
Definition connection.h:160
struct connection::@60 compression
char ipaddr[MAX_LEN_ADDR]
Definition connection.h:226
struct socket_packet_buffer * send_buffer
Definition connection.h:159
struct byte_vector queue
Definition connection.h:274
char capability[MAX_LEN_CAPSTR]
Definition connection.h:176
int frozen_level
Definition connection.h:272
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition connection.h:186
char addr[MAX_LEN_ADDR]
Definition connection.h:170
struct genhash ** sent
Definition connection.h:265
struct socket_packet_buffer * buffer
Definition connection.h:158
unsigned char * data
Definition connection.h:125
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
bool fc_isspace(char c)
Definition support.c:1249
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
int fc_strncasequotecmp(const char *str0, const char *str1, size_t n)
Definition support.c:379
size_t effectivestrlenquote(const char *str)
Definition support.c:359
#define sz_strlcpy(dest, src)
Definition support.h:167
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:168
void timer_destroy(struct timer *t)
Definition timing.c:191
void timer_start(struct timer *t)
Definition timing.c:224
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use)
Definition timing.c:176
@ TIMER_ACTIVE
Definition timing.h:45
@ TIMER_USER
Definition timing.h:41