DELTA 26834 2287 414
SVN  ®K¯0O …j ¶ ¨[…a™®/FREECIV_JSON_CONNECTION
#include "dataio_json.h"
#elseREECIV_JSON_CONNECTION */ENDREP
DELTA 27705 1216 572
SVN  ›9œ< …C œ …(…;  \Š]ataio_json.c	\
		dataio_jsonackets_json.h	\
		packets_json.cENDREP
DELTA
SVN   ´´€´/********************************************************************** 
 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/
#ifndef FC__PACKETS_JSON_H
#define FC__PACKETS_JSON_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <jansson.h>
  
struct connection;
struct data_in;

#include "connection.h"		/* struct connection, MAX_LEN_* */
#include "diptreaty.h"
#include "effects.h"
#include "events.h"
#include "improvement.h"	/* bv_imprs */
#include "map.h"
#include "player.h"
#include "requirements.h"
#include "shared.h"		/* MAX_LEN_ADDR */
#include "spaceship.h"
#include "team.h"
#include "traderoutes.h"
#include "unittype.h"
#include "worklist.h"


/* Used in network protocol. */
#define MAX_LEN_MSG             1536
#define MAX_LEN_ROUTE		2000	  /* MAX_LEN_PACKET/2 - header */

/* The size of opaque (void *) data sent in the network packet.  To avoid
 * fragmentation issues, this SHOULD NOT be larger than the standard
 * ethernet or PPP 1500 byte frame size (with room for headers).
 *
 * Do not spend much time optimizing, you have no idea of the actual dynamic
 * path characteristics between systems, such as VPNs and tunnels.
 *
 * Used in network protocol.
 */
#define ATTRIBUTE_CHUNK_SIZE    (1400)

/* Used in network protocol. */
enum report_type {
  REPORT_WONDERS_OF_THE_WORLD,
  REPORT_TOP_5_CITIES,
  REPORT_DEMOGRAPHIC,
  REPORT_ACHIEVEMENTS
};

/* Used in network protocol. */
enum unit_info_use {
  UNIT_INFO_IDENTITY,
  UNIT_INFO_CITY_SUPPORTED,
  UNIT_INFO_CITY_PRESENT
};

/* Used in network protocol. */
enum authentication_type {
  AUTH_LOGIN_FIRST,   /* request a password for a returning user */
  AUTH_NEWUSER_FIRST, /* request a password for a new user */
  AUTH_LOGIN_RETRY,   /* inform the client to try a different password */
  AUTH_NEWUSER_RETRY  /* inform the client to try a different [new] password */
};

#include "packets_gen.h"

struct packet_handlers {
  union {
    int (*no_packet)(struct connection *pconn);
    int (*packet)(struct connection *pconn, const void *packet);
    int (*force_to_send)(struct connection *pconn, const void *packet,
                         bool force_to_send);
  } send[PACKET_LAST];
  void *(*receive[PACKET_LAST])(struct connection *pconn);
};

void *get_packet_from_connection(struct connection *pc,
                                 enum packet_type *ptype);
void remove_packet_from_buffer(struct socket_packet_buffer *buffer);

void send_attribute_block(const struct player *pplayer,
			  struct connection *pconn);
void generic_handle_player_attribute_chunk(struct player *pplayer,
					   const struct
					   packet_player_attribute_chunk
					   *chunk);
void packet_handlers_fill_initial(struct packet_handlers *phandlers);
void packet_handlers_fill_capability(struct packet_handlers *phandlers,
                                     const char *capability);
const char *packet_name(enum packet_type type);
bool packet_has_game_info_flag(enum packet_type type);

void packet_header_init(struct packet_header *packet_header);
void post_send_packet_server_join_reply(struct connection *pconn,
                                        const struct packet_server_join_reply
                                        *packet);
void post_receive_packet_server_join_reply(struct connection *pconn,
                                           const struct
                                           packet_server_join_reply *packet);

void pre_send_packet_player_attribute_chunk(struct connection *pc,
					    struct packet_player_attribute_chunk
					    *packet);

const struct packet_handlers *packet_handlers_initial(void);
const struct packet_handlers *packet_handlers_get(const char *capability);

#define SEND_PACKET_START(packet_type) \
  unsigned char buffer[MAX_LEN_PACKET]; \
  char *json_buffer = NULL; \
  struct data_out dout; \
  dout.json = json_object(); \
  \
  dio_output_init(&dout, buffer, sizeof(buffer)); \
  dio_put_uint16_old(&dout, 0); \
  dio_put_uint16_old(&dout, packet_type); \
  dio_put_uint8(&dout, "pid", packet_type);

#define SEND_PACKET_END(packet_type) \
  { \
    json_buffer = json_dumps(dout.json, JSON_COMPACT | JSON_ENSURE_ASCII); \
    if (json_buffer) { \
      dio_put_string_old(&dout, json_buffer); \
    } \
    size_t size = dio_output_used(&dout); \
    \
    dio_output_rewind(&dout); \
    dio_put_uint16_old(&dout, size); \
    free(json_buffer); \
    json_decref(dout.json); \
    fc_assert(!dout.too_short); \
    return send_packet_data(pc, buffer, size, packet_type); \
  }

#define RECEIVE_PACKET_START(packet_type, result) \
  struct packet_type packet_buf, *result = &packet_buf;

#define RECEIVE_PACKET_END(result) \
  json_decref(pc->json_packet); \
  result = fc_malloc(sizeof(*result)); \
  *result = packet_buf; \
  return result;

#define RECEIVE_PACKET_FIELD_ERROR(field, ...) \
  log_packet("Error on field '" #field "'" __VA_ARGS__); \
  return NULL

int send_packet_data(struct connection *pc, unsigned char *data, int len,
                     enum packet_type packet_type);

/* Utilities to exchange strings and string vectors. */
#define PACKET_STRVEC_SEPARATOR '\3'
#define PACKET_STRVEC_COMPUTE(str, strvec)                                  \
  if (NULL != strvec) {                                                     \
    strvec_to_str(strvec, PACKET_STRVEC_SEPARATOR, str, sizeof(str));       \
  } else {                                                                  \
    str[0] = '\0';                                                          \
  }
#define PACKET_STRVEC_EXTRACT(strvec, str)                                  \
  if ('\0' != str[0]) {                                                     \
    strvec = strvec_new();                                                  \
    strvec_from_str(strvec, PACKET_STRVEC_SEPARATOR, str);                  \
  } else {                                                                  \
    strvec = NULL;                                                          \
  }

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif  /* FC__PACKETS_JSON_H */
ENDREP
DELTA
SVN   ÖGÖG€ÖG/********************************************************************** 
 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

/*
 * The DataIO module provides a system independent (endianess and
 * sizeof(int) independent) way to write and read data. It supports
 * multiple datas which are collected in a buffer. It provides
 * recognition of error cases like "not enough space" or "not enough
 * data".
 */

#ifdef HAVE_CONFIG_H
#include <fc_config.h>
#endif

#ifdef FREECIV_JSON_CONNECTION

#include <limits.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_WINSOCK
#include <winsock.h>
#endif

/* utility */
#include "bitvector.h"
#include "capability.h"
#include "log.h"
#include "mem.h"
#include "support.h"

/* common */
#include "events.h"
#include "player.h"
#include "requirements.h"
#include "tech.h"
#include "worklist.h"

#include "dataio.h"

static bool get_conv(char *dst, size_t ndst, const char *src,
		     size_t nsrc);

static DIO_PUT_CONV_FUN put_conv_callback = NULL;
static DIO_GET_CONV_FUN get_conv_callback = get_conv;

/* Uncomment to make field range tests to asserts, fatal with -F */
/* #define FIELD_RANGE_ASSERT */

#ifdef FIELD_RANGE_ASSERT
/* This evaluates _test_ twice. If that's a problem,
 * it should evaluate it just once and store result to variable.
 * That would lose verbosity of the assert message. */
#define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
  fc_assert(!(_test_));                                   \
  if (_test_) {                                           \
    _action_                                              \
  }
#else
#define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
  if (_test_) {                                           \
    _action_                                              \
    log_error(_format_, ## __VA_ARGS__);                  \
  }
#endif

/**************************************************************************
  Sets string conversion callback to be used when putting text.
**************************************************************************/
void dio_set_put_conv_callback(DIO_PUT_CONV_FUN fun)
{
  put_conv_callback = fun;
}

/**************************************************************************
 Returns FALSE if the destination isn't large enough or the source was
 bad. This is default get_conv_callback.
**************************************************************************/
static bool get_conv(char *dst, size_t ndst, const char *src,
		     size_t nsrc)
{
  size_t len = nsrc;		/* length to copy, not including null */
  bool ret = TRUE;

  if (ndst > 0 && len >= ndst) {
    ret = FALSE;
    len = ndst - 1;
  }

  memcpy(dst, src, len);
  dst[len] = '\0';

  return ret;
}

/**************************************************************************
  Sets string conversion callback to use when getting text.
**************************************************************************/
void dio_set_get_conv_callback(DIO_GET_CONV_FUN fun)
{
  get_conv_callback = fun;
}

/**************************************************************************
  Returns TRUE iff the output has size bytes available.
**************************************************************************/
static bool enough_space(struct data_out *dout, size_t size)
{
  if (dout->current + size > dout->dest_size) {
    dout->too_short = TRUE;
    return FALSE;
  } else {
    dout->used = MAX(dout->used, dout->current + size);
    return TRUE;
  }
}

/**************************************************************************
  Returns TRUE iff the input contains size unread bytes.
**************************************************************************/
static bool enough_data(struct data_in *din, size_t size)
{
  return dio_input_remaining(din) >= size;
}

/**************************************************************************
  Initializes the output to the given output buffer and the given
  buffer size.
**************************************************************************/
void dio_output_init(struct data_out *dout, void *destination,
		     size_t dest_size)
{
  dout->dest = destination;
  dout->dest_size = dest_size;
  dout->current = 0;
  dout->used = 0;
  dout->too_short = FALSE;
}

/**************************************************************************
  Return the maximum number of bytes used.
**************************************************************************/
size_t dio_output_used(struct data_out *dout)
{
  return dout->used;
}

/**************************************************************************
  Rewinds the stream so that the put-functions start from the
  beginning.
**************************************************************************/
void dio_output_rewind(struct data_out *dout)
{
  dout->current = 0;
}

/**************************************************************************
  Initializes the input to the given input buffer and the given
  number of valid input bytes.
**************************************************************************/
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
{
  din->src = src;
  din->src_size = src_size;
  din->current = 0;
}

/**************************************************************************
  Rewinds the stream so that the get-functions start from the
  beginning.
**************************************************************************/
void dio_input_rewind(struct data_in *din)
{
  din->current = 0;
}

/**************************************************************************
  Return the number of unread bytes.
**************************************************************************/
size_t dio_input_remaining(struct data_in *din)
{
  return din->src_size - din->current;
}

/**************************************************************************
  Return the size of the data_type in bytes.
**************************************************************************/
size_t data_type_size(enum data_type type)
{
  switch (type) {
  case DIOT_UINT8:
  case DIOT_SINT8:
    return 1;
  case DIOT_UINT16:
  case DIOT_SINT16:
    return 2;
  case DIOT_UINT32:
  case DIOT_SINT32:
    return 4;
  case DIOT_LAST:
    break;
  }

  fc_assert_msg(FALSE, "data_type %d not handled.", type);
  return 0;
}

/**************************************************************************
   Skips 'n' bytes.
**************************************************************************/
bool dio_input_skip(struct data_in *din, size_t size)
{
  if (enough_data(din, size)) {
    din->current += size;
    return TRUE;
  } else {
    return FALSE;
  }
}

/**************************************************************************
  Insert 8 bit value with json.
**************************************************************************/
void dio_put_uint8(struct data_out *dout, char *key, int value)
{
  json_object_set_new(dout->json, key, json_integer(value));
}

/**************************************************************************
  Insert value using 8 bits. May overflow.
**************************************************************************/
void dio_put_uint8_old(struct data_out *dout, int value)
{
  uint8_t x = value;
  FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_1_byte);

  FIELD_RANGE_TEST((int) x != value, ,
                   "Trying to put %d into 8 bits; "
                   "it will result %d at receiving side.",
                   value, (int) x);

  if (enough_space(dout, 1)) {
    memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 1);
    dout->current++;
  }
}

/**************************************************************************
  Insert value using 16 bits. May overflow.
**************************************************************************/
void dio_put_uint16_old(struct data_out *dout, int value)
{
  uint16_t x = htons(value);
  FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);

  FIELD_RANGE_TEST((int) ntohs(x) != value, ,
                   "Trying to put %d into 16 bits; "
                   "it will result %d at receiving side.",
                   value, (int) ntohs(x));

  if (enough_space(dout, 2)) {
    memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 2);
    dout->current += 2;
  }
}

