message system mostly in, just needs to be tested and checked for accuracy

This commit is contained in:
locklainn.linden
2008-08-01 21:02:55 +00:00
committed by Salad Dais
parent e290c1377c
commit 853e96a554
11 changed files with 228 additions and 86 deletions

View File

@@ -5,6 +5,13 @@ class Host(object):
self.ip = ip_addr
self.port = port
def is_ok(self):
if self.ip == None or self.port == None or \
self.ip == 0 or self.port == 0:
return False
return True
def set_host_by_name(self, hostname):
pass
@@ -14,17 +21,17 @@ class Circuit(object):
""" Some statistics things we may need: bytes/packets in, bytes/packets out,
unacked packet count/bytes, acked packet count/bytes"""
def __init__(self, host, circuit_code, remote_session_id):
def __init__(self, host, pack_in_id):
self.host = host
self.circuit_code = circuit_code
self.session_id = remote_session_id
self.circuit_code = 0
self.session_id = 0
self.is_alive = True
self.is_blocked = False
self.allow_timeout = True
self.last_packet_out_id = 0 #id of the packet we last sent
self.last_packet_in_id = 0 #id of the packet we last received
self.last_packet_in_id = pack_in_id
self.acks = [] #packets we need to ack
self.acks = [] #packets we need to ack (ids)
self.unacked_packets = {} #packets we want acked, can be resent
self.unack_packet_count = 0
self.unack_packet_bytes = 0
@@ -44,15 +51,15 @@ class Circuit(object):
(need to send ack out)"""
self.acks.append(packet_id)
def add_reliable_packet(self, sock, message_buffer, buffer_length, **kwds):
def add_reliable_packet(self, sock, message_buffer, buffer_length, params):
""" add a packet that we want to be acked
(want an incoming ack) """
packet = Packet(sock, message_buffer, buffer_length, kwds)
self.unack_packet_count += 1
self.unack_packet_bytes += buffer_length
#if it can be resent/retried (not final) add it to the unack list
if 'retries' in kwds:
if 'retries' in params:
packet.retries = params['retries']
self.unacked_packets[packet.packet_id] = packet
#otherwise, it can't be resent to get acked
else:
@@ -63,7 +70,8 @@ class CircuitManager(object):
functionality to do so. """
def __init__(self):
self.circuit_map = {}
self.unacked_circuits = {}
def get_unacked_circuits(self):
#go through circuits, if it has any unacked packets waiting ack, add
#to a list

View File

@@ -19,6 +19,9 @@ class IMessageBuilder(Interface):
"""base interface for a message builder"""
current_msg = Attribute("""the message built/being built""")
def is_built():
""" returns true if the message has been built """
def build_message():
""" returns the message and its size in serialized form. """

View File

