00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include "SequenceIDBlockProcessor.h"
00022 #include "Bundle.h"
00023 #include "BundleDaemon.h"
00024 #include "BundleProtocol.h"
00025 #include "contacts/Link.h"
00026 #include "SDNV.h"
00027
00028 namespace dtn {
00029
00030
00031 SequenceIDBlockProcessor::SequenceIDBlockProcessor(u_int8_t block_type)
00032 : BlockProcessor(block_type)
00033 {
00034 ASSERT(block_type == BundleProtocol::SEQUENCE_ID_BLOCK ||
00035 block_type == BundleProtocol::OBSOLETES_ID_BLOCK);
00036 }
00037
00038
00039 int
00040 SequenceIDBlockProcessor::prepare(const Bundle* bundle,
00041 BlockInfoVec* xmit_blocks,
00042 const BlockInfo* source,
00043 const LinkRef& link,
00044 BlockInfo::list_owner_t list)
00045 {
00046 const SequenceID& sequence_id =
00047 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00048 bundle->sequence_id() :
00049 bundle->obsoletes_id();
00050
00051 if (sequence_id.empty()) {
00052 return BP_SUCCESS;
00053 }
00054
00055 BlockProcessor::prepare(bundle, xmit_blocks, source, link, list);
00056 return BP_SUCCESS;
00057 }
00058
00059
00060 int
00061 SequenceIDBlockProcessor::generate(const Bundle* bundle,
00062 BlockInfoVec* xmit_blocks,
00063 BlockInfo* block,
00064 const LinkRef& link,
00065 bool last)
00066 {
00067 (void)link;
00068
00069 const SequenceID& sequence_id =
00070 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00071 bundle->sequence_id() :
00072 bundle->obsoletes_id();
00073
00074 size_t length = 0;
00075
00076
00077
00078 SequenceID::const_iterator iter;
00079 for (iter = sequence_id.begin(); iter != sequence_id.end(); ++iter)
00080 {
00081 block->add_eid(iter->eid_);
00082
00083 length += 1;
00084
00085 if (iter->type_ == SequenceID::COUNTER) {
00086 length += SDNV::encoding_len(iter->counter_);
00087 } else if (iter->type_ == SequenceID::IDENTIFIER) {
00088 length += SDNV::encoding_len(iter->identifier_.length());
00089 length += iter->identifier_.length();
00090 } else {
00091 NOTREACHED;
00092 }
00093 }
00094
00095 generate_preamble(xmit_blocks,
00096 block,
00097 block_type(),
00098 BundleProtocol::BLOCK_FLAG_REPLICATE |
00099 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00100 length);
00101
00102 BlockInfo::DataBuffer* contents = block->writable_contents();
00103 contents->reserve(block->data_offset() + length);
00104 contents->set_len(block->data_offset() + length);
00105
00106 u_int8_t* bp = contents->buf() + block->data_offset();
00107 for (iter = sequence_id.begin(); iter != sequence_id.end(); ++iter)
00108 {
00109
00110 *bp++ = static_cast<u_int8_t>(iter->type_);
00111 length--;
00112
00113 if (iter->type_ == SequenceID::COUNTER)
00114 {
00115 int len = SDNV::encode(iter->counter_, bp, length);
00116 ASSERT(len > 0);
00117 bp += len;
00118 length -= len;
00119 }
00120 else
00121 {
00122 size_t id_len = iter->identifier_.length();
00123 int sdnv_len = SDNV::encode(id_len, bp, length);
00124 ASSERT(sdnv_len > 0);
00125 bp += sdnv_len;
00126 length -= sdnv_len;
00127
00128 ASSERT(length >= id_len);
00129 memcpy(bp, iter->identifier_.data(), id_len);
00130 bp += id_len;
00131 length -= id_len;
00132 }
00133 }
00134
00135 ASSERT(length == 0);
00136
00137 return BP_SUCCESS;
00138 }
00139
00140
00141 int
00142 SequenceIDBlockProcessor::consume(Bundle* bundle, BlockInfo* block,
00143 u_char* buf, size_t len)
00144 {
00145 SequenceID* mutable_sequence_id =
00146 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00147 bundle->mutable_sequence_id() :
00148 bundle->mutable_obsoletes_id();
00149
00150 int cc = BlockProcessor::consume(bundle, block, buf, len);
00151
00152 if (cc == -1) {
00153 return -1;
00154 }
00155
00156 if (! block->complete()) {
00157 ASSERT(cc == (int)len);
00158 return cc;
00159 }
00160
00161 size_t count = block->eid_list().size();
00162 if (count == 0) {
00163 log_err_p("/dtn/bundle/protocol",
00164 "error parsing sequence id block -- no eids in list");
00165 return -1;
00166 }
00167
00168 size_t length = block->data_length();
00169 u_char* bp = block->data();
00170
00171 for (size_t i = 0; i < count; ++i)
00172 {
00173 u_int8_t type = *bp++;
00174 length--;
00175
00176 if (type == SequenceID::COUNTER)
00177 {
00178 u_int64_t counter;
00179 int sdnv_len = SDNV::decode(bp, length, &counter);
00180 if (sdnv_len == -1) {
00181 return -1;
00182 }
00183
00184 bp += sdnv_len;
00185 length -= sdnv_len;
00186
00187 log_debug_p("/dtn/bundle/protocol",
00188 "parsed %s id entry %s %llu",
00189 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00190 "sequence" : "obsoletes",
00191 block->eid_list()[i].c_str(), U64FMT(counter));
00192
00193 mutable_sequence_id->add(block->eid_list()[i], counter);
00194 }
00195 else if (type == SequenceID::IDENTIFIER)
00196 {
00197 u_int64_t id_len;
00198 int sdnv_len = SDNV::decode(bp, length, &id_len);
00199 if (sdnv_len == -1) {
00200 return -1;
00201 }
00202
00203 bp += sdnv_len;
00204 length -= sdnv_len;
00205
00206 std::string id_str(reinterpret_cast<const char*>(bp),
00207 static_cast<size_t>(id_len));
00208
00209 log_debug_p("/dtn/bundle/protocol",
00210 "parsed %s id entry %s %s",
00211 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00212 "sequence" : "obsoletes",
00213 block->eid_list()[i].c_str(), id_str.c_str());
00214
00215 mutable_sequence_id->add(block->eid_list()[i], id_str);
00216
00217 bp += id_len;
00218 length -= id_len;
00219 }
00220 else
00221 {
00222 log_warn_p("/dtn/bundle/protocol",
00223 "invalid type code %u for %s block entry", type,
00224 (block_type() == BundleProtocol::SEQUENCE_ID_BLOCK) ?
00225 "sequence" : "obsoletes");
00226 return -1;
00227 }
00228 }
00229
00230 return cc;
00231 }
00232
00233 }