servlib/bundling/Dictionary.cc
changeset 0 2b3e5ec03512
--- /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 <dtn-config.h>
+#endif
+
+#include "Dictionary.h"
+#include <oasys/debug/Log.h>
+
+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