CustodySignal.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  * 2006 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 <oasys/util/ScratchBuffer.h>
00040 #include "CustodySignal.h"
00041 #include "SDNV.h"
00042 
00043 namespace dtn {
00044 
00045 void
00046 CustodySignal::create_custody_signal(Bundle*           bundle,
00047                                      const Bundle*     orig_bundle,
00048                                      const EndpointID& source_eid,
00049                                      bool              succeeded,
00050                                      reason_t          reason)
00051 {
00052     bundle->source_.assign(source_eid);
00053     if (orig_bundle->custodian_.equals(EndpointID::NULL_EID())) {
00054         PANIC("create_custody_signal(*%p): "
00055               "custody signal cannot be generated to null eid",
00056               orig_bundle);
00057     }
00058     bundle->dest_.assign(orig_bundle->custodian_);
00059     bundle->replyto_.assign(EndpointID::NULL_EID());
00060     bundle->custodian_.assign(EndpointID::NULL_EID());
00061     bundle->is_admin_ = true;
00062 
00063     // use the expiration time from the original bundle
00064     // XXX/demmer maybe something more clever??
00065     bundle->expiration_ = orig_bundle->expiration_;
00066 
00067     int sdnv_encoding_len = 0;
00068     int signal_len = 0;
00069     
00070     // we generally don't expect the Custody Signal length to be > 256 bytes
00071     oasys::ScratchBuffer<u_char*, 256> scratch;
00072     
00073     // format of custody signals:
00074     //
00075     // 1 byte admin payload type and flags
00076     // 1 byte status code
00077     // SDNV   [Fragment Offset (if present)]
00078     // SDNV   [Fragment Length (if present)]
00079     // 8 byte Time of custody signal
00080     // 8 byte Copy of bundle X's Creation Timestamp
00081     // SDNV   Length of X's source endpoint ID
00082     // vari   Source endpoint ID of bundle X
00083 
00084     //
00085     // first calculate the length
00086     //
00087 
00088     // the non-optional, fixed-length fields above:
00089     signal_len =  1 + 1 + 8 + 8;
00090 
00091     // the 2 SDNV fragment fields:
00092     if (orig_bundle->is_fragment_) {
00093         signal_len += SDNV::encoding_len(orig_bundle->frag_offset_);
00094         signal_len += SDNV::encoding_len(orig_bundle->orig_length_);
00095     }
00096 
00097     // the Source Endpoint ID length and value
00098     signal_len += SDNV::encoding_len(orig_bundle->source_.length()) +
00099                   orig_bundle->source_.length();
00100 
00101     //
00102     // now format the buffer
00103     //
00104     u_char* bp = scratch.buf(signal_len);
00105     int len = signal_len;
00106     
00107     // Admin Payload Type and flags
00108     *bp = (BundleProtocol::ADMIN_CUSTODY_SIGNAL << 4);
00109     if (orig_bundle->is_fragment_) {
00110         *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
00111     }
00112     bp++;
00113     len--;
00114     
00115     // Success flag and reason code
00116     *bp++ = ((succeeded ? 1 : 0) << 7) | (reason & 0x7f);
00117     len--;
00118     
00119     // The 2 Fragment Fields
00120     if (orig_bundle->is_fragment_) {
00121         sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset_, bp, len);
00122         ASSERT(sdnv_encoding_len > 0);
00123         bp  += sdnv_encoding_len;
00124         len -= sdnv_encoding_len;
00125         
00126         sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length_, bp, len);
00127         ASSERT(sdnv_encoding_len > 0);
00128         bp  += sdnv_encoding_len;
00129         len -= sdnv_encoding_len;
00130     }   
00131 
00132     // Time field, set to the current time:
00133     BundleTimestamp now;
00134     now.seconds_ = BundleTimestamp::get_current_time();
00135     now.seqno_   = 0;
00136     BundleProtocol::set_timestamp(bp, &now);
00137     len -= sizeof(u_int64_t);
00138     bp  += sizeof(u_int64_t);
00139 
00140     // Copy of bundle X's Creation Timestamp
00141     BundleProtocol::set_timestamp(bp, &orig_bundle->creation_ts_);
00142     len -= sizeof(u_int64_t);
00143     bp  += sizeof(u_int64_t);
00144     
00145     // The Endpoint ID length and data
00146     sdnv_encoding_len = SDNV::encode(orig_bundle->source_.length(), bp, len);
00147     ASSERT(sdnv_encoding_len > 0);
00148     len -= sdnv_encoding_len;
00149     bp  += sdnv_encoding_len;
00150     
00151     ASSERT((u_int)len == orig_bundle->source_.length());
00152     memcpy(bp, orig_bundle->source_.c_str(), orig_bundle->source_.length());
00153     
00154     // 
00155     // Finished generating the payload
00156     //
00157     bundle->payload_.set_data(scratch.buf(), signal_len);
00158 }
00159 
00160 bool
00161 CustodySignal::parse_custody_signal(data_t* data,
00162                                     const u_char* bp, u_int len)
00163 {
00164     // 1 byte Admin Payload Type + Flags:
00165     if (len < 1) { return false; }
00166     data->admin_type_  = (*bp >> 4);
00167     data->admin_flags_ = *bp & 0xf;
00168     bp++;
00169     len--;
00170 
00171     // validate the admin type
00172     if (data->admin_type_ != BundleProtocol::ADMIN_CUSTODY_SIGNAL) {
00173         return false;
00174     }
00175 
00176     // Success flag and reason code
00177     if (len < 1) { return false; }
00178     data->succeeded_ = (*bp >> 7);
00179     data->reason_    = (*bp & 0x7f);
00180     bp++;
00181     len--;
00182     
00183     // Fragment SDNV Fields (offset & length), if present:
00184     if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT)
00185     {
00186         int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
00187         if (sdnv_bytes == -1) { return false; }
00188         bp  += sdnv_bytes;
00189         len -= sdnv_bytes;
00190         
00191         sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
00192         if (sdnv_bytes == -1) { return false; }
00193         bp  += sdnv_bytes;
00194         len -= sdnv_bytes;
00195     }
00196 
00197     // The signal timestamp
00198     if (len < sizeof(u_int64_t)) { return false; }
00199     BundleProtocol::get_timestamp(&data->custody_signal_tv_, bp);
00200     bp  += sizeof(u_int64_t);
00201     len -= sizeof(u_int64_t);
00202 
00203     // Copy of the bundle's creation timestamp
00204     if (len < sizeof(u_int64_t)) { return false; }
00205     BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp);
00206     bp  += sizeof(u_int64_t);
00207     len -= sizeof(u_int64_t);
00208 
00209     // Source Endpoint ID of Bundle
00210     u_int64_t EID_len;
00211     int num_bytes = SDNV::decode(bp, len, &EID_len);
00212     if (num_bytes == -1) { return false; }
00213     bp  += num_bytes;
00214     len -= num_bytes;
00215 
00216     if (len != EID_len) { return false; }
00217     bool ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
00218     if (!ok) {
00219         return false;
00220     }
00221     
00222     return true;
00223 }
00224 
00225 const char*
00226 CustodySignal::reason_to_str(u_int8_t reason)
00227 {
00228     switch (reason) {
00229     case BundleProtocol::CUSTODY_NO_ADDTL_INFO:
00230         return "no additional info";
00231         
00232     case BundleProtocol::CUSTODY_REDUNDANT_RECEPTION:
00233         return "redundant reception";
00234         
00235     case BundleProtocol::CUSTODY_DEPLETED_STORAGE:
00236         return "depleted storage";
00237         
00238     case BundleProtocol::CUSTODY_ENDPOINT_ID_UNINTELLIGIBLE:
00239         return "eid unintelligible";
00240         
00241     case BundleProtocol::CUSTODY_NO_ROUTE_TO_DEST:
00242         return "no route to dest";
00243         
00244     case BundleProtocol::CUSTODY_NO_TIMELY_CONTACT:
00245         return "no timely contact";
00246         
00247     case BundleProtocol::CUSTODY_BLOCK_UNINTELLIGIBLE:
00248         return "block unintelligible";
00249     }
00250 
00251     static char buf[64];
00252     snprintf(buf, 64, "unknown reason %d", reason);
00253     return buf;
00254 }
00255 
00256 } // namespace dtn

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