25#ifdef HAVE_ARPA_INET_H
28#ifdef HAVE_NETINET_IN_H
29#include <netinet/in.h>
53#define JUMBO_SIZE 0xffff
58#define COMPRESSION_BORDER (16*1024+1)
63#define JUMBO_BORDER (64*1024-COMPRESSION_BORDER-1)
65#define log_compress log_debug
66#define log_compress2 log_debug
68#define MAX_DECOMPRESSION 400
76#define PACKET_SIZE_STATISTICS 0
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
99 static int level = -2;
102 const char *s =
getenv(
"FREECIV_COMPRESSION_LEVEL");
123#ifndef FREECIV_NDEBUG
127 pconn->compression.queue.p,
128 pconn->compression.queue.size,
144 log_compress(
"COMPRESS: compressed %lu bytes to %ld (level %d)",
145 (
unsigned long)
pconn->compression.queue.size,
151 unsigned char header[2];
163 unsigned char header[6];
176 log_compress(
"COMPRESS: would enlarge %lu bytes to %ld; "
177 "sending uncompressed",
178 (
unsigned long)
pconn->compression.queue.size,
181 pconn->compression.queue.size);
196#ifdef USE_COMPRESSION
197 pconn->compression.frozen_level--;
199 pconn->compression.frozen_level = 0,
200 "Too many calls to conn_compression_thaw on %s!",
202 if (0 ==
pconn->compression.frozen_level) {
219 log_packet(
"sending packet type=%s(%d) len=%d to %s",
224 pc->client.last_request_id_used =
226 result =
pc->client.last_request_id_used;
230 if (
pc->outgoing_packet_notify) {
234#ifdef USE_COMPRESSION
244#define MAX_LEN_COMPRESS_QUEUE (MAX_LEN_BUFFER/2)
252 log_compress2(
"COMPRESS: huge queue, forcing to flush (%lu/%lu)",
269 log_compress(
"COMPRESS: sending %s alone (%d bytes total)",
274 log_compress2(
"COMPRESS: STATS: alone=%d compression-expand=%d "
275 "compression (before/after) = %d/%d",
283#if PACKET_SIZE_STATISTICS
326#define log_ll log_debug
328#if PACKET_SIZE_STATISTICS == 2
331 log_ll(
"Transmitted packets:");
332 log_ll(
"%8s %8s %8s %s",
"Packets",
"Bytes",
"Byt/Pac",
"Name");
339 log_ll(
"%8d %8d %8d %s(%i)",
344 log_test(
"turn=%d; transmitted %d bytes in %d packets;average size "
348 pc->statistics.bytes_send);
358 pc->statistics.bytes_send = 0;
383#ifdef USE_COMPRESSION
388 void *(*receive_handler)(
struct connection *);
405#ifdef USE_COMPRESSION
424 log_compress(
"COMPRESS: got a normal packet of size %d",
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.");
464 log_verbose(
"Uncompressing of the packet stream failed. "
465 "The connection will be closed now.");
471 }
while (error !=
Z_OK);
513 log_verbose(
"The packet stream is corrupt. The connection "
514 "will be closed now.");
520 utype.type = utype.itype;
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.",
531 log_packet(
"got packet type=(%s)%d len=%d from %s",
537 if (
pc->incoming_packet_notify) {
541#if PACKET_SIZE_STATISTICS
574 log_test(
" [%-25.25s %3d]: %6d packets; %8d bytes total; "
575 "%5d bytes/packet average",
580 log_test(
"received %d bytes in %d packets;average size "
581 "per packet %d bytes",
586 data = receive_handler(
pc);
607 log_debug(
"remove_packet_from_buffer: remove %d; remaining %d",
676 log_packet(
"received long packet (type %d, len %d, rem %lu) from %s",
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);
700 if (
chunk->total_length < 0
701 ||
chunk->chunk_length < 0
707 || (
chunk->offset != 0
715 log_error(
"Received wrong attribute chunk");
719 if (
chunk->offset == 0) {
805 log_packet(
"sending attribute chunk %d/%d %d",
858 if (token[0] ==
'+') {
bool has_capability(const char *cap, const char *capstr)
#define ATTRIBUTE_CHUNK_SIZE
int get_next_request_id(int old_request_id)
void connection_do_buffer(struct connection *pc)
void connection_close(struct connection *pconn, const char *reason)
const char * conn_description(const struct connection *pconn)
bool connection_send_data(struct connection *pconn, const unsigned char *data, int len)
bool conn_compression_frozen(const struct connection *pconn)
void connection_do_unbuffer(struct connection *pc)
int dio_put_uint32_raw(struct raw_data_out *dout, int value)
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
size_t dio_input_remaining(struct data_in *din)
bool dio_get_uint32_raw(struct data_in *din, int *dest)
void dio_input_rewind(struct data_in *din)
bool dio_get_uint16_raw(struct data_in *din, int *dest)
bool dio_get_type_raw(struct data_in *din, enum data_type type, int *dest)
int dio_put_uint16_raw(struct raw_data_out *dout, int value)
size_t data_type_size(enum data_type type)
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
void free_tokens(char **tokens, size_t ntokens)
int get_tokens(const char *str, char **tokens, size_t num_tokens, const char *delimiterset)
static bool is_server(void)
#define fc_assert_ret(condition)
#define log_verbose(message,...)
#define fc_assert(condition)
#define fc_assert_action_msg(condition, action, message,...)
#define fc_assert_ret_val(condition, val)
#define log_debug(message,...)
#define log_error(message,...)
#define FC_STATIC_ASSERT(cond, tag)
#define fc_realloc(ptr, sz)
void post_receive_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
static void packet_handlers_free(void)
void * get_packet_from_connection_raw(struct connection *pc, enum packet_type *ptype)
bool packet_check(struct data_in *din, struct connection *pc)
void packet_header_init(struct packet_header *packet_header)
bool conn_compression_thaw(struct connection *pconn)
const struct packet_handlers * packet_handlers_initial(void)
const char *const packet_functional_capability
void packets_deinit(void)
void pre_send_packet_player_attribute_chunk(struct connection *pc, struct packet_player_attribute_chunk *packet)
static void packet_header_set(struct packet_header *packet_header)
void remove_packet_from_buffer(struct socket_packet_buffer *buffer)
void post_send_packet_server_join_reply(struct connection *pconn, const struct packet_server_join_reply *packet)
int send_packet_data(struct connection *pc, unsigned char *data, int len, enum packet_type packet_type)
void generic_handle_player_attribute_chunk(struct player *pplayer, const struct packet_player_attribute_chunk *chunk)
void send_attribute_block(const struct player *pplayer, struct connection *pconn)
const struct packet_handlers * packet_handlers_get(const char *capability)
#define get_packet_from_connection(pc, ptype)
void packet_handlers_fill_capability(struct packet_handlers *phandlers, const char *capability)
const char * packet_name(enum packet_type type)
void packet_handlers_fill_initial(struct packet_handlers *phandlers)
void delta_stats_reset(void)
void delta_stats_report(void)
int send_packet_player_attribute_chunk(struct connection *pc, const struct packet_player_attribute_chunk *packet)
@ PACKET_PROCESSING_FINISHED
#define MAX_ATTRIBUTE_BLOCK
struct setting_list * level[OLEVELS_NUM]
int compare_strings_ptrs(const void *first, const void *second)
bool str_to_int(const char *str, int *pint)
#define ADD_TO_POINTER(p, n)
unsigned char data[ATTRIBUTE_CHUNK_SIZE]
struct attribute_block_s attribute_block
struct attribute_block_s attribute_block_buffer
#define sz_strlcat(dest, src)