00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <oasys/util/ScratchBuffer.h>
00019 #include "CustodySignal.h"
00020 #include "SDNV.h"
00021
00022 namespace dtn {
00023
00024 void
00025 CustodySignal::create_custody_signal(Bundle* bundle,
00026 const Bundle* orig_bundle,
00027 const EndpointID& source_eid,
00028 bool succeeded,
00029 reason_t reason)
00030 {
00031 bundle->source_.assign(source_eid);
00032 if (orig_bundle->custodian_.equals(EndpointID::NULL_EID())) {
00033 PANIC("create_custody_signal(*%p): "
00034 "custody signal cannot be generated to null eid",
00035 orig_bundle);
00036 }
00037 bundle->dest_.assign(orig_bundle->custodian_);
00038 bundle->replyto_.assign(EndpointID::NULL_EID());
00039 bundle->custodian_.assign(EndpointID::NULL_EID());
00040 bundle->is_admin_ = true;
00041
00042
00043
00044 bundle->expiration_ = orig_bundle->expiration_;
00045
00046 int sdnv_encoding_len = 0;
00047 int signal_len = 0;
00048
00049
00050 oasys::ScratchBuffer<u_char*, 256> scratch;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 signal_len = 1 + 1 + 8 + 8;
00069
00070
00071 if (orig_bundle->is_fragment_) {
00072 signal_len += SDNV::encoding_len(orig_bundle->frag_offset_);
00073 signal_len += SDNV::encoding_len(orig_bundle->orig_length_);
00074 }
00075
00076
00077 signal_len += SDNV::encoding_len(orig_bundle->source_.length()) +
00078 orig_bundle->source_.length();
00079
00080
00081
00082
00083 u_char* bp = scratch.buf(signal_len);
00084 int len = signal_len;
00085
00086
00087 *bp = (BundleProtocol::ADMIN_CUSTODY_SIGNAL << 4);
00088 if (orig_bundle->is_fragment_) {
00089 *bp |= BundleProtocol::ADMIN_IS_FRAGMENT;
00090 }
00091 bp++;
00092 len--;
00093
00094
00095 *bp++ = ((succeeded ? 1 : 0) << 7) | (reason & 0x7f);
00096 len--;
00097
00098
00099 if (orig_bundle->is_fragment_) {
00100 sdnv_encoding_len = SDNV::encode(orig_bundle->frag_offset_, bp, len);
00101 ASSERT(sdnv_encoding_len > 0);
00102 bp += sdnv_encoding_len;
00103 len -= sdnv_encoding_len;
00104
00105 sdnv_encoding_len = SDNV::encode(orig_bundle->orig_length_, bp, len);
00106 ASSERT(sdnv_encoding_len > 0);
00107 bp += sdnv_encoding_len;
00108 len -= sdnv_encoding_len;
00109 }
00110
00111
00112 BundleTimestamp now;
00113 now.seconds_ = BundleTimestamp::get_current_time();
00114 now.seqno_ = 0;
00115 BundleProtocol::set_timestamp(bp, &now);
00116 len -= sizeof(u_int64_t);
00117 bp += sizeof(u_int64_t);
00118
00119
00120 BundleProtocol::set_timestamp(bp, &orig_bundle->creation_ts_);
00121 len -= sizeof(u_int64_t);
00122 bp += sizeof(u_int64_t);
00123
00124
00125 sdnv_encoding_len = SDNV::encode(orig_bundle->source_.length(), bp, len);
00126 ASSERT(sdnv_encoding_len > 0);
00127 len -= sdnv_encoding_len;
00128 bp += sdnv_encoding_len;
00129
00130 ASSERT((u_int)len == orig_bundle->source_.length());
00131 memcpy(bp, orig_bundle->source_.c_str(), orig_bundle->source_.length());
00132
00133
00134
00135
00136 bundle->payload_.set_data(scratch.buf(), signal_len);
00137 }
00138
00139 bool
00140 CustodySignal::parse_custody_signal(data_t* data,
00141 const u_char* bp, u_int len)
00142 {
00143
00144 if (len < 1) { return false; }
00145 data->admin_type_ = (*bp >> 4);
00146 data->admin_flags_ = *bp & 0xf;
00147 bp++;
00148 len--;
00149
00150
00151 if (data->admin_type_ != BundleProtocol::ADMIN_CUSTODY_SIGNAL) {
00152 return false;
00153 }
00154
00155
00156 if (len < 1) { return false; }
00157 data->succeeded_ = (*bp >> 7);
00158 data->reason_ = (*bp & 0x7f);
00159 bp++;
00160 len--;
00161
00162
00163 if (data->admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT)
00164 {
00165 int sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_offset_);
00166 if (sdnv_bytes == -1) { return false; }
00167 bp += sdnv_bytes;
00168 len -= sdnv_bytes;
00169
00170 sdnv_bytes = SDNV::decode(bp, len, &data->orig_frag_length_);
00171 if (sdnv_bytes == -1) { return false; }
00172 bp += sdnv_bytes;
00173 len -= sdnv_bytes;
00174 }
00175
00176
00177 if (len < sizeof(u_int64_t)) { return false; }
00178 BundleProtocol::get_timestamp(&data->custody_signal_tv_, bp);
00179 bp += sizeof(u_int64_t);
00180 len -= sizeof(u_int64_t);
00181
00182
00183 if (len < sizeof(u_int64_t)) { return false; }
00184 BundleProtocol::get_timestamp(&data->orig_creation_tv_, bp);
00185 bp += sizeof(u_int64_t);
00186 len -= sizeof(u_int64_t);
00187
00188
00189 u_int64_t EID_len;
00190 int num_bytes = SDNV::decode(bp, len, &EID_len);
00191 if (num_bytes == -1) { return false; }
00192 bp += num_bytes;
00193 len -= num_bytes;
00194
00195 if (len != EID_len) { return false; }
00196 bool ok = data->orig_source_eid_.assign(std::string((const char*)bp, len));
00197 if (!ok) {
00198 return false;
00199 }
00200
00201 return true;
00202 }
00203
00204 const char*
00205 CustodySignal::reason_to_str(u_int8_t reason)
00206 {
00207 switch (reason) {
00208 case BundleProtocol::CUSTODY_NO_ADDTL_INFO:
00209 return "no additional info";
00210
00211 case BundleProtocol::CUSTODY_REDUNDANT_RECEPTION:
00212 return "redundant reception";
00213
00214 case BundleProtocol::CUSTODY_DEPLETED_STORAGE:
00215 return "depleted storage";
00216
00217 case BundleProtocol::CUSTODY_ENDPOINT_ID_UNINTELLIGIBLE:
00218 return "eid unintelligible";
00219
00220 case BundleProtocol::CUSTODY_NO_ROUTE_TO_DEST:
00221 return "no route to dest";
00222
00223 case BundleProtocol::CUSTODY_NO_TIMELY_CONTACT:
00224 return "no timely contact";
00225
00226 case BundleProtocol::CUSTODY_BLOCK_UNINTELLIGIBLE:
00227 return "block unintelligible";
00228 }
00229
00230 static char buf[64];
00231 snprintf(buf, 64, "unknown reason %d", reason);
00232 return buf;
00233 }
00234
00235 }