def read_message(self):
header = self.read_all(self.__block_size_in, check_rekey=True)<EOL>if self.__block_engine_in is not None:<EOL><INDENT>header = self.__block_engine_in.update(header)<EOL><DEDENT>if self.__dump_packets:<EOL><INDENT>self._log(DEBUG, util.format_binary(header, "<STR_LIT>"))<EOL><DEDENT>packet_size = struct.unpack("<STR_LIT>", header[:<NUM_LIT:4>])[<NUM_LIT:0>]<EOL>leftover = header[<NUM_LIT:4>:]<EOL>if (packet_size - len(leftover)) % self.__block_size_in != <NUM_LIT:0>:<EOL><INDENT>raise SSHException("<STR_LIT>")<EOL><DEDENT>buf = self.read_all(packet_size + self.__mac_size_in - len(leftover))<EOL>packet = buf[: packet_size - len(leftover)]<EOL>post_packet = buf[packet_size - len(leftover) :]<EOL>if self.__block_engine_in is not None:<EOL><INDENT>packet = self.__block_engine_in.update(packet)<EOL><DEDENT>if self.__dump_packets:<EOL><INDENT>self._log(DEBUG, util.format_binary(packet, "<STR_LIT>"))<EOL><DEDENT>packet = leftover + packet<EOL>if self.__mac_size_in > <NUM_LIT:0>:<EOL><INDENT>mac = post_packet[: self.__mac_size_in]<EOL>mac_payload = (<EOL>struct.pack("<STR_LIT>", self.__sequence_number_in, packet_size)<EOL>+ packet<EOL>)<EOL>my_mac = compute_hmac(<EOL>self.__mac_key_in, mac_payload, self.__mac_engine_in<EOL>)[: self.__mac_size_in]<EOL>if not util.constant_time_bytes_eq(my_mac, mac):<EOL><INDENT>raise SSHException("<STR_LIT>")<EOL><DEDENT><DEDENT>padding = byte_ord(packet[<NUM_LIT:0>])<EOL>payload = packet[<NUM_LIT:1> : packet_size - padding]<EOL>if self.__dump_packets:<EOL><INDENT>self._log(<EOL>DEBUG,<EOL>"<STR_LIT>".format(<EOL>packet_size, padding<EOL>),<EOL>)<EOL><DEDENT>if self.__compress_engine_in is not None:<EOL><INDENT>payload = self.__compress_engine_in(payload)<EOL><DEDENT>msg = Message(payload[<NUM_LIT:1>:])<EOL>msg.seqno = self.__sequence_number_in<EOL>self.__sequence_number_in = (self.__sequence_number_in + <NUM_LIT:1>) & xffffffff<EOL>raw_packet_size = packet_size + self.__mac_size_in + <NUM_LIT:4><EOL>self.__received_bytes += raw_packet_size<EOL>self.__received_packets += <NUM_LIT:1><EOL>if self.__need_rekey:<EOL><INDENT>self.__received_bytes_overflow += raw_packet_size<EOL>self.__received_packets_overflow += <NUM_LIT:1><EOL>if (<EOL>self.__received_packets_overflow<EOL>>= self.REKEY_PACKETS_OVERFLOW_MAX<EOL>) or (<EOL>self.__received_bytes_overflow >= self.REKEY_BYTES_OVERFLOW_MAX<EOL>):<EOL><INDENT>raise SSHException(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT><DEDENT>elif (self.__received_packets >= self.REKEY_PACKETS) or (<EOL>self.__received_bytes >= self.REKEY_BYTES<EOL>):<EOL><INDENT>err = "<STR_LIT>"<EOL>self._log(<EOL>DEBUG,<EOL>err.format(self.__received_packets, self.__received_bytes),<EOL>)<EOL>self.__received_bytes_overflow = <NUM_LIT:0><EOL>self.__received_packets_overflow = <NUM_LIT:0><EOL>self._trigger_rekey()<EOL><DEDENT>cmd = byte_ord(payload[<NUM_LIT:0>])<EOL>if cmd in MSG_NAMES:<EOL><INDENT>cmd_name = MSG_NAMES[cmd]<EOL><DEDENT>else:<EOL><INDENT>cmd_name = "<STR_LIT>".format(cmd)<EOL><DEDENT>if self.__dump_packets:<EOL><INDENT>self._log(<EOL>DEBUG,<EOL>"<STR_LIT>".format(cmd_name, len(payload)),<EOL>)<EOL><DEDENT>return cmd, msg<EOL>
Only one thread should ever be in this function (no other locking is
done).

:raises: `.SSHException` -- if the packet is mangled
:raises: `.NeedRekeyException` -- if the transport should rekey