00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "ProphetTLV.h"
00018 #include "bundling/BundleDaemon.h"
00019
00020 namespace dtn {
00021
00022 void
00023 BaseTLV::dump(oasys::StringBuffer* buf)
00024 {
00025 buf->appendf("-+-+-+-\nTLV Type: %s\n"
00026 "Flags: %d\n"
00027 "Length: %d\n",
00028 Prophet::tlv_to_str(typecode_),flags_,length_);
00029 }
00030
00031 void
00032 HelloTLV::dump(oasys::StringBuffer* buf)
00033 {
00034 BaseTLV::dump(buf);
00035 buf->appendf("HF: %s\n"
00036 "Timer: %d\n"
00037 "Sender: %s\n",
00038 Prophet::hf_to_str(hf_),timer_,sender_.c_str());
00039 }
00040
00041 void
00042 RIBDTLV::dump(oasys::StringBuffer* buf)
00043 {
00044 BaseTLV::dump(buf);
00045 buf->appendf("RIBD Entries: %zu\n",ribd_.size());
00046
00047 ribd_.dump(buf);
00048 }
00049
00050 void
00051 RIBTLV::dump(oasys::StringBuffer* buf)
00052 {
00053 BaseTLV::dump(buf);
00054 buf->appendf("Relay: %s\n"
00055 "Custody: %s\n"
00056 "Internet GW: %s\n"
00057 "RIB Entries: %zu\n",
00058 relay_ ? "true" : "false",
00059 custody_ ? "true" : "false",
00060 internet_ ? "true" : "false",
00061 nodes_.size());
00062 for(PointerList<RIBNode>::iterator i = nodes_.begin();
00063 i != nodes_.end();
00064 i++)
00065 {
00066 (*i)->dump(buf);
00067 }
00068 }
00069
00070 void
00071 BundleTLV::dump(oasys::StringBuffer* buf)
00072 {
00073 BaseTLV::dump(buf);
00074 buf->appendf("Type: %s\n"
00075 "Bundle Entries: %zu\n",
00076 BundleOffer::type_to_str(list_.type()),
00077 list_.size());
00078
00079 list_.dump(buf);
00080 }
00081
00082 void
00083 ProphetTLV::dump(oasys::StringBuffer* buf)
00084 {
00085 buf->appendf("ProphetTLV Header\n-----------------\n"
00086 "Result: %s\n"
00087 "Sender: %d\n"
00088 "Receiver: %d\n"
00089 "TransactionID: %d\n"
00090 "Length: %d\n"
00091 "Entries: %zu\n",
00092 Prophet::result_to_str(result_),
00093 sender_instance_,
00094 receiver_instance_,
00095 tid_,
00096 parsedlen_,
00097 num_tlv());
00098 for(iterator i = list_.begin(); i != list_.end(); i++)
00099 {
00100 switch((*i)->typecode())
00101 {
00102 case Prophet::HELLO_TLV:
00103 {
00104 HelloTLV* p = dynamic_cast<HelloTLV*>(*i);
00105 p->dump(buf);
00106 break;
00107 }
00108 case Prophet::RIBD_TLV:
00109 {
00110 RIBDTLV* p = dynamic_cast<RIBDTLV*>(*i);
00111 p->dump(buf);
00112 break;
00113 }
00114 case Prophet::RIB_TLV:
00115 {
00116 RIBTLV* p = dynamic_cast<RIBTLV*>(*i);
00117 p->dump(buf);
00118 break;
00119 }
00120 case Prophet::BUNDLE_TLV:
00121 {
00122 BundleTLV* p = dynamic_cast<BundleTLV*>(*i);
00123 p->dump(buf);
00124 break;
00125 }
00126 case Prophet::UNKNOWN_TLV:
00127 default:
00128 buf->appendf("Unknown TLV\n");
00129 break;
00130 }
00131 }
00132 }
00133
00134 bool
00135 HelloTLV::deserialize(u_char* buffer, size_t len)
00136 {
00137 size_t hdrsz = Prophet::HelloTLVHeaderSize;
00138 Prophet::HelloTLVHeader *hdr = (Prophet::HelloTLVHeader*) buffer;
00139
00140
00141 if (hdr->type != Prophet::HELLO_TLV) {
00142 log_err("looking for TLV type %u but got %u",
00143 Prophet::HELLO_TLV,hdr->type);
00144 return false;
00145 }
00146
00147
00148 if (len < hdrsz)
00149 return false;
00150
00151
00152 size_t hello_len = ntohs(hdr->length);
00153 if (len < hello_len)
00154 return false;
00155
00156
00157 if (hello_len < hdr->name_length)
00158 return false;
00159
00160 hf_ = (Prophet::hello_hf_t) hdr->HF;
00161 length_ = hello_len;
00162 timer_ = hdr->timer;
00163
00164 std::string name((char*)&hdr->sender_name[0],(int)hdr->name_length);
00165 sender_.assign(name);
00166
00167 return true;
00168 }
00169
00170 size_t
00171 RIBDTLV::read_ras_entry(u_int16_t* sid,
00172 EndpointID* eid,
00173 u_char* buffer,
00174 size_t len)
00175 {
00176 size_t ras_sz = Prophet::RoutingAddressStringSize;
00177 if (len <= ras_sz)
00178 return 0;
00179 Prophet::RoutingAddressString* ras =
00180 (Prophet::RoutingAddressString*) buffer;
00181 size_t retval = ras_sz;
00182 *sid = ntohs(ras->string_id);
00183
00184 size_t copylen = FOUR_BYTE_ALIGN(ras->length);
00185 if (len - retval >= copylen) {
00186 std::string eidstr((char*)&ras->ra_string[0],ras->length);
00187 eid->assign(eidstr);
00188 ASSERT(eid->equals(EndpointID::NULL_EID())==false);
00189 retval += copylen;
00190 }
00191 log_debug("read_ras_entry: read %zu bytes from %zu byte buffer",
00192 retval,len);
00193 return retval;
00194 }
00195
00196 bool
00197 RIBDTLV::deserialize(u_char* buffer, size_t len)
00198 {
00199 Prophet::RIBDTLVHeader* hdr = (Prophet::RIBDTLVHeader*) buffer;
00200 if (hdr->type != typecode_) {
00201 log_err("looking for TLV type %u but got %u",
00202 typecode_,hdr->type);
00203 return false;
00204 }
00205
00206 if (len < Prophet::RIBDTLVHeaderSize)
00207 return false;
00208
00209 length_ = ntohs(hdr->length);
00210
00211 if (len < length_)
00212 return false;
00213
00214 flags_ = hdr->flags;
00215
00216 size_t ribd_entry_count = ntohs(hdr->entry_count);
00217 u_char* bp = buffer + Prophet::RIBDTLVHeaderSize;
00218
00219 size_t amt_read = Prophet::RIBDTLVHeaderSize;
00220 len -= Prophet::RIBDTLVHeaderSize;
00221
00222 u_int16_t sid;
00223 EndpointID eid;
00224 ribd_.clear();
00225 while (ribd_entry_count-- > 0) {
00226
00227
00228 size_t bytes_read = read_ras_entry(&sid,&eid,bp,len);
00229 if (bytes_read == 0) {
00230
00231 break;
00232 }
00233
00234
00235 if(ribd_.assign(eid,sid) == false) {
00236
00237 break;
00238 }
00239
00240 len -= bytes_read;
00241 bp += bytes_read;
00242 amt_read += bytes_read;
00243 }
00244
00245 return (amt_read == length_);
00246 }
00247
00248 size_t
00249 RIBTLV::read_rib_entry(u_int16_t* sid, double* pvalue, bool* relay,
00250 bool* custody, bool* internet,
00251 u_char* buffer, size_t len)
00252 {
00253 size_t rib_sz = Prophet::RIBEntrySize;
00254 if (len < rib_sz)
00255 return 0;
00256 Prophet::RIBEntry* rib = (Prophet::RIBEntry*) buffer;
00257 *sid = ntohs(rib->string_id);
00258 *pvalue = ((rib->pvalue & 0xff) + 0.0) / (256.0);
00259 *relay = ((rib->flags & Prophet::RELAY_NODE) ==
00260 Prophet::RELAY_NODE);
00261 *custody = ((rib->flags & Prophet::CUSTODY_NODE) ==
00262 Prophet::CUSTODY_NODE);
00263 *internet = ((rib->flags & Prophet::INTERNET_GW_NODE) ==
00264 Prophet::INTERNET_GW_NODE);
00265 log_debug("read_rib_entry: read %zu bytes from %zu byte buffer",
00266 rib_sz,len);
00267 return rib_sz;
00268 }
00269
00270 bool
00271 RIBTLV::deserialize(u_char* buffer, size_t len)
00272 {
00273 size_t hdrsz = Prophet::RIBTLVHeaderSize;
00274 Prophet::RIBTLVHeader* hdr = (Prophet::RIBTLVHeader*) buffer;
00275 if (hdr->type != typecode_) {
00276 log_err("looking for TLV type %u but got %u",
00277 typecode_,hdr->type);
00278 return 0;
00279 }
00280
00281 if (len < hdrsz)
00282 return 0;
00283
00284 length_ = ntohs(hdr->length);
00285
00286 if (len < length_)
00287 return 0;
00288
00289 flags_ = hdr->flags;
00290
00291 size_t rib_entry_count = ntohs(hdr->rib_string_count);
00292 u_char* bp = buffer + hdrsz;
00293
00294 size_t amt_read = hdrsz;
00295 len -= hdrsz;
00296
00297
00298
00299 size_t ribsz = Prophet::RIBEntrySize;
00300 while (rib_entry_count-- > 0) {
00301
00302 RIBNode remote;
00303 u_int16_t sid = 0;
00304 double pvalue = 0;
00305 bool relay = false;
00306 bool custody = false;
00307 bool internet = false;
00308
00309
00310 size_t bytes_read = read_rib_entry(&sid, &pvalue, &relay,
00311 &custody, &internet, bp, len);
00312 if (bytes_read != ribsz) {
00313
00314 break;
00315 }
00316
00317 remote.set_pvalue(pvalue);
00318 remote.set_relay(relay);
00319 remote.set_custody(custody);
00320 remote.set_internet_gw(internet);
00321 remote.sid_ = sid;
00322
00323
00324 nodes_.push_back(new RIBNode(remote));
00325
00326 len -= bytes_read;
00327 bp += bytes_read;
00328 amt_read += bytes_read;
00329 }
00330
00331 return (amt_read == length_);
00332 }
00333
00334 size_t
00335 BundleTLV::read_bundle_offer(u_int32_t *cts, u_int16_t *sid,
00336 bool *custody, bool *accept, bool *ack,
00337 BundleOffer::bundle_offer_t *type,
00338 u_char* bp, size_t len)
00339 {
00340 size_t boe_sz = Prophet::BundleOfferEntrySize;
00341 if (len < boe_sz) {
00342 log_debug("not enough buffer to parse in Bundle entry, "
00343 "needed %zu but got %zu",boe_sz,len);
00344 return 0;
00345 }
00346 Prophet::BundleOfferEntry* p =
00347 (Prophet::BundleOfferEntry*) bp;
00348
00349 u_int8_t offer_mask =
00350 (Prophet::CUSTODY_OFFERED | Prophet::PROPHET_ACK) & 0xff;
00351
00352 u_int8_t response_mask =
00353 (Prophet::CUSTODY_ACCEPTED | Prophet::BUNDLE_ACCEPTED) & 0xff;
00354
00355 u_int8_t flags = p->b_flags & 0xff;
00356
00357
00358 if ((flags & offer_mask) == flags)
00359 {
00360 *type = BundleOffer::OFFER;
00361 *custody = ((flags & Prophet::CUSTODY_OFFERED) ==
00362 Prophet::CUSTODY_OFFERED);
00363 *ack = ((flags & Prophet::PROPHET_ACK) ==
00364 Prophet::PROPHET_ACK);
00365 }
00366 else
00367 if ((flags & response_mask) == flags)
00368 {
00369 *type = BundleOffer::RESPONSE;
00370 *custody = ((flags & Prophet::CUSTODY_ACCEPTED) ==
00371 Prophet::CUSTODY_ACCEPTED);
00372 *accept = ((flags & Prophet::BUNDLE_ACCEPTED) ==
00373 Prophet::BUNDLE_ACCEPTED);
00374 }
00375 else
00376 {
00377 *type = BundleOffer::UNDEFINED;
00378 log_debug("illegal flag on Bundle entry: %x",flags);
00379 return 0;
00380 }
00381
00382 *sid = ntohs(p->dest_string_id);
00383 *cts = ntohl(p->creation_timestamp);
00384 return boe_sz;
00385 }
00386
00387 bool
00388 BundleTLV::deserialize(u_char* buffer, size_t len)
00389 {
00390 Prophet::BundleOfferTLVHeader* hdr =
00391 (Prophet::BundleOfferTLVHeader*) buffer;
00392
00393 size_t hdrlen = Prophet::BundleOfferTLVHeaderSize;
00394 size_t amt_read = 0;
00395 if (hdr->type != typecode_) {
00396 log_debug("read_bundle_offer: looking for TLV type %u but got %u",
00397 typecode_,hdr->type);
00398 return false;
00399 }
00400
00401 if (len < hdrlen) {
00402 return false;
00403 }
00404
00405 length_ = ntohs(hdr->length);
00406
00407 if (len < length_) {
00408 return false;
00409 }
00410
00411 flags_ = hdr->flags;
00412
00413 size_t offer_count = ntohs(hdr->offer_count);
00414
00415 buffer += hdrlen;
00416 len -= hdrlen;
00417 amt_read += hdrlen;
00418
00419 ASSERT(list_.empty());
00420 ASSERT(list_.type() == BundleOffer::UNDEFINED);
00421
00422 size_t entrylen = Prophet::BundleOfferEntrySize;
00423 while (len >= entrylen &&
00424 amt_read + entrylen <= length_ &&
00425 offer_count-- > 0)
00426 {
00427 u_int32_t cts = 0;
00428 u_int16_t sid = 0;
00429 bool custody = false,
00430 accept = false,
00431 ack = false;
00432 BundleOffer::bundle_offer_t type = BundleOffer::UNDEFINED;
00433
00434 if (read_bundle_offer(&cts,&sid,&custody,&accept,&ack,&type,
00435 buffer,len) == 0)
00436 break;
00437
00438
00439 if (list_.type() == BundleOffer::UNDEFINED) {
00440 ASSERT(list_.empty());
00441 list_.set_type(type);
00442 }
00443
00444 ASSERTF(list_.type() == type,"\n%s != %s\n"
00445 "cts %d\n"
00446 "sid %d\n"
00447 "custody %s\n"
00448 "accept %s\n"
00449 "ack %s\n"
00450 "offer_count %d\n",
00451 BundleOffer::type_to_str(list_.type()),
00452 BundleOffer::type_to_str(type),
00453 cts,sid,
00454 custody ? "true" : "false",
00455 accept ? "true" : "false",
00456 ack ? "true" : "false",
00457 ntohs(hdr->offer_count));
00458
00459 list_.add_offer(cts,sid,custody,accept,ack);
00460
00461 len -= entrylen;
00462 amt_read += entrylen;
00463 buffer += entrylen;
00464 }
00465
00466 return (amt_read == length_);
00467 }
00468
00469 ProphetTLV::ProphetTLV(const char* logpath) :
00470 oasys::Logger("ProphetTLV",logpath),
00471 result_(Prophet::UnknownResult),
00472 sender_instance_(0),
00473 receiver_instance_(0),
00474 tid_(0),
00475 parsedlen_(0)
00476 {
00477 list_.clear();
00478 }
00479
00480 ProphetTLV::ProphetTLV(Prophet::header_result_t result,
00481 u_int16_t local_instance,
00482 u_int16_t remote_instance,
00483 u_int32_t tid,
00484 const char* logpath) :
00485 oasys::Logger("ProphetTLV",logpath),
00486 result_(result),
00487 sender_instance_(local_instance),
00488 receiver_instance_(remote_instance),
00489 tid_(tid),
00490 parsedlen_(Prophet::ProphetHeaderSize)
00491 {
00492 ASSERTF(local_instance != 0, "0 is not a valid sender_instance id");
00493 list_.clear();
00494 }
00495
00496 ProphetTLV::~ProphetTLV()
00497 {
00498 for(iterator i = list_.begin();
00499 i != list_.end();
00500 i++)
00501 {
00502 BaseTLV* b = *i;
00503 switch(b->typecode()) {
00504 case Prophet::HELLO_TLV:
00505 delete (HelloTLV*) b;
00506 break;
00507 case Prophet::RIBD_TLV:
00508 delete (RIBDTLV*) b;
00509 break;
00510 case Prophet::RIB_TLV:
00511 delete (RIBTLV*) b;
00512 break;
00513 case Prophet::BUNDLE_TLV:
00514 delete (BundleTLV*) b;
00515 break;
00516 case Prophet::UNKNOWN_TLV:
00517 default:
00518 PANIC("Unexpected typecode in ~ProphetTLV");
00519 break;
00520 }
00521 }
00522 }
00523
00524 BaseTLV*
00525 ProphetTLV::get_tlv()
00526 {
00527 if (list_.empty())
00528 return NULL;
00529 BaseTLV* t = list_.front();
00530 list_.pop_front();
00531 return t;
00532 }
00533
00534 void
00535 ProphetTLV::add_tlv(BaseTLV* tlv)
00536 {
00537 ASSERT(tlv != NULL);
00538 parsedlen_ += tlv->length();
00539 list_.push_back(tlv);
00540 }
00541
00542 ProphetTLV*
00543 ProphetTLV::deserialize(Bundle* b,
00544 EndpointID* local,
00545 EndpointID* remote,
00546 const char* logpath)
00547 {
00548
00549 size_t buflen = b->payload_.length();
00550 oasys::ScratchBuffer<u_char*> buf(buflen);
00551
00552
00553 u_char* bp = (u_char*)b->payload_.read_data(0, buflen,
00554 (u_char*)buf.buf(buflen));
00555
00556 ProphetTLV* pt = new ProphetTLV(logpath);
00557 if (local != NULL) local->assign(b->dest_);
00558 if (remote != NULL) remote->assign(b->source_);
00559
00560 if ( pt->deserialize(bp,buflen) ) {
00561 return pt;
00562 }
00563
00564
00565 delete pt;
00566 return NULL;
00567 }
00568
00569 bool
00570 ProphetTLV::deserialize(u_char* bp, size_t buflen)
00571 {
00572
00573 ASSERT(parsedlen_ == 0);
00574
00575 if (bp == NULL)
00576 {
00577 log_err("can't deserialize with uninitialized pointer");
00578 return false;
00579 }
00580
00581 if (buflen < Prophet::ProphetHeaderSize)
00582 {
00583 log_err("not enough buffer to deserialize: got %zu need "
00584 "more than %zu",buflen,Prophet::ProphetHeaderSize);
00585 return false;
00586 }
00587
00588 Prophet::ProphetHeader* hdr = (Prophet::ProphetHeader*) bp;
00589
00590 if (hdr->version != Prophet::PROPHET_VERSION)
00591 {
00592 log_err("unsupported Prophet version %x",hdr->version);
00593 return false;
00594 }
00595
00596 if (hdr->flags != 0)
00597 {
00598 log_err("unsupported Prophet header flags %x",hdr->flags);
00599 return false;
00600 }
00601
00602 if (hdr->code != 0)
00603 {
00604 log_err("unsupported Prophet header code %x",hdr->code);
00605 return false;
00606 }
00607
00608 if (ntohs(hdr->length) != buflen)
00609 {
00610 log_err("badly formatted Prophet header");
00611 return false;
00612 }
00613
00614 result_ = (Prophet::header_result_t) hdr->result;
00615 sender_instance_ = ntohs(hdr->sender_instance);
00616 receiver_instance_ = ntohs(hdr->receiver_instance);
00617 tid_ = ntohl(hdr->transaction_id);
00618 bool submessage_flag = (hdr->submessage_flag == 0x1);
00619 u_int16_t submessage_num = ntohs(hdr->submessage_num);
00620
00621 if (submessage_flag == true || submessage_num != 0) {
00622
00623 return false;
00624 }
00625
00626
00627 size_t hdrsz = Prophet::ProphetHeaderSize;
00628 parsedlen_ = hdrsz;
00629 u_char* p = bp + hdrsz;
00630
00631
00632 Prophet::prophet_tlv_t typecode = Prophet::UNKNOWN_TLV;
00633 size_t len = buflen - hdrsz;
00634 BaseTLV* tlv = NULL;
00635
00636 while (len > 0) {
00637 typecode = (Prophet::prophet_tlv_t)*p;
00638 switch (typecode) {
00639 case Prophet::HELLO_TLV:
00640 tlv = TLVFactory<HelloTLV>::deserialize(p,len,logpath_);
00641 break;
00642 case Prophet::RIBD_TLV:
00643 tlv = TLVFactory<RIBDTLV>::deserialize(p,len,logpath_);
00644 break;
00645 case Prophet::RIB_TLV:
00646 tlv = TLVFactory<RIBTLV>::deserialize(p,len,logpath_);
00647 break;
00648 case Prophet::BUNDLE_TLV:
00649 tlv = TLVFactory<BundleTLV>::deserialize(p,len,logpath_);
00650 break;
00651 default:
00652 break;
00653 }
00654 if (tlv == NULL)
00655 break;
00656
00657 add_tlv(tlv);
00658
00659 p += tlv->length();
00660 len -= tlv->length();
00661 }
00662
00663 return (parsedlen_ == buflen);
00664 }
00665
00666 bool
00667 ProphetTLV::create_bundle(Bundle* b,
00668 const EndpointID& local,
00669 const EndpointID& remote) const
00670 {
00671
00672 oasys::ScratchBuffer<u_char*> buf(parsedlen_);
00673
00674 u_char* bp = buf.buf(parsedlen_);
00675 if (serialize(bp,parsedlen_) != parsedlen_) {
00676 return false;
00677 }
00678
00679 ASSERT (b != NULL);
00680
00681 EndpointID src(local), dest(remote);
00682 src.append_service_tag("prophet");
00683 dest.append_service_tag("prophet");
00684
00685 b->source_.assign(src);
00686 b->dest_.assign(dest);
00687 b->replyto_.assign(EndpointID::NULL_EID());
00688 b->custodian_.assign(EndpointID::NULL_EID());
00689 b->expiration_ = 3600;
00690
00691 b->payload_.set_data(bp,parsedlen_);
00692
00693 return true;
00694 }
00695
00696 size_t
00697 ProphetTLV::serialize(u_char* bp, size_t len) const
00698 {
00699 size_t hdr_sz = Prophet::ProphetHeaderSize;
00700 size_t buflen = hdr_sz;
00701
00702 if (len < parsedlen_) {
00703
00704 return 0;
00705 }
00706
00707
00708 u_char* p = bp + hdr_sz;
00709 len -= hdr_sz;
00710
00711
00712 for(const_iterator ti = (const_iterator) list_.begin();
00713 ti != (const_iterator) list_.end() && len > 0;
00714 ti++)
00715 {
00716 BaseTLV* tlv = *ti;
00717 size_t tlvsize = tlv->serialize(p, len);
00718 if (tlvsize != tlv->length())
00719 break;
00720 buflen += tlvsize;
00721 len -= tlvsize;
00722 p += tlvsize;
00723 }
00724
00725
00726 if(parsedlen_ != buflen) {
00727
00728 return 0;
00729 }
00730
00731
00732 Prophet::ProphetHeader* hdr = (Prophet::ProphetHeader*) bp;
00733 memset(hdr,0,hdr_sz);
00734 hdr->version = Prophet::PROPHET_VERSION;
00735 hdr->flags = 0;
00736 hdr->result = result_;
00737 hdr->code = 0;
00738 hdr->sender_instance = htons(sender_instance_);
00739 hdr->receiver_instance = htons(receiver_instance_);
00740 hdr->transaction_id = htonl(tid_);
00741 hdr->length = htons(parsedlen_);
00742
00743 return parsedlen_;
00744 }
00745
00746 size_t
00747 HelloTLV::serialize(u_char* bp, size_t len)
00748 {
00749 size_t eidsz = sender_.length();
00750 size_t hdrsz = Prophet::HelloTLVHeaderSize;
00751
00752
00753 size_t hello_sz = FOUR_BYTE_ALIGN(hdrsz + eidsz);
00754
00755
00756 if (len < hello_sz)
00757 return 0;
00758
00759 length_ = hello_sz;
00760
00761 Prophet::HelloTLVHeader *hdr = (Prophet::HelloTLVHeader*) bp;
00762
00763 memset(bp,0,length_);
00764 hdr->type = typecode_;
00765 hdr->HF = hf_;
00766 hdr->length = htons(length_);
00767 hdr->timer = timer_;
00768
00769 hdr->name_length = eidsz & 0xff;
00770
00771 size_t buflen = hello_sz;
00772 memcpy(&hdr->sender_name[0],sender_.c_str(),eidsz);
00773
00774
00775 while(buflen-- > hdrsz + eidsz)
00776 bp[buflen] = '\0';
00777
00778 return hello_sz;
00779 }
00780
00781 size_t
00782 RIBDTLV::write_ras_entry(u_int16_t sid,
00783 EndpointID eid,
00784 u_char* buffer,
00785 size_t len)
00786 {
00787 size_t ras_sz = Prophet::RoutingAddressStringSize;
00788 if (len <= ras_sz)
00789 return 0;
00790
00791
00792 memset(buffer,0,ras_sz);
00793
00794 Prophet::RoutingAddressString* ras =
00795 (Prophet::RoutingAddressString*) buffer;
00796
00797 ASSERT(eid.equals(EndpointID::NULL_EID())==false);
00798 size_t retval = ras_sz;
00799 ras->string_id = htons(sid);
00800 ras->length = eid.length() & 0xff;
00801
00802 size_t copylen = FOUR_BYTE_ALIGN(ras->length);
00803 if (len - retval >= copylen) {
00804 memcpy(&ras->ra_string[0],eid.c_str(),ras->length);
00805 retval += copylen;
00806
00807 while (--copylen > ras->length)
00808 ras->ra_string[copylen] = 0;
00809 }
00810
00811 log_debug("write_ras_entry: wrote %zu bytes to %zu byte buffer",
00812 retval,len);
00813 return retval;
00814 }
00815
00816 size_t
00817 RIBDTLV::serialize(u_char* bp, size_t len)
00818 {
00819
00820 size_t ribd_sz = ribd_.guess_ribd_size();
00821 size_t hdrsz = Prophet::RIBDTLVHeaderSize;
00822 if ( len < ribd_sz + hdrsz) {
00823 log_err("serialize buffer length too short - needed > %zu, got %zu",
00824 ribd_sz + hdrsz,len);
00825 return 0;
00826 }
00827
00828 Prophet::RIBDTLVHeader* hdr = (Prophet::RIBDTLVHeader*) bp;
00829 size_t ribd_entry_count = 0;
00830 length_ = 0;
00831
00832
00833 memset(hdr,0,hdrsz);
00834
00835
00836 bp += hdrsz;
00837 length_ += hdrsz;
00838
00839
00840 for (ProphetDictionary::const_iterator it = ribd_.begin();
00841 it != ribd_.end();
00842 it++) {
00843
00844 if ((*it).first == 0 || (*it).first == 1)
00845 continue;
00846
00847 size_t bytes_written = 0;
00848
00849 if ((bytes_written=write_ras_entry((*it).first,
00850 (*it).second,
00851 bp,len)) == 0)
00852 break;
00853
00854 bp += bytes_written;
00855 len -= bytes_written;
00856 length_ += bytes_written;
00857
00858 ribd_entry_count++;
00859 }
00860
00861
00862 hdr->type = Prophet::RIBD_TLV;
00863 hdr->flags = 0;
00864 hdr->length = htons(length_);
00865 hdr->entry_count = htons(ribd_entry_count);
00866
00867 log_debug("serialize wrote %zu of %zu RAS entries for a total %d bytes",
00868 ribd_entry_count,ribd_.size(),length_);
00869 return length_;
00870 }
00871
00872 size_t
00873 RIBTLV::write_rib_entry(u_int16_t sid, double pvalue,
00874 bool relay, bool custody, bool internet,
00875 u_char* buffer, size_t len)
00876 {
00877 size_t rib_sz = Prophet::RIBEntrySize;
00878 if (len < rib_sz)
00879 return 0;
00880
00881
00882 memset(buffer,0,rib_sz);
00883
00884 Prophet::RIBEntry* rib = (Prophet::RIBEntry*) buffer;
00885
00886 rib->string_id = htons(sid);
00887 rib->pvalue = (u_int8_t) ( (int) (pvalue * (256.0)) ) & 0xff;
00888 rib->flags = 0;
00889 if (relay) rib->flags |= Prophet::RELAY_NODE;
00890 if (custody) rib->flags |= Prophet::CUSTODY_NODE;
00891 if (internet) rib->flags |= Prophet::INTERNET_GW_NODE;
00892 log_debug("write_rib_entry: wrote %zu bytes to %zu byte buffer",
00893 rib_sz,len);
00894 return rib_sz;
00895 }
00896
00897 size_t
00898 RIBTLV::serialize(u_char* bp, size_t len)
00899 {
00900 size_t hdrsz = Prophet::RIBTLVHeaderSize;
00901 size_t rib_entry_count = nodes_.size();
00902 length_ = hdrsz + rib_entry_count * Prophet::RIBEntrySize;
00903
00904
00905 if ( len < length_ ) {
00906 log_err("serialize buffer length too short - needed %d got %zu",
00907 length_,len);
00908 return 0;
00909 }
00910
00911 Prophet::RIBTLVHeader* hdr = (Prophet::RIBTLVHeader*) bp;
00912
00913
00914 length_ = 0;
00915 rib_entry_count = 0;
00916
00917
00918 bp += hdrsz;
00919 length_ += hdrsz;
00920
00921 RIBNode *node = NULL;
00922
00923 for(iterator it = nodes_.begin();
00924 it != nodes_.end();
00925 it++) {
00926
00927 node = (*it);
00928
00929 size_t bytes_written = 0;
00930 if ((bytes_written=write_rib_entry(node->sid_,
00931 node->p_value(),
00932 node->relay(),
00933 node->custody(),
00934 node->internet_gw(),
00935 bp,
00936 len)) == 0) {
00937 break;
00938 }
00939
00940 bp += bytes_written;
00941 len -= bytes_written;
00942 length_ += bytes_written;
00943
00944 rib_entry_count++;
00945
00946 node = NULL;
00947 }
00948
00949
00950 hdr->type = typecode_;
00951 hdr->length = htons(length_);
00952 hdr->rib_string_count = htons(rib_entry_count);
00953 hdr->flags = 0;
00954
00955 if (relay_) hdr->flags |= Prophet::RELAY_NODE;
00956 if (custody_) hdr->flags |= Prophet::CUSTODY_NODE;
00957 if (internet_) hdr->flags |= Prophet::INTERNET_GW_NODE;
00958
00959 return length_;
00960 }
00961
00962 size_t
00963 BundleTLV::write_bundle_offer(u_int32_t cts, u_int16_t sid,
00964 bool custody, bool accept, bool ack,
00965 BundleOffer::bundle_offer_t type,
00966 u_char* bp, size_t len)
00967 {
00968 size_t boe_sz = Prophet::BundleOfferEntrySize;
00969 if (len < boe_sz) {
00970 log_debug("not enough buffer to write out Bundle entry, "
00971 "needed %zu but got %zu",boe_sz,len);
00972 return 0;
00973 }
00974 Prophet::BundleOfferEntry* p = (Prophet::BundleOfferEntry*) bp;
00975 memset(p,0,boe_sz);
00976 if (type == BundleOffer::OFFER) {
00977 if (custody)
00978 p->b_flags |= Prophet::CUSTODY_OFFERED;
00979 if (ack)
00980 p->b_flags |= Prophet::PROPHET_ACK;
00981 }
00982 else
00983 if (type == BundleOffer::RESPONSE) {
00984 if (custody)
00985 p->b_flags |= Prophet::CUSTODY_ACCEPTED;
00986 if (accept)
00987 p->b_flags |= Prophet::BUNDLE_ACCEPTED;
00988 }
00989 else
00990 {
00991 log_debug("Bundle entry with undefined type (%d), skipping",
00992 (int)type);
00993 return 0;
00994 }
00995 p->dest_string_id = htons(sid);
00996 p->creation_timestamp = htonl(cts);
00997 return boe_sz;
00998 }
00999
01000 size_t
01001 BundleTLV::serialize(u_char* bp, size_t len)
01002 {
01003
01004 size_t tlv_size = Prophet::BundleOfferTLVHeaderSize +
01005 list_.guess_size();
01006 length_ = 0;
01007
01008
01009 if(len < tlv_size)
01010 return 0;
01011
01012
01013 Prophet::BundleOfferTLVHeader* hdr =
01014 (Prophet::BundleOfferTLVHeader*) bp;
01015 memset(hdr,0,Prophet::BundleOfferTLVHeaderSize);
01016 hdr->type = Prophet::BUNDLE_TLV;
01017 hdr->flags = 0;
01018 hdr->offer_count = htons(list_.size());
01019
01020 length_ += Prophet::BundleOfferTLVHeaderSize;
01021 bp += Prophet::BundleOfferTLVHeaderSize;
01022 len -= Prophet::BundleOfferTLVHeaderSize;
01023
01024
01025 oasys::ScopeLock l(list_.lock(),"BundleTLV::serialize");
01026 BundleOfferList::iterator i = list_.begin();
01027 while (i != list_.end()) {
01028 BundleOffer* bo = *i;
01029
01030 size_t boe_sz = write_bundle_offer(bo->creation_ts(),bo->sid(),
01031 bo->custody(),bo->accept(),bo->ack(),
01032 bo->type(),bp,len);
01033
01034 if (boe_sz == 0)
01035 break;
01036
01037 length_ += boe_sz;
01038 bp += boe_sz;
01039 len -= boe_sz;
01040 i++;
01041 }
01042
01043 hdr->length = htons(length_);
01044 return length_;
01045 }
01046
01047 }