Esempio n. 1
0
  /**
   * "Generate contents for the given BlockInfoVec on the given Link." [DTN2]
   *
   * @return "the total length of the formatted blocks for this bundle." [DTN2]
   */
  public static int generate_blocks(Bundle bundle, BlockInfoVec blocks, final Link link) {
    // "now assert there's at least 2 blocks (primary + payload) and
    // that the primary is first" [DTN2]
    assert (blocks.size() >= 2);
    assert (blocks.front().type() == bundle_block_type_t.PRIMARY_BLOCK);

    // "now we make a pass through the list and call generate on
    // each block processor" [DTN2]

    for (int i = 0; i < blocks.size(); i++) {
      boolean last = i == blocks.size() - 1;

      BlockInfo iter = blocks.get(i);

      iter.owner().generate(bundle, blocks, iter, link, last);

      BPF.getInstance()
          .getBPFLogger()
          .debug(
              TAG,
              String.format(
                  "generated block (owner %s type %s) "
                      + "data_offset %d data_length %d , contents_length %d",
                  iter.owner().block_type(),
                  iter.type(),
                  iter.data_offset(),
                  iter.data_length(),
                  iter.contents().position()));

      if (last) {
        assert ((iter.flags() & BundleProtocol.block_flag_t.BLOCK_FLAG_LAST_BLOCK.getCode()) != 0);
      } else {
        assert ((iter.flags() & BundleProtocol.block_flag_t.BLOCK_FLAG_LAST_BLOCK.getCode()) == 0);
      }
    }

    // "Now that all the EID references are added to the dictionary,
    // generate the primary block." [DTN2]
    PrimaryBlockProcessor pbp =
        (PrimaryBlockProcessor) find_processor(BundleProtocol.bundle_block_type_t.PRIMARY_BLOCK);
    assert (blocks.front().owner() == pbp);
    pbp.generate_primary(bundle, blocks, blocks.front());

    // "make a final pass through, calling finalize() and extracting
    // the block length" [DTN2]
    int total_len = 0;
    for (int i = blocks.size() - 1; i >= 0; i--) {
      BlockInfo iter = blocks.get(i);
      iter.owner().finalize(bundle, blocks, iter, link);
      total_len += iter.full_length();
    }

    return total_len;
  }
Esempio n. 2
0
  /**
   * "Parse the supplied chunk of arriving data and append it to the rcvd_blocks_ list in the given
   * bundle, finding the appropriate BlockProcessor element and calling its receive() handler.
   *
   * <p>When called repeatedly for arriving chunks of data, this properly fills in the entire
   * bundle, including the in_blocks_ record of the arriving blocks and the payload (which is stored
   * externally)." [DTN2]
   *
   * @return "the length of data consumed or -1 on protocol error, plus sets last to true if the
   *     bundle is complete." [DTN2]
   */
  public static int consume(Bundle bundle, IByteBuffer data, int len, boolean[] last) {

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

    BlockInfoVec recv_blocks = bundle.recv_blocks();

    // "special case for first time we get called, since we need to
    // create a BlockInfo struct for the primary block without knowing
    // the typecode or the length" [DTN2]
    if (recv_blocks.isEmpty()) {
      BPF.getInstance()
          .getBPFLogger()
          .debug(TAG, "consume: got first block... " + "creating primary block info");
      recv_blocks.append_block(find_processor(bundle_block_type_t.PRIMARY_BLOCK), null);
    }

    // "loop as long as there is data left to process" [DTN2]
    while (len != 0) {
      BPF.getInstance()
          .getBPFLogger()
          .debug(TAG, String.format("consume: %d bytes left to process", len));
      BlockInfo info = recv_blocks.back();

      // "if the last received block is complete, create a new one
      // and push it onto the vector. at this stage we consume all
      // blocks, even if there's no BlockProcessor that understands
      // how to parse it" [DTN2]
      if (info.complete()) {
        data.mark();
        byte bundle_block_type_byte = data.get();
        bundle_block_type_t type = bundle_block_type_t.get(bundle_block_type_byte);
        data.reset();
        info = recv_blocks.append_block(find_processor(type), null);
        BPF.getInstance()
            .getBPFLogger()
            .debug(
                TAG,
                String.format(
                    "consume: previous block complete, " + "created new BlockInfo type %s",
                    info.owner().block_type()));
      }

      // "now we know that the block isn't complete, so we tell it to
      // consume a chunk of data" [DTN2]
      BPF.getInstance()
          .getBPFLogger()
          .debug(
              TAG,
              String.format(
                  "consume: block processor %s type %s incomplete, "
                      + "calling consume (%d bytes already buffered)",
                  info.owner().block_type(), info.type(), info.contents().position()));

      int cc = info.owner().consume(bundle, info, data, len);
      if (cc < 0) {
        BPF.getInstance()
            .getBPFLogger()
            .error(TAG, String.format("consume: protocol error handling block %s", info.type()));
        return -1;
      }

      // "decrement the amount that was just handled from the overall
      // total. verify that the block was either completed or
      // consumed all the data that was passed in." [DTN2]
      len -= cc;
      data.position(data.position() + cc);

      BPF.getInstance()
          .getBPFLogger()
          .debug(
              TAG,
              String.format(
                  "consume: consumed %d bytes of block type %s (%s)",
                  cc, info.type(), info.complete() ? "complete" : "not complete"));

      if (info.complete()) {
        // check if we're done with the bundle
        if ((info.flags() & block_flag_t.BLOCK_FLAG_LAST_BLOCK.getCode()) > 0) {
          last[0] = true;
          break;
        }

      } else {
        assert (len == 0);
      }
    }

    BPF.getInstance()
        .getBPFLogger()
        .debug(
            TAG,
            String.format(
                "bundle id %d consume completed, %d/%d bytes consumed %s",
                bundle.bundleid(), origlen - len, origlen, last[0] ? "(completed bundle)" : ""));

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