예제 #1
0
 def input_new_packet(self, packet: RU10Packet):
     """
     Removes auxpackets (LDPC and Half) and adds the remaining data to the GEPP matrix.
     :param packet: A Packet to add to the GEPP matrix
     :return: True: If solved. False: Else.
     """
     if self.auxBlocks == dict() and self.dist is None:  # self.isPseudo and
         self.dist = RaptorDistribution(self.number_of_chunks)
         self.number_of_chunks = packet.get_total_number_of_chunks()
         _, self.s, self.h = intermediate_symbols(self.number_of_chunks,
                                                  self.dist)
         self.createAuxBlocks()
     # we need to do it twice sine half symbols may contain ldpc symbols (which by definition are repair codes.)
     if self.debug:
         print("----")
         print("Id = " + str(packet.id))
         print(packet.used_packets)
     removed = self.removeAndXorAuxPackets(packet)
     if self.debug:
         print(from_true_false_list(removed))
         print(packet.get_error_correction())
         print("----")
     packet.set_used_packets(set(from_true_false_list(removed)))
     if self.count:
         for i in range(len(removed)):
             if i in self.counter.keys():
                 if removed[i]:
                     self.counter[i] += 1
             else:
                 self.counter[i] = 1
     self.addPacket(packet)
     return self.updatePackets(packet)
예제 #2
0
 def removeAndXorAuxPackets(self, packet: RU10Packet):
     """
     Removes auxpackets (LDCP and Half) from a given packet to get the packets data.
     :param packet: Packet to remove auxpackets from
     :return: The data without the auxpackets
     """
     aux_mapping = self.getHalfPacketListFromPacket(
         packet)  # Enthaelt Data + LDPC Nummern
     aux_mapping.append(packet.get_bool_array_used_and_ldpc_packets())
     xored_list = logical_xor(aux_mapping)
     del aux_mapping
     tmp = from_true_false_list(
         xored_list)  # Nur noch Data + LDPC sind vorhanden
     if self.debug:
         print(tmp)
     tmp = RU10Packet("",
                      tmp,
                      self.number_of_chunks,
                      packet.id,
                      packet.dist,
                      read_only=True)
     aux_mapping = self.getAuxPacketListFromPacket(tmp)
     aux_mapping.append(
         tmp.get_bool_array_used_packets())  # [-len(self.auxBlocks):])
     res = logical_xor(aux_mapping)
     del tmp, aux_mapping
     return res
예제 #3
0
 def input_new_packet(self, packet: RU10Packet):
     """
     Removes auxpackets (LDPC and Half) and adds the remaining data to the GEPP matrix.
     :param packet: A Packet to add to the GEPP matrix
     :return: True: If solved. False: Else.
     """
     if self.ldpcANDhalf == dict(
     ) and self.distribution is None:  # self.isPseudo and
         self.distribution = RaptorDistribution(self.number_of_chunks)
         self.number_of_chunks = packet.get_total_number_of_chunks()
         _, self.s, self.h = intermediate_symbols(self.number_of_chunks,
                                                  self.distribution)
         self.createAuxBlocks()
         self.progress_bar = self.create_progress_bar(
             self.number_of_chunks + 0.02 * self.number_of_chunks)
     # we need to do it twice sine half symbols may contain ldpc symbols (which by definition are repair codes.)
     if self.debug:
         print("----")
         print("Id = " + str(packet.id))
         print(packet.used_packets)
     removed = self.removeAndXorAuxPackets(packet)
     if self.debug:
         print(from_true_false_list(removed))
         print(packet.get_error_correction())
         print("----")
     if self.count:
         for i in range(len(removed)):
             if i in self.counter.keys():
                 if removed[i]:
                     self.counter[i] += 1
             else:
                 self.counter[i] = 1
     if self.GEPP is None:
         self.GEPP = GEPP(
             np.array([removed], dtype=bool),
             np.array([[packet.get_data()]], dtype=bytes),
         )
     else:
         self.GEPP.addRow(
             np.array(removed, dtype=bool),
             np.frombuffer(packet.get_data(), dtype="uint8"),
         )
     if (self.isPseudo or not self.read_all_before_decode
         ) and self.GEPP.isPotentionallySolvable():
         # and self.GEPP.n % 5 == 0:  # Nur alle 5 Packete versuch starten
         if self.debug:
             print("current size: " + str(self.GEPP.n))
         return self.GEPP.solve(partial=False)
     return False
예제 #4
0
 def getHalfPacketListFromPacket(
         self, packet: RU10Packet) -> typing.List[typing.List[bool]]:
     """
     Generates a list of halfpackets from a packet.
     :param packet: The packet to get the list from
     :return: List of halfpackets
     """
     res: typing.List[typing.List[bool]] = []
     aux_used_packets = packet.get_bool_array_half_packets()
     for i in range(len(aux_used_packets)):
         if aux_used_packets[i]:
             res.append(
                 (self.auxBlocks[packet.get_number_of_ldpc_blocks() +
                                 i].get_bool_array_used_and_ldpc_packets()))
     return res
