瀏覽代碼

Merge branch 'master' into resource-manager

Daniele Bartolini 13 年之前
父節點
當前提交
d323e39c2b

+ 4 - 3
src/CMakeLists.txt

@@ -128,14 +128,12 @@ set (MATH_HEADERS
 )
 
 set (STREAMS_SRC
-	core/streams/File.cpp
 	core/streams/FileStream.cpp
 	core/streams/MemoryStream.cpp
 	core/streams/Stream.cpp
 )
 
 set (STREAMS_HEADERS
-	core/streams/File.h
 	core/streams/FileStream.h
 	core/streams/MemoryStream.h
 	core/streams/NullStream.h
@@ -225,9 +223,11 @@ set (LINUX_SRC
 	os/linux/Input.cpp
 	os/linux/LinuxTCPSocket.cpp
 	os/linux/LinuxUDPSocket.cpp	
+	os/linux/File.cpp
 )
 
 set (LINUX_HEADERS
+	os/linux/File.h
 #	os/linux/EGLRenderWindow.h
 )
 
@@ -239,12 +239,13 @@ set (WIN_SRC
 set (NETWORK_SRC
 	network/BitMessage.cpp
 	network/AsyncConnection.cpp
-	
+	network/PacketQueue.h
 )
 
 set (NETWORK_HEADERS
 	network/BitMessage.h
 	network/AsyncConnection.h
+	network/PacketQueue.h
 )
 
 set (SOURCES

+ 23 - 23
src/core/streams/FileStream.cpp

@@ -60,8 +60,7 @@ void FileStream::seek(size_t position)
 {
 	check_valid();
 
-	//flush(); <<<---?
-	fseek(m_file->get_handle(), position, SEEK_SET);
+	m_file->seek(position, SEEK_SET);
 }
 
 //-----------------------------------------------------------------------------
@@ -69,7 +68,7 @@ void FileStream::seek_to_end()
 {
 	check_valid();
 
-	fseek(m_file->get_handle(), 0, SEEK_END);
+	m_file->seek(0, SEEK_END);
 }
 
 //-----------------------------------------------------------------------------
@@ -77,7 +76,7 @@ void FileStream::skip(size_t bytes)
 {
 	check_valid();
 
-	fseek(m_file->get_handle(), bytes, SEEK_CUR);
+	m_file->seek(bytes, SEEK_CUR);
 }
 
 //-----------------------------------------------------------------------------
@@ -88,14 +87,14 @@ uint8_t FileStream::read_byte()
 	if (!m_last_was_read)
 	{
 		m_last_was_read = true;
-		fseek(m_file->get_handle(), 0, SEEK_CUR);
+		m_file->seek(0, SEEK_CUR);
 	}
 
 	uint8_t buffer;
-
-	if (fread(&buffer, 1, 1, m_file->get_handle()) != 1)
+	
+	if (m_file->read(&buffer, 1, 1) != 1)
 	{
-		Log::E("Could not read from file.");
+		Log::E("Could not read from file");
 	}
 
 	return buffer;
@@ -109,10 +108,10 @@ void FileStream::read(void* buffer, size_t size)
 	if (!m_last_was_read)
 	{
 		m_last_was_read = true;
-		fseek(m_file->get_handle(), 0, SEEK_CUR);
+		m_file->seek(0, SEEK_CUR);
 	}
 
-	if (fread(buffer, size, 1, m_file->get_handle()) != 1)
+	if (m_file->read(buffer, size, 1) != 1)
 	{
 		Log::E("Could not read from file.");
 	}
@@ -138,11 +137,12 @@ bool FileStream::copy_to(Stream* stream, size_t size)
 	{
 		int32_t readBytes;
 		int32_t expectedReadBytes = math::min(size - totReadBytes, chunksize);
-		readBytes = fread(buff, 1, expectedReadBytes, m_file->get_handle());
+
+		readBytes = m_file->read(buff, 1, expectedReadBytes);
 
 		if (readBytes < expectedReadBytes)
 		{
-			if (feof(m_file->get_handle()))
+			if (m_file->eof())
 			{
 				if (readBytes != 0)
 				{
@@ -190,10 +190,10 @@ void FileStream::write_byte(uint8_t val)
 	if (m_last_was_read)
 	{
 		m_last_was_read = false;
-		fseek(m_file->get_handle(), 0, SEEK_CUR);
+		m_file->seek(0, SEEK_CUR);
 	}
 
-	if (fputc(val, m_file->get_handle()) == EOF)
+	if (m_file->write(&val, 1, 1) != 1)
 	{
 		Log::E("Could not write to file.");
 	}
@@ -207,10 +207,10 @@ void FileStream::write(const void* buffer, size_t size)
 	if (m_last_was_read)
 	{
 		m_last_was_read = false;
-		fseek(m_file->get_handle(), 0, SEEK_CUR);
+		m_file->seek(0, SEEK_CUR);
 	}
 
-	if (fwrite(buffer, size, 1, m_file->get_handle()) != 1)
+	if (m_file->write(buffer, size, 1) != 1)
 	{
 		Log::E("Could not write to file.");
 	}
@@ -220,24 +220,24 @@ void FileStream::write(const void* buffer, size_t size)
 void FileStream::flush()
 {
 	check_valid();
-	fflush(m_file->get_handle());
+	
+	// FIXME implement flush in File
 }
 
 //-----------------------------------------------------------------------------
 size_t FileStream::position() const
 {
 	check_valid();
-	return ftell(m_file->get_handle());
+
+	return m_file->tell();
 }
 
 //-----------------------------------------------------------------------------
 size_t FileStream::size() const
 {
-	size_t pos = position();
-	fseek(m_file->get_handle(), 0, SEEK_END);
-	size_t size = position();
-	fseek(m_file->get_handle(), pos, SEEK_SET);
-	return size;
+	check_valid();
+	
+	return m_file->size();
 }
 
 //-----------------------------------------------------------------------------

+ 112 - 163
src/network/AsyncConnection.cpp

@@ -11,26 +11,22 @@ AsyncConnection::AsyncConnection(Allocator& allocator) :
 	m_mode(NONE),
 	m_state(DISCONNECTED),
 	m_max_rate(MAX_RATE),
-	m_outgoing_rate_time(0),
-	m_outgoing_rate_bytes(0),
-	m_incoming_rate_time(0),
-	m_incoming_rate_bytes(0),
-	m_incoming_recv_packets(0.0f),
-	m_incoming_dropped_packets(0.0f),
-	m_incoming_packet_loss_time(0),
-	m_outgoing_sent_packet(0),
+	m_sent_packets(0),
+	m_recv_packets(0),
+	m_dropped_packets(0.0f),
 	m_local_sequence(0),
 	m_remote_sequence(0),
 	m_max_sequence(MAX_SEQUENCE),
 	m_max_rtt(MAX_RTT),	//in milliseconds
-	m_rtt(0),		
-	m_last_send_time(0),
-	m_last_data_bytes(0),
+	m_rtt(0),
+	m_sent_queue(allocator),
+	m_received_queue(allocator),
 	m_running(false),
- 	m_sent_msg(allocator),
- 	m_received_msg(allocator),
- 	m_pending_ack(allocator),
- 	m_acked(allocator)
+	m_sent_packet(allocator),
+	m_received_packet(allocator),
+	m_pending_ack(allocator),
+	m_acked(allocator),
+	m_allocator(&allocator)
 {
   
 }
@@ -70,12 +66,19 @@ void AsyncConnection::stop()
 {
 	// if connection is running
 	assert(m_running);
-	os::printf("stop connection\n");;
-//  	bool connected = is_connected();
-	_clear_data();
-	// close socket
-	m_socket.close();
-	m_running = false;
+	os::printf("stopping connection...\n");;
+
+	if (is_connected())
+	{
+		os::printf("connection stopped\n");;
+		_clear_data();
+		// close socket
+		m_socket.close();
+		m_running = false;
+		return;
+	}
+	
+	os::printf("connection is running yet");
 }
 
 //-----------------------------------------------------------------------------
@@ -108,12 +111,7 @@ void AsyncConnection::connect(const os::NetAddress& addr)
 //-----------------------------------------------------------------------------
 void AsyncConnection::reset_rate()
 {
-  	m_last_send_time = 0;
-	m_last_data_bytes = 0;
-	m_outgoing_rate_time = 0;
-	m_outgoing_rate_bytes = 0;
-	m_incoming_rate_time = 0;
-	m_incoming_rate_bytes = 0;
+
 }
 
 //-----------------------------------------------------------------------------
@@ -137,24 +135,22 @@ os::NetAddress AsyncConnection::get_remote_address() const
 //-----------------------------------------------------------------------------
 int AsyncConnection::get_outgoing_rate() const
 {
-	return m_outgoing_rate_bytes;
 }
 
 //-----------------------------------------------------------------------------
 int AsyncConnection::get_incoming_rate() const
 {
-	return m_incoming_rate_bytes;
 }
 
 //-----------------------------------------------------------------------------
 float AsyncConnection::get_incoming_packet_loss() const
 {
-	if (m_incoming_recv_packets == 0 && m_incoming_dropped_packets == 0)
+	if (m_recv_packets == 0 && m_dropped_packets == 0)
 	{
 		return 0.0f;
 	}
 	// return loss packet %
-	return m_incoming_dropped_packets * 100 / (m_incoming_recv_packets + m_incoming_dropped_packets);
+	return m_dropped_packets * 100 / (m_recv_packets + m_dropped_packets);
 }
 
 //-----------------------------------------------------------------------------
@@ -166,30 +162,59 @@ uint16_t AsyncConnection::get_local_sequence() const
 void AsyncConnection::send_message(BitMessage& msg, const uint32_t time)
 {
 	assert(m_running);
-	
-	m_socket.send(m_remote_address, msg.get_data(), msg.get_size());
-
+	// set header
+	msg.set_header(m_id, m_local_sequence, m_remote_sequence, _generate_ack_bits());
+	// evaluate message size	
+	size_t size = msg.get_header_size() + msg.get_size();
+	uint8_t* data = (uint8_t*)m_allocator->allocate(size);
+	// merge header with data 
+	memcpy(data, msg.get_header(), 12);
+	memcpy(data + 12, msg.get_data(), size - 12);
+	// send message
+	m_socket.send(m_remote_address, data, size);
+	// storage outgoing message
+	m_sent_queue.push_back(msg);
 }
 
 //-----------------------------------------------------------------------------
 int32_t AsyncConnection::receive_message(BitMessage& msg, const uint32_t time)
 {
 	assert(m_running);
-	// init BitMessage handler
-	msg.init(175);
-	msg.begin_writing();
-	size_t size = 175;
-	// NetAddress handler
+	
 	os::NetAddress sender(0, 0, 0, 0, 0);
+
+	size_t size = msg.get_max_size();
+	
+	uint8_t* data = (uint8_t*)m_allocator->allocate(msg.get_header_size() + size);
+
 	// receive message
-	int32_t bytes = m_socket.receive(sender, msg.get_data(), size);
-	//TODO: why received bytes is zero
-	os::printf("%d bytes received\n", bytes);
+	int32_t received_bytes = m_socket.receive(sender, data, size);
+	if (received_bytes <= 0)
+	{
+		return 0;
+	}
+
+	// header-taking
+	uint32_t protocol_id = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+	uint16_t sequence = data[4] << 8 | data[5];
+	uint16_t ack = data[6] << 8 | data[7];
+	uint32_t ack_bits = data[8] << 24 | data[9] << 16 | data[10] << 8 | data[11];
+	
+	msg.begin_writing();
+	msg.set_header(protocol_id, sequence, ack, ack_bits);
+	//data-taking
+ 	uint8_t* tmp_ptr = &data[12];
+	memcpy(msg.get_data(), tmp_ptr, msg.get_max_size());
 	msg.set_size(size);
-	// sets BitMessage in only-read
+	
+ 	// storage incoming message	
+	m_received_queue.push_back(msg);
+	
+	// sets BitMessage in read-only for processing
 	msg.begin_reading();
 	
-	if (m_mode == SERVER && !is_connected() && bytes > 0)
+	// establish connection after first packet is received
+	if (m_mode == SERVER && !is_connected())
 	{
 		os::printf("server accepts connection from client ");
 		os::printf("%i.", (uint8_t)sender.address[0]);
@@ -201,7 +226,8 @@ int32_t AsyncConnection::receive_message(BitMessage& msg, const uint32_t time)
 		m_state = CONNECTED;
 		m_remote_address = sender;
 	}
-
+	
+	// completes connection after first packet is received from server
 	if (sender == m_remote_address)
 	{
 		if (m_mode == CLIENT && m_state == CONNECTING)
@@ -218,17 +244,17 @@ int32_t AsyncConnection::receive_message(BitMessage& msg, const uint32_t time)
 //-----------------------------------------------------------------------------
 void AsyncConnection::clear_reliable_messages()
 {
-	m_sent_msg.clear();
-	m_received_msg.clear();
+	m_sent_queue.clear();
+	m_received_queue.clear();
 }
 
 //-----------------------------------------------------------------------------
 void AsyncConnection::update(real delta)
 {
 	assert(m_running);
-	
+	// improve timeout accumulator of delta time
 	m_timeout_acc += delta;
-	
+	// if timeout accumulator > generic timeout
 	if (m_timeout_acc > m_timeout)
 	{
 		if (m_state == CONNECTING)
@@ -246,31 +272,11 @@ void AsyncConnection::update(real delta)
 				m_state = CONNECT_FAIL;
 			}
 		}
-	}	
+	}
 }	
 
 //-----------------------------------------------------------------------------
 bool AsyncConnection::ready_to_send(const int time) const
-{
-	// if max rate isn't set, send message
-	if (!m_max_rate)
-	{
-		return true;
-	}
-	
-	int delta_time;
-	
-	delta_time = time - m_last_send_time;
-	if (delta_time > 1000)
-	{
-		return true;
-	}
-	// if last message wasn't sent, sent it!
-	return ((m_last_data_bytes - ((delta_time * m_max_rate) / 1000)) <= 0);
-}
-
-//-----------------------------------------------------------------------------
-bool AsyncConnection::process(const os::NetAddress from, int time, BitMessage &msg, int &sequence)
 {
 
 }
@@ -301,22 +307,22 @@ bool AsyncConnection::is_connect_fail() const
 
 //-----------------------------------------------------------------------------
 void AsyncConnection::_packet_sent(size_t size)
-{
+{/*
 	bool seq_exists_in_sent_queue = false;
 	bool seq_exists_in_pending_ack_queue = false;
   
-	BitMessage::Header tmp;
-	BitMessage::Header* h_ptr;
+	PacketData tmp;
+	PacketData* h_ptr;
 	
 	tmp.sequence = m_local_sequence;
 
-	// If local_sequence_number is already in sent_queue
-	h_ptr = std::find(m_sent_msg.begin(), m_sent_msg.end(), tmp);
-	if (h_ptr != m_sent_msg.end())
+	// If local_sequence_number exists
+	h_ptr = std::find(m_sent_packet.begin(), m_sent_packet.end(), tmp);
+	if (h_ptr != m_sent_packet.end())
 	{
 		seq_exists_in_sent_queue = true;
 	}
-	// If local_sequence_number is already in pending_ack_queue
+
 	h_ptr = std::find(m_pending_ack.begin(), m_pending_ack.end(), tmp);
 	if(h_ptr != m_pending_ack.end())
 	{
@@ -327,54 +333,54 @@ void AsyncConnection::_packet_sent(size_t size)
  	assert(!seq_exists_in_pending_ack_queue);
 	
 	// Creates Header for saving in queues
-	BitMessage::Header header;
-	header.sequence = m_local_sequence;
-	header.time = 0.0f;
-	header.size = size;
+	PacketData packet;
+	packet.sequence = m_local_sequence;
+	packet.time = 0.0f;
+	packet.size = size;
 	// Push packet data in sent_queue
-	m_sent_msg.push_back(header);
+	m_sent_packet.push_back(packet);
 	// push packet data in pending_ack_queue
-	m_pending_ack.push_back(header);
-	// Increments sent packet
-	m_outgoing_sent_packet++;
+	m_pending_ack.push_back(packet);
+	// Increments sent packets
+	m_sent_packets++;
 	// Increments local sequence
 	m_local_sequence++;
 
 	if (m_local_sequence > m_max_sequence)
 	{
 		m_local_sequence = 0;
-	}
+	}*/
 }
 
 //-----------------------------------------------------------------------------
 void AsyncConnection::_packet_received(uint16_t sequence, size_t size)
-{
-	BitMessage::Header tmp;
-	BitMessage::Header* h_ptr;
+{/*
+	PacketData tmp;
+	PacketData* h_ptr;
 
 	tmp.sequence = sequence;
 
 	// Increment received packets
-	m_incoming_recv_packets++;
+	m_recv_packets++;
 	
 	// If packet's sequence exists, return
-	h_ptr = std::find(m_received_msg.begin(), m_received_msg.end(), tmp);
-	if (h_ptr != m_received_msg.end())
+	h_ptr = std::find(m_received_packet.begin(), m_received_packet.end(), tmp);
+	if (h_ptr != m_received_packet.end())
 	{
 		return;
 	}
 	
-	BitMessage::Header header;
-	header.sequence = sequence;
-	header.time = 0.0f;
-	header.size = size;
+	PacketData packet;
+	packet.sequence = sequence;
+	packet.time = 0.0f;
+	packet.size = size;
 	// Push packet data in received_queue
-	m_received_msg.push_back(header);
+	m_received_packet.push_back(packet);
 	// update m_remote_sequence
 	if (_sequence_more_recent(sequence, m_remote_sequence))
 	{
 		m_remote_sequence = sequence;
-	}  
+	}  */
 }
 
 //-----------------------------------------------------------------------------
@@ -385,7 +391,7 @@ void AsyncConnection::_process_ack(uint16_t ack, int32_t ack_bits)
 		return;
 	}
 	
-	BitMessage::Header* i = m_pending_ack.begin();
+	PacketData* i = m_pending_ack.begin();
 	while (i != m_pending_ack.end())
 	{
 		bool acked = false;
@@ -414,6 +420,7 @@ void AsyncConnection::_process_ack(uint16_t ack, int32_t ack_bits)
 			++i;
 		}
 	}  
+	
 	m_pending_ack.clear();
 }
 
@@ -445,18 +452,18 @@ int32_t AsyncConnection::_bit_index_for_sequence(uint16_t seq, uint16_t ack)
 }
 
 //-----------------------------------------------------------------------------
-int32_t AsyncConnection::_generate_ack_bits(uint16_t ack)
+int32_t AsyncConnection::_generate_ack_bits()
 {
 	int32_t ack_bits = 0;
 	
-	for (BitMessage::Header* i = m_received_msg.begin(); i != m_received_msg.end(); i++)
+	for (PacketData* i = m_received_packet.begin(); i != m_received_packet.end(); i++)
 	{
-		if (i->sequence == ack || _sequence_more_recent(i->sequence, ack))
+		if (i->sequence == m_remote_sequence || _sequence_more_recent(i->sequence, m_remote_sequence))
 		{
 			break;
 		}
 		
-        int32_t bit_index = _bit_index_for_sequence(i->sequence, ack);
+        int32_t bit_index = _bit_index_for_sequence(i->sequence, m_remote_sequence);
 		if (bit_index <= 31)
 		{
 			ack_bits |= 1 << bit_index;
@@ -468,76 +475,18 @@ int32_t AsyncConnection::_generate_ack_bits(uint16_t ack)
 //-----------------------------------------------------------------------------
 void AsyncConnection::_update_outgoing_rate(const uint32_t time, const size_t size)
 {
-	// update the outgoing rate control variables
-	int delta_time;
-	delta_time = time - m_last_send_time;
-	if (delta_time > 1000) 
-	{
-		m_last_data_bytes = 0;
-	}
-	else 
-	{
-		m_last_data_bytes -= (delta_time * m_max_rate) / 1000;
-		if ( m_last_data_bytes < 0 ) 
-		{
-			m_last_data_bytes = 0;
-		}
-	}
-	
-	m_last_data_bytes += size;
-	m_last_send_time = time;  
-	
-	// update outgoing rate variables
-	if (time - m_outgoing_rate_time > 1000) 
-	{
-		m_outgoing_rate_bytes -= m_outgoing_rate_bytes * (time - m_outgoing_rate_time - 1000) / 1000;
-		if (m_outgoing_rate_bytes < 0) 
-		{
-			m_outgoing_rate_bytes = 0;
-		}
-	}
-	
-	m_outgoing_rate_time = time - 1000;
-	m_outgoing_rate_bytes += size;
+
 }
 
 //-----------------------------------------------------------------------------
 void AsyncConnection::_update_incoming_rate(const uint32_t time, const size_t size)
 {
-	// update incoming rate variables
-	if (time - m_incoming_rate_time > 1000) 
-	{
-		m_incoming_rate_bytes -= m_incoming_rate_bytes * (time - m_incoming_rate_time - 1000) / 1000;
-		if (m_incoming_rate_bytes < 0) 
-		{
-			m_incoming_rate_bytes = 0;
-		}
-	}
-	m_incoming_rate_time = time - 1000;
-	m_incoming_rate_bytes += size;  
+ 
 }
 
 //-----------------------------------------------------------------------------
 void AsyncConnection::_update_packet_loss(const uint32_t time, const uint32_t num_recv, const uint32_t num_dropped)
 {
-	// update incoming packet loss variables
-	if (time - m_incoming_packet_loss_time > 5000) 
-	{
-		float scale = (time - m_incoming_packet_loss_time - 5000) * (1.0f / 5000.0f);
-		m_incoming_recv_packets -= m_incoming_recv_packets * scale;
-		if (m_incoming_recv_packets < 0.0f) 
-		{
-			m_incoming_recv_packets = 0.0f;
-		}
-		m_incoming_dropped_packets -= m_incoming_dropped_packets * scale;
-		if (m_incoming_dropped_packets < 0.0f) 
-		{
-			m_incoming_dropped_packets = 0.0f;
-		}
-	}
-	m_incoming_packet_loss_time = time - 5000;
-	m_incoming_recv_packets += num_recv;
-	m_incoming_dropped_packets += num_dropped;
 }
 
 void AsyncConnection::_clear_data()

+ 53 - 41
src/network/AsyncConnection.h

@@ -6,26 +6,37 @@
 #include "BitMessage.h"
 #include "Queue.h"
 
-#define DEFAULT_PROTOCOL_ID 0xFFFFFFFF
-#define DEFAULT_TIMEOUT		10.0f
-#define MAX_RATE			64000
-#define MAX_SEQUENCE		0xFFFFFFFF
-#define MAX_RTT				1000
-#define MAX_PACKET_LEN		1400
-#define MAX_MESSAGE_SIZE	16384
-#define MAX_QUEUE_SIZE		16384
-
 namespace crown
 {
 namespace network
 {
 
-	
 /**
  * Reliable connection over UDP
  */
 class AsyncConnection
 {
+public:
+  
+	struct PacketData
+	{
+		  uint32_t 	sequence;
+		  real		time;
+		  size_t	size;
+		  
+		  PacketData()
+		  {
+			  sequence = 0;
+			  time = 0.0f;
+			  size = 0;
+		  }
+		  
+		  bool operator==(const PacketData& packet)
+		  {
+			  return sequence == packet.sequence;
+		  }
+	};
+  
 public:
 
 									AsyncConnection(Allocator& allocator);
@@ -56,7 +67,7 @@ public:
 	uint16_t						get_remote_sequence() const;
 									// Sends message
 	void							send_message(BitMessage& msg, const uint32_t time);
-									// Receive message
+									// Receive message and process
 	int32_t							receive_message(BitMessage& msg, const uint32_t time);
 									// Removes any pending outgoing or incoming reliable messages.
 	void							clear_reliable_messages();
@@ -64,8 +75,6 @@ public:
 	void 							update(real delta);
 									// Returns true if the connection is ready to send new data based on the maximum rate.
 	bool							ready_to_send(const int32_t time) const;
-									// Processes the incoming message.
-	bool							process(const os::NetAddress from, int32_t time, BitMessage &msg, int32_t &sequence);
 	
 	bool 							is_connecting() const;
 	bool 							is_listening() const; 
@@ -100,11 +109,11 @@ private:
 	void 							_process_ack(uint16_t ack, int32_t ack_bits);
 	bool							_sequence_more_recent(uint16_t s1, uint16_t s2);
 	int32_t							_bit_index_for_sequence(uint16_t seq, uint16_t ack);
-	int32_t							_generate_ack_bits(uint16_t ack);
+	int32_t							_generate_ack_bits();
 									// methods which provides a flow control system
-	void							_update_outgoing_rate(const uint32_t time, const size_t size);
-	void							_update_incoming_rate(const uint32_t time, const size_t size);
-	void							_update_packet_loss(const uint32_t time, const uint32_t num_recv, const uint32_t num_dropped);
+	void							_update_outgoing_rate(const uint32_t delta, const size_t size);
+	void							_update_incoming_rate(const uint32_t delta, const size_t size);
+	void							_update_packet_loss(const uint32_t delta, const uint32_t num_recv, const uint32_t num_dropped);
 	
 	void							_clear_data();
 
@@ -113,23 +122,15 @@ private:
   
 	os::NetAddress					m_remote_address;			// address of remote host
 	os::UDPSocket					m_socket;					// socket
-	int32_t							m_id;						// our identification used instead of port number
+	uint32_t						m_id;						// our identification used instead of port number
 	Mode							m_mode;						// connection mode
 	State							m_state;					// connection state
-	int32_t							m_max_rate;					// maximum number of bytes that may go out per second
-
-									// variables to keep track of the rate
-	int32_t							m_outgoing_rate_time;		// outgoing time rate
-	int32_t							m_outgoing_rate_bytes;		// outgoing bytes rate
-	int32_t							m_incoming_rate_time;		// incoming time rate
-	int32_t							m_incoming_rate_bytes;		// incoming bytes rate
+	uint32_t						m_max_rate;					// maximum number of bytes that may go out per second
 
 									// variables to keep track of the incoming packet loss
-	real							m_incoming_recv_packets;
-	real							m_incoming_dropped_packets;
-	int32_t							m_incoming_packet_loss_time;
-
-	int32_t							m_outgoing_sent_packet;		// keep track of sent packet
+	uint32_t						m_sent_packets;		
+	uint32_t						m_recv_packets;
+	real							m_dropped_packets;
 
 									// sequencing variables
 	uint16_t						m_local_sequence;
@@ -141,19 +142,30 @@ private:
 	real							m_timeout;					// connection timeout value
 	real							m_timeout_acc;				// timeout accumulator
 	
-									// variables to control the outgoing rate
-	int32_t							m_last_send_time;			// last time data was sent out
-	int32_t							m_last_data_bytes;			// bytes left to send at last send time
-									
+									// reliable message queues
+	Queue<BitMessage>				m_sent_queue;
+	Queue<BitMessage>				m_received_queue;
+	
 									// flag variables
 	bool							m_running;
-									// reliable messages
-	Queue<BitMessage::Header>		m_sent_msg;					// Sent messages queue
-	Queue<BitMessage::Header>		m_received_msg;				// Received messages queue
-	Queue<BitMessage::Header>		m_pending_ack;				// Pending acknokledges queue
-	Queue<BitMessage::Header>		m_acked;					// Acknowledges queue
-					
-
+	
+									// packet queues
+	Queue<PacketData>				m_sent_packet;					// Sent messages queue
+	Queue<PacketData>				m_received_packet;				// Received messages queue
+	Queue<PacketData>				m_pending_ack;					// Pending acknokledges queue
+	Queue<PacketData>				m_acked;						// Acknowledges queue
+	
+	Allocator*						m_allocator;					// dynamic allocator
+									
+									// constants
+	static const uint32_t			DEFAULT_PROTOCOL_ID	= 0xFFFFFFFF;
+	static const uint32_t			DEFAULT_TIMEOUT		= 10;
+	static const uint32_t			MAX_RATE			= 64000;
+	static const uint32_t			MAX_SEQUENCE		= 0xFFFF;
+	static const uint32_t			MAX_RTT				= 1000;
+	static const uint32_t			MAX_PACKET_LEN		= 1400;
+	static const uint32_t			MAX_MESSAGE_SIZE	= 16384;
+	static const uint32_t			MAX_QUEUE_SIZE		= 16384;
 
 };
 

+ 64 - 42
src/network/BitMessage.cpp

@@ -19,7 +19,8 @@ BitMessage::BitMessage(Allocator& allocator) :
 	m_read_count(0),
 	m_write_bit(0), 
 	m_read_bit(0),
-	m_overflowed(false)
+	m_overflowed(false),
+	m_init(false)
 {
 }
 
@@ -27,10 +28,14 @@ BitMessage::BitMessage(Allocator& allocator) :
 
 BitMessage::~BitMessage()
 {
-  if (m_data)
-  {
-		m_allocator->deallocate((void*)m_data);
-  }
+	if (m_header)
+	{
+		m_allocator->deallocate((void*)m_header);
+	}
+	if (m_data)
+	{
+		  m_allocator->deallocate((void*)m_data);
+	}
 }
 //---------------------------------------------------------------------------------------------
 
@@ -77,46 +82,87 @@ bool BitMessage::check_overflow(int32_t num_bits)
 }
 
 //---------------------------------------------------------------------------------------------
-
 void BitMessage::init(int32_t len)
 {
+	m_header = (uint8_t*)m_allocator->allocate(12);
+	
 	m_data = (uint8_t*)m_allocator->allocate(len);
 	
 	m_write = m_data;
 	m_read = m_data;
 	m_max_size = len;
+	
+	m_init = true;
 }
 
 //---------------------------------------------------------------------------------------------
+void BitMessage::set_header(uint32_t id, uint16_t sequence, uint16_t ack, uint32_t ack_bits)
+{
+	uint8_t header[12];
+	header[0]	= (uint8_t)(id >> 24);
+	header[1]	= (uint8_t)(id >> 16);
+	header[2]	= (uint8_t)(id >> 8);
+	header[3]	= (uint8_t)id;
+	header[4]	= (uint8_t)(sequence >> 8);
+	header[5]	= (uint8_t)sequence;
+	header[6]	= (uint8_t)(ack >> 8);
+	header[7]	= (uint8_t)ack;
+	header[8]	= (uint8_t)(ack_bits >> 24);
+	header[9]	= (uint8_t)(ack_bits >> 16);
+	header[10]	= (uint8_t)(ack_bits >> 8);
+	header[11]	= (uint8_t)(ack_bits);
+	
+	memcpy(m_header, header, 12);
+}
 
+//---------------------------------------------------------------------------------------------
+uint8_t* BitMessage::get_header()
+{
+	return m_header;
+}
+
+//---------------------------------------------------------------------------------------------
+const uint8_t* BitMessage::get_header() const
+{
+	return m_header;
+}
+//---------------------------------------------------------------------------------------------
 uint8_t* BitMessage::get_data()
 {
 	return m_write;
 }
 
 //---------------------------------------------------------------------------------------------
-
 const uint8_t* BitMessage::get_data() const
 {
 	return m_read;
 }
 
 //---------------------------------------------------------------------------------------------
-
 size_t BitMessage::get_max_size() const
 {
 	return m_max_size;
 }
 
 //---------------------------------------------------------------------------------------------
-
 bool BitMessage::is_overflowed()
 {
 	return m_overflowed;
 }
 
 //---------------------------------------------------------------------------------------------
+bool BitMessage::is_init()
+{
+	return m_init;
+}
+
+//---------------------------------------------------------------------------------------------
+size_t BitMessage::get_header_size() const
+{
+	return 12;
+}
 
+//---------------------------------------------------------------------------------------------
 size_t BitMessage::get_size() const
 {
 	return m_cur_size;
@@ -317,7 +363,7 @@ void BitMessage::write_bits(int32_t value, int32_t num_bits)
 		}
 	}
 
-	// Change sign if it is negative
+	// Change sign if it's negative
 	if (num_bits < 0 ) 
 	{
 		num_bits = -num_bits;
@@ -414,23 +460,23 @@ void BitMessage::write_string(const char* s, int32_t max_len, bool make_7_bit)
 	else 
 	{
 		int32_t i;
-		int32_t l;
+		int32_t len = std::strlen(s);
 		uint8_t* data_ptr;
 		const uint8_t* byte_ptr;
 		
 		// calculates length
-		for (l = 0; s[l]; l++) {}
+		len = std::strlen(s);
 		
-		if (max_len >= 0 && l >= max_len) 
+		if (max_len >= 0 && len >= max_len) 
 		{
-			l = max_len - 1;
+			len = max_len - 1;
 		}
 		
-		data_ptr = get_byte_space(l + 1);
+		data_ptr = get_byte_space(len + 1);
 		byte_ptr = reinterpret_cast<const uint8_t*>(s);
 		if (make_7_bit) 
 		{
-			for (i = 0; i < l; i++) 
+			for (i = 0; i < len; i++) 
 			{
 				if ( byte_ptr[i] > 127 ) 
 				{
@@ -444,7 +490,7 @@ void BitMessage::write_string(const char* s, int32_t max_len, bool make_7_bit)
 		}
 		else 
 		{
-			for (i = 0; i < l; i++) 
+			for (i = 0; i < len; i++) 
 			{
 				data_ptr[i] = byte_ptr[i];
 			}
@@ -705,35 +751,11 @@ void BitMessage::read_netaddr(os::NetAddress* addr) const
 	addr->port = read_uint16();  
 }
 
-//---------------------------------------------------------------------------------------------
-void BitMessage::write_header(Header& header)
-{
-	// write header only on top of BitMessage
-	if (m_cur_size == 0)
-	{
-		write_int32(header.protocol_id);
-		write_uint16(header.sequence);
-		write_uint16(header.ack);
-		write_int32(header.ack_bits);
-		write_uint16(header.size);
-	}
-}
-
-//---------------------------------------------------------------------------------------------
-size_t BitMessage::read_header(Header& header)
-{
-	header.protocol_id = read_int32();
-	header.sequence = read_uint16();
-	header.ack = read_uint16();
-	header.ack_bits = read_int32();
-	header.size = (size_t)read_uint16();
-}
-
 //---------------------------------------------------------------------------------------------
 void BitMessage::print() const
 {
 	os::printf("MAX_SIZE: %d\n", m_max_size);
-	os::printf("CUR_SIZE: %d\n", m_cur_size);	
+	os::printf("CUR_SIZE: %d\n", m_cur_size);
 }
   
 }	//namespace network

+ 40 - 64
src/network/BitMessage.h

@@ -10,72 +10,50 @@ namespace crown
 namespace network
 {
 	/**
-	* bit-packet reliable message
+	* bit-packet reliable message.
+	* Usage: After every instantition, must be initialized with @init(len)
 	*/
 
 class BitMessage
 {
 
-public:
-
-	struct Header
-	{	
-		// Header fields in BitMessage - 14 Bytes
-		uint32_t		protocol_id;
-		uint16_t		sequence;
-		uint16_t		ack;
-		uint32_t		ack_bits;
-		uint16_t		size;
-		// Used to checks BitMessage's validity
-		uint32_t		time;
-
-		void set(uint32_t protocol_id, uint16_t sequence, uint16_t ack, uint32_t ack_bits, size_t size)
-		{
-			this->protocol_id = protocol_id;
-			this->sequence = sequence;
-			this->ack = ack;
-			this->ack_bits = ack_bits;
-			this->size = size;
-		}
-		
-		bool operator==(const Header& header)
-		{
-			return this->sequence == header.sequence;
-		}
-	}; 
-		
 public:
 						BitMessage(Allocator& allocator);
 						~BitMessage();
 
-	void				init(int32_t len);								// init with data length in byte
-	uint8_t*			get_data();										// get data for writing
-	const uint8_t*		get_data() const;								// get data for reading
-	size_t				get_max_size() const;							// get the maximum message size
-	bool 				is_overflowed();								// get overflowed flag
-
-	size_t				get_size() const;								// size of the message in bytes
-	void				set_size(size_t size);							// set the message size
-	int32_t				get_write_bit() const;							// get current write bit
-	void				set_write_bit(int32_t bit);						// set current write bit
-	int32_t				get_num_bits_written() const;					// returns number of bits written
-	int32_t				get_remaining_write_bits() const;				// space left in bits for writing
-	void				save_write_state(int32_t& s,int32_t& b) const;	// save the write state
-	void				restore_write_state(int32_t s,int32_t b);		// restore the write state
+	void				init(int32_t len);									// init with data length in byte
+	void				set_header(uint32_t id, uint16_t sequence, uint16_t ack, uint32_t ack_bits);
+	uint8_t*			get_header();										// get message header for writing
+	const uint8_t*		get_header() const;									// get message header for reading
+	uint8_t*			get_data();											// get message data for writing
+	const uint8_t*		get_data() const;									// get message data for reading
+	size_t				get_max_size() const;								// get the maximum message size
+	bool 				is_overflowed();									// is message overflowed
+	bool				is_init();											// is message initialized
+	
+	size_t				get_header_size() const;							// return 12 bytes
+	size_t				get_size() const;									// size of the message in bytes
+	void				set_size(size_t size);								// set the message size
+	int32_t				get_write_bit() const;								// get current write bit
+	void				set_write_bit(int32_t bit);							// set current write bit
+	int32_t				get_num_bits_written() const;						// returns number of bits written
+	int32_t				get_remaining_write_bits() const;					// space left in bits for writing
+	void				save_write_state(int32_t& s,int32_t& b) const;		// save the write state
+	void				restore_write_state(int32_t s,int32_t b);			// restore the write state
 
-	int32_t				get_read_count() const;							// bytes read so far
-	void				set_read_count(int32_t bytes);					// set the number of bytes and bits read
-	int32_t				get_read_bit() const;							// get current read bit
-	void				set_read_bit(int32_t bit);						// set current read bit
-	int32_t				get_num_bits_read() const;						// returns number of bits read
-	int32_t				get_remaining_read_bits() const;				// number of bits left to read
-	void				save_read_state(int32_t& c, int32_t& b) const;	// save the read state
-	void				restore_read_state(int32_t c, int32_t b);		// restore the read state
+	int32_t				get_read_count() const;								// bytes read so far
+	void				set_read_count(int32_t bytes);						// set the number of bytes and bits read
+	int32_t				get_read_bit() const;								// get current read bit
+	void				set_read_bit(int32_t bit);							// set current read bit
+	int32_t				get_num_bits_read() const;							// returns number of bits read
+	int32_t				get_remaining_read_bits() const;					// number of bits left to read
+	void				save_read_state(int32_t& c, int32_t& b) const;		// save the read state
+	void				restore_read_state(int32_t c, int32_t b);			// restore the read state
 						// write state utilities
-	void				begin_writing();								// begin writing
-	int32_t				get_remaining_space() const;					// space left in bytes
-	void				write_byte_align();								// write up to the next byte boundary
-	void				write_bits(int32_t value, int32_t num_bits);	// write the specified number of bits
+	void				begin_writing();									// begin writing
+	int32_t				get_remaining_space() const;						// space left in bytes
+	void				write_byte_align();									// write up to the next byte boundary
+	void				write_bits(int32_t value, int32_t num_bits);		// write the specified number of bits
 	void				write_int8(int32_t c);
 	void				write_uint8(int32_t c);
 	void				write_int16(int32_t c);
@@ -86,13 +64,12 @@ public:
 	void				write_string(const char* s, int32_t max_len = -1, bool make_7_bit = true);
 	void				write_data(const void* data, int32_t length);
 	void				write_netaddr(const os::NetAddress addr);
-	void				write_header(Header& header);
 
 						// read state utilities
-	void				begin_reading() const;							// begin reading.
-	int32_t				get_remaing_data() const;						// number of bytes left to read
-	void				read_byte_align() const;						// read up to the next byte boundary
-	int32_t				read_bits(int32_t num_bits) const;				// read the specified number of bits
+	void				begin_reading() const;								// begin reading.
+	int32_t				get_remaing_data() const;							// number of bytes left to read
+	void				read_byte_align() const;							// read up to the next byte boundary
+	int32_t				read_bits(int32_t num_bits) const;					// read the specified number of bits
 	int32_t				read_int8() const;
 	int32_t				read_uint8() const;
 	int32_t				read_int16() const;
@@ -103,7 +80,6 @@ public:
 	int32_t				read_string(char* buffer, int32_t buffer_size) const;
 	int32_t				read_data(void* data, int32_t length) const;
 	void				read_netaddr(os::NetAddress* addr) const;
-	size_t				read_header(Header& header);
 	
 	void				print() const;
 
@@ -115,9 +91,8 @@ private:
 private:
 	
 	Allocator*			m_allocator;								// memory allocator
-
-	Header*				m_header;									// message header abstraction 
 	
+	uint8_t*			m_header;
 	uint8_t*			m_data;
 	uint8_t*			m_write;									// pointer to data for writing
 	const uint8_t*		m_read;										// point32_ter to data for reading
@@ -130,7 +105,8 @@ private:
 	mutable int32_t		m_read_bit;									// number of bits read from the last read byte
 	
 	bool 				m_overflowed;								// overflow flag
-				
+	bool				m_init;										// is init flag
+	
 };
 } // namespace network
 } // namespace crown

+ 138 - 0
src/network/PacketQueue.cpp

@@ -0,0 +1,138 @@
+#include "PacketQueue.h"
+
+namespace crown
+{
+namespace network
+{
+
+//-------------------------------------------------------------
+PacketQueue::PacketQueue() :
+	m_first(0),
+	m_last(0),
+	m_start_index(0),
+	m_end_index(0)
+{
+
+}
+
+//-------------------------------------------------------------
+PacketQueue::~PacketQueue()
+{
+
+}
+
+//-------------------------------------------------------------
+bool PacketQueue::add(const PacketData& pd)
+{	
+	if (get_space_left() < sizeof(PacketData))
+	{
+		return false;
+	}
+	// update last sequence number
+	write_uint16(pd.sequence);
+	write_int32(pd.time);
+	write_int32(pd.time);
+	last++; 
+	return true;
+}
+
+//-------------------------------------------------------------
+bool PacketQueue::get(PacketData& pd)
+{	
+	// empty queue
+	if (first == last)
+	{
+		return false;
+	}
+
+	pd.sequence = read_uint16();
+	pd.time = read_int32();
+	pd.size = read_int32();
+
+	assert(pd.sequence == first);
+	first++;
+	return true;
+}
+
+//-------------------------------------------------------------
+size_t PacketQueue::get_total_size() const
+{
+	if (m_start_index <= m_end_index) 
+	{
+		return endIndex - startIndex;
+	} 
+	else 
+	{
+		return sizeof(buffer) - startIndex + endIndex;
+	}
+}
+
+//-------------------------------------------------------------
+size_t PacketQueue::get_space_left() const
+{
+	if (m_start_index <= m_end_index) 
+	{
+		return sizeof(buffer) - (endIndex - startIndex) - 1;
+	} 
+	else 
+	{
+		return (startIndex - endIndex) - 1;
+	}
+}
+
+//-------------------------------------------------------------
+int32_t PacketQueue::get_first() const
+{
+	return m_first;
+}
+
+//-------------------------------------------------------------
+int32_t PacketQueue::get_last() const
+{
+	return m_last;
+}
+
+//-------------------------------------------------------------
+void PacketQueue::write_uint8(uint8_t value)
+{
+	m_buffer[m_end_index] = value;
+	m_end_index = (m_end_index + 1) & (MAX_QUEUE_SIZE - 1);
+}
+
+//-------------------------------------------------------------
+void PacketQueue::write_uint16(int32_t value)
+{
+	write_uint8((value >> 0) & 255); 
+	write_uint8((value >> 8) & 255);
+}
+
+//-------------------------------------------------------------
+void PacketQueue::write_int32(int32_t value)
+{
+	write_uint8((value >> 0) & 255); 
+	write_uint8((value >> 8) & 255);
+	write_uint8((value >> 16) & 255); 
+	write_uint8((value >> 24) & 255);	
+}
+
+//-------------------------------------------------------------
+int8_t PacketQueue::read_uint8()
+{
+	uint8_t value = m_buffer[m_start_index];
+	m_start_index = (m_start_index + 1) & (MAX_QUEUE_SIZE - 1);
+}
+
+//-------------------------------------------------------------
+int32_t PacketQueue::read_uint16()
+{
+	return (read_uint8()) | (read_uint8() << 8);
+}
+
+//-------------------------------------------------------------
+int32_t PacketQueue::read_int32()
+{
+	return (read_uint8()) | (read_uint8() << 8) | (read_uint8() << 16) | (read_uint8() << 24);
+}
+
+}
+} // namespace crown

+ 53 - 0
src/network/PacketQueue.h

@@ -0,0 +1,53 @@
+#pragma once
+#include "Types.h"
+
+namespace crown
+{
+namespace network
+{
+
+class PacketQueue
+{
+public:
+
+	struct PacketData
+	{
+		uint16_t sequence;	
+		uint32_t time;
+		size_t size;
+	};
+
+public:
+
+							PacketQueue();
+							~PacketQueue();
+
+	bool					add(const PacketData& pd);
+	bool					get(PacketData& pd);
+	size_t					get_total_size() const;
+	size_t					get_space_left() const;
+	int32_t					get_first() const; 
+	int32_t					get_last() const;
+
+private:
+
+	void 					write_uint8(int32_t value);
+	void					write_uint16(int32_t value);
+	void 					write_int32(int32_t value);
+
+	int32_t					read_uint8();
+	int32_t					read_uint16();
+	int32_t					read_int32();
+
+private:
+	static const uint32_t 	MAX_QUEUE_SIZE = 16384;	
+
+	uint8_t					m_buffer[MAX_QUEUE_SIZE];
+	uint32_t				m_first;							// sequence number of first message in queue
+	uint32_t				m_last;							// sequence number of last message in queue
+	uint32_t				m_start_index;					// index pointing to the first byte of the first message
+	uint32_t				m_end_index;						// index pointing to the first byte after the last message
+};
+
+} // namespace network
+} // namespace crown

+ 45 - 2
src/core/streams/File.cpp → src/os/linux/File.cpp

@@ -26,20 +26,21 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "File.h"
 #include "Log.h"
 #include "MathUtils.h"
+#include <cassert>
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
 File::File() :
-	m_file_handle(0), m_mode(FOM_READ)
+	m_file_handle(NULL), m_mode(FOM_READ)
 {
 }
 
 //-----------------------------------------------------------------------------
 File::~File()
 {
-	if (m_file_handle != 0)
+	if (m_file_handle != NULL)
 	{
 		fclose(m_file_handle);
 	}
@@ -89,6 +90,48 @@ File* File::open(const char* path, FileOpenMode mode)
 	return f;
 }
 
+//-----------------------------------------------------------------------------
+size_t File::read(void* ptr, size_t size, size_t nmemb)
+{
+	assert(m_file_handle != NULL);
+	assert(ptr != NULL);
+
+	return fread(ptr, size, nmemb, m_file_handle);
+}
+
+//-----------------------------------------------------------------------------
+size_t File::write(const void* ptr, size_t size, size_t nmemb)
+{
+	assert(m_file_handle != NULL);
+	assert(ptr != NULL);
+
+	return fwrite(ptr, size, nmemb, m_file_handle);
+}
+
+//-----------------------------------------------------------------------------
+int File::seek(int32_t offset, int whence)
+{
+	assert(m_file_handle != NULL);
+
+	return fseek(m_file_handle, offset, whence);
+}
+
+//-----------------------------------------------------------------------------
+int32_t File::tell()
+{
+	assert(m_file_handle != NULL);
+	
+	return ftell(m_file_handle);
+}
+
+//-----------------------------------------------------------------------------
+int File::eof()
+{
+	assert(m_file_handle != NULL);
+	
+	return feof(m_file_handle);
+}
+
 //-----------------------------------------------------------------------------
 size_t File::size()
 {

+ 10 - 1
src/core/streams/File.h → src/os/linux/File.h

@@ -48,12 +48,21 @@ class File
 
 public:
 
-	virtual				~File();
+						~File();
 
 	bool				is_valid();
 
 	FileOpenMode		mode();
+
 	FILE*				get_handle();
+
+	size_t				read(void* ptr, size_t size, size_t nmemb);
+	size_t				write(const void* ptr, size_t size, size_t nmemb);
+	int					seek(int32_t offset, int whence);
+	int32_t				tell();
+
+	int					eof();
+
 	size_t				size();
 
 	static File*		open(const char* path, FileOpenMode mode);

+ 29 - 4
tests/connections.cpp

@@ -5,12 +5,13 @@
 #include "MallocAllocator.h"
 #include "BitMessage.h"
 #include "AsyncConnection.h"
+#include "PacketQueue.h"
 
 using namespace crown;
 
 const unsigned int server_port = 30000;
 const unsigned int client_port = 30001;
-const unsigned int protocol_id = 0x99887766;
+const uint32_t protocol_id = 0x00;
 const float delta_time = 1.0f / 45.0f;
 const real send_rate = 1.0f / 45.0f;
 
@@ -102,10 +103,21 @@ int main(int argc, char** argv)
 				int32_t bytes = connection.receive_message(received, delta_time);
 				if (bytes > 0)
 				{
+					uint8_t* header = received.get_header();
+					uint32_t protocol_id = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
+					uint16_t sequence = header[4] << 8 | header[5];
+					uint16_t ack = header[6] << 8 | header[7];
+					uint32_t ack_bits = header[8] << 24 | header[9] << 16 | header[10] << 8 | header[11];  
 					char string[6];
 					received.read_string(string, 6);
- 					os::printf("%s\n", string);
-					
+					os::printf("------------------\n");
+					os::printf("protocol_id: %d\n", protocol_id);
+					os::printf("sequence: %d\n", sequence);
+					os::printf("ack: %d\n", ack);
+					os::printf("ack_bits: %d\n", ack_bits);
+ 					os::printf("data: %s\n", string);
+					os::printf("------------------\n");
+
 				} 
 				
 				if (bytes <= 0)
@@ -122,10 +134,23 @@ int main(int argc, char** argv)
 				network::BitMessage message(alloc);
 			
 				message.init(6);
+				message.begin_writing();
 				message.write_string("prova", 6);
 				
 				connection.send_message(message, delta_time);
-				
+
+				uint8_t* header = message.get_header();
+				uint32_t protocol_id = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
+				uint16_t sequence = header[4] << 8 | header[5];
+				uint16_t ack = header[6] << 8 | header[7];
+				uint32_t ack_bits = header[8] << 24 | header[9] << 16 | header[10] << 8 | header[11];
+				os::printf("------------------\n");
+				os::printf("protocol_id: %d\n", protocol_id);
+				os::printf("sequence: %d\n", sequence);
+				os::printf("ack: %d\n", ack);
+				os::printf("ack_bits: %d\n", ack_bits);
+				os::printf("------------------\n");
+
 				send_acc -= 1.0f / send_rate;
 			}
 		}

+ 35 - 3
tests/messages.cpp

@@ -317,7 +317,7 @@ void test_data()
 
 void test_net_address()
 {
-  	uint32_t bits_written;
+	uint32_t bits_written;
 	uint32_t rem_write_bits;
 	uint32_t bits_read;
 	uint32_t rem_read_bits; 
@@ -350,12 +350,12 @@ void test_net_address()
 	printf("bits read = %d\n", bits_read);
 	printf("remaining read bits = %d\n", rem_read_bits);
 	printf("-----------------------------\n");
-	printf("\n");	
+	printf("\n");
 }
 
 int main()
 {
-	
+/*	
 	test_int8();
 	test_uint8();
 	test_int16();
@@ -366,6 +366,38 @@ int main()
 	test_string();
 	test_data();
 	test_net_address();
+*/
+	MallocAllocator allocator;
+	network::BitMessage msg = network::BitMessage(allocator);
+	
+	uint32_t protocol_id = 0xFFFFFFFF;
+	uint16_t sequence = 12345;
+	uint16_t ack	  = 12344;
+	uint32_t ack_bits = 1234543;
+	
+	msg.init(6);
+	msg.set_header(protocol_id, sequence, ack, ack_bits);
+	msg.begin_writing();
+	msg.write_string("prova", 6);
+	
+	msg.begin_reading();
+	uint8_t* header = msg.get_header();
+ 	char data[6];
+ 	msg.read_string(data, 6);
+	
+	uint32_t tmp1 = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
+	uint16_t tmp2 = header[4] << 8 | header[5];
+	uint16_t tmp3 = header[6] << 8 | header[7];
+	uint32_t tmp4 = header[8] << 24 | header[9] << 16 | header[10] << 8 | header[11];
+	
+	os::printf("protocol_id: %d\n", tmp1);
+	os::printf("sequence: %d\n", tmp2);
+	os::printf("ack: %d\n", tmp3);
+	os::printf("ack_bits: %d\n", tmp4);
+ 	os::printf("data: %s\n", data);
+	os::printf("\n");
+
+	
 	
 	return 0;
 }