Freeciv-3.3
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
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/************************************************************************/
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{
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;) {
176
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);
219 pc->last_write = timer_renew(pc->last_write, TIMER_USER, TIMER_ACTIVE,
220 pc->last_write != NULL ? NULL : "socket write");
221 timer_start(pc->last_write);
222 }
223
224 return 0;
225}
226
227/**********************************************************************/
231{
232 if (pc && pc->used && pc->send_buffer->ndata > 0) {
233 write_socket_data(pc, pc->send_buffer, 0);
234 if (pc->notify_of_writable_data) {
235 pc->notify_of_writable_data(pc, pc->send_buffer
236 && pc->send_buffer->ndata > 0);
237 }
238 }
239}
240
241/**********************************************************************/
244#ifndef FREECIV_JSON_CONNECTION
246{
247 if (pc && pc->used && pc->send_buffer->ndata >= MAX_LEN_PACKET) {
248 write_socket_data(pc, pc->send_buffer, MAX_LEN_PACKET-1);
249 if (pc->notify_of_writable_data) {
250 pc->notify_of_writable_data(pc, pc->send_buffer
251 && pc->send_buffer->ndata > 0);
252 }
253 }
254}
255#endif /* FREECIV_JSON_CONNECTION */
256
257/**********************************************************************/
261 const unsigned char *data, int len)
262{
264
265 if (NULL == pconn
266 || !pconn->used
267 || (is_server() && pconn->server.is_closing)) {
268 return TRUE;
269 }
270
271 buf = pconn->send_buffer;
272 log_debug("add %d bytes to %d (space =%d)", len, buf->ndata, buf->nsize);
274 connection_close(pconn, _("buffer overflow"));
275 return FALSE;
276 }
277
278 memcpy(buf->data + buf->ndata, data, len);
279 buf->ndata += len;
280
281 return TRUE;
282}
283
284/**********************************************************************/
288 const unsigned char *data, int len)
289{
290 if (NULL == pconn
291 || !pconn->used
292 || (is_server() && pconn->server.is_closing)) {
293 return TRUE;
294 }
295
296 pconn->statistics.bytes_send += len;
297
298#ifndef FREECIV_JSON_CONNECTION
299 if (0 < pconn->send_buffer->do_buffer_sends) {
302 log_verbose("cut connection %s due to huge send buffer (1)",
304 return FALSE;
305 }
307 } else
308#endif /* FREECIV_JSON_CONNECTION */
309 {
312 log_verbose("cut connection %s due to huge send buffer (2)",
314 return FALSE;
315 }
317 }
318 return TRUE;
319}
320
321/**********************************************************************/
325{
326 if (pc && pc->used) {
327 pc->send_buffer->do_buffer_sends++;
328 }
329}
330
331/**********************************************************************/
337{
338 if (NULL == pc || !pc->used || (is_server() && pc->server.is_closing)) {
339 return;
340 }
341
342 pc->send_buffer->do_buffer_sends--;
343 if (0 > pc->send_buffer->do_buffer_sends) {
344 log_error("Too many calls to unbuffer %s!", pc->username);
345 pc->send_buffer->do_buffer_sends = 0;
346 }
347
348 if (0 == pc->send_buffer->do_buffer_sends) {
350 }
351}
352
353/**********************************************************************/
362
363/**********************************************************************/
372
373/**********************************************************************/
378{
380 if (fc_strcasecmp(user_name, pconn->username) == 0) {
381 return pconn;
382 }
384
385 return NULL;
386}
387
388/**********************************************************************/
394static const char *connection_accessor(int i) {
396}
397
399 enum m_pre_result *result)
400{
401 int ind;
402
407
408 if (*result < M_PRE_AMBIGUOUS) {
410 } else {
411 return NULL;
412 }
413}
414
415/**********************************************************************/
422{
425 "Trying to look at the id of a non existing connection");
426
427 if (pconn->id == id) {
428 return pconn;
429 }
430 }
432
433 return NULL;
434}
435
436/**********************************************************************/
440{
442
443 buf = fc_malloc(sizeof(*buf));
444 buf->ndata = 0;
445 buf->do_buffer_sends = 0;
446 buf->nsize = 10*MAX_LEN_PACKET;
447 buf->data = (unsigned char *)fc_malloc(buf->nsize);
448
449 return buf;
450}
451
452/**********************************************************************/
456{
457 if (buf) {
458 if (buf->data) {
459 free(buf->data);
460 }
461 free(buf);
462 }
463}
464
465/**********************************************************************/
474const char *conn_description(const struct connection *pconn)
475{
476 static char buffer[MAX_LEN_NAME*2 + MAX_LEN_ADDR + 128];
477
478 buffer[0] = '\0';
479
480 if (*pconn->username != '\0') {
481 fc_snprintf(buffer, sizeof(buffer), _("%s from %s"),
482 pconn->username, pconn->addr);
483 } else {
484 sz_strlcpy(buffer, "server");
485 }
486 if (NULL != pconn->closing_reason) {
487 /* TRANS: Appending the reason why a connection has closed.
488 * Preserve leading space. */
489 cat_snprintf(buffer, sizeof(buffer), _(" (%s)"), pconn->closing_reason);
490 } else if (!pconn->established) {
491 /* TRANS: preserve leading space. */
492 sz_strlcat(buffer, _(" (connection incomplete)"));
493 return buffer;
494 }
495 if (NULL != pconn->playing) {
496 /* TRANS: preserve leading space. */
497 cat_snprintf(buffer, sizeof(buffer), _(" (player %s)"),
498 player_name(pconn->playing));
499 }
500 if (pconn->observer) {
501 /* TRANS: preserve leading space. */
502 sz_strlcat(buffer, _(" (observer)"));
503 }
504
505 return buffer;
506}
507
508/**********************************************************************/
511bool can_conn_edit(const struct connection *pconn)
512{
515 && (NULL != pconn->playing || pconn->observer));
516}
517
518/**********************************************************************/
522{
523 return pconn->access_level == ALLOW_HACK;
524}
525
526/**********************************************************************/
531{
532 int result = old_request_id + 1;
533
534 if ((result & 0xffff) == 0) {
535 log_packet("INFORMATION: request_id has wrapped around; "
536 "setting from %d to 2", result);
537 result = 2;
538 }
539 fc_assert(0 != result);
540
541 return result;
542}
543
544/**********************************************************************/
548{
549#ifdef USE_COMPRESSION
550 byte_vector_free(&pc->compression.queue);
551#endif /* USE_COMPRESSION */
552}
553
554/**********************************************************************/
557static void init_packet_hashes(struct connection *pc)
558{
559 enum packet_type i;
560
561 pc->phs.sent = fc_malloc(sizeof(*pc->phs.sent) * PACKET_LAST);
562 pc->phs.received = fc_malloc(sizeof(*pc->phs.received) * PACKET_LAST);
563 pc->phs.handlers = packet_handlers_initial();
564
565 for (i = 0; i < PACKET_LAST; i++) {
566 pc->phs.sent[i] = NULL;
567 pc->phs.received[i] = NULL;
568 }
569}
570
571/**********************************************************************/
574static void free_packet_hashes(struct connection *pc)
575{
576 int i;
577
578 if (pc->phs.sent) {
579 for (i = 0; i < PACKET_LAST; i++) {
580 if (pc->phs.sent[i] != NULL) {
581 genhash_destroy(pc->phs.sent[i]);
582 }
583 }
584 free(pc->phs.sent);
585 pc->phs.sent = NULL;
586 }
587
588 if (pc->phs.received) {
589 for (i = 0; i < PACKET_LAST; i++) {
590 if (pc->phs.received[i] != NULL) {
591 genhash_destroy(pc->phs.received[i]);
592 }
593 }
594 free(pc->phs.received);
595 pc->phs.received = NULL;
596 }
597}
598
599/**********************************************************************/
604{
605 pconn->established = FALSE;
606 pconn->used = TRUE;
607 packet_header_init(&pconn->packet_header);
608 pconn->closing_reason = NULL;
609 pconn->last_write = NULL;
611 pconn->send_buffer = new_socket_packet_buffer();
612 pconn->statistics.bytes_send = 0;
613#ifdef FREECIV_JSON_CONNECTION
614 pconn->json_mode = TRUE;
615#endif /* FREECIV_JSON_CONNECTION */
616
618
619#ifdef USE_COMPRESSION
620 byte_vector_init(&pconn->compression.queue);
621 pconn->compression.frozen_level = 0;
622#endif /* USE_COMPRESSION */
623
624 pconn->client_gui = GUI_STUB;
625}
626
627/**********************************************************************/
631{
632 if (!pconn->used) {
633 log_error("WARNING: Trying to close already closed connection");
634 } else {
635 fc_closesocket(pconn->sock);
636 pconn->used = FALSE;
637 pconn->established = FALSE;
638 if (NULL != pconn->closing_reason) {
639 free(pconn->closing_reason);
640 }
641
643 pconn->buffer = NULL;
644
645 free_socket_packet_buffer(pconn->send_buffer);
646 pconn->send_buffer = NULL;
647
648 if (pconn->last_write) {
649 timer_destroy(pconn->last_write);
650 pconn->last_write = NULL;
651 }
652
655 }
656}
657
658/**********************************************************************/
661void conn_set_capability(struct connection *pconn, const char *capability)
662{
663 fc_assert(strlen(capability) < sizeof(pconn->capability));
664
665 sz_strlcpy(pconn->capability, capability);
666 pconn->phs.handlers = packet_handlers_get(capability);
667}
668
669/**********************************************************************/
674{
675 int i;
676
677 for (i = 0; i < PACKET_LAST; i++) {
679 if (NULL != pc->phs.sent && NULL != pc->phs.sent[i]) {
680 genhash_clear(pc->phs.sent[i]);
681 }
682 if (NULL != pc->phs.received && NULL != pc->phs.received[i]) {
683 genhash_clear(pc->phs.received[i]);
684 }
685 }
686 }
687}
688
689/**********************************************************************/
695{
696#ifdef USE_COMPRESSION
697 if (0 == pconn->compression.frozen_level) {
698 byte_vector_reserve(&pconn->compression.queue, 0);
699 }
700 pconn->compression.frozen_level++;
701#endif /* USE_COMPRESSION */
702}
703
704/**********************************************************************/
709{
710#ifdef USE_COMPRESSION
711 return 0 < pconn->compression.frozen_level;
712#else /* USE_COMPRESSION */
713 return FALSE;
714#endif /* USE_COMPRESSION */
715}
716
717/**********************************************************************/
721{
722#ifdef USE_COMPRESSION
726#endif /* USE_COMPRESSION */
727}
728
729/**********************************************************************/
733{
734#ifdef USE_COMPRESSION
738#endif /* USE_COMPRESSION */
739}
740
741/**********************************************************************/
746{
747 return pconn && pconn->playing && !pconn->observer;
748}
749
750/**********************************************************************/
754{
755 return pconn && !pconn->playing && pconn->observer;
756}
757
758/**********************************************************************/
764{
765 if (!pconn) {
766 return NULL;
767 }
768 return pconn->playing;
769}
770
771/**********************************************************************/
776{
777 if (!pconn) {
778 return ALLOW_NONE; /* Would not want to give hack on error... */
779 }
780 return pconn->access_level;
781}
782
783
784/**************************************************************************
785 Connection patterns.
786**************************************************************************/
791
792/**********************************************************************/
796 const char *wildcard)
797{
798 struct conn_pattern *ppattern = fc_malloc(sizeof(*ppattern));
799
800 ppattern->type = type;
801 ppattern->wildcard = fc_strdup(wildcard);
802
803 return ppattern;
804}
805
806/**********************************************************************/
810{
812 free(ppattern->wildcard);
813 free(ppattern);
814}
815
816/**********************************************************************/
820 const struct connection *pconn)
821{
822 const char *test = NULL;
823
824 switch (ppattern->type) {
825 case CPT_USER:
826 test = pconn->username;
827 break;
828 case CPT_HOST:
829 test = pconn->addr;
830 break;
831 case CPT_IP:
832 if (is_server()) {
833 test = pconn->server.ipaddr;
834 }
835 break;
836 }
837
838 if (NULL != test) {
839 return wildcard_fit_string(ppattern->wildcard, test);
840 } else {
841 log_error("%s(): Invalid pattern type (%d)",
842 __FUNCTION__, ppattern->type);
843 return FALSE;
844 }
845}
846
847/**********************************************************************/
851 const struct connection *pconn)
852{
855 return TRUE;
856 }
858
859 return FALSE;
860}
861
862/**********************************************************************/
866 char *buf, size_t buf_len)
867{
868 return fc_snprintf(buf, buf_len, "<%s=%s>",
870 ppattern->wildcard);
871}
872
873/**********************************************************************/
879 enum conn_pattern_type prefer,
880 char *error_buf,
881 size_t error_buf_len)
882{
884 const char *p;
885
886 /* Determine pattern type. */
887 if ((p = strchr(pattern, '='))) {
888 /* Special character to separate the type of the pattern. */
889 const size_t pattern_type_len = ++p - pattern;
891
896 if (NULL != error_buf) {
898 _("\"%s\" is not a valid pattern type"),
900 }
901 return NULL;
902 }
903 } else {
904 /* Use 'prefer' type. */
905 p = pattern;
906 type = prefer;
908 if (NULL != error_buf) {
909 fc_strlcpy(error_buf, _("Missing pattern type"), error_buf_len);
910 }
911 return NULL;
912 }
913 }
914
915 /* Remove leading spaces. */
916 while (fc_isspace(*p)) {
917 p++;
918 }
919
920 if ('\0' == *p) {
921 if (NULL != error_buf) {
922 fc_strlcpy(error_buf, _("Missing pattern"), error_buf_len);
923 }
924 return NULL;
925 }
926
927 return conn_pattern_new(type, p);
928}
929
930/**********************************************************************/
934bool conn_is_valid(const struct connection *pconn)
935{
936 return (pconn && pconn->used && !pconn->server.is_closing);
937}
char user_name[512]
char * incite_cost
Definition comments.c:76
#define MAX_LEN_PACKET
Definition conn_types.h:29
#define MAX_LEN_BUFFER
Definition conn_types.h:34
size_t conn_pattern_to_string(const struct conn_pattern *ppattern, char *buf, size_t buf_len)
Definition connection.c:865
static conn_close_fn_t conn_close_callback
Definition connection.c:65
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
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:398
bool can_conn_edit(const struct connection *pconn)
Definition connection.c:511
struct connection * conn_by_user(const char *user_name)
Definition connection.c:377
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c:732
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:245
static const char * connection_accessor(int i)
Definition connection.c:394
void flush_connection_send_buffer_all(struct connection *pc)
Definition connection.c:230
int get_next_request_id(int old_request_id)
Definition connection.c:530
struct socket_packet_buffer * new_socket_packet_buffer(void)
Definition connection.c:439
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
bool can_conn_enable_editing(const struct connection *pconn)
Definition connection.c:521
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
static bool add_connection_data(struct connection *pconn, const unsigned char *data, int len)
Definition connection.c:260
bool conn_pattern_match(const struct conn_pattern *ppattern, const struct connection *pconn)
Definition connection.c:819
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:661
static void init_packet_hashes(struct connection *pc)
Definition connection.c:557
void conn_pattern_destroy(struct conn_pattern *ppattern)
Definition connection.c:809
void conn_reset_delta_state(struct connection *pc)
Definition connection.c:673
void connection_common_init(struct connection *pconn)
Definition connection.c:603
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:720
struct conn_pattern * conn_pattern_new(enum conn_pattern_type type, const char *wildcard)
Definition connection.c:795
bool conn_controls_player(const struct connection *pconn)
Definition connection.c:745
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
void connection_common_close(struct connection *pconn)
Definition connection.c:630
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:878
void conn_compression_freeze(struct connection *pconn)
Definition connection.c:694
static void free_packet_hashes(struct connection *pc)
Definition connection.c:574
static void free_socket_packet_buffer(struct socket_packet_buffer *buf)
Definition connection.c:455
struct connection * conn_by_number(int id)
Definition connection.c:421
void free_compression_queue(struct connection *pc)
Definition connection.c:547
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:287
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:775
bool conn_is_valid(const struct connection *pconn)
Definition connection.c:934
bool conn_compression_frozen(const struct connection *pconn)
Definition connection.c:708
bool conn_pattern_list_match(const struct conn_pattern_list *plist, const struct connection *pconn)
Definition connection.c:850
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
#define conn_pattern_list_iterate_end
Definition connection.h:338
void(* conn_close_fn_t)(struct connection *pconn)
Definition connection.h:281
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_pattern_list_iterate(plist, ppatern)
Definition connection.h:336
#define conn_list_iterate_end
Definition connection.h:110
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:61
void genhash_destroy(struct genhash *pgenhash)
Definition genhash.c:290
void genhash_clear(struct genhash *pgenhash)
Definition genhash.c:576
GType type
Definition repodlgs.c:1313
get_token_fn_t func
Definition inputfile.c:128
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_packet
Definition log.h:138
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#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:127
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool wildcard_fit_string(const char *pattern, const char *test)
Definition shared.c:2156
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:1583
void remove_leading_trailing_spaces(char *s)
Definition shared.c:444
#define MIN(x, y)
Definition shared.h:55
m_pre_result
Definition shared.h:213
@ M_PRE_AMBIGUOUS
Definition shared.h:216
#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:789
enum conn_pattern_type type
Definition connection.c:788
char username[MAX_LEN_NAME]
Definition connection.h:164
unsigned char * data
Definition connection.h:120
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
bool fc_isspace(char c)
Definition support.c:1240
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_strncasequotecmp(const char *str0, const char *str1, size_t n)
Definition support.c:377
size_t effectivestrlenquote(const char *str)
Definition support.c:356
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:180
@ TIMER_ACTIVE
Definition timing.h:46
@ TIMER_USER
Definition timing.h:42