@@ -16,6 +16,10 @@ class LLSDMessageBuilder(object):
self.cur_msg_name = ''
self.cur_block_name = ''
self.has_been_built = False
def is_built(self):
return self.has_been_built
def build_message(self):
""" this does not serialize it for this type of builder. The message
@@ -40,20 +44,24 @@ class LLSDMessageBuilder(object):
#the variable holds the key-value pairs of data
#for the block
block[variable.name] = variable.data
self.has_been_built = True
return msg, len(msg)
def new_message(self, message_name):
self.has_been_built = False
self.current_msg = MsgData(message_name)
self.cur_msg_name = message_name
def next_block(self, block_name):
self.has_been_built = False
block = MsgBlockData(block_name)
self.current_msg.add_block(block)
self.current_block = block
self.cur_block_name = block_name
def add_data(self, var_name, data, data_type):
self.has_been_built = False
var = MsgVariableData(var_name, data_type)
self.current_block.add_variable(var)
#size doesn't matter for llsd, formatter will take care of it

View File

@@ -9,14 +9,21 @@ from pyogp.lib.base.message.message_template_reader import MessageTemplateReader
from pyogp.lib.base.message.message_template_dict import TemplateDictionary
from pyogp.lib.base.message.message_dict import MessageDictionary
from pyogp.lib.base.message.circuitdata import CircuitManager
from pyogp.lib.base.message.message_types import PackFlags, sizeof
from pyogp.lib.base.message.message_types import PacketLayout, PackFlags,\
MsgType, sizeof
from pyogp.lib.base.message.data_unpacker import DataUnpacker
from pyogp.lib.base.message.data_packer import DataPacker
from pyogp.lib.base.message.net import *
class MessageSystem(object):
def __init__(self, port):
#holds the details of the message, or how the messages should be sent,
#built, and read
self.send_buffer = ''
self.send_flags = PackFlags.LL_NONE
self.send_reliable = False
self.reliable_params = {}
self.message_details = None
self.builder = None
self.reader = None
@@ -25,7 +32,7 @@ class MessageSystem(object):
self.socket = None
#the ID of the packet we most recently received
self.receive_packet_id = -1
self.llsd_builder = LLSDMessageBuilder()
#self.llsd_reader = LLSDMessageReader()
@@ -34,8 +41,8 @@ class MessageSystem(object):
self.template_reader = MessageTemplateReader(template_dict)
self.socket = start_udp_connection(self.port)
self.unpacker = DataUnpacker()
self.packer = DataPacker()
def load_template(self, template_file, details_file):
#use the parser to load the message_template.msg message templates
@@ -72,7 +79,7 @@ class MessageSystem(object):
#determine packet flags
flag = ord(msg_buf[0])
self.receive_packet_id = \
self.unpacker.unpack_data(msg_buf[1:1+sizeof(MsgType.U32)], MsgType.U32)
self.unpacker.unpack_data(msg_buf,MsgType.U32, 1)
#determine sender
host = get_sender()
@@ -137,65 +144,153 @@ class MessageSystem(object):
self.template_reader.clear_message()
return valid_packet
def send_reliable(self, host):
def send_reliable(self, host, retries, message_buf=None):
""" Wants to be acked """
#sets up the message so send_message will add the RELIABLE flag to
#the message
pass
self.send_reliable = True
unacked_packet.buffer[PacketLayout.PHL_FLAGS] |= PackFlags.LL_RELIABLE_FLAG
self.reliable_params = {}
self.reliable_params['retries'] = retries
send_message(host)
def send_retry(self, host):
def send_retry(self, host, message_buf=None):
""" This is a retry because we didn't get acked """
#sets up the message so send_message will add the RETRY flag to it
pass
def send_acks(self, host):
""" Acks all packets received that we haven't acked yet. """
#go through the circuit manager, find the circuits that need acks
#and send the acks by building ack messages
#acks are just the packet_id that we are acking
pass
def send_message_circuit(self, circuit):
""" allows someone to send a message only knowing the circuit """
#send_message(map_circuit_to_host(circuit))
pass
unacked_packet.buffer[PacketLayout.PHL_FLAGS] |= PackFlags.LL_RESENT_FLAG
send_message(host, message_buf)
def send_message_llsd(self, host, name, message):
""" sends an llsd message without going through builder """
pass
def send_message(self, host):
def send_message(self, host, message_buf=None):
""" Sends the message that is currently built to the desired host """
#build it if it isn't built
message_size = -1
#make sure host is OK (ip and address aren't null)
if host.is_ok() == False:
return
#build it if it isn't built
if message_buf == None:
if self.builder.is_built() == False:
message_buf, message_size = self.builder.build_message()
else:
message_buf = self.self.builder.current_msg
#IF UDP/template message
#use circuit manager to get the circuit to send on
#if the packet is reliable, add it to the circuit manager's list of
#unacked circuits
#also, tell the circuit it is waiting for an ack for this packet
circuit = self.find_circuit(host)
#also, sends as many acks as we can onto the end of the packet
#acks are just the packet_id that we are acking
pass
ack_count = len(circuit.acks)
if ack_count > 0:
self.send_flags |= PackFlags.LL_ACK_FLAG
for packet_id in circuit.acks:
pack_id = self.packer.pack_data(packet_id, MsgType.MVT_S32)
message_buf += pack_id
append_ack_count = self.packer.pack_data(ack_count, MsgType.MVT_U8)
message_buf += append_ack_count
self.send_buffer = ''
#put the flags in the begining of the data
self.send_buffer += self.packer.pack_data(self.send_flags, MsgType.MVT_U8)
#set packet ID
self.send_buffer += self.packer.pack_data(circuit.next_packet_id(), \
MsgType.MVT_S32)
if self.send_reliable == True:
if circuit.unack_packet_count <= 0:
self.circuit_manager.unacked_circuits[host] = circuit
circuit.add_reliable_packet(self.socket, self.send_buffer, \
len(self.send_buffer), \
self.reliable_params)
#now that the pre-message data is added, add the real data to the end
self.send_buffer += message_buf
#TODO: remove this when testing a network
#send_packet(self.socket, self.send_buffer, host)
self.send_reliable = False
self.reliable_params = {}
def process_acks(self):
""" resends all of our messages that were unacked, and acks all
the messages that others are waiting to be acked. """
#send the ones we didn't get acked
resend_all_unacked()
#send the acks we didn't reply to
send_acks()
pass
def resend_all_unacked(self):
""" Resends all packets sent that haven't yet been acked. """
#now_time = get_time_now()
#go through all circuits in the map
#go through all packets for circuit that are unacked
#resend the packet
pass
for circuit in self.circuit_manager.unacked_circuits.values():
for unacked_packet in circuit.unacked_packets.values():
unacked_packet.retries -= 1
#is this correct? should it be serialized or something?
self.reset_send_buffer()
self.send_buffer += unacked_packet.buffer
send_retry(unacked_packet.host, unacked_packet.retries)
if unacked_packet.retries <= 0:
circuit.final_retry_packets[packet.packet_id] = unacked_packet
del circuit.unacked_packets[unacked_packet.packet_id]
#final retries aren't resent, they are just forgotten about. boo
#for unacked_packet in circuit.final_retry_packets.values():
# if now_time > unacked_packet.expiration_time:
# del circuit.final_retry_packets[unacked_packet.packet_id]
def send_acks(self, host):
""" Acks all packets received that we haven't acked yet. """
for circuit in self.circuit_manager.circuit_map.values():
acks_this_packet = 0
for packet_id in circuit.acks:
if acks_this_packet == 0:
new_message("PacketAck")
next_block("Packets")
add_data("ID", packet_id, MsgType.U32)
acks_this_packet += 1
if acks_this_packet > 250:
send_message(circuit.host)
acks_this_packet = 0
if acks_this_packet > 0:
send_message(circuit.host)
circuit.acks.clear()
#the following methods are for a higher-level api
#new_message is important because it selects the correct builder
def new_message(self, message_name):
if self.message_dict[message_name] == None:
return
flavor = self.message_dict.get_message_flavor(message_name)
if flavor == 'template':
self.builder = self.template_builder
elif flavor == 'llsd':
self.builder = self.llsd_builder
self.send_reliable = False
self.builder.new_message(message_name)
def next_block(self, block_name):
self.builder.next_block(block_name)
def add_data(self, var_name, data, data_type):
self.builder.add_data(var_name, data, data_type)

