00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <dtn-config.h>
00024 #endif
00025
00026 #include "MetadataBlockProcessor.h"
00027 #include "MetadataBlock.h"
00028 #include "Bundle.h"
00029 #include "SDNV.h"
00030
00031 namespace dtn {
00032
00033
00034 MetadataBlockProcessor::MetadataBlockProcessor()
00035 : BlockProcessor(BundleProtocol::METADATA_BLOCK)
00036 {
00037 }
00038
00039
00040 int
00041 MetadataBlockProcessor::consume(Bundle* bundle,
00042 BlockInfo* block,
00043 u_char* buf,
00044 size_t len)
00045 {
00046 ASSERT(bundle != NULL);
00047 ASSERT(block != NULL);
00048
00049 int cc = BlockProcessor::consume(bundle, block, buf, len);
00050
00051 if (cc == -1) {
00052 return -1;
00053 }
00054
00055 if (!block->complete()) {
00056 ASSERT(cc == (int)len);
00057 return cc;
00058 }
00059
00060 parse_metadata(bundle, block);
00061
00062 return cc;
00063 }
00064
00065
00066 bool
00067 MetadataBlockProcessor::validate(const Bundle* bundle,
00068 BlockInfoVec* block_list,
00069 BlockInfo* block,
00070 status_report_reason_t* reception_reason,
00071 status_report_reason_t* deletion_reason)
00072 {
00073 static const char* log = "/dtn/bundle/protocol";
00074 (void)log;
00075
00076 ASSERT(bundle != NULL);
00077 ASSERT(block != NULL);
00078 ASSERT(block->owner() == this);
00079 ASSERT(block->type() == BundleProtocol::METADATA_BLOCK);
00080
00081 MetadataBlock *metablock = dynamic_cast<MetadataBlock*>(block->locals());
00082 ASSERT(metablock != NULL);
00083
00084 if (metablock->error()) {
00085 log_debug_p(log, "MetadataBlockProcessor::validate: "
00086 "error in metadata block preamble");
00087 return handle_error(block, reception_reason, deletion_reason);
00088 }
00089
00090
00091 if (!BlockProcessor::validate(bundle, block_list, block,
00092 reception_reason, deletion_reason)) {
00093 metablock->set_block_error();
00094 return false;
00095 }
00096
00097 return true;
00098 }
00099
00100
00101 int
00102 MetadataBlockProcessor::prepare(const Bundle* bundle,
00103 BlockInfoVec* xmit_blocks,
00104 const BlockInfo* source,
00105 const LinkRef& link,
00106 list_owner_t list)
00107 {
00108 static const char* log = "/dtn/bundle/protocol";
00109 (void)log;
00110
00111 ASSERT(bundle != NULL);
00112 ASSERT(xmit_blocks != NULL);
00113
00114
00115 if (source == NULL) {
00116 return BP_FAIL;
00117 }
00118
00119 ASSERT(source != NULL);
00120 ASSERT(source->owner() == this);
00121 ASSERT(source->type() == BundleProtocol::METADATA_BLOCK);
00122
00123 MetadataBlock* source_metadata =
00124 dynamic_cast<MetadataBlock*>(source->locals());
00125
00126
00127
00128 if (source_metadata == NULL) {
00129 log_debug_p(log, "MetadataBlockProcessor::prepare: "
00130 "invalid NULL source metadata");
00131 return BP_FAIL;
00132 }
00133
00134 oasys::ScopeLock metadata_lock(source_metadata->lock(),
00135 "MetadataBlockProcessor::prepare");
00136
00137
00138 if (source_metadata->error() &&
00139 (source->flags() & BundleProtocol::BLOCK_FLAG_DISCARD_BLOCK_ONERROR)) {
00140 return BP_FAIL;
00141 }
00142
00143
00144 if (source_metadata->metadata_removed(link)) {
00145 return BP_FAIL;
00146 }
00147
00148 BlockProcessor::prepare(bundle, xmit_blocks, source, link, list);
00149
00150 return BP_SUCCESS;
00151 }
00152
00153
00154 void
00155 MetadataBlockProcessor::prepare_generated_metadata(Bundle* bundle,
00156 BlockInfoVec* blocks,
00157 const LinkRef& link)
00158 {
00159 ASSERT(bundle != NULL);
00160 ASSERT(blocks != NULL);
00161
00162 oasys::ScopeLock bundle_lock(bundle->lock(),
00163 "MetadataBlockProcessor::prepare_generated_metadata");
00164
00165
00166 const MetadataVec* metadata =
00167 bundle->generated_metadata().find_blocks(link);
00168 if (metadata != NULL) {
00169 MetadataVec::const_iterator iter;
00170 for (iter = metadata->begin(); iter != metadata->end(); ++iter) {
00171 if ((*iter)->metadata_len() > 0) {
00172 blocks->push_back(BlockInfo(this));
00173 blocks->back().set_locals(iter->object());
00174 }
00175 }
00176 }
00177
00178
00179 LinkRef null_link("MetadataBlockProcessor::prepare_generated_metadata");
00180 const MetadataVec*
00181 nulldata = bundle->generated_metadata().find_blocks(null_link);
00182
00183 if (nulldata != NULL) {
00184 MetadataVec::const_iterator iter;
00185 for (iter = nulldata->begin(); iter != nulldata->end(); ++iter) {
00186 bool link_specific = false;
00187 if (metadata != NULL) {
00188 MetadataVec::const_iterator liter = metadata->begin();
00189 for ( ; liter != metadata->end(); ++liter) {
00190 if ((*liter)->source() &&
00191 ((*liter)->source_id() == (*iter)->id())) {
00192 link_specific = true;
00193 break;
00194 }
00195 }
00196 }
00197
00198 if (link_specific) {
00199 continue;
00200 }
00201
00202 blocks->push_back(BlockInfo(this));
00203 blocks->back().set_locals(iter->object());
00204 }
00205 }
00206 }
00207
00208
00209 int
00210 MetadataBlockProcessor::generate(const Bundle* bundle,
00211 BlockInfoVec* xmit_blocks,
00212 BlockInfo* block,
00213 const LinkRef& link,
00214 bool last)
00215 {
00216 (void)xmit_blocks;
00217
00218 ASSERT(bundle != NULL);
00219 ASSERT(block != NULL);
00220 ASSERT(block->owner() == this);
00221
00222
00223
00224 MetadataBlock* metadata = NULL;
00225 bool received_block = false;
00226 bool generated_block = false;
00227
00228 if (block->source() != NULL) {
00229 ASSERT(block->source()->owner() == this);
00230 received_block = true;
00231 metadata = dynamic_cast<MetadataBlock*>(block->source()->locals());
00232 ASSERT(metadata != NULL);
00233 }
00234
00235 if (block->locals() != NULL) {
00236 generated_block = true;
00237 metadata = dynamic_cast<MetadataBlock*>(block->locals());
00238 ASSERT(metadata != NULL);
00239 }
00240
00241 ASSERT(received_block || generated_block);
00242 ASSERT(!(received_block && generated_block));
00243 ASSERT(metadata != NULL);
00244
00245 oasys::ScopeLock metadata_lock(metadata->lock(),
00246 "MetadataBlockProcessor::generate");
00247
00248 if (received_block && metadata->error()) {
00249 ASSERT((block->source()->flags() &
00250 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR) == 0);
00251 ASSERT((block->source()->flags() &
00252 BundleProtocol::BLOCK_FLAG_DISCARD_BLOCK_ONERROR) == 0);
00253 }
00254
00255
00256 u_char* buf = NULL;
00257 u_int32_t len = 0;
00258
00259
00260
00261 bool modified = (received_block ?
00262 metadata->metadata_modified(link, &buf, len) : false);
00263
00264
00265 size_t block_data_len;
00266 if (received_block && !modified) {
00267 block_data_len = block->source()->data_length();
00268
00269 } else {
00270 if (!modified) {
00271 buf = metadata->metadata();
00272 len = metadata->metadata_len();
00273 }
00274
00275
00276
00277 block_data_len = SDNV::encoding_len(metadata->ontology()) +
00278 SDNV::encoding_len(len) + len;
00279 }
00280
00281
00282 u_int8_t flags = 0;
00283 if (received_block) {
00284 flags = block->source()->flags();
00285 } else {
00286 flags |= metadata->flags();
00287 }
00288 if (last) {
00289 flags |= BundleProtocol::BLOCK_FLAG_LAST_BLOCK;
00290 } else {
00291 flags &= ~BundleProtocol::BLOCK_FLAG_LAST_BLOCK;
00292 }
00293
00294
00295
00296 generate_preamble(xmit_blocks, block, block_type(), flags, block_data_len);
00297 block->writable_contents()->reserve(block->data_offset() + block_data_len);
00298 block->writable_contents()->set_len(block->data_offset() + block_data_len);
00299
00300
00301
00302
00303 if (received_block && !modified) {
00304 memcpy(block->writable_contents()->buf() + block->data_offset(),
00305 block->source()->contents().buf() + block->data_offset(),
00306 block->data_length());
00307 return BP_SUCCESS;
00308 }
00309
00310
00311 u_char* outgoing_buf = block->writable_contents()->buf() +
00312 block->data_offset();
00313 u_int32_t outgoing_len = block_data_len;
00314
00315
00316 size_t sdnv_len = SDNV::encode(metadata->ontology(),
00317 outgoing_buf, outgoing_len);
00318 ASSERT(sdnv_len > 0);
00319 outgoing_buf += sdnv_len;
00320 outgoing_len -= sdnv_len;
00321
00322
00323 sdnv_len = SDNV::encode(len, outgoing_buf, outgoing_len);
00324 ASSERT(sdnv_len > 0);
00325 outgoing_buf += sdnv_len;
00326 outgoing_len -= sdnv_len;
00327
00328
00329 ASSERT(block->contents().nfree() >= len);
00330 memcpy(outgoing_buf, buf, outgoing_len);
00331
00332 return BP_SUCCESS;
00333 }
00334
00335
00336 bool
00337 MetadataBlockProcessor::parse_metadata(Bundle* bundle, BlockInfo* block)
00338 {
00339 static const char* log = "/dtn/bundle/protocol";
00340
00341 ASSERT(bundle != NULL);
00342 ASSERT(block != NULL);
00343 ASSERT(block->owner() == this);
00344 ASSERT(block->type() == BundleProtocol::METADATA_BLOCK);
00345 ASSERT(block->complete());
00346 ASSERT(block->data_offset() > 0);
00347
00348
00349
00350 MetadataBlock* metadata = new MetadataBlock(block);
00351 bundle->mutable_recv_metadata()->push_back(metadata);
00352
00353 block->set_locals(metadata);
00354
00355
00356 u_char * buf = block->data();
00357 u_int32_t len = block->data_length();
00358
00359
00360 int ontology_len = 0;
00361 u_int64_t ontology = 0;
00362 if ((ontology_len = SDNV::decode(buf, len, &ontology)) < 0) {
00363 log_err_p(log, "MetadataBlockProcessor::parse_metadata_ontology: "
00364 "invalid ontology field length");
00365 metadata->set_block_error();
00366 return false;
00367 }
00368 buf += ontology_len;
00369 len -= ontology_len;
00370
00371 metadata->set_ontology(ontology);
00372
00373
00374
00375
00376
00377
00378 int length_len = 0;
00379 u_int64_t length = 0;
00380 if ((length_len = SDNV::decode(buf, len, &length)) < 0) {
00381 log_err_p(log, "MetadataBlockProcessor::parse_metadata_ontology: "
00382 "invalid ontology length field length");
00383 metadata->set_block_error();
00384 return false;
00385 }
00386 buf += length_len;
00387 len -= length_len;
00388
00389 if (len != length) {
00390 log_err_p(log, "MetadataBlockProcessor::parse_metadata_ontology: "
00391 "ontology length fails to match remaining block length");
00392 metadata->set_block_error();
00393 return false;
00394 }
00395
00396
00397 metadata->set_metadata(buf, len);
00398
00399 return true;
00400 }
00401
00402
00403 bool
00404 MetadataBlockProcessor::handle_error(const BlockInfo* block,
00405 status_report_reason_t* reception_reason,
00406 status_report_reason_t* deletion_reason)
00407 {
00408 if (block->flags() & BundleProtocol::BLOCK_FLAG_REPORT_ONERROR) {
00409 *reception_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00410 }
00411
00412 if (block->flags() & BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR) {
00413 *deletion_reason = BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE;
00414 return false;
00415 }
00416
00417 return true;
00418 }
00419
00420
00421 void
00422 MetadataBlockProcessor::delete_generated_metadata(Bundle* bundle,
00423 const LinkRef& link)
00424 {
00425 ASSERT(bundle != NULL);
00426
00427 bundle->mutable_generated_metadata()->delete_blocks(link);
00428
00429 MetadataVec::const_iterator iter;
00430 for (iter = bundle->recv_metadata().begin();
00431 iter != bundle->recv_metadata().end(); ++iter)
00432 {
00433 (*iter)->delete_outgoing_metadata(link);
00434 }
00435 }
00436
00437 }