00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "BundleCore.h"
00018 #include "HelloTLV.h"
00019 #include "RIBDTLV.h"
00020 #include "RIBTLV.h"
00021 #include "OfferTLV.h"
00022 #include "ResponseTLV.h"
00023 #include "TLVCreator.h"
00024 #include "Encounter.h"
00025
00026 #define NEXT_TID (++next_tid_ == 0) ? ++next_tid_ : next_tid_
00027
00028 #define PROPHET_TLV(_tlv, _result, _tid) do { \
00029 _tlv = new ProphetTLV( \
00030 oracle_->core()->prophet_id(), \
00031 oracle_->core()->prophet_id(next_hop_), \
00032 _result, \
00033 local_instance_, \
00034 remote_instance_, \
00035 (_tid == 0) ? NEXT_TID : _tid); \
00036 } while (0)
00037
00038 #define SEND_ACK(_tid) send_hello(HelloTLV::ACK, \
00039 ProphetTLV::NoSuccessAck,_tid)
00040 #define SEND_SYN(_tid) send_hello(HelloTLV::SYN, \
00041 ProphetTLV::NoSuccessAck,_tid)
00042 #define SEND_SYNACK(_tid) send_hello(HelloTLV::SYNACK, \
00043 ProphetTLV::NoSuccessAck,_tid)
00044 #define SEND_RSTACK(_tid) send_hello(HelloTLV::RSTACK,\
00045 ProphetTLV::Failure,_tid)
00046
00047 #define LOG(_level, _args...) oracle_->core()->print_log( \
00048 name_.c_str(), BundleCore::_level, _args )
00049
00050 #define SET_STATE(_new) do { LOG(LOG_DEBUG, "state_ %s -> %s %s:%d", \
00051 state_to_str(state_), state_to_str(_new), __FILE__, __LINE__); \
00052 state_ = _new; \
00053 } while (0)
00054
00055 #define UPDATE_PEER_VERIFIER(_sender_instance) do { \
00056 remote_instance_ = _sender_instance; \
00057 LOG(LOG_DEBUG, "update peer verifier %d", \
00058 (_sender_instance)); } while (0) \
00059
00060 #define ASSIGN_ROLES(_s,_r) do { \
00061 if (synsender_) { \
00062 _s = oracle_->core()->local_eid(); \
00063 _r = next_hop_->remote_eid(); } \
00064 else { \
00065 _s = next_hop_->remote_eid(); \
00066 _r = oracle_->core()->local_eid(); }\
00067 } while (0)
00068
00069
00070 namespace prophet
00071 {
00072
00073 Encounter::Encounter(const Link* nexthop,
00074 Oracle* oracle,
00075 u_int16_t instance)
00076 : ExpirationHandler(),
00077 oracle_(oracle),
00078 local_instance_(instance),
00079 remote_instance_(0),
00080 tid_(0),
00081 next_tid_(0),
00082 timeout_(oracle_->params()->hello_interval() * 100),
00083 next_hop_(nexthop),
00084 tlv_(NULL),
00085 synsender_(oracle_->core()->local_eid().compare(
00086 next_hop_->remote_eid()) < 0),
00087 state_(WAIT_NB),
00088 synsent_(false),
00089 estab_(false),
00090 neighbor_gone_(false),
00091 remote_nodes_(oracle_->core(),"remote",false),
00092 hello_rate_(0),
00093 data_sent_(time(0)),
00094 data_rcvd_(time(0)),
00095 alarm_(NULL)
00096 {
00097 std::string name("encounter-");
00098 char buff[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00099 size_t len = snprintf(buff,10,"%d",instance);
00100 name.append(buff,len);
00101 ExpirationHandler::set_name(name.c_str());
00102
00103 if (synsender_)
00104 if (send_hello(HelloTLV::SYN))
00105 SET_STATE(SYNSENT);
00106
00107
00108 alarm_ = oracle_->core()->create_alarm(this,timeout_);
00109 if (alarm_ == NULL) neighbor_gone_ = true;
00110
00111 LOG(LOG_DEBUG,"constructor(%s,%u)",nexthop->remote_eid(),instance);
00112
00113 }
00114
00115 Encounter::Encounter(const Encounter& e)
00116 : ExpirationHandler(e),
00117 oracle_(e.oracle_),
00118 local_instance_(e.local_instance_),
00119 remote_instance_(e.remote_instance_),
00120 tid_(e.tid_),
00121 timeout_(e.timeout_),
00122 next_hop_(e.next_hop_),
00123 tlv_(e.tlv_),
00124 synsender_(e.synsender_),
00125 state_(e.state_),
00126 synsent_(e.synsent_),
00127 estab_(e.estab_),
00128 neighbor_gone_(e.neighbor_gone_),
00129 local_ribd_(e.local_ribd_),
00130 remote_ribd_(e.remote_ribd_),
00131 remote_offers_(e.remote_offers_),
00132 local_response_(e.local_response_),
00133 remote_nodes_(e.remote_nodes_),
00134 hello_rate_(e.hello_rate_),
00135 data_sent_(e.data_sent_),
00136 data_rcvd_(e.data_rcvd_),
00137 alarm_(NULL)
00138 {
00139 LOG(LOG_DEBUG,"copy constructor(%u)",local_instance_);
00140 alarm_ = oracle_->core()->create_alarm(this,e.alarm_->time_remaining());
00141 if (alarm_ == NULL) neighbor_gone_ = true;
00142 }
00143
00144 Encounter::~Encounter()
00145 {
00146 if (alarm_ != NULL && alarm_->pending())
00147 alarm_->cancel();
00148 }
00149
00150 void
00151 Encounter::hello_interval_changed()
00152 {
00153 if (neighbor_gone_) return;
00154
00155
00156 u_int timeout = oracle_->params()->hello_interval() * 100;
00157 if (timeout == timeout_) return;
00158
00159
00160 if (alarm_->pending())
00161 {
00162 if (alarm_->time_remaining() == 0)
00163
00164 goto set_timeout;
00165
00166
00167 u_int diff;
00168 u_int new_alarm;
00169 if (timeout_ > timeout)
00170 {
00171
00172 diff = timeout_ - timeout;
00173 new_alarm = alarm_->time_remaining() < diff ?
00174 0 : alarm_->time_remaining() - diff;
00175 }
00176 else
00177 {
00178
00179 diff = timeout - timeout_;
00180 new_alarm = alarm_->time_remaining() + diff;
00181 }
00182
00183
00184 alarm_->cancel();
00185
00186
00187 alarm_ = oracle_->core()->create_alarm(this,new_alarm);
00188
00189
00190 if (alarm_ == NULL) neighbor_gone_ = true;
00191 }
00192
00193 set_timeout:
00194 LOG(LOG_DEBUG,"hello_interval changed (%u -> %u)", timeout_,timeout);
00195
00196
00197 timeout_ = timeout;
00198 }
00199
00200 bool
00201 Encounter::receive_tlv(ProphetTLV* tlv)
00202 {
00203 if (neighbor_gone_) return false;
00204
00205 if (tlv == NULL)
00206 return false;
00207
00208 LOG(LOG_DEBUG,"receive_tlv");
00209
00210
00211 tlv_ = tlv;
00212
00213
00214 data_rcvd_ = time(0);
00215
00216
00217 if (alarm_->pending())
00218 alarm_->cancel();
00219
00220
00221 tid_ = tlv_->transaction_id();
00222
00223 BaseTLV* bt = NULL;
00224 bool ok = true;
00225
00226 while ( (bt = tlv_->get_tlv()) != NULL && ok )
00227 {
00228 ok = dispatch_tlv(bt);
00229 delete bt;
00230 }
00231
00232
00233 delete tlv_;
00234 tlv_ = NULL;
00235
00236 if (ok)
00237 {
00238
00239
00240 if (alarm_->pending())
00241 alarm_->cancel();
00242 else
00243 delete alarm_;
00244
00245 alarm_ = oracle_->core()->create_alarm(this,timeout_,true);
00246
00247
00248 if (alarm_ == NULL) neighbor_gone_ = true;
00249 }
00250 else
00251
00252 neighbor_gone_ = true;
00253
00254 return ok;
00255 }
00256
00257 bool
00258 Encounter::dispatch_tlv(BaseTLV* tlv)
00259 {
00260 LOG(LOG_DEBUG,"dispatch_tlv");
00261
00262 bool ok = false;
00263 bool pre_dispatch = estab_;
00264
00265 switch (tlv->typecode())
00266 {
00267 case BaseTLV::HELLO_TLV:
00268 ok = handle_hello_tlv(tlv);
00269 if (ok && !pre_dispatch && estab_)
00270 {
00271
00272
00273 if (synsender_)
00274 {
00275 SET_STATE(CREATE_DR);
00276 bool ok = send_dictionary_rib();
00277 if (ok) SET_STATE(SEND_DR);
00278 return ok;
00279 }
00280 else
00281 SET_STATE(WAIT_DICT);
00282 }
00283 return ok;
00284 case BaseTLV::RIBD_TLV:
00285 if (! estab_) break;
00286 return handle_ribd_tlv(tlv);
00287 case BaseTLV::RIB_TLV:
00288 if (! estab_) break;
00289 return handle_rib_tlv(tlv);
00290 case BaseTLV::OFFER_TLV:
00291 if (! estab_) break;
00292 ok = handle_offer_tlv(tlv);
00293 if (ok && synsender_ && state_ == WAIT_INFO)
00294 {
00295
00296 SET_STATE(WAIT_DICT);
00297 }
00298 return ok;
00299 case BaseTLV::RESPONSE_TLV:
00300 if (! estab_) break;
00301 ok = handle_response_tlv(tlv);
00302 if (ok && !synsender_ && state_ == WAIT_INFO)
00303 {
00304
00305 SET_STATE(CREATE_DR);
00306 ok = send_dictionary_rib();
00307 if (ok) SET_STATE(SEND_DR);
00308 }
00309 return ok;
00310 case BaseTLV::ERROR_TLV:
00311 case BaseTLV::UNKNOWN_TLV:
00312 default:
00313 return false;
00314 }
00315
00316
00317
00318 hello_rate_ = 2;
00319 if (state_ == SYNSENT)
00320 return SEND_SYN(NEXT_TID);
00321 else if (state_ == SYNRCVD)
00322 return SEND_SYNACK(tid_);
00323
00324
00325 return true;
00326 }
00327
00328 void
00329 Encounter::handle_bundle_received(const Bundle* b)
00330 {
00331 if (state_ != REQUEST) return;
00332 if (b == NULL) return;
00333
00334 LOG(LOG_DEBUG,"handle_bundle_received: "
00335 "%s %u:%u",b->destination_id().c_str(),
00336 b->creation_ts(), b->sequence_num());
00337
00338
00339 std::string eid = oracle_->core()->get_route(b->destination_id());
00340
00341
00342 u_int sid = local_ribd_.find(eid);
00343
00344
00345 if (sid == Dictionary::INVALID_SID) return;
00346
00347
00348 local_response_.remove_entry(
00349 b->creation_ts(),
00350 b->sequence_num(),
00351 sid);
00352
00353
00354
00355 if (alarm_->pending())
00356 alarm_->cancel();
00357 else
00358 delete alarm_;
00359
00360
00361 alarm_ = oracle_->core()->create_alarm(this,timeout_,true);
00362
00363
00364 if (alarm_ == NULL) neighbor_gone_ = true;
00365 }
00366
00367 void
00368 Encounter::handle_timeout()
00369 {
00370 LOG(LOG_DEBUG,"handle_timeout");
00371
00372 if (neighbor_gone_) return;
00373
00374 bool ok = false;
00375 switch (state_)
00376 {
00377 case WAIT_NB:
00378 ok = true;
00379 SET_STATE(WAIT_NB);
00380 break;
00381 case SYNSENT:
00382 ok = SEND_SYN(NEXT_TID);
00383 SET_STATE(SYNSENT);
00384 break;
00385 case SYNRCVD:
00386 ok = SEND_SYNACK(tid_);
00387 SET_STATE(SYNRCVD);
00388 break;
00389 case ESTAB:
00390
00391 ok = false;
00392 break;
00393 case WAIT_DICT:
00394 ok = SEND_ACK(tid_);
00395 SET_STATE(WAIT_DICT);
00396 break;
00397 case WAIT_RIB:
00398 ok = SEND_ACK(tid_);
00399 SET_STATE(WAIT_DICT);
00400 break;
00401 case OFFER:
00402 ok = send_offer();
00403 SET_STATE(OFFER);
00404 break;
00405 case SEND_DR:
00406 ok = send_dictionary_rib();
00407 if (ok) SET_STATE(SEND_DR);
00408 break;
00409 case REQUEST:
00410 ok = send_response();
00411 break;
00412 case WAIT_INFO:
00413
00414
00415 if (time(0) - data_rcvd_ >
00416 (oracle_->params()->hello_dead() *
00417 oracle_->params()->hello_interval() / 20))
00418 {
00419 if (synsender_)
00420 {
00421 SET_STATE(CREATE_DR);
00422 ok = send_dictionary_rib();
00423 if (ok) SET_STATE(SEND_DR);
00424 }
00425 else
00426 {
00427 SET_STATE(WAIT_DICT);
00428 ok = true;
00429 }
00430 }
00431 else
00432 ok = true;
00433 break;
00434 default:
00435 break;
00436 }
00437
00438
00439 if (!ok ||
00440 (time(0) - data_rcvd_) >
00441 (oracle_->params()->hello_dead() *
00442
00443 oracle_->params()->hello_interval() / 10))
00444 {
00445 neighbor_gone_ = true;
00446 return;
00447 }
00448
00449
00450
00451 if (alarm_->pending())
00452 alarm_->cancel();
00453 else
00454 delete alarm_;
00455
00456
00457 alarm_ = oracle_->core()->create_alarm(this,timeout_,true);
00458
00459
00460 if (alarm_ == NULL) neighbor_gone_ = true;
00461 }
00462
00463 bool
00464 Encounter::handle_hello_tlv(BaseTLV* tlv)
00465 {
00466 if (tlv_ == NULL) return false;
00467 HelloTLV* hello = static_cast<HelloTLV*>(tlv);
00468 if (hello == NULL || hello->typecode() != BaseTLV::HELLO_TLV)
00469 return false;
00470
00471 LOG(LOG_DEBUG,"handle_hello_tlv(%s,%u) from %s",
00472 hello->hf_str(),hello->timer(),hello->sender().c_str());
00473
00474
00475 bool hello_a = (remote_instance_ == tlv_->sender_instance());
00476 LOG(LOG_DEBUG,"hello_a %s remote_instance_ %u tlv %u",
00477 hello_a ? "true" : "false", remote_instance_,
00478 tlv_->sender_instance());
00479 bool hello_b = hello_a &&
00480 (oracle_->core()->prophet_id(next_hop_) == tlv_->source());
00481 LOG(LOG_DEBUG,"hello_b %s next_hop_ %s tlv %s",
00482 hello_b ? "true" : "false",
00483 oracle_->core()->prophet_id(next_hop_).c_str(),
00484 tlv_->source().c_str());
00485 bool hello_c = (local_instance_ == tlv_->receiver_instance());
00486 LOG(LOG_DEBUG,"hello_c %s local_instance_ %u tlv %u",
00487 hello_c ? "true" : "false",
00488 local_instance_, tlv_->receiver_instance());
00489
00490
00491 u_int timeout = std::min((u_int)oracle_->params()->hello_interval(),
00492 (u_int)hello->timer(), std::less<u_int>());
00493
00494 if (!estab_ && (timeout * 100) != timeout_)
00495 {
00496 LOG(LOG_DEBUG,"timeout_ %u -> %u (line %d)",
00497 timeout_, timeout, __LINE__);
00498
00499 timeout_ = timeout * 100;
00500 }
00501
00502 bool ok = true;
00503 switch (hello->hf())
00504 {
00505 case HelloTLV::SYN:
00506 if (estab_)
00507 {
00508
00509 hello_rate_ = 2;
00510 ok = SEND_ACK(tid_);
00511 }
00512 else
00513 if (state_ == SYNSENT ||
00514 state_ == SYNRCVD ||
00515 state_ == WAIT_NB)
00516 {
00517 UPDATE_PEER_VERIFIER(tlv_->sender_instance());
00518 LOG(LOG_DEBUG,"handle_hello_tlv(SYN): state_ %s remote_instance_ %u",
00519 state_to_str(state_),remote_instance_);
00520 ok = SEND_SYNACK(tid_);
00521 SET_STATE(SYNRCVD);
00522 }
00523 break;
00524 case HelloTLV::SYNACK:
00525 if (estab_)
00526 {
00527
00528 hello_rate_ = 2;
00529 ok = SEND_ACK(tid_);
00530 }
00531 else
00532 if (state_ == SYNSENT)
00533 {
00534 if ( hello_c)
00535 {
00536 hello_rate_ = 0;
00537 UPDATE_PEER_VERIFIER(tlv_->sender_instance());
00538 if (ok = SEND_ACK(tid_))
00539 {
00540 SET_STATE(ESTAB);
00541 estab_ = true;
00542 }
00543 }
00544 else
00545 {
00546 ok = SEND_RSTACK(tid_);
00547 SET_STATE(SYNSENT);
00548 }
00549 }
00550 else
00551 if (state_ == SYNRCVD)
00552 {
00553 if (hello_c)
00554 {
00555 hello_rate_ = 0;
00556 UPDATE_PEER_VERIFIER(tlv_->sender_instance());
00557 if (ok = SEND_ACK(tid_))
00558 {
00559 SET_STATE(ESTAB);
00560 estab_ = true;
00561 }
00562 }
00563 else
00564 {
00565 ok = SEND_RSTACK(tid_);
00566 SET_STATE(SYNRCVD);
00567 }
00568 }
00569 break;
00570 case HelloTLV::ACK:
00571 if (estab_ && !(hello_b && hello_c))
00572 {
00573 ok = SEND_RSTACK(tid_);
00574 break;
00575 }
00576 if (state_ == SYNSENT)
00577 {
00578 ok = SEND_RSTACK(tid_);
00579 SET_STATE(SYNSENT);
00580 }
00581 else
00582 if (state_ == SYNRCVD)
00583 {
00584 if (hello_b && hello_c)
00585 {
00586 SET_STATE(ESTAB);
00587 estab_ = true;
00588 }
00589 else
00590 {
00591 LOG(LOG_DEBUG,"handle_hello_tlv(ACK): state_ SYNRCVD "
00592 "remote_instance_ %u tlv instance %u",
00593 remote_instance_,tlv_->sender_instance());
00594 ok = SEND_RSTACK(tid_);
00595 SET_STATE(SYNRCVD);
00596 }
00597 }
00598 else
00599 if (state_ == WAIT_RIB || state_ == OFFER)
00600 {
00601 SET_STATE(WAIT_DICT);
00602 }
00603 else
00604 if (state_ == REQUEST)
00605 {
00606 SET_STATE(CREATE_DR);
00607 ok = send_dictionary_rib();
00608 if (ok) SET_STATE(SEND_DR);
00609 }
00610 else
00611 if (state_ == WAIT_INFO)
00612 {
00613
00614 if (time(0) - data_sent_ > oracle_->params()->hello_interval())
00615 {
00616 if (synsender_)
00617 {
00618 SET_STATE(CREATE_DR);
00619 bool ok = send_dictionary_rib();
00620 if (ok) SET_STATE(SEND_DR);
00621 return ok;
00622 }
00623 else
00624 {
00625 SET_STATE(WAIT_DICT);
00626 }
00627 }
00628 }
00629 break;
00630 case HelloTLV::RSTACK:
00631 if (hello_a && hello_c && !synsent_)
00632 {
00633
00634 return false;
00635 }
00636 break;
00637 case HelloTLV::HF_UNKNOWN:
00638 default:
00639 break;
00640 }
00641
00642 return ok;
00643 }
00644
00645 bool
00646 Encounter::handle_ribd_tlv(BaseTLV* tlv)
00647 {
00648 LOG(LOG_DEBUG,"handle_ribd_tlv");
00649
00650 RIBDTLV* ribd = static_cast<RIBDTLV*>(tlv);
00651 if (ribd == NULL)
00652 return false;
00653
00654
00655 std::string sender, receiver;
00656 ASSIGN_ROLES(sender,receiver);
00657
00658 switch (state_)
00659 {
00660 case WAIT_INFO:
00661
00662 if (time(0) - data_sent_ > oracle_->params()->hello_interval())
00663 {
00664 if (synsender_)
00665 return false;
00666 else
00667 SET_STATE(WAIT_DICT);
00668 }
00669 case WAIT_DICT:
00670 case WAIT_RIB:
00671 remote_ribd_ = ribd->ribd(sender,receiver);
00672 remote_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00673 SET_STATE(WAIT_RIB);
00674 return true;
00675 case OFFER:
00676 SET_STATE(OFFER);
00677 return send_offer();
00678 default:
00679 break;
00680 }
00681 return false;
00682 }
00683
00684 bool
00685 Encounter::handle_rib_tlv(BaseTLV* tlv)
00686 {
00687 LOG(LOG_DEBUG,"handle_rib_tlv");
00688
00689 RIBTLV* rib = static_cast<RIBTLV*>(tlv);
00690 if (rib == NULL)
00691 return false;
00692
00693 remote_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00694 Table* nodes = oracle_->nodes();
00695 if (state_ == WAIT_RIB)
00696 {
00697
00698 nodes->update_route(next_hop_->remote_eid(),
00699 rib->relay(),
00700 rib->custody(),
00701 rib->internet());
00702
00703 nodes->update_transitive(next_hop_->remote_eid(),
00704 rib->nodes(),
00705 remote_ribd_);
00706
00707 remote_nodes_.assign(rib->nodes(),
00708 remote_ribd_);
00709 SET_STATE(OFFER);
00710 return send_offer();
00711 }
00712 return false;
00713 }
00714
00715 bool
00716 Encounter::handle_offer_tlv(BaseTLV* tlv)
00717 {
00718 LOG(LOG_DEBUG,"handle_offer_tlv");
00719
00720 OfferTLV* offer = static_cast<OfferTLV*>(tlv);
00721 if (offer == NULL)
00722 {
00723 LOG(LOG_DEBUG,"failed to downcast tlv");
00724 return false;
00725 }
00726
00727 if (state_ == SEND_DR || state_ == REQUEST)
00728 {
00729 remote_offers_ = offer->list();
00730 LOG(LOG_DEBUG,"received %zu offers",remote_offers_.size());
00731 SET_STATE(REQUEST);
00732 return send_response();
00733 }
00734 else if (state_ == WAIT_INFO)
00735 {
00736
00737 return true;
00738 }
00739 else
00740 {
00741 LOG(LOG_ERR,"received offer tlv when state_ == %s",state_str());
00742 }
00743
00744 return false;
00745 }
00746
00747 bool
00748 Encounter::handle_response_tlv(BaseTLV* tlv)
00749 {
00750 LOG(LOG_DEBUG,"handle_response_tlv");
00751
00752 ResponseTLV* response = static_cast<ResponseTLV*>(tlv);
00753 if (response == NULL)
00754 return false;
00755
00756 switch (state_)
00757 {
00758 case WAIT_RIB:
00759 SET_STATE(WAIT_DICT);
00760 return SEND_ACK(tid_);
00761 case OFFER:
00762
00763 if (response->list().empty())
00764 {
00765 LOG(LOG_DEBUG,"received empty request");
00766 SET_STATE(WAIT_INFO);
00767 return true;
00768 }
00769 else
00770 {
00771 LOG(LOG_DEBUG,"received %zu requests",response->list().size());
00772
00773 BundleList bundles = oracle_->core()->bundles();
00774
00775 remote_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00776
00777
00778 for(BundleResponseList::const_iterator i =
00779 response->list().begin();
00780 i != response->list().end();
00781 i++)
00782 {
00783
00784 std::string eid = remote_ribd_.find((*i)->sid());
00785 const Bundle* b = oracle_->core()->find(bundles,
00786 eid,(*i)->creation_ts(),(*i)->seqno());
00787
00788
00789 if (b == NULL)
00790 {
00791 LOG(LOG_ERR,"failed to locate bundle for request "
00792 "%u -> %s, %u, %u", (*i)->sid(),
00793 remote_ribd_.find((*i)->sid()).c_str(),
00794 (*i)->creation_ts(),(*i)->seqno());
00795 continue;
00796 }
00797
00798
00799 if (!oracle_->core()->send_bundle(b,next_hop_))
00800 {
00801 LOG(LOG_ERR,"failed to send bundle for request "
00802 "%s, %u, %u", remote_ribd_.find((*i)->sid()).c_str(),
00803 (*i)->creation_ts(),(*i)->seqno());
00804 continue;
00805 }
00806
00807
00808 data_sent_ = time(0);
00809
00810 }
00811 SET_STATE(OFFER);
00812 return true;
00813 }
00814 default:
00815 LOG(LOG_ERR,"received response when state_ == %s",
00816 state_to_str(state_));
00817 break;
00818 }
00819
00820 return false;
00821 }
00822
00823 bool
00824 Encounter::send_hello(HelloTLV::hello_hf_t hf,
00825 ProphetTLV::header_result_t hr,
00826 u_int32_t tid)
00827 {
00828
00829
00830 if ((state_ != WAIT_NB) &&
00831 (hello_rate_ > 0) &&
00832 (hf != HelloTLV::RSTACK) &&
00833 (time(0) - data_sent_ < timeout_ / hello_rate_) )
00834 return true;
00835
00836
00837
00838 HelloTLV* ht = new HelloTLV(hf,
00839 oracle_->params()->hello_interval(),
00840 oracle_->core()->local_eid());
00841
00842 LOG(LOG_DEBUG,"send_hello(%s,%u)",
00843 ht->hf_str(),ht->timer());
00844
00845
00846 ProphetTLV* tlv = NULL;
00847 PROPHET_TLV(tlv,hr,tid);
00848 if (tlv == NULL)
00849 {
00850 delete ht;
00851 delete tlv;
00852 return false;
00853 }
00854
00855
00856 if (!tlv->add_tlv(ht))
00857 {
00858 delete ht;
00859 delete tlv;
00860 return false;
00861 }
00862
00863
00864 bool ok = send_tlv(tlv);
00865
00866
00867 if (ok && (hf == HelloTLV::SYN || hf == HelloTLV::SYNACK))
00868 synsent_ = true;
00869
00870 return ok;
00871 }
00872
00873 bool
00874 Encounter::send_dictionary_rib(ProphetTLV::header_result_t hr,
00875 u_int32_t tid)
00876 {
00877 LOG(LOG_DEBUG,"send_dictionary_rib");
00878
00879 if (state_ != CREATE_DR && state_ != SEND_DR)
00880 return false;
00881
00882
00883 std::string sender, receiver;
00884 ASSIGN_ROLES(sender,receiver);
00885
00886
00887 RIBDTLV* ribdtlv = TLVCreator::ribd(oracle_->core(),
00888 oracle_->nodes(),
00889 sender, receiver);
00890
00891 if (ribdtlv == NULL) return false;
00892
00893
00894 local_ribd_ = ribdtlv->ribd(sender,receiver);
00895 local_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00896
00897
00898 ProphetTLV* tlv = NULL;
00899 PROPHET_TLV(tlv,hr,tid);
00900 if (tlv == NULL)
00901 {
00902 delete ribdtlv;
00903 return false;
00904 }
00905
00906
00907 if (!tlv->add_tlv(ribdtlv))
00908 {
00909 delete ribdtlv;
00910 delete tlv;
00911 return false;
00912 }
00913
00914 RIBTLV* rib = TLVCreator::rib(oracle_,
00915 local_ribd_,
00916 oracle_->params()->relay_node(),
00917 oracle_->core()->custody_accepted(),
00918 oracle_->params()->internet_gw());
00919
00920 if (rib == NULL)
00921 {
00922 delete tlv;
00923 return false;
00924 }
00925
00926
00927 if (!tlv->add_tlv(rib))
00928 {
00929 delete rib;
00930 delete tlv;
00931 return false;
00932 }
00933
00934
00935 return send_tlv(tlv);
00936 }
00937
00938 bool
00939 Encounter::send_offer(ProphetTLV::header_result_t hr,
00940 u_int32_t tid)
00941 {
00942 LOG(LOG_DEBUG,"send_offer");
00943 remote_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00944
00945
00946 OfferTLV* offer = TLVCreator::offer(oracle_,
00947 next_hop_,
00948 remote_ribd_,
00949 remote_nodes_);
00950
00951 if (offer == NULL) return false;
00952
00953
00954 ProphetTLV* tlv = NULL;
00955 PROPHET_TLV(tlv,hr,tid);
00956 if (tlv == NULL)
00957 {
00958 delete offer;
00959 return false;
00960 }
00961
00962
00963 if (!tlv->add_tlv(offer))
00964 {
00965 delete offer;
00966 delete tlv;
00967 return false;
00968 }
00969
00970
00971 return send_tlv(tlv);
00972 }
00973
00974 bool
00975 Encounter::send_response(ProphetTLV::header_result_t hr,
00976 u_int32_t tid)
00977 {
00978 LOG(LOG_DEBUG,"send_response");
00979 local_ribd_.dump(oracle_->core(),__FILE__,__LINE__);
00980
00981 ResponseTLV* response = TLVCreator::response(oracle_,
00982 remote_offers_,
00983 local_response_,
00984 local_ribd_);
00985
00986 if (response == NULL) return false;
00987
00988
00989 ProphetTLV* tlv = NULL;
00990 PROPHET_TLV(tlv,hr,tid);
00991 if (tlv == NULL)
00992 {
00993 delete response;
00994 return false;
00995 }
00996
00997
00998 if (!tlv->add_tlv(response))
00999 {
01000 delete response;
01001 delete tlv;
01002 return false;
01003 }
01004
01005
01006 bool wait_info = local_response_.empty();
01007
01008
01009 bool ok = send_tlv(tlv);
01010
01011 if (wait_info && ok)
01012 SET_STATE(WAIT_INFO);
01013
01014 return ok;
01015 }
01016
01017 bool
01018 Encounter::send_tlv(ProphetTLV* tlv)
01019 {
01020
01021 if (tlv == NULL) return false;
01022
01023 LOG(LOG_DEBUG,"send_tlv(%u) with %zu TLVs",tid_,tlv->size());
01024
01025
01026
01027
01028 Bundle* b = oracle_->core()->create_bundle(
01029 tlv->source(),tlv->destination(),
01030 oracle_->params()->hello_dead() *
01031 oracle_->params()->hello_interval() / 10);
01032
01033
01034
01035 u_char* buf = new u_char[tlv->length() + 512];
01036
01037 size_t len = tlv->serialize(buf,tlv->length() + 512);
01038 bool ok = oracle_->core()->write_bundle(b,buf,len);
01039
01040
01041 delete [] buf;
01042 delete tlv;
01043
01044 if (ok)
01045 {
01046 ok = oracle_->core()->send_bundle(b, next_hop_);
01047 if (ok)
01048 {
01049
01050 data_sent_ = time(0);
01051 }
01052 else
01053 LOG(LOG_ERR,"failed to send TLV");
01054 }
01055
01056 return ok;
01057 }
01058
01059 };