/** "Parsing function for custody signal bundles." [DTN2] */ public static boolean parse_custody_signal(data_t data, IByteBuffer bp, int len) { // "1 byte Admin Payload Type + Flags:" [DTN2] byte type_and_flag_byte = bp.get(); if (len < 1) { return false; } data.admin_type_ = admin_record_type_t.get((byte) (type_and_flag_byte >> 4)); data.admin_flags_ = (byte) (type_and_flag_byte & 0xf); len--; // "validate the admin type" [DTN2] if (data.admin_type_ != BundleProtocol.admin_record_type_t.ADMIN_CUSTODY_SIGNAL) { return false; } int status_flag_byte = bp.get(); // Success flag and reason code if (len < 1) { return false; } data.succeeded_ = (status_flag_byte & 0x80) > 0; data.reason_ = BundleProtocol.custody_signal_reason_t.get((byte) (status_flag_byte & 0x7f)); len--; // "Fragment SDNV Fields (offset & length), if present:" [DTN2] if ((data.admin_flags_ & BundleProtocol.admin_record_flags_t.ADMIN_IS_FRAGMENT.getCode()) > 0) { int[] value = new int[1]; int sdnv_bytes = SDNV.decode(bp, len, value); if (sdnv_bytes == -1) { return false; } len -= sdnv_bytes; data.set_orig_frag_offset(value[0]); sdnv_bytes = SDNV.decode(bp, len, value); if (sdnv_bytes == -1) { return false; } len -= sdnv_bytes; data.set_orig_frag_length(value[0]); } int ts_len; // The signal DTNTime ts_len = DTNTime.SDNV_decoding_len(bp); if (ts_len < 0) { return false; } DTNTime.decodeSDNV(data.custody_signal_tv(), bp); len -= ts_len; // Bundle Creation Timestamp ts_len = BundleTimestamp.SDNV_decoding_len(bp); if (ts_len < 0) { return false; } BundleTimestamp.decodeSDNV(data.orig_creation_tv(), bp); len -= ts_len; // Source Endpoint ID of Bundle int[] EID_len = new int[1]; int num_bytes = SDNV.decode(bp, len, EID_len); if (num_bytes == -1) { return false; } len -= num_bytes; if (len != EID_len[0]) { return false; } byte[] source_eid_bytes = new byte[EID_len[0]]; bp.get(source_eid_bytes); boolean ok = data.orig_source_eid_.assign(source_eid_bytes); if (!ok) { return false; } return true; }
/** "Constructor-like function to create a new custody signal bundle." [DTN2] */ public static Bundle create_custody_signal( final Bundle orig_bundle, final EndpointID source_eid, boolean succeeded, BundleProtocol.custody_signal_reason_t reason) { Bundle bundle = new Bundle(location_t.MEMORY); bundle.source().assign(source_eid); if (orig_bundle.custodian().equals(EndpointID.NULL_EID())) { Logger.getInstance() .error( TAG, String.format( "create_custody_signal(for bundle id %d): " + "custody signal cannot be generated due to custodian is null eid", orig_bundle.bundleid())); } bundle.dest().assign(orig_bundle.custodian()); bundle.replyto().assign(EndpointID.NULL_EID()); bundle.custodian().assign(EndpointID.NULL_EID()); bundle.set_is_admin(true); bundle.set_expiration(orig_bundle.expiration()); int sdnv_encoding_len = 0; int signal_len = 0; // "format of custody signals: // // 1 byte admin payload type and flags // 1 byte status code // SDNV [Fragment Offset (if present)] // SDNV [Fragment Length (if present)] // SDNVx2 Time of custody signal // SDNVx2 Copy of bundle X's Creation Timestamp // SDNV Length of X's source endpoint ID // vari Source endpoint ID of bundle X // // first calculate the length // // the non-optional, fixed-length fields above:" [DTN2] signal_len = 1 + 1; // "the 2 SDNV fragment fields:" [DTN2] if (orig_bundle.is_fragment()) { signal_len += SDNV.encoding_len(orig_bundle.frag_offset()); signal_len += SDNV.encoding_len(orig_bundle.orig_length()); } // "Time field, set to the current time:" [DTN2] DTNTime now = new DTNTime(); signal_len += DTNTime.SDNV_encoding_len(now); // "The bundle's creation timestamp:" [DTN2] signal_len += BundleTimestamp.SDNV_encoding_len(orig_bundle.creation_ts()); // the Source Endpoint ID length and value signal_len += SDNV.encoding_len(orig_bundle.source().length()) + orig_bundle.source().length(); // // "We got all the data ready, now format the buffer" [DTN2] // IByteBuffer bp = new SerializableByteBuffer(signal_len); int len = signal_len; bp.rewind(); // "Admin Payload Type and flags" [DTN2] byte type_and_flags_byte = (byte) (BundleProtocol.admin_record_type_t.ADMIN_CUSTODY_SIGNAL.getCode() << 4); if (orig_bundle.is_fragment()) { type_and_flags_byte |= BundleProtocol.admin_record_flags_t.ADMIN_IS_FRAGMENT.getCode(); } bp.put(type_and_flags_byte); len--; // Status_Flag_Byte consists of Success flag and reason code byte status_flag_byte = (byte) ((succeeded ? 1 : 0) << 7 | (reason.getCode() & 0x7f)); bp.put(status_flag_byte); len--; // "The 2 Fragment Fields" [DTN2] if (orig_bundle.is_fragment()) { sdnv_encoding_len = SDNV.encode(orig_bundle.frag_offset(), bp, len); assert (sdnv_encoding_len > 0); len -= sdnv_encoding_len; sdnv_encoding_len = SDNV.encode(orig_bundle.orig_length(), bp, len); assert (sdnv_encoding_len > 0); len -= sdnv_encoding_len; } // DTNTime which is a time of signal field sdnv_encoding_len = DTNTime.SDNV_encoding_len(now); assert (sdnv_encoding_len > 0); DTNTime.encodeSDNV(now, bp); len -= sdnv_encoding_len; // "Copy of bundle X's Creation Timestamp" [DTN2] sdnv_encoding_len = BundleTimestamp.SDNV_encoding_len(orig_bundle.creation_ts()); assert (sdnv_encoding_len > 0); BundleTimestamp.encodeSDNV(orig_bundle.creation_ts(), bp); len -= sdnv_encoding_len; // "The Endpoint ID length and data" [DTN2] sdnv_encoding_len = SDNV.encode(orig_bundle.source().length(), bp, len); assert (sdnv_encoding_len > 0); len -= sdnv_encoding_len; assert (len == orig_bundle.source().length()); bp.put(orig_bundle.source().byte_array()); // // "Finished generating the payload" [DTN2] // bp.rewind(); bundle.payload().set_data(bp, signal_len); return bundle; }