#standard libraries import struct import string import re import pprint #local libraries import template from data import msg_tmpl from msgtypes import MsgFrequency, MsgTrust, MsgEncoding from msgtypes import MsgDeprecation, MsgBlockType, MsgType, sizeof MESSAGE = 1 BLOCK = 2 DATA = 3 class MessageTemplateParser(object): """a parser which parses the message template and creates MessageTemplate objects which are stored in self.message_templates """ def __init__(self, template_file): if template_file == None: raise exc.MessageTemplateNotFound("initializing template parser") self.template_file = template_file self.message_templates = [] self.version = '' self.count = 0 self.state = 0 self._parse_template_file() def _add_template(self, new_template): self.count += 1 self.message_templates.append(new_template) def _parse_template_file(self): #regular expressions self.template_file.seek(0) lines = self.template_file start_re = '.*\{.*' end_re = '.*\}.*' block_data_re = '.*?(\w+)\s+(\w+)(\s+(\d+))?.*' block_header_re = '.*?(\w+)\s+(\w+)(\s+(\d+))?.*' message_header_re = '.*?(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)(\s+(\w+))?.*' version_re = "version.(.+)" comment_re = "^//.*$" current_template = None current_block = None while True: try: line = lines.next() except StopIteration: break if re.match(comment_re, line): continue start = re.match(start_re, line) end = re.match(end_re, line) if self.version == '': version_test = re.match(version_re, line) #gets packet headers if version_test != None: parts = version_test.group(1) parts = parts.split() self.version = float(parts[0]) if start: self.state += 1 if self.state == MESSAGE: message_header = re.match(message_header_re, line) if message_header != None: current_template = self._start_new_template(message_header) self._add_template(current_template) if self.state == BLOCK: block_header = re.match(block_header_re, line) if block_header != None: current_block = self._start_new_block(block_header) current_template.add_block(current_block) if self.state == DATA: block_data = re.match(block_data_re, line) if block_data != None: current_block.add_variable(self._start_new_var(block_data)) if end: self.state -= 1 def _start_new_template(self, match): new_template = template.MessageTemplate(match.group(1)) frequency = None if match.group(2) == 'Low': frequency = MsgFrequency.LOW_FREQUENCY_MESSAGE elif match.group(2) == 'Medium': frequency = MsgFrequency.MEDIUM_FREQUENCY_MESSAGE elif match.group(2) == 'High': frequency = MsgFrequency.HIGH_FREQUENCY_MESSAGE elif match.group(2) == 'Fixed': frequency = MsgFrequency.FIXED_FREQUENCY_MESSAGE new_template.frequency = frequency msg_num = string.atoi(match.group(3),0) if frequency == MsgFrequency.FIXED_FREQUENCY_MESSAGE: #have to do this because Fixed messages are stored as a long in the template binTemp = struct.pack('>L', string.atol(match.group(3),0)) msg_num_hex = binTemp msg_num = struct.unpack('>h','\x00' + binTemp[3])[0] elif frequency == MsgFrequency.LOW_FREQUENCY_MESSAGE: msg_num_hex = struct.pack('>BBB',0xff,0xff, msg_num) elif frequency == MsgFrequency.MEDIUM_FREQUENCY_MESSAGE: msg_num_hex = struct.pack('>BB',0xff, msg_num) elif frequency == MsgFrequency.HIGH_FREQUENCY_MESSAGE: msg_num_hex = struct.pack('>B', msg_num) new_template.msg_num = msg_num new_template.msg_num_hex = msg_num_hex msg_trust = None if match.group(4) == 'Trusted': msg_trust = MsgTrust.LL_TRUSTED elif match.group(4) == 'NotTrusted': msg_trust = MsgTrust.LL_NOTRUST new_template.msg_trust = msg_trust msg_encoding = None if match.group(5) == 'Unencoded': msg_encoding = MsgEncoding.LL_UNENCODED elif match.group(5) == 'Zerocoded': msg_encoding = MsgEncoding.LL_ZEROCODED new_template.msg_encoding = msg_encoding msg_dep = None if match.group(7) != None: if match.group(7) == 'Deprecated': msg_dep = MsgDeprecation.LL_DEPRECATED elif match.group(7) == 'UDPDeprecated': msg_dep = MsgDeprecation.LL_UDPDEPRECATED elif match.group(7) == 'UDPBlackListed': msg_dep = MsgDeprecation.LL_UDPBLACKLISTED elif match.group(7) == 'NotDeprecated': msg_dep = MsgDeprecation.LL_NOTDEPRECATED else: msg_dep = MsgDeprecation.LL_NOTDEPRECATED if msg_dep == None: print match.groups() new_template.msg_deprecation = msg_dep return new_template def _start_new_block(self, match): new_block = template.MessageTemplateBlock(match.group(1)) block_type = None block_num = 0 if match.group(2) == 'Single': block_type = MsgBlockType.MBT_SINGLE elif match.group(2) == 'Multiple': block_type = MsgBlockType.MBT_MULTIPLE block_num = int(match.group(4)) elif match.group(2) == 'Variable': block_type = MsgBlockType.MBT_VARIABLE #LDE 230ct2008 block_type vs block.type issues... new_block.block_type = block_type new_block.number = block_num return new_block def _start_new_var(self, match): type_string = match.group(2) var_type = None var_size = -1 if type_string == 'U8': var_type = MsgType.MVT_U8 elif type_string == 'U16': var_type = MsgType.MVT_U16 elif type_string == 'U32': var_type = MsgType.MVT_U32 elif type_string == 'U64': var_type = MsgType.MVT_U64 elif type_string == 'S8': var_type = MsgType.MVT_S8 elif type_string == 'S16': var_type = MsgType.MVT_S16 elif type_string == 'S32': var_type = MsgType.MVT_S32 elif type_string == 'S64': var_type = MsgType.MVT_S64 elif type_string == 'F32': var_type = MsgType.MVT_F32 elif type_string == 'F64': var_type = MsgType.MVT_F64 elif type_string == 'LLVector3': var_type = MsgType.MVT_LLVector3 elif type_string == 'LLVector3d': var_type = MsgType.MVT_LLVector3d elif type_string == 'LLVector4': var_type = MsgType.MVT_LLVector4 elif type_string == 'LLQuaternion': var_type = MsgType.MVT_LLQuaternion elif type_string == 'LLUUID': var_type = MsgType.MVT_LLUUID elif type_string == 'BOOL': var_type = MsgType.MVT_BOOL elif type_string == 'IPADDR': var_type = MsgType.MVT_IP_ADDR elif type_string == 'IPPORT': var_type = MsgType.MVT_IP_PORT elif type_string == 'Fixed' or type_string == 'Variable': if type_string == 'Fixed': var_type = MsgType.MVT_FIXED elif type_string == 'Variable': var_type = MsgType.MVT_VARIABLE var_size = int(match.group(4)) if var_size <= 0: raise exc.MessageTemplateParsingError("variable size %s does not match %s" % (var_size, type_string)) #if the size hasn't been read yet, then read it from message_types if var_size == -1: var_size = sizeof(var_type) #LDE 23oct2008 add var+type to creation of MTV object for subsequent formmating goodness return template.MessageTemplateVariable(match.group(1), \ var_type, var_size) def print_packet_names(packet_list): frequency_counter = {"low":0, 'medium':0, "high":0, 'fixed':0} counter = 0 for packet in packet_list: print '=================================================================================' counter += 1 frequency_counter[packet.get_frequency_as_string()]+=1 #if packet.get_frequency_as_string() == "low": print counter, packet.get_name() + ' ' + packet.get_frequency_as_string() print '=================================================================================' print for counters in frequency_counter: print counters, frequency_counter[counters] print def print_packet_list(packet_list): for packet in packet_list: print '=================================================================================' print packet.get_name() + ' ' + packet.get_frequency_as_string() + ' ' + \ str(packet.get_message_number()) + ' ' + packet.get_message_hex_num() + \ ' ' + packet.get_message_trust_as_string() + ' ' + \ packet.get_message_encoding_as_string() + ' ' + packet.get_deprecation_as_string() for block in packet.get_blocks(): print '\t' + str(block.get_name()) + ' ' + block.get_block_type_as_string() + ' ' + \ str(block.get_block_number()) for variable in block.get_variables(): sz = len(variable.get_name()) print '\t\t' + variable.get_name().ljust(20) +"\t" + variable.get_type_as_string() def get_all_types(packet_list): type_set = set([]) for packet in packet_list: for block in packet.get_blocks(): for variable in block.get_variables(): type_set.add(variable.get_type_as_string()) #LDE 23oct2008 display using _as_string call type_list = list(type_set) type_list.sort() return type_list def main(): """tidied up this test which didn't seem to be working for me at first til I made a few changes""" parser = MessageTemplateParser(msg_tmpl) #parser._parse_template_file() #LDE 23oct2008 part of tidying up thing above templates = parser.message_templates print_packet_names(templates) print_packet_list(templates) p_typelist = get_all_types(templates) pprint.pprint(p_typelist) return if __name__ == "__main__": main() """ Contributors can be viewed at: http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt $LicenseInfo:firstyear=2008&license=apachev2$ Copyright 2009, Linden Research, Inc. Licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 or in http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt $/LicenseInfo$ """