/**************************************************************************
  Insert value using 32 bits. May overflow.
**************************************************************************/
void dio_put_uint16(struct data_out *dout, char *key, int value)
{
  json_object_set_new(dout->json, key, json_integer(value));
}

/**************************************************************************
  Insert block directly from memory.
**************************************************************************/
void dio_put_memory_old(struct data_out *dout, const void *value, size_t size)
{
  if (enough_space(dout, size)) {
    memcpy(ADD_TO_POINTER(dout->dest, dout->current), value, size);
    dout->current += size;
  }
}

/**************************************************************************
  Insert NULL-terminated string. Conversion callback is used if set.
**************************************************************************/
void dio_put_string_old(struct data_out *dout, const char *value)
{
  if (put_conv_callback) {
    size_t length;
    char *buffer;

    if ((buffer = (*put_conv_callback) (value, &length))) {
      dio_put_memory_old(dout, buffer, length + 1);
      free(buffer);
    }
  } else {
    dio_put_memory_old(dout, value, strlen(value) + 1);
  }
}

/**************************************************************************
  Insert unit type numbers from value array as 8 bit values until there is
  value U_LAST or MAX_NUM_UNIT_LIST numbers have been inserted.
**************************************************************************/
void dio_put_unit_list(struct data_out *dout, char *key, const int *value)
{
  /* TODO: implement */
}

/**************************************************************************
  Insert building type numbers from value array as 8 bit values until there
  is value B_LAST or MAX_NUM_BUILDING_LIST numbers have been inserted.
**************************************************************************/
void dio_put_building_list(struct data_out *dout, char *key, const int *value)
{
  /* TODO: implement */
}

