lots of work on the builder. serializer for message template data is in, building messages is in, now testing it all to make sure it works

This commit is contained in:
locklainn.linden
2008-07-23 18:06:26 +00:00
committed by Salad Dais
parent b56d100787
commit 81b556d67d
3 changed files with 166 additions and 87 deletions

View File

@@ -47,7 +47,8 @@ class MsgData():
self.blocks = {}
def add_block(self, block):
self.blocks[block.get_name()] = block
self.blocks[block.get_name()] = []
self.blocks[block.get_name()].append(block)
def get_blocks(self):
return self.blocks
@@ -64,7 +65,7 @@ class MsgBlockData():
serialized and sent. """
def __init__(self, name):
self.name = name
self.total_size = 0
self.size = 0
self.variables = {}
def get_name(self):
@@ -87,7 +88,10 @@ class MsgVariableData():
serialized and sent """
def __init__(self, name, tp):
self.name = name
self.total_size = 0
#data_size holds info whether or not the variable is of type
#MVT_VARIABLE
self.data_size = 0
self.size = -1
self.lltype = tp
self.data = None
@@ -101,7 +105,7 @@ class MsgVariableData():
def get_data(self):
return self.data
def get_total_size(self):
def get_size(self):
return self.total_size
def get_type(self):

View File

@@ -1,6 +1,12 @@
#standard libs
import struct
#pyogp libs
from pyogp.lib.base.message_template import MsgData, MsgBlockData, \
MsgVariableData
from pyogp.lib.base.message_types import MsgType
import pyogp.lib.base.message_types
#from pyogp.lib.base.message_types import MsgType, MsgBlockType, MsgFrequency
from pyogp.lib.base.data_packer import DataPacker
class MessageTemplateBuilder():
""" This class builds messages at its high level, that is, keeping
@@ -17,6 +23,8 @@ class MessageTemplateBuilder():
self.cur_msg_name = ''
self.cur_block_name = ''
self.packer = DataPacker()
def get_current_message(self):
return self.current_msg
@@ -31,13 +39,86 @@ class MessageTemplateBuilder():
#and the blocks variables
#serializer should adapt the interface of MsgData (whatever it is),
#and implement ISerializer
pass
def build_block(self):
pass
def build_variable(self):
pass
#doesn't build in the header flags, sequence number, or data offset
msg_buffer = ''
bytes = 0
if self.current_template == None:
#error
return None
#don't need to pack the frequency and message number. The template
#stores it because it doesn't change per template.
pack_freq_num = self.current_template.get_message_hex_num()
msg_buffer += pack_freq_num
bytes += len(pack_freq_num)
#add some offset?
for block in self.current_template:
packed_block, block_size = build_block(block, self.current_msg)
msg_buffer += packed_block
bytes += block_size
return msg_buffer, bytes
def build_block(self, template_block, message_data):
block_buffer = ''
bytes = 0
block_list = message_data.get_block(template_block.get_name())
block_count = len(block_list)
message_block = block_list[0]
#multiple block type means there is a static number of these blocks
#that make up this message, with the number stored in the template
#don't need to add it to the buffer, because the message handlers that
#receieve this know how many to read automatically
if template_block.get_type() == MsgBlockType.MBT_MULTIPLE:
if template_block.get_block_number() != message_block.get_block_number():
raise Exception('Block ' + template_block.get_name() + ' is type MBT_MULTIPLE \
but only has data stored for ' + str(block_count) + ' out of its ' + \
template_block.get_block_number() + ' blocks')
#variable means the block variables can repeat, so we have to
#mark how many blocks there are of this type that repeat, stored in
#the data
if template_block.get_type() == MsgBlockType.MBT_VARIABLE:
block_buffer += struct.pack('>B', message_block.get_block_number())
bytes += 1
for block in block_list:
for variable in message_block.get_variables():
var_size = variable.get_size()
if var_size == -1:
raise Exception('Variable ' + variable.get_name() + ' in block ' + \
message_block.get_name() + ' of message ' + message_data.get_name() + \
' wasn"t set prior to buildMessage call')
data_size = variable.get_data_size()
#variable's data_size represents whether or not it is of the type
#MVT_VARIABLE. If it is positive, it is
if data_size > 0:
if data_size == 1:
block_buffer += struct.pack('>B', var_size)
elif data_size == 2:
block_buffer += struct.pack('>H', var_size)
elif data_size == 4:
block_buffer += struct.pack('>I', var_size)
else:
raise Exception('Attempting to build variable with unknown size \
of ' + str(var_size))
bytes += data_size
#make sure there IS data to pack
if variable.get_data() != None and var_size > 0:
data = self.packer.pack_data(variable.get_data())
block_buffer += data
bytes += len(data)
def new_message(self, message_name):
""" Creates a new packet where data can be added to it. Note, the variables
@@ -55,7 +136,8 @@ class MessageTemplateBuilder():
def next_block(self, block_name):
self.current_block = self.current_template.get_block(block_name)
#error check
#if it doesn't exist, create a new block (may be a VARIABLE or MULTIPLE type
#block
self.cur_block_name = block_name
@@ -63,34 +145,17 @@ class MessageTemplateBuilder():
var_data = MsgVariableData(variable.get_name(), variable.get_type())
self.current_block.add_variable(var_data)
def add_data(self, var_name, data, data_size):
self.check_size(var_name, data_size)
self.current_block.add_data(var_name, data, data_size)
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.__check_size(var_name, data_type)
self.current_block.add_data(var_name, data, data_type)
def check_size(self, var_name, data, data_size):
def __check_size(self, var_name, data, data_type):
block = self.template_list[cur_msg_name].get_block(self.cur_block_name)
data_size = MsgType.sizeof(data_type)
size = block.get_variable(var_name).get_size()
if size != data_size:
#warning
#for now, exception
raise Exception('Variable size isn"t the same as the variable size')
def add_bool(self, var_name, bool_data):
self.add_data(var_name, bool_data, MsgType.sizeof(MsgType.MVT_BOOL))
"""class IMessageSerializer():
implements ISerializer
adapts MessageData
#goes through MessageData and builds a byte string that can be sent over
#UDP or tcp
serialize (pack_message, build_message)
#goes through each block of the message data
pack_block
#goes through each block of the message variables, creating a byte-code
#string to return
pack_variable"""