예제 #5
0
 def getAuxPacketListFromPacket(self, packet: RU10Packet):
     """
     Creates a list for a packet with information about whether auxpackets have been used for that packet.
     :param packet: The packet to check.
     :return: Information about used auxpackets.
     """
     res = []
     aux_used_packets = packet.get_bool_array_repair_packets()
     for i in range(len(aux_used_packets)):
         if aux_used_packets[i]:
             res.append((self.ldpcANDhalf[i].get_bool_array_used_packets()))
     return res
예제 #6
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)
예제 #7
0
 def parallel_to_normal(par_packet,
                        error_correction,
                        dist,
                        quality=7,
                        epsilon=0.06):
     """
     Converts parallel packets either to RU10Packets, normal Packets or OnlinePackets based on the original class of
     the packet.
     :param par_packet:
     :param error_correction:
     :param dist:
     :param quality:
     :param epsilon:
     :return: Converted packet
     """
     if par_packet.get_org_class() == "RU10Packet":
         packet = RU10Packet(
             data=par_packet.data,
             used_packets=par_packet.used_packets,
             total_number_of_chunks=par_packet.total_number_of_chunks,
             id=par_packet.id,
             dist=dist,
             error_correction=error_correction,
             packet_len_format=par_packet.packet_len_format,
             crc_len_format=par_packet.crc_len_format,
             number_of_chunks_len_format=par_packet.
             number_of_chunks_len_format,
             id_len_format=par_packet.id_len_format,
             save_number_of_chunks_in_packet=par_packet.
             safe_number_of_chunks_in_packet)
         packet.error_prob = par_packet.error_prob
     elif par_packet.get_org_class() == "Packet":
         packet = Packet(
             data=par_packet.data,
             used_packets=par_packet.used_packets,
             total_number_of_chunks=par_packet.total_number_of_chunks,
             error_correction=error_correction,
             packet_len_format=par_packet.packet_len_format,
             crc_len_format=par_packet.crc_len_format,
             number_of_chunks_len_format=par_packet.
             number_of_chunks_len_format,
             id_len_format=par_packet.id_len_format)
         packet.error_prob = par_packet.error_prob
     elif par_packet.get_org_class() == "OnlinePacket":
         packet = OnlinePacket(
             data=par_packet.data,
             used_packets=par_packet.used_packets,
             check_block_number=par_packet.id,
             total_number_of_chunks=par_packet.total_number_of_chunks,
             error_correction=error_correction,
             dist=dist,
             quality=quality,
             epsilon=epsilon,
             crc_len_format=par_packet.crc_len_format,
             number_of_chunks_len_format=par_packet.
             number_of_chunks_len_format,
             check_block_number_len_format=par_packet.id_len_format)
         packet.error_prob = par_packet.error_prob
     else:
         raise RuntimeError("Unsupported packet type")
     return packet
예제 #8
0
 def create_new_packet_from_chunks(
         self,
         method: str,
         systematic: bool = False,
         seed: typing.Optional[int] = None,
         window: int = 0) -> typing.Optional[RU10Packet]:
     """
     Creates a new packet only using chunks based on the choosen method. You can use "even" or "odd" which
     basically uses chunks with even or odd numbers. "window_30" and "window_40" are methods, that split the whole
     chunklist into windows with 30 or 40 chunks overlapping by 10 chunks for each window. "window" says what window
     the packet should be generated for, starting with 0 for the window that contains the first 30 or 40 chunks.
     The packets will be added to the encoders packets and can be saved with the save_packets method like normal
     packets. To decode the packets set use_method = True while creating a decoder.
     :param method:
     :param systematic:
     :param seed:
     :param window:
     :return: A new RU10Packet
     """
     if method == "window_30":
         window_size = 30
         start = window * (window_size - 10)
         if start > self.number_of_chunks:
             print("Please select a valid window.")
             return None
         chunk_lst: typing.List[int] = [
             ch for ch in range(start, start + window_size)
             if ch <= self.number_of_chunks
         ]
     elif method == "window_40":
         window_size = 40
         start = window * (window_size - 10)
         if start > self.number_of_chunks:
             print("Please select a valid window.")
             return None
         chunk_lst = [
             ch for ch in range(start, start + window_size)
             if ch <= self.number_of_chunks
         ]
     elif method == "even":
         chunk_lst = [
             ch for ch in range(0, self.number_of_chunks + 1) if ch % 2 == 0
         ]
     elif method == "odd":
         chunk_lst = [
             ch for ch in range(0, self.number_of_chunks + 1) if ch % 2 != 0
         ]
     else:
         raise RuntimeError(
             "Please select a valid method (even, odd, window (including window_size and start_ind)"
         )
     if seed is None:
         seed = self.generate_new_id()
     packet_numbers = choose_packet_numbers(len(chunk_lst),
                                            seed,
                                            self.dist,
                                            systematic=systematic,
                                            max_l=len(chunk_lst))
     packets = [self.chunks[chunk_lst[i]] for i in packet_numbers]
     packet = RU10Packet(
         listXOR(packets), [chunk_lst[i] for i in packet_numbers],
         self.number_of_chunks,
         seed,
         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,
         method=method,
         window=window,
         prepend=self.prepend,
         append=self.append)
     self.encodedPackets.add(packet)
     return packet
