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