Freeciv-3.4
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{
90 fc_assert_ret(pconn != nullptr);
91
92 if (reason != nullptr && pconn->closing_reason == nullptr) {
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, nullptr, &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 != nullptr
221 ? nullptr : "socket write");
222 timer_start(pc->last_write);
223 }
224
225 return 0;
226}
227
228/**********************************************************************/
232{
233 if (pc && pc->used && pc->send_buffer->ndata > 0) {
234 write_socket_data(pc, pc->send_buffer, 0);
235 if (pc->notify_of_writable_data) {
236 pc->notify_of_writable_data(pc, pc->send_buffer
237 && pc->send_buffer->ndata > 0);
238 }
239 }
240}
241
242/**********************************************************************/
245#ifndef FREECIV_JSON_CONNECTION
247{
248 if (pc && pc->used && pc->send_buffer->ndata >= MAX_LEN_PACKET) {
249 write_socket_data(pc, pc->send_buffer, MAX_LEN_PACKET-1);
250 if (pc->notify_of_writable_data) {
251 pc->notify_of_writable_data(pc, pc->send_buffer
252 && pc->send_buffer->ndata > 0);
253 }
254 }
255}
256#endif /* FREECIV_JSON_CONNECTION */
257
258/**********************************************************************/
262 const unsigned char *data, int len)
263{
265
266 if (pconn == nullptr
267 || !pconn->used
268 || (is_server() && pconn->server.is_closing)) {
269 return TRUE;
270 }
271
272 buf = pconn->send_buffer;
273 log_debug("add %d bytes to %d (space =%d)", len, buf->ndata, buf->nsize);
275 connection_close(pconn, _("buffer overflow"));
276 return FALSE;
277 }
278
279 memcpy(buf->data + buf->ndata, data, len);
280 buf->ndata += len;
281
282 return TRUE;
283}
284
285/**********************************************************************/
289 const unsigned char *data, int len)
290{
291 if (pconn == nullptr
292 || !pconn->used
293 || (is_server() && pconn->server.is_closing)) {
294 return TRUE;
295 }
296
297 pconn->statistics.bytes_send += len;
298
299#ifndef FREECIV_JSON_CONNECTION
300 if (0 < pconn->send_buffer->do_buffer_sends) {
303 log_verbose("cut connection %s due to huge send buffer (1)",
305 return FALSE;
306 }
308 } else
309#endif /* FREECIV_JSON_CONNECTION */
310 {
313 log_verbose("cut connection %s due to huge send buffer (2)",
315 return FALSE;
316 }
318 }
319 return TRUE;
320}
321
322/**********************************************************************/
326{
327 if (pc && pc->used) {
328 pc->send_buffer->do_buffer_sends++;
329 }
330}
331
332/**********************************************************************/
338{
339 if (pc == nullptr || !pc->used
340 || (is_server() && pc->server.is_closing)) {
341 return;
342 }
343
344 pc->send_buffer->do_buffer_sends--;
345 if (0 > pc->send_buffer->do_buffer_sends) {
346 log_error("Too many calls to unbuffer %s!", pc->username);
347 pc->send_buffer->do_buffer_sends = 0;
348 }
349
350 if (0 == pc->send_buffer->do_buffer_sends) {
352 }
353}
354
355/**********************************************************************/
364
365/**********************************************************************/
374
375/**********************************************************************/
380{
382 if (fc_strcasecmp(user_name, pconn->username) == 0) {
383 return pconn;
384 }
386
387 return nullptr;
388}
389
390/**********************************************************************/
396static const char *connection_accessor(int i) {
398}
399
401 enum m_pre_result *result)
402{
403 int ind;
404
409
410 if (*result < M_PRE_AMBIGUOUS) {
412 } else {
413 return nullptr;
414 }
415}
416
417/**********************************************************************/
424{
426 fc_assert_msg(pconn != nullptr,
427 "Trying to look at the id of a non existing connection");
428
429 if (pconn->id == id) {
430 return pconn;
431 }
432 }
434
435 return nullptr;
436}
437
438/**********************************************************************/
442{
444
445 buf = fc_malloc(sizeof(*buf));
446 buf->ndata = 0;
447 buf->do_buffer_sends = 0;
448 buf->nsize = 10*MAX_LEN_PACKET;
449 buf->data = (unsigned char *)fc_malloc(buf->nsize);
450
451 return buf;
452}
453
454/**********************************************************************/
458{
459 if (buf) {
460 if (buf->data) {
461 free(buf->data);
462 }
463 free(buf);
464 }
465}
466
467/**********************************************************************/
476const char *conn_description(const struct connection *pconn)
477{
478 static char buffer[MAX_LEN_NAME*2 + MAX_LEN_ADDR + 128];
479
480 buffer[0] = '\0';
481
482 if (*pconn->username != '\0') {
483 fc_snprintf(buffer, sizeof(buffer), _("%s from %s"),
484 pconn->username, pconn->addr);
485 } else {
486 sz_strlcpy(buffer, "server");
487 }
488 if (pconn->closing_reason != nullptr) {
489 /* TRANS: Appending the reason why a connection has closed.
490 * Preserve leading space. */
491 cat_snprintf(buffer, sizeof(buffer), _(" (%s)"), pconn->closing_reason);
492 } else if (!pconn->established) {
493 /* TRANS: Preserve leading space. */
494 sz_strlcat(buffer, _(" (connection incomplete)"));
495 return buffer;
496 }
497 if (pconn->playing != nullptr) {
498 /* TRANS: Preserve leading space. */
499 cat_snprintf(buffer, sizeof(buffer), _(" (player %s)"),
500 player_name(pconn->playing));
501 }
502 if (pconn->observer) {
503 /* TRANS: Preserve leading space. */
504 sz_strlcat(buffer, _(" (observer)"));
505 }
506
507 return buffer;
508}
509
510/**********************************************************************/
513bool can_conn_edit(const struct connection *pconn)
514{
517 && (pconn->playing != nullptr || pconn->observer));
518}
519
520/**********************************************************************/
524{
525 return pconn->access_level == ALLOW_HACK;
526}
527
528/**********************************************************************/
533{
534 int result = old_request_id + 1;
535
536 if ((result & 0xffff) == 0) {
537 log_packet("INFORMATION: request_id has wrapped around; "
538 "setting from %d to 2", result);
539 result = 2;
540 }
541 fc_assert(0 != result);
542
543 return result;
544}
545
546/**********************************************************************/
550{
551#ifdef USE_COMPRESSION
552 byte_vector_free(&pc->compression.queue);
553#endif /* USE_COMPRESSION */
554}
555
556/**********************************************************************/
559static void init_packet_hashes(struct connection *pc)
560{
561 enum packet_type i;
562
563 pc->phs.sent = fc_malloc(sizeof(*pc->phs.sent) * PACKET_LAST);
564 pc->phs.received = fc_malloc(sizeof(*pc->phs.received) * PACKET_LAST);
565 pc->phs.handlers = packet_handlers_initial();
566
567 for (i = 0; i < PACKET_LAST; i++) {
568 pc->phs.sent[i] = nullptr;
569 pc->phs.received[i] = nullptr;
570 }
571}
572
573/**********************************************************************/
576static void free_packet_hashes(struct connection *pc)
577{
578 int i;
579
580 if (pc->phs.sent) {
581 for (i = 0; i < PACKET_LAST; i++) {
582 if (pc->phs.sent[i] != nullptr) {
583 genhash_destroy(pc->phs.sent[i]);
584 }
585 }
586 free(pc->phs.sent);
587 pc->phs.sent = nullptr;
588 }
589
590 if (pc->phs.received) {
591 for (i = 0; i < PACKET_LAST; i++) {
592 if (pc->phs.received[i] != nullptr) {
593 genhash_destroy(pc->phs.received[i]);
594 }
595 }
596 free(pc->phs.received);
597 pc->phs.received = nullptr;
598 }
599}
600
601/**********************************************************************/
606{
607 pconn->established = FALSE;
608 pconn->used = TRUE;
609 packet_header_init(&pconn->packet_header);
610 pconn->closing_reason = nullptr;
611 pconn->last_write = nullptr;
613 pconn->send_buffer = new_socket_packet_buffer();
614 pconn->statistics.bytes_send = 0;
615#ifdef FREECIV_JSON_CONNECTION
616 pconn->json_mode = TRUE;
617#endif /* FREECIV_JSON_CONNECTION */
618
620
621#ifdef USE_COMPRESSION
622 byte_vector_init(&pconn->compression.queue);
623 pconn->compression.frozen_level = 0;
624#endif /* USE_COMPRESSION */
625
626 pconn->client_gui = GUI_STUB;
627}
628
629/**********************************************************************/
633{
634 if (!pconn->used) {
635 log_error("WARNING: Trying to close already closed connection");
636 } else {
637 fc_closesocket(pconn->sock);
638 pconn->used = FALSE;
639 pconn->established = FALSE;
640 if (pconn->closing_reason != nullptr) {
641 free(pconn->closing_reason);
642 }
643
645 pconn->buffer = nullptr;
646
647 free_socket_packet_buffer(pconn->send_buffer);
648 pconn->send_buffer = nullptr;
649
650 if (pconn->last_write) {
651 timer_destroy(pconn->last_write);
652 pconn->last_write = nullptr;
653 }
654
657 }
658}
659
660/**********************************************************************/
663void conn_set_capability(struct connection *pconn, const char *capability)
664{
665 fc_assert(strlen(capability) < sizeof(pconn->capability));
666
667 sz_strlcpy(pconn->capability, capability);
668 pconn->phs.handlers = packet_handlers_get(capability);
669}
670
671/**********************************************************************/
676{
677 int i;
678
679 for (i = 0; i < PACKET_LAST; i++) {
681 if (pc->phs.sent != nullptr && pc->phs.sent[i] != nullptr) {
682 genhash_clear(pc->phs.sent[i]);
683 }
684 if (pc->phs.received != nullptr && pc->phs.received[i] != nullptr) {
685 genhash_clear(pc->phs.received[i]);
686 }
687 }
688 }
689}
690
691/**********************************************************************/
697{
698#ifdef USE_COMPRESSION
699 if (0 == pconn->compression.frozen_level) {
700 byte_vector_reserve(&pconn->compression.queue, 0);
701 }
702 pconn->compression.frozen_level++;
703#endif /* USE_COMPRESSION */
704}
705
706/**********************************************************************/
711{
712#ifdef USE_COMPRESSION
713 return 0 < pconn->compression.frozen_level;
714#else /* USE_COMPRESSION */
715 return FALSE;
716#endif /* USE_COMPRESSION */
717}
718
719/**********************************************************************/
723{
724#ifdef USE_COMPRESSION
728#endif /* USE_COMPRESSION */
729}
730
731/**********************************************************************/
735{
736#ifdef USE_COMPRESSION
740#endif /* USE_COMPRESSION */
741}
742
743/**********************************************************************/
748{
749 return pconn && pconn->playing && !pconn->observer;
750}
751
752/**********************************************************************/
756{
757 return pconn && !pconn->playing && pconn->observer;
758}
759
760/**********************************************************************/
766{
767 if (pconn == nullptr) {
768 return nullptr;
769 }
770
771 return pconn->playing;
772}
773
774/**********************************************************************/
779{
780 if (pconn == nullptr) {
781 return ALLOW_NONE; /* Would not want to give hack on error... */
782 }
783
784 return pconn->access_level;
785}
786
787
788/**************************************************************************
789 Connection patterns.
790**************************************************************************/
795
796/**********************************************************************/
800 const char *wildcard)
801{
802 struct conn_pattern *ppattern = fc_malloc(sizeof(*ppattern));
803
804 ppattern->type = type;
805 ppattern->wildcard = fc_strdup(wildcard);
806
807 return ppattern;
808}
809
810/**********************************************************************/
814{
815 fc_assert_ret(ppattern != nullptr);
816 free(ppattern->wildcard);
817 free(ppattern);
818}
819
820/**********************************************************************/
824 const struct connection *pconn)
825{
826 const char *test = nullptr;
827
828 switch (ppattern->type) {
829 case CPT_USER:
830 test = pconn->username;
831 break;
832 case CPT_HOST:
833 test = pconn->addr;
834 break;
835 case CPT_IP:
836 if (is_server()) {
837 test = pconn->server.ipaddr;
838 }
839 break;
840 }
841
842 if (test != nullptr) {
843 return wildcard_fit_string(ppattern->wildcard, test);
844 } else {
845 log_error("%s(): Invalid pattern type (%d)",
846 __FUNCTION__, ppattern->type);
847 return FALSE;
848 }
849}
850
851/**********************************************************************/
855 const struct connection *pconn)
856{
859 return TRUE;
860 }
862
863 return FALSE;
864}
865
866/**********************************************************************/
870 char *buf, size_t buf_len)
871{
872 return fc_snprintf(buf, buf_len, "<%s=%s>",
874 ppattern->wildcard);
875}
876
877/**********************************************************************/
883 enum conn_pattern_type prefer,
884 char *error_buf,
885 size_t error_buf_len)
886{
888 const char *p;
889
890 /* Determine pattern type. */
891 if ((p = strchr(pattern, '='))) {
892 /* Special character to separate the type of the pattern. */
893 const size_t pattern_type_len = ++p - pattern;
895
900 if (error_buf != nullptr) {
902 _("\"%s\" is not a valid pattern type"),
904 }
905
906 return nullptr;
907 }
908 } else {
909 /* Use 'prefer' type. */
910 p = pattern;
911 type = prefer;
913 if (error_buf != nullptr) {
914 fc_strlcpy(error_buf, _("Missing pattern type"), error_buf_len);
915 }
916
917 return nullptr;
918 }
919 }
920
921 /* Remove leading spaces. */
922 while (fc_isspace(*p)) {
923 p++;
924 }
925
926 if ('\0' == *p) {
927 if (error_buf != nullptr) {
928 fc_strlcpy(error_buf, _("Missing pattern"), error_buf_len);
929 }
930
931 return nullptr;
932 }
933
934 return conn_pattern_new(type, p);
935}
936
937/**********************************************************************/
941bool conn_is_valid(const struct connection *pconn)
942{
943 return (pconn != nullptr && pconn->used && !pconn->server.is_closing);
944}
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:869
static conn_close_fn_t conn_close_callback
Definition connection.c:65
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:765
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:368
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:400
bool can_conn_edit(const struct connection *pconn)
Definition connection.c:513
struct connection * conn_by_user(const char *user_name)
Definition connection.c:379
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c:734
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:246
static const char * connection_accessor(int i)
Definition connection.c:396
void flush_connection_send_buffer_all(struct connection *pc)
Definition connection.c:231
int get_next_request_id(int old_request_id)
Definition connection.c:532
struct socket_packet_buffer * new_socket_packet_buffer(void)
Definition connection.c:441
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:358
bool can_conn_enable_editing(const struct connection *pconn)
Definition connection.c:523
void connection_do_buffer(struct connection *pc)
Definition connection.c:325
static bool add_connection_data(struct connection *pconn, const unsigned char *data, int len)
Definition connection.c:261
bool conn_pattern_match(const struct conn_pattern *ppattern, const struct connection *pconn)
Definition connection.c:823
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:663
static void init_packet_hashes(struct connection *pc)
Definition connection.c:559
void conn_pattern_destroy(struct conn_pattern *ppattern)
Definition connection.c:813
void conn_reset_delta_state(struct connection *pc)
Definition connection.c:675
void connection_common_init(struct connection *pconn)
Definition connection.c:605
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:722
struct conn_pattern * conn_pattern_new(enum conn_pattern_type type, const char *wildcard)
Definition connection.c:799
bool conn_controls_player(const struct connection *pconn)
Definition connection.c:747
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:755
const char * conn_description(const struct connection *pconn)
Definition connection.c:476
void connection_common_close(struct connection *pconn)
Definition connection.c:632
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:882
void conn_compression_freeze(struct connection *pconn)
Definition connection.c:696
static void free_packet_hashes(struct connection *pc)
Definition connection.c:576
static void free_socket_packet_buffer(struct socket_packet_buffer *buf)
Definition connection.c:457
struct connection * conn_by_number(int id)
Definition connection.c:423
void free_compression_queue(struct connection *pc)
Definition connection.c:549
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:288
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:778
bool conn_is_valid(const struct connection *pconn)
Definition connection.c:941
bool conn_compression_frozen(const struct connection *pconn)
Definition connection.c:710
bool conn_pattern_list_match(const struct conn_pattern_list *plist, const struct connection *pconn)
Definition connection.c:854
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:337
#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:67
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
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
packet_type
@ PACKET_LAST
#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)
int len
Definition packhand.c:128
const char * player_name(const struct player *pplayer)
Definition player.c:900
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:793
enum conn_pattern_type type
Definition connection.c:792
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