PayloadBlockProcessor.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include "PayloadBlockProcessor.h"
00018 #include "Bundle.h"
00019 #include "BundleProtocol.h"
00020 
00021 namespace dtn {
00022 
00023 //----------------------------------------------------------------------
00024 PayloadBlockProcessor::PayloadBlockProcessor()
00025     : BlockProcessor(BundleProtocol::PAYLOAD_BLOCK)
00026 {
00027 }
00028 
00029 //----------------------------------------------------------------------
00030 int
00031 PayloadBlockProcessor::consume(Bundle*    bundle,
00032                                BlockInfo* block,
00033                                u_char*    buf,
00034                                size_t     len)
00035 {
00036     static const char* log = "/dtn/bundle/protocol";
00037     (void)log;
00038     
00039     size_t consumed = 0;
00040     if (block->data_offset() == 0) {
00041         int cc = consume_preamble(block, buf, len);
00042         if (cc == -1) {
00043             return -1;
00044         }
00045 
00046         buf += cc;
00047         len -= cc;
00048 
00049         consumed += cc;
00050 
00051         ASSERT(bundle->payload_.length() == 0);
00052     }
00053     
00054     // If we still don't know the data offset, we must have consumed
00055     // the whole buffer
00056     if (block->data_offset() == 0) {
00057         ASSERT(len == 0);
00058     }
00059 
00060     // Special case for the simulator -- if the payload location is
00061     // NODATA, then we're done.
00062     if (bundle->payload_.location() == BundlePayload::NODATA) {
00063         block->set_complete(true);
00064         return consumed;
00065     }
00066 
00067     // If there's nothing left to do, we can bail for now, though we
00068     // need to be careful to properly set the complete bit to both
00069     // handle zero-length bundles and partially received preambles
00070     if (len == 0) {
00071         if (block->data_offset() != 0 && block->data_length() == 0) {
00072             block->set_complete(true);
00073         }
00074         return consumed;
00075     }
00076     
00077     // Otherwise, the buffer should always hold just the preamble
00078     // since we store the rest in the payload file
00079     ASSERT(block->contents().len() == block->data_offset());
00080 
00081     // Now make sure there's still something left to do for the block,
00082     // otherwise it should have been marked as complete
00083     ASSERT(block->data_length() > bundle->payload_.length());
00084 
00085     size_t rcvd      = bundle->payload_.length();
00086     size_t remainder = block->data_length() - rcvd;
00087     size_t tocopy;
00088 
00089     if (len >= remainder) {
00090         block->set_complete(true);
00091         tocopy = remainder;
00092     } else {
00093         tocopy = len;
00094     }
00095 
00096     bundle->payload_.set_length(rcvd + tocopy);
00097     bundle->payload_.write_data(buf, rcvd, tocopy);
00098 
00099     consumed += tocopy;
00100 
00101     log_debug_p(log, "PayloadBlockProcessor consumed %zu/%u (%s)",
00102                 consumed, block->full_length(), 
00103                 block->complete() ? "complete" : "not complete");
00104     
00105     return consumed;
00106 }
00107 
00108 //----------------------------------------------------------------------
00109 void
00110 PayloadBlockProcessor::generate(const Bundle* bundle,
00111                                 Link*         link,
00112                                 BlockInfo*    block,
00113                                 bool          last)
00114 {
00115     (void)link;
00116     
00117     // in the ::generate pass, we just need to set up the preamble,
00118     // since the payload stays on disk
00119     generate_preamble(block,
00120                       BundleProtocol::PAYLOAD_BLOCK,
00121                       last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0,
00122                       bundle->payload_.length());
00123 }
00124 
00125 //----------------------------------------------------------------------
00126 void
00127 PayloadBlockProcessor::produce(const Bundle*    bundle,
00128                                const BlockInfo* block,
00129                                u_char*          buf,
00130                                size_t           offset,
00131                                size_t           len)
00132 {
00133     // First copy out the specified range of the preamble
00134     if (offset < block->data_offset()) {
00135         size_t tocopy = std::min(len, block->data_offset() - offset);
00136         memcpy(buf, block->contents().buf() + offset, tocopy);
00137         buf    += tocopy;
00138         offset += tocopy;
00139         len    -= tocopy;
00140     }
00141 
00142     if (len == 0)
00143         return;
00144 
00145     // Adjust offset to account for the preamble
00146     size_t payload_offset = offset - block->data_offset();
00147 
00148     size_t tocopy = std::min(len, bundle->payload_.length() - payload_offset);
00149     bundle->payload_.read_data(payload_offset, tocopy, buf,
00150                                BundlePayload::FORCE_COPY);
00151 }
00152 
00153 } // namespace dtn

Generated on Sat Sep 8 08:36:17 2007 for DTN Reference Implementation by  doxygen 1.5.3