00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <sys/types.h>
00040 #include <netinet/in.h>
00041 #include <algorithm>
00042
00043 #include <oasys/debug/DebugUtils.h>
00044 #include <oasys/util/StringUtils.h>
00045
00046 #include "Bundle.h"
00047 #include "BundleProtocol.h"
00048 #include "BundleTimestamp.h"
00049 #include "SDNV.h"
00050
00051 namespace dtn {
00052
00053
00054 struct DictionaryEntry {
00055 DictionaryEntry(const std::string& s, size_t off)
00056 : str(s), offset(off) {}
00057
00058 std::string str;
00059 size_t offset;
00060 };
00061
00062 class DictionaryVector : public std::vector<DictionaryEntry> {};
00063
00064
00065 void
00066 BundleProtocol::add_to_dictionary(const EndpointID& eid,
00067 DictionaryVector* dict,
00068 size_t* dictlen)
00069 {
00070
00071
00072
00073
00074
00075
00076 DictionaryVector::iterator iter;
00077 bool found_scheme = false;
00078 bool found_ssp = false;
00079
00080 for (iter = dict->begin(); iter != dict->end(); ++iter) {
00081 if (iter->str == eid.scheme_str())
00082 found_scheme = true;
00083
00084 if (iter->str == eid.ssp())
00085 found_ssp = true;
00086 }
00087
00088 if (found_scheme == false) {
00089 dict->push_back(DictionaryEntry(eid.scheme_str(), *dictlen));
00090 *dictlen += (eid.scheme_str().length() + 1);
00091 }
00092
00093 if (found_ssp == false) {
00094 dict->push_back(DictionaryEntry(eid.ssp(), *dictlen));
00095 *dictlen += (eid.ssp().length() + 1);
00096 }
00097 }
00098
00099
00100 void
00101 BundleProtocol::get_dictionary_offsets(DictionaryVector *dict,
00102 EndpointID eid,
00103 u_int16_t* scheme_offset,
00104 u_int16_t* ssp_offset)
00105 {
00106 DictionaryVector::iterator iter;
00107 for (iter = dict->begin(); iter != dict->end(); ++iter) {
00108 if (iter->str == eid.scheme_str())
00109 *scheme_offset = htons(iter->offset);
00110
00111 if (iter->str == eid.ssp())
00112 *ssp_offset = htons(iter->offset);
00113 }
00114 }
00115
00116
00117 size_t
00118 BundleProtocol::get_primary_len(const Bundle* bundle,
00119 DictionaryVector* dict,
00120 size_t* dictionary_len,
00121 size_t* primary_var_len)
00122 {
00123 static const char* log = "/dtn/bundle/protocol";
00124 size_t primary_len = 0;
00125 *dictionary_len = 0;
00126 *primary_var_len = 0;
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 add_to_dictionary(bundle->dest_, dict, dictionary_len);
00139 add_to_dictionary(bundle->source_, dict, dictionary_len);
00140 add_to_dictionary(bundle->custodian_, dict, dictionary_len);
00141 add_to_dictionary(bundle->replyto_, dict, dictionary_len);
00142
00143 (void)log;
00144 log_debug(log, "generated dictionary length %zu", *dictionary_len);
00145
00146 *primary_var_len += SDNV::encoding_len(*dictionary_len);
00147 *primary_var_len += *dictionary_len;
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 if (bundle->is_fragment_) {
00158 *primary_var_len += SDNV::encoding_len(bundle->frag_offset_);
00159 *primary_var_len += SDNV::encoding_len(bundle->orig_length_);
00160 }
00161
00162
00163
00164
00165 *primary_var_len += sizeof(PrimaryBlock2);
00166
00167
00168
00169
00170
00171
00172 primary_len = sizeof(PrimaryBlock1) +
00173 SDNV::encoding_len(*primary_var_len) +
00174 *primary_var_len;
00175
00176 log_debug(log, "get_primary_len(bundle %d): %zu",
00177 bundle->bundleid_, primary_len);
00178
00179 return primary_len;
00180 }
00181
00182
00183 size_t
00184 BundleProtocol::get_payload_block_len(const Bundle* bundle)
00185 {
00186 return (sizeof(BlockPreamble) +
00187 SDNV::encoding_len(bundle->payload_.length()));
00188 }
00189
00190
00191 int
00192 BundleProtocol::format_header_blocks(const Bundle* bundle,
00193 u_char* buf, size_t len)
00194 {
00195 static const char* log = "/dtn/bundle/protocol";
00196 DictionaryVector dict;
00197 size_t orig_len = len;
00198 size_t primary_len = 0;
00199 size_t primary_var_len = 0;
00200 size_t dictionary_len = 0;
00201 int encoding_len = 0;
00202
00203
00204
00205
00206
00207 primary_len = get_primary_len(bundle, &dict, &dictionary_len,
00208 &primary_var_len);
00209 if (len < primary_len) {
00210 return -1;
00211 }
00212
00213 (void)log;
00214 log_debug(log, "primary length %zu (preamble %zu var length %zu)",
00215 primary_len,
00216 (sizeof(PrimaryBlock1) + SDNV::encoding_len(primary_var_len)),
00217 primary_var_len);
00218
00219
00220
00221
00222 PrimaryBlock1* primary1 = (PrimaryBlock1*)buf;
00223 primary1->version = CURRENT_VERSION;
00224 primary1->bundle_processing_flags = format_bundle_flags(bundle);
00225 primary1->class_of_service_flags = format_cos_flags(bundle);
00226 primary1->status_report_request_flags = format_srr_flags(bundle);
00227
00228 encoding_len = SDNV::encode(primary_var_len,
00229 &primary1->block_length[0], len - 3);
00230 ASSERT(encoding_len > 0);
00231 buf += (sizeof(PrimaryBlock1) + encoding_len);
00232 len -= (sizeof(PrimaryBlock1) + encoding_len);
00233
00234
00235
00236
00237 PrimaryBlock2* primary2 = (PrimaryBlock2*)buf;
00238
00239 get_dictionary_offsets(&dict, bundle->dest_,
00240 &primary2->dest_scheme_offset,
00241 &primary2->dest_ssp_offset);
00242
00243 get_dictionary_offsets(&dict, bundle->source_,
00244 &primary2->source_scheme_offset,
00245 &primary2->source_ssp_offset);
00246
00247 get_dictionary_offsets(&dict, bundle->custodian_,
00248 &primary2->custodian_scheme_offset,
00249 &primary2->custodian_ssp_offset);
00250
00251 get_dictionary_offsets(&dict, bundle->replyto_,
00252 &primary2->replyto_scheme_offset,
00253 &primary2->replyto_ssp_offset);
00254
00255 set_timestamp(&primary2->creation_ts, &bundle->creation_ts_);
00256 u_int32_t lifetime = htonl(bundle->expiration_);
00257 memcpy(&primary2->lifetime, &lifetime, sizeof(lifetime));
00258
00259 buf += sizeof(PrimaryBlock2);
00260 len -= sizeof(PrimaryBlock2);
00261
00262
00263
00264
00265 encoding_len = SDNV::encode(dictionary_len, buf, len);
00266 ASSERT(encoding_len > 0);
00267 buf += encoding_len;
00268 len -= encoding_len;
00269
00270 DictionaryVector::iterator dict_iter;
00271 for (dict_iter = dict.begin(); dict_iter != dict.end(); ++dict_iter) {
00272 strcpy((char*)buf, dict_iter->str.c_str());
00273 buf += dict_iter->str.length() + 1;
00274 len -= dict_iter->str.length() + 1;
00275 }
00276
00277 if (oasys::__log_enabled(oasys::LOG_DEBUG, "/dtn/bundle/protocol/dictionary")) {
00278 oasys::StringBuffer dict_copy;
00279 ASSERT(buf[-1] == '\0');
00280 char* bp = (char*)buf - dictionary_len;
00281 while (bp != (char*)buf) {
00282 dict_copy.appendf("%s ", bp);
00283 bp += strlen(bp) + 1;
00284 }
00285
00286 log_debug("/dtn/bundle/protocol/dictionary",
00287 "len %zu, value: '%s'", dictionary_len, dict_copy.c_str());
00288
00289 log_debug("/dtn/bundle/protocol/dictionary",
00290 "offsets: dest %u,%u source %u,%u, "
00291 "custodian %u,%u replyto %u,%u",
00292 ntohs(primary2->dest_scheme_offset),
00293 ntohs(primary2->dest_ssp_offset),
00294 ntohs(primary2->source_scheme_offset),
00295 ntohs(primary2->source_ssp_offset),
00296 ntohs(primary2->custodian_scheme_offset),
00297 ntohs(primary2->custodian_ssp_offset),
00298 ntohs(primary2->replyto_scheme_offset),
00299 ntohs(primary2->replyto_ssp_offset));
00300 }
00301
00302
00303
00304
00305
00306 if (bundle->is_fragment_) {
00307 encoding_len = SDNV::encode(bundle->frag_offset_, buf, len);
00308 ASSERT(encoding_len > 0);
00309 buf += encoding_len;
00310 len -= encoding_len;
00311
00312 encoding_len = SDNV::encode(bundle->orig_length_, buf, len);
00313 ASSERT(encoding_len > 0);
00314 buf += encoding_len;
00315 len -= encoding_len;
00316 }
00317
00318 #ifndef NDEBUG
00319 {
00320 DictionaryVector dict2;
00321 size_t dict2_len = 0;
00322 size_t p2len;
00323 size_t len2 = get_primary_len(bundle, &dict2, &dict2_len, &p2len);
00324 ASSERT(len2 == (orig_len - len));
00325 }
00326 #endif
00327
00328
00329 ASSERT(primary_len == (orig_len - len));
00330
00331
00332
00333
00334
00335
00336
00337
00338 u_int32_t payload_len = bundle->payload_.length();
00339 if (len < (sizeof(BlockPreamble) +
00340 SDNV::encoding_len(payload_len)))
00341 {
00342 return -1;
00343 }
00344
00345 BlockPreamble* payload_block = (BlockPreamble*)buf;
00346 payload_block->type = PAYLOAD_BLOCK;
00347 payload_block->flags = BLOCK_FLAG_LAST_BLOCK;
00348 buf += sizeof(BlockPreamble);
00349 len -= sizeof(BlockPreamble);
00350
00351 encoding_len = SDNV::encode(payload_len, buf, len);
00352 ASSERT(encoding_len > 0);
00353 buf += encoding_len;
00354 len -= encoding_len;
00355
00356
00357 log_debug(log, "encoding done -- total length %zu", (orig_len - len));
00358 return orig_len - len;
00359 }
00360
00361
00362 int
00363 BundleProtocol::parse_header_blocks(Bundle* bundle,
00364 u_char* buf, size_t len)
00365 {
00366 static const char* log = "/dtn/bundle/protocol";
00367 size_t origlen = len;
00368 int encoding_len;
00369
00370
00371
00372
00373 PrimaryBlock1* primary1;
00374 if (len < sizeof(PrimaryBlock1)) {
00375 tooshort1:
00376 log_debug(log, "buffer too short (parsed %zu/%zu)",
00377 (origlen - len), origlen);
00378 return -1;
00379 }
00380
00381 primary1 = (PrimaryBlock1*)buf;
00382 buf += sizeof(PrimaryBlock1);
00383 len -= sizeof(PrimaryBlock1);
00384
00385 log_debug(log, "parsed primary block 1: version %d", primary1->version);
00386
00387 if (primary1->version != CURRENT_VERSION) {
00388 log_warn(log, "protocol version mismatch %d != %d",
00389 primary1->version, CURRENT_VERSION);
00390 return -1;
00391 }
00392
00393 parse_bundle_flags(bundle, primary1->bundle_processing_flags);
00394 parse_cos_flags(bundle, primary1->class_of_service_flags);
00395 parse_srr_flags(bundle, primary1->status_report_request_flags);
00396
00397
00398
00399
00400
00401 u_int32_t primary_len;
00402 encoding_len = SDNV::decode(buf, len, &primary_len);
00403 if (encoding_len == -1) {
00404 goto tooshort1;
00405 }
00406
00407 buf += encoding_len;
00408 len -= encoding_len;
00409
00410 log_debug(log, "parsed primary block length %u", primary_len);
00411
00412
00413
00414
00415
00416 if (len < primary_len) {
00417 goto tooshort1;
00418 }
00419
00420
00421
00422
00423
00424 if (len < sizeof(PrimaryBlock2)) {
00425 tooshort2:
00426 log_err(log, "primary block advertised incorrect length: "
00427 "advertised %u, total buffer %zu", primary_len, len);
00428 return -1;
00429 }
00430
00431
00432
00433
00434 PrimaryBlock2* primary2 = (PrimaryBlock2*)buf;
00435 buf += sizeof(PrimaryBlock2);
00436 len -= sizeof(PrimaryBlock2);
00437
00438 get_timestamp(&bundle->creation_ts_, &primary2->creation_ts);
00439 u_int32_t lifetime;
00440 memcpy(&lifetime, &primary2->lifetime, sizeof(lifetime));
00441 bundle->expiration_ = ntohl(lifetime);
00442
00443
00444
00445
00446 u_int32_t dictionary_len = 0;
00447 encoding_len = SDNV::decode(buf, len, &dictionary_len);
00448 if (encoding_len < 0) {
00449 goto tooshort2;
00450 }
00451 buf += encoding_len;
00452 len -= encoding_len;
00453
00454
00455
00456
00457 if (len < dictionary_len) {
00458 goto tooshort2;
00459 }
00460
00461
00462
00463
00464 if (buf[dictionary_len - 1] != '\0') {
00465 log_err(log, "dictionary does not end with a NULL character!");
00466 return -1;
00467 }
00468
00469
00470
00471
00472
00473
00474 u_char* dictionary = buf;
00475 buf += dictionary_len;
00476 len -= dictionary_len;
00477
00478 u_int16_t scheme_offset, ssp_offset;
00479
00480 if (oasys::__log_enabled(oasys::LOG_DEBUG, "/dtn/bundle/protocol/dictionary")) {
00481 oasys::StringBuffer dict_copy;
00482 ASSERT(buf[-1] == '\0');
00483 char* bp = (char*)buf - dictionary_len;
00484 while (bp != (char*)buf) {
00485 dict_copy.appendf("%s ", bp);
00486 bp += strlen(bp) + 1;
00487 }
00488
00489 log_debug("/dtn/bundle/protocol/dictionary",
00490 "len %u, value: '%s'", dictionary_len, dict_copy.c_str());
00491 }
00492
00493
00494 #define EXTRACT_DICTIONARY_EID(_what) \
00495 memcpy(&scheme_offset, &primary2->_what##_scheme_offset, 2); \
00496 memcpy(&ssp_offset, &primary2->_what##_ssp_offset, 2); \
00497 scheme_offset = ntohs(scheme_offset); \
00498 ssp_offset = ntohs(ssp_offset); \
00499 \
00500 if (scheme_offset >= (dictionary_len - 1)) { \
00501 log_err(log, "illegal offset for %s scheme dictionary offset: " \
00502 "offset %d, total length %u", #_what, \
00503 scheme_offset, dictionary_len); \
00504 return -1; \
00505 } \
00506 \
00507 if (ssp_offset >= (dictionary_len - 1)) { \
00508 log_err(log, "illegal offset for %s ssp dictionary offset: " \
00509 "offset %d, total length %u", #_what, \
00510 ssp_offset, dictionary_len); \
00511 return -1; \
00512 } \
00513 bundle->_what##_.assign((char*)&dictionary[scheme_offset], \
00514 (char*)&dictionary[ssp_offset]); \
00515 \
00516 \
00517 if (! bundle->_what##_.valid()) { \
00518 log_err(log, "invalid %s endpoint id '%s': " \
00519 "scheme '%s' offset %u ssp '%s' offset %u/%u", #_what, \
00520 bundle->_what##_.c_str(), \
00521 bundle->_what##_.scheme_str().c_str(), \
00522 scheme_offset, \
00523 bundle->_what##_.ssp().c_str(), \
00524 ssp_offset, dictionary_len); \
00525 return -1; \
00526 } \
00527 \
00528 log_debug(log, "parsed %s eid (offsets %d, %d) %s", #_what, \
00529 scheme_offset, ssp_offset, bundle->_what##_.c_str()); \
00530
00531 EXTRACT_DICTIONARY_EID(source);
00532 EXTRACT_DICTIONARY_EID(dest);
00533 EXTRACT_DICTIONARY_EID(custodian);
00534 EXTRACT_DICTIONARY_EID(replyto);
00535
00536 if (bundle->is_fragment_) {
00537 encoding_len = SDNV::decode(buf, len, &bundle->frag_offset_);
00538 if (encoding_len == -1) {
00539 goto tooshort2;
00540 }
00541 buf += encoding_len;
00542 len -= encoding_len;
00543
00544 encoding_len = SDNV::decode(buf, len, &bundle->orig_length_);
00545 if (encoding_len == -1) {
00546 goto tooshort2;
00547 }
00548 buf += encoding_len;
00549 len -= encoding_len;
00550
00551 log_debug(log, "parsed fragmentation info: offset %u, orig_len %u",
00552 bundle->frag_offset_, bundle->orig_length_);
00553 }
00554
00555
00556
00557
00558
00559 while (len != 0) {
00560 if (len <= sizeof(BlockPreamble)) {
00561 goto tooshort1;
00562 }
00563
00564 BlockPreamble* preamble = (BlockPreamble*)buf;
00565 buf += sizeof(BlockPreamble);
00566 len -= sizeof(BlockPreamble);
00567
00568
00569
00570
00571 u_int32_t block_len;
00572 encoding_len = SDNV::decode(buf, len, &block_len);
00573 if (encoding_len == -1) {
00574 goto tooshort1;
00575 }
00576 buf += encoding_len;
00577 len -= encoding_len;
00578
00579 switch (preamble->type) {
00580 case PAYLOAD_BLOCK: {
00581 bundle->payload_.set_length(block_len);
00582 log_debug(log, "parsed payload length %zu",
00583 bundle->payload_.length());
00584
00585
00586 if (! (preamble->flags & BLOCK_FLAG_LAST_BLOCK)) {
00587 log_crit(log,
00588 "this implementation cannot handle blocks after "
00589 "the payload!!");
00590 }
00591
00592
00593
00594
00595
00596 goto done;
00597 }
00598
00599 default:
00600
00601 log_err(log, "unknown block code 0x%x", preamble->type);
00602 return -1;
00603 }
00604 }
00605
00606
00607 done:
00608 return origlen - len;
00609 }
00610
00611
00612 size_t
00613 BundleProtocol::header_block_length(const Bundle* bundle)
00614 {
00615 DictionaryVector dict;
00616 size_t dictionary_len;
00617 size_t primary_var_len;
00618
00619
00620
00621 return (get_primary_len(bundle, &dict, &dictionary_len, &primary_var_len) +
00622 get_payload_block_len(bundle));
00623 }
00624
00625
00626 size_t
00627 BundleProtocol::formatted_length(const Bundle* bundle)
00628 {
00629 return header_block_length(bundle) +
00630 bundle->payload_.length() +
00631 tail_block_length(bundle);
00632 }
00633
00634
00635 int
00636 BundleProtocol::format_bundle(const Bundle* bundle, u_char* buf, size_t len)
00637 {
00638 size_t origlen = len;
00639
00640
00641 int ret = format_header_blocks(bundle, buf, len);
00642 if (ret < 0) {
00643 return ret;
00644 }
00645 buf += ret;
00646 len -= ret;
00647
00648
00649 size_t payload_len = bundle->payload_.length();
00650 if (payload_len > len) {
00651 return -1;
00652 }
00653 bundle->payload_.read_data(0, payload_len, buf,
00654 BundlePayload::FORCE_COPY);
00655 len -= payload_len;
00656 buf += payload_len;
00657
00658 ret = format_tail_blocks(bundle, buf, len);
00659 if (ret < 0) {
00660 return ret;
00661 }
00662 len -= ret;
00663 buf += ret;
00664
00665 return origlen - len;
00666 }
00667
00668
00669 int
00670 BundleProtocol::parse_bundle(Bundle* bundle, u_char* buf, size_t len)
00671 {
00672 size_t origlen = len;
00673
00674
00675 int ret = parse_header_blocks(bundle, buf, len);
00676 if (ret < 0) {
00677 return ret;
00678 }
00679 buf += ret;
00680 len -= ret;
00681
00682
00683 size_t payload_len = bundle->payload_.length();
00684 if (payload_len > len) {
00685 return -1;
00686 }
00687 bundle->payload_.set_data(buf, payload_len);
00688 len -= payload_len;
00689 buf += payload_len;
00690
00691 ret = parse_tail_blocks(bundle, buf, len);
00692 if (ret < 0) {
00693 return ret;
00694 }
00695 len -= ret;
00696 buf += ret;
00697
00698 return origlen - len;
00699 }
00700
00701
00702 void
00703 BundleProtocol::set_timestamp(u_char* ts, const BundleTimestamp* tv)
00704 {
00705 u_int32_t tmp;
00706
00707 tmp = htonl(tv->seconds_);
00708 memcpy(ts, &tmp, sizeof(u_int32_t));
00709 ts += sizeof(u_int32_t);
00710
00711 tmp = htonl(tv->seqno_);
00712 memcpy(ts, &tmp, sizeof(u_int32_t));
00713 }
00714
00715
00716 void
00717 BundleProtocol::get_timestamp(BundleTimestamp* tv, const u_char* ts)
00718 {
00719 u_int32_t tmp;
00720
00721 memcpy(&tmp, ts, sizeof(u_int32_t));
00722 tv->seconds_ = ntohl(tmp);
00723 ts += sizeof(u_int32_t);
00724
00725 memcpy(&tmp, ts, sizeof(u_int32_t));
00726 tv->seqno_ = ntohl(tmp);
00727 }
00728
00729
00730 u_int8_t
00731 BundleProtocol::format_bundle_flags(const Bundle* bundle)
00732 {
00733 u_int8_t flags = 0;
00734
00735 if (bundle->is_fragment_) {
00736 flags |= BUNDLE_IS_FRAGMENT;
00737 }
00738
00739 if (bundle->is_admin_) {
00740 flags |= BUNDLE_IS_ADMIN;
00741 }
00742
00743 if (bundle->do_not_fragment_) {
00744 flags |= BUNDLE_DO_NOT_FRAGMENT;
00745 }
00746
00747 if (bundle->custody_requested_) {
00748 flags |= BUNDLE_CUSTODY_XFER_REQUESTED;
00749 }
00750
00751 if (bundle->singleton_dest_) {
00752 flags |= BUNDLE_SINGLETON_DESTINATION;
00753 }
00754
00755 return flags;
00756 }
00757
00758
00759 void
00760 BundleProtocol::parse_bundle_flags(Bundle* bundle, u_int8_t flags)
00761 {
00762 if (flags & BUNDLE_IS_FRAGMENT) {
00763 bundle->is_fragment_ = true;
00764 }
00765
00766 if (flags & BUNDLE_IS_ADMIN) {
00767 bundle->is_admin_ = true;
00768 }
00769
00770 if (flags & BUNDLE_DO_NOT_FRAGMENT) {
00771 bundle->do_not_fragment_ = true;
00772 }
00773
00774 if (flags & BUNDLE_CUSTODY_XFER_REQUESTED) {
00775 bundle->custody_requested_ = true;
00776 }
00777
00778 if (flags & BUNDLE_SINGLETON_DESTINATION) {
00779 bundle->singleton_dest_ = true;
00780 }
00781 }
00782
00783
00784 u_int8_t
00785 BundleProtocol::format_cos_flags(const Bundle* b)
00786 {
00787 u_int8_t cos_flags = 0;
00788
00789 cos_flags = ((b->priority_ & 0x3) << 6);
00790
00791 return cos_flags;
00792 }
00793
00794
00795 void
00796 BundleProtocol::parse_cos_flags(Bundle* b, u_int8_t cos_flags)
00797 {
00798 b->priority_ = ((cos_flags >> 6) & 0x3);
00799 }
00800
00801
00802 u_int8_t
00803 BundleProtocol::format_srr_flags(const Bundle* b)
00804 {
00805 u_int8_t srr_flags = 0;
00806
00807 if (b->receive_rcpt_)
00808 srr_flags |= STATUS_RECEIVED;
00809
00810 if (b->custody_rcpt_)
00811 srr_flags |= STATUS_CUSTODY_ACCEPTED;
00812
00813 if (b->forward_rcpt_)
00814 srr_flags |= STATUS_FORWARDED;
00815
00816 if (b->delivery_rcpt_)
00817 srr_flags |= STATUS_DELIVERED;
00818
00819 if (b->deletion_rcpt_)
00820 srr_flags |= STATUS_DELETED;
00821
00822 if (b->app_acked_rcpt_)
00823 srr_flags |= STATUS_ACKED_BY_APP;
00824
00825 return srr_flags;
00826 }
00827
00828
00829 void
00830 BundleProtocol::parse_srr_flags(Bundle* b, u_int8_t srr_flags)
00831 {
00832 if (srr_flags & STATUS_RECEIVED)
00833 b->receive_rcpt_ = true;
00834
00835 if (srr_flags & STATUS_CUSTODY_ACCEPTED)
00836 b->custody_rcpt_ = true;
00837
00838 if (srr_flags & STATUS_FORWARDED)
00839 b->forward_rcpt_ = true;
00840
00841 if (srr_flags & STATUS_DELIVERED)
00842 b->delivery_rcpt_ = true;
00843
00844 if (srr_flags & STATUS_DELETED)
00845 b->deletion_rcpt_ = true;
00846
00847 if (srr_flags & STATUS_ACKED_BY_APP)
00848 b->app_acked_rcpt_ = true;
00849 }
00850
00851
00852 bool
00853 BundleProtocol::get_admin_type(const Bundle* bundle, admin_record_type_t* type)
00854 {
00855 if (! bundle->is_admin_) {
00856 return false;
00857 }
00858
00859 u_char buf[16];
00860 const u_char* bp = bundle->payload_.read_data(0, sizeof(buf), buf);
00861
00862 switch (bp[0] >> 4)
00863 {
00864 #define CASE(_what) case _what: *type = _what; return true;
00865
00866 CASE(ADMIN_STATUS_REPORT);
00867 CASE(ADMIN_CUSTODY_SIGNAL);
00868 CASE(ADMIN_ECHO);
00869 CASE(ADMIN_NULL);
00870 CASE(ADMIN_ANNOUNCE);
00871
00872 #undef CASE
00873 default:
00874 return false;
00875 }
00876
00877 NOTREACHED;
00878 }
00879
00880 }