View File

@@ -4,19 +4,29 @@ class MsgBlockType():
MBT_VARIABLE = range(3)
#pack flags
#= '\x80'
#= '\x80'
#= '\x40'
#= '\x20'
#= '\x10'
#= '\x00'
class PackFlags():
LL_ZERO_CODE_FLAG = '\x80'
LL_RELIABLE_FLAG = '\x40'
LL_RESENT_FLAG = '\x20'
LL_ACK_FLAG = '\x10'
LL_NONE = '\x00'
LL_ZERO_CODE_FLAG, \
LL_RELIABLE_FLAG, \
LL_RESENT_FLAG, \
LL_ACK_FLAG, \
LL_NONE = range(5)
#frequency for messages
#= '\xFF\xFF\xFF'
#= '\xFF\xFF'
#= '\xFF'
#= ''
class MsgFrequency():
FIXED_FREQUENCY_MESSAGE = '\xFF\xFF\xFF'
LOW_FREQUENCY_MESSAGE = '\xFF\xFF'
MEDIUM_FREQUENCY_MESSAGE = '\xFF'
HIGH_FREQUENCY_MESSAGE = ''
FIXED_FREQUENCY_MESSAGE, \
LOW_FREQUENCY_MESSAGE, \
MEDIUM_FREQUENCY_MESSAGE, \
HIGH_FREQUENCY_MESSAGE = range(4)
class MsgTrust():
LL_TRUSTED, \
@@ -61,45 +71,45 @@ class MsgType():
MVT_IP_ADDR, \
MVT_IP_PORT = range(20)
#TODO should this be changed? Less switch-style and more object-style?
def sizeof(var):
if var == MsgType.MVT_FIXED:
return -1
elif var == MsgType.MVT_VARIABLE:
return -1
elif var == MsgType.MVT_U8:
return 1
elif var == MsgType.MVT_U16:
return 2
elif var == MsgType.MVT_U32:
return 4
elif var == MsgType.MVT_U64:
return 8
elif var == MsgType.MVT_S8:
return 1
elif var == MsgType.MVT_S16:
return 2
elif var == MsgType.MVT_S32:
return 4
elif var == MsgType.MVT_S64:
return 8
elif var == MsgType.MVT_F32:
return 4
elif var == MsgType.MVT_F64:
return 8
elif var == MsgType.MVT_LLVector3:
return 12
elif var == MsgType.MVT_LLVector3d:
return 24
elif var == MsgType.MVT_LLVector4:
return 16
elif var == MsgType.MVT_LLQuaternion:
return 12
elif var == MsgType.MVT_LLUUID:
return 16
elif var == MsgType.MVT_BOOL:
return 1
elif var == MsgType.MVT_IP_ADDR:
return 4
elif var == MsgType.MVT_IP_PORT:
return 2
#TODO should this be changed? Less switch-style and more object-style?
def sizeof(var):
if var == MsgType.MVT_FIXED:
return -1
elif var == MsgType.MVT_VARIABLE:
return -1
elif var == MsgType.MVT_U8:
return 1
elif var == MsgType.MVT_U16:
return 2
elif var == MsgType.MVT_U32:
return 4
elif var == MsgType.MVT_U64:
return 8
elif var == MsgType.MVT_S8:
return 1
elif var == MsgType.MVT_S16:
return 2
elif var == MsgType.MVT_S32:
return 4
elif var == MsgType.MVT_S64:
return 8
elif var == MsgType.MVT_F32:
return 4
elif var == MsgType.MVT_F64:
return 8
elif var == MsgType.MVT_LLVector3:
return 12
elif var == MsgType.MVT_LLVector3d:
return 24
elif var == MsgType.MVT_LLVector4:
return 16
elif var == MsgType.MVT_LLQuaternion:
return 12
elif var == MsgType.MVT_LLUUID:
return 16
elif var == MsgType.MVT_BOOL:
return 1
elif var == MsgType.MVT_IP_ADDR:
return 4
elif var == MsgType.MVT_IP_PORT:
return 2