예제 #1
0
  /** "Return the total length of the formatted bundle block data." [DTN2] */
  public static int total_length(final BlockInfoVec blocks) {

    int ret = 0;
    Iterator<BlockInfo> itr = blocks.iterator();
    while (itr.hasNext()) {
      BlockInfo block = itr.next();
      ret += block.full_length();
    }
    return ret;
  }
예제 #2
0
  /** "Give the processors a chance to chew on the bundle after reloading from disk." [DTN2] */
  public static void reload_post_process(Bundle bundle) {
    BlockInfoVec recv_blocks = bundle.recv_blocks();

    Iterator<BlockInfo> iter = recv_blocks.iterator();
    while (iter.hasNext()) {
      // "allow BlockProcessors [and Ciphersuites] a chance to re-do
      // things needed after a load-from-store" [DTN2]
      BlockInfo block = iter.next();
      block.owner().reload_post_process(bundle, recv_blocks, block);
    }
  }
예제 #3
0
  /**
   * "Generate a BlockInfoVec for the outgoing link and put it into xmit_blocks_." [DTN2]
   *
   * @return a list of new BLockInfo
   */
  public static BlockInfoVec prepare_blocks(Bundle bundle, final Link link) {
    // "create a new block list for the outgoing link by first calling
    // prepare on all the BlockProcessor classes for the blocks that
    // arrived on the link" [DTN2]
    BlockInfoVec xmit_blocks = bundle.xmit_link_block_set().create_blocks(link);
    BlockInfoVec recv_blocks = bundle.recv_blocks();

    if (recv_blocks.size() > 0) {
      // "if there is a received block, the first one better be the primary"
      // [DTN2]
      assert (recv_blocks.front().type() == bundle_block_type_t.PRIMARY_BLOCK);

      Iterator<BlockInfo> iter = recv_blocks.iterator();
      while (iter.hasNext()) {
        BlockInfo block = iter.next();

        if (bundle.fragmented_incoming()
            && xmit_blocks.find_block(BundleProtocol.bundle_block_type_t.PAYLOAD_BLOCK) != null) {
          continue;
        }

        block
            .owner()
            .prepare(bundle, xmit_blocks, block, link, BlockInfo.list_owner_t.LIST_RECEIVED);
      }

    } else {
      BPF.getInstance().getBPFLogger().debug(TAG, "adding primary and payload block");
      BlockProcessor bp = find_processor(BundleProtocol.bundle_block_type_t.PRIMARY_BLOCK);
      bp.prepare(bundle, xmit_blocks, null, link, BlockInfo.list_owner_t.LIST_NONE);
      bp = find_processor(bundle_block_type_t.PAYLOAD_BLOCK);
      bp.prepare(bundle, xmit_blocks, null, link, BlockInfo.list_owner_t.LIST_NONE);
    }

    // "now we also make sure to prepare() on any registered processors
    // that don't already have a block in the output list. this
    // handles the case where we have a locally generated block with
    // nothing in the recv_blocks vector" [DTN2]

    Iterator<BlockProcessor> itr = processors_.iterator();
    while (itr.hasNext()) {
      BlockProcessor bp = itr.next();
      if (!xmit_blocks.has_block(bp.block_type())) {
        bp.prepare(bundle, xmit_blocks, null, link, BlockInfo.list_owner_t.LIST_NONE);
      }
    }

    // Now prepare security blocks
    BPF.getInstance().getBPFLogger().debug(TAG, "Now preparing security blocks...");
    Security.prepare_out_blocks(bundle, link, xmit_blocks);

    return xmit_blocks;
  }
예제 #4
0
  /**
   * "Temporary helper function to find the offset of the first byte of the payload in a
   * BlockInfoVec." [DTN2]
   */
  public static int payload_offset(final BlockInfoVec blocks) {

    int ret = 0;
    Iterator<BlockInfo> itr = blocks.iterator();
    while (itr.hasNext()) {
      BlockInfo block = itr.next();

      if (block.type() == BundleProtocol.bundle_block_type_t.PAYLOAD_BLOCK) {
        ret += block.data_offset();
        return ret;
      }

      ret += block.full_length();
    }

    return ret;
  }
예제 #5
0
  /**
   * "Copies out a chunk of formatted bundle data at a specified offset from the provided
   * BlockInfoVec." [DTN2]
   *
   * @return "the length of the chunk produced (up to the supplied length) and sets last to true if
   *     the bundle is complete." [DTN2]
   */
  public static int produce(
      final Bundle bundle,
      final BlockInfoVec blocks,
      IByteBuffer data,
      int offset,
      int len,
      boolean[] last) {

    int old_position = data.position();
    int origlen = len;
    last[0] = false;

    if (len == 0) return 0;

    assert (!blocks.isEmpty());

    Iterator<BlockInfo> iter = blocks.iterator();

    BlockInfo current_block = iter.next();
    // "advance past any blocks that are skipped by the given offset."[DTN2]
    while (offset >= current_block.full_length()) {

      BPF.getInstance()
          .getBPFLogger()
          .debug(
              TAG,
              String.format(
                  "BundleProtocol::produce skipping block type %s "
                      + "since offset %d >= block length %d",
                  current_block.type().toString(), offset, current_block.full_length()));

      offset -= current_block.full_length();
      current_block = iter.next();
    }
    // "the offset value now should be within the current block" [DTN2]

    while (true) {
      // The first time remainder will be minus from leftover offset above
      // but later on it will be the full content of the block
      int remainder = current_block.full_length() - offset;
      int tocopy = Math.min(len, remainder);
      BPF.getInstance()
          .getBPFLogger()
          .debug(
              TAG,
              String.format(
                  "BundleProtocol::produce copying %d/%d bytes from "
                      + "block type %s at offset %d",
                  tocopy, remainder, current_block.type().toString(), offset));

      current_block.owner().produce(bundle, current_block, data, offset, tocopy);

      len -= tocopy;

      // move the position of IByteBuffer
      data.position(data.position() + tocopy);

      // "if we've copied out the full amount the user asked for,
      // we're done. note that we need to check the corner case
      // where we completed the block exactly to properly set the
      // last bit" [DTN2]
      if (len == 0) {
        if ((tocopy == remainder)
            && ((current_block.flags()
                    & BundleProtocol.block_flag_t.BLOCK_FLAG_LAST_BLOCK.getCode())
                > 0)) {

          last[0] = true;
        }

        break;
      }

      // "we completed the current block, so we're done if this
      // is the last block, even if there's space in the user buffer"
      // [DTN2]
      assert (tocopy == remainder);
      if ((current_block.flags() & BundleProtocol.block_flag_t.BLOCK_FLAG_LAST_BLOCK.getCode())
          > 0) {

        last[0] = true;
        break;
      }

      // advance to next block
      current_block = iter.next();
      offset = 0;
    }

    BPF.getInstance()
        .getBPFLogger()
        .debug(
            TAG,
            String.format(
                "BundleProtocol::produce complete: "
                    + "produced %d bytes, bundle id %d, status is  %s",
                origlen - len, bundle.bundleid(), last[0] ? "complete" : "not complete"));

    data.position(old_position);
    return origlen - len;
  }