/**************************************************************************
...
**************************************************************************/
void dio_put_worklist(struct data_out *dout, char *key, const struct worklist *pwl)
{
  /* TODO: implement */
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_uint8(struct data_out *dout, char *key, int *values, int size)
{
  int i;
  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    json_array_append_new(array, json_integer(values[i]));
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_uint32(struct data_out *dout, char *key, int *values, int size)
{
  int i;
  json_t *array = json_array();

  for (i = 0; i < size; i++) {
    json_array_append_new(array, json_integer(values[i]));
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_sint8(struct data_out *dout, char *key, int *values, int size)
{
  int i;
  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    json_array_append_new(array, json_integer(values[i]));
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_sint16(struct data_out *dout, char *key, int *values, int size)
{
  int i;
  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    json_array_append_new(array, json_integer(values[i]));
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_sint32(struct data_out *dout, char *key, int *values, int size)
{
  int i;
  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    json_array_append_new(array, json_integer(values[i]));
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_array_bool8(struct data_out *dout, char *key, bool *values, int size)
{
  int i;
  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    json_array_append_new(array, values[i] ? json_true() : json_false());
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
 Receive uint8 value to dest.
**************************************************************************/
bool dio_get_uint8_old(struct data_in *din, int *dest)
{
  uint8_t x;

  FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_byte);

  if (!enough_data(din, 1)) {
    log_packet("Packet too short to read 1 byte");

    return FALSE;
  }

  memcpy(&x, ADD_TO_POINTER(din->src, din->current), 1);
  *dest = x;
  din->current++;
  return TRUE;
}

/**************************************************************************
 Receive uint8 value to dest with json.
**************************************************************************/
bool dio_get_uint8(json_t *json_packet, char *key, int *dest)
{
  json_t *pint = json_object_get(json_packet, key);

  if (!pint) {
    log_error("ERROR: Unable to get uint8 with key: %s", key);
    return FALSE;
  } 
  *dest = json_integer_value(pint);

  if (!dest) {
    log_error("ERROR: Unable to get unit8 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
 Receive uint16 value to dest with json.
**************************************************************************/
bool dio_get_uint16(json_t *json_packet, char *key, int *dest)
{
  json_t *pint = json_object_get(json_packet, key);

  if (!pint) {
    log_error("ERROR: Unable to get uint16 with key: %s", key);
    return FALSE;
  } 
  *dest = json_integer_value(pint);

  if (!dest) {
    log_error("ERROR: Unable to get unit16 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
 ..
**************************************************************************/
bool dio_get_uint32(json_t *json_packet, char *key, int *dest)
{
  json_t *pint = json_object_get(json_packet, key);

  if (!pint) {
    log_error("ERROR: Unable to get uint32 with key: %s", key);
    return FALSE;
  } 
  *dest = json_integer_value(pint);

  if (!dest) {
    log_error("ERROR: Unable to get unit32 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
 ..
**************************************************************************/
bool dio_get_tech_list(json_t *json_packet, char *key, int *dest)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
  Take unit type numbers until U_LAST encountered, or MAX_NUM_UNIT_LIST
  types retrieved.
**************************************************************************/
bool dio_get_unit_list(json_t *json_packet, char *key, int *dest)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
 ..
**************************************************************************/
bool dio_get_building_list(json_t *json_packet, char *key, int *dest)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
 ..
**************************************************************************/
bool dio_get_worklist(json_t *json_packet, char *key, struct worklist *pwl)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
 Receive uint16 value to dest.
**************************************************************************/
bool dio_get_uint16_old(struct data_in *din, int *dest)
{
  uint16_t x;

  FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);

  if (!enough_data(din, 2)) {
    log_packet("Packet too short to read 2 bytes");

    return FALSE;
  }

  memcpy(&x, ADD_TO_POINTER(din->src, din->current), 2);
  *dest = ntohs(x);
  din->current += 2;
  return TRUE;
}

/**************************************************************************
  Take string. Conversion callback is used.
**************************************************************************/
bool dio_get_string_old(struct data_in *din, char *dest, size_t max_dest_size)
{
  char *c;
  size_t offset, remaining;

  fc_assert(max_dest_size > 0);

  if (!enough_data(din, 1)) {
    log_packet("Got a bad string");
    return FALSE;
  }

  remaining = dio_input_remaining(din);
  c = ADD_TO_POINTER(din->src, din->current);

  /* avoid using strlen (or strcpy) on an (unsigned char*)  --dwp */
  for (offset = 0; offset < remaining && c[offset] != '\0'; offset++) {
    /* nothing */
  }

  if (offset >= remaining) {
    log_packet("Got a too short string");
    return FALSE;
  }

  if (!(*get_conv_callback) (dest, max_dest_size, c, offset)) {
    log_packet("Got a bad encoded string");
    return FALSE;
  }

  din->current += offset + 1;
  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_uint8_vec8(json_t *json_packet, char *key, int **values, int stop_value)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_uint16_vec8(json_t *json_packet, char *key, int **values,
                         int stop_value)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
  ..
**************************************************************************/
bool dio_get_requirement(json_t *json_packet, char *key, struct requirement *preq)
{
  /* TODO: implement */
  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
void dio_put_uint32(struct data_out *dout, char *key, int value)
{
  json_object_set_new(dout->json, key, json_integer(value));
}

/**************************************************************************
...
**************************************************************************/
void dio_put_bool8(struct data_out *dout, char *key, bool value)
{
  json_object_set_new(dout->json, key, value ? json_true() : json_false());
}

/**************************************************************************
...
**************************************************************************/
void dio_put_bool32(struct data_out *dout, char *key, bool value)
{
  json_object_set_new(dout->json, key, value ? json_true() : json_false());
}

/**************************************************************************
...
**************************************************************************/
void dio_put_ufloat(struct data_out *dout, char *key, float value, int float_factor)
{
  json_object_set_new(dout->json, key, json_real(value));
}

/**************************************************************************
...
**************************************************************************/
void dio_put_sfloat(struct data_out *dout, char *key, float value, int float_factor)
{
  json_object_set_new(dout->json, key, json_real(value));
}

/**************************************************************************
...
**************************************************************************/
void dio_put_uint8_vec8(struct data_out *dout, char *key, int *values, int stop_value)
{
  /* TODO: implement. */
}

/**************************************************************************
...
**************************************************************************/
void dio_put_uint16_vec8(struct data_out *dout, char *key, int *values,
                         int stop_value)
{
  /* TODO: implement. */
}

/**************************************************************************
...
**************************************************************************/
void dio_put_memory(struct data_out *dout, char *key, const void *value, size_t size)
{
  /* TODO: implement */
}

/**************************************************************************
...
**************************************************************************/
void dio_put_string(struct data_out *dout, char *key, const char *value)
{
  json_object_set_new(dout->json, key, json_string(value));
}

/**************************************************************************
...
**************************************************************************/
void dio_put_string_array(struct data_out *dout, char *key, 
		          const char *value, int size)
{
  int i;

  json_t *array = json_array();
  for (i = 0; i < size; i++) {
    if (value != NULL) {
      json_array_append_new(array, json_string(value + i));
    }
  }
  
  json_object_set_new(dout->json, key, array);
}

/**************************************************************************
...
**************************************************************************/
void dio_put_tech_list(struct data_out *dout, char *key, const int *value)
{
  /* TODO: implement */
}

/**************************************************************************
  ..
**************************************************************************/
void dio_put_requirement(struct data_out *dout, char *key, const struct requirement *preq, int size)
{
  /* TODO: implement */
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_bool8(json_t *json_packet, char *key, bool * dest)
{
  json_t *pbool = json_object_get(json_packet, key);

  if (!pbool) {
    log_error("ERROR: Unable to get bool8 with key: %s", key);
    return FALSE;
  } 
  *dest = json_is_true(pbool);

  if (!dest) {
    log_error("ERROR: Unable to get bool with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_bool32(json_t *json_packet, char *key, bool *dest)
{
  json_t *pbool = json_object_get(json_packet, key);

  if (!pbool) {
    log_error("ERROR: Unable to get bool32 with key: %s", key);
    return FALSE;
  }
  *dest = json_is_true(pbool);

  if (!dest) {
    log_error("ERROR: Unable to get bool32 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
  ...
**************************************************************************/
bool dio_get_ufloat(json_t *json_packet, char *key, float *dest, int float_factor)
{
  json_t *preal = json_object_get(json_packet, key);

  if (!preal) {
    log_error("ERROR: Unable to get real with key: %s", key);
    return FALSE;
  }
  *dest = json_real_value(preal);

  return TRUE;
}

/**************************************************************************
  ...
**************************************************************************/
bool dio_get_sfloat(json_t *json_packet, char *key, float *dest, int float_factor)
{
  json_t *preal = json_object_get(json_packet, key);

  if (!preal) {
    log_error("ERROR: Unable to get real with key: %s", key);
    return FALSE;
  }
  *dest = json_real_value(preal);

  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_sint8(json_t *json_packet, char *key, int *dest)
{
  json_t *pint = json_object_get(json_packet, key);

  if (!pint) {
    log_error("ERROR: Unable to get sint8 with key: %s", key);
    return FALSE;
  }
  *dest = json_integer_value(pint);

  if (!dest) {
    log_error("ERROR: Unable to get sint8 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_sint16(json_t *json_packet, char *key, int *dest)
{
  json_t *pint = json_object_get(json_packet, key);

  if (!pint) {
    log_error("ERROR: Unable to get sint16 with key: %s", key);
    return FALSE;
  }
  *dest = json_integer_value(pint);

  if (!dest) {
    log_error("ERROR: Unable to get sint16 with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_memory(json_t *json_packet, char *key, void *dest, size_t dest_size)
{
  /* TODO: implement */ 
  return TRUE;
}

/**************************************************************************
...
**************************************************************************/
bool dio_get_string(json_t *json_packet, char *key, char *dest, size_t max_dest_size)
{
  json_t *pstring = json_object_get(json_packet, key);

  if (!pstring) {
    log_error("ERROR: Unable to get string with key: %s", key);
    return FALSE;
  }
  const char *result_str = json_string_value(pstring);

  if (dest && !(*get_conv_callback) (dest, max_dest_size, result_str, strlen(result_str))) {
    log_error("ERROR: Unable to get string with key: %s", key);
    return FALSE;
  }

  return TRUE;
}

#endif /* FREECIV_JSON_CONNECTION */
ENDREP
DELTA 27339 0 27161
SVN  ƒÒƒÓ}&‚i é( €T #é7€E rë: ì,¤ §AíB« ‚¼•#ifndef FREECIV_JSON_CONNECTION
          %(c)s
#endif /* FREECIV_JSON_CONNECTION */#ifndef FREECIV_JSON_CONNECTION
        %(c)s
#endif /* FREECIV_JSON_CONNECTION */
      }
    } '''%self.get_dict(vars())
        else:
            return '''
    {
#ifndef FREECIV_JSON_CONNECTION #endif /* FREECIV_JSON_CONNECTION */DIO_GET(%(dataio_type)s, &din, \"%(name)s\"ENDREP
DELTA 27337 6167 3106
SVN  â*âqC …o  Ü?…k¦fndef FREECIV_JSON_CONNECTION
#endif /* FREECIV_JSON_CONNECTION */
ENDREP
DELTA 27832 0 386
SVN  ‚üv‚ÿ{1„ —z €R ‚¿˜$€( „‚Ø€e ƒ2‚Ü¤ IÄ 4‚à€e ›6‚á@¥
#ifndef FREECIV_JSON_CONNECTION
static void send_lanserver_response(void);
#endiffd_set readfs, exceptfs;
  struct timeval tv;
#ifndef FREECIV_JSON_CONNECTION
  char msgbuf[128];
  struct data_in din;
  int type;
#endif /* FREECIV_JSON_CONNECTION */  /* We would need a raw network connection for broadcast messages */
#ifndef FREECIV_JSON_CONNECTION#endif /* FREECIV_JSON_CONNECTION */  /* We would need a raw network connection for broadcast messages */
#ifndef FREECIV_JSON_CONNECTION#endif /* FREECIV_JSON_CONNECTION */
ENDREP
DELTA
SVN   ¶\¶\€¶\/********************************************************************** 
 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/
#ifndef FC__DATAIO_JSON_H
#define FC__DATAIO_JSON_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <jansson.h>

#include "bitvector.h"
#include "support.h"            /* bool type */

struct worklist;
struct requirement;

struct data_in {
  const void *src;
  size_t src_size, current;
};

struct data_out {
  void *dest;
  json_t *json;
  size_t dest_size, used, current;
  bool too_short;		/* set to 1 if try to read past end */
};

/* Used for dio_<put|get>_type() methods.
 * NB: we only support integer handling currently. */
enum data_type {
  DIOT_UINT8,
  DIOT_UINT16,
  DIOT_UINT32,
  DIOT_SINT8,
  DIOT_SINT16,
  DIOT_SINT32,

  DIOT_LAST
};

/* network string conversion */
typedef char *(*DIO_PUT_CONV_FUN) (const char *src, size_t *length);
void dio_set_put_conv_callback(DIO_PUT_CONV_FUN fun);

typedef bool(*DIO_GET_CONV_FUN) (char *dst, size_t ndst,
				 const char *src, size_t nsrc);
void dio_set_get_conv_callback(DIO_GET_CONV_FUN fun);

/* General functions */
void dio_output_init(struct data_out *dout, void *destination,
		     size_t dest_size);
void dio_output_rewind(struct data_out *dout);
size_t dio_output_used(struct data_out *dout);

void dio_input_init(struct data_in *dout, const void *src, size_t src_size);
void dio_input_rewind(struct data_in *din);
size_t dio_input_remaining(struct data_in *din);
bool dio_input_skip(struct data_in *din, size_t size);

size_t data_type_size(enum data_type type);

/* gets */
bool dio_get_type(struct data_in *din, enum data_type type, int *dest)
    fc__attribute((nonnull (3)));

bool dio_get_uint8(json_t *json_packet, char *key, int *dest);
bool dio_get_uint16(json_t *json_packet, char *key, int *dest);
bool dio_get_uint32(json_t *json_packet, char *key, int *dest);

bool dio_get_uint16_old(struct data_in *din, int *dest);
bool dio_get_uint8_old(struct data_in *din, int *dest);
bool dio_get_sint8(json_t *json_packet, char *key, int *dest);
bool dio_get_sint16(json_t *json_packet, char *key, int *dest);
#define dio_get_sint32(d,v,x) dio_get_uint32(d,v,x)


bool dio_get_bool8(json_t *json_packet, char *key, bool *dest);
bool dio_get_bool32(json_t *json_packet, char *key, bool *dest);
bool dio_get_ufloat(json_t *json_packet, char *key, float *dest, int float_factor);
bool dio_get_sfloat(json_t *json_packet, char *key, float *dest, int float_factor);
bool dio_get_memory(json_t *json_packet, char *key, void *dest, size_t dest_size);
bool dio_get_string(json_t *json_packet, char *key, char *dest, size_t max_dest_size);
bool dio_get_string_old(struct data_in *din, char *dest, size_t max_dest_size);
bool dio_get_bit_string(json_t *json_packet, char *key, char *dest,
 			size_t max_dest_size);
bool dio_get_tech_list(json_t *json_packet, char *key, int *dest);
bool dio_get_unit_list(json_t *json_packet, char *key, int *dest);
bool dio_get_building_list(json_t *json_packet, char *key, int *dest);
bool dio_get_worklist(json_t *json_packet, char *key, struct worklist *pwl);
bool dio_get_requirement(json_t *json_packet, char *key, struct requirement *preq);

bool dio_get_uint8_vec8(json_t *json_packet, char *key, int **values, int stop_value);
bool dio_get_uint16_vec8(json_t *json_packet, char *key, int **values, int stop_value);

/* Should be a function but we need some macro magic. */
#define DIO_BV_GET(pdin, bv) \
  dio_get_memory(pc->json_packet, "mem", (bv).vec, sizeof((bv).vec))

#define DIO_GET(f, d, k, ...) dio_get_##f(pc->json_packet, k, ## __VA_ARGS__)

/* puts */
void dio_put_type(struct data_out *dout, enum data_type type, char *key, int value);

void dio_put_uint8(struct data_out *dout, char *key, int value);
void dio_put_uint8_old(struct data_out *dout, int value);
void dio_put_uint16(struct data_out *dout, char *key, int value);
void dio_put_uint32(struct data_out *dout, char *key, int value);
void dio_put_uint16_old(struct data_out *dout, int value);

void dio_put_array_uint8(struct data_out *dout, char *key, int *values, int size);
void dio_put_array_uint32(struct data_out *dout, char *key, int *values, int size);
void dio_put_array_sint8(struct data_out *dout, char *key, int *values, int size);
void dio_put_array_sint16(struct data_out *dout, char *key, int *values, int size);
void dio_put_array_sint32(struct data_out *dout, char *key, int *values, int size);
void dio_put_array_bool8(struct data_out *dout, char *key, bool *values, int size);

#define dio_put_sint8(d,k,v) dio_put_uint8(d,k,v)
#define dio_put_sint16(d,k,v) dio_put_uint16(d,k,v)
#define dio_put_sint32(d,k,v) dio_put_uint32(d,k,v)

void dio_put_bool8(struct data_out *dout, char *key, bool value);
void dio_put_bool32(struct data_out *dout, char *key, bool value);
void dio_put_ufloat(struct data_out *dout, char *key, float value, int float_factor);
void dio_put_sfloat(struct data_out *dout, char *key, float value, int float_factor);

void dio_put_memory(struct data_out *dout, char *key, const void *value, size_t size);
void dio_put_string(struct data_out *dout, char *key, const char *value);
void dio_put_bit_string(struct data_out *dout, char *key, const char *value);
void dio_put_city_map(struct data_out *dout, char *key, const char *value);
void dio_put_tech_list(struct data_out *dout, char *key, const int *value);
void dio_put_unit_list(struct data_out *dout, char *key, const int *value);
void dio_put_building_list(struct data_out *dout, char *key, const int *value);
void dio_put_worklist(struct data_out *dout, char *key, const struct worklist *pwl);
void dio_put_requirement(struct data_out *dout, char *key, const struct requirement *preq, int size);

void dio_put_uint8_vec8(struct data_out *dout, char *key, int *values, int stop_value);
void dio_put_uint16_vec8(struct data_out *dout, char *key, int *values, int stop_value);
void dio_put_string_old(struct data_out *dout, const char *value);
void dio_put_memory_old(struct data_out *dout, const void *value, size_t size);
void dio_put_string_array(struct data_out *dout, char *key, const char *value, int size);

/* Should be a function but we need some macro magic. */
#define DIO_BV_PUT(pdout, type, bv) \
  dio_put_memory((pdout), type, (bv).vec, sizeof((bv).vec))

#define DIO_PUT(f, d, k, ...) dio_put_##f(d, k, ## __VA_ARGS__)

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif  /* FC__DATAIO_JSON_H */
ENDREP
DELTA 27336 10261 6107
SVN  ¶¶tP …l · °…c™µqFREECIV_JSON_CONNECTION
#include "packets_json.h"
#elseREECIV_JSON_CONNECTION */ENDREP
DELTA 27009 0 2728
SVN  â$êQ\“= ˆ  †Fˆ€† P³ §0€7 ƒO·h€F ƒR¼e€F sÁe€# ‚#Ó_€H eÓp ‚+Ø €‚ ^á> _Ø ‡ L¤?€ƒ €sá1¦fndef FREECIV_JSON_CONNECTION Uncomment to make field range tests to asserts, fatal with -F */
/* #define FIELD_RANGE_ASSERT */

#ifdef FIELD_RANGE_ASSERT
/* This evaluates _test_ twice. If that's a problem,
 * it should evaluate it just once and store result to variable.
 * That would lose verbosity of the assert message. */
#define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
  fc_assert(!(_test_));                                   \
  if (_test_) {                                           \
    _action_                                              \
  }
#else
#define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
  if (_test_) {                                           \
    _action_                                              \
    log_error(_format_, ## __VA_ARGS__);                  \
  }
#endifFIELD_RANGE_TEST((int) x != value, ,
                   "Trying to put %d into 8 bits; "
                   "it will result %d at receiving side.",
                   value, (int) x);FIELD_RANGE_TEST((int) ntohs(x) != value, ,
                   "Trying to put %d into 16 bits; "
                   "it will result %d at receiving side.",
                   value, (int) ntohs(x));FIELD_RANGE_TEST((int) ntohl(x) != value, ,
                   "Trying to put %d into 32 bits; "
                   "it will result %d at receiving side.",
                   value, (int) ntohl(x));FIELD_RANGE_TEST(value != TRUE && value != FALSE,
                   value = (value != FALSE);,
                   "Trying to put a non-boolean: %d", (int) value);FIELD_RANGE_TEST(value != TRUE && value != FALSE,
                   value = (value != FALSE);,
                   "Trying to put a non-boolean: %d",
                   (int) value);

  dio_put_uint32FIELD_RANGE_TEST(fabsf((float) v / float_factor - value) >= 1.0 / float_factor, ,
                   "Trying to put %f with factor %d in 32 bits; "
                   "it will result %f at receiving side.",
                   value, float_factor, (float) v / float_factor);

  dio_put_u sint32**/
void dio_put_sfloat(struct data_out *dout, float value, int float_factor)
{
  int32_t v = value * float_factor;

  FIELD_RANGE_TEST(fabsf((float) v / float_factor - value) >= 1.0 / float_factor, ,
                   "Trying to put %f with factor %d in 32 bits; "
                   "it will result %f at receiving side.",
                   value, float_factor, (float) v / float_factor);
#endif /* FREECIV_JSON_CONNECTION */
ENDREP
DELTA
SVN   á.á.€á./********************************************************************** 
 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

#ifdef HAVE_CONFIG_H
#include <fc_config.h>
#endif

#ifdef FREECIV_JSON_CONNECTION

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_WINSOCK
#include <winsock.h>
#endif

#include <jansson.h>

/* utility */
#include "capability.h"
#include "fcintl.h"
#include "log.h"
#include "mem.h"
#include "shared.h"
#include "support.h"

/* commmon */
#include "dataio.h"
#include "game.h"
#include "events.h"
#include "map.h"

#include "packets_json.h"

#ifdef USE_COMPRESSION
#include <zlib.h>
/*
 * Value for the 16bit size to indicate a jumbo packet
 */
#define JUMBO_SIZE		0xffff

/*
 * All values 0<=size<COMPRESSION_BORDER are uncompressed packets.
 */
#define COMPRESSION_BORDER	(16*1024+1)

/*
 * All compressed packets this size or greater are sent as a jumbo packet.
 */
#define JUMBO_BORDER 		(64*1024-COMPRESSION_BORDER-1)
#endif

#define log_compress    log_debug
#define log_compress2   log_debug

/* 
 * Valid values are 0, 1 and 2. For 2 you have to set generate_stats
 * to 1 in generate_packets.py.
 */
#define PACKET_SIZE_STATISTICS 0

extern const char *const packet_functional_capability;

#define SPECHASH_TAG packet_handler
#define SPECHASH_ASTR_KEY_TYPE
#define SPECHASH_IDATA_TYPE struct packet_handlers *
#define SPECHASH_IDATA_FREE (packet_handler_hash_data_free_fn_t) free
#include "spechash.h"

static struct packet_handler_hash *packet_handlers = NULL;

#ifdef USE_COMPRESSION
static int stat_size_alone = 0;
static int stat_size_uncompressed = 0;
static int stat_size_compressed = 0;
static int stat_size_no_compression = 0;

/****************************************************************************
  Returns the compression level. Initilialize it if needed.
****************************************************************************/
static inline int get_compression_level(void)
{
  static int level = -2;        /* Magic not initialized, see below. */

  if (-2 == level) {
    const char *s = getenv("FREECIV_COMPRESSION_LEVEL");

    if (NULL == s || !str_to_int(s, &level) || -1 > level || 9 < level) {
      level = -1;
    }
  }

  return level;
}

/****************************************************************************
  Send all waiting data. Return TRUE on success.
****************************************************************************/
static bool conn_compression_flush(struct connection *pconn)
{
  int compression_level = get_compression_level();
  uLongf compressed_size = 12 + 1.001 * pconn->compression.queue.size;
  int error;
  Bytef compressed[compressed_size];
  bool jumbo;
  unsigned long compressed_packet_len;

  error = compress2(compressed, &compressed_size,
                    pconn->compression.queue.p,
                    pconn->compression.queue.size,
                    compression_level);
  fc_assert_ret_val(error == Z_OK, FALSE);

  /* Compression signalling currently assumes a 2-byte packet length; if that
   * changes, the protocol should probably be changed */
  fc_assert_ret_val(data_type_size(pconn->packet_header.length) == 2, FALSE);

  /* Include normal length field in decision */
  jumbo = (compressed_size+2 >= JUMBO_BORDER);

  compressed_packet_len = compressed_size + (jumbo ? 6 : 2);
  if (compressed_packet_len < pconn->compression.queue.size) {
    struct data_out dout;

    log_compress("COMPRESS: compressed %lu bytes to %ld (level %d)",
                 (unsigned long) pconn->compression.queue.size,
                 compressed_size, compression_level);
    stat_size_uncompressed += pconn->compression.queue.size;
    stat_size_compressed += compressed_size;

    if (!jumbo) {
      unsigned char header[2];
      FC_STATIC_ASSERT(COMPRESSION_BORDER > MAX_LEN_PACKET,
                       uncompressed_compressed_packet_len_overlap);

      log_compress("COMPRESS: sending %ld as normal", compressed_size);

      dio_output_init(&dout, header, sizeof(header));
      dio_put_uint16(&dout, 2 + compressed_size + COMPRESSION_BORDER);
      connection_send_data(pconn, header, sizeof(header));
      connection_send_data(pconn, compressed, compressed_size);
    } else {
      unsigned char header[6];
      FC_STATIC_ASSERT(JUMBO_SIZE >= JUMBO_BORDER+COMPRESSION_BORDER,
                       compressed_normal_jumbo_packet_len_overlap);

      log_compress("COMPRESS: sending %ld as jumbo", compressed_size);
      dio_output_init(&dout, header, sizeof(header));
      dio_put_uint16(&dout, JUMBO_SIZE);
      dio_put_uint32(&dout, 6 + compressed_size);
      connection_send_data(pconn, header, sizeof(header));
      connection_send_data(pconn, compressed, compressed_size);
    }
  } else {
    log_compress("COMPRESS: would enlarge %lu bytes to %ld; "
                 "sending uncompressed",
                 (unsigned long) pconn->compression.queue.size,
                 compressed_packet_len);
    connection_send_data(pconn, pconn->compression.queue.p,
                         pconn->compression.queue.size);
    stat_size_no_compression += pconn->compression.queue.size;
  }
  return pconn->used;
}
#endif /* USE_COMPRESSION */

/****************************************************************************
  Thaw the connection. Then maybe compress the data waiting to send them
  to the connection. Returns TRUE on success. See also
  conn_compression_freeze().
****************************************************************************/
bool conn_compression_thaw(struct connection *pconn)
{
#ifdef USE_COMPRESSION
  pconn->compression.frozen_level--;
  fc_assert_action_msg(pconn->compression.frozen_level >= 0,
                       pconn->compression.frozen_level = 0,
                       "Too many calls to conn_compression_thaw on %s!",
                       conn_description(pconn));
  if (0 == pconn->compression.frozen_level) {
    return conn_compression_flush(pconn);
  }
#endif /* USE_COMPRESSION */
  return pconn->used;
}


/**************************************************************************
  It returns the request id of the outgoing packet (or 0 if is_server()).
**************************************************************************/
int send_packet_data(struct connection *pc, unsigned char *data, int len,
                     enum packet_type packet_type)
{
  /* default for the server */
  int result = 0;


  log_packet("sending packet type=%s(%d) len=%d to %s",
             packet_name(packet_type), packet_type, len,
             is_server() ? pc->username : "server");

  if (!is_server()) {
    pc->client.last_request_id_used =
        get_next_request_id(pc->client.last_request_id_used);
    result = pc->client.last_request_id_used;
    log_packet("sending request %d", result);
  }

  if (pc->outgoing_packet_notify) {
    pc->outgoing_packet_notify(pc, packet_type, len, result);
  }

#ifdef USE_COMPRESSION
  if (TRUE) {
    int size = len;

    if (conn_compression_frozen(pc)) {
      size_t old_size;

      /* Keep this a decent amount less than MAX_LEN_BUFFER to avoid the
       * (remote) possibility of trying to dump MAX_LEN_BUFFER to the
       * network in one go */
#define MAX_LEN_COMPRESS_QUEUE (MAX_LEN_BUFFER/2)
      FC_STATIC_ASSERT(MAX_LEN_COMPRESS_QUEUE < MAX_LEN_BUFFER,
                       compress_queue_maxlen_too_big);

      /* If this packet would cause us to overfill the queue, flush
       * everything that's in there already before queuing this one */
      if (MAX_LEN_COMPRESS_QUEUE
          < byte_vector_size(&pc->compression.queue) + len) {
        log_compress2("COMPRESS: huge queue, forcing to flush (%lu/%lu)",
                      (long unsigned)
                      byte_vector_size(&pc->compression.queue),
                      (long unsigned) MAX_LEN_COMPRESS_QUEUE);
        if (!conn_compression_flush(pc)) {
          return -1;
        }
        byte_vector_reserve(&pc->compression.queue, 0);
      }

      old_size = byte_vector_size(&pc->compression.queue);
      byte_vector_reserve(&pc->compression.queue, old_size + len);
      memcpy(pc->compression.queue.p + old_size, data, len);
      log_compress2("COMPRESS: putting %s into the queue",
                    packet_name(packet_type));
    } else {
      stat_size_alone += size;
      log_compress("COMPRESS: sending %s alone (%d bytes total)",
                   packet_name(packet_type), stat_size_alone);
      connection_send_data(pc, data, len);
    }

    log_compress2("COMPRESS: STATS: alone=%d compression-expand=%d "
                  "compression (before/after) = %d/%d",
                  stat_size_alone, stat_size_no_compression,
                  stat_size_uncompressed, stat_size_compressed);
  }
#else  /* USE_COMPRESSION */
  connection_send_data(pc, data, len);
#endif /* USE_COMPRESSION */

#if PACKET_SIZE_STATISTICS
  {
    static struct {
      int counter;
      int size;
    } packets_stats[PACKET_LAST];
    static int packet_counter = 0;
    static int last_start_turn_seen = -1;
    static bool start_turn_seen = FALSE;

    int size = len;
    bool print = FALSE;
    bool clear = FALSE;

    if (!packet_counter) {
      int i;

      for (i = 0; i < PACKET_LAST; i++) {
	packets_stats[i].counter = 0;
	packets_stats[i].size = 0;
      }
    }

    packets_stats[packet_type].counter++;
    packets_stats[packet_type].size += size;

    packet_counter++;
    if (packet_type == PACKET_START_TURN
	&& last_start_turn_seen != game.turn) {
	start_turn_seen=TRUE;
      last_start_turn_seen = game.turn;
    }

    if ((packet_type ==
	 PACKET_PROCESSING_FINISHED || packet_type == PACKET_THAW_HINT)
	&& start_turn_seen) {
      start_turn_seen = FALSE;
      print = TRUE;
      clear = TRUE;
    }

    if(print) {
      int i, sum = 0;
#define log_ll log_debug

#if PACKET_SIZE_STATISTICS == 2
      delta_stats_report();
#endif
      log_ll("Transmitted packets:");
      log_ll("%8s %8s %8s %s", "Packets", "Bytes", "Byt/Pac", "Name");

      for (i = 0; i < PACKET_LAST; i++) {
	if (packets_stats[i].counter == 0) {
	  continue;
	}
	sum += packets_stats[i].size;
        log_ll("%8d %8d %8d %s(%i)",
               packets_stats[i].counter, packets_stats[i].size,
               packets_stats[i].size / packets_stats[i].counter,
               packet_name(i),i);
      }
      log_test("turn=%d; transmitted %d bytes in %d packets;average size "
               "per packet %d bytes", game.turn, sum, packet_counter,
               sum / packet_counter);
      log_test("turn=%d; transmitted %d bytes", game.turn,
               pc->statistics.bytes_send);
    }
    if (clear) {
      int i;

      for (i = 0; i < PACKET_LAST; i++) {
	packets_stats[i].counter = 0;
	packets_stats[i].size = 0;
      }
      packet_counter = 0;
      pc->statistics.bytes_send = 0;
      delta_stats_reset();
    }
  }
#undef log_ll
#endif /* PACKET_SIZE_STATISTICS */

  return result;
}

/**************************************************************************
  Read and return a packet from the connection 'pc'. The type of the
  packet is written in 'ptype'. On error, the connection is closed and
  the function returns NULL.
**************************************************************************/
void *get_packet_from_connection(struct connection *pc,
                                 enum packet_type *ptype)
{
  int len_read;
  int whole_packet_len;
  struct {
    enum packet_type type;
    int itype;
  } utype;
  struct data_in din;
#ifdef USE_COMPRESSION
  bool compressed_packet = FALSE;
  int header_size = 0;
#endif
  void *data;
  void *(*receive_handler)(struct connection *);

  if (!pc->used) {
    return NULL;		/* connection was closed, stop reading */
  }
  
  if (pc->buffer->ndata < data_type_size(pc->packet_header.length)) {
    /* Not got enough for a length field yet */
    return NULL;
  }

  dio_input_init(&din, pc->buffer->data, pc->buffer->ndata);
  dio_get_uint16_old(&din, &len_read);

  /* The non-compressed case */
  whole_packet_len = len_read;

#ifdef USE_COMPRESSION
  /* Compression signalling currently assumes a 2-byte packet length; if that
   * changes, the protocol should probably be changed */
  fc_assert(data_type_size(pc->packet_header.length) == 2);
  if (len_read == JUMBO_SIZE) {
    compressed_packet = TRUE;
    header_size = 6;
    if (dio_input_remaining(&din) >= 4) {
      dio_get_uint32(&din, &whole_packet_len);
      log_compress("COMPRESS: got a jumbo packet of size %d",
                   whole_packet_len);
    } else {
      /* to return NULL below */
      whole_packet_len = 6;
    }
  } else if (len_read >= COMPRESSION_BORDER) {
    compressed_packet = TRUE;
    header_size = 2;
    whole_packet_len = len_read - COMPRESSION_BORDER;
    log_compress("COMPRESS: got a normal packet of size %d",
                 whole_packet_len);
  }
#endif /* USE_COMPRESSION */

  if ((unsigned)whole_packet_len > pc->buffer->ndata) {
    return NULL;		/* not all data has been read */
  }

#ifdef USE_COMPRESSION
  if (whole_packet_len < header_size) {
    log_verbose("The packet size is reported to be less than header alone. "
                "The connection will be closed now.");
    connection_close(pc, _("illegal packet size"));

    return NULL;
  }

  if (compressed_packet) {
    uLong compressed_size = whole_packet_len - header_size;
    /* 
     * We don't know the decompressed size. We assume a bad case
     * here: an expansion by an factor of 100. 
     */
    unsigned long int decompressed_size = 100 * compressed_size;
    void *decompressed = fc_malloc(decompressed_size);
    int error;
    struct socket_packet_buffer *buffer = pc->buffer;
    
    error =
	uncompress(decompressed, &decompressed_size,
		   ADD_TO_POINTER(buffer->data, header_size), 
		   compressed_size);
    if (error != Z_OK) {
      log_verbose("Uncompressing of the packet stream failed. "
                  "The connection will be closed now.");
      connection_close(pc, _("decoding error"));
      return NULL;
    }

    buffer->ndata -= whole_packet_len;
    /* 
     * Remove the packet with the compressed data and shift all the
     * remaining data to the front. 
     */
    memmove(buffer->data, buffer->data + whole_packet_len, buffer->ndata);

    if (buffer->ndata + decompressed_size > buffer->nsize) {
      buffer->nsize += decompressed_size;
      buffer->data = fc_realloc(buffer->data, buffer->nsize);
    }

    /*
     * Make place for the uncompressed data by moving the remaining
     * data.
     */
    memmove(buffer->data + decompressed_size, buffer->data, buffer->ndata);

    /* 
     * Copy the uncompressed data.
     */
    memcpy(buffer->data, decompressed, decompressed_size);

    free(decompressed);

    buffer->ndata += decompressed_size;
    
    log_compress("COMPRESS: decompressed %ld into %ld",
                 compressed_size, decompressed_size);

    return get_packet_from_connection(pc, ptype);
  }
#endif /* USE_COMPRESSION */

  /*
   * At this point the packet is a plain uncompressed one. These have
   * to have to be at least the header bytes in size.
   */
  if (whole_packet_len < (data_type_size(pc->packet_header.length)
                          + data_type_size(pc->packet_header.type))) {
    log_verbose("The packet stream is corrupt. The connection "
                "will be closed now.");
    connection_close(pc, _("decoding error"));
    return NULL;
  }

  /* Parse JSON packet. */
  json_error_t error;

  pc->json_packet = json_loadb((char*)pc->buffer->data + 4, whole_packet_len, 0, &error);

  memmove(pc->buffer->data, pc->buffer->data, pc->buffer->ndata);
  pc->buffer->ndata = 0;

  if (!pc->json_packet) {
    log_error("ERROR: Unable to parse packet: %s", pc->buffer->data);
    return NULL;
  }

  json_t *pint = json_object_get(pc->json_packet, "type");

  if (!pint) {
    log_error("ERROR: Unable to get packet type.");
    return NULL;
  } 

  json_int_t packet_type = json_integer_value(pint);
  utype.type = packet_type;

  if (utype.type < 0
      || utype.type >= PACKET_LAST
      || (receive_handler = pc->phs.handlers->receive[utype.type]) == NULL) {
    log_verbose("Received unsupported packet type %d (%s). The connection "
                "will be closed now.",
                utype.type, packet_name(utype.type));
    connection_close(pc, _("unsupported packet type"));
    return NULL;
  }

  log_packet("got packet type=(%s) len=%d from %s",
             packet_name(utype.type), whole_packet_len,
             is_server() ? pc->username : "server");

  *ptype = utype.type;

  if (pc->incoming_packet_notify) {
    pc->incoming_packet_notify(pc, utype.type, whole_packet_len);
  }

#if PACKET_SIZE_STATISTICS 
  {
    static struct {
      int counter;
      int size;
    } packets_stats[PACKET_LAST];
    static int packet_counter = 0;

    int packet_type = utype.itype;
    int size = whole_packet_len;

    if (!packet_counter) {
      int i;

      for (i = 0; i < PACKET_LAST; i++) {
	packets_stats[i].counter = 0;
	packets_stats[i].size = 0;
      }
    }

    packets_stats[packet_type].counter++;
    packets_stats[packet_type].size += size;

    packet_counter++;
    if (packet_counter % 100 == 0) {
      int i, sum = 0;

      log_test("Received packets:");
      for (i = 0; i < PACKET_LAST; i++) {
	if (packets_stats[i].counter == 0)
	  continue;
	sum += packets_stats[i].size;
        log_test("  [%-25.25s %3d]: %6d packets; %8d bytes total; "
                 "%5d bytes/packet average",
                 packet_name(i), i, packets_stats[i].counter,
                 packets_stats[i].size,
                 packets_stats[i].size / packets_stats[i].counter);
      }
      log_test("received %d bytes in %d packets;average size "
               "per packet %d bytes",
               sum, packet_counter, sum / packet_counter);
    }
  }
#endif /* PACKET_SIZE_STATISTICS */
  data = receive_handler(pc);
  if (!data) {
    connection_close(pc, _("incompatible packet contents"));
    return NULL;
  } else {
    return data;
  }
}

/**************************************************************************
  Remove the packet from the buffer
**************************************************************************/
void remove_packet_from_buffer(struct socket_packet_buffer *buffer)
{
  struct data_in din;
  int len;
 
  dio_input_init(&din, buffer->data, buffer->ndata);
  dio_get_uint16_old(&din, &len);
  memmove(buffer->data, buffer->data + len, buffer->ndata - len);
  buffer->ndata -= len;
  log_debug("remove_packet_from_buffer: remove %d; remaining %d",
            len, buffer->ndata);
}

/****************************************************************************
  Set the packet header field lengths used for the login protocol,
  before the capability of the connection could be checked.

  NB: These values cannot be changed for backward compatibility reasons.
****************************************************************************/
void packet_header_init(struct packet_header *packet_header)
{
  packet_header->length = DIOT_UINT16;
  packet_header->type = DIOT_UINT8;
}

/****************************************************************************
  Set the packet header field lengths used after the login protocol,
  after the capability of the connection could be checked.
****************************************************************************/
static inline void packet_header_set(struct packet_header *packet_header)
{
  /* Ensure we have values initialized in packet_header_init(). */
  fc_assert(packet_header->length == DIOT_UINT16);
  fc_assert(packet_header->type == DIOT_UINT8);

  packet_header->length = DIOT_UINT16;
  packet_header->type = DIOT_UINT16;
}

/****************************************************************************
  Modify if needed the packet header field lengths.
****************************************************************************/
void post_send_packet_server_join_reply(struct connection *pconn,
                                        const struct packet_server_join_reply
                                        *packet)
{
  if (packet->you_can_join) {
    packet_header_set(&pconn->packet_header);
  }
}

/****************************************************************************
  Modify if needed the packet header field lengths.
****************************************************************************/
void post_receive_packet_server_join_reply(struct connection *pconn,
                                           const struct
                                           packet_server_join_reply *packet)
{
  if (packet->you_can_join) {
    packet_header_set(&pconn->packet_header);
  }
}

/**************************************************************************
 Updates pplayer->attribute_block according to the given packet.
**************************************************************************/
void generic_handle_player_attribute_chunk(struct player *pplayer,
					   const struct
					   packet_player_attribute_chunk
					   *chunk)
{
  log_packet("received attribute chunk %u/%u %u",
             (unsigned int) chunk->offset,
             (unsigned int) chunk->total_length,
             (unsigned int) chunk->chunk_length);

  if (chunk->total_length < 0
      || chunk->chunk_length < 0
      || chunk->total_length >= MAX_ATTRIBUTE_BLOCK
      || chunk->offset < 0
      || chunk->offset > chunk->total_length /* necessary check on 32 bit systems */
      || chunk->chunk_length > chunk->total_length
      || chunk->offset + chunk->chunk_length > chunk->total_length
      || (chunk->offset != 0
          && chunk->total_length != pplayer->attribute_block_buffer.length)) {
    /* wrong attribute data */
    if (pplayer->attribute_block_buffer.data) {
      free(pplayer->attribute_block_buffer.data);
      pplayer->attribute_block_buffer.data = NULL;
    }
    pplayer->attribute_block_buffer.length = 0;
    log_error("Received wrong attribute chunk");
    return;
  }
  /* first one in a row */
  if (chunk->offset == 0) {
    if (pplayer->attribute_block_buffer.data) {
      free(pplayer->attribute_block_buffer.data);
      pplayer->attribute_block_buffer.data = NULL;
    }
    pplayer->attribute_block_buffer.data = fc_malloc(chunk->total_length);
    pplayer->attribute_block_buffer.length = chunk->total_length;
  }
  memcpy((char *) (pplayer->attribute_block_buffer.data) + chunk->offset,
	 chunk->data, chunk->chunk_length);
  
  if (chunk->offset + chunk->chunk_length == chunk->total_length) {
    /* Received full attribute block */
    if (pplayer->attribute_block.data != NULL) {
      free(pplayer->attribute_block.data);
    }
    pplayer->attribute_block.data = pplayer->attribute_block_buffer.data;
    pplayer->attribute_block.length = pplayer->attribute_block_buffer.length;
    
    pplayer->attribute_block_buffer.data = NULL;
    pplayer->attribute_block_buffer.length = 0;
  }
}

/**************************************************************************
 Split the attribute block into chunks and send them over pconn.
**************************************************************************/
void send_attribute_block(const struct player *pplayer,
			  struct connection *pconn)
{
  struct packet_player_attribute_chunk packet;
  int current_chunk, chunks, bytes_left;

  if (!pplayer || !pplayer->attribute_block.data) {
    return;
  }

  fc_assert_ret(pplayer->attribute_block.length > 0
                && pplayer->attribute_block.length < MAX_ATTRIBUTE_BLOCK);

  chunks =
      (pplayer->attribute_block.length - 1) / ATTRIBUTE_CHUNK_SIZE + 1;
  bytes_left = pplayer->attribute_block.length;

  connection_do_buffer(pconn);

  for (current_chunk = 0; current_chunk < chunks; current_chunk++) {
    int size_of_current_chunk = MIN(bytes_left, ATTRIBUTE_CHUNK_SIZE);

    packet.offset = ATTRIBUTE_CHUNK_SIZE * current_chunk;
    packet.total_length = pplayer->attribute_block.length;
    packet.chunk_length = size_of_current_chunk;

    memcpy(packet.data,
	   (char *) (pplayer->attribute_block.data) + packet.offset,
	   packet.chunk_length);
    bytes_left -= packet.chunk_length;

    if (packet.chunk_length < ATTRIBUTE_CHUNK_SIZE) {
      /* Last chunk is not full. Make sure that delta does
       * not use random data. */
      memset(packet.data + packet.chunk_length, 0,
             ATTRIBUTE_CHUNK_SIZE - packet.chunk_length);
    }

    send_packet_player_attribute_chunk(pconn, &packet);
  }

  connection_do_unbuffer(pconn);
}

/**************************************************************************
  Test and log for sending player attribute_block
**************************************************************************/
void pre_send_packet_player_attribute_chunk(struct connection *pc,
                                            struct packet_player_attribute_chunk
                                            *packet)
{
  fc_assert(packet->total_length > 0
            && packet->total_length < MAX_ATTRIBUTE_BLOCK);
  /* 500 bytes header, just to be sure */
  fc_assert(packet->chunk_length > 0
            && packet->chunk_length < MAX_LEN_PACKET - 500);
  fc_assert(packet->chunk_length <= packet->total_length);
  fc_assert(packet->offset >= 0 && packet->offset < packet->total_length);

  log_packet("sending attribute chunk %d/%d %d",
             packet->offset, packet->total_length, packet->chunk_length);

}

/****************************************************************************
  Destroy the packet handler hash table.
****************************************************************************/
static void packet_handlers_free(void)
{
  if (packet_handlers != NULL) {
    packet_handler_hash_destroy(packet_handlers);
    packet_handlers = NULL;
  }
}

/****************************************************************************
  Returns the packet handlers variant with no special capability.
****************************************************************************/
const struct packet_handlers *packet_handlers_initial(void)
{
  static struct packet_handlers default_handlers;
  static bool initialized = FALSE;

  if (!initialized) {
    memset(&default_handlers, 0, sizeof(default_handlers));
    packet_handlers_fill_initial(&default_handlers);
    initialized = TRUE;
  }

  return &default_handlers;
}

/****************************************************************************
  Returns the packet handlers variant for 'capability'.
****************************************************************************/
const struct packet_handlers *packet_handlers_get(const char *capability)
{
  struct packet_handlers *phandlers;
  char functional_capability[MAX_LEN_CAPSTR] = "";
  char *tokens[MAX_LEN_CAPSTR / 2];
  int tokens_num;
  int i;

  fc_assert(strlen(capability) < sizeof(functional_capability));

  /* Get functional network capability string. */
  tokens_num = get_tokens(capability, tokens, ARRAY_SIZE(tokens), " \t\n,");
  qsort(tokens, tokens_num, sizeof(*tokens), compare_strings_ptrs);
  for (i = 0; i < tokens_num; i++) {
    if (!has_capability(tokens[i], packet_functional_capability)) {
      continue;
    }
    if (functional_capability[0] != '\0') {
      sz_strlcat(functional_capability, " ");
    }
    sz_strlcat(functional_capability, tokens[i]);
  }
  free_tokens(tokens, tokens_num);

  /* Ensure the hash table is created. */
  if (packet_handlers == NULL) {
    packet_handlers = packet_handler_hash_new();
    atexit(packet_handlers_free);
  }

  /* Lookup handlers for the capabilities or create new handlers. */
  if (!packet_handler_hash_lookup(packet_handlers, functional_capability,
                                  &phandlers)) {
    phandlers = fc_malloc(sizeof(*phandlers));
    memcpy(phandlers, packet_handlers_initial(), sizeof(*phandlers));
    packet_handlers_fill_capability(phandlers, functional_capability);
    packet_handler_hash_insert(packet_handlers, functional_capability,
                               phandlers);
  }

  fc_assert(phandlers != NULL);
  return phandlers;
}

#endif /* FREECIV_JSON_CONNECTION */
ENDREP
id: 15.5ck.r27888/74266
type: file
pred: 15.5ck.r27832/414
count: 253
text: 27888 34986 588 49147 f99fc2f8949528ff57dd9bacb4f24734
props: 10956 5264 112 0 3b4f53580729e091747f5670a0f86c52
cpath: /trunk/server/sernet.c
copyroot: 15280 /trunk

PLAIN
K 11
Makefile.am
V 24
file 5q.5ck.r27705/60281
K 8
advisors
V 23
dir 4n2.5ck.r27812/8972
K 9
aiiface.c
V 25
file 4gm.5ck.r26905/55786
K 9
aiiface.h
V 25
file 4gn.5ck.r26905/56374
K 9
animals.c
V 25
file vnk.5ck.r26905/62972
K 9
animals.h
V 25
file vnm.5ck.r26905/63257
K 6
auth.c
V 25
file 39c.5ck.r20274/32101
K 6
auth.h
V 25
file 39d.5ck.r18977/19170
K 11
barbarian.c
V 23
file lw.5ck.r27499/1629
K 11
barbarian.h
V 24
file lx.5ck.r22667/36940
K 14
citizenshand.c
V 25
file 6mz.5ck.r26905/56079
K 14
citizenshand.h
V 25
file 6n0.5ck.r26905/56662
K 10
cityhand.c
V 24
file 10.5ck.r19573/66885
K 10
cityhand.h
V 23
file 4f.0.r13297/423686
K 11
citytools.c
V 21
file 4g.5ck.r27313/65
K 11
citytools.h
V 24
file 4h.5ck.r26863/25714
K 10
cityturn.c
V 23
file 4i.5ck.r27878/2068
K 10
cityturn.h
V 24
file 4j.5ck.r24742/16670
K 11
civserver.c
V 23
file 4k.5ck.r27134/1477
K 10
commands.c
V 24
file 2ly.5ck.r27781/9025
K 10
commands.h
V 24
file 2lz.5ck.r27781/8049
K 13
connecthand.c
V 25
file 2dw.5ck.r27336/16958
K 13
connecthand.h
V 24
file 2dx.5ck.r23606/2057
K 9
console.c
V 24
file dd.5ck.r24895/15492
K 9
console.h
V 23
file de.5ck.r19183/7918
K 10
diplhand.c
V 23
file 4m.5ck.r27517/8673
K 10
diplhand.h
V 23
file 4n.5ck.r27517/8916
K 11
diplomats.c
V 25
file vz.5ck.r27708/118706
K 11
diplomats.h
V 23
file w0.5ck.r27461/1674
K 10
edithand.c
V 25
file 3bk.5ck.r27611/83395
K 10
edithand.h
V 25
file 4ez.5ck.r26905/64705
K 6
fcdb.c
V 25
file 6l3.5ck.r26905/56956
K 6
fcdb.h
V 25
file 6l4.5ck.r26905/57239
K 10
gamehand.c
V 23
file 4o.5ck.r27042/1951
K 10
gamehand.h
V 24
file 4p.5ck.r26564/23149
K 9
generator
V 24
dir 2me.5ck.r27705/61438
K 10
handchat.c
V 23
file 4q.5ck.r25915/6654
K 10
handchat.h
V 24
file dj.5ck.r18270/28229
K 9
maphand.c
V 23
file 13.5ck.r27854/1225
K 9
maphand.h
V 23
file 14.5ck.r24759/3742
K 6
meta.c
V 23
file 4s.5ck.r27134/1241
K 6
meta.h
V 23
file 4t.5ck.r27204/3095
K 6
mood.c
V 26
file 112c.5ck.r26905/63547
K 6
mood.h
V 26
file 112e.5ck.r26905/64129
K 8
notify.c
V 25
file 4i2.5ck.r26905/57814
K 8
notify.h
V 25
file 4i3.5ck.r26905/58681
K 9
plrhand.c
V 24
file 4u.5ck.r27223/43157
K 9
plrhand.h
V 23
file 4v.5ck.r26956/6294
K 8
report.c
V 24
file vi.5ck.r27611/82881
K 8
report.h
V 24
file vj.5ck.r24891/20006
K 10
rscompat.c
V 27
file 1kte.5ck.r27708/118458
K 10
rscompat.h
V 25
file 1ktg.5ck.r27698/6947
K 10
rssanity.c
V 25
file hew.5ck.r26905/55205
K 10
rssanity.h
V 25
file hey.5ck.r26905/55500
K 9
ruleset.c
V 22
file 8w.5ck.r27773/383
K 9
ruleset.h
V 23
file 8x.5ck.r27724/4145
K 13
sanitycheck.c
V 22
file wi.5ck.r27281/872
K 13
sanitycheck.h
V 24
file wj.5ck.r20315/26296
K 12
savecompat.c
V 25
file qva.5ck.r27475/19728
K 12
savecompat.h
V 25
file qvc.5ck.r27279/35421
K 10
savegame.c
V 23
file vl.5ck.r27748/2915
K 10
savegame.h
V 24
file vm.5ck.r20758/19233
K 11
savegame2.c
V 24
file 4m0.5ck.r27663/7672
K 11
savegame2.h
V 25
file 4m1.5ck.r27478/65017
K 11
savegame3.c
V 23
file 4m0.5ql.r27841/246
K 11
savegame3.h
V 25
file 4m1.5qm.r27478/64506
K 7
score.c
V 25
file 2eg.5ck.r25535/51502
K 7
score.h
V 24
file 2eh.5ck.r21929/6179
K 9
scripting
V 24
dir 31x.5ck.r27705/62838
K 8
sernet.c
V 24
file 15.5ck.r27888/74266
K 8
sernet.h
V 23
file 4y.5ck.r23685/5129
K 10
settings.c
V 24
file 2m0.5ck.r27878/1821
K 10
settings.h
V 24
file 2m1.5ck.r27836/7287
K 11
spacerace.c
V 24
file 9a.5ck.r25063/30975
K 11
spacerace.h
V 21
file 9b.0.r11338/1129
K 9
srv_log.c
V 23
file 15t.5el.r27820/656
K 9
srv_log.h
V 23
file 15u.5em.r27820/911
K 10
srv_main.c
V 23
file vg.5ck.r27805/3907
K 10
srv_main.h
V 22
file vh.5ck.r27134/762
K 11
stdinhand.c
V 23
file 4z.5ck.r27867/1315
K 11
stdinhand.h
V 24
file 50.5ck.r26100/15471
K 11
techtools.c
V 24
file 33n.5ck.r27058/1887
K 11
techtools.h
V 24
file 33o.5ck.r27058/2134
K 10
unithand.c
V 24
file 18.5ck.r27865/53172
K 10
unithand.h
V 24
file 19.5ck.r23027/66151
K 11
unittools.c
V 23
file 1a.5ck.r27658/1061
K 11
unittools.h
V 23
file 1b.5ck.r27658/1303
K 8
voting.c
V 25
file 4ex.5ck.r26905/57525
K 8
voting.h
V 25
file 4ey.5ck.r26905/58399
END
ENDREP
id: z.5ck.r27888/78551
type: dir
pred: z.5ck.r27878/6351
count: 5867
text: 27888 74508 4030 4030 4de2e927e0799287ff6f12c7d7e008ff
props: 23990 448 166 0 e5026e1cb18fe57b41417951bfac7b19
cpath: /trunk/server
copyroot: 15280 /trunk

id: 43.5ck.r27888/78782
type: file
pred: 43.5ck.r27337/9550
count: 323
text: 27888 34865 92 29041 e32ba80e34f244898fa4fb8bd721d12d
props: 11001 6188 112 0 be233b9f2c09b9a4fa715b44e3833b02
cpath: /trunk/common/packets.c
copyroot: 15280 /trunk

id: 44.5ck.r27888/79025
type: file
pred: 44.5ck.r27336/26555
count: 193
text: 27888 42630 105 7028 25dcfe4a536564f633a551cd331cf2a4
props: 10995 4056 112 0 3c18238954a206b16025cb856b574b65
cpath: /trunk/common/packets.h
copyroot: 15280 /trunk

id: 15r.5ck.r27888/79269
type: file
pred: 15r.5ck.r27027/2551
count: 54
text: 27888 42765 2599 30033 6b20f6ee736e93868b9b0d666529019e
props: 10806 11936 111 0 227f1557f5d66bc46d32e4db301b2671
cpath: /trunk/common/dataio.c
copyroot: 15280 /trunk

id: 15s.5ck.r27888/79515
type: file
pred: 15s.5ck.r26834/4081
count: 23
text: 27888 0 104 6064 c2fea65bb274fe0a2681246dae13226b
props: 10480 9927 110 0 a3ee73c7ed0bd397f9f2fedc7793a5b7
cpath: /trunk/common/dataio.h
copyroot: 15280 /trunk

id: 2f4.5ck.r27888/79754
type: file
pred: 2f4.5ck.r27339/27191
count: 65
text: 27888 34425 413 59901 482cf7dc93b4f4f4ee3a53a44f0e6c92
props: 10337 94 137 0 976e34fef28b87787fa073fe4d6aecb4
cpath: /trunk/common/generate_packets.py
copyroot: 15280 /trunk

id: 1m61.5ck.r27888/80008
type: file
count: 0
text: 27888 6932 27480 27463 1d043f13e8bf40e014bfa2bea629df4d
cpath: /trunk/common/dataio_json.c
copyroot: 15280 /trunk

id: 1m63.5ck.r27888/80175
type: file
count: 0
text: 27888 35599 7018 7004 1322fcbec0b3406a51fcae7a5fe4e09d
cpath: /trunk/common/dataio_json.h
copyroot: 15280 /trunk

id: 1m64.5ck.r27888/80341
type: file
count: 0
text: 27888 45390 28863 28846 29d71e6bf2736032ee4e91e64dbb1ef3
cpath: /trunk/common/packets_json.c
copyroot: 15280 /trunk

id: 1m65.5ck.r27888/80510
type: file
count: 0
text: 27888 247 6672 6658 d3032130c9f30de85afe16ac5f81ac6e
cpath: /trunk/common/packets_json.h
copyroot: 15280 /trunk

id: 5h.5ck.r27888/80675
type: file
pred: 5h.5ck.r27705/40065
count: 105
text: 27888 132 87 3587 f2dcbc971e5ee67d914504b5d2c00807
props: 10503 239 111 0 7f9b5cf6c8fffd7438ed66579e7ad166
cpath: /trunk/common/Makefile.am
copyroot: 15280 /trunk

PLAIN
K 11
Makefile.am
V 24
file 5h.5ck.r27888/80675
K 14
achievements.c
V 26
file qhc.5ck.r26905/214675
K 14
achievements.h
V 26
file qhe.5ck.r26905/215849
K 9
actions.c
V 25
file r7a.5ck.r27865/41768
K 9
actions.h
V 23
file r7c.5ck.r27712/233
K 4
ai.c
V 26
file 4go.5ck.r26905/200613
K 4
ai.h
V 24
file 4gp.5ck.r27002/6597
K 6
aicore
V 24
dir 18t.5ck.r27705/39824
K 6
base.c
V 25
file 3jw.5ck.r27223/37135
K 6
base.h
V 25
file 3jx.5ck.r27876/17009
K 9
borders.c
V 25
file 4f0.5ck.r27223/36397
K 9
borders.h
V 26
file 4f1.5ck.r26905/213493
K 10
calendar.c
V 27
file 147p.5ck.r26905/214086
K 10
calendar.h
V 27
file 147r.5ck.r26905/215265
K 8
capstr.c
V 22
file dv.5ck.r24976/289
K 8
capstr.h
V 24
file dw.5ck.r18858/97074
K 10
citizens.c
V 26
file 6mx.5ck.r26905/203234
K 10
citizens.h
V 26
file 6my.5ck.r26905/204108
K 6
city.c
V 21
file q.5ck.r26947/614
K 6
city.h
V 23
file 3q.5ck.r26874/2910
K 13
clientutils.c
V 26
file zj9.5ck.r26905/212022
K 13
clientutils.h
V 26
file zjb.5ck.r26905/213199
K 8
combat.c
V 22
file wp.5ck.r27137/126
K 8
combat.h
V 24
file wq.5ck.r24573/25814
K 12
connection.c
V 23
file un.5ck.r27857/9823
K 12
connection.h
V 23
file uo.5ck.r27799/1027
K 9
culture.c
V 27
file 104t.5ck.r26905/202652
K 9
culture.h
V 27
file 104v.5ck.r26905/203523
K 8
dataio.c
V 25
file 15r.5ck.r27888/79269
K 8
dataio.h
V 25
file 15s.5ck.r27888/79515
K 13
dataio_json.c
V 26
file 1m61.5ck.r27888/80008
K 13
dataio_json.h
V 26
file 1m63.5ck.r27888/80175
K 11
diptreaty.c
V 24
file 3r.5ck.r27517/13334
K 11
diptreaty.h
V 24
file 3s.5ck.r27517/13575
K 10
disaster.c
V 26
file b2m.5ck.r26905/214973
K 10
disaster.h
V 26
file b2o.5ck.r26905/216145
K 9
effects.c
V 25
file 2eo.5ck.r26392/11084
K 9
effects.h
V 25
file 2ep.5ck.r27458/49187
K 8
events.c
V 25
file 33h.5ck.r27673/14547
K 8
events.h
V 24
file 3t.5ck.r27673/14789
K 8
extras.c
V 23
file o9u.5ck.r27700/774
K 8
extras.h
V 25
file o9w.5ck.r27774/59099
K 12
fc_cmdhelp.c
V 26
file 76j.5ck.r26905/216438
K 12
fc_cmdhelp.h
V 26
file 76k.5ck.r26905/216731
K 14
fc_interface.c
V 26
file 4up.5ck.r26905/201770
K 14
fc_interface.h
V 26
file 4uq.5ck.r26905/202358
K 10
fc_types.h
V 25
file 2ll.5ck.r27774/58849
K 15
featured_text.c
V 26
file 4h3.5ck.r26905/212899
K 15
featured_text.h
V 26
file 4h4.5ck.r26905/213786
K 6
game.c
V 22
file 3u.5ck.r27750/580
K 6
game.h
V 22
file 3v.5ck.r27479/114
K 19
generate_packets.py
V 25
file 2f4.5ck.r27888/79754
K 12
government.c
V 25
file he.5ck.r25382/101248
K 12
government.h
V 24
file hf.5ck.r25151/83855
K 6
idex.c
V 24
file qo.5ck.r25151/84101
K 6
idex.h
V 24
file qp.5ck.r18858/92434
K 13
improvement.c
V 22
file vb.5ck.r27036/203
K 13
improvement.h
V 23
file vc.5ck.r26605/3666
K 5
map.c
V 22
file r.5ck.r27605/1397
K 5
map.h
V 23
file 41.5ck.r27446/5985
K 8
mapimg.c
V 26
file 6n9.5ck.r26905/214381
K 8
mapimg.h
V 26
file 6na.5ck.r26905/215559
K 15
metaknowledge.c
V 26
file siq.5ck.r26905/206154
K 15
metaknowledge.h
V 26
file sis.5ck.r26905/206455
K 10
movement.c
V 25
file 2xv.5ck.r26369/89463
K 10
movement.h
V 25
file 2xw.5ck.r26369/89711
K 13
multipliers.c
V 27
file 197b.5ck.r26905/218478
K 13
multipliers.h
V 27
file 197d.5ck.r26905/219360
K 18
name_translation.h
V 26
file 4k1.5ck.r26905/217596
K 8
nation.c
V 24
file il.5ck.r26881/35006
K 8
nation.h
V 22
file im.5ck.r27000/284
K 9
packets.c
V 24
file 43.5ck.r27888/78782
K 11
packets.def
V 25
file 2f5.5ck.r27819/14673
K 9
packets.h
V 24
file 44.5ck.r27888/79025
K 14
packets_json.c
V 26
file 1m64.5ck.r27888/80341
K 14
packets_json.h
V 26
file 1m65.5ck.r27888/80510
K 8
player.c
V 22
file 45.5ck.r27147/309
K 8
player.h
V 24
file 46.5ck.r26824/28997
K 14
requirements.c
V 24
file 2wq.5ck.r26954/4125
K 14
requirements.h
V 23
file 2wr.5ck.r27694/573
K 10
research.c
V 23
file 4ro.5ck.r27847/664
K 10
research.h
V 24
file 4rp.5ck.r27750/1056
K 10
rgbcolor.c
V 26
file 6i6.5ck.r26905/218776
K 10
rgbcolor.h
V 26
file 6i7.5ck.r26905/219068
K 6
road.c
V 26
file 6pq.5ck.r26905/202943
K 6
road.h
V 25
file 6pr.5ck.r27876/17736
K 10
scriptcore
V 24
dir 75a.5ck.r27705/41927
K 11
spaceship.c
V 23
file 98.5ck.r26349/9773
K 11
spaceship.h
V 24
file 99.5ck.r26349/10015
K 12
specialist.c
V 23
file 33f.5ck.r22372/258
K 12
specialist.h
V 25
file 33g.5ck.r23560/15220
K 7
style.c
V 26
file zzb.5ck.r26905/204398
K 7
style.h
V 26
file zzd.5ck.r26905/204988
K 6
team.c
V 23
file 33i.5ck.r25891/212
K 6
team.h
V 23
file 33j.5ck.r26183/314
K 6
tech.c
V 22
file t.5ck.r27149/7328
K 6
tech.h
V 23
file u.5ck.r27876/17497
K 9
terrain.c
V 24
file 2fp.5ck.r27149/7564
K 9
terrain.h
V 24
file qs.5ck.r27876/16764
K 6
tile.c
V 26
file 2ys.5ck.r27620/186567
K 6
tile.h
V 25
file 2yt.5ck.r26109/28279
K 13
traderoutes.c
V 25
file bf8.5ck.r27547/37733
K 13
traderoutes.h
V 25
file bfa.5ck.r27547/37984
K 8
traits.h
V 26
file 7k3.5ck.r26905/202065
K 6
unit.c
V 23
file v.5ck.r27631/12601
K 6
unit.h
V 24
file 48.5ck.r27631/12837
K 10
unitlist.c
V 26
file 39m.5ck.r27611/109866
K 10
unitlist.h
V 26
file 39n.5ck.r27611/110113
K 10
unittype.c
V 25
file v9.5ck.r27611/110594
K 10
unittype.h
V 24
file va.5ck.r27876/17249
K 9
version.c
V 23
file oe.5ck.r26171/7093
K 9
version.h
V 23
file e7.5ck.r26171/7331
K 9
victory.c
V 26
file qex.5ck.r26905/217020
K 9
victory.h
V 26
file qez.5ck.r26905/217896
K 8
vision.c
V 22
file 4dm.5ck.r27638/98
K 8
vision.h
V 24
file 4dn.5ck.r24742/9986
K 12
workertask.c
V 26
file llw.5ck.r26905/206753
K 12
workertask.h
V 26
file lly.5ck.r26905/212604
K 10
worklist.c
V 25
file o8.5ck.r19259/402799
K 10
worklist.h
V 24
file o9.5ck.r18858/98299
END
ENDREP
id: p.5ck.r27888/86438
type: dir
pred: p.5ck.r27876/23289
count: 4170
text: 27888 80917 5508 5508 26d9d71bd3e1e0e4080a720b2f013cd7
props: 23743 0 112 0 b2bc91bf125d83375389d51f25ff2c2f
cpath: /trunk/common
copyroot: 15280 /trunk

PLAIN
K 9
ABOUT-NLS
V 24
file fu.5ck.r27270/69307
K 7
AUTHORS
V 24
file 5u.5ck.r22143/14016
K 7
COPYING
V 19
file 1h.0.r9643/400
K 9
ChangeLog
V 26
file 6l.5ck.r27473/7455495
K 7
INSTALL
V 22
file 6.5ck.r27777/1982
K 11
Makefile.am
V 23
file 59.5ck.r27480/1506
K 4
NEWS
V 24
file 6m.5ck.r25634/30702
K 6
README
V 20
file 7.0.r4421/96382
K 2
ai
V 22
dir 8.5ck.r27865/50400
K 10
autogen.sh
V 23
file 12o.5ck.r27624/562
K 9
bootstrap
V 23
dir 2p5.5ck.r27114/4172
K 6
client
V 22
dir d.5ck.r27877/21284
K 6
common
V 22
dir p.5ck.r27888/86438
K 12
configure.ac
V 25
file 149.5ck.r27705/58094
K 4
data
V 22
dir w.5ck.r27877/16520
K 12
dependencies
V 22
dir 2yu.5ck.r27817/318
K 3
doc
V 23
dir k7.5ck.r27865/52944
K 10
fc_version
V 25
file 2lo.5en.r27865/50626
K 11
gen_headers
V 24
dir 1hsw.5ck.r27799/7131
K 2
m4
V 23
dir 12p.5ck.r27799/9591
K 7
scripts
V 23
dir 2yo.5ck.r27213/1366
K 6
server
V 22
dir z.5ck.r27888/78551
K 5
tests
V 23
dir 2g9.5ck.r27783/1363
K 5
tools
V 23
dir 4pj.5js.r27748/2435
K 12
translations
V 23
dir t0a.5ck.r27827/7773
K 7
utility
V 22
dir 1c.5ck.r27792/3100
K 5
win32
V 24
dir 2eu.5ck.r27475/16089
END
ENDREP
id: 3.5ck.r27888/87801
type: dir
pred: 3.5ck.r27878/7712
count: 19077
text: 27888 86668 1120 1120 98fa92e3ad5d2121de1320325ef19d08
props: 23244 4830 282 0 e4bb46e81629a60eef613b169b23a9ea
cpath: /trunk
copyroot: 15280 /trunk

PLAIN
K 8
branches
V 19
dir 1.0.r27887/6145
K 4
tags
V 19
dir 2.0.r27200/6414
K 5
trunk
V 22
dir 3.5ck.r27888/87801
K 7
website
V 21
dir 3ge.0.r22980/2263
END
ENDREP
id: 0.0.r27888/88193
type: dir
pred: 0.0.r27887/6464
count: 27888
text: 27888 88027 153 153 26c5e552848e40d57c0fd66e4aafb94b
cpath: /
copyroot: 0 /

_6.5ck.t27887-1 add true false /trunk/common/packets_json.h

5h.5ck.t27887-1 modify true false /trunk/common/Makefile.am

_2.5ck.t27887-1 add true false /trunk/common/dataio_json.c

2f4.5ck.t27887-1 modify true false /trunk/common/generate_packets.py

43.5ck.t27887-1 modify true false /trunk/common/packets.c

15.5ck.t27887-1 modify true false /trunk/server/sernet.c

_4.5ck.t27887-1 add true false /trunk/common/dataio_json.h

44.5ck.t27887-1 modify true false /trunk/common/packets.h

15r.5ck.t27887-1 modify true false /trunk/common/dataio.c

_5.5ck.t27887-1 add true false /trunk/common/packets_json.c

15s.5ck.t27887-1 modify true false /trunk/common/dataio.h


88193 88342
