servlib/bundling/CustodySignal.cc
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2006 Intel Corporation
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #ifdef HAVE_CONFIG_H
       
    18 #  include <dtn-config.h>
       
    19 #endif
       
    20 
       
    21 #include <oasys/util/ScratchBuffer.h>
       
    22 #include "CustodySignal.h"
       
    23 #include "SDNV.h"
       
    24 
       
    25 namespace dtn {
       
    26 
       
    27 //----------------------------------------------------------------------
       
    28 void
       
    29 CustodySignal::create_custody_signal(Bundle*           bundle,
       
    30                                      const Bundle*     orig_bundle,
       
    31                                      const EndpointID& source_eid,
       
    32                                      bool              succeeded,
       
    33                                      reason_t          reason)
       
    34 {
       
    35     bundle->mutable_source()->assign(source_eid);
       
    36     if (orig_bundle->custodian().equals(EndpointID::NULL_EID())) {
       
    37         PANIC("create_custody_signal(*%p): "
       
    38               "custody signal cannot be generated to null eid",
       
    39               orig_bundle);
       
    40     }
       
    41     bundle->mutable_dest()->assign(orig_bundle->custodian());
       
    42     bundle->mutable_replyto()->assign(EndpointID::NULL_EID());
       
    43     bundle->mutable_custodian()->assign(EndpointID::NULL_EID());
       
    44     bundle->set_is_admin(true);
       
    45 
       
    46     // use the expiration time from the original bundle
       
    47     // XXX/demmer maybe something more clever??
       
    48     bundle->set_expiration(orig_bundle->expiration());
       
    49 
       
    50     int sdnv_encoding_len = 0;
       
    51     int signal_len = 0;
       
    52     
       
    53     // we generally don't expect the Custody Signal length to be > 256 bytes
       
    54     oasys::ScratchBuffer<u_char*, 256> scratch;
       
    55     
       
    56     // format of custody signals:
       
    57     //
       
    58     // 1 byte admin payload type and flags
       
    59     // 1 byte status code
       
    60     // SDNV   [Fragment Offset (if present)]
       
    61     // SDNV   [Fragment Length (if present)]
       
    62     // SDNVx2 Time of custody signal
       
    63     // SDNVx2 Copy of bundle X's Creation Timestamp
       
    64     // SDNV   Length of X's source endpoint ID
       
    65     // vari   Source endpoint ID of bundle X
       
    66 
       
    67     //
       
    68     // first calculate the length
       
    69     //
       
    70 
       
    71     // the non-optional, fixed-length fields above:
       
    72     signal_len =  1 + 1;
       
    73 
       
    74     // the 2 SDNV fragment fields:
       
    75     if (orig_bundle->is_fragment()) {
       
    76         signal_len += SDNV::encoding_len(orig_bundle->frag_offset());
       
    77         signal_len += SDNV::encoding_len(orig_bundle->orig_length());
       
    78     }
       
    79     
       
    80     // Time field, set to the current time:
       
    81     BundleTimestamp now;
       
    82     now.seconds_ = BundleTimestamp::get_current_time();
       
    83     now.seqno_   = 0;
       
    84     signal_len += BundleProtocol::ts_encoding_len(now);
       
    85     
       
    86     // The bundle's creation timestamp:
       
    87     signal_len += BundleProtocol::ts_encoding_len(orig_bundle->creation_ts());
       
    88 
       
    89     // the Source Endpoint ID length and value
       
    90 int ipn = 0;
       
    91 if(strncmp((const char*)orig_bundle->source().c_str(), "ipn", 3) == 0)
       
    92  ipn = 2;
       
    93     signal_len += SDNV::encoding_len(orig_bundle->source().length() - ipn) +
       
    94                   orig_bundle->source().length() - ipn;
       
    95 
       
    96     //
       
    97     // now format the buffer
       
    98     //
       
    99     u_char* bp = scratch.buf(signal_len);
       
   100     int len = signal_len;
       
   101     
       
   102     // Admin Payload Type and flags
       
   103     *bp = (BundleProtocol::ADMIN_CUSTODY_SIGNAL << 4);
       
   104     if (orig_bundle->is_fragment()) {
       
   105         *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
       
   106     }
       
   107     bp++;
       
   108     len--;
       
   109     
       
   110     // Success flag and reason code
       
   111     *bp++ = ((succeeded ? 1 : 0) << 7) | (reason & 0x7f);
       
   112     len--;
       
   113     
       
   114     // The 2 Fragment Fields
       
   115     if (orig_bundle->is_fragment()) {
       
   116         sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset(), bp, len);
       
   117         ASSERT(sdnv_encoding_len > 0);
       
   118         bp  += sdnv_encoding_len;
       
   119         len -= sdnv_encoding_len;
       
   120         
       
   121         sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length(), bp, len);
       
   122         ASSERT(sdnv_encoding_len > 0);
       
   123         bp  += sdnv_encoding_len;
       
   124         len -= sdnv_encoding_len;
       
   125     }
       
   126     
       
   127     sdnv_encoding_len = BundleProtocol::set_timestamp(bp, len, now);
       
   128     ASSERT(sdnv_encoding_len > 0);
       
   129     bp  += sdnv_encoding_len;
       
   130     len -= sdnv_encoding_len;
       
   131 
       
   132     // Copy of bundle X's Creation Timestamp
       
   133     sdnv_encoding_len = 
       
   134         BundleProtocol::set_timestamp(bp, len, orig_bundle->creation_ts());
       
   135     ASSERT(sdnv_encoding_len > 0);
       
   136     bp  += sdnv_encoding_len;
       
   137     len -= sdnv_encoding_len;
       
   138 
       
   139     // The Endpoint ID length and data
       
   140 char buf[80];
       
   141 u_int64_t a, b;
       
   142 size_t eidlen;
       
   143 
       
   144 if(sscanf((const char*)orig_bundle->source().c_str(), "ipn://%" PRIu64 "/%" PRIu64, &a, &b) == 2)
       
   145 {
       
   146         sprintf(buf, "ipn:%" PRIu64 ".%" PRIu64, a, b);
       
   147         eidlen = strlen(buf);
       
   148 	sdnv_encoding_len = SDNV::encode(eidlen, bp, len);
       
   149 	ASSERT(sdnv_encoding_len > 0);
       
   150 	len -= sdnv_encoding_len;
       
   151 	bp += sdnv_encoding_len;
       
   152 
       
   153         memcpy(bp, buf, len);
       
   154 }
       
   155 else
       
   156 {
       
   157 
       
   158     sdnv_encoding_len = SDNV::encode(orig_bundle->source().length(), bp, len);
       
   159     ASSERT(sdnv_encoding_len > 0);
       
   160     len -= sdnv_encoding_len;
       
   161     bp  += sdnv_encoding_len;
       
   162     
       
   163     ASSERT((u_int)len == orig_bundle->source().length());
       
   164 
       
   165     memcpy(bp, orig_bundle->source().c_str(), orig_bundle->source().length());
       
   166 }
       
   167 //printf("WTF %s\n", orig_bundle->source().c_str()); 
       
   168     // 
       
   169     // Finished generating the payload
       
   170     //
       
   171     bundle->mutable_payload()->set_data(scratch.buf(), signal_len);
       
   172 }
       
   173 
       
   174 //----------------------------------------------------------------------
       
   175 bool
       
   176 CustodySignal::parse_custody_signal(data_t* data,
       
   177                                     const u_char* bp, u_int len)
       
   178 {
       
   179     // 1 byte Admin Payload Type + Flags:
       
   180     if (len < 1) { return false; }
       
   181     data->admin_type_  = (*bp >> 4);
       
   182     data->admin_flags_ = *bp & 0xf;
       
   183     bp++;
       
   184     len--;
       
   185 
       
   186     // validate the admin type
       
   187     if (data->admin_type_ != BundleProtocol::ADMIN_CUSTODY_SIGNAL) {
       
   188         return false;
       
   189     }
       
   190 
       
   191     // Success flag and reason code
       
   192     if (len < 1) { return false; }
       
   193     data->succeeded_ = (*bp >> 7);
       
   194     data->reason_    = (*bp & 0x7f);
       
   195     bp++;
       
   196     len--;
       
   197     
       
   198     // Fragment SDNV Fields (offset & length), if present:
       
   199     if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT)
       
   200     {
       
   201         int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
       
   202         if (sdnv_bytes == -1) { return false; }
       
   203         bp  += sdnv_bytes;
       
   204         len -= sdnv_bytes;
       
   205         
       
   206         sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
       
   207         if (sdnv_bytes == -1) { return false; }
       
   208         bp  += sdnv_bytes;
       
   209         len -= sdnv_bytes;
       
   210     }
       
   211     
       
   212     int ts_len;
       
   213 
       
   214     // The signal timestamp
       
   215     ts_len = BundleProtocol::get_timestamp(&data->custody_signal_tv_, bp, len);
       
   216     if (ts_len < 0) { return false; }
       
   217     bp  += ts_len;
       
   218     len -= ts_len;
       
   219 
       
   220     // Bundle Creation Timestamp
       
   221     ts_len = BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp, len);
       
   222     if (ts_len < 0) { return false; }
       
   223     bp  += ts_len;
       
   224     len -= ts_len;
       
   225 
       
   226     // Source Endpoint ID of Bundle
       
   227     u_int64_t EID_len;
       
   228     int num_bytes = SDNV::decode(bp, len, &EID_len);
       
   229     if (num_bytes == -1) { return false; }
       
   230     bp  += num_bytes;
       
   231     len -= num_bytes;
       
   232 
       
   233     if (len != EID_len) { return false; }
       
   234 
       
   235     bool ok;
       
   236     u_int64_t a, b;
       
   237     if(sscanf((const char*)bp, "ipn:%" PRIu64 ".%" PRIu64, &a, &b) == 2)
       
   238     {
       
   239        char buf[80];
       
   240        sscanf((const char*)bp, "ipn:%" PRIu64 ".%" PRIu64, &a, &b);
       
   241        sprintf(buf, "ipn://%" PRIu64 "/%" PRIu64, a, b);
       
   242        len = strlen(buf);
       
   243        ok = data->orig_source_eid_.assign(std::string((const char*)buf, len));
       
   244     }
       
   245     else
       
   246     {
       
   247        ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
       
   248     }
       
   249     if (!ok) {
       
   250         return false;
       
   251     }
       
   252     
       
   253     return true;
       
   254 }
       
   255 
       
   256 //----------------------------------------------------------------------
       
   257 const char*
       
   258 CustodySignal::reason_to_str(u_int8_t reason)
       
   259 {
       
   260     switch (reason) {
       
   261     case BundleProtocol::CUSTODY_NO_ADDTL_INFO:
       
   262         return "no additional info";
       
   263         
       
   264     case BundleProtocol::CUSTODY_REDUNDANT_RECEPTION:
       
   265         return "redundant reception";
       
   266         
       
   267     case BundleProtocol::CUSTODY_DEPLETED_STORAGE:
       
   268         return "depleted storage";
       
   269         
       
   270     case BundleProtocol::CUSTODY_ENDPOINT_ID_UNINTELLIGIBLE:
       
   271         return "eid unintelligible";
       
   272         
       
   273     case BundleProtocol::CUSTODY_NO_ROUTE_TO_DEST:
       
   274         return "no route to dest";
       
   275         
       
   276     case BundleProtocol::CUSTODY_NO_TIMELY_CONTACT:
       
   277         return "no timely contact";
       
   278         
       
   279     case BundleProtocol::CUSTODY_BLOCK_UNINTELLIGIBLE:
       
   280         return "block unintelligible";
       
   281     }
       
   282 
       
   283     static char buf[64];
       
   284     snprintf(buf, 64, "unknown reason %d", reason);
       
   285     return buf;
       
   286 }
       
   287 
       
   288 } // namespace dtn