def crc32_decode(txt: typing.Union[bytes, str, bytearray], crc_len_format="L") -> bytes: crc_len = -struct.calcsize("<" + crc_len_format) crc = struct.unpack("<" + crc_len_format, txt[crc_len:])[0] payload = txt[:crc_len] calced_crc = calc_crc(payload) assert crc == calced_crc, "CRC-Error - " + str(hex(crc)) + " != " + str( hex(calced_crc)) return payload
def parse_raw_packet(self, packet: bytes, crc_len_format="L", number_of_chunks_len_format="I", quality_len_format="I", epsilon_len_format="f", check_block_number_len_format="I") -> \ typing.Optional[typing.Union[str, OnlinePacket]]: crc_len = -struct.calcsize("<" + crc_len_format) if self.error_correction.__code__.co_name == crc32.__code__.co_name: payload = packet[:crc_len] crc: int = struct.unpack("<" + crc_len_format, packet[crc_len:])[0] calced_crc: int = calc_crc(payload) if crc != calced_crc: # If the Packet is corrupt, try next one print("[-] CRC-Error - " + str(hex(crc)) + " != " + str(hex(calced_crc))) self.corrupt += 1 return "CORRUPT" else: crc_len = None try: packet = self.error_correction(packet) except: return "CORRUPT" # if RS or other error correction cannot reconstruct this packet struct_str: str = "<" + number_of_chunks_len_format + quality_len_format + epsilon_len_format + check_block_number_len_format struct_len: int = struct.calcsize(struct_str) data: bytes = packet[struct_len:crc_len] len_data: typing.Union[typing.Tuple[int, int, float, int], typing.Tuple[int, float, int]] = struct.unpack( struct_str, packet[0:struct_len]) if self.static_number_of_chunks is None: number_of_chunks, quality, self.epsilon, check_block_number = len_data self.number_of_chunks = xor_mask(number_of_chunks, number_of_chunks_len_format) else: quality, self.epsilon, check_block_number = len_data self.epsilon = round(self.epsilon, 6) self.quality = xor_mask(quality, quality_len_format) if self.dist is None: self.dist = OnlineDistribution(self.epsilon) if self.correct == 0: self.createAuxBlocks() # Create MockUp AuxBlocks with the given Pseudo-Random Number -> we will know which Packets are Encoded in which AuxBlock self.correct += 1 res = OnlinePacket( data, self.number_of_chunks, self.quality, self.epsilon, check_block_number, dist=self.dist, read_only=True, error_correction=self.error_correction, crc_len_format=crc_len_format, number_of_chunks_len_format=number_of_chunks_len_format, quality_len_format=quality_len_format, epsilon_len_format=epsilon_len_format, check_block_number_len_format=check_block_number_len_format, save_number_of_chunks_in_packet=self.static_number_of_chunks is None) return res
def parse_raw_packet(self, packet: bytes, crc_len_format: str = "L", number_of_chunks_len_format: str = "I", degree_len_format: str = "I", seed_len_format: str = "I") -> typing.Union[str, Packet]: crc_len = -struct.calcsize("<" + crc_len_format) if self.error_correction.__code__.co_name == crc32.__code__.co_name: payload: bytes = packet[:crc_len] crc: int = struct.unpack("<" + crc_len_format, packet[crc_len:])[0] calced_crc: int = calc_crc(payload) if crc != calced_crc: # If the Packet is corrupt, try next one print("[-] CRC-Error - " + str(hex(crc)) + " != " + str(hex(calced_crc))) self.corrupt += 1 return "CORRUPT" else: crc_len = None try: packet = self.error_correction(packet) except: self.corrupt += 1 return "CORRUPT" if self.implicit_mode: degree_len_format = "" struct_str: str = "<" + number_of_chunks_len_format + degree_len_format + seed_len_format struct_len: int = struct.calcsize(struct_str) len_data: typing.Union[int, typing.Tuple[int, int], typing.Tuple[int, int, int]] = struct.unpack(struct_str, packet[ 0:struct_len]) degree: typing.Optional[int] = None if self.static_number_of_chunks is None: if self.implicit_mode: number_of_chunks, seed = len_data else: number_of_chunks, degree, seed = len_data self.number_of_chunks = xor_mask(number_of_chunks, number_of_chunks_len_format) else: if self.implicit_mode: seed = len_data else: degree, seed = len_data seed: int = xor_mask(seed, seed_len_format) if degree is None: self.dist.set_seed(seed) degree: int = self.dist.getNumber() else: degree: int = xor_mask(degree, degree_len_format) used_packets = self.choose_packet_numbers(degree, seed) data = packet[struct_len:crc_len] self.correct += 1 return Packet(data, used_packets, self.number_of_chunks, read_only=True, error_correction=self.error_correction, save_number_of_chunks_in_packet=self.static_number_of_chunks is None)
def create_new_packet(self, systematic: bool = False, seed: typing.Optional[int] = None) -> RU10Packet: """ Creates a new RU10Packet with an ID, the number of participated packets and the XORed payload. :param seed: :param systematic: :return: A new RU10Packet """ if seed is None: seed = self.generate_new_id() packet_numbers = choose_packet_numbers(self.number_of_chunks, seed, self.dist, systematic=systematic) packets = [self.chunks[i] for i in packet_numbers] if self.debug: print("----") print("Id = " + str(seed)) print(packet_numbers) print(calc_crc(listXOR(packets))) print("----") return RU10Packet( listXOR(packets), packet_numbers, self.number_of_chunks, seed, dist=self.dist, read_only=False, error_correction=self.error_correction, packet_len_format=self.packet_len_format, crc_len_format=self.crc_len_format, number_of_chunks_len_format=self.number_of_chunks_len_format, id_len_format=self.id_len_format, save_number_of_chunks_in_packet=self. save_number_of_chunks_in_packet, prepend=self.prepend, append=self.append)
def getNextValidPacket(self, from_multiple_files: bool = False, packet_len_format: str = "I", crc_len_format: str = "L", number_of_chunks_len_format: str = "I", degree_len_format: str = "I", seed_len_format: str = "I", last_chunk_len_format: str = "I") -> typing.Optional[Packet]: if not from_multiple_files: packet_len: typing.Union[bytes, int] = self.f.read(struct.calcsize("<" + packet_len_format)) packet_len = struct.unpack("<" + packet_len_format, packet_len)[0] packet: bytes = self.f.read(int(packet_len)) else: packet = self.f.read() packet_len = len(packet) if not packet or not packet_len: # EOF self.EOF: bool = True self.f.close() return None crc_len: typing.Optional[int] = -struct.calcsize("<" + crc_len_format) if self.error_correction.__code__.co_name == crc32.__code__.co_name: payload = packet[:crc_len] # instead of typing.Any we would have _SupportsIndex: crc: typing.Union[int, typing.Any] = struct.unpack("<" + crc_len_format, packet[crc_len:])[0] calced_crc = calc_crc(payload) if crc != calced_crc: # If the Packet is corrupt, try next one print("[-] CRC-Error - " + str(hex(crc)) + " != " + str(hex(calced_crc))) self.corrupt += 1 return self.getNextValidPacket(from_multiple_files, packet_len_format=packet_len_format, crc_len_format=crc_len_format, number_of_chunks_len_format=number_of_chunks_len_format, degree_len_format=degree_len_format, seed_len_format=seed_len_format, last_chunk_len_format=last_chunk_len_format) else: crc_len = None try: packet = self.error_correction(packet) except: self.corrupt += 1 return self.getNextValidPacket(from_multiple_files) struct_str = "<" + number_of_chunks_len_format + degree_len_format + seed_len_format struct_len = struct.calcsize(struct_str) len_data = struct.unpack(struct_str, packet[0:struct_len]) degree = None if self.static_number_of_chunks is None: if self.implicit_mode: number_of_chunks, seed = len_data else: number_of_chunks, degree, seed = len_data self.number_of_chunks = xor_mask(number_of_chunks, number_of_chunks_len_format) else: if self.implicit_mode: seed, = len_data else: degree, seed = len_data seed = xor_mask(seed, seed_len_format) if degree is None: self.dist.set_seed(seed) degree = self.dist.getNumber() else: degree = xor_mask(degree, degree_len_format) used_packets = self.choose_packet_numbers(degree, seed=seed) data = packet[struct_len:crc_len] self.correct += 1 res = DecodePacket(data, used_packets, error_correction=self.error_correction, number_of_chunks=self.number_of_chunks) if used_packets.issubset({0}) and self.headerChunk is None and self.use_headerchunk: self.headerChunk = HeaderChunk(res) return res
def crc32(txt: typing.Union[bytes, str, bytearray], crc_len_format="L") -> bytes: crc = calc_crc(txt) packed = struct.pack("<" + str(len(txt)) + "s" + crc_len_format, txt, crc) return packed
def getNextValidPacket( self, from_multiple_files: bool = False, packet_len_format: str = "I", crc_len_format: str = "L", number_of_chunks_len_format: str = "I", quality_len_format: str = "I", epsilon_len_format: str = "f", check_block_number_len_format: str = "I" ) -> typing.Optional[OnlinePacket]: if not from_multiple_files: packet_len = self.f.read(struct.calcsize("<" + packet_len_format)) packet_len = struct.unpack("<" + packet_len_format, packet_len)[0] packet: bytes = self.f.read(int(packet_len)) else: packet = self.f.read() packet_len = len(packet) if not packet or not packet_len: # EOF self.EOF = True self.f.close() return None crc_len: typing.Optional[int] = struct.calcsize("<" + crc_len_format) if self.error_correction.__code__.co_name == crc32.__code__.co_name: payload = packet[:crc_len] crc = struct.unpack("<L", packet[crc_len:])[0] calced_crc = calc_crc(payload) if crc != calced_crc: # If the Packet is corrupt, try next one print("[-] CRC-Error - " + str(hex(crc)) + " != " + str(hex(calced_crc))) self.corrupt += 1 return self.getNextValidPacket(from_multiple_files) else: crc_len = None try: packet = self.error_correction(packet) except: self.corrupt += 1 return self.getNextValidPacket(from_multiple_files) struct_str: str = "<" + number_of_chunks_len_format + quality_len_format + epsilon_len_format + check_block_number_len_format struct_len: int = struct.calcsize(struct_str) data = packet[struct_len:crc_len] len_data: typing.Union[typing.Tuple[int, float, int], typing.Tuple[int, int, float, int]] = struct.unpack( struct_str, packet[0:struct_len]) if self.static_number_of_chunks is None: number_of_chunks, quality, self.epsilon, check_block_number = len_data self.number_of_chunks = xor_mask(number_of_chunks, number_of_chunks_len_format) else: quality, self.epsilon, check_block_number = len_data self.quality = xor_mask(quality, quality_len_format) if self.dist is None: self.dist = OnlineDistribution(self.epsilon) if self.correct == 0: # Create MockUp AuxBlocks with the given Pseudo-Random Number -> we will know which Packets are Encoded in which AuxBlock self.createAuxBlocks() self.correct += 1 res = OnlinePacket( data, self.number_of_chunks, self.quality, self.epsilon, check_block_number, read_only=True, crc_len_format=crc_len_format, number_of_chunks_len_format=number_of_chunks_len_format, quality_len_format=quality_len_format, epsilon_len_format=epsilon_len_format, check_block_number_len_format=check_block_number_len_format, save_number_of_chunks_in_packet=self.static_number_of_chunks is None) return res