diff -r 000000000000 -r 2b3e5ec03512 servlib/bundling/Dictionary.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlib/bundling/Dictionary.cc Thu Apr 21 14:57:45 2011 +0100 @@ -0,0 +1,298 @@ +/* + * Copyright 2006 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Dictionary.h" +#include + +namespace dtn { + +//---------------------------------------------------------------------- +Dictionary::Dictionary() + : dict_(NULL), dict_length_(0), length_(0) +{ +} + +//---------------------------------------------------------------------- +Dictionary::Dictionary(const oasys::Builder&) + : dict_(NULL), dict_length_(0), length_(0) +{ +} + +//---------------------------------------------------------------------- +Dictionary::~Dictionary() +{ + if (dict_) { + free(dict_); + dict_ = 0; + dict_length_ = 0; + length_ = 0; + } +} + +//---------------------------------------------------------------------- +void +Dictionary::set_dict(const u_char* dict, u_int32_t length) +{ + ASSERT(dict_ == NULL); + dict_ = (u_char*)malloc(length); + memcpy(dict_, dict, length); + length_ = dict_length_ = length; +} + +//---------------------------------------------------------------------- +bool +Dictionary::get_offset(const std::string& str, u_int32_t* offset) +{ + *offset = 0; + while (*offset < length_) { + u_int32_t len = strlen((char*)(&dict_[*offset])); + if (!strncmp(str.c_str(), (char*)(&dict_[*offset]), len)) { + if (str.length() == len) { + return true; // already there + } + } + *offset += (len + 1); + ASSERT(*offset <= length_); + } + + return false; +} + +//---------------------------------------------------------------------- +bool +Dictionary::get_offset(const std::string& str, u_int64_t* offset) +{ + *offset = 0; + while (*offset < length_) { + u_int64_t len = strlen((char*)(&dict_[*offset])); + if (!strncmp(str.c_str(), (char*)(&dict_[*offset]), len)) { + if (str.length() == len) { + return true; // already there + } + } + *offset += (len + 1); + ASSERT(*offset <= length_); + } + + return false; +} + +//---------------------------------------------------------------------- +void +Dictionary::add_str(const std::string& str) +{ + u_int32_t offset; + if (get_offset(str, &offset)) { + return; + } + + if (dict_length_ < length_ + str.length() + 1) { + do { + dict_length_ = (dict_length_ == 0) ? 64 : dict_length_ * 2; + } while (dict_length_ < length_ + str.length() + 1); + + dict_ = (u_char*)realloc(dict_, dict_length_); + } + + memcpy(&dict_[length_], str.data(), str.length()); + dict_[length_ + str.length()] = '\0'; + length_ += str.length() + 1; +} + + +//---------------------------------------------------------------------- +void +Dictionary::serialize(oasys::SerializeAction* a) +{ + a->process("dict", dict_, length_); + a->process("dict_length", &dict_length_); + a->process("length", &length_); +} + +//---------------------------------------------------------------------- +bool +Dictionary::extract_eid(EndpointID* eid, + u_int32_t scheme_offset, + u_int32_t ssp_offset) +{ + static const char* log = "/dtn/bundle/protocol"; + + // If there's nothing in the dictionary, return + if (dict_length_ == 0) { + log_err_p(log, "cannot extract eid from zero-length dictionary"); + return false; + } + + if (scheme_offset >= (dict_length_ - 1)) { + log_err_p(log, "illegal offset for scheme dictionary offset: " + "offset %d, total length %u", + scheme_offset, dict_length_); + return false; + } + + if (ssp_offset >= (dict_length_ - 1)) { + log_err_p(log, "illegal offset for ssp dictionary offset: " + "offset %d, total length %u", + ssp_offset, dict_length_); + return false; + } + + eid->assign((char*)&dict_[scheme_offset], + (char*)&dict_[ssp_offset]); + + if (! eid->valid()) { + log_err_p(log, "invalid endpoint id '%s': " + "scheme '%s' offset %u/%u ssp '%s' offset %u/%u", + eid->c_str(), + eid->scheme_str().c_str(), + scheme_offset, dict_length_, + eid->ssp().c_str(), + ssp_offset, dict_length_); + return false; + } + + log_debug_p(log, "parsed eid (offsets %u, %u) %s", + scheme_offset, ssp_offset, eid->c_str()); + return true; +} + +//---------------------------------------------------------------------- +bool +Dictionary::extract_eid(EndpointID* eid, + u_int64_t scheme_offset, + u_int64_t ssp_offset) +{ + u_int32_t scheme_offset32 = scheme_offset; + u_int32_t ssp_offset32 = ssp_offset; + + return extract_eid(eid, scheme_offset32, ssp_offset32); +} + +#if 0 +// the routines here are slightly different from those +// in PrimaryBlockProcessor.cc although the functionality +// appears to be the same +///XXX-pl TODO check to see + +//---------------------------------------------------------------------- +void +PrimaryBlockProcessor::get_dictionary_offsets(DictionaryVector *dict, + const EndpointID& eid, + u_int16_t* scheme_offset, + u_int16_t* ssp_offset) +{ + DictionaryVector::iterator iter; + for (iter = dict->begin(); iter != dict->end(); ++iter) { + if (iter->str == eid.scheme_str()) + *scheme_offset = htons(iter->offset); + + if (iter->str == eid.ssp()) + *ssp_offset = htons(iter->offset); + } +} + +//---------------------------------------------------------------------- +bool +PrimaryBlockProcessor::extract_dictionary_eid(EndpointID* eid, + const char* what, + u_int16_t* scheme_offsetp, + u_int16_t* ssp_offsetp, + u_char* dictionary, + u_int32_t dictionary_len) +{ + static const char* log = "/dtn/bundle/protocol"; + u_int16_t scheme_offset, ssp_offset; + memcpy(&scheme_offset, scheme_offsetp, 2); + memcpy(&ssp_offset, ssp_offsetp, 2); + scheme_offset = ntohs(scheme_offset); + ssp_offset = ntohs(ssp_offset); + + if (scheme_offset >= (dictionary_len - 1)) { + log_err_p(log, "illegal offset for %s scheme dictionary offset: " + "offset %d, total length %u", what, + scheme_offset, dictionary_len); + return false; + } + + if (ssp_offset >= (dictionary_len - 1)) { + log_err_p(log, "illegal offset for %s ssp dictionary offset: " + "offset %d, total length %u", what, + ssp_offset, dictionary_len); + return false; + } + + eid->assign((char*)&dictionary[scheme_offset], + (char*)&dictionary[ssp_offset]); + + if (! eid->valid()) { + log_err_p(log, "invalid %s endpoint id '%s': " + "scheme '%s' offset %u/%u ssp '%s' offset %u/%u", + what, eid->c_str(), + eid->scheme_str().c_str(), + scheme_offset, dictionary_len, + eid->ssp().c_str(), + ssp_offset, dictionary_len); + return false; + } + + log_debug_p(log, "parsed %s eid (offsets %u, %u) %s", + what, scheme_offset, ssp_offset, eid->c_str()); + return true; +} + +//---------------------------------------------------------------------- +void +PrimaryBlockProcessor::debug_dump_dictionary(const char* bp, u_int32_t len, + PrimaryBlock2* primary2) +{ +#ifndef NDEBUG + oasys::StringBuffer dict_copy; + + const char* end = bp + len; + ASSERT(end[-1] == '\0'); + + while (bp != end) { + dict_copy.appendf("%s ", bp); + bp += strlen(bp) + 1; + } + + log_debug_p("/dtn/bundle/protocol", + "dictionary len %zu, value: '%s'", len, dict_copy.c_str()); + + log_debug_p("/dtn/bundle/protocol", + "dictionary offsets: dest %u,%u source %u,%u, " + "custodian %u,%u replyto %u,%u", + ntohs(primary2->dest_scheme_offset), + ntohs(primary2->dest_ssp_offset), + ntohs(primary2->source_scheme_offset), + ntohs(primary2->source_ssp_offset), + ntohs(primary2->custodian_scheme_offset), + ntohs(primary2->custodian_ssp_offset), + ntohs(primary2->replyto_scheme_offset), + ntohs(primary2->replyto_ssp_offset)); +#else + (void)bp; + (void)len; + (void)primary2; +#endif +} +#endif /* zero */ + +} // namespace dtn