Exemple #1
0
/****************************************************************************
  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];

  error = compress2(compressed, &compressed_size,
                    pconn->compression.queue.p,
                    pconn->compression.queue.size,
                    compression_level);
  fc_assert_ret_val(error == Z_OK, FALSE);
  if (compressed_size + 2 < 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 (compressed_size <= JUMBO_BORDER) {
      unsigned char header[2];

      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];

      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 enlarging %lu bytes to %ld; "
                 "sending uncompressed",
                 (unsigned long) pconn->compression.queue.size,
                 compressed_size);
    connection_send_data(pconn, pconn->compression.queue.p,
                         pconn->compression.queue.size);
    stat_size_no_compression += pconn->compression.queue.size;
  }
  return pconn->used;
}
Exemple #2
0
static int
send_request(MHANDLE con, MBTCPHDR *mb)
{
	static unsigned short tid = 1;
	static unsigned short count = 1;
	unsigned char data[8];
	unsigned char mbtcp_buf[260];
	unsigned short addr, d;
	int len;

	mb->trans_identifier = tid;
	if (tid == 65535) tid = 1; else tid++;

	/* compose request PDU */
	data[0] = 10;	/* slave ID */
	data[1] = 0x03;	/* function code */
	addr = 100;
	d = BSWAP16(addr);
	memcpy(&data[2], &d, 2);
	d = BSWAP16(count);
	memcpy(&data[4], &d, 2);
	if (count == 10) count = 1; else count++;
	len = mbtcp_packet_format(mb, data, 6, mbtcp_buf);
	connection_send_data(con, (char *)mbtcp_buf, len);

	return 0;
}
/*  this user-defined function is called after the user program receives
	a data packet. It reverses the content of the packet and then send 
	the result back to the client */
static int	
udp_server_dispatch_client (MHANDLE conp, void *private_data, DATAPKT *dpkt)
{
	char buffer[1024];

	(void) private_data;

	dpkt->packet_consumed = dpkt->packet_size;
	memcpy(buffer, dpkt->packet_data, dpkt->packet_size);
	buffer[dpkt->packet_size] = 0;
printf("RECV: %s\n", buffer);
	/* reverse the received data */
	reverse_bytes(buffer, dpkt->packet_size);
	buffer[dpkt->packet_size] = 0;
printf("SEND: %s\n", buffer);
	/* send data back to the client */
	connection_send_data(conp, buffer, dpkt->packet_size);
	return 0;
}
Exemple #4
0
/*  This user-defined function is called after the user program receives
	a data packet. It processes the content of the packet and then send 
	the simulated result back to the master */
static int	
mbasc_slave_dispatch (MHANDLE conp, void *private_data, DATAPKT *dpkt)
{
	unsigned char *buf = (unsigned char *) private_data;
	unsigned int plen = dpkt->packet_size;
	int consumed;
	unsigned char mbasc_buf[256];
	int len;
	unsigned short slave_id;
	unsigned short Modbus_id = 10;

	len = mbasc_packet_digest(dpkt->packet_data, &plen, mbasc_buf);
	if (len <= 0)
	{
		/* MODBUS ADU packet not complete */
		slave_id = mbasc_buf[0];
		if (slave_id == Modbus_id) /* wait */
			consumed = 0;
		else /* discard */
			consumed = plen;
	}
	else
	{
		consumed = plen;
		slave_id = mbasc_buf[0];
		if (slave_id == Modbus_id)
		{
			/* process MODBUS ASCII request packet and get response PDU */
			len = mbasc_parser(mbasc_buf, len, buf, sizeof(buf));
			/* format response ADU */
			len = mbasc_packet_format(buf, len, mbasc_buf);
			/* send MODBUS ASCII response */
			if (len > 0)
				connection_send_data(conp, mbasc_buf, len);
		}
	}
	dpkt->packet_consumed = consumed;

	return consumed; 
}
Exemple #5
0
/**************************************************************************
  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)
{
  /* default for the server */
  int result = 0;

  log_packet("sending packet type=%s(%d) len=%d to %s",
             packet_name(data[2]), data[2], len,
             is_server() ? pc->username : "******");

  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, data[2], len, result);
  }

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

    packet_type = data[2];
    if (conn_compression_frozen(pc)) {
      size_t old_size = pc->compression.queue.size;

      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));
      if (MAX_LEN_BUFFER < byte_vector_size(&pc->compression.queue)) {
        log_compress2("COMPRESS: huge queue, forcing to flush (%lu/%lu)",
                      (long unsigned)
                      byte_vector_size(&pc->compression.queue),
                      (long unsigned) MAX_LEN_BUFFER);
        if (!conn_compression_flush(pc)) {
          return -1;
        }
        byte_vector_reserve(&pc->compression.queue, 0);
      }
    } 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
  connection_send_data(pc, data, len);
#endif

#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 packet_type = data[2];
    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;
}
Exemple #6
0
/**************************************************************************
  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 : "******");

  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;
}
Exemple #7
0
/****************************************************************************
  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;
}