Freeciv-3.2
Loading...
Searching...
No Matches
packets.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 <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <limits.h>
24
25#ifdef HAVE_ARPA_INET_H
26#include <arpa/inet.h>
27#endif
28#ifdef HAVE_NETINET_IN_H
29#include <netinet/in.h>
30#endif
31
32/* utility */
33#include "capability.h"
34#include "fc_cmdline.h"
35#include "fcintl.h"
36#include "log.h"
37#include "mem.h"
38#include "support.h"
39
40/* common */
41#include "dataio.h"
42#include "game.h"
43#include "events.h"
44#include "map.h"
45
46#include "packets.h"
47
48#ifdef USE_COMPRESSION
49#include <zlib.h>
50/*
51 * Value for the 16bit size to indicate a jumbo packet
52 */
53#define JUMBO_SIZE 0xffff
54
55/*
56 * All values 0 <= size < COMPRESSION_BORDER are uncompressed packets.
57 */
58#define COMPRESSION_BORDER (16*1024+1)
59
60/*
61 * All compressed packets this size or greater are sent as a jumbo packet.
62 */
63#define JUMBO_BORDER (64*1024-COMPRESSION_BORDER-1)
64
65#define log_compress log_debug
66#define log_compress2 log_debug
67
68#define MAX_DECOMPRESSION 400
69
70#endif /* USE_COMPRESSION */
71
72/*
73 * Valid values are 0, 1 and 2. For 2 you have to run generate_packets.py
74 * with --gen-stats.
75 */
76#define PACKET_SIZE_STATISTICS 0
77
78extern const char *const packet_functional_capability;
79
80#define SPECHASH_TAG packet_handler
81#define SPECHASH_ASTR_KEY_TYPE
82#define SPECHASH_IDATA_TYPE struct packet_handlers *
83#define SPECHASH_IDATA_FREE (packet_handler_hash_data_free_fn_t) free
84#include "spechash.h"
85
87
88#ifdef USE_COMPRESSION
89static int stat_size_alone = 0;
90static int stat_size_uncompressed = 0;
91static int stat_size_compressed = 0;
92static int stat_size_no_compression = 0;
93
94/**********************************************************************/
97static inline int get_compression_level(void)
98{
99 static int level = -2; /* Magic not initialized, see below. */
100
101 if (-2 == level) {
102 const char *s = getenv("FREECIV_COMPRESSION_LEVEL");
103
104 if (NULL == s || !str_to_int(s, &level) || -1 > level || 9 < level) {
105 level = -1;
106 }
107 }
108
109 return level;
110}
111
112/**********************************************************************/
115static bool conn_compression_flush(struct connection *pconn)
116{
118 uLongf compressed_size = 12 + 1.001 * pconn->compression.queue.size;
120 bool jumbo;
121 unsigned long compressed_packet_len;
122
123#ifndef FREECIV_NDEBUG
124 int error =
125#endif
127 pconn->compression.queue.p,
128 pconn->compression.queue.size,
130
131 fc_assert_ret_val(error == Z_OK, FALSE);
132
133 /* Compression signalling currently assumes a 2-byte packet length; if that
134 * changes, the protocol should probably be changed */
135 fc_assert_ret_val(data_type_size(pconn->packet_header.length) == 2, FALSE);
136
137 /* Include normal length field in decision */
139
141 if (compressed_packet_len < pconn->compression.queue.size) {
142 struct raw_data_out dout;
143
144 log_compress("COMPRESS: compressed %lu bytes to %ld (level %d)",
145 (unsigned long) pconn->compression.queue.size,
147 stat_size_uncompressed += pconn->compression.queue.size;
149
150 if (!jumbo) {
151 unsigned char header[2];
152
155
156 log_compress("COMPRESS: sending %ld as normal", compressed_size);
157
158 dio_output_init(&dout, header, sizeof(header));
160 connection_send_data(pconn, header, sizeof(header));
162 } else {
163 unsigned char header[6];
164
167
168 log_compress("COMPRESS: sending %ld as jumbo", compressed_size);
169 dio_output_init(&dout, header, sizeof(header));
172 connection_send_data(pconn, header, sizeof(header));
174 }
175 } else {
176 log_compress("COMPRESS: would enlarge %lu bytes to %ld; "
177 "sending uncompressed",
178 (unsigned long) pconn->compression.queue.size,
180 connection_send_data(pconn, pconn->compression.queue.p,
181 pconn->compression.queue.size);
182 stat_size_no_compression += pconn->compression.queue.size;
183 }
184
185 return pconn->used;
186}
187#endif /* USE_COMPRESSION */
188
189/**********************************************************************/
195{
196#ifdef USE_COMPRESSION
197 pconn->compression.frozen_level--;
198 fc_assert_action_msg(pconn->compression.frozen_level >= 0,
199 pconn->compression.frozen_level = 0,
200 "Too many calls to conn_compression_thaw on %s!",
202 if (0 == pconn->compression.frozen_level) {
204 }
205#endif /* USE_COMPRESSION */
206
207 return pconn->used;
208}
209
210/**********************************************************************/
213int send_packet_data(struct connection *pc, unsigned char *data, int len,
215{
216 /* default for the server */
217 int result = 0;
218
219 log_packet("sending packet type=%s(%d) len=%d to %s",
221 is_server() ? pc->username : "server");
222
223 if (!is_server()) {
224 pc->client.last_request_id_used =
225 get_next_request_id(pc->client.last_request_id_used);
226 result = pc->client.last_request_id_used;
227 log_packet("sending request %d", result);
228 }
229
230 if (pc->outgoing_packet_notify) {
231 pc->outgoing_packet_notify(pc, packet_type, len, result);
232 }
233
234#ifdef USE_COMPRESSION
235 if (TRUE) {
236 int size = len;
237
239 size_t old_size;
240
241 /* Keep this a decent amount less than MAX_LEN_BUFFER to avoid the
242 * (remote) possibility of trying to dump MAX_LEN_BUFFER to the
243 * network in one go */
244#define MAX_LEN_COMPRESS_QUEUE (MAX_LEN_BUFFER/2)
247
248 /* If this packet would cause us to overfill the queue, flush
249 * everything that's in there already before queuing this one */
251 < byte_vector_size(&pc->compression.queue) + len) {
252 log_compress2("COMPRESS: huge queue, forcing to flush (%lu/%lu)",
253 (long unsigned)
254 byte_vector_size(&pc->compression.queue),
255 (long unsigned) MAX_LEN_COMPRESS_QUEUE);
257 return -1;
258 }
259 byte_vector_reserve(&pc->compression.queue, 0);
260 }
261
262 old_size = byte_vector_size(&pc->compression.queue);
263 byte_vector_reserve(&pc->compression.queue, old_size + len);
264 memcpy(pc->compression.queue.p + old_size, data, len);
265 log_compress2("COMPRESS: putting %s into the queue",
267 } else {
269 log_compress("COMPRESS: sending %s alone (%d bytes total)",
272 }
273
274 log_compress2("COMPRESS: STATS: alone=%d compression-expand=%d "
275 "compression (before/after) = %d/%d",
278 }
279#else /* USE_COMPRESSION */
281#endif /* USE_COMPRESSION */
282
283#if PACKET_SIZE_STATISTICS
284 {
285 static struct {
286 int counter;
287 int size;
289 static int packet_counter = 0;
290 static int last_start_turn_seen = -1;
291 static bool start_turn_seen = FALSE;
292
293 int size = len;
294 bool print = FALSE;
295 bool clear = FALSE;
296
297 if (!packet_counter) {
298 int i;
299
300 for (i = 0; i < PACKET_LAST; i++) {
301 packets_stats[i].counter = 0;
302 packets_stats[i].size = 0;
303 }
304 }
305
306 packets_stats[packet_type].counter++;
308
311 && last_start_turn_seen != game.turn) {
314 }
315
316 if ((packet_type ==
318 && start_turn_seen) {
320 print = TRUE;
321 clear = TRUE;
322 }
323
324 if (print) {
325 int i, sum = 0;
326#define log_ll log_debug
327
328#if PACKET_SIZE_STATISTICS == 2
330#endif
331 log_ll("Transmitted packets:");
332 log_ll("%8s %8s %8s %s", "Packets", "Bytes", "Byt/Pac", "Name");
333
334 for (i = 0; i < PACKET_LAST; i++) {
335 if (packets_stats[i].counter == 0) {
336 continue;
337 }
338 sum += packets_stats[i].size;
339 log_ll("%8d %8d %8d %s(%i)",
342 packet_name(i),i);
343 }
344 log_test("turn=%d; transmitted %d bytes in %d packets;average size "
345 "per packet %d bytes", game.turn, sum, packet_counter,
346 sum / packet_counter);
347 log_test("turn=%d; transmitted %d bytes", game.turn,
348 pc->statistics.bytes_send);
349 }
350 if (clear) {
351 int i;
352
353 for (i = 0; i < PACKET_LAST; i++) {
354 packets_stats[i].counter = 0;
355 packets_stats[i].size = 0;
356 }
357 packet_counter = 0;
358 pc->statistics.bytes_send = 0;
360 }
361 }
362#undef log_ll
363#endif /* PACKET_SIZE_STATISTICS */
364
365 return result;
366}
367
368/**********************************************************************/
374 enum packet_type *ptype,
375 bool recursed)
376{
377 int len_read;
379 struct {
380 enum packet_type type;
381 int itype;
382 } utype;
383 struct data_in din;
384#ifdef USE_COMPRESSION
386 int header_size = 0;
387#endif
388 void *data;
389 void *(*receive_handler)(struct connection *);
390
391 if (!pc->used) {
392 return NULL; /* connection was closed, stop reading */
393 }
394
395 if (pc->buffer->ndata < data_type_size(pc->packet_header.length)) {
396 /* Not got enough for a length field yet */
397 return NULL;
398 }
399
400 dio_input_init(&din, pc->buffer->data, pc->buffer->ndata);
401 dio_get_type_raw(&din, pc->packet_header.length, &len_read);
402
403 /* The non-compressed case */
405
406#ifdef USE_COMPRESSION
407 /* Compression signalling currently assumes a 2-byte packet length; if that
408 * changes, the protocol should probably be changed */
409 fc_assert(data_type_size(pc->packet_header.length) == 2);
410 if (len_read == JUMBO_SIZE) {
411 if (recursed) {
412 log_verbose("Got recursive jumbo packet. That's not acceptable. "
413 "The connection will be closed now.");
414 connection_close(pc, _("recursive jumbo packet"));
415 return NULL;
416 }
418 header_size = 6;
419 if (dio_input_remaining(&din) >= 4) {
421 log_compress("COMPRESS: got a jumbo packet of size %d",
423 } else {
424 /* to return NULL below */
426 }
427 } else if (len_read >= COMPRESSION_BORDER) {
429 header_size = 2;
431 log_compress("COMPRESS: got a normal packet of size %d",
433 }
434#endif /* USE_COMPRESSION */
435
436 if ((unsigned)whole_packet_len > pc->buffer->ndata) {
437 return NULL; /* not all data has been read */
438 }
439
440#ifdef USE_COMPRESSION
442 log_verbose("The packet size is reported to be less than header alone. "
443 "The connection will be closed now.");
444 connection_close(pc, _("illegal packet size"));
445
446 return NULL;
447 }
448
449 if (compressed_packet) {
451 int decompress_factor = 80;
453 int error = Z_BUF_ERROR;
454 struct socket_packet_buffer *buffer = pc->buffer;
456
457 do {
458 error =
462
463 if (error == Z_BUF_ERROR) {
464 decompress_factor += 50;
467 }
468
469 if (error != Z_OK) {
471 log_verbose("Uncompressing of the packet stream failed. "
472 "The connection will be closed now.");
473 connection_close(pc, _("decoding error"));
474 return NULL;
475 }
476 }
477
478 } while (error != Z_OK);
479
480 buffer->ndata -= whole_packet_len;
481 /*
482 * Remove the packet with the compressed data and shift all the
483 * remaining data to the front.
484 */
485 memmove(buffer->data, buffer->data + whole_packet_len, buffer->ndata);
486
487 if (buffer->ndata + decompressed_size > buffer->nsize) {
488 buffer->nsize += decompressed_size;
489 buffer->data = fc_realloc(buffer->data, buffer->nsize);
490 }
491
492 /*
493 * Make place for the uncompressed data by moving the remaining
494 * data.
495 */
496 memmove(buffer->data + decompressed_size, buffer->data, buffer->ndata);
497
498 /*
499 * Copy the uncompressed data.
500 */
502
504
505 buffer->ndata += decompressed_size;
506
507 log_compress("COMPRESS: decompressed %ld into %ld",
509
511 }
512#endif /* USE_COMPRESSION */
513
514 /*
515 * At this point the packet is a plain uncompressed one. These have
516 * to have to be at least the header bytes in size.
517 */
518 if (whole_packet_len < (data_type_size(pc->packet_header.length)
519 + data_type_size(pc->packet_header.type))) {
520 log_verbose("The packet stream is corrupt. The connection "
521 "will be closed now.");
522 connection_close(pc, _("decoding error"));
523 return NULL;
524 }
525
526 dio_get_type_raw(&din, pc->packet_header.type, &utype.itype);
527 utype.type = utype.itype;
528
529 if (utype.type >= PACKET_LAST
530 || (receive_handler = pc->phs.handlers->receive[utype.type]) == NULL) {
531 log_verbose("Received unsupported packet type %d (%s). The connection "
532 "will be closed now.",
533 utype.type, packet_name(utype.type));
534 connection_close(pc, _("unsupported packet type"));
535 return NULL;
536 }
537
538 log_packet("got packet type=(%s)%d len=%d from %s",
539 packet_name(utype.type), utype.itype, whole_packet_len,
540 is_server() ? pc->username : "server");
541
542 *ptype = utype.type;
543
544 if (pc->incoming_packet_notify) {
545 pc->incoming_packet_notify(pc, utype.type, whole_packet_len);
546 }
547
548#if PACKET_SIZE_STATISTICS
549 {
550 static struct {
551 int counter;
552 int size;
554 static int packet_counter = 0;
555
556 int packet_type = utype.itype;
558
559 if (!packet_counter) {
560 int i;
561
562 for (i = 0; i < PACKET_LAST; i++) {
563 packets_stats[i].counter = 0;
564 packets_stats[i].size = 0;
565 }
566 }
567
568 packets_stats[packet_type].counter++;
570
572 if (packet_counter % 100 == 0) {
573 int i, sum = 0;
574
575 log_test("Received packets:");
576 for (i = 0; i < PACKET_LAST; i++) {
577 if (packets_stats[i].counter == 0) {
578 continue;
579 }
580 sum += packets_stats[i].size;
581 log_test(" [%-25.25s %3d]: %6d packets; %8d bytes total; "
582 "%5d bytes/packet average",
586 }
587 log_test("received %d bytes in %d packets;average size "
588 "per packet %d bytes",
589 sum, packet_counter, sum / packet_counter);
590 }
591 }
592#endif /* PACKET_SIZE_STATISTICS */
593 data = receive_handler(pc);
594 if (!data) {
595 connection_close(pc, _("incompatible packet contents"));
596 return NULL;
597 } else {
598 return data;
599 }
600}
601
602/**********************************************************************/
606{
607 struct data_in din;
608 int len;
609
610 dio_input_init(&din, buffer->data, buffer->ndata);
612 memmove(buffer->data, buffer->data + len, buffer->ndata - len);
613 buffer->ndata -= len;
614 log_debug("remove_packet_from_buffer: remove %d; remaining %d",
615 len, buffer->ndata);
616}
617
618/**********************************************************************/
629
630/**********************************************************************/
635{
636 /* Ensure we have values initialized in packet_header_init(). */
639
642}
643
644/**********************************************************************/
648 const struct packet_server_join_reply
649 *packet)
650{
651 if (packet->you_can_join) {
652 packet_header_set(&pconn->packet_header);
653 }
654}
655
656/**********************************************************************/
660 const struct
662{
663 if (packet->you_can_join) {
664 packet_header_set(&pconn->packet_header);
665 }
666}
667
668
669/**********************************************************************/
672bool packet_check(struct data_in *din, struct connection *pc)
673{
674 size_t rem = dio_input_remaining(din);
675
676 if (rem > 0) {
677 int type, len;
678
680 dio_get_type_raw(din, pc->packet_header.length, &len);
681 dio_get_type_raw(din, pc->packet_header.type, &type);
682
683 log_packet("received long packet (type %d, len %d, rem %lu) from %s",
684 type,
685 len,
686 (unsigned long) rem,
688 return FALSE;
689 }
690
691 return TRUE;
692}
693
694/**********************************************************************/
698 const struct
700 *chunk)
701{
702 log_packet("received attribute chunk %u/%u %u",
703 (unsigned int) chunk->offset,
704 (unsigned int) chunk->total_length,
705 (unsigned int) chunk->chunk_length);
706
707 if (chunk->total_length < 0
708 || chunk->chunk_length < 0
709 || chunk->total_length >= MAX_ATTRIBUTE_BLOCK
710 || chunk->offset < 0
711 || chunk->offset > chunk->total_length /* necessary check on 32 bit systems */
712 || chunk->chunk_length > chunk->total_length
713 || chunk->offset + chunk->chunk_length > chunk->total_length
714 || (chunk->offset != 0
715 && chunk->total_length != pplayer->attribute_block_buffer.length)) {
716 /* wrong attribute data */
717 if (pplayer->attribute_block_buffer.data) {
720 }
721 pplayer->attribute_block_buffer.length = 0;
722 log_error("Received wrong attribute chunk");
723 return;
724 }
725 /* first one in a row */
726 if (chunk->offset == 0) {
727 if (pplayer->attribute_block_buffer.data) {
730 }
731 pplayer->attribute_block_buffer.data = fc_malloc(chunk->total_length);
732 pplayer->attribute_block_buffer.length = chunk->total_length;
733 }
734 memcpy((char *) (pplayer->attribute_block_buffer.data) + chunk->offset,
735 chunk->data, chunk->chunk_length);
736
737 if (chunk->offset + chunk->chunk_length == chunk->total_length) {
738 /* Received full attribute block */
739 if (pplayer->attribute_block.data != NULL) {
740 free(pplayer->attribute_block.data);
741 }
744
746 pplayer->attribute_block_buffer.length = 0;
747 }
748}
749
750/**********************************************************************/
753void send_attribute_block(const struct player *pplayer,
754 struct connection *pconn)
755{
756 struct packet_player_attribute_chunk packet;
758
759 if (!pplayer || !pplayer->attribute_block.data) {
760 return;
761 }
762
765
766 chunks =
767 (pplayer->attribute_block.length - 1) / ATTRIBUTE_CHUNK_SIZE + 1;
769
771
774
776 packet.total_length = pplayer->attribute_block.length;
778
779 memcpy(packet.data,
780 (char *) (pplayer->attribute_block.data) + packet.offset,
781 packet.chunk_length);
782 bytes_left -= packet.chunk_length;
783
784 if (packet.chunk_length < ATTRIBUTE_CHUNK_SIZE) {
785 /* Last chunk is not full. Make sure that delta does
786 * not use random data. */
787 memset(packet.data + packet.chunk_length, 0,
789 }
790
792 }
793
795}
796
797/**********************************************************************/
802 *packet)
803{
804 fc_assert(packet->total_length > 0
805 && packet->total_length < MAX_ATTRIBUTE_BLOCK);
806 /* 500 bytes header, just to be sure */
807 fc_assert(packet->chunk_length > 0
808 && packet->chunk_length < MAX_LEN_PACKET - 500);
809 fc_assert(packet->chunk_length <= packet->total_length);
810 fc_assert(packet->offset >= 0 && packet->offset < packet->total_length);
811
812 log_packet("sending attribute chunk %d/%d %d",
813 packet->offset, packet->total_length, packet->chunk_length);
814}
815
816/**********************************************************************/
826
827/**********************************************************************/
831{
832 static struct packet_handlers default_handlers;
833 static bool initialized = FALSE;
834
835 if (!initialized) {
839 }
840
841 return &default_handlers;
842}
843
844/**********************************************************************/
847const struct packet_handlers *packet_handlers_get(const char *capability)
848{
851 char *tokens[MAX_LEN_CAPSTR / 2];
853 int tokens_num;
854 int functional_tokens_num = 0;
855 int i;
856
857 fc_assert(strlen(capability) < sizeof(functional_capability));
858
859 /* Get functional network capability string. */
860 tokens_num = get_tokens(capability, tokens, ARRAY_SIZE(tokens), " \t\n,");
861 for (i = 0; i < tokens_num; i++) {
862 char *token;
863
864 token = tokens[i];
865 if (token[0] == '+') {
866 token++;
867 }
868
871 }
872 }
875 for (i = 0; i < functional_tokens_num; i++) {
876 if (functional_capability[0] != '\0') {
878 }
880 }
882
883 /* Ensure the hash table is created. */
884 if (packet_handlers == NULL) {
886 }
887
888 /* Lookup handlers for the capabilities or create new handlers. */
890 &phandlers)) {
891 phandlers = fc_malloc(sizeof(*phandlers));
895 phandlers);
896 }
897
899
900 return phandlers;
901}
902
903/**********************************************************************/
908{
910}
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:77
char * incite_cost
Definition comments.c:75
#define ATTRIBUTE_CHUNK_SIZE
Definition conn_types.h:66
#define MAX_LEN_PACKET
Definition conn_types.h:29
#define MAX_LEN_BUFFER
Definition conn_types.h:34
#define MAX_LEN_CAPSTR
Definition conn_types.h:30
int get_next_request_id(int old_request_id)
Definition connection.c:530
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
void connection_close(struct connection *pconn, const char *reason)
Definition connection.c:88
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
bool connection_send_data(struct connection *pconn, const unsigned char *data, int len)
Definition connection.c:287
bool conn_compression_frozen(const struct connection *pconn)
Definition connection.c:708
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
int dio_put_uint32_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:309
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
size_t dio_input_remaining(struct data_in *din)
Definition dataio_raw.c:221
bool dio_get_uint32_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:640
void dio_input_rewind(struct data_in *din)
Definition dataio_raw.c:213
bool dio_get_uint16_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:619
bool dio_get_type_raw(struct data_in *din, enum data_type type, int *dest)
Definition dataio_raw.c:661
int dio_put_uint16_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:287
size_t data_type_size(enum data_type type)
Definition dataio_raw.c:229
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Definition dataio_raw.c:202
@ DIOT_UINT8
Definition dataio_raw.h:44
@ DIOT_UINT16
Definition dataio_raw.h:45
static bool initialized
Definition effects.c:42
void free_tokens(char **tokens, size_t ntokens)
Definition fc_cmdline.c:203
int get_tokens(const char *str, char **tokens, size_t num_tokens, const char *delimiterset)
Definition fc_cmdline.c:166
static bool is_server(void)
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
GType type
Definition repodlgs.c:1313
#define fc_assert_ret(condition)
Definition log.h:191
#define log_packet
Definition log.h:137
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_action_msg(condition, action, message,...)
Definition log.h:201
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#define FC_STATIC_ASSERT(cond, tag)
Definition log.h:235
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
void * get_packet_from_connection_raw(struct connection *pc, enum packet_type *ptype, bool recursed)
Definition packets.c:373
void post_receive_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
Definition packets.c:659
static void packet_handlers_free(void)
Definition packets.c:819
bool packet_check(struct data_in *din, struct connection *pc)
Definition packets.c:672
void packet_header_init(struct packet_header *packet_header)
Definition packets.c:624
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
const struct packet_handlers * packet_handlers_initial(void)
Definition packets.c:830
const char *const packet_functional_capability
Definition packets_gen.c:30
void packets_deinit(void)
Definition packets.c:907
void pre_send_packet_player_attribute_chunk(struct connection *pc, struct packet_player_attribute_chunk *packet)
Definition packets.c:800
static void packet_header_set(struct packet_header *packet_header)
Definition packets.c:634
void remove_packet_from_buffer(struct socket_packet_buffer *buffer)
Definition packets.c:605
void post_send_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
Definition packets.c:647
int send_packet_data(struct connection *pc, unsigned char *data, int len, enum packet_type packet_type)
Definition packets.c:213
void generic_handle_player_attribute_chunk(struct player *pplayer, const struct packet_player_attribute_chunk *chunk)
Definition packets.c:697
void send_attribute_block(const struct player *pplayer, struct connection *pconn)
Definition packets.c:753
const struct packet_handlers * packet_handlers_get(const char *capability)
Definition packets.c:847
#define get_packet_from_connection(pc, ptype, recursed)
Definition packets.h:92
void packet_handlers_fill_capability(struct packet_handlers *phandlers, const char *capability)
const char * packet_name(enum packet_type type)
Definition packets_gen.c:48
void packet_handlers_fill_initial(struct packet_handlers *phandlers)
void delta_stats_reset(void)
Definition packets_gen.c:46
void delta_stats_report(void)
Definition packets_gen.c:44
int send_packet_player_attribute_chunk(struct connection *pc, const struct packet_player_attribute_chunk *packet)
packet_type
@ PACKET_LAST
@ PACKET_PROCESSING_FINISHED
int len
Definition packhand.c:127
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:221
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
int compare_strings_ptrs(const void *first, const void *second)
Definition shared.c:369
bool str_to_int(const char *str, int *pint)
Definition shared.c:517
#define ADD_TO_POINTER(p, n)
Definition shared.h:86
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
size_t size
Definition specvec.h:72
unsigned int length
Definition connection.h:124
unsigned int type
Definition connection.h:125
unsigned char data[ATTRIBUTE_CHUNK_SIZE]
struct attribute_block_s attribute_block
Definition player.h:305
struct attribute_block_s attribute_block_buffer
Definition player.h:306
unsigned char * data
Definition connection.h:120
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196