Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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"]
    ]
Ejemplo n.º 5
0
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)