Beispiel #1
0
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
Beispiel #2
0
 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
Beispiel #3
0
    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)
Beispiel #4
0
 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)
Beispiel #5
0
    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
Beispiel #6
0
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
Beispiel #7
0
    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