/** * Prepare function prepare bundle to generate. It adds Primary Block Info at the start of * xmit_blocks and add endpoint eids at the start of dictionary. * * @param bundle Bundle to prepare * @param xmit_blocks Empty xmit_blocks of the blundle * @param source Source endpoint id * @param link Link of the bundle * @param list Owner type * @return Return success message on success */ public int prepare( final Bundle bundle, BlockInfoVec xmit_blocks, final BlockInfo source, final Link link, list_owner_t list) { // There shouldn't already be anything in the xmit_blocks assert (xmit_blocks.size() == 0) : TAG + ": prepare() there shouldn't be anything already in xmit_blocks"; // Add EIDs to start off the dictionary xmit_blocks.dict().add_eid(bundle.dest()); xmit_blocks.dict().add_eid(bundle.source()); xmit_blocks.dict().add_eid(bundle.replyto()); xmit_blocks.dict().add_eid(bundle.custodian()); // make sure to add the primary to the front xmit_blocks.add(0, new BlockInfo(this, source)); return BP_SUCCESS; }
/** * Internal function get the total length of primary block to write on the buffer * * @param bundle Bundle to generate * @param dict Dictionary to get the offsets of the endpoint eids * @param primary PrimaryBlock data strucre object * @return Total numbers of Bytes required to write primary block */ protected static int get_primary_len(final Bundle bundle, Dictionary dict, PrimaryBlock primary) { int primary_len = 0; int block_len = 0; primary.set_dictionary_length(0); primary.set_block_length(0); /* * We need to figure out the total length of the primary block, * except for the SDNVs used to encode flags and the length itself and * the one byte version field. * * First, we determine the size of the dictionary by first * figuring out all the unique strings, and in the process, * remembering their offsets and summing up their lengths * (including the null terminator for each). */ dict.get_offsets(bundle.dest(), primary.dest_scheme_offset(), primary.dest_ssp_offset()); block_len += SDNV.encoding_len(primary.dest_scheme_offset()); block_len += SDNV.encoding_len(primary.dest_ssp_offset()); dict.get_offsets(bundle.source(), primary.source_scheme_offset(), primary.source_ssp_offset()); block_len += SDNV.encoding_len(primary.source_scheme_offset()); block_len += SDNV.encoding_len(primary.source_ssp_offset()); dict.get_offsets( bundle.replyto(), primary.replyto_scheme_offset(), primary.replyto_ssp_offset()); block_len += SDNV.encoding_len(primary.replyto_scheme_offset()); block_len += SDNV.encoding_len(primary.replyto_ssp_offset()); dict.get_offsets( bundle.custodian(), primary.custodian_scheme_offset(), primary.custodian_ssp_offset()); block_len += SDNV.encoding_len(primary.custodian_scheme_offset()); block_len += SDNV.encoding_len(primary.custodian_ssp_offset()); primary.set_dictionary_length(dict.dict_length()); block_len += SDNV.encoding_len(bundle.creation_ts().seconds()); block_len += SDNV.encoding_len(bundle.creation_ts().seqno()); block_len += SDNV.encoding_len(bundle.expiration()); block_len += SDNV.encoding_len(primary.dictionary_length_value()); block_len += primary.dictionary_length_value(); /* * If the bundle is a fragment, we need to include space for the * fragment offset and the original payload length. * * Note: Any changes to this protocol must be reflected into the * FragmentManager since it depends on this length when * calculating fragment sizes. */ if (bundle.is_fragment()) { block_len += SDNV.encoding_len(bundle.frag_offset()); block_len += SDNV.encoding_len(bundle.orig_length()); } // Format the processing flags. primary.set_processing_flags(format_bundle_flags(bundle)); primary.set_processing_flags(format_bundle_flags(bundle)); primary.set_processing_flags(primary.processing_flags_value() | format_cos_flags(bundle)); primary.set_processing_flags(primary.processing_flags_value() | format_srr_flags(bundle)); /* * Finally, add up the initial preamble and the variable * length part. */ primary.set_block_length(block_len); primary_len = (int) (1 + SDNV.encoding_len(primary.processing_flags) + SDNV.encoding_len(primary.block_length()) + primary.block_length_value()); Log.d(TAG, "get_primary_len: for bundleid = " + bundle.bundleid() + ": " + primary_len); // Fill in the remaining values of 'primary' just for the sake of returning // a complete data structure. primary.set_version(BundleProtocol.CURRENT_VERSION); primary.set_creation_time(bundle.creation_ts().seconds()); primary.set_creation_sequence(bundle.creation_ts().seqno()); primary.set_lifetime(bundle.expiration()); return primary_len; }
/** * This function consumes the primary block of the bundle. It is a virtual from BlockProcessor. * * @param bundle Bundle to set data after consuming * @param blcok Primary block to set data after consuming * @param buf Populated buffer to read data from for consuming * @param len Number of bytes to consume * @return Return number of bytes successfully consumed, In case of error return -1 */ public int consume(Bundle bundle, BlockInfo block, IByteBuffer buffer, int len) { int consumed = buffer.position(); PrimaryBlock primary = new PrimaryBlock(); // buf.position(0); assert (!block.complete()) : TAG + ": consume() block already complete"; Dictionary dict = bundle.recv_blocks().dict(); IByteBuffer byte_buffer_temp = new SerializableByteBuffer(len); // byte_buffer_temp = BufferHelper.reserve(byte_buffer_temp, len); block.set_contents(byte_buffer_temp); BufferHelper.copy_data( byte_buffer_temp, byte_buffer_temp.position(), buffer, buffer.position(), len); byte_buffer_temp.position(byte_buffer_temp.position() + len); IByteBuffer buf_block_content = block.contents(); int primary_len = len = buf_block_content.capacity() - buf_block_content.remaining(); buf_block_content.position(0); Log.d(TAG, " primary_len: " + primary_len + " : len:" + len); assert (primary_len == len) : TAG + ": consume() primary!=len"; primary.set_version(buf_block_content.get()); if (primary.version() != BundleProtocol.CURRENT_VERSION) { Log.e( TAG, String.format( "protocol version mismatch %s != %s", primary.version, BundleProtocol.CURRENT_VERSION)); return -1; } len -= 1; try { // Grab the SDNVs representing the flags and the block length. len -= read_sdnv(buf_block_content, primary.processing_flags()); len -= read_sdnv(buf_block_content, primary.block_length()); Log.d( TAG, String.format( "parsed primary block: version %s length %s", primary.version(), block.data_length())); // Parse the flags. parse_bundle_flags(bundle, primary.processing_flags_value()); parse_cos_flags(bundle, primary.processing_flags_value()); parse_srr_flags(bundle, primary.processing_flags_value()); // What remains in the buffer should now be equal to what the block-length // field advertised./ assert (len == block.data_length()) : TAG + ": consume() data and block length not equal"; // set data_offset block.set_data_offset(buf_block_content.position()); block.set_data_length((int) primary.block_length_value()); len -= read_sdnv(buf_block_content, primary.dest_scheme_offset()); len -= read_sdnv(buf_block_content, primary.dest_ssp_offset()); len -= read_sdnv(buf_block_content, primary.source_scheme_offset()); len -= read_sdnv(buf_block_content, primary.source_ssp_offset()); len -= read_sdnv(buf_block_content, primary.replyto_scheme_offset()); len -= read_sdnv(buf_block_content, primary.replyto_ssp_offset()); len -= read_sdnv(buf_block_content, primary.custodian_scheme_offset()); len -= read_sdnv(buf_block_content, primary.custodian_ssp_offset()); len -= read_sdnv(buf_block_content, primary.creation_time()); if (primary.creation_time_value() > Integer.MAX_VALUE) { Log.e( TAG, String.format( "creation timestamp time is too large: %s", primary.creation_time_value())); return -1; } len -= read_sdnv(buf_block_content, primary.creation_sequence()); if (primary.creation_sequence_value() > Integer.MAX_VALUE) { Log.e( TAG, String.format( "creation timestamp sequence is too large: %s", primary.creation_sequence())); return -1; } len -= read_sdnv(buf_block_content, primary.lifetime()); if (primary.lifetime_value() > Integer.MAX_VALUE) { Log.e(TAG, String.format("lifetime is too large: %s", primary.lifetime)); return -1; } len -= read_sdnv(buf_block_content, primary.dictionary_length()); // Make sure that the creation timestamp parts and the lifetime fit into // a 32 bit integer. bundle.set_creation_ts( new BundleTimestamp(primary.creation_time_value(), primary.creation_sequence_value())); bundle.set_expiration((int) primary.lifetime_value()); /* * Verify that we have the whole dictionary. */ if (len < primary.dictionary_length_value()) { Log.e( TAG, String.format("primary block advertised incorrect length %s", block.data_length())); return -1; } /* * Make sure that the dictionary ends with a null byte./ */ if (buf_block_content.get( (int) (buf_block_content.position() + primary.dictionary_length_value() - 1)) != '\0') { Log.e(TAG, "dictionary does not end with a NULL character! " + primary_len); return -1; } /* * Now use the dictionary buffer to parse out the various endpoint * identifiers, making sure that none of them peeks past the end * of the dictionary block. */ IByteBuffer dictionary = buf_block_content; len -= primary.dictionary_length_value(); Log.d(TAG, "Dict starting point :" + (primary_len - primary.dictionary_length_value())); // dictionary.position((int)(primary_len-primary.dictionary_length_value())); dict.set_dict(dictionary, (int) primary.dictionary_length_value()); Log.d(TAG, "Extract source :" + (primary_len - primary.dictionary_length_value())); if (!dict.extract_eid( bundle.source(), primary.source_scheme_offset(), primary.source_ssp_offset())) { Log.e(TAG, "Extract source fail:"); } else { block.eid_list().add(bundle.source()); Log.d(TAG, "Extract source :" + bundle.source().str()); } if (!dict.extract_eid( bundle.dest(), primary.dest_scheme_offset(), primary.dest_ssp_offset())) { Log.e(TAG, "Extract dest fail:"); } else { block.eid_list().add(bundle.dest()); Log.d(TAG, "Extract dest :" + bundle.dest().str()); } if (!dict.extract_eid( bundle.replyto(), primary.replyto_scheme_offset(), primary.replyto_ssp_offset())) { Log.e(TAG, "Extract reply fail :"); } else { block.eid_list().add(bundle.replyto()); Log.d(TAG, "Extract reply :" + bundle.replyto().str()); } if (!dict.extract_eid( bundle.custodian(), primary.custodian_scheme_offset(), primary.custodian_ssp_offset())) { Log.e(TAG, "Extract custodian fail:"); } else { block.eid_list().add(bundle.custodian()); Log.d(TAG, "Extract custodian :" + bundle.custodian().str()); } buf_block_content.position( (int) (buf_block_content.position() + primary.dictionary_length_value())); // If the bundle is a fragment, grab the fragment offset and original // bundle size (and make sure they fit in a 32 bit integer). if (bundle.is_fragment()) { int[] sdnv_buf = new int[1]; sdnv_buf[0] = 0; len -= read_sdnv(buf_block_content, sdnv_buf); if ((int) sdnv_buf[0] > Integer.MAX_VALUE) { Log.e(TAG, String.format("fragment offset is too large: %s", sdnv_buf)); return -1; } bundle.set_frag_offset(sdnv_buf[0]); sdnv_buf[0] = 0; len -= read_sdnv(buf_block_content, sdnv_buf); if (sdnv_buf[0] > Integer.MAX_VALUE) { Log.e(TAG, String.format("fragment original length is too large: %s", sdnv_buf)); return -1; } bundle.set_orig_length(sdnv_buf[0]); Log.d( TAG, String.format( TAG, "parsed fragmentation info: offset %s orig_len %s", bundle.frag_offset(), bundle.orig_length())); } Log.d(TAG, "primary_len: " + primary_len + " : ln" + len + ": Consumed" + consumed); block.set_complete(true); return primary_len - len; } catch (BlockProcessorTooShortException e) { // revert position buf_block_content.position(); return -1; } }
/** * Check the validity of the Primary block * * @param bundle Bundle to check the generic validity of block * @param block_list List of Blocks * @param block Block to check if it's valid or not * @param reception_reason If block is not valid then reception reason * @param deletion_reason If block is not balid then deletion reason * @return True if the block is valid else false */ public boolean validate( final Bundle bundle, BlockInfoVec block_list, BlockInfo block, status_report_reason_t[] reception_reason, status_report_reason_t[] deletion_reason) { // Make sure all four EIDs are valid. boolean eids_valid = true; eids_valid &= bundle.source().valid(); eids_valid &= bundle.dest().valid(); eids_valid &= bundle.custodian().valid(); eids_valid &= bundle.replyto().valid(); if (!eids_valid) { Log.e(TAG, "bad value for one or more EIDs"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } // According to BP section 3.3, there are certain things that a bundle // with a null source EID should not try to do. Check for these cases // and reject the bundle if any is true. Log.d(TAG, "Going to check null eid"); if (bundle.source().equals(EndpointID.NULL_EID())) { Log.d(TAG, "Inside of Going to check null eid"); if (bundle.receipt_requested() || bundle.app_acked_rcpt()) { Log.e(TAG, "bundle with null source eid has requested a report; reject it"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } if (bundle.custody_requested()) { Log.e(TAG, "bundle with null source eid has requested custody transfer; reject it"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } if (!bundle.do_not_fragment()) { Log.e( TAG, "bundle with null source eid has not set " + "'do-not-fragment' flag; reject it"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } } Log.d(TAG, "Out of Going to check null eid"); // Admin bundles cannot request custody transfer. if (bundle.is_admin()) { if (bundle.custody_requested()) { Log.e(TAG, "admin bundle requested custody transfer; reject it"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } if (bundle.receive_rcpt() || bundle.custody_rcpt() || bundle.forward_rcpt() || bundle.delivery_rcpt() || bundle.deletion_rcpt() || bundle.app_acked_rcpt()) { Log.e(TAG, "admin bundle has requested a report; reject it"); deletion_reason[0] = status_report_reason_t.REASON_BLOCK_UNINTELLIGIBLE; return false; } } return true; }