def _handle_zfec_encode(_request, request_data): log = logging.getLogger("_handle_zfec_encode") log.debug("encode {0} bytes".format(len(request_data[0]))) encoder = Encoder(_min_segments, _num_segments) result_list = encoder.encode(request_data[0]) reply = { "message-type" : "zfec-encode-reply", "result" : "success", "padding-size" : _padding_size(request_data[0]), "error-message" : "" } return reply, result_list
def _handle_zfec_encode(_request, request_data): log = logging.getLogger("_handle_zfec_encode") log.debug("encode {0} bytes".format(len(request_data[0]))) encoder = Encoder(_min_segments, _num_segments) result_list = encoder.encode(request_data[0]) reply = { "message-type": "zfec-encode-reply", "result": "success", "padding-size": _padding_size(request_data[0]), "error-message": "" } return reply, result_list
def encode(self, data_blocks): """ data_blocks a list of data blocks to be encoded return a list size=num_segments of lists of encoded blocks (zfec shares) """ return_list = [list() for _ in range(self.num_segments)] encoder = Encoder(self.min_segments, self.num_segments) for data_block in data_blocks: for segment_list, zfec_share in zip(return_list, encoder.encode(data_block)): segment_list.append(zfec_share) return return_list
def encode(self, data): """ data data to be encoded return a list of num_segments of encoded zfec shares concatenated """ return_list = [list() for _ in range(self.num_segments)] encoder = Encoder(self.min_segments, self.num_segments) for data_slice in _slice_generator(data, block_size): for segment_list, zfec_share in zip( return_list, encoder.encode(data_slice) ): segment_list.append(zfec_share) return ["".join(sublist) for sublist in return_list]
def _handle_zfec_rebuild_encoded_shares(request, request_data): log = logging.getLogger("_handle_zfec_rebuild_encoded_shares") # first decode the good segments into the original data decoder = Decoder(_min_segments, _num_segments) zfec_segment_numbers = [n-1 for n in request["segment-numbers"]] decoded_block = decoder.decode(request_data, zfec_segment_numbers, request["padding-size"]) # now re-encode the block to get the missing segments encoder = Encoder(_min_segments, _num_segments) result_list = encoder.encode(decoded_block) reply = { "message-type" : "zfec-rebuild-encoded-shares-reply", "rebuilt-segment-numbers" : request["needed-segment-numbers"], "result" : "success", "error-message" : "" } log.debug("rebuilt {0}".format(reply["rebuilt-segment-numbers"])) return reply, [result_list[n-1] for n in request["needed-segment-numbers"]]
def _handle_zfec_rebuild_encoded_shares(request, request_data): log = logging.getLogger("_handle_zfec_rebuild_encoded_shares") # first decode the good segments into the original data decoder = Decoder(_min_segments, _num_segments) zfec_segment_numbers = [n - 1 for n in request["segment-numbers"]] decoded_block = decoder.decode(request_data, zfec_segment_numbers, request["padding-size"]) # now re-encode the block to get the missing segments encoder = Encoder(_min_segments, _num_segments) result_list = encoder.encode(decoded_block) reply = { "message-type": "zfec-rebuild-encoded-shares-reply", "rebuilt-segment-numbers": request["needed-segment-numbers"], "result": "success", "error-message": "" } log.debug("rebuilt {0}".format(reply["rebuilt-segment-numbers"])) return reply, [ result_list[n - 1] for n in request["needed-segment-numbers"] ]
def send(data, encryption_key, integrity_key, send_flag=0, id_=0x3f, possible_loss=.8): if len(data) % 16 != 0: LOGGER.error( "Length of data must be a multiple of 16. It is currently %s.", len(data)) return if int(send_flag) >= 2: # 1 bit long LOGGER.error("Send flag is too large: %s. It must be less than 2.", send_flag) return if possible_loss not in utils.FEC_LOSS: LOGGER.error("'possible_loss' must be one of these values: %s", utils.fec_loss) return if len(utils.FEC_LOSS) > 4: LOGGER.error( "FEC_LOSS list is too large: %s. It must be only 4 elements.", len(utils.FEC_LOSS)) return if id_ >= 64: # 6 bits long LOGGER.error("id is too large: %s. It must be less than 64.", id_) return iv_data = utils.generate_iv() global_sequence_data = struct.pack(utils.GLOBAL_SEQUENCE_FORMAT, int(time.time())) encrypted_data = utils.encrypt_message(key=encryption_key, iv=iv_data, message=data) mac_data = utils.hash_message(key=integrity_key, message=global_sequence_data + encrypted_data) # Convert from str to list of ints (bytearrays) iv_data = bytearray(iv_data) global_sequence_data = bytearray(global_sequence_data) encrypted_data = bytearray(encrypted_data) mac_data = bytearray(mac_data) LOGGER.debug("IV: %s", list(iv_data)) LOGGER.debug("Global sequence number: %s", list(global_sequence_data)) LOGGER.debug("Encrypted data: %s", list(encrypted_data)) LOGGER.debug("MAC: %s", list(mac_data)) all_data = iv_data + global_sequence_data + encrypted_data + mac_data # Add padding if len(all_data) % utils.TOTAL_DATA != 0: padding = utils.TOTAL_DATA - (len(all_data) % utils.TOTAL_DATA) all_data.extend(['\x00'] * padding) # Add FEC k = len(all_data) // utils.TOTAL_DATA m = int(math.ceil(round(k * (1 / (1 - possible_loss))) / 2) * 2) encoder = Encoder(k, m) encoded_data = encoder.encode(all_data) LOGGER.debug("Encoding data: k=%s, m=%s", k, m) all_encoded_data = bytearray() for x in encoded_data: all_encoded_data.extend(x) if len(all_data) % utils.TOTAL_DATA != 0: LOGGER.error("Total data must be divisible by %s. It's size is %s", utils.TOTAL_DATA, len(all_data)) return total_packets = len(all_encoded_data) // utils.TOTAL_DATA LOGGER.debug("Total packets: %s", total_packets) if total_packets % 2 != 0: LOGGER.error("Total number of packets must be even") return if total_packets >= 128: # 7 bits long LOGGER.error( "The data is too big and too many packets need to be sent.") return # iiii ii10 fnnt tttt t000 0000 header = (id_ << 18) + \ (0b10 << 16) + \ (int(send_flag) << 15) + \ (utils.FEC_LOSS.index(possible_loss) << 13) + \ ((total_packets >> 1) << 7) for sequence, group in enumerate( grouper(all_encoded_data, utils.TOTAL_DATA)): # iiii ii10 fnnt tttt tsss ssss packet_header = header + sequence src = SRC_MAC.format((packet_header & 0xFF0000) >> 16, (packet_header & 0x00FF00) >> 8, (packet_header & 0x0000FF), *group[:3]) dst = DST_MAC.format(*group[3:]) LOGGER.debug("Sending packet: Ether(src=%s, dst=%s)", src, dst) sendp(Ether(src=src, dst=dst)) time.sleep(.05)