async def read_msg(self) -> Tuple[protocol.Command, protocol._DecodedMsgType]: header_data = await self.read(HEADER_LEN + MAC_LEN) header = self.decrypt_header(header_data) frame_size = self.get_frame_size(header) # The frame_size specified in the header does not include the padding to 16-byte boundary, # so need to do this here to ensure we read all the frame's data. read_size = roundup_16(frame_size) frame_data = await self.read(read_size + MAC_LEN) msg = self.decrypt_body(frame_data, frame_size) cmd = self.get_protocol_command_for(msg) decoded_msg = cmd.decode(msg) self.logger.debug("Successfully decoded %s msg: %s", cmd, decoded_msg) return cmd, decoded_msg
def decrypt_body(self, data: bytes, body_size: int) -> bytes: read_size = roundup_16(body_size) if len(data) < read_size + MAC_LEN: raise ValueError('Insufficient body length; Got {}, wanted {}'.format( len(data), (read_size + MAC_LEN))) frame_ciphertext = data[:read_size] frame_mac = data[read_size:read_size + MAC_LEN] self.ingress_mac.update(frame_ciphertext) fmac_seed = self.ingress_mac.digest()[:MAC_LEN] self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed)) expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN] if not bytes_eq(expected_frame_mac, frame_mac): raise AuthenticationError('Invalid frame mac') return self.aes_dec.update(frame_ciphertext)[:body_size]
async def read_msg( self) -> Tuple[protocol.Command, protocol._DecodedMsgType]: header_data = await self.read(HEADER_LEN + MAC_LEN) header = self.decrypt_header(header_data) frame_size = self.get_frame_size(header) # The frame_size specified in the header does not include the padding to 16-byte boundary, # so need to do this here to ensure we read all the frame's data. read_size = roundup_16(frame_size) frame_data = await self.read(read_size + MAC_LEN) msg = self.decrypt_body(frame_data, frame_size) cmd = self.get_protocol_command_for(msg) loop = asyncio.get_event_loop() decoded_msg = await wait_with_token(loop.run_in_executor( None, cmd.decode, msg), token=self.cancel_token) self.logger.debug("Successfully decoded %s msg: %s", cmd, decoded_msg) return cmd, decoded_msg
def decrypt_body(self, data: bytes, body_size: int) -> bytes: read_size = roundup_16(body_size) if len(data) < read_size + MAC_LEN: raise ValueError( 'Insufficient body length; Got {}, wanted {}'.format( len(data), (read_size + MAC_LEN))) frame_ciphertext = data[:read_size] frame_mac = data[read_size:read_size + MAC_LEN] self.ingress_mac.update(frame_ciphertext) fmac_seed = self.ingress_mac.digest()[:MAC_LEN] self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed)) expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN] if not bytes_eq(expected_frame_mac, frame_mac): raise DecryptionError('Invalid frame mac') return self.aes_dec.update(frame_ciphertext)[:body_size]
async def read_msg(self) -> Tuple[protocol.Command, protocol.PayloadType]: header_data = await self.read(HEADER_LEN + MAC_LEN) try: header = self.decrypt_header(header_data) except DecryptionError as err: self.logger.debug( "Bad message header from peer %s: Error: %r", self, err, ) raise MalformedMessage from err frame_size = self.get_frame_size(header) # The frame_size specified in the header does not include the padding to 16-byte boundary, # so need to do this here to ensure we read all the frame's data. read_size = roundup_16(frame_size) frame_data = await self.read(read_size + MAC_LEN) try: msg = self.decrypt_body(frame_data, frame_size) except DecryptionError as err: self.logger.debug( "Bad message body from peer %s: Error: %r", self, err, ) raise MalformedMessage from err cmd = self.get_protocol_command_for(msg) # NOTE: This used to be a bottleneck but it doesn't seem to be so anymore. If we notice # too much time is being spent on this again, we need to consider running this in a # ProcessPoolExecutor(). Need to make sure we don't use all CPUs in the machine for that, # though, otherwise asyncio's event loop can't run and we can't keep up with other peers. try: decoded_msg = cast(Dict[str, Any], cmd.decode(msg)) except MalformedMessage as err: self.logger.debug( "Malformed message from peer %s: CMD:%s Error: %r", self, type(cmd).__name__, err, ) raise else: self.logger.trace("Successfully decoded %s msg: %s", cmd, decoded_msg) self.received_msgs[cmd] += 1 return cmd, decoded_msg
async def read_msg( self) -> Tuple[protocol.Command, protocol._DecodedMsgType]: header_data = await self.read(HEADER_LEN + MAC_LEN) header = self.decrypt_header(header_data) frame_size = self.get_frame_size(header) # The frame_size specified in the header does not include the padding to 16-byte boundary, # so need to do this here to ensure we read all the frame's data. read_size = roundup_16(frame_size) frame_data = await self.read(read_size + MAC_LEN) msg = self.decrypt_body(frame_data, frame_size) cmd = self.get_protocol_command_for(msg) # NOTE: This used to be a bottleneck but it doesn't seem to be so anymore. If we notice # too much time is being spent on this again, we need to consider running this in a # ProcessPoolExecutor(). Need to make sure we don't use all CPUs in the machine for that, # though, otherwise asyncio's event loop can't run and we can't keep up with other peers. decoded_msg = cast(Dict[str, Any], cmd.decode(msg)) self.logger.trace("Successfully decoded %s msg: %s", cmd, decoded_msg) return cmd, decoded_msg