00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "BundleStatusReport.h"
00019 #include "SDNV.h"
00020 #include <netinet/in.h>
00021 #include <oasys/util/ScratchBuffer.h>
00022
00023 namespace dtn {
00024
00025
00026 void
00027 BundleStatusReport::create_status_report(Bundle* bundle,
00028 const Bundle* orig_bundle,
00029 const EndpointID& source,
00030 flag_t status_flags,
00031 reason_t reason)
00032 {
00033 bundle->source_.assign(source);
00034 if (orig_bundle->replyto_.equals(EndpointID::NULL_EID())){
00035 bundle->dest_.assign(orig_bundle->source_);
00036 } else {
00037 bundle->dest_.assign(orig_bundle->replyto_);
00038 }
00039 bundle->replyto_.assign(EndpointID::NULL_EID());
00040 bundle->custodian_.assign(EndpointID::NULL_EID());
00041
00042 bundle->is_admin_ = true;
00043
00044
00045
00046 bundle->expiration_ = orig_bundle->expiration_;
00047
00048
00049 EndpointID orig_source(orig_bundle->source_);
00050
00051 int sdnv_encoding_len = 0;
00052 int report_length = 0;
00053
00054
00055 oasys::ScratchBuffer<u_char*, 256> scratch;
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 report_length = 1 + 1 + 1 + 8 + 8;
00079
00080
00081 if (orig_bundle->is_fragment_) {
00082 report_length += SDNV::encoding_len(orig_bundle->frag_offset_);
00083 report_length += SDNV::encoding_len(orig_bundle->orig_length_);
00084 }
00085
00086
00087 report_length += SDNV::encoding_len(orig_source.length()) + orig_source.length();
00088
00089
00090
00091
00092
00093 u_char* bp = scratch.buf(report_length);
00094 int len = report_length;
00095
00096
00097 *bp = BundleProtocol::ADMIN_STATUS_REPORT << 4;
00098 if (orig_bundle->is_fragment_) {
00099 *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
00100 }
00101 bp++;
00102 len--;
00103
00104
00105 *bp++ = status_flags;
00106 len--;
00107
00108
00109 *bp++ = reason;
00110 len--;
00111
00112
00113 if (orig_bundle->is_fragment_) {
00114 sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset_, bp, len);
00115 ASSERT(sdnv_encoding_len > 0);
00116 bp += sdnv_encoding_len;
00117 len -= sdnv_encoding_len;
00118
00119 sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length_, bp, len);
00120 ASSERT(sdnv_encoding_len > 0);
00121 bp += sdnv_encoding_len;
00122 len -= sdnv_encoding_len;
00123 }
00124
00125
00126
00127 BundleTimestamp now;
00128 now.seconds_ = BundleTimestamp::get_current_time();
00129 now.seqno_ = 0;
00130 BundleProtocol::set_timestamp(bp, &now);
00131 len -= sizeof(u_int64_t);
00132 bp += sizeof(u_int64_t);
00133
00134
00135 BundleProtocol::set_timestamp(bp, &orig_bundle->creation_ts_);
00136 len -= sizeof(u_int64_t);
00137 bp += sizeof(u_int64_t);
00138
00139
00140 sdnv_encoding_len = SDNV::encode(orig_source.length(), bp, len);
00141 ASSERT(sdnv_encoding_len > 0);
00142 len -= sdnv_encoding_len;
00143 bp += sdnv_encoding_len;
00144
00145 ASSERT((u_int)len == orig_source.length());
00146 memcpy(bp, orig_source.c_str(), orig_source.length());
00147
00148
00149
00150
00151 bundle->payload_.set_data(scratch.buf(), report_length);
00152 }
00153
00154
00155 bool BundleStatusReport::parse_status_report(data_t* data,
00156 const u_char* bp, u_int len)
00157 {
00158
00159 if (len < 1) { return false; }
00160 data->admin_type_ = (*bp >> 4);
00161 data->admin_flags_ = *bp & 0xf;
00162 bp++;
00163 len--;
00164
00165
00166 if (data->admin_type_ != BundleProtocol::ADMIN_STATUS_REPORT) {
00167 return false;
00168 }
00169
00170
00171 if (len < 1) { return false; }
00172 data->status_flags_ = *bp++;
00173 len--;
00174
00175
00176 if (len < 1) { return false; }
00177 data->reason_code_ = *bp++;
00178 len--;
00179
00180
00181 if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT) {
00182 int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
00183 if (sdnv_bytes == -1) { return false; }
00184 bp += sdnv_bytes;
00185 len -= sdnv_bytes;
00186 sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
00187 if (sdnv_bytes == -1) { return false; }
00188 bp += sdnv_bytes;
00189 len -= sdnv_bytes;
00190 }
00191
00192
00193
00194 if (data->status_flags_ & BundleProtocol::STATUS_RECEIVED) {
00195 if (len < sizeof(u_int64_t)) { return false; }
00196 BundleProtocol::get_timestamp(&data->receipt_tv_, bp);
00197 bp += sizeof(u_int64_t);
00198 len -= sizeof(u_int64_t);
00199 }
00200
00201 if (data->status_flags_ & BundleProtocol::STATUS_CUSTODY_ACCEPTED) {
00202 if (len < sizeof(u_int64_t)) { return false; }
00203 BundleProtocol::get_timestamp(&data->custody_tv_, bp);
00204 bp += sizeof(u_int64_t);
00205 len -= sizeof(u_int64_t);
00206 }
00207
00208 if (data->status_flags_ & BundleProtocol::STATUS_FORWARDED) {
00209 if (len < sizeof(u_int64_t)) { return false; }
00210 BundleProtocol::get_timestamp(&data->forwarding_tv_, bp);
00211 bp += sizeof(u_int64_t);
00212 len -= sizeof(u_int64_t);
00213 }
00214
00215 if (data->status_flags_ & BundleProtocol::STATUS_DELIVERED) {
00216 if (len < sizeof(u_int64_t)) { return false; }
00217 BundleProtocol::get_timestamp(&data->delivery_tv_, bp);
00218 bp += sizeof(u_int64_t);
00219 len -= sizeof(u_int64_t);
00220 }
00221
00222 if (data->status_flags_ & BundleProtocol::STATUS_DELETED) {
00223 if (len < sizeof(u_int64_t)) { return false; }
00224 BundleProtocol::get_timestamp(&data->deletion_tv_, bp);
00225 bp += sizeof(u_int64_t);
00226 len -= sizeof(u_int64_t);
00227 }
00228
00229 if (data->status_flags_ & BundleProtocol::STATUS_ACKED_BY_APP) {
00230 if (len < sizeof(u_int64_t)) { return false; }
00231 BundleProtocol::get_timestamp(&data->acknowledgement_tv_, bp);
00232 bp += sizeof(u_int64_t);
00233 len -= sizeof(u_int64_t);
00234 }
00235
00236
00237
00238 if (len < sizeof(u_int64_t)) { return false; }
00239 BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp);
00240 bp += sizeof(u_int64_t);
00241 len -= sizeof(u_int64_t);
00242
00243
00244
00245 u_int64_t EID_len;
00246 int num_bytes = SDNV::decode(bp, len, &EID_len);
00247 if (num_bytes == -1) { return false; }
00248 bp += num_bytes;
00249 len -= num_bytes;
00250
00251 if (len != EID_len) { return false; }
00252 bool ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
00253 if (!ok) {
00254 return false;
00255 }
00256
00257 return true;
00258 }
00259
00260
00261 bool
00262 BundleStatusReport::parse_status_report(data_t* data,
00263 const Bundle* bundle)
00264 {
00265 BundleProtocol::admin_record_type_t admin_type;
00266 if (! BundleProtocol::get_admin_type(bundle, &admin_type)) {
00267 return false;
00268 }
00269
00270 if (admin_type != BundleProtocol::ADMIN_STATUS_REPORT) {
00271 return false;
00272 }
00273
00274 size_t payload_len = bundle->payload_.length();
00275 if (payload_len > 16384) {
00276 log_err_p("/dtn/bundle/protocol",
00277 "status report length %zu too big to be parsed!!",
00278 payload_len);
00279 return false;
00280 }
00281
00282 oasys::ScratchBuffer<u_char*, 256> buf;
00283 buf.reserve(payload_len);
00284 const u_char* bp = bundle->payload_.read_data(0, payload_len, buf.buf());
00285 return parse_status_report(data, bp, payload_len);
00286 }
00287
00288
00289 const char*
00290 BundleStatusReport::reason_to_str(u_int8_t reason)
00291 {
00292 switch (reason) {
00293 case BundleProtocol::REASON_NO_ADDTL_INFO:
00294 return "no additional information";
00295
00296 case BundleProtocol::REASON_LIFETIME_EXPIRED:
00297 return "lifetime expired";
00298
00299 case BundleProtocol::REASON_FORWARDED_UNIDIR_LINK:
00300 return "forwarded over unidirectional link";
00301
00302 case BundleProtocol::REASON_TRANSMISSION_CANCELLED:
00303 return "transmission cancelled";
00304
00305 case BundleProtocol::REASON_DEPLETED_STORAGE:
00306 return "depleted storage";
00307
00308 case BundleProtocol::REASON_ENDPOINT_ID_UNINTELLIGIBLE:
00309 return "endpoint id unintelligible";
00310
00311 case BundleProtocol::REASON_NO_ROUTE_TO_DEST:
00312 return "no known route to destination";
00313
00314 case BundleProtocol::REASON_NO_TIMELY_CONTACT:
00315 return "no timely contact";
00316
00317 case BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE:
00318 return "block unintelligible";
00319
00320 default:
00321 return "(unknown reason)";
00322 }
00323 }
00324
00325 }