View File

@@ -24,6 +24,10 @@ class MessageTemplateBuilder(object):
self.cur_block_name = ''
self.packer = DataPacker()
self.has_been_built = False
def is_built(self):
return self.has_been_built
def build_message(self):
""" Builds the message by serializing the data. Creates a packet ready
@@ -54,7 +58,9 @@ class MessageTemplateBuilder(object):
packed_block, block_size = self.build_block(block, self.current_msg)
msg_buffer += packed_block
bytes += block_size
self.has_been_built = True
return msg_buffer, bytes
def build_block(self, template_block, message_data):
@@ -121,6 +127,7 @@ class MessageTemplateBuilder(object):
""" Creates a new packet where data can be added to it. Note, the variables
are added when they are used, or data added to them, so to make sure
no bad data is sent over the network. """
self.has_been_built = False
self.current_template = self.template_list[message_name]
#error check
if self.current_template == None:
@@ -133,6 +140,7 @@ class MessageTemplateBuilder(object):
self.current_msg.add_block(block_data)
def next_block(self, block_name):
self.has_been_built = False
if block_name not in self.current_template.block_map:
#error:
return
@@ -176,6 +184,7 @@ class MessageTemplateBuilder(object):
def add_data(self, var_name, data, data_type):
""" the data type is passed in to make sure that the programmer is aware of
what type (and therefore size) of the data that is being passed in. """
self.has_been_built = False
if self.current_template == None:
raise Exception('Attempting to add data to a null message')

View File

@@ -6,7 +6,7 @@ from pyogp.lib.base.message.message_template import MsgData, MsgBlockData, \
MsgVariableData
#import pyogp.lib.base.message_types
from pyogp.lib.base.message.message_types import MsgType, MsgBlockType, \
MsgFrequency, MsgHeader, sizeof
MsgFrequency, PacketLayout, sizeof
from pyogp.lib.base.message.data_unpacker import DataUnpacker
class MessageTemplateReader(object):
@@ -61,12 +61,12 @@ class MessageTemplateReader(object):
def __decode_template(self, message_buffer, buffer_size):
""" Determines the template that the message in the buffer
appears to be using. """
if MsgHeader.PACKET_ID_LENGTH >= buffer_size:
raise Exception("Reading " + str(MsgHeader.PACKET_ID_LENGTH) + \
if PacketLayout.PACKET_ID_LENGTH >= buffer_size:
raise Exception("Reading " + str(PacketLayout.PACKET_ID_LENGTH) + \
" bytes from a buffer that is only " + \
str(buffer_size) + " bytes long")
header = message_buffer[MsgHeader.PACKET_ID_LENGTH:]
header = message_buffer[PacketLayout.PACKET_ID_LENGTH:]
self.current_template = self.__decode_header(header)
if self.current_template != None:
return True
@@ -82,14 +82,14 @@ class MessageTemplateReader(object):
#at the offset position, the messages stores the offset to where the
#payload begins (may be extra header information)
offset = self.unpacker.unpack_data(data[MsgHeader.PHL_OFFSET:MsgHeader.PHL_OFFSET+1], MsgType.MVT_U8)
offset = self.unpacker.unpack_data(data[PacketLayout.PHL_OFFSET:PacketLayout.PHL_OFFSET+1], MsgType.MVT_U8)
freq_bytes = self.current_template.frequency
#HACK: fixed case
if freq_bytes == -1:
freq_bytes = 4
decode_pos = MsgHeader.PACKET_ID_LENGTH + \
decode_pos = PacketLayout.PACKET_ID_LENGTH + \
freq_bytes + \
offset

View File

@@ -1,9 +1,14 @@
#represents how much of a message is taken up by packet ID things, such as
#the packet flags and the sequence number. After the ID, then comes the header
#NOTE: This will be moved into a messaging system eventually
class MsgHeader(object):
class PacketLayout(object):
PACKET_ID_LENGTH = 6
PHL_FLAGS = 0
PHL_PACKET_ID = 1 #length of 4
PHL_OFFSET = 5
PHL_NAME = 6
#1 byte flags, 4 bytes sequence, 1 byte offset + 1 byte message name (high)
MINIMUM_VALID_PACKET_SIZE = PACKET_ID_LENGTH + 1
class MsgBlockType(object):
MBT_SINGLE, \
@@ -12,11 +17,11 @@ class MsgBlockType(object):
#pack flags
class PackFlags(object):
LL_ZERO_CODE_FLAG = '\x80'
LL_RELIABLE_FLAG = '\x40'
LL_RESENT_FLAG = '\x20'
LL_ACK_FLAG = '\x10'
LL_NONE = '\x00'
LL_ZERO_CODE_FLAG = 0x80
LL_RELIABLE_FLAG = 0x40
LL_RESENT_FLAG = 0x20
LL_ACK_FLAG = 0x10
LL_NONE = 0x00
#frequency for messages
#= '\xFF\xFF\xFF'

View File

@@ -4,10 +4,9 @@ import socket
#maybe put this isnt' a class
#returns true if packet was sent successfully
def send_packet(socket, send_buffer, size, ip_addr, port):
pass
#returns message and size, or None if error
def send_packet(sock, send_buffer, host):
sock.sendto(send_buffer, (host.ip_addr, host.port))
def receive_packet(socket):
buf = 10000
data, addr = socket.recvfrom(buf)
@@ -20,5 +19,3 @@ def start_udp_connection(port):
#will probably be other setup for this
return sock

View File

@@ -1,19 +1,20 @@
from pyogp.lib.base.message.data_unpacker import DataUnpacker
from pyogp.lib.base.message.message_types import MsgHeader, MsgType
from pyogp.lib.base.message.message_types import PacketLayout, MsgType
class Packet(object):
def __init__(self, sock, packet_buffer, buffer_length, **kwds):
self.name = ''
self.socket = sock
self.buffer = packet_buffer
self.buffer_length = buffer_length
self.retries = 0
self.host = None
self.socket = sock
self.buffer = packet_buffer
self.buffer_length = buffer_length
self.retries = 0
self.host = None
self.expiration_time = 0
if kwds != {}:
self.host = kwds['host']
self.retries = kwds['retries']
self.name = kwds['name']
id_buf = packet_buffer[MsgHeader.PACKET_ID_LENGTH:MsgHeader.PACKET_ID_LENGTH+4]
id_buf = packet_buffer[PacketLayout.PACKET_ID_LENGTH:PacketLayout.PACKET_ID_LENGTH+4]
self.packet_id = DataUnpacker().unpack_data(id_buf, MsgType.MVT_U32)

View File

@@ -4,6 +4,8 @@ import pprint
#local libraries
from pyogp.lib.base.message.message_system import MessageSystem
from pyogp.lib.base.message.message_types import MsgType
from pyogp.lib.base.message.circuitdata import Host
class TestMessageSystem(unittest.TestCase):
@@ -16,7 +18,21 @@ class TestMessageSystem(unittest.TestCase):
def test_init(self):
assert self.message_system.message_dict.get_message_flavor('UseCircuitCode') \
== 'template', "Parsing message.xml failed"
def test_send_message1(self):
assert self.message_system.builder == None, "Has builder already"
self.message_system.new_message('PacketAck')
assert self.message_system.builder == \
self.message_system.template_builder, "Builder incorrect"
self.message_system.next_block('Packets')
self.message_system.add_data('ID', 0x00000001, MsgType.MVT_U32)
host = Host(0x101210120, 80)
self.message_system.send_message(host)
print repr(self.message_system.send_buffer)
def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()

View File

@@ -30,7 +30,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x00' +'\x00' + message
message = '\x00' + '\x00\x00\x00\x00' +'\x00' + message
size = len(message)
assert self.reader.validate_message(message, size) == True, \
"Validation failed"
@@ -43,7 +43,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x00' +'\x00' + message
message = '\x00' + '\x00\x00\x00\x00' +'\x00' + message
size = len(message)
self.reader.validate_message(message, size)
assert self.reader.current_template != None, "Validate failed"
@@ -60,7 +60,7 @@ class TestTemplateReader(unittest.TestCase):
def test_validation_fail(self):
self.reader.clear_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00'
message = '\x00' + '\x00\x00\x00\x01' + '\x00'
message += '\xff\xff\x01\xC2'
assert self.reader.validate_message(message, len(message)) == False, \
"Validation passed with incorrect message"
@@ -79,7 +79,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), "Validation failed for test_read"
assert self.reader.read_message(message), "Read failed"
@@ -92,7 +92,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
try:
self.reader.read_message(message)
@@ -102,7 +102,7 @@ class TestTemplateReader(unittest.TestCase):
def test_read_no_validate(self):
self.reader.clear_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + 'Sweetmessage'
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + 'Sweetmessage'
try:
assert self.reader.receive_size == -1, "Receive size incorrect"
@@ -128,7 +128,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
self.reader.validate_message(message, size)
self.reader.read_message(message)
@@ -144,7 +144,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('Packets')
self.builder.add_data('ID', 0x00000001, MsgType.MVT_U32)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), \
@@ -180,7 +180,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
self.builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), "Multiple invalid"
assert self.reader.read_message(message), "Multiple read fail"
@@ -235,7 +235,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.add_data('EstateID', 0x00000001, MsgType.MVT_U32)
self.builder.add_data('SimAccess', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), "Variable invalid"
assert self.reader.read_message(message), "Variable read fail"
@@ -256,7 +256,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.add_data('SimAccess', 0x01, MsgType.MVT_U8)
self.builder.add_data('TeleportFlags', 0x00000001, MsgType.MVT_U32)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), "Variable invalid"
assert self.reader.read_message(message), "Variable read fail"
@@ -272,7 +272,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.add_data('AgentID', UUID("550e8400-e29b-41d4-a716-446655440000"), MsgType.MVT_LLUUID)
self.builder.add_data('SessionID', UUID("550e8400-e29b-41d4-a716-446655440000"), MsgType.MVT_LLUUID)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
assert self.reader.validate_message(message, size), "Variable invalid"
@@ -284,7 +284,7 @@ class TestTemplateReader(unittest.TestCase):
self.builder.next_block('PingID')
self.builder.add_data('PingID', 0x01, MsgType.MVT_U8)
message, size = self.builder.build_message()
message = PackFlags.LL_NONE + '\x00\x00\x00\x01' + '\x00' + message
message = '\x00' + '\x00\x00\x00\x01' + '\x00' + message
size = len(message)
self.reader.validate_message(message, size)
self.reader.read_message(message)