def from_bytes(cls, bitstream): ''' +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | /| Priority | Weight | M Priority | M Weight | | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | o | Unused Flags |L|p|R| Loc-AFI | | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | \| Locator | +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ''' record = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the priorities and weights (record.priority, record.weight, record.m_priority, record.m_weight) = bitstream.readlist('4*uint:8') # Read over unused flags record.reserved = bitstream.read(13) # Read the flags (record.local, record.probed_locator, record.reachable) = bitstream.readlist('3*bool') # Read the locator record.address = read_afi_address_from_bitstream(bitstream) return record
def mc_parser(): out, buff = yield while True: header_bytes = yield from buff.read(24) header = ConstBitStream(header_bytes) readlist_fmt = 'uint:8, uint:8, uint:16' magic, opcode, key_length = header.readlist(readlist_fmt) extras_length, data_type, status = header.readlist(readlist_fmt) total_body_length = header.read('uint:32') opaque = header.read('uint:32') cas = header.read('uint:64') extras = None if extras_length: extras = yield from buff.read(extras_length) key = None if key_length: key = yield from buff.read(key_length) value_length = total_body_length - (key_length + extras_length) value = None if value_length: value = yield from buff.read(value_length) out.feed_data(MCResponse(opcode, data_type, status, cas, extras, key, value))
def testReadList(self): s = CBS('0b10001111001') t = s.readlist('pad:1, uint:3, pad:4, uint:3') self.assertEqual(t, [0, 1]) s.pos = 0 t = s.readlist('pad:1, pad:5') self.assertEqual(t, []) self.assertEqual(s.pos, 6) s.pos = 0 t = s.readlist('pad:1, bin, pad:4, uint:3') self.assertEqual(t, ['000', 1]) s.pos = 0 t = s.readlist('pad, bin:3, pad:4, uint:3') self.assertEqual(t, ['000', 1])
def testReadList(self): s = CBS("0b10001111001") t = s.readlist("pad:1, uint:3, pad:4, uint:3") self.assertEqual(t, [0, 1]) s.pos = 0 t = s.readlist("pad:1, pad:5") self.assertEqual(t, []) self.assertEqual(s.pos, 6) s.pos = 0 t = s.readlist("pad:1, bin, pad:4, uint:3") self.assertEqual(t, ["000", 1]) s.pos = 0 t = s.readlist("pad, bin:3, pad:4, uint:3") self.assertEqual(t, ["000", 1])
def decode(byte_string): data = ConstBitStream(bytes=byte_string) packet_type = data[_PACKET_TYPE_OFFSET:_PACKET_TYPE_OFFSET + _PACKET_TYPE_SIZE].read(_PACKET_TYPE_SPEC) read_spec = _READ_SPECS[packet_type] values = data.readlist(read_spec['format']) return read_spec['name'], dict(zip(read_spec['fields'], values))
def find_fpt(data_bits: bitstring.ConstBitStream, begin_at_offset_in_bytes: int = 0): """ Scan the bitstream looking for a Magic Number (see code below) that identifies a File Table. Return the position of the file table (needed for further descent into the file structures) and some other info (versions and number of entries) :param data_bits: a BitStream object representing the input (generally constructed from the input specified to the decoder, like a file. e.g. look at the function 'find_fpt_in_opened_file' :param begin_at_offset_in_bytes: from where in the input the BitStream was constructed. This is NOT necessary for correct operation; it is a convenience so that the return value will already have computed the location relative to the start of the input file (but if the caller wishes, it can do this addition/offsetting itself, and just leave the default 0 value for the parameter) :return: a list of values: [0] = the location in the bitstream where the Magic Number for the File Table was found (* the exact meaning of the "location" depends on begin_at_offset_in_bytes and the bitstream that was passed in; see above) [1] = the number of entries (code partition directories) in this file [2] = the header version; this varies from CSME version to version [3] = the version of the code p. directories. Again, this varies... """ f = data_bits.find('0x24465054', bytealigned=True ) # look for the string '$FPT' (expressed in hex, here) if f: # grab the number of entries, the header version and entry version, to return (this helps the human interpreting # the result in figuring out if this is a valid FPT) fpt_tag, num_entries, header_version, entry_version = data_bits.readlist( 'hex:32, uintle:32, uint:8, uint:8') return [ begin_at_offset_in_bytes + int(f[0] / 8), num_entries, header_version, entry_version ] return None
def parseAxisBlock(axBlkStr): ret = dict() if len(axBlkStr) != AX_BLK_SIZE: raise ValueError("Invalid passed string length") keys = [ "status", "switches", "stopCode", "refPos", "motorPos", "posError", "auxPos", "vel", "torque", "analog" ] statusKeys = [ "moving", "motionMode1", "motionMode1", "findingEdge", "homing", "homeP1Done", "homeP2Done", "coordMotion", "movingNeg", "contourMode", "slewingMode", "stopping", "finalDecel", "latchArmed", "offOnErrArmed", "motorOff" ] # The f*****g galil is little endian, so [:2] splits off the segment of the string we want, and [::-1] reverses it statusBs = ConstBitStream(bytes=axBlkStr[:2][::-1]) # Status is 16 boolean values packed into a uint_16 statusVals = statusBs.readlist(["uint:1"] * 16) # zip flags and names into dict zipped = zip(statusKeys, statusVals) vals = [dict(zipped)] vals.extend(struct.unpack(AX_BLK_PARSE_STR, axBlkStr)) ret = dict(zip(keys, vals)) return ret
def _parse_packet(data: ConstBitStream) -> Packet: version, type = data.readlist("3, 3") PacketClass = _get_packet_class(type) packet = PacketClass(version, type) packet.consume(data) return packet
def _get_translation_tables(): raw = ConstBitStream(filename='text_eng.dat', offset=0x8 * 8) tables = [] try: while True: table_len = raw.read('intle:32') table = {} for _ in range(table_len): parsed_id, str_len = raw.readlist('intle:32, intle:32') parsed_str = raw.read('hex:{}'.format(str_len * 8))[:-4].decode('hex') # Replace random unicode shit with closest ASCII equivalent parsed_str = parsed_str.replace( '\xe2\x80\x93', '-') # U-2013 EN-DASH to ASCII dash table[parsed_id] = parsed_str.decode('ascii', 'ignore') tables.append(table) except ReadError: # EOF pass return tables
def check_file(file_path, byte_array): s = ConstBitStream(filename=file_path) found = s.find(byte_array, bytealigned=True) if found: print("File: %s" % file_path) print("Found start code at byte offset %d." % found[0]) s0f0, length, bitdepth, height, width = s.readlist('hex:16, uint:16, uint:8, 2*uint:16') print("Width %d, Height %d\n" % (width, height))
def from_bytes(cls, bitstream): """ Parse the given record and update properties accordingly """ record = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the record TTL record.ttl = bitstream.read("uint:32") # Store the locator record count until we need it referral_count = bitstream.read("uint:8") # Store the EID prefix mask length until we need it eid_prefix_len = bitstream.read("uint:8") # Read the Negative Map_Reply action record.action = bitstream.read("uint:3") # Read the flags (record.authoritative, record.incomplete) = bitstream.readlist("2*bool") # Read reserved bits record._reserved1 = bitstream.read(11) # Read the signature count sig_count = bitstream.read("uint:4") # Read the map version record.map_version = bitstream.read("uint:12") # Read the EID prefix record.eid_prefix = read_afi_address_from_bitstream(bitstream, eid_prefix_len) # Read the locator records for dummy in range(referral_count): locator_record = LocatorRecord.from_bytes(bitstream) record.locator_records.append(locator_record) # TODO: Can't handle signatures yet! [LISP-Security] if sig_count: raise NotImplementedError("Cannot handle signatures yet") # Verify that the properties make sense record.sanitize() return record
def checkValideDir(self, inodeTotalNumber, fsimg, offset, size): validDir = 0 minixfs = open(fsimg) minixfs.seek(offset) raw_table = minixfs.read(size) for i in range(inodeTotalNumber): raw_table.seek(i) s = ConstBitStream(raw_table.read(1)) type = s.readlist('uintle:4') if type == 4: validDir += 1 return validDir
def from_bytes(cls, bitstream): ''' Parse the given packet and update properties accordingly ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read the flags (packet.probe, packet.enlra_enabled, packet.security) = bitstream.readlist('3*bool') # Skip reserved bits packet._reserved1 = bitstream.read(17) # Store the record count until we need it record_count = bitstream.read('uint:8') # Read the nonce packet.nonce = bitstream.read('bytes:8') # Read the records for dummy in range(record_count): record = MapReplyRecord.from_bytes(bitstream) packet.records.append(record) # If the security flag is set then there should be security data left # TODO: deal with security flag [LISP-Security] if packet.security: raise NotImplementedError('Handling security data is not ' + 'implemented yet') # Verify that the properties make sense packet.sanitize() return packet
def parse_one_command_from_buffer(self): retry = True # until we have one or don't have enough errors = [] cmd = None message_type = None bits_parsed = 0 while retry and len(self.buffer) > 0: try: s = ConstBitStream(bytes=self.buffer) cmd_length, message_type = self.parse_serial_interface_header( s) if message_type == MessageType.REBOOTED.value: cmd = s.read("uint:8") elif message_type == MessageType.LOGGING.value: cmd = (s.readlist('bytes:b', b=cmd_length)[0]) else: if self.skip_alp_parsing: if s.length < cmd_length: raise ReadError cmd = s.read("bytes:" + str(cmd_length)) else: cmd = AlpParser().parse(s, cmd_length) bits_parsed = s.pos self.shift_buffer(bits_parsed / 8) retry = False # got one, carry on except ReadError: # not enough to read, carry on and wait for more retry = False except Exception as e: # actual problem with current buffer, need to skip errors.append({ "error": e.args[0], "buffer": " ".join(map(lambda b: format(b, "02x"), self.buffer)), "pos": s.pos, "skipped": self.skip_bad_buffer_content() }) info = { "parsed": bits_parsed, "buffer": len(self.buffer) * 8, "errors": errors } return (message_type, cmd, info)
def from_bytes(cls, bitstream): ''' Parse the given packet and update properties accordingly ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the source and destination ports (packet.source_port, packet.destination_port) = bitstream.readlist('2*uint:16') # Store the length length = bitstream.read('uint:16') if length < 8: raise ValueError('Invalid UDP length') # Read the checksum packet.checksum = bitstream.read('uint:16') # And the rest is payload payload_bytes = length - 8 packet.payload = bitstream.read('bytes:%d' % payload_bytes) # LISP-specific handling if packet.source_port == 4341 or packet.destination_port == 4341: # Payload is a LISP data packet from pylisp.packet.lisp.data import DataPacket packet.payload = DataPacket.from_bytes(packet.payload) elif packet.source_port == 4342 or packet.destination_port == 4342: # Payload is a LISP control message from pylisp.packet.lisp.control.base import ControlMessage packet.payload = ControlMessage.from_bytes(packet.payload) # There should be no remaining bits if bitstream.pos != bitstream.len: raise ValueError('Bits remaining after processing packet') # Verify that the properties make sense packet.sanitize() return packet
def process_tm_packet(binary_packet): bits = ConstBitStream(binary_packet) header = { k: v for k, v in zip(tm_header.keys(), bits.readlist(tm_header.values())) } if header['service_type'] in [3, 21 ] and header['service_subtype'] in [25, 6]: try: ssid = bits.peek('uint:8') header['ssid'] = ssid except ReadError as e: header['ssid'] = -1 if header['data_len'] + 7 != len(bits.hex) / 2: raise ValueError('Expected and actual packet lentght do not match') return header, bits.hex
def _get_translation_tables(): raw = ConstBitStream(filename='bestiary/com2us_data/text_eng.dat', offset=0x8 * 8) tables = [] try: while True: table_len = raw.read('intle:32') table = {} for _ in range(table_len): parsed_id, str_len = raw.readlist('intle:32, intle:32') parsed_str = binascii.a2b_hex(raw.read('hex:{}'.format(str_len * 8))[:-4]) table[parsed_id] = parsed_str.decode("utf-8") tables.append(table) except ReadError: # EOF pass return tables
def extractXMP(self, filename): xmpStr = "" # Can initialise from files, bytes, etc. try: s = ConstBitStream(filename = filename) # Search for ":xmpmeta" string in file keepSearching = True while keepSearching: keepSearching = False colonXmpmetaInHexStr = '0x3a786d706d657461' foundSt = s.find(colonXmpmetaInHexStr, bytealigned=True) if foundSt: byteStart = (int(foundSt[0])//8) # The start of data can be "<xmp:xmpmeta" or "<x:xmpmeta" s.bytepos = byteStart - 4 prevals = s.peeklist("4*uint:8") prestr = ''.join(chr(i) for i in prevals) # print (prestr, prestr[2:]) if prestr == "<xmp": byteStart = byteStart - 4 prefix = "0x3c2f786d70" # "<\xmp" in hex elif prestr[2:] == "<x": byteStart = byteStart - 2 prefix = "0x3c2f78" # "<\x" in hex else: # print ("Cont") keepSearching = True continue # print("Found start code at byte offset %d." % byteStart) foundEnd = s.find(prefix + colonXmpmetaInHexStr, bytealigned=True) if foundEnd: byteEnd = (int(foundEnd[0])//8) s.bytepos = byteStart # print("Found end code at byte offset %d." % byteEnd) xmpBytes = s.readlist(str(byteEnd-byteStart+len(prefix)//2+9) +"*uint:8") xmpStr = ''.join(chr(i) for i in xmpBytes) #if "Rating" in xmpStr: # print (xmpStr) except: xmpStr = "" return xmpStr
def _get_localvalue_tables(table_id): tables = {} decrypted_localvalue = _decrypt_localvalue_dat() raw = ConstBitStream(decrypted_localvalue) raw.read('pad:{}'.format(0x24 * 8)) num_tables = raw.read('intle:32') - 1 raw.read('pad:{}'.format(0xc * 8)) if num_tables > int(max(LocalvalueTables)): print( 'WARNING! Found {} tables in localvalue.dat. There are only {} tables defined!' .format(num_tables, int(max(LocalvalueTables)))) # Read the locations of all defined tables for x in range(0, num_tables): table_num, start, end = raw.readlist(['intle:32'] * 3) tables[table_num] = {'start': start, 'end': end} # Record where we are now, as that is the offset of where the first table starts table_start_offset = int(raw.pos / 8) # Load the requested table and return it raw = ConstBitStream(decrypted_localvalue) table_data = {'header': [], 'rows': []} raw.read('pad:{}'.format( (table_start_offset + tables[table_id]['start']) * 8)) table_str = raw.read( 'bytes:{}'.format(tables[table_id]['end'] - tables[table_id]['start'])).decode('utf-8').strip() table_rows = table_str.split('\r\n') table_data['header'] = table_rows[0].split('\t') table_data['rows'] = [{ table_data['header'][col]: value for col, value in enumerate(row.split('\t')) } for row in table_rows[1:]] return table_data
def from_bytes(cls, bitstream, prefix_len=None): ''' Look at the type of the message, instantiate the correct class and let it parse the message. ''' # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Skip the reserved bits rsvd1 = bitstream.read(8) # Read the flags (and ignore them, no flags are defined yet) flags = bitstream.readlist('8*bool') # Read the type type_nr = bitstream.read('uint:8') # Skip the reserved bits rsvd2 = bitstream.read(8) # Read the length length = bitstream.read('uint:16') # Read the data data = bitstream.read(length * 8) # Look for the right class from pylisp.utils.lcaf import type_registry type_class = type_registry.get_type_class(type_nr) if not type_class: raise ValueError("Can't handle LCAF type {0}".format(type_nr)) # Let the specific class handle it from now on return type_class._from_data_bytes(data, prefix_len, rsvd1, flags, rsvd2)
def from_bytes(cls, bitstream): r''' Parse the given packet and update properties accordingly >>> data_hex = ('80000000' ... '6e000000004811402a0086400001ffff' ... '000000000000000a2a02000000000000' ... '0000000000000000' ... '10f610f600487396' ... '10000201ee924adef97a97d700000001' ... '57c3c44d00015f61535d0002200109e0' ... '85000b000000000000000001000f0002' ... '2a020000000000000000000000000000') >>> data = data_hex.decode('hex') >>> message = EncapsulatedControlMessage.from_bytes(data) >>> message.security False >>> message.ddt_originated False >>> bytes(message.payload) ... # doctest: +ELLIPSIS 'n\x00\x00\x00\x00H\x11...\x00\x00' ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read the flags (packet.security, packet.ddt_originated) = bitstream.readlist('2*bool') # Read reserved bits packet._reserved1 = bitstream.read(26) # If the security flag is set then there should be security data here # TODO: deal with security flag [LISP-Security] if packet.security: raise NotImplementedError('Handling security data is not ' + 'implemented yet') # The rest of the packet is payload remaining = bitstream[bitstream.pos:] # Parse IP packet if len(remaining): ip_version = remaining.peek('uint:4') if ip_version == 4: packet.payload = IPv4Packet.from_bytes(remaining) elif ip_version == 6: packet.payload = IPv6Packet.from_bytes(remaining) else: packet.payload = remaining.bytes # Verify that the properties make sense packet.sanitize() return packet
from bitstring import ConstBitStream ## 494 is length (247 normal for parsing) spat_data = 'cd100100dc02aa0000000000000000020000007d00dc02aa000000000300dc01db000000000000000004003f00bc003f00bc0000000005003f02d400000000000000000600000093003f02d40000000007003f00d2000000000000000008003f01a1003f01a100000000090000000000000000000000000a0000000000000000000000000b0000000000000000000000000c0000000000000000000000000d0000000000000000000000000e0000000000000000000000000f0000000000000000000000001000000000000000000000000000dd0000002200ff00000000000000000000000000000000085d003eca03ce00000000' stream = ConstBitStream(bytes.fromhex(spat_data)) pre = stream.read('hex:8') #'CD' DynObj13 response byte (0xcd) block = stream.read('int:8') #The number of blocks of phase/overlap below 16. phases = [] for i in range(block): outP = stream.read('int:8') #2 outVMin, outVMax = stream.readlist('int:16, 16') #3,4 5,6 outPMin, outPMax = stream.readlist('int:16, 16') #7, 8 9, 10 outOMin, outOMax = stream.readlist( 'int:16, 16') #11, 12 Overlap min #13, 14 Overlap Max phase = { "phase": outP, "color": 'RED', "flash": False, "vehTimeMin": outVMin, "vehTimeMax": outVMax, "pedTimeMin": outPMin, "pedTimeMax": outPMax, } phases.append(phase) # bytes 210-215: PhaseStatusReds, Yellows, Greens (2 bytes bit-mapped for phases 1-16) outR, outY, outG = stream.readlist('bin:16, 16, 16') # # bytes 216-221: PhaseStatusDontWalks, PhaseStatusPedClears, PhaseStatusWalks (2 bytes bit-mapped for phases 1-16) outDW, outPC, outW = stream.readlist('bin:16, 16, 16')
def from_bytes(cls, bitstream, decode_payload=True): ''' Parse the given packet and update properties accordingly ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the version version = bitstream.read('uint:4') if version != packet.version: raise ValueError('Provided bytes do not contain an IPv4 packet') # Read the header length ihl = bitstream.read('uint:4') if ihl < 5: raise ValueError('Invalid IPv4 header length') # Now that we know the length of the header we store it to be able # to easily recalculate the header checksum later remaining_header_bits = (ihl * 32) - 8 header = (BitStream('uint:4=4, uint:4=%d' % ihl) + bitstream.peek(remaining_header_bits)) # Read the type of service packet.tos = bitstream.read('uint:8') # Read the total length total_length = bitstream.read('uint:16') if total_length < ihl * 4: raise ValueError('Total length is shorter than the header') # Read the identification packet.identification = bitstream.read('uint:16') # Read the flags (reserved, packet.dont_fragment, packet.more_fragments) = bitstream.readlist('3*bool') if reserved: raise ValueError('Reserved flag must be 0') # Read the fragment offset packet.fragment_offset = bitstream.read('uint:13') # Read the TTL packet.ttl = bitstream.read('uint:8') # Read the protocol number packet.protocol = bitstream.read('uint:8') # Read the header checksum header_checksum = bitstream.read('uint:16') # Set the checksum bits in the header to 0 and re-calculate header[80:96] = BitStream(16) my_checksum = checksum.ones_complement(header.bytes) if my_checksum != header_checksum: raise ValueError('Header checksum does not match') # Read the source and destination addresses packet.source = IPv4Address(bitstream.read('uint:32')) packet.destination = IPv4Address(bitstream.read('uint:32')) # Read the options option_len = (ihl - 5) * 4 packet.options = bitstream.read('bytes:%d' % option_len) # And the rest is payload payload_bytes = (total_length) - (ihl * 4) packet.payload = bitstream.read('bytes:%d' % payload_bytes) if decode_payload: payload_class = protocol_registry.get_type_class(packet.protocol) if payload_class: packet.payload = payload_class.from_bytes(packet.payload) # There should be no remaining bits if bitstream.pos != bitstream.len: raise ValueError('Bits remaining after processing packet') # Verify that the properties make sense packet.sanitize() return packet
def from_bytes(cls, bitstream): ''' 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Type=2 |P|E|S| Reserved | Record Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Nonce . . . | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | . . . Nonce | +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | Record TTL | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ R | Locator Count | EID mask-len | ACT |A| Reserved | e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ c | Rsvd | Map-Version Number | EID-Prefix-AFI | o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ r | EID-Prefix | d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | /| Priority | Weight | M Priority | M Weight | | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | o | Unused Flags |L|p|R| Loc-AFI | | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | \| Locator | +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read the flags (packet.probe, packet.enlra_enabled, packet.security) = bitstream.readlist('3*bool') # Skip reserved bits packet._reserved1 = bitstream.read(17) # Store the record count until we need it record_count = bitstream.read('uint:8') # Read the nonce packet.nonce = bitstream.read('bytes:8') # Read the records for dummy in range(record_count): record = MapReplyRecord.from_bytes(bitstream) packet.records.append(record) return packet
#!/usr/bin/env python # -*- coding: utf-8 -*- from bitstring import ConstBitStream import sys c = ConstBitStream(filename=sys.argv[1]) #Most log entry ends with 0A, this helps us to seek to the beginning of an entry start = c.find('0x0A', bytealigned=True)[0] #Seek 8 byte into the stream to skip EOL from previus log entry start += 8 c.pos = start while True: #Read and print the binary log header header = c.readlist('8*uintle:32') print header #Get the size in bits of the log message msgSize = (header[0] * 8 - 256) #Move pointer after message c.pos += msgSize #Check if EOL is present after message, if true, move pointer 8 byte if c.peek(8).hex == '0a': c.pos += 8
def parse_field_values(self): data = ConstBitStream(filename=self._packet_data) self._field_values = dict( zip(self._field_size.keys(), data.readlist(self.get_field_size())))
class SSIF_Reader(object): """Reads .SSIF files""" def __init__(self, fileString): self.stream = ConstBitStream(filename=fileString) name_b, self.width, self.height, self.depth, self.timepoints, self.channels, self.bytesPerPix, packingOrder_idx = self.stream.readlist('bytes:64, uintle:32, uintle:32, uintle:32, uintle:32, uintle:32, uintle:32, uintle:32') self.packingOrder = GetFilePackingOrder(packingOrder_idx) self.name = StringFromBytes(name_b) self.channelNames = [] for i in range(self.channels): self.channelNames.append(StringFromBytes(self.stream.read('bytes:32'))) self.imageMap = [] n = self.channels * self.depth * self.timepoints for i in range(n): nBytes = self.stream.read('uintle:32') self.imageMap.append({'offset': self.stream.bytepos, 'nBytes': nBytes}) if i < (n - 1): self.stream.bytepos += nBytes def BaseLookUpFunc(first, second, third, n1, n2): nf = len(first) ns = len(second) nt = len(third) first = np.repeat(first, ns * nt) second = np.tile(np.repeat(second, nt), nf) third = np.tile(third, nf * ns) return (first * n1) + (second * n2) + third if self.packingOrder == file_packing_order['ZTC']: def LookUpFunc(z, t, c): return BaseLookUpFunc(c, t, z, self.depth * self.timepoints, self.depth) elif self.packingOrder == file_packing_order['ZCT']: def LookUpFunc(z, t, c): return BaseLookUpFunc(t, c, z, self.depth * self.channels, self.depth) elif self.packingOrder == file_packing_order['TZC']: def LookUpFunc(z, t, c): return BaseLookUpFunc(c, z, t, self.depth * self.timepoints, self.timepoints) elif self.packingOrder == file_packing_order['TCZ']: def LookUpFunc(z, t, c): return BaseLookUpFunc(z, c, t, self.timepoints * self.channels, self.timepoints) elif self.packingOrder == file_packing_order['CZT']: def LookUpFunc(z, t, c): return BaseLookUpFunc(t, z, c, self.depth * self.channels, self.channels) elif self.packingOrder == file_packing_order['CTZ']: def LookUpFunc(z, t, c): return BaseLookUpFunc(z, t, c, self.timepoints * self.channels, self.channels) self._LookUpFunc_ = LookUpFunc if self.bytesPerPix == 4: dt = np.dtype(np.uint32) elif self.bytesPerPix == 2: dt = np.dtype(np.uint16) elif self.bytesPerPix == 1: dt = np.dtype(np.uint8) self._dt_ = dt.newbyteorder('<') def GetImage(self, z=0, t=0, c=0, image_type='raw', normalise=None): if type(c) is str: c = self.channelNames.index(c) if type(z) is int: z = [z] if type(t) is int: t = [t] if type(c) is int: c = [c] z = np.array(z) t = np.array(t) c = np.array(c) ns = self._LookUpFunc_(z, t, c) im = np.zeros((self.width, self.height, len(ns))).astype(self._dt_) for idx, n in enumerate(ns): offset = self.imageMap[n]['offset'] nBytes = self.imageMap[n]['nBytes'] self.stream.bytepos = offset im[:, :, idx] = np.frombuffer(decompress(self.stream.readlist('bytes:n', n=nBytes)[0], bufsize=(self.bytesPerPix * self.height * self.width)), dtype=self._dt_).reshape((self.width, self.height)) if image_type == 'float' or image_type == 'pil': im = im.astype(np.float) if normalise == 'full_range' and image_type != 'pil': im /= ((2**(8*self.bytesPerPix))-1) elif normalise == '01' or image_type == 'pil': normRange = min(im.flatten()), max(im.flatten()) im = (im - normRange[0]) / (normRange[1] - normRange[0]) if image_type == 'pil': from PIL import Image im = [Image.fromarray(im[:, :, i] * 255.0) for i in range(im.shape[-1])] return im
#offset_list.extend(list(s.findall('0x6B617254', bytealigned = True))) #offset_list.extend(list(s.findall('0x74536e49', bytealigned = True))) #offset_list.extend(list(s.findall('0x74537854', bytealigned = True))) #offset_list.extend(list(s.findall('0x69766e45', bytealigned = True))) sorted_offset_list = sorted(offset_list) for thisOffset in sorted_offset_list: s.pos = thisOffset if bDebug: debugPrint("Byte offset {}".format(thisOffset)) dumphex(64, s) recordType, recordSubType, recordNumber, recordMidiID, dataLength = s.readlist( "pad:32, uintle:16, uintle:32, uintle:32, uintle:32, 2*pad:32, pad:16, uintle:32, pad:32" ) # We are now at the start of the data so save this position for later... dataStart = s.pos if bDebug: debugPrint( "Data length is: {} Type is: {} Record no: {} MIDI ID: {}".format( dataLength, recordType, recordNumber, recordMidiID)) if (recordType == 1 or recordType == 5): dumphex(dataLength, s) # Test for a MIDI block header blockType = s.read("bytes:3") debugPrint("BlockType is {}".format(blockType.hex()))
class Blob(object): _data = None def __init__(self, bin_data=None, rw=False): """Initialising the class with an byte (octet) array or make a new, empty one. :param bin_data: Byte array. :param rw: If bin_data is set, make it read/write-able, otherwise it's read-only. """ if bin_data is None: self._data = BitStream() elif rw: self._data = BitStream(bytes=bin_data) else: self._data = ConstBitStream(bytes=bin_data) self.reset() def __str__(self): return "%dB %d/%d" % (len(self._data) // 8, self._data.pos // 8, self._data.pos % 8) def __len__(self): return len(self._data) def __getitem__(self, x): if isinstance(x, tuple): return self._data[x[0]:x[1]] else: return self._data[x] def reset(self, x=0): """Reset internal pointer to position x or start""" self._data.pos = x * 8 def get_bytes(self): return self._data.bytes def get_point(self): return self._data.pos // 8 def set_point(self, point): self._data.pos = point * 8 def get_bitcons(self): return self._data.pos % 8 def set_bitcons(self, consumed): self._data.pos += consumed p = property(get_point, set_point) bc = property(get_bitcons, set_bitcons) def read(self, fmt): return self._data.read(fmt) def readlist(self, fmt): return self._data.readlist(fmt) def writelist(self, fmt, json_data): self._data += Bits(fmt.format(*json_data)) def read_align(self, even=False): p = self._data.pos self._data.bytealign() if even and (self._data.pos // 8) & 1: self._data.pos += 8 return self._data.pos - p def write_align(self, even=False): width = (8 - (len(self._data) % 8)) & 7 self._data += ("uint:{}={}").format(width, 0) if even and (len(self._data) // 8) & 1: self._data += ("uint:{}={}").format(8, 0) def read_skip(self, width): """Skip width bits. Move internal pointer when some bits don't need processing. :return: Void. """ # self._data.read("pad:%d" % width) self._data.pos += width def write_skip(self, width): """Skip width bits. Move internal pointer when some bits don't need processing. :return: Void. """ self._data += ("uintbe:{}={}" if not width & 7 else "uint:{}={}").format(width, 0) def read_bytes(self, width=1): return self._data.read("bytes:%d" % width) def read_bits(self, width): """Read width bits from internal buffer. :return: character buffer, which needs further decoding. """ if width & 7: return self._data.read("uint:%d" % width) else: return self._data.read("uintbe:%d" % width) def write_bytes(self, value, width=None): """ :param value: character array (String) :param width: the string's width in bits, not octets. """ if isinstance(value, six.text_type): value = value.encode("latin-1") value_len = len(value) if width is None: width = value_len else: width //= 8 if value_len > width: value = value[:width] elif value_len < width: value += b"\x00" * (width - value_len) self._data += Bits(bytes=value) return len(self._data) def write_uint(self, value, width): value = int(value) self._data += ("uintbe:{}={}" if width % 8 == 0 else "uint:{}={}").format(width, value) return len(self._data) def set_uint(self, value, width, bitpos): if width // 8 == 0: bins = Bits(uint=value, length=width) else: bins = Bits(uintbe=value, length=24) self._data[bitpos:bitpos + width] = bins
def from_bytes(cls, bitstream): r''' Parse the given packet and update properties accordingly >>> data_hex = ('13000001ae92b5574f849cd00001ac10' ... '1f0300015cfe1cbd00200001ac101f01') >>> data = data_hex.decode('hex') >>> message = ControlMessage.from_bytes(data) >>> message.message_type 1 >>> message.authoritative False >>> message.probe True >>> message.smr True >>> message.pitr False >>> message.smr_invoked False >>> message.nonce '\xae\x92\xb5WO\x84\x9c\xd0' >>> message.source_eid IPv4Address(u'172.16.31.3') >>> message.itr_rlocs [IPv4Address(u'92.254.28.189')] >>> message.eid_prefixes [IPv4Network(u'172.16.31.1/32')] >>> message.map_reply ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the message type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read the flags (packet.authoritative, map_data_present, packet.probe, packet.smr, packet.pitr, packet.smr_invoked) = bitstream.readlist('6*bool') # Skip over reserved bits packet._reserved1 = bitstream.read(9) # Save the IRC until we reach the actual data irc = bitstream.read('uint:5') # Save the record count until we reach the actual data record_count = bitstream.read('uint:8') # Read the nonce packet.nonce = bitstream.read('bytes:8') # Read the source EID packet.source_eid = read_afi_address_from_bitstream(bitstream) # Read the ITR RLOCs for dummy in range(irc + 1): itr_rloc = read_afi_address_from_bitstream(bitstream) packet.itr_rlocs.append(itr_rloc) # Read the EIDs for dummy in range(record_count): # A records begins with 8 reserved bits: skip bitstream.read(8) # Read 8 bits for the prefix length prefix_len = bitstream.read('uint:8') # Then an AFI style prefix eid_prefix = read_afi_address_from_bitstream(bitstream, prefix_len) packet.eid_prefixes.append(eid_prefix) # Read the map-reply record if present if map_data_present: packet.map_reply = MapReplyRecord.from_bytes(bitstream) # Verify that the properties make sense packet.sanitize() return packet
def decode(byte_string): data = ConstBitStream(bytes=byte_string) packet_type = data[_PACKET_TYPE_OFFSET:_PACKET_TYPE_OFFSET+_PACKET_TYPE_SIZE].read(_PACKET_TYPE_SPEC) read_spec = _READ_SPECS[packet_type] values = data.readlist(read_spec['format']) return read_spec['name'], dict(zip(read_spec['fields'], values))
def from_bytes(cls, bitstream, decode_payload=True): r''' Parse the given packet and update properties accordingly >>> data_hex = ('c033d3c10000000745c0005835400000' ... 'ff06094a254d38204d45d1a30016f597' ... 'a1c3c7406718bf1b50180ff0793f0000' ... 'b555e59ff5ba6aad33d875c600fd8c1f' ... 'c5268078f365ee199179fbd09d09d690' ... '193622a6b70bcbc7bf5f20dda4258801') >>> data = data_hex.decode('hex') >>> message = DataPacket.from_bytes(data) >>> message.echo_nonce_request False >>> message.nonce '3\xd3\xc1' >>> message.source_map_version >>> message.destination_map_version >>> message.lsb ... # doctest: +ELLIPSIS [True, True, True, False, False, ..., False, False, False, False] >>> message.instance_id >>> bytes(message.payload) ... # doctest: +ELLIPSIS 'E\xc0\x00X5@\x00\x00\xff\x06\tJ%M8...\xdd\xa4%\x88\x01' ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the flags (nonce_present, lsb_enabled, packet.echo_nonce_request, map_version_present, instance_id_present) = bitstream.readlist('5*bool') # Skip over reserved bits bitstream.read(3) # Parse nonce or map versions if nonce_present: # Nonce: yes, versions: no packet.nonce = bitstream.read('bytes:3') packet.source_map_version = None packet.destination_map_version = None elif map_version_present: # Nonce: no, versions: yes packet.nonce = None (packet.source_map_version, packet.destination_map_version) = bitstream.readlist('2*uint:12') else: # Nonce: no, versions: no packet.nonce = None packet.source_map_version = None packet.destination_map_version = None # Skip over the nonce/map-version bits bitstream.read(24) # Parse instance-id if instance_id_present: packet.instance_id = bitstream.read('uint:24') # 8 bits remaining for LSB lsb_bits = 8 else: # 32 bits remaining for LSB lsb_bits = 32 # Parse LSBs if lsb_enabled: packet.lsb = bitstream.readlist('%d*bool' % lsb_bits) # Reverse for readability: least significant locator-bit first packet.lsb.reverse() else: # Skip over the LSBs bitstream.read(lsb_bits) # The rest of the packet is payload remaining = bitstream[bitstream.pos:] # Parse IP packet if len(remaining): ip_version = remaining.peek('uint:4') if ip_version == 4: packet.payload = IPv4Packet.from_bytes(remaining, decode_payload=decode_payload) elif ip_version == 6: packet.payload = IPv6Packet.from_bytes(remaining, decode_payload=decode_payload) else: packet.payload = remaining.bytes # Verify that the properties make sense packet.sanitize() return packet
class DenseChunk(object): def __init__(self, chunk_data, attribute, start_pos, end_pos, chunk_len, schema): self._chunk_data_stream = ConstBitStream(bytes=chunk_data) self._attribute_id = attribute.id self._start_pos = start_pos self._end_pos = end_pos self._chunk_len = chunk_len self._curr_elem = 0 self._end = False self._schema = schema self._nullable = attribute.nullable self._buf_pos = 0 self._n_elems = 1 for i in range(0, len(self._start_pos)): interval = self._end_pos[i] - self._start_pos[i] + 1 self._n_elems *= interval self._bitmap_size = ( (self._n_elems + 7) >> 3) if attribute.nullable else 0 self._varying_offs = 0 self._elem_size = type_bitsize(attribute.type) if self._elem_size == 0: self._elem_size = 4 self._varying_offs = self._n_elems * self._elem_size else: self._elem_size >>= 3 self._calc_buf_pos() self._item_getter = { TID_INT8: self._get_int8, TID_INT16: self._get_int16, TID_INT32: self._get_int32, TID_INT64: self._get_int64, TID_UINT8: self._get_uint8, TID_UINT16: self._get_uint16, TID_UINT32: self._get_uint32, TID_UINT64: self._get_uint64, TID_FLOAT: self._get_float, TID_DOUBLE: self._get_double, TID_CHAR: self._get_char, TID_BOOL: self._get_bool, TID_STRING: self._get_string, TID_VOID: None }[attribute.type] def next_item(self): self._curr_elem += 1 if self._curr_elem >= self._n_elems: self._end = True return self._calc_buf_pos() def _calc_buf_pos(self): self._buf_pos = self._bitmap_size + ( self._curr_elem >> 3 if self._elem_size == 0 else self._curr_elem * self._elem_size) @property def end(self): return self._end @property def eof(self): return False def get_coordinates(self): l = self._curr_elem coords = {} for i in xrange(len(self._start_pos) - 1, -1, -1): pos = self._start_pos[i] + l % self._chunk_len[i] coords[self._schema.dimensions[i].name] = pos coords[i] = pos l /= self._chunk_len[i] return coords def get_item(self): if self.end: return None if self._nullable: null = False pos_tmp = self._buf_pos bitmap_pos = self._curr_elem >> 3 self._chunk_data_stream.bytepos = bitmap_pos if self._chunk_data_stream.read('uintle:8') & ( 1 << (self._curr_elem & 7)): null = True self._buf_pos = pos_tmp if null: return None return self._item_getter() def _get_int8(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:8') def _get_int16(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:16') def _get_int32(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:32') def _get_int64(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:64') def _get_uint8(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:8') def _get_uint16(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:16') def _get_uint32(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:32') def _get_uint64(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:64') def _get_float(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('floatle:32') def _get_double(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('floatle:64') def _get_char(self): self._chunk_data_stream.bytepos = self._buf_pos return chr(self._chunk_data_stream.read('intle:8')) def _get_bool(self): self._chunk_data_stream.bytepos = self._buf_pos b = self._chunk_data_stream.read('intle:8') return (b & (1 << (self._curr_elem & 7))) != 0 def _get_string(self): self._chunk_data_stream.bytepos = self._buf_pos data_offset = self._chunk_data_stream.read('intle:32') _buf_pos = self._bitmap_size + data_offset + self._varying_offs self._chunk_data_stream.bytepos = _buf_pos s = self._chunk_data_stream.read('uintle:8') if s != 0: item_size = s else: (a, b, c, d) = self._chunk_data_stream.readlist( 'uintle:8, uintle:8, uintle:8, uintle:8') item_size = (a << 24) | (b << 16) | (c << 8) | d return str(self._chunk_data_stream.read('bytes:%d' % (item_size - 1)))
class DenseChunk(object): def __init__(self, chunk_data, attribute, start_pos, end_pos, chunk_len, schema): self._chunk_data_stream = ConstBitStream(bytes=chunk_data) self._attribute_id = attribute.id self._start_pos = start_pos self._end_pos = end_pos self._chunk_len = chunk_len self._curr_elem = 0 self._end = False self._schema = schema self._nullable = attribute.nullable self._buf_pos = 0 self._n_elems = 1 for i in range(0, len(self._start_pos)): interval = self._end_pos[i] - self._start_pos[i] + 1 self._n_elems *= interval self._bitmap_size = ((self._n_elems + 7) >> 3) if attribute.nullable else 0 self._varying_offs = 0 self._elem_size = type_bitsize(attribute.type) if self._elem_size == 0: self._elem_size = 4 self._varying_offs = self._n_elems * self._elem_size else: self._elem_size >>= 3 self._calc_buf_pos() self._item_getter = { TID_INT8: self._get_int8, TID_INT16: self._get_int16, TID_INT32: self._get_int32, TID_INT64: self._get_int64, TID_UINT8: self._get_uint8, TID_UINT16: self._get_uint16, TID_UINT32: self._get_uint32, TID_UINT64: self._get_uint64, TID_FLOAT: self._get_float, TID_DOUBLE: self._get_double, TID_CHAR: self._get_char, TID_BOOL: self._get_bool, TID_STRING: self._get_string, TID_VOID: None }[attribute.type] def next_item(self): self._curr_elem += 1 if self._curr_elem >= self._n_elems: self._end = True return self._calc_buf_pos() def _calc_buf_pos(self): self._buf_pos = self._bitmap_size + ( self._curr_elem >> 3 if self._elem_size == 0 else self._curr_elem * self._elem_size) @property def end(self): return self._end @property def eof(self): return False def get_coordinates(self): l = self._curr_elem coords = {} for i in xrange(len(self._start_pos) - 1, -1, -1): pos = self._start_pos[i] + l % self._chunk_len[i] coords[self._schema.dimensions[i].name] = pos coords[i] = pos l /= self._chunk_len[i] return coords def get_item(self): if self.end: return None if self._nullable: null = False pos_tmp = self._buf_pos bitmap_pos = self._curr_elem >> 3 self._chunk_data_stream.bytepos = bitmap_pos if self._chunk_data_stream.read('uintle:8') & (1 << (self._curr_elem & 7)): null = True self._buf_pos = pos_tmp if null: return None return self._item_getter() def _get_int8(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:8') def _get_int16(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:16') def _get_int32(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:32') def _get_int64(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('intle:64') def _get_uint8(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:8') def _get_uint16(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:16') def _get_uint32(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:32') def _get_uint64(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('uintle:64') def _get_float(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('floatle:32') def _get_double(self): self._chunk_data_stream.bytepos = self._buf_pos return self._chunk_data_stream.read('floatle:64') def _get_char(self): self._chunk_data_stream.bytepos = self._buf_pos return chr(self._chunk_data_stream.read('intle:8')) def _get_bool(self): self._chunk_data_stream.bytepos = self._buf_pos b = self._chunk_data_stream.read('intle:8') return (b & (1 << (self._curr_elem & 7))) != 0 def _get_string(self): self._chunk_data_stream.bytepos = self._buf_pos data_offset = self._chunk_data_stream.read('intle:32') _buf_pos = self._bitmap_size + data_offset + self._varying_offs self._chunk_data_stream.bytepos = _buf_pos s = self._chunk_data_stream.read('uintle:8') if s != 0: item_size = s else: (a, b, c, d) = self._chunk_data_stream.readlist('uintle:8, uintle:8, uintle:8, uintle:8') item_size = (a << 24) | (b << 16) | (c << 8) | d return str(self._chunk_data_stream.read('bytes:%d' % (item_size - 1)))
def parseAxisBlock(axBlkStr): ret = dict() if len(axBlkStr) != AX_BLK_SIZE: raise ValueError("Invalid passed string length") keys = ["status", "switches", "stopCode", "refPos", "motorPos", "posError", "auxPos", "vel", "torque", "analog"] statusKeys = ["moving", "motionMode1", "motionMode1", "findingEdge", "homing", "homeP1Done", "homeP2Done", "coordMotion", "movingNeg", "contourMode", "slewingMode", "stopping", "finalDecel", "latchArmed", "offOnErrArmed", "motorOff"] # The f*****g galil is little endian, so [:2] splits off the segment of the string we want, and [::-1] reverses it statusBs = ConstBitStream(bytes=axBlkStr[:2][::-1]) # Status is 16 boolean values packed into a uint_16 statusVals = statusBs.readlist(["uint:1"]*16) # zip flags and names into dict zipped = zip(statusKeys, statusVals) vals = [dict(zipped)] vals.extend(struct.unpack(AX_BLK_PARSE_STR, axBlkStr)) ret = dict(zip(keys, vals)) return ret