def _scan_with_tlvlist(self, hexcode, tagset): bytelets = [] #print "TAGSET", tagset while len(hexcode)>0: (T,L,V), hexcode = self._split(hexcode) #print "T", T #print "L", L if len(V) != L.num(): V = Hex("{ <----------- ERROR: not enough bytes available!}") V.format = Hex.F_ASCII # print "rest", hexcode child = tagset.get(T.num()) if child: btl = Bytelet([child.tag,{},[['Tag',{},[],T],['Len',{},[],L]],'']) if child._children: if child._attrs.get("use") == "std": child_schema = ByteletSchema(child._tree) btl = child_schema._parse_std_schema(T//L//V, True) else: tags = {} for c in child.children(): t = c._attrs["tag"] tags[Hex(t).num()] = c for sub in self._scan_with_tlvlist(V, tags): sub._parent = btl btl._children.append(sub) else: btl = Bytelet([child.tag,{},[['Tag',{},[],T],['Len',{},[],L],['Val',{},[],V]],'']) else: btl = Bytelet(['UNDEF',{},[['Tag',{},[],T],['Len',{},[],L],['Val',{},[],V]],'']) btl._remap() bytelets.append(btl) return bytelets
def hex(self): bitshift = [False] items = [] def _hex(btl): if btl._children == []: if btl._content!='': if isinstance(btl._content, Flow): hx = btl._content.flow_value() else: btl._content hx = Hex(btl._content) width = int(btl._attrs.get("w",0)) if width: if self._check_size(width, hx): bitshift[0] = True else: raise TypeError("Hex object %s does not fit into a %d bit array."%(hx, width)) items.append((hx, width)) else: for child in btl.children(): _hex(child) _hex(self) h = Hex() if not bitshift[0] or len(items)==1: for (item,w) in items: h.bytes.extend(item.bytes) else: #print "TO-HEX", len(items), [type(t[0]) for t in items] offset = 0 for (item,w) in items: offset, h = h.concat(item, offset, w) return h
def _parse_std_schema(self, hexcode, strict): hexoffset = 0 binoffset = 0 if type(hexcode) == Hex: bc = hexcode else: bc = Hex(hexcode) if self.tag.startswith("bl-schema"): tag = "bl:"+self.tag.split(":")[1] else: tag = self.tag matched = Bytelet([tag,{},[],'']) for child in self.children(): if hexoffset>=len(bc): if strict: content = child._tree[-1] if isinstance(content, FlowFieldVal): content.set_node(child, matched) n = content.flow_value().num() if n == 0: continue else: n = child.hex().num() if n == 0: continue raise ByteletError("[01]: Schema too short. Field `%s` of ByteletSchema `%s` does not match any hexcode."%(child.tag, self.tag)) break content = child._tree[-1] if isinstance(content, FlowFieldVal): # print "MATCH FlowFieldVal" content.set_node(child, matched) n = content.flow_value().num() if strict and hexoffset+n>len(bc): raise ByteletError("[02]:Incorrect number of bytes for field `%s`. Expected `%s` bytes but `%s` bytes found."%(child.tag, n, hexoffset+n-len(bc))) (hexoffset, binoffset),v = bc.section(hexoffset, binoffset, n) matched._children.append(Bytelet([child.tag, {}, [], v], matched)) elif isinstance(content, FlowLen): # print "MATCH FlowLen" lgt = bc.byte(hexoffset, binoffset) if lgt & 0x80: lenlen = 1 + (lgt & 0x0F) (hexoffset, binoffset),v = bc.section(hexoffset, binoffset, lenlen.num()) else: v = lgt hexoffset+=1 # print "NEW HEXOFFSET", hexoffset # set new flow len value flen = copy(content) flen.set_flow_value(v) matched._children.append(Bytelet([child.tag, {}, [], flen], matched)) elif len(child._children)>0: # print "MATCH children" if not isinstance(child, ByteletSchema): child_schema = ByteletSchema(child._tree, child._parent) else: child_schema = child mi = child_schema.parse(bc.rest(hexoffset, binoffset), strict) # print "MATCHED", mi matched._children.append(mi) hexoffset+=len(mi) elif isinstance(content, Bin): # print "MATCH bits" n = content.num() #print "REST", bc[hexoffset:] (hexoffset, binoffset),v = bc.section(hexoffset, binoffset, n, bit = True) #print "V",v matched._children.append(Bytelet([child.tag, {"w":n}, [], v], matched)) elif isinstance(content, Hex): # print "MATCH HX exact" n = len(content) (hexoffset, binoffset), section = bc.section(hexoffset,binoffset,n) if strict and section != content: raise ByteletError("[03]:Expected content of field `%s` = `%s`. Received: `%s`."%(child.tag, content, section)) matched._children.append(Bytelet([child.tag, {}, [], content], matched)) else: # print "MATCH bytes" n = Hex(content).num() (hexoffset, binoffset),section = bc.section(hexoffset,binoffset,n) matched._children.append(Bytelet([child.tag, {}, [], section], matched)) if strict: n = hexoffset - len(bc) if n<0 and self._parent is None: n = len(bc) - hexoffset if binoffset: raise ByteletError("[041]: Schema too short. ByteletSchema `%s` did not scan %s bits of hexcode."%(self.tag, 8*n-binoffset)) else: raise ByteletError("[042]: Schema too short. ByteletSchema `%s` did not scan %s bytes of hexcode."%(self.tag,n)) elif n>0 or binoffset: if n>0: raise ByteletError("[051]: Schema too long. ByteletSchema `%s` specified %d bytes that did not match."%(self.tag, n)) else: raise ByteletError("[052]: Schema too long. ByteletSchema `%s` specified %d bits that did not match."%(self.tag, binoffset)) matched._remap() return matched