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