Freeciv-3.3
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{
376 int len_read;
378 struct {
379 enum packet_type type;
380 int itype;
381 } utype;
382 struct data_in din;
383#ifdef USE_COMPRESSION
385 int header_size = 0;
386#endif
387 void *data;
388 void *(*receive_handler)(struct connection *);
389
390 if (!pc->used) {
391 return NULL; /* connection was closed, stop reading */
392 }
393
394 if (pc->buffer->ndata < data_type_size(pc->packet_header.length)) {
395 /* Not got enough for a length field yet */
396 return NULL;
397 }
398
399 dio_input_init(&din, pc->buffer->data, pc->buffer->ndata);
400 dio_get_type_raw(&din, pc->packet_header.length, &len_read);
401
402 /* The non-compressed case */
404
405#ifdef USE_COMPRESSION
406 /* Compression signalling currently assumes a 2-byte packet length; if that
407 * changes, the protocol should probably be changed */
408 fc_assert(data_type_size(pc->packet_header.length) == 2);
409 if (len_read == JUMBO_SIZE) {
411 header_size = 6;
412 if (dio_input_remaining(&din) >= 4) {
414 log_compress("COMPRESS: got a jumbo packet of size %d",
416 } else {
417 /* to return NULL below */
419 }
420 } else if (len_read >= COMPRESSION_BORDER) {
422 header_size = 2;
424 log_compress("COMPRESS: got a normal packet of size %d",
426 }
427#endif /* USE_COMPRESSION */
428
429 if ((unsigned)whole_packet_len > pc->buffer->ndata) {
430 return NULL; /* not all data has been read */
431 }
432
433#ifdef USE_COMPRESSION
435 log_verbose("The packet size is reported to be less than header alone. "
436 "The connection will be closed now.");
437 connection_close(pc, _("illegal packet size"));
438
439 return NULL;
440 }
441
442 if (compressed_packet) {
444 int decompress_factor = 80;
446 int error = Z_BUF_ERROR;
447 struct socket_packet_buffer *buffer = pc->buffer;
449
450 do {
451 error =
455
456 if (error == Z_BUF_ERROR) {
457 decompress_factor += 50;
460 }
461
462 if (error != Z_OK) {
464 log_verbose("Uncompressing of the packet stream failed. "
465 "The connection will be closed now.");
466 connection_close(pc, _("decoding error"));
467 return NULL;
468 }
469 }
470
471 } while (error != Z_OK);
472
473 buffer->ndata -= whole_packet_len;
474 /*
475 * Remove the packet with the compressed data and shift all the
476 * remaining data to the front.
477 */
478 memmove(buffer->data, buffer->data + whole_packet_len, buffer->ndata);
479
480 if (buffer->ndata + decompressed_size > buffer->nsize) {
481 buffer->nsize += decompressed_size;
482 buffer->data = fc_realloc(buffer->data, buffer->nsize);
483 }
484
485 /*
486 * Make place for the uncompressed data by moving the remaining
487 * data.
488 */
489 memmove(buffer->data + decompressed_size, buffer->data, buffer->ndata);
490
491 /*
492 * Copy the uncompressed data.
493 */
495
497
498 buffer->ndata += decompressed_size;
499
500 log_compress("COMPRESS: decompressed %ld into %ld",
502
504 }
505#endif /* USE_COMPRESSION */
506
507 /*
508 * At this point the packet is a plain uncompressed one. These have
509 * to have to be at least the header bytes in size.
510 */
511 if (whole_packet_len < (data_type_size(pc->packet_header.length)
512 + data_type_size(pc->packet_header.type))) {
513 log_verbose("The packet stream is corrupt. The connection "
514 "will be closed now.");
515 connection_close(pc, _("decoding error"));
516 return NULL;
517 }
518
519 dio_get_type_raw(&din, pc->packet_header.type, &utype.itype);
520 utype.type = utype.itype;
521
522 if (utype.type >= PACKET_LAST
523 || (receive_handler = pc->phs.handlers->receive[utype.type]) == NULL) {
524 log_verbose("Received unsupported packet type %d (%s). The connection "
525 "will be closed now.",
526 utype.type, packet_name(utype.type));
527 connection_close(pc, _("unsupported packet type"));
528 return NULL;
529 }
530
531 log_packet("got packet type=(%s)%d len=%d from %s",
532 packet_name(utype.type), utype.itype, whole_packet_len,
533 is_server() ? pc->username : "server");
534
535 *ptype = utype.type;
536
537 if (pc->incoming_packet_notify) {
538 pc->incoming_packet_notify(pc, utype.type, whole_packet_len);
539 }
540
541#if PACKET_SIZE_STATISTICS
542 {
543 static struct {
544 int counter;
545 int size;
547 static int packet_counter = 0;
548
549 int packet_type = utype.itype;
551
552 if (!packet_counter) {
553 int i;
554
555 for (i = 0; i < PACKET_LAST; i++) {
556 packets_stats[i].counter = 0;
557 packets_stats[i].size = 0;
558 }
559 }
560
561 packets_stats[packet_type].counter++;
563
565 if (packet_counter % 100 == 0) {
566 int i, sum = 0;
567
568 log_test("Received packets:");
569 for (i = 0; i < PACKET_LAST; i++) {
570 if (packets_stats[i].counter == 0) {
571 continue;
572 }
573 sum += packets_stats[i].size;
574 log_test(" [%-25.25s %3d]: %6d packets; %8d bytes total; "
575 "%5d bytes/packet average",
579 }
580 log_test("received %d bytes in %d packets;average size "
581 "per packet %d bytes",
582 sum, packet_counter, sum / packet_counter);
583 }
584 }
585#endif /* PACKET_SIZE_STATISTICS */
586 data = receive_handler(pc);
587 if (!data) {
588 connection_close(pc, _("incompatible packet contents"));
589 return NULL;
590 } else {
591 return data;
592 }
593}
594
595/**********************************************************************/
599{
600 struct data_in din;
601 int len;
602
603 dio_input_init(&din, buffer->data, buffer->ndata);
605 memmove(buffer->data, buffer->data + len, buffer->ndata - len);
606 buffer->ndata -= len;
607 log_debug("remove_packet_from_buffer: remove %d; remaining %d",
608 len, buffer->ndata);
609}
610
611/**********************************************************************/
622
623/**********************************************************************/
628{
629 /* Ensure we have values initialized in packet_header_init(). */
632
635}
636
637/**********************************************************************/
641 const struct packet_server_join_reply
642 *packet)
643{
644 if (packet->you_can_join) {
645 packet_header_set(&pconn->packet_header);
646 }
647}
648
649/**********************************************************************/
653 const struct
655{
656 if (packet->you_can_join) {
657 packet_header_set(&pconn->packet_header);
658 }
659}
660
661
662/**********************************************************************/
665bool packet_check(struct data_in *din, struct connection *pc)
666{
667 size_t rem = dio_input_remaining(din);
668
669 if (rem > 0) {
670 int type, len;
671
673 dio_get_type_raw(din, pc->packet_header.length, &len);
674 dio_get_type_raw(din, pc->packet_header.type, &type);
675
676 log_packet("received long packet (type %d, len %d, rem %lu) from %s",
677 type,
678 len,
679 (unsigned long) rem,
681 return FALSE;
682 }
683
684 return TRUE;
685}
686
687/**********************************************************************/
691 const struct
693 *chunk)
694{
695 log_packet("received attribute chunk %u/%u %u",
696 (unsigned int) chunk->offset,
697 (unsigned int) chunk->total_length,
698 (unsigned int) chunk->chunk_length);
699
700 if (chunk->total_length < 0
701 || chunk->chunk_length < 0
702 || chunk->total_length >= MAX_ATTRIBUTE_BLOCK
703 || chunk->offset < 0
704 || chunk->offset > chunk->total_length /* necessary check on 32 bit systems */
705 || chunk->chunk_length > chunk->total_length
706 || chunk->offset + chunk->chunk_length > chunk->total_length
707 || (chunk->offset != 0
708 && chunk->total_length != pplayer->attribute_block_buffer.length)) {
709 /* wrong attribute data */
710 if (pplayer->attribute_block_buffer.data) {
713 }
714 pplayer->attribute_block_buffer.length = 0;
715 log_error("Received wrong attribute chunk");
716 return;
717 }
718 /* first one in a row */
719 if (chunk->offset == 0) {
720 if (pplayer->attribute_block_buffer.data) {
723 }
724 pplayer->attribute_block_buffer.data = fc_malloc(chunk->total_length);
725 pplayer->attribute_block_buffer.length = chunk->total_length;
726 }
727 memcpy((char *) (pplayer->attribute_block_buffer.data) + chunk->offset,
728 chunk->data, chunk->chunk_length);
729
730 if (chunk->offset + chunk->chunk_length == chunk->total_length) {
731 /* Received full attribute block */
732 if (pplayer->attribute_block.data != NULL) {
733 free(pplayer->attribute_block.data);
734 }
737
739 pplayer->attribute_block_buffer.length = 0;
740 }
741}
742
743/**********************************************************************/
746void send_attribute_block(const struct player *pplayer,
747 struct connection *pconn)
748{
749 struct packet_player_attribute_chunk packet;
751
752 if (!pplayer || !pplayer->attribute_block.data) {
753 return;
754 }
755
758
759 chunks =
760 (pplayer->attribute_block.length - 1) / ATTRIBUTE_CHUNK_SIZE + 1;
762
764
767
769 packet.total_length = pplayer->attribute_block.length;
771
772 memcpy(packet.data,
773 (char *) (pplayer->attribute_block.data) + packet.offset,
774 packet.chunk_length);
775 bytes_left -= packet.chunk_length;
776
777 if (packet.chunk_length < ATTRIBUTE_CHUNK_SIZE) {
778 /* Last chunk is not full. Make sure that delta does
779 * not use random data. */
780 memset(packet.data + packet.chunk_length, 0,
782 }
783
785 }
786
788}
789
790/**********************************************************************/
795 *packet)
796{
797 fc_assert(packet->total_length > 0
798 && packet->total_length < MAX_ATTRIBUTE_BLOCK);
799 /* 500 bytes header, just to be sure */
800 fc_assert(packet->chunk_length > 0
801 && packet->chunk_length < MAX_LEN_PACKET - 500);
802 fc_assert(packet->chunk_length <= packet->total_length);
803 fc_assert(packet->offset >= 0 && packet->offset < packet->total_length);
804
805 log_packet("sending attribute chunk %d/%d %d",
806 packet->offset, packet->total_length, packet->chunk_length);
807}
808
809/**********************************************************************/
819
820/**********************************************************************/
824{
825 static struct packet_handlers default_handlers;
826 static bool initialized = FALSE;
827
828 if (!initialized) {
832 }
833
834 return &default_handlers;
835}
836
837/**********************************************************************/
840const struct packet_handlers *packet_handlers_get(const char *capability)
841{
844 char *tokens[MAX_LEN_CAPSTR / 2];
846 int tokens_num;
847 int functional_tokens_num = 0;
848 int i;
849
850 fc_assert(strlen(capability) < sizeof(functional_capability));
851
852 /* Get functional network capability string. */
853 tokens_num = get_tokens(capability, tokens, ARRAY_SIZE(tokens), " \t\n,");
854 for (i = 0; i < tokens_num; i++) {
855 char *token;
856
857 token = tokens[i];
858 if (token[0] == '+') {
859 token++;
860 }
861
864 }
865 }
868 for (i = 0; i < functional_tokens_num; i++) {
869 if (functional_capability[0] != '\0') {
871 }
873 }
875
876 /* Ensure the hash table is created. */
877 if (packet_handlers == NULL) {
879 }
880
881 /* Lookup handlers for the capabilities or create new handlers. */
883 &phandlers)) {
884 phandlers = fc_malloc(sizeof(*phandlers));
888 phandlers);
889 }
890
892
893 return phandlers;
894}
895
896/**********************************************************************/
901{
903}
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
char * incite_cost
Definition comments.c:76
#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:61
GType type
Definition repodlgs.c:1313
#define fc_assert_ret(condition)
Definition log.h:192
#define log_packet
Definition log.h:138
#define log_test
Definition log.h:137
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action_msg(condition, action, message,...)
Definition log.h:202
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#define FC_STATIC_ASSERT(cond, tag)
Definition log.h:238
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
void post_receive_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
Definition packets.c:652
static void packet_handlers_free(void)
Definition packets.c:812
void * get_packet_from_connection_raw(struct connection *pc, enum packet_type *ptype)
Definition packets.c:373
bool packet_check(struct data_in *din, struct connection *pc)
Definition packets.c:665
void packet_header_init(struct packet_header *packet_header)
Definition packets.c:617
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
const struct packet_handlers * packet_handlers_initial(void)
Definition packets.c:823
const char *const packet_functional_capability
Definition packets_gen.c:30
void packets_deinit(void)
Definition packets.c:900
void pre_send_packet_player_attribute_chunk(struct connection *pc, struct packet_player_attribute_chunk *packet)
Definition packets.c:793
static void packet_header_set(struct packet_header *packet_header)
Definition packets.c:627
void remove_packet_from_buffer(struct socket_packet_buffer *buffer)
Definition packets.c:598
void post_send_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
Definition packets.c:640
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:690
void send_attribute_block(const struct player *pplayer, struct connection *pconn)
Definition packets.c:746
const struct packet_handlers * packet_handlers_get(const char *capability)
Definition packets.c:840
#define get_packet_from_connection(pc, ptype)
Definition packets.h:90
void packet_handlers_fill_capability(struct packet_handlers *phandlers, const char *capability)
const char * packet_name(enum packet_type type)
Definition packets_gen.c:47
void packet_handlers_fill_initial(struct packet_handlers *phandlers)
void delta_stats_reset(void)
Definition packets_gen.c:45
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:223
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
int compare_strings_ptrs(const void *first, const void *second)
Definition shared.c:373
bool str_to_int(const char *str, int *pint)
Definition shared.c:515
#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:307
struct attribute_block_s attribute_block_buffer
Definition player.h:308
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