PrimaryBlockProcessor.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 #include <string>
00018 #include <sys/types.h>
00019 #include <netinet/in.h>
00020 
00021 #include "Bundle.h"
00022 #include "BundleProtocol.h"
00023 #include "PrimaryBlockProcessor.h"
00024 #include "naming/EndpointID.h"
00025 #include "SDNV.h"
00026 
00027 namespace dtn {
00028 
00029 //----------------------------------------------------------------------
00030 struct DictionaryEntry {
00031     DictionaryEntry(const std::string& s, size_t off)
00032         : str(s), offset(off) {}
00033 
00034     std::string str;
00035     size_t offset;
00036 };
00037 
00038 class DictionaryVector : public std::vector<DictionaryEntry> {};
00039 
00040 //----------------------------------------------------------------------
00041 PrimaryBlockProcessor::PrimaryBlockProcessor()
00042     : BlockProcessor(BundleProtocol::PRIMARY_BLOCK)
00043 {
00044 }
00045 
00046 //----------------------------------------------------------------------
00047 void
00048 PrimaryBlockProcessor::add_to_dictionary(const EndpointID& eid,
00049                                          DictionaryVector* dict,
00050                                          size_t* dictlen)
00051 {
00052     /*
00053      * For the scheme and ssp parts of the given endpoint id, see if
00054      * they've already appeared in the vector. If not, add them, and
00055      * record their length (with the null terminator) in the running
00056      * length total.
00057      */
00058     DictionaryVector::iterator iter;
00059     bool found_scheme = false;
00060     bool found_ssp = false;
00061 
00062     for (iter = dict->begin(); iter != dict->end(); ++iter) {
00063         if (iter->str == eid.scheme_str())
00064             found_scheme = true;
00065 
00066         if (iter->str == eid.ssp())
00067             found_ssp = true;
00068     }
00069 
00070     if (found_scheme == false) {
00071         dict->push_back(DictionaryEntry(eid.scheme_str(), *dictlen));
00072         *dictlen += (eid.scheme_str().length() + 1);
00073     }
00074 
00075     if (found_ssp == false) {
00076         dict->push_back(DictionaryEntry(eid.ssp(), *dictlen));
00077         *dictlen += (eid.ssp().length() + 1);
00078     }
00079 }
00080 
00081 //----------------------------------------------------------------------
00082 void
00083 PrimaryBlockProcessor::get_dictionary_offsets(DictionaryVector *dict,
00084                                               const EndpointID& eid,
00085                                               u_int16_t* scheme_offset,
00086                                               u_int16_t* ssp_offset)
00087 {
00088     DictionaryVector::iterator iter;
00089     for (iter = dict->begin(); iter != dict->end(); ++iter) {
00090         if (iter->str == eid.scheme_str())
00091             *scheme_offset = htons(iter->offset);
00092 
00093         if (iter->str == eid.ssp())
00094             *ssp_offset = htons(iter->offset);
00095     }
00096 }
00097 
00098 //----------------------------------------------------------------------
00099 bool
00100 PrimaryBlockProcessor::extract_dictionary_eid(EndpointID* eid,
00101                                               const char* what,
00102                                               u_int16_t* scheme_offsetp,
00103                                               u_int16_t* ssp_offsetp,
00104                                               u_char* dictionary,
00105                                               u_int32_t dictionary_len)
00106 {
00107     static const char* log = "/dtn/bundle/protocol";
00108     u_int16_t scheme_offset, ssp_offset;
00109     memcpy(&scheme_offset, scheme_offsetp, 2);
00110     memcpy(&ssp_offset, ssp_offsetp, 2);
00111     scheme_offset = ntohs(scheme_offset);
00112     ssp_offset = ntohs(ssp_offset);
00113 
00114     if (scheme_offset >= (dictionary_len - 1)) {
00115         log_err_p(log, "illegal offset for %s scheme dictionary offset: "
00116                   "offset %d, total length %u", what,
00117                   scheme_offset, dictionary_len);
00118         return false;
00119     }
00120 
00121     if (ssp_offset >= (dictionary_len - 1)) {
00122         log_err_p(log, "illegal offset for %s ssp dictionary offset: "
00123                   "offset %d, total length %u", what,
00124                   ssp_offset, dictionary_len);
00125         return false;
00126     }
00127     
00128     eid->assign((char*)&dictionary[scheme_offset],
00129                 (char*)&dictionary[ssp_offset]);
00130 
00131     if (! eid->valid()) {
00132         log_err_p(log, "invalid %s endpoint id '%s': "
00133                   "scheme '%s' offset %u/%u ssp '%s' offset %u/%u",
00134                   what, eid->c_str(),
00135                   eid->scheme_str().c_str(),
00136                   scheme_offset, dictionary_len,
00137                   eid->ssp().c_str(),
00138                   ssp_offset, dictionary_len);
00139         return false;                                                      
00140     }                                                                   
00141     
00142     log_debug_p(log, "parsed %s eid (offsets %u, %u) %s", 
00143                 what, scheme_offset, ssp_offset, eid->c_str());
00144     return true;
00145 }
00146 
00147 //----------------------------------------------------------------------
00148 void
00149 PrimaryBlockProcessor::debug_dump_dictionary(const char* bp, size_t len,
00150                                              PrimaryBlock2* primary2)
00151 {
00152 #ifndef NDEBUG
00153     oasys::StringBuffer dict_copy;
00154 
00155     const char* end = bp + len;
00156     ASSERT(end[-1] == '\0');
00157     
00158     while (bp != end) {
00159         dict_copy.appendf("%s ", bp);
00160         bp += strlen(bp) + 1;
00161     }
00162 
00163     log_debug_p("/dtn/bundle/protocol",
00164                 "dictionary len %zu, value: '%s'", len, dict_copy.c_str());
00165                   
00166     log_debug_p("/dtn/bundle/protocol",
00167                 "dictionary offsets: dest %u,%u source %u,%u, "
00168                 "custodian %u,%u replyto %u,%u",
00169                 ntohs(primary2->dest_scheme_offset),
00170                 ntohs(primary2->dest_ssp_offset),
00171                 ntohs(primary2->source_scheme_offset),
00172                 ntohs(primary2->source_ssp_offset),
00173                 ntohs(primary2->custodian_scheme_offset),
00174                 ntohs(primary2->custodian_ssp_offset),
00175                 ntohs(primary2->replyto_scheme_offset),
00176                 ntohs(primary2->replyto_ssp_offset));
00177 #else
00178     (void)bp;
00179     (void)len;
00180     (void)primary2;
00181 #endif
00182 }
00183 
00184 //----------------------------------------------------------------------
00185 u_int8_t
00186 PrimaryBlockProcessor::format_bundle_flags(const Bundle* bundle)
00187 {
00188     u_int8_t flags = 0;
00189 
00190     if (bundle->is_fragment_) {
00191         flags |= BUNDLE_IS_FRAGMENT;
00192     }
00193 
00194     if (bundle->is_admin_) {
00195         flags |= BUNDLE_IS_ADMIN;
00196     }
00197 
00198     if (bundle->do_not_fragment_) {
00199         flags |= BUNDLE_DO_NOT_FRAGMENT;
00200     }
00201 
00202     if (bundle->custody_requested_) {
00203         flags |= BUNDLE_CUSTODY_XFER_REQUESTED;
00204     }
00205 
00206     if (bundle->singleton_dest_) {
00207         flags |= BUNDLE_SINGLETON_DESTINATION;
00208     }
00209 
00210     return flags;
00211 }
00212 
00213 //----------------------------------------------------------------------
00214 void
00215 PrimaryBlockProcessor::parse_bundle_flags(Bundle* bundle, u_int8_t flags)
00216 {
00217     if (flags & BUNDLE_IS_FRAGMENT) {
00218         bundle->is_fragment_ = true;
00219     }
00220 
00221     if (flags & BUNDLE_IS_ADMIN) {
00222         bundle->is_admin_ = true;
00223     }
00224 
00225     if (flags & BUNDLE_DO_NOT_FRAGMENT) {
00226         bundle->do_not_fragment_ = true;
00227     }
00228 
00229     if (flags & BUNDLE_CUSTODY_XFER_REQUESTED) {
00230         bundle->custody_requested_ = true;
00231     }
00232 
00233     if (flags & BUNDLE_SINGLETON_DESTINATION) {
00234         bundle->singleton_dest_ = true;
00235     }
00236 }
00237 
00238 //----------------------------------------------------------------------
00239 u_int8_t
00240 PrimaryBlockProcessor::format_cos_flags(const Bundle* b)
00241 {
00242     u_int8_t cos_flags = 0;
00243 
00244     cos_flags = ((b->priority_ & 0x3) << 6);
00245 
00246     return cos_flags;
00247 }
00248 
00249 //----------------------------------------------------------------------
00250 void
00251 PrimaryBlockProcessor::parse_cos_flags(Bundle* b, u_int8_t cos_flags)
00252 {
00253     b->priority_ = ((cos_flags >> 6) & 0x3);
00254 }
00255 
00256 //----------------------------------------------------------------------
00257 u_int8_t
00258 PrimaryBlockProcessor::format_srr_flags(const Bundle* b)
00259 {
00260     u_int8_t srr_flags = 0;
00261     
00262     if (b->receive_rcpt_)
00263         srr_flags |= BundleProtocol::STATUS_RECEIVED;
00264 
00265     if (b->custody_rcpt_)
00266         srr_flags |= BundleProtocol::STATUS_CUSTODY_ACCEPTED;
00267 
00268     if (b->forward_rcpt_)
00269         srr_flags |= BundleProtocol::STATUS_FORWARDED;
00270 
00271     if (b->delivery_rcpt_)
00272         srr_flags |= BundleProtocol::STATUS_DELIVERED;
00273 
00274     if (b->deletion_rcpt_)
00275         srr_flags |= BundleProtocol::STATUS_DELETED;
00276 
00277     if (b->app_acked_rcpt_)
00278         srr_flags |= BundleProtocol::STATUS_ACKED_BY_APP;
00279 
00280     return srr_flags;
00281 }
00282     
00283 //----------------------------------------------------------------------
00284 void
00285 PrimaryBlockProcessor::parse_srr_flags(Bundle* b, u_int8_t srr_flags)
00286 {
00287     if (srr_flags & BundleProtocol::STATUS_RECEIVED)
00288         b->receive_rcpt_ = true;
00289 
00290     if (srr_flags & BundleProtocol::STATUS_CUSTODY_ACCEPTED)
00291         b->custody_rcpt_ = true;
00292 
00293     if (srr_flags & BundleProtocol::STATUS_FORWARDED)
00294         b->forward_rcpt_ = true;
00295 
00296     if (srr_flags & BundleProtocol::STATUS_DELIVERED)
00297         b->delivery_rcpt_ = true;
00298 
00299     if (srr_flags & BundleProtocol::STATUS_DELETED)
00300         b->deletion_rcpt_ = true;
00301 
00302     if (srr_flags & BundleProtocol::STATUS_ACKED_BY_APP)
00303         b->app_acked_rcpt_ = true;
00304 }
00305 
00306 //----------------------------------------------------------------------
00307 size_t
00308 PrimaryBlockProcessor::get_primary_len(const Bundle* bundle,
00309                                        DictionaryVector* dict,
00310                                        size_t* dictionary_len,
00311                                        size_t* primary_var_len)
00312 {
00313     static const char* log = "/dtn/bundle/protocol";
00314     size_t primary_len = 0;
00315     *dictionary_len = 0;
00316     *primary_var_len = 0;
00317     
00318     /*
00319      * We need to figure out the total length of the primary block,
00320      * except for the SDNV used to encode the length itself and the
00321      * three byte preamble (PrimaryBlock1).
00322      *
00323      * First, we determine the size of the dictionary by first
00324      * figuring out all the unique strings, and in the process,
00325      * remembering their offsets and summing up their lengths
00326      * (including the null terminator for each).
00327      */
00328     add_to_dictionary(bundle->dest_,      dict, dictionary_len);
00329     add_to_dictionary(bundle->source_,    dict, dictionary_len);
00330     add_to_dictionary(bundle->custodian_, dict, dictionary_len);
00331     add_to_dictionary(bundle->replyto_,   dict, dictionary_len);
00332 
00333     (void)log; // in case NDEBUG is defined
00334     log_debug_p(log, "generated dictionary length %zu", *dictionary_len);
00335 
00336     *primary_var_len += SDNV::encoding_len(*dictionary_len);
00337     *primary_var_len += *dictionary_len;
00338 
00339     /*
00340      * If the bundle is a fragment, we need to include space for the
00341      * fragment offset and the original payload length.
00342      *
00343      * Note: Any changes to this protocol must be reflected into the
00344      * FragmentManager since it depends on this length when
00345      * calculating fragment sizes.
00346      */
00347     if (bundle->is_fragment_) {
00348         *primary_var_len += SDNV::encoding_len(bundle->frag_offset_);
00349         *primary_var_len += SDNV::encoding_len(bundle->orig_length_);
00350     }
00351 
00352     /*
00353      * Tack on the size of the PrimaryBlock2, 
00354      */
00355     *primary_var_len += sizeof(PrimaryBlock2);
00356 
00357     /*
00358      * Finally, add up the initial PrimaryBlock1 plus the size of the
00359      * SDNV to encode the variable length part, plus the variable
00360      * length part itself.
00361      */
00362     primary_len = sizeof(PrimaryBlock1) +
00363                   SDNV::encoding_len(*primary_var_len) +
00364                   *primary_var_len;
00365     
00366     log_debug_p(log, "get_primary_len(bundle %d): %zu",
00367                 bundle->bundleid_, primary_len);
00368     
00369     return primary_len;
00370 }
00371 
00372 //----------------------------------------------------------------------
00373 size_t
00374 PrimaryBlockProcessor::get_primary_len(const Bundle* bundle)
00375 {
00376     DictionaryVector dict;
00377     size_t dictionary_len;
00378     size_t primary_var_len;
00379 
00380     return get_primary_len(bundle, &dict, &dictionary_len, &primary_var_len);
00381 }
00382 
00383 //----------------------------------------------------------------------
00384 int
00385 PrimaryBlockProcessor::consume(Bundle* bundle, BlockInfo* block, u_char* buf, size_t len)
00386 {
00387     static const char* log = "/dtn/bundle/protocol";
00388     size_t consumed = 0;
00389     
00390     ASSERT(! block->complete());
00391     
00392     /*
00393      * The first thing we need to do is find the length of the primary
00394      * block, noting that it may be split across multiple calls. 
00395      */
00396     if (block->data_length() == 0) {
00397         int cc = consume_preamble(block, buf, len, sizeof(PrimaryBlock1));
00398         
00399         if (cc == -1) {
00400             return -1; // protocol error
00401         }
00402 
00403         // If the data offset isn't set, then the whole buffer must
00404         // have been consumed since there's not enough data to parse
00405         // the length.
00406         if (block->data_offset() == 0) {
00407             ASSERT(cc == (int)len);
00408             return cc;
00409         }
00410 
00411         // Ok, we now know the whole length
00412         log_debug_p(log, "parsed primary block length %u (preamble %u)",
00413                   block->data_length(), block->data_offset());
00414         buf += cc;
00415         len -= cc;
00416 
00417         consumed += cc;
00418 
00419         if (block->data_length() == 0) {
00420             log_err_p(log, "got primary block with zero length");
00421             return -1; // protocol error
00422         }
00423     }
00424 
00425     /*
00426      * Now see if this completes the primary by calling into
00427      * BlockProcessor::consume() to get the default behavior (now that
00428      * we've found the data length above).
00429      */
00430     ASSERT(block->full_length() > block->contents().len());
00431     int cc = BlockProcessor::consume(bundle, block, buf, len);
00432 
00433     if (cc == -1) {
00434         return -1; // protocol error
00435     }
00436     
00437     if (! block->complete()) {
00438         ASSERT(cc == (int)len);
00439         return consumed + cc;
00440     }
00441 
00442     /*
00443      * Ok, now the block is complete so we can parse it. We'll return
00444      * the total amount consumed (or -1 for protocol error) when
00445      * finished.
00446      */
00447     consumed += cc;
00448 
00449     size_t primary_len = block->full_length();
00450 
00451     buf = block->writable_contents()->buf();
00452     len = block->writable_contents()->len();
00453 
00454     ASSERT(primary_len == len);
00455 
00456     /*
00457      * Process the PrimaryBlock1
00458      */
00459     PrimaryBlock1* primary1 = (PrimaryBlock1*)buf;
00460     log_debug_p(log, "parsed primary block 1: version %d length %u",
00461                 primary1->version, block->data_length());
00462     
00463     if (primary1->version != BundleProtocol::CURRENT_VERSION) {
00464         log_warn_p(log, "protocol version mismatch %d != %d",
00465                    primary1->version, BundleProtocol::CURRENT_VERSION);
00466         return -1;
00467     }
00468     
00469     parse_bundle_flags(bundle, primary1->bundle_processing_flags);
00470     parse_cos_flags(bundle, primary1->class_of_service_flags);
00471     parse_srr_flags(bundle, primary1->status_report_request_flags);
00472 
00473     /*
00474      * Now skip past the PrimaryBlock1 and the SDNV that describes the
00475      * total primary block length.
00476      */
00477     buf += block->data_offset();
00478     len -= block->data_offset();
00479 
00480     ASSERT(len == block->data_length());
00481 
00482     /*
00483      * Make sure that the sender didn't lie and that we really do have
00484      * enough for the next set of fixed-length fields. We'll return to
00485      * this label periodically as we parse different components.
00486      */
00487     u_int32_t primary2_len    = sizeof(PrimaryBlock2);
00488     int       dict_sdnv_len   = 0;
00489     u_int32_t dictionary_len  = 0;
00490     int       frag_offset_len = 0;
00491     int       frag_length_len = 0;
00492     if (len < sizeof(PrimaryBlock2)) {
00493 tooshort:
00494         log_err_p(log, "primary block advertised incorrect length %u: "
00495                   "fixed-length %u, dict_sdnv %d, dict %u, frag %d %d",
00496                   block->data_length(), primary2_len, dict_sdnv_len,
00497                   dictionary_len, frag_offset_len, frag_length_len);
00498         return -1;
00499     }
00500 
00501     /*
00502      * Parse the PrimaryBlock2
00503      */
00504     PrimaryBlock2* primary2 = (PrimaryBlock2*)buf;
00505     buf += sizeof(PrimaryBlock2);
00506     len -= sizeof(PrimaryBlock2);
00507     
00508     BundleProtocol::get_timestamp(&bundle->creation_ts_, &primary2->creation_ts);
00509     u_int32_t lifetime;
00510     memcpy(&lifetime, &primary2->lifetime, sizeof(lifetime));
00511     bundle->expiration_ = ntohl(lifetime);
00512 
00513     /*
00514      * Read the dictionary length.
00515      */
00516     dict_sdnv_len = SDNV::decode(buf, len, &dictionary_len);
00517     if (dict_sdnv_len < 0) {
00518         goto tooshort;
00519     }
00520     buf += dict_sdnv_len;
00521     len -= dict_sdnv_len;
00522 
00523     /*
00524      * Verify that we have the whole dictionary.
00525      */
00526     if (len < dictionary_len) {
00527         goto tooshort;
00528     }
00529 
00530     /*
00531      * Make sure that the dictionary ends with a null byte.
00532      */
00533     if (buf[dictionary_len - 1] != '\0') {
00534         log_err_p(log, "dictionary does not end with a NULL character!");
00535         return -1;
00536     }
00537 
00538     /*
00539      * Now use the dictionary buffer to parse out the various endpoint
00540      * identifiers, making sure that none of them peeks past the end
00541      * of the dictionary block.
00542      */
00543     u_char* dictionary = buf;
00544     buf += dictionary_len;
00545     len -= dictionary_len;
00546 
00547     debug_dump_dictionary((char*)dictionary, dictionary_len, primary2);
00548 
00549     extract_dictionary_eid(&bundle->source_, "source",
00550                            &primary2->source_scheme_offset,
00551                            &primary2->source_ssp_offset,
00552                            dictionary, dictionary_len);
00553     
00554     extract_dictionary_eid(&bundle->dest_, "dest",
00555                            &primary2->dest_scheme_offset,
00556                            &primary2->dest_ssp_offset,
00557                            dictionary, dictionary_len);
00558     
00559     extract_dictionary_eid(&bundle->replyto_, "replyto",
00560                            &primary2->replyto_scheme_offset,
00561                            &primary2->replyto_ssp_offset,
00562                            dictionary, dictionary_len);
00563     
00564     extract_dictionary_eid(&bundle->custodian_, "custodian",
00565                            &primary2->custodian_scheme_offset,
00566                            &primary2->custodian_ssp_offset,
00567                            dictionary, dictionary_len);
00568     
00569     if (bundle->is_fragment_) {
00570         frag_offset_len = SDNV::decode(buf, len, &bundle->frag_offset_);
00571         if (frag_offset_len == -1) {
00572             goto tooshort;
00573         }
00574         buf += frag_offset_len;
00575         len -= frag_offset_len;
00576 
00577         frag_length_len = SDNV::decode(buf, len, &bundle->orig_length_);
00578         if (frag_length_len == -1) {
00579             goto tooshort;
00580         }
00581         buf += frag_length_len;
00582         len -= frag_length_len;
00583 
00584         log_debug_p(log, "parsed fragmentation info: offset %u, orig_len %u",
00585                     bundle->frag_offset_, bundle->orig_length_);
00586     }
00587 
00588     return consumed;
00589 }
00590 
00591 //----------------------------------------------------------------------
00592 void
00593 PrimaryBlockProcessor::generate(const Bundle* bundle,
00594                                 Link*         link,
00595                                 BlockInfo*    block,
00596                                 bool last)
00597 {
00598     (void)link;
00599 
00600     /*
00601      * The primary can't be last since there must be a payload block
00602      */
00603     ASSERT(!last);
00604 
00605     static const char* log = "/dtn/bundle/protocol";
00606     DictionaryVector dict;
00607     size_t primary_len = 0;     // total length of the primary block
00608     size_t primary_var_len = 0; // length of the variable part of the primary
00609     size_t dictionary_len = 0;  // length of the dictionary
00610     int sdnv_len = 0;           // use an int to handle -1 return values
00611 
00612     /*
00613      * Calculate the primary block length and initialize the buffer.
00614      */
00615     primary_len = get_primary_len(bundle, &dict, &dictionary_len,
00616                                   &primary_var_len);
00617     block->writable_contents()->reserve(primary_len);
00618     block->writable_contents()->set_len(primary_len);
00619     block->set_data_length(primary_len);
00620 
00621     /*
00622      * Advance buf and decrement len as we go through the process.
00623      */
00624     u_char* buf = block->writable_contents()->buf();
00625     int     len = primary_len;
00626     
00627     (void)log; // in case NDEBUG is defined
00628     log_debug_p(log, "generating primary: length %zu (preamble %zu var length %zu)",
00629                 primary_len,
00630                 (sizeof(PrimaryBlock1) + SDNV::encoding_len(primary_var_len)),
00631                 primary_var_len);
00632     
00633     /*
00634      * Ok, stuff in the preamble and the total block length.
00635      */
00636     PrimaryBlock1* primary1               = (PrimaryBlock1*)buf;
00637     primary1->version                     = BundleProtocol::CURRENT_VERSION;
00638     primary1->bundle_processing_flags     = format_bundle_flags(bundle);
00639     primary1->class_of_service_flags      = format_cos_flags(bundle);
00640     primary1->status_report_request_flags = format_srr_flags(bundle);
00641     
00642     sdnv_len = SDNV::encode(primary_var_len,
00643                             &primary1->block_length[0], len - 3);
00644     ASSERT(sdnv_len > 0);
00645     buf += (sizeof(PrimaryBlock1) + sdnv_len);
00646     len -= (sizeof(PrimaryBlock1) + sdnv_len);
00647 
00648     /*
00649      * Now fill in the PrimaryBlock2.
00650      */
00651     PrimaryBlock2* primary2 = (PrimaryBlock2*)buf;
00652 
00653     get_dictionary_offsets(&dict, bundle->dest_,
00654                            &primary2->dest_scheme_offset,
00655                            &primary2->dest_ssp_offset);
00656 
00657     get_dictionary_offsets(&dict, bundle->source_,
00658                            &primary2->source_scheme_offset,
00659                            &primary2->source_ssp_offset);
00660 
00661     get_dictionary_offsets(&dict, bundle->custodian_,
00662                            &primary2->custodian_scheme_offset,
00663                            &primary2->custodian_ssp_offset);
00664 
00665     get_dictionary_offsets(&dict, bundle->replyto_,
00666                            &primary2->replyto_scheme_offset,
00667                            &primary2->replyto_ssp_offset);
00668 
00669     BundleProtocol::set_timestamp(&primary2->creation_ts, &bundle->creation_ts_);
00670     u_int32_t lifetime = htonl(bundle->expiration_);
00671     memcpy(&primary2->lifetime, &lifetime, sizeof(lifetime));
00672 
00673     buf += sizeof(PrimaryBlock2);
00674     len -= sizeof(PrimaryBlock2);
00675 
00676     /*
00677      * Stuff in the dictionary length and dictionary bytes.
00678      */
00679     sdnv_len = SDNV::encode(dictionary_len, buf, len);
00680     ASSERT(sdnv_len > 0);
00681     buf += sdnv_len;
00682     len -= sdnv_len;
00683 
00684     DictionaryVector::iterator dict_iter;
00685     for (dict_iter = dict.begin(); dict_iter != dict.end(); ++dict_iter) {
00686         strcpy((char*)buf, dict_iter->str.c_str());
00687         buf += dict_iter->str.length() + 1;
00688         len -= dict_iter->str.length() + 1;
00689     }
00690     
00691     debug_dump_dictionary((char*)buf - dictionary_len, dictionary_len, primary2);
00692     
00693     /*
00694      * If the bundle is a fragment, stuff in SDNVs for the fragment
00695      * offset and original length.
00696      */
00697     if (bundle->is_fragment_) {
00698         sdnv_len = SDNV::encode(bundle->frag_offset_, buf, len);
00699         ASSERT(sdnv_len > 0);
00700         buf += sdnv_len;
00701         len -= sdnv_len;
00702 
00703         sdnv_len = SDNV::encode(bundle->orig_length_, buf, len);
00704         ASSERT(sdnv_len > 0);
00705         buf += sdnv_len;
00706         len -= sdnv_len;
00707     }
00708 
00709 #ifndef NDEBUG
00710     {
00711         DictionaryVector dict2;
00712         size_t dict2_len = 0;
00713         size_t p2len;
00714         size_t len2 = get_primary_len(bundle, &dict2, &dict2_len, &p2len);
00715         ASSERT(len2 == primary_len);
00716     }
00717 #endif
00718 
00719     /*
00720      * Asuming that get_primary_len is written correctly, len should
00721      * now be zero since we initialized it to primary_len at the
00722      * beginning of the function.
00723      */
00724     ASSERT(len == 0);
00725 }
00726 
00727 
00728 } // namespace dtn

Generated on Sat Sep 8 08:43:31 2007 for DTN Reference Implementation by  doxygen 1.5.3