BundleStatusReport.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include "BundleStatusReport.h"
00040 #include "SDNV.h"
00041 #include <netinet/in.h>
00042 #include <oasys/util/ScratchBuffer.h>
00043 
00044 namespace dtn {
00045 
00046 void
00047 BundleStatusReport::create_status_report(Bundle*           bundle,
00048                                          const Bundle*     orig_bundle,
00049                                          const EndpointID& source,
00050                                          flag_t            status_flags,
00051                                          reason_t          reason)
00052 {
00053     bundle->source_.assign(source);
00054     if (orig_bundle->replyto_.equals(EndpointID::NULL_EID())){
00055         bundle->dest_.assign(orig_bundle->source_);
00056     } else {
00057         bundle->dest_.assign(orig_bundle->replyto_);
00058     }
00059     bundle->replyto_.assign(EndpointID::NULL_EID());
00060     bundle->custodian_.assign(EndpointID::NULL_EID());
00061     
00062     bundle->is_admin_ = true;
00063 
00064     // use the expiration time from the original bundle
00065     // XXX/demmer maybe something more clever??
00066     bundle->expiration_ = orig_bundle->expiration_;
00067 
00068     // store the original bundle's source eid
00069     EndpointID orig_source(orig_bundle->source_);
00070 
00071     int sdnv_encoding_len = 0;  // use an int to handle -1 return values
00072     int report_length = 0;
00073     
00074     // we generally don't expect the Status Peport length to be > 256 bytes
00075     oasys::ScratchBuffer<u_char*, 256> scratch;
00076 
00077     //
00078     // Structure of bundle status reports:
00079     //
00080     // 1 byte Admin Payload type and flags
00081     // 1 byte Status Flags
00082     // 1 byte Reason Code
00083     // SDNV   [Fragment Offset (if present)]
00084     // SDNV   [Fragment Length (if present)]
00085     // 8 byte Time of {receipt/forwarding/delivery/deletion/custody/app-ack}
00086     //        of bundle X
00087     // 8 byte Copy of bundle X's Creation Timestamp
00088     // SDNV   Length of X's source endpoint ID
00089     // vari   Source endpoint ID of bundle X
00090 
00091     // note that the spec allows for all 6 of the "Time of..." fields
00092     // to be present in a single Status Report, but for this
00093     // implementation we will always have one and only one of the 6
00094     // timestamp fields
00095     // XXX/matt we may want to change to allow multiple-timestamps per SR
00096 
00097     // the non-optional, fixed-length fields above:
00098     report_length = 1 + 1 + 1 + 8 + 8;
00099 
00100     // the 2 SDNV fragment fields:
00101     if (orig_bundle->is_fragment_) {
00102         report_length += SDNV::encoding_len(orig_bundle->frag_offset_);
00103         report_length += SDNV::encoding_len(orig_bundle->orig_length_);
00104     }
00105 
00106     // the Source Endpoint ID:
00107     report_length += SDNV::encoding_len(orig_source.length()) + orig_source.length();
00108 
00109     //
00110     // Done calculating length, now create the report payload
00111     //
00112     
00113     u_char* bp = scratch.buf(report_length);
00114     int len = report_length;
00115     
00116     // Admin Payload Type and flags
00117     *bp = BundleProtocol::ADMIN_STATUS_REPORT << 4;
00118     if (orig_bundle->is_fragment_) {
00119         *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
00120     }
00121     bp++;
00122     len--;
00123     
00124     // Status Flags
00125     *bp++ = status_flags;
00126     len--;
00127 
00128     // Reason Code
00129     *bp++ = reason;
00130     len--;
00131     
00132     // The 2 Fragment Fields
00133     if (orig_bundle->is_fragment_) {
00134         sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset_, bp, len);
00135         ASSERT(sdnv_encoding_len > 0);
00136         bp  += sdnv_encoding_len;
00137         len -= sdnv_encoding_len;
00138         
00139         sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length_, bp, len);
00140         ASSERT(sdnv_encoding_len > 0);
00141         bp  += sdnv_encoding_len;
00142         len -= sdnv_encoding_len;
00143     }   
00144 
00145     // Time field, set to the current time (with no sub-second
00146     // accuracy defined at all)
00147     BundleTimestamp now;
00148     now.seconds_ = BundleTimestamp::get_current_time();
00149     now.seqno_   = 0;
00150     BundleProtocol::set_timestamp(bp, &now);
00151     len -= sizeof(u_int64_t);
00152     bp  += sizeof(u_int64_t);
00153 
00154     // Copy of bundle X's Creation Timestamp
00155     BundleProtocol::set_timestamp(bp, &orig_bundle->creation_ts_);
00156     len -= sizeof(u_int64_t);
00157     bp  += sizeof(u_int64_t);
00158     
00159     // The 2 Endpoint ID fields:
00160     sdnv_encoding_len = SDNV::encode(orig_source.length(), bp, len);
00161     ASSERT(sdnv_encoding_len > 0);
00162     len -= sdnv_encoding_len;
00163     bp  += sdnv_encoding_len;
00164     
00165     ASSERT((u_int)len == orig_source.length());
00166     memcpy(bp, orig_source.c_str(), orig_source.length());
00167     
00168     // 
00169     // Finished generating the payload
00170     //
00171     bundle->payload_.set_data(scratch.buf(), report_length);
00172 }
00173 
00178 bool BundleStatusReport::parse_status_report(data_t* data,
00179                                              const u_char* bp, u_int len)
00180 {
00181     // 1 byte Admin Payload Type + Flags:
00182     if (len < 1) { return false; }
00183     data->admin_type_  = (*bp >> 4);
00184     data->admin_flags_ = *bp & 0xf;
00185     bp++;
00186     len--;
00187 
00188     // validate the admin type
00189     if (data->admin_type_ != BundleProtocol::ADMIN_STATUS_REPORT) {
00190         return false;
00191     }
00192 
00193     // 1 byte Status Flags:
00194     if (len < 1) { return false; }
00195     data->status_flags_ = *bp++;
00196     len--;
00197     
00198     // 1 byte Reason Code:
00199     if (len < 1) { return false; }
00200     data->reason_code_ = *bp++;
00201     len--;
00202     
00203     // Fragment SDNV Fields (offset & length), if present:
00204     if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT) {
00205         int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
00206         if (sdnv_bytes == -1) { return false; }
00207         bp  += sdnv_bytes;
00208         len -= sdnv_bytes;
00209         sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
00210         if (sdnv_bytes == -1) { return false; }
00211         bp  += sdnv_bytes;
00212         len -= sdnv_bytes;
00213     }
00214 
00215     // The 6 Optional ACK Timestamps:
00216     
00217     if (data->status_flags_ & BundleProtocol::STATUS_RECEIVED) {
00218         if (len < sizeof(u_int64_t)) { return false; }
00219         BundleProtocol::get_timestamp(&data->receipt_tv_, bp);
00220         bp  += sizeof(u_int64_t);
00221         len -= sizeof(u_int64_t);
00222     }
00223 
00224     if (data->status_flags_ & BundleProtocol::STATUS_CUSTODY_ACCEPTED) {
00225         if (len < sizeof(u_int64_t)) { return false; }
00226         BundleProtocol::get_timestamp(&data->custody_tv_, bp);
00227         bp  += sizeof(u_int64_t);
00228         len -= sizeof(u_int64_t);
00229     }
00230 
00231     if (data->status_flags_ & BundleProtocol::STATUS_FORWARDED) {
00232         if (len < sizeof(u_int64_t)) { return false; }
00233         BundleProtocol::get_timestamp(&data->forwarding_tv_, bp);
00234         bp  += sizeof(u_int64_t);
00235         len -= sizeof(u_int64_t);
00236     }
00237 
00238     if (data->status_flags_ & BundleProtocol::STATUS_DELIVERED) {
00239         if (len < sizeof(u_int64_t)) { return false; }
00240         BundleProtocol::get_timestamp(&data->delivery_tv_, bp);
00241         bp  += sizeof(u_int64_t);
00242         len -= sizeof(u_int64_t);
00243     }
00244 
00245     if (data->status_flags_ & BundleProtocol::STATUS_DELETED) {
00246         if (len < sizeof(u_int64_t)) { return false; }
00247         BundleProtocol::get_timestamp(&data->deletion_tv_, bp);
00248         bp  += sizeof(u_int64_t);
00249         len -= sizeof(u_int64_t);
00250     }
00251 
00252     if (data->status_flags_ & BundleProtocol::STATUS_ACKED_BY_APP) {
00253         if (len < sizeof(u_int64_t)) { return false; }
00254         BundleProtocol::get_timestamp(&data->acknowledgement_tv_, bp);
00255         bp  += sizeof(u_int64_t);
00256         len -= sizeof(u_int64_t);
00257     }
00258 
00259     
00260     // Bundle Creation Timestamp
00261     if (len < sizeof(u_int64_t)) { return false; }
00262     BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp);
00263     bp  += sizeof(u_int64_t);
00264     len -= sizeof(u_int64_t);
00265 
00266     
00267     // EID of Bundle
00268     u_int64_t EID_len;
00269     int num_bytes = SDNV::decode(bp, len, &EID_len);
00270     if (num_bytes == -1) { return false; }
00271     bp  += num_bytes;
00272     len -= num_bytes;
00273 
00274     if (len != EID_len) { return false; }
00275     bool ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
00276     if (!ok) {
00277         return false;
00278     }
00279     
00280     return true;
00281 }
00282 
00283 } // namespace dtn

Generated on Fri Dec 22 14:47:58 2006 for DTN Reference Implementation by  doxygen 1.5.1