python - unpack_from requires a buffer of at least 4 bytes -


i receiving packet client, consisting of many fields. read fields successfully, when comes last field tag_end, python gives me error:

unpack_from requires buffer of @ least 4 bytes not found.

this code:

def set_bin(self, buf):     """reads vector of bytes (probably received network or     read file) , tries construct packet structure     it, reading each packet member buffer.      somehow deserializing packet.     """     assert isinstance(buf, bytearray), 'buffer type not valid'     offset = 0      print("$$$$$$$$$$$$$$$$ set bin $$$$$$$$$$$$$$$$$")      try:         (self._tag_start, self._version, self._checksum, self._connection_id,          self._packet_seq) = packet.packer_1.unpack_from(str(buf), offset)     except struct.error e:         print(e)         raise deserializeerror(e)     except valueerror e:         print(e)         raise deserializeerror(e)           #i=4 h=2 b=1     offset = packet.offset_guid     #14 correct     self._guid = buf[offset:offset+packet.uuid_size] #14-16 correct      offset = packet.offset_guid + packet.uuid_size      print("$$$$$$$$$$$$$$$$ guid read  $$$$$$$$$$$$$$$$$")      try:        (self._timestamp_sec, self._timestamp_microsec, self._command,         self._command_seq, self._subcommand, self._data_seq,         self._data_length) = packet.packer_3.unpack_from(str(buf), offset)     except struct.error e:         print(e)         raise deserializeerror(e)     except valueerror e:         print(e)         raise deserializeerror(e)      print("$$$$$$$$$$$$$$$$ timestamps read $$$$$$$$$$$$$$$$$")    offset = packet.offset_authenticate     self._username = buf[offset:offset + self.username_size]        #saman     offset += self.username_size      print("$$$$$$$$$$$$$$$$ username read  $$$$$$$$$$$$$$$$$")      self._password = buf[offset:offset+self.username_size]     offset += self.password_size      print("$$$$$$$$$$$$$$$$ password read $$$$$$$$$$$$$$$$$")      self._data = buf[offset:offset+self._data_length]     offset = offset + self._data_length      print("$$$$$$$$$$$$$$$$ data read  $$$$$$$$$$$$$$$$$")      try:         (self._tag_end,) = packet.packer_4.unpack_from(str(buf), offset)     except struct.error e:         print(e)         raise deserializeerror(e)     except valueerror e:         print(e)         raise deserializeerror(e)      print("$$$$$$$$$$$$$$$$ tag end read $$$$$$$$$$$$$$$$$")       if len(buf) != packet.packer.size + self._data_length:         print('failed deserialize binary data correctly , construct packet due data')     else:         print('@@@@@@@@@@@@@@@ deserialized successfully') 

and constants used in code:

struct_format_str   = r'=ihihh 16b iihhhhh 6c 9c' #saman struct_format_str_1 = r'=ihihh' struct_format_str_2 = r'=16b' struct_format_str_3 = r'=iihhhhh' struct_format_str_4 = r'=i' struct_format_str_5 = r'=6c' struct_format_str_6 = r'=9c' uuid_size   = 16 offset_guid = 14 #offset_data = 48     #shifting offset data 15 char       offset_authenticate = 48 packer   = struct.struct(str(struct_format_str))     #saman packer_1 = struct.struct(str(struct_format_str_1)) packer_2 = struct.struct(str(struct_format_str_2)) packer_3 = struct.struct(str(struct_format_str_3)) packer_4 = struct.struct(str(struct_format_str_4)) packer_5 = struct.struct(str(struct_format_str_5)) packer_6 = struct.struct(str(struct_format_str_6)) bytes_tag_start = packer_4.pack(tag_start) bytes_tag_end   = packer_4.pack(tag_end) 

and initialization of packet object, initializes fields:

def init(self, **kwargs): if 'buf' in kwargs: self.set_bin(kwargs['buf']) else: assert kwargs['command'] in packet.rtcinet_commands.values() , kwargs['subcommand'] in packet.rtcinet_commands.values(), 'undefined protocol command' assert isinstance(kwargs['data'], bytearray), 'invalid type data field' field in ('command', 'subcommand', 'data'): setattr(self, '_' + field, kwargs[field])

    self._tag_start = packet.tag_start     self._version = packet.version_current % (packet.ushrt_max + 1)     self._checksum = packet.crc_init     self._connection_id = kwargs.get('connection_id', 0) % (packet.ushrt_max + 1)     self._packet_seq = packet.packet_seq     packet.packet_seq = (packet.packet_seq + 1) % (packet.ushrt_max + 1)     self._guid = uuid.uuid4().bytes     dt = datetime.datetime.now()     self._timestamp_sec = int(time.mktime(dt.timetuple()))     self._timestamp_microsec = dt.microsecond     # self._command = kwargs['command']     self._command_seq = kwargs.get('command_seq', 0)     # self._subcommand = kwargs['subcommand']     self._data_seq = kwargs.get('data_seq', 0)     self._data_length = len(kwargs['data'])      self._username = packet.username            #saman     self._password = packet.password 

i have made sure read fields in right order, written in packet client program. still couldn't manage solve problem.

do have idea how solved?

the problem seems you're converting things str on place no reason.

in places, packer_1 = struct.struct(str(struct_format_str_1)), makes code less readable , understandable, doesn't affect actual output. example, struct_format_str_1 str, str(struct_format_str_1) same str.

but in other places, it's far worse that. in particular, @ lines packet.packer_1.unpack_from(str(buf), offset). there, buf bytearray. (it has be, because assert it.) calling str on bytearray gives string representation of bytearray. example:

>>> b = bytearray(b'abc') >>> len(b) 3 >>> s = str(b) >>> s "bytearray(b'abc')" >>> len(s) 17 

that string representation not going have same length actual buffer you're representing. it's no wonder errors length being wrong. (and if got unlucky , didn't have such errors, you'd reading garbage values instead.)

so, should convert bytearray struct module can handle? nothing! the docs say:

several struct functions (and methods of struct) take buffer argument. refers objects implement buffer protocol , provide either readable or read-writable buffer. common types used purpose bytes , bytearray


Comments

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -