def parse(data): response = HttpResponse() for i in range(0, len(data)): response.parse(data[i]) if response.is_read_completely(): break return response
def _read_response(self, timeout=10): # following the information from page 71 about HTTP Message splitting: # The blocks start with 2 byte little endian defining the length of the encrypted data (max 1024 bytes) # followed by 16 byte authTag blocks = [] tmp = bytearray() exp_len = 1024 response = HttpResponse() while not response.is_read_completely(): # make sure we read all blocks but without blocking to long. Was introduced to support chunked transfer mode # from https://github.com/maximkulkin/esp-homekit self.sock.setblocking(0) no_data_remaining = (len(tmp) == 0) # if there is no data use the long timeout so we don't miss anything, else since there is still data go on # much quicker. if no_data_remaining: used_timeout = timeout else: used_timeout = 0.01 data_ready = select.select([self.sock], [], [], used_timeout)[0] # check if there is anything more to do if not data_ready and no_data_remaining: break self.sock.settimeout(0.1) data = self.sock.recv(exp_len) # ready but no data => continue if not data and no_data_remaining: continue tmp += data length = int.from_bytes(tmp[0:2], 'little') if length + 18 > len(tmp): # if the the amount of data in tmp is not length + 2 bytes for length + 16 bytes for the tag, the block # is not complete yet continue tmp = tmp[2:] block = tmp[0:length] tmp = tmp[length:] tag = tmp[0:16] tmp = tmp[16:] decrypted = self.decrypt_block(length, block, tag) # TODO how to react to False? if tmp is not False: response.parse(decrypted) # check how long next block will be if int.from_bytes(tmp[0:2], 'little') < 1024: exp_len = int.from_bytes(tmp[0:2], 'little') - len(tmp) + 18 return response
def _read_response(self): # following the information from page 71 about HTTP Message splitting: # The blocks start with 2 byte little endian defining the length of the encrypted data (max 1024 bytes) # followed by 16 byte authTag blocks = [] tmp = bytearray() exp_len = 128 response = HttpResponse() while not response.is_read_completly(): # make sure we read all blocks but without blocking to long. Was introduced to support chunked transfer mode # from https://github.com/maximkulkin/esp-homekit self.sock.setblocking(0) ready = select.select([self.sock], [], [], 10) if not ready[0]: break self.sock.settimeout(0.1) data = self.sock.recv(exp_len) # ready but no data => quit if not data: break tmp += data length = int.from_bytes(tmp[0:2], 'little') if length + 18 > len(tmp): # if the the amount of data in tmp is not length + 2 bytes for length + 16 bytes for the tag, the block # is not complete yet continue tmp = tmp[2:] block = tmp[0:length] tmp = tmp[length:] tag = tmp[0:16] tmp = tmp[16:] response.parse(self.decrypt_block(length, block, tag)) # check how long next block will be if int.from_bytes(tmp[0:2], 'little') < 1024: exp_len = int.from_bytes(tmp[0:2], 'little') - len(tmp) + 18 return response