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