예제 #9
0
def __handle_raptor(packet: RU10Packet):
    p_decoder = RU10Decoder.pseudo_decoder(packet.get_total_number_of_chunks())
    p_decoder.input_new_packet(packet)
    return p_decoder.removeAndXorAuxPackets(packet)
예제 #10
0
    def parse_raw_packet(
            self,
            packet,
            crc_len_format: str = "L",
            number_of_chunks_len_format: str = "L",
            packet_len_format: str = "I",
            id_len_format: str = "L") -> typing.Union[RU10Packet, str]:
        """
        Creates a RU10 packet from a raw given packet. Also checks if the packet is corrupted. If any method was used to
        create packets from specific chunks, set self.use_method = True. This will treat the last byte of the raw packet
        data as the byte that contains the information about the used method ("even", "odd", "window_30 + window" or
        "window_40 + window". See RU10Encoder.create_new_packet_from_chunks for further information.
        :param packet: A raw packet
        :param packet_len_format: Format of the packet length
        :param crc_len_format:  Format of the crc length
        :param number_of_chunks_len_format: Format of the number of chunks length
        :param id_len_format: Format of the ID length
        :return: RU10Packet or an error message
        """
        struct_str = "<" + number_of_chunks_len_format + id_len_format
        struct_len = struct.calcsize(struct_str)
        """"
        if self.error_correction.__code__.co_name == crc32.__code__.co_name:
            crc_len = -struct.calcsize("<" + crc_len_format)
            payload = packet[:crc_len]
            crc = 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 "CORRUPT"
    
        else:
        """
        try:
            packet = self.error_correction(packet)
        except:
            self.corrupt += 1
            return "CORRUPT"

        data = packet[struct_len:]
        if self.use_method:
            method_data = bin(data[-1])[2:]
            while len(method_data) < 8:
                method_data = '0' + method_data
            data = data[:-1]
            if method_data.startswith('00'):
                chunk_lst = [
                    ch for ch in range(0, self.number_of_chunks + 1)
                    if ch % 2 == 0
                ]
            elif method_data.startswith('01'):
                chunk_lst = [
                    ch for ch in range(0, self.number_of_chunks + 1)
                    if ch % 2 != 0
                ]
            elif method_data.startswith('10'):
                window = int(method_data[2:], 2)
                window_size = 30
                start = window * (window_size - 10)
                chunk_lst = [
                    ch for ch in range(start, start + window_size)
                    if ch <= self.number_of_chunks
                ]
            elif method_data.startswith('11'):
                window = int(method_data[2:], 2)
                window_size = 40
                start = window * (window_size - 10)
                chunk_lst = [
                    ch for ch in range(start, start + window_size)
                    if ch <= self.number_of_chunks
                ]
            else:
                raise RuntimeError(f"Invalid method_data: %s" % method_data)
        len_data = struct.unpack(struct_str, packet[0:struct_len])
        if self.static_number_of_chunks is None:
            self.number_of_chunks = xor_mask(len_data[0],
                                             number_of_chunks_len_format)
            unxored_id = xor_mask(len_data[1], id_len_format)
        else:
            unxored_id = xor_mask(len_data[0], id_len_format)
        if self.dist is None:
            self.dist = RaptorDistribution(self.number_of_chunks)
            _, self.s, self.h = intermediate_symbols(self.number_of_chunks,
                                                     self.dist)

        if self.correct == 0:
            self.createAuxBlocks()
        self.correct += 1
        if self.use_method:
            numbers = choose_packet_numbers(len(chunk_lst),
                                            unxored_id,
                                            self.dist,
                                            systematic=False,
                                            max_l=len(chunk_lst))
            used_packets = set([chunk_lst[i] for i in numbers])
        else:
            used_packets = set(
                choose_packet_numbers(self.number_of_chunks,
                                      unxored_id,
                                      self.dist,
                                      systematic=False))
        res = RU10Packet(
            data,
            used_packets,
            self.number_of_chunks,
            unxored_id,
            read_only=True,
            packet_len_format=packet_len_format,
            crc_len_format=crc_len_format,
            number_of_chunks_len_format=number_of_chunks_len_format,
            id_len_format=id_len_format,
            save_number_of_chunks_in_packet=self.static_number_of_chunks is
            None)
        return res