00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include "Bundle.h"
00022 #include "FragmentState.h"
00023
00024 namespace dtn {
00025
00026
00027 void
00028 FragmentState::add_fragment(Bundle* fragment)
00029 {
00030 fragments_.insert_sorted(fragment, BundleList::SORT_FRAG_OFFSET);
00031 }
00032
00033
00034 bool
00035 FragmentState::erase_fragment(Bundle* fragment)
00036 {
00037 return fragments_.erase(fragment);
00038 }
00039
00040
00041 bool
00042 FragmentState::check_completed() const
00043 {
00044 Bundle* fragment;
00045 BundleList::iterator iter;
00046 oasys::ScopeLock l(fragments_.lock(),
00047 "FragmentState::check_completed");
00048
00049 size_t done_up_to = 0;
00050 size_t f_len;
00051 size_t f_offset;
00052 size_t f_origlen;
00053
00054 size_t total_len = bundle_->payload().length();
00055
00056 int fragi = 0;
00057 int fragn = fragments_.size();
00058 (void)fragn;
00059
00060 for (iter = fragments_.begin();
00061 iter != fragments_.end();
00062 ++iter, ++fragi)
00063 {
00064 fragment = *iter;
00065
00066 f_len = fragment->payload().length();
00067 f_offset = fragment->frag_offset();
00068 f_origlen = fragment->orig_length();
00069
00070 ASSERT(fragment->is_fragment());
00071
00072 if (f_origlen != total_len) {
00073 PANIC("check_completed: error fragment orig len %zu != total %zu",
00074 f_origlen, total_len);
00075
00076 }
00077
00078 if (done_up_to == f_offset) {
00079
00080
00081
00082
00083
00084 log_debug("check_completed fragment %d/%d: "
00085 "offset %zu len %zu total %zu done_up_to %zu: "
00086 "(perfect fit)",
00087 fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
00088 done_up_to += f_len;
00089 }
00090
00091 else if (done_up_to < f_offset) {
00092
00093
00094
00095
00096 log_debug("check_completed fragment %d/%d: "
00097 "offset %zu len %zu total %zu done_up_to %zu: "
00098 "(found a hole)",
00099 fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
00100 return false;
00101
00102 }
00103
00104 else if (done_up_to > (f_offset + f_len)) {
00105
00106
00107
00108
00109 log_debug("check_completed fragment %d/%d: "
00110 "offset %zu len %zu total %zu done_up_to %zu: "
00111 "(redundant fragment)",
00112 fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
00113 continue;
00114 }
00115
00116 else if (done_up_to > f_offset) {
00117
00118
00119
00120
00121
00122 log_debug("check_completed fragment %d/%d: "
00123 "offset %zu len %zu total %zu done_up_to %zu: "
00124 "(overlapping fragment, reducing len to %zu)",
00125 fragi, fragn, f_offset, f_len, f_origlen, done_up_to,
00126 (f_len - (done_up_to - f_offset)));
00127
00128 f_len -= (done_up_to - f_offset);
00129 done_up_to += f_len;
00130 }
00131
00132 else {
00133
00134 NOTREACHED;
00135 }
00136 }
00137
00138 if (done_up_to == total_len) {
00139 log_debug("check_completed reassembly complete!");
00140 return true;
00141 } else {
00142 log_debug("check_completed reassembly not done (got %zu/%zu)",
00143 done_up_to, total_len);
00144 return false;
00145 }
00146 }
00147
00148 }
00149