CustodySignal.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 
00018 #include <oasys/util/ScratchBuffer.h>
00019 #include "CustodySignal.h"
00020 #include "SDNV.h"
00021 
00022 namespace dtn {
00023 
00024 void
00025 CustodySignal::create_custody_signal(Bundle*           bundle,
00026                                      const Bundle*     orig_bundle,
00027                                      const EndpointID& source_eid,
00028                                      bool              succeeded,
00029                                      reason_t          reason)
00030 {
00031     bundle->source_.assign(source_eid);
00032     if (orig_bundle->custodian_.equals(EndpointID::NULL_EID())) {
00033         PANIC("create_custody_signal(*%p): "
00034               "custody signal cannot be generated to null eid",
00035               orig_bundle);
00036     }
00037     bundle->dest_.assign(orig_bundle->custodian_);
00038     bundle->replyto_.assign(EndpointID::NULL_EID());
00039     bundle->custodian_.assign(EndpointID::NULL_EID());
00040     bundle->is_admin_ = true;
00041 
00042     // use the expiration time from the original bundle
00043     // XXX/demmer maybe something more clever??
00044     bundle->expiration_ = orig_bundle->expiration_;
00045 
00046     int sdnv_encoding_len = 0;
00047     int signal_len = 0;
00048     
00049     // we generally don't expect the Custody Signal length to be > 256 bytes
00050     oasys::ScratchBuffer<u_char*, 256> scratch;
00051     
00052     // format of custody signals:
00053     //
00054     // 1 byte admin payload type and flags
00055     // 1 byte status code
00056     // SDNV   [Fragment Offset (if present)]
00057     // SDNV   [Fragment Length (if present)]
00058     // 8 byte Time of custody signal
00059     // 8 byte Copy of bundle X's Creation Timestamp
00060     // SDNV   Length of X's source endpoint ID
00061     // vari   Source endpoint ID of bundle X
00062 
00063     //
00064     // first calculate the length
00065     //
00066 
00067     // the non-optional, fixed-length fields above:
00068     signal_len =  1 + 1 + 8 + 8;
00069 
00070     // the 2 SDNV fragment fields:
00071     if (orig_bundle->is_fragment_) {
00072         signal_len += SDNV::encoding_len(orig_bundle->frag_offset_);
00073         signal_len += SDNV::encoding_len(orig_bundle->orig_length_);
00074     }
00075 
00076     // the Source Endpoint ID length and value
00077     signal_len += SDNV::encoding_len(orig_bundle->source_.length()) +
00078                   orig_bundle->source_.length();
00079 
00080     //
00081     // now format the buffer
00082     //
00083     u_char* bp = scratch.buf(signal_len);
00084     int len = signal_len;
00085     
00086     // Admin Payload Type and flags
00087     *bp = (BundleProtocol::ADMIN_CUSTODY_SIGNAL << 4);
00088     if (orig_bundle->is_fragment_) {
00089         *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
00090     }
00091     bp++;
00092     len--;
00093     
00094     // Success flag and reason code
00095     *bp++ = ((succeeded ? 1 : 0) << 7) | (reason & 0x7f);
00096     len--;
00097     
00098     // The 2 Fragment Fields
00099     if (orig_bundle->is_fragment_) {
00100         sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset_, bp, len);
00101         ASSERT(sdnv_encoding_len > 0);
00102         bp  += sdnv_encoding_len;
00103         len -= sdnv_encoding_len;
00104         
00105         sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length_, bp, len);
00106         ASSERT(sdnv_encoding_len > 0);
00107         bp  += sdnv_encoding_len;
00108         len -= sdnv_encoding_len;
00109     }   
00110 
00111     // Time field, set to the current time:
00112     BundleTimestamp now;
00113     now.seconds_ = BundleTimestamp::get_current_time();
00114     now.seqno_   = 0;
00115     BundleProtocol::set_timestamp(bp, &now);
00116     len -= sizeof(u_int64_t);
00117     bp  += sizeof(u_int64_t);
00118 
00119     // Copy of bundle X's Creation Timestamp
00120     BundleProtocol::set_timestamp(bp, &orig_bundle->creation_ts_);
00121     len -= sizeof(u_int64_t);
00122     bp  += sizeof(u_int64_t);
00123     
00124     // The Endpoint ID length and data
00125     sdnv_encoding_len = SDNV::encode(orig_bundle->source_.length(), bp, len);
00126     ASSERT(sdnv_encoding_len > 0);
00127     len -= sdnv_encoding_len;
00128     bp  += sdnv_encoding_len;
00129     
00130     ASSERT((u_int)len == orig_bundle->source_.length());
00131     memcpy(bp, orig_bundle->source_.c_str(), orig_bundle->source_.length());
00132     
00133     // 
00134     // Finished generating the payload
00135     //
00136     bundle->payload_.set_data(scratch.buf(), signal_len);
00137 }
00138 
00139 bool
00140 CustodySignal::parse_custody_signal(data_t* data,
00141                                     const u_char* bp, u_int len)
00142 {
00143     // 1 byte Admin Payload Type + Flags:
00144     if (len < 1) { return false; }
00145     data->admin_type_  = (*bp >> 4);
00146     data->admin_flags_ = *bp & 0xf;
00147     bp++;
00148     len--;
00149 
00150     // validate the admin type
00151     if (data->admin_type_ != BundleProtocol::ADMIN_CUSTODY_SIGNAL) {
00152         return false;
00153     }
00154 
00155     // Success flag and reason code
00156     if (len < 1) { return false; }
00157     data->succeeded_ = (*bp >> 7);
00158     data->reason_    = (*bp & 0x7f);
00159     bp++;
00160     len--;
00161     
00162     // Fragment SDNV Fields (offset & length), if present:
00163     if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT)
00164     {
00165         int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
00166         if (sdnv_bytes == -1) { return false; }
00167         bp  += sdnv_bytes;
00168         len -= sdnv_bytes;
00169         
00170         sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
00171         if (sdnv_bytes == -1) { return false; }
00172         bp  += sdnv_bytes;
00173         len -= sdnv_bytes;
00174     }
00175 
00176     // The signal timestamp
00177     if (len < sizeof(u_int64_t)) { return false; }
00178     BundleProtocol::get_timestamp(&data->custody_signal_tv_, bp);
00179     bp  += sizeof(u_int64_t);
00180     len -= sizeof(u_int64_t);
00181 
00182     // Copy of the bundle's creation timestamp
00183     if (len < sizeof(u_int64_t)) { return false; }
00184     BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp);
00185     bp  += sizeof(u_int64_t);
00186     len -= sizeof(u_int64_t);
00187 
00188     // Source Endpoint ID of Bundle
00189     u_int64_t EID_len;
00190     int num_bytes = SDNV::decode(bp, len, &EID_len);
00191     if (num_bytes == -1) { return false; }
00192     bp  += num_bytes;
00193     len -= num_bytes;
00194 
00195     if (len != EID_len) { return false; }
00196     bool ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
00197     if (!ok) {
00198         return false;
00199     }
00200     
00201     return true;
00202 }
00203 
00204 const char*
00205 CustodySignal::reason_to_str(u_int8_t reason)
00206 {
00207     switch (reason) {
00208     case BundleProtocol::CUSTODY_NO_ADDTL_INFO:
00209         return "no additional info";
00210         
00211     case BundleProtocol::CUSTODY_REDUNDANT_RECEPTION:
00212         return "redundant reception";
00213         
00214     case BundleProtocol::CUSTODY_DEPLETED_STORAGE:
00215         return "depleted storage";
00216         
00217     case BundleProtocol::CUSTODY_ENDPOINT_ID_UNINTELLIGIBLE:
00218         return "eid unintelligible";
00219         
00220     case BundleProtocol::CUSTODY_NO_ROUTE_TO_DEST:
00221         return "no route to dest";
00222         
00223     case BundleProtocol::CUSTODY_NO_TIMELY_CONTACT:
00224         return "no timely contact";
00225         
00226     case BundleProtocol::CUSTODY_BLOCK_UNINTELLIGIBLE:
00227         return "block unintelligible";
00228     }
00229 
00230     static char buf[64];
00231     snprintf(buf, 64, "unknown reason %d", reason);
00232     return buf;
00233 }
00234 
00235 } // namespace dtn

Generated on Thu Jun 7 12:54:26 2007 for DTN Reference Implementation by  doxygen 1.5.1