servlib/bundling/BPQBlock.cc
changeset 64 1296a0283271
parent 55 1938118cd06c
child 65 333724f2f7cf
--- a/servlib/bundling/BPQBlock.cc	Tue Oct 18 11:52:07 2011 +0100
+++ b/servlib/bundling/BPQBlock.cc	Mon Oct 24 18:28:33 2011 +0100
@@ -1,5 +1,5 @@
 /*
- *    Copyright 2006 Intel Corporation
+ *    Copyright 2010-2011 Trinity College Dublin
  * 
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -25,50 +25,38 @@
 
 namespace dtn {
 
-// Setup our logging information
-static const char* LOG = "/dtn/bundle/extblock/bpq";
-
-BPQBlock::BPQBlock(Bundle* bundle)
+BPQBlock::BPQBlock(const Bundle* bundle)
+		: Logger("BPQBlock", "/dtn/bundle/bpq")
 {
-    log_info_p(LOG, "BPQBlock::constructor()");
+    log_info("constructor()");
 
     if( bundle->recv_blocks().
         has_block(BundleProtocol::QUERY_EXTENSION_BLOCK) ) {
 
-        log_debug_p(LOG, "BPQBlock found in Recv Block Vec => created remotly");
+        log_debug("BPQBlock found in Recv Block Vec => created remotely");
         initialise( const_cast<BlockInfo*> (bundle->recv_blocks().
-                    find_block(BundleProtocol::QUERY_EXTENSION_BLOCK)) );
+                    find_block(BundleProtocol::QUERY_EXTENSION_BLOCK)),
+        			true, bundle);
 
-    } else if( bundle->api_blocks()->
+    } else if( const_cast<Bundle*>(bundle)->api_blocks()->
                has_block(BundleProtocol::QUERY_EXTENSION_BLOCK) ) {
 
-        log_debug_p(LOG, "BPQBlock found in API Block Vec => created locally");
-        initialise( const_cast<BlockInfo*> (bundle->api_blocks()->
-                    find_block(BundleProtocol::QUERY_EXTENSION_BLOCK)) );
+        log_debug("BPQBlock found in API Block Vec => created locally");
+        initialise( const_cast<BlockInfo*> (const_cast<Bundle*>(bundle)->api_blocks()->
+                    find_block(BundleProtocol::QUERY_EXTENSION_BLOCK)),
+                    true, bundle);
 
     } else {
-        log_err_p(LOG, "BPQ Block not found in bundle");
+        log_err("BPQ Block not found in bundle");
     }
 
-    log_info_p(LOG, "leaving constructor");
-}
-
-//----------------------------------------------------------------------
-BPQBlock::BPQBlock(BlockInfo* block)
-{
-    log_info_p(LOG, "BPQBlock::constructor()");
-
-    ASSERT( block->type() == BundleProtocol::QUERY_EXTENSION_BLOCK);
-
-    initialise(block);
-
-    log_info_p(LOG, "leaving constructor");
+    log_info("leaving constructor");
 }
 
 //----------------------------------------------------------------------
 BPQBlock::~BPQBlock()
 {
-    log_info_p(LOG, "BPQBlock: destructor");
+    log_info("BPQBlock: destructor");
     if ( query_val_ != NULL ){
         free(query_val_);
         query_val_ = NULL;
@@ -94,12 +82,44 @@
     else
         return -1;
 
+    // timestamp secs		SDNV
+    if ( i < len &&
+        (encoding_len = SDNV::encode (creation_ts_.seconds_, &(buf[i]), len -i)) >= 0 ) {
+        i += encoding_len;
+    } else {
+        log_err("Error encoding BPQ creation timestamp secs");
+        return -1;
+    }
+
+    // timestamp seqno		SDNV
+    if ( i < len &&
+        (encoding_len = SDNV::encode (creation_ts_.seqno_, &(buf[i]), len -i)) >= 0 ) {
+        i += encoding_len;
+    } else {
+        log_err("Error encoding BPQ creation timestamp seqno");
+        return -1;
+    }
+
+    // source eid length	SDNV
+    if ( i < len &&
+        (encoding_len = SDNV::encode (source_.length(), &(buf[i]), len -i)) >= 0 ) {
+        i += encoding_len;
+    } else {
+        log_err("Error encoding BPQ source EID length");
+        return -1;
+    }
+
+    // source eid           n-bytes
+    const char* src_eid = source_.c_str();
+    for (j=0; src_eid != NULL && i < len && j < source_.length(); i++, j++)
+        buf[i] = src_eid[j];
+
     // query-length         SDNV
     if ( i < len &&
         (encoding_len = SDNV::encode (query_len_, &(buf[i]), len -i)) >= 0 ) {
         i += encoding_len;
     } else {
-        log_err_p(LOG, "Error encoding _BPQ query length");
+        log_err("Error encoding BPQ query length");
         return -1;
     }
 
@@ -112,7 +132,7 @@
         (encoding_len = SDNV::encode (frag_len(), &(buf[i]), len -i)) >= 0 ) {
         i += encoding_len;
     } else {
-        log_err_p(LOG, "Error encoding _BPQ fragment length");
+        log_err("Error encoding BPQ fragment length");
         return -1;
     }
 
@@ -126,7 +146,7 @@
             (encoding_len = SDNV::encode (iter->offset(), &(buf[i]), len -i)) >= 0 ) {
             i += encoding_len;
         } else {
-            log_err_p(LOG, "Error encoding _BPQ individual fragment offset");
+            log_err("Error encoding BPQ individual fragment offset");
             return -1;
         }
 
@@ -134,7 +154,7 @@
             (encoding_len = SDNV::encode (iter->length(), &(buf[i]), len -i)) >= 0 ) {
             i += encoding_len;
         } else {
-            log_err_p(LOG, "Error encoding _BPQ individual fragment length");
+            log_err("Error encoding BPQ individual fragment length");
             return -1;
         }
     }
@@ -151,10 +171,15 @@
     // initial size {kind, matching rule}
     u_int len = 2; 
         
+    len += SDNV::encoding_len(creation_ts_.seconds_);
+    len += SDNV::encoding_len(creation_ts_.seqno_);
+    len += SDNV::encoding_len(source_.length());
+    len += source_.length();
+
     len += SDNV::encoding_len(query_len_);
     len += query_len_;
+
     len += SDNV::encoding_len(frag_len());
-
     BPQFragmentVec::const_iterator iter;
 	for (iter  = fragments_.begin();
 		 iter != fragments_.end();
@@ -171,166 +196,272 @@
 bool
 BPQBlock::match(const BPQBlock* other) const
 {
-    return query_len_ == other->query_len() &&
+    return matching_rule_ == other->matching_rule() &&
+    	   query_len_ == other->query_len() 		&&
            strncmp( (char*)query_val_, (char*)other->query_val(),
                      query_len_ ) == 0;
 }
 
 //----------------------------------------------------------------------
 int
-BPQBlock::initialise(BlockInfo* b)
+BPQBlock::initialise(BlockInfo* block, bool created_locally, const Bundle* bundle)
 {
-    ASSERT ( b != NULL);
+#define TRY(fn) 		\
+    if(!fn) { 			\
+        return BP_FAIL; \
+    }
+
+	ASSERT ( block != NULL);
+
+	u_int buf_index = 0;
+	u_int buf_length = block->data_length();
+	const u_char* buf = block->data();
+
+	log_block_info(block);
+	TRY (extract_kind(buf, &buf_index, buf_length));
+	TRY (extract_matching_rule(buf, &buf_index, buf_length));
 
-    int decoding_len=0;
-	u_int i=0, j=0, offset=0, length=0, full_len=0;
-	u_int frag_count=0, frag_off=0, frag_len=0;
-	u_char* buf = 0;
-    BlockInfo* block = b;
+	if (created_locally) {
+		creation_ts_.seconds_ 	= bundle->creation_ts().seconds_;
+		creation_ts_.seqno_		= bundle->creation_ts().seqno_;
+		source_.assign(bundle->source());
+	} else {
+		TRY (extract_creation_ts(buf, &buf_index, buf_length));
+		TRY (extract_source(buf, &buf_index, buf_length));
+	}
+
+	TRY (extract_query(buf, &buf_index, buf_length));
+	TRY (extract_fragments(buf, &buf_index, buf_length));
+
+	return BP_SUCCESS;
 
-    /**************************************************************************
-     * Begin extracting block length with lots of logging
-     *************************************************************************/
-    log_debug_p(LOG, "block: data_length() = %d", block->data_length());
-    log_debug_p(LOG, "block: data_offset() = %d", block->data_offset());
-    log_debug_p(LOG, "block: full_length() = %d", block->full_length());
-    log_debug_p(LOG, "block: complete() = %s",
+#undef TRY
+}
+
+//----------------------------------------------------------------------
+void
+BPQBlock::log_block_info(BlockInfo* block)
+{
+    ASSERT ( block != NULL);
+
+    log_debug("block: data_length() = %d", block->data_length());
+    log_debug("block: data_offset() = %d", block->data_offset());
+    log_debug("block: full_length() = %d", block->full_length());
+    log_debug("block: complete() = %s",
         (block->complete()) ? "true" : "false" );
 
-    log_debug_p(LOG, "block: reloaded() = %s",
+    log_debug("block: reloaded() = %s",
         (block->reloaded()) ? "true" : "false" );
 
-    if ( b->source() != NULL ) {
-        BlockInfo* block_src = const_cast<BlockInfo*>(b->source());;
+    if ( block->source() != NULL ) {
+        BlockInfo* block_src = const_cast<BlockInfo*>(block->source());
 
-        log_debug_p(LOG, "block_src: data_length() = %d", block_src->data_length());
-        log_debug_p(LOG, "block_src: data_offset() = %d", block_src->data_offset());
-        log_debug_p(LOG, "block_src: full_length() = %d", block_src->full_length());
-        log_debug_p(LOG, "block_src: complete() = %s",
+        log_debug("block_src: data_length() = %d", block_src->data_length());
+        log_debug("block_src: data_offset() = %d", block_src->data_offset());
+        log_debug("block_src: full_length() = %d", block_src->full_length());
+        log_debug("block_src: complete() = %s",
             (block_src->complete()) ? "true" : "false" );
-    
-        log_debug_p(LOG, "block_src: reloaded() = %s",
+
+        log_debug("block_src: reloaded() = %s",
             (block_src->reloaded()) ? "true" : "false" );
     }
 
-
-    offset = block->data_offset();
-    length = block->data_length();
-    full_len = block->full_length();
-
-    if ( full_len != offset + length ) {
-        log_err_p(LOG, "BPQBlock::initialise: full_len != offset + length");
+    if ( block->full_length() != block->data_offset() + block->data_length() ) {
+        log_err("BPQBlock: full_len != offset + length");
     }
 
-    if ( block->writable_contents()->buf_len() < full_len ){
-        log_err_p(LOG, "BPQBlock::initialise:  buf_len() < full_len");
-        log_err_p(LOG, "BPQBlock::initialise:  buf_len() = %zu",
-            block->writable_contents()->buf_len());
-
-        log_debug_p(LOG, "BPQBlock::initialise: reserving space in buffer %zu",
-            full_len);
-
-        block->writable_contents()->reserve(full_len);
-        log_debug_p(LOG, "BPQBlock::initialise: new buf_len() = %zu",
+    if ( block->writable_contents()->buf_len() < block->full_length() ){
+        log_err("BPQBlock:  buf_len() < full_len");
+        log_err("BPQBlock:  buf_len() = %zu",
             block->writable_contents()->buf_len());
     }
 
-    buf = block->data();
-
-
-    // BPQ Kind must be 0 or 1
-    if ( *(block->data()) != 0 &&
-         *(block->data()) != 1 ) {
-        log_err_p(LOG, "BPQBlock::initialise: block->data() = %c (should be 0|1)",
+    if ( *(block->data()) != KIND_QUERY 		||
+         *(block->data()) != KIND_RESPONSE 		||
+         *(block->data()) != KIND_RESPONSE_DO_NOT_CACHE_FRAG ) {
+        log_err("BPQBlock: block->data() = %c (should be 0|1|2)",
             *(block->data()));
-        return BP_FAIL;
     }
-
-    /**************************************************************************
-     * Begin extracting block info
-     *************************************************************************/
+}
 
-    // BPQ-kind             1-byte
-    if ( i < length ) {
-        log_debug_p(LOG, "BPQBlock::initialise: extracting kind");
-        kind_ = (kind_t) buf[i++];
-        log_debug_p(LOG, "BPQBlock::initialise: kind = %d", kind_);
-    } else {
-    	log_err_p(LOG, "Error decoding BPQ kind");
-    	return BP_FAIL;
-    }
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_kind (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	if ( *buf_index < buf_length ) {
+	    kind_ = (kind_t) buf[*buf_index++];
+	    log_debug("BPQBlock::extract_kind: kind = %d", kind_);
+	    return BP_SUCCESS;
 
-    // matching rule type   1-byte
-    if ( i < length ) {
-        matching_rule_ = (u_int) buf[i++];
-        log_debug_p(LOG, "BPQBlock::initialise: matching rule = %u", matching_rule_);
-    } else {
-    	log_err_p(LOG, "Error decoding BPQ matching rule");
-    	return BP_FAIL;
-    }
-
-    // query-len			SDNV
-    if ( i < length &&
-        (decoding_len = SDNV::decode(&(buf[i]), length - i, &query_len_)) >= 0 ) {
-        i += decoding_len;
-        log_debug_p(LOG, "BPQBlock::initialise: query len = %u", query_len_);
-    } else {
-        log_err_p(LOG, "Error decoding BPQ query length");
-        return BP_FAIL;
-    }
+	} else {
+	    log_err("Error decoding kind");
+	    return BP_FAIL;
+	}
+}
 
-    // query-value           n-bytes
-    if ( (i+query_len_) < length ) {
-        query_val_ = (u_char*) malloc ( sizeof(u_char) * query_len_ );
-
-        for (j=0; query_val_ != NULL && i < length && j < query_len_; i++, j++)
-            query_val_[j] = buf[i];
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_matching_rule (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	if ( *buf_index < buf_length ) {
+	    matching_rule_ = (kind_t) buf[*buf_index++];
+	    log_debug("BPQBlock::extract_matching_rule: matching rule = %d", matching_rule_);
+	    return BP_SUCCESS;
 
-        log_debug_p(LOG, "BPQBlock::initialise: query val = %s", query_val_);
-
-    } else {
-        query_val_ = NULL;
-        log_err_p(LOG, "Error extracting BPQ query value");
-        return BP_FAIL;
-    }
+	} else {
+	    log_err("Error decoding matching rule");
+	    return BP_FAIL;
+	}
+}
 
-    if ( i < length &&
-        (decoding_len = SDNV::decode(&(buf[i]), length - i, &frag_count)) >= 0 ) {
-        i += decoding_len;
-        log_debug_p(LOG, "BPQBlock::initialise: frag count = %u", frag_count);
-    } else {
-        log_err_p(LOG, "Error decoding BPQ fragment count");
-        return BP_FAIL;
-    }
-
-
-	for (j=0;  i < length && j < frag_count; j++) {
-
-		if ( (decoding_len = SDNV::decode(&(buf[i]), length - i, &frag_off)) >= 0 ) {
-			i += decoding_len;
-			log_debug_p(LOG, "BPQBlock::initialise: frag offset = %u", frag_off);
-		} else {
-			log_err_p(LOG, "Error decoding BPQ fragment offset");
-			return BP_FAIL;
-		}
-
-		if ( (decoding_len = SDNV::decode(&(buf[i]), length - i, &frag_len)) >= 0 ) {
-			i += decoding_len;
-			log_debug_p(LOG, "BPQBlock::initialise: frag length = %u", frag_len);
-		} else {
-			log_err_p(LOG, "Error decoding BPQ fragment length");
-			return BP_FAIL;
-		}
-
-
-		BPQFragment frag(frag_off, frag_len);
-		add_fragment(frag);
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_creation_ts (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	int decoding_len = 0;
+	if (*buf_index < buf_length &&
+		(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+				 	 	 	 	 	 	buf_length - *buf_index,
+				 	 	 	 	 	 	&(creation_ts_.seconds_)) ) >= 0 ) {
+		*buf_index += decoding_len;
+		log_debug("BPQBlock::extract_creation_ts: timestamp seconds = %llu",
+				creation_ts_.seconds_);
+	} else {
+		log_err("Error decoding timestamp seconds");
+		return BP_FAIL;
 	}
 
 
+	if (*buf_index < buf_length &&
+		(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+										buf_length - *buf_index,
+										&(creation_ts_.seqno_)) ) >= 0 ) {
+		*buf_index += decoding_len;
+		log_debug("BPQBlock::extract_creation_ts: timestamp sequence number = %llu",
+				creation_ts_.seqno_);
+	} else {
+		log_err("Error decoding timestamp sequence number");
+		return BP_FAIL;
+	}
+
+	return BP_SUCCESS;
+}
+
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_source (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	int decoding_len = 0;
+	u_int src_eid_len = 0;
+
+	if (*buf_index < buf_length &&
+		(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+										buf_length - *buf_index,
+										&src_eid_len)) >= 0 ) {
+		*buf_index += decoding_len;
+		log_debug("BPQBlock::extract_source: Source EID length = %u", src_eid_len);
+	} else {
+		log_err("Error decoding Source EID length");
+		return BP_FAIL;
+	}
+
+    if ((*buf_index + src_eid_len) < buf_length  &&
+        source_.assign((const char*) &(buf[*buf_index]), src_eid_len) ) {
+
+    	*buf_index += src_eid_len;
+    	log_debug("BPQBlock::extract_source: Source EID = %s", source_.c_str());
+
+    } else {
+        log_err("Error extracting Source EID");
+        return BP_FAIL;
+    }
 
     return BP_SUCCESS;
 }
 
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_query (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	int decoding_len = 0;
+
+	if (*buf_index < buf_length &&
+		(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+										buf_length - *buf_index,
+										&query_len_)) >= 0 ) {
+		*buf_index += decoding_len;
+		log_debug("BPQBlock::extract_query: query length = %u", query_len_);
+    } else {
+        log_err("Error decoding BPQ query length");
+        return BP_FAIL;
+	}
+
+    if ((*buf_index + query_len_) < buf_length) {
+    	query_val_ = (u_char*) malloc ( sizeof(u_char) * query_len_ );
+
+    	memcpy(query_val_, &(buf[*buf_index]), query_len_);
+
+    	*buf_index += query_len_;
+    	log_debug("BPQBlock::extract_query: query value = %s", query_val_);
+
+    } else {
+        log_err("Error extracting query value");
+        return BP_FAIL;
+    }
+
+    return BP_SUCCESS;
+}
+
+//----------------------------------------------------------------------
+int
+BPQBlock::extract_fragments (const u_char* buf, u_int* buf_index, u_int buf_length)
+{
+	int decoding_len = 0;
+	u_int i;
+	u_int frag_count = 0;
+	u_int frag_off = 0;
+	u_int frag_len = 0;
+
+	if (*buf_index < buf_length &&
+		(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+										buf_length - *buf_index,
+										&frag_count)) >= 0 ) {
+		*buf_index += decoding_len;
+		log_debug("BPQBlock::extract_fragments: number of fragments = %u", frag_count);
+    } else {
+        log_err("Error decoding number of fragments");
+        return BP_FAIL;
+	}
+
+	for (i=0; i < frag_count; i++) {
+
+		if (*buf_index < buf_length &&
+			(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+											buf_length - *buf_index,
+											&frag_off)) >= 0 ) {
+			*buf_index += decoding_len;
+			log_debug("BPQBlock::extract_fragments: fragment [%u] offset = %u", i, frag_off);
+	    } else {
+	        log_err("Error decoding fragment [%u] offset", i);
+	        return BP_FAIL;
+		}
+
+		if (*buf_index < buf_length &&
+			(decoding_len = SDNV::decode(	&(buf[*buf_index]),
+											buf_length - *buf_index,
+											&frag_len)) >= 0 ) {
+			*buf_index += decoding_len;
+			log_debug("BPQBlock::extract_fragments: fragment [%u] length = %u", i, frag_len);
+	    } else {
+	        log_err("Error decoding fragment [%u] length", i);
+	        return BP_FAIL;
+		}
+
+		BPQFragment frag(frag_off, frag_len);
+		this->add_fragment(frag);
+	}
+
+	return BP_SUCCESS;
+}
+
 } // namespace dtn
-