00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _DTN_PROPHET_ENCOUNTER_
00018 #define _DTN_PROPHET_ENCOUNTER_
00019
00020 #include <oasys/debug/Log.h>
00021 #include <oasys/thread/MsgQueue.h>
00022 #include <oasys/util/Time.h>
00023 #include "naming/EndpointID.h"
00024 #include "contacts/Link.h"
00025 #include <sys/types.h>
00026
00027 #include "routing/Prophet.h"
00028 #include "routing/ProphetNode.h"
00029 #include "routing/ProphetLists.h"
00030 #include "routing/ProphetTLV.h"
00031
00032 #include "bundling/BundleList.h"
00033 #include "bundling/BundleActions.h"
00034
00039 namespace dtn {
00040
00041 class ProphetOracle {
00042 public:
00043 virtual ~ProphetOracle() {}
00044 virtual ProphetParams* params() = 0;
00045 virtual ProphetBundleQueue* bundles() = 0;
00046 virtual ProphetTable* nodes() = 0;
00047 virtual BundleActions* actions() = 0;
00048 virtual ProphetAckList* acks() = 0;
00049 virtual ProphetStats* stats() = 0;
00050 };
00051
00069 class ProphetEncounter : public oasys::Thread,
00070 public oasys::Logger
00071 {
00072 public:
00073
00085 typedef enum {
00086 PEMSG_INVALID = 0,
00087 PEMSG_PROPHET_TLV_RECEIVED,
00088 PEMSG_HELLO_INTERVAL_CHANGED,
00089 PEMSG_NEIGHBOR_GONE,
00090 } pemsg_t;
00091
00092 const char* pemsg_to_str(pemsg_t type) {
00093 switch(type) {
00094 case PEMSG_INVALID: return "PEMSG_INVALID";
00095 case PEMSG_PROPHET_TLV_RECEIVED: return "PEMSG_PROPHET_TLV_RECEIVED";
00096 case PEMSG_HELLO_INTERVAL_CHANGED: return "PEMSG_HELLO_INTERVAL_CHANGED";
00097 case PEMSG_NEIGHBOR_GONE: return "PEMSG_NEIGHBOR_GONE";
00098 default: PANIC("bogus pemsg_t");
00099 }
00100 }
00101
00102 struct PEMsg {
00103 PEMsg()
00104 : type_(PEMSG_INVALID),
00105 tlv_(NULL) {}
00106 PEMsg(pemsg_t type,ProphetTLV* tlv = NULL)
00107 : type_(type), tlv_(tlv) {}
00108
00109 pemsg_t type_;
00110 ProphetTLV* tlv_;
00111 };
00112
00117 ProphetEncounter(Link* nexthop,
00118 ProphetOracle* oracle);
00119
00120 private:
00124 ProphetEncounter(const ProphetEncounter& pe)
00125 :
00126 oasys::Thread("ProphetEncounter"),
00127 oasys::Logger("ProphetEncounter",pe.logpath_),
00128 cmdqueue_("/dtn/route/prophet/encounter"),
00129 to_be_fwd_("ProphetEncounter to be forwarded") {}
00130
00131 public:
00132 virtual ~ProphetEncounter();
00133
00134 typedef enum {
00135 UNDEFINED = 0,
00136 WAIT_NB,
00137 SYNSENT,
00138 SYNRCVD,
00139 ESTAB,
00140 WAIT_DICT,
00141 WAIT_RIB,
00142 OFFER,
00143 CREATE_DR,
00144 SEND_DR,
00145 REQUEST,
00146 WAIT_INFO
00147 } prophet_state_t;
00148
00149 static const char* state_to_str(prophet_state_t st) {
00150 switch(st) {
00151 #define CASE(_state) case _state: return # _state
00152 CASE(WAIT_NB);
00153 CASE(SYNSENT);
00154 CASE(SYNRCVD);
00155 CASE(ESTAB);
00156 CASE(WAIT_DICT);
00157 CASE(WAIT_RIB);
00158 CASE(OFFER);
00159 CASE(CREATE_DR);
00160 CASE(SEND_DR);
00161 CASE(REQUEST);
00162 CASE(WAIT_INFO);
00163 #undef CASE
00164 default: PANIC("Unknown State");
00165 }
00166 }
00167
00172 void receive_tlv(ProphetTLV*);
00173
00178 u_int16_t remote_instance() const { return remote_instance_; }
00179
00184 u_int16_t local_instance() const { return local_instance_; }
00185
00186 const EndpointID& remote_eid() const { return next_hop_->remote_eid(); }
00187
00188 bool operator< (const ProphetEncounter& p) const;
00189 bool operator< (u_int16_t instance) const;
00190
00191 Link* next_hop() const {return next_hop_;}
00192
00204 void reset_link();
00205
00209 void neighbor_gone();
00210
00216 void flush_pending() { fwd_to_nexthop(NULL); }
00217
00218 void dump_state(oasys::StringBuffer* buf);
00219 void handle_bundle_received(Bundle*);
00220 void hello_interval_changed() {
00221 log_notice("hello_interval_changed");
00222 cmdqueue_.push_back(PEMsg(PEMSG_HELLO_INTERVAL_CHANGED));
00223 }
00224 protected:
00225
00230 void run();
00231
00239 void update_peer_verifier(u_int16_t instance) {
00240 remote_instance_ = instance;
00241 remote_addr_ = next_hop_->nexthop();
00242 }
00243
00247 void process_command();
00248
00252 void handle_prophet_tlv(ProphetTLV* pt);
00253
00257 bool handle_hello_tlv(HelloTLV* hello,ProphetTLV* pt);
00258
00262 bool handle_ribd_tlv(RIBDTLV* ribd,ProphetTLV* pt);
00263
00267 bool handle_rib_tlv(RIBTLV* rib,ProphetTLV* pt);
00268
00272 bool handle_bundle_tlv(BundleTLV* btlv,ProphetTLV* pt);
00273
00277 bool handle_bad_protocol(u_int32_t tid);
00278
00282 void handle_neighbor_gone();
00283
00287 void handle_poll_timeout();
00288
00294 void switch_info_role();
00295
00300 void reset_ribd();
00301
00305 void handle_hello_interval_changed();
00306
00310 void send_dictionary();
00311
00315 void send_bundle_offer();
00316
00321
00322 void enqueue_hello(Prophet::hello_hf_t hf,
00323 u_int32_t tid = 0,
00324 Prophet::header_result_t result = Prophet::NoSuccessAck);
00325 void enqueue_ribd(const ProphetDictionary& ribd,
00326 u_int32_t tid = 0,
00327 Prophet::header_result_t result = Prophet::NoSuccessAck);
00328 void enqueue_rib(const RIBTLV::List& nodes,
00329 u_int32_t tid = 0,
00330 Prophet::header_result_t result = Prophet::NoSuccessAck);
00331 void enqueue_bundle_tlv(const BundleOfferList& list,
00332 u_int32_t tid = 0,
00333 Prophet::header_result_t result = Prophet::NoSuccessAck);
00335
00339 ProphetTLV* outbound_tlv(u_int32_t tid,
00340 Prophet::header_result_t result);
00341
00345 bool send_prophet_tlv();
00346
00350 bool should_fwd(Bundle* bundle);
00351
00355 void fwd_to_nexthop(Bundle* bundle,bool add_front = false);
00356
00361
00362 void set_state(prophet_state_t);
00363 prophet_state_t get_state(const char* where);
00365
00366 ProphetOracle* oracle_;
00367 u_int16_t remote_instance_;
00368 std::string remote_addr_;
00369 u_int16_t local_instance_;
00370 u_int32_t tid_;
00371 u_int32_t timeout_;
00372 u_int32_t ack_count_;
00373 Link* next_hop_;
00374 bool synsender_;
00375 bool initiator_;
00376 bool synsent_;
00377 bool synrcvd_;
00378 bool estab_;
00379 bool dictsent_;
00380 volatile bool neighbor_gone_;
00381 prophet_state_t state_;
00382 ProphetDictionary ribd_;
00383 BundleOfferList offers_;
00384 BundleOfferList requests_;
00385 oasys::MsgQueue<PEMsg> cmdqueue_;
00386 ProphetTable remote_nodes_;
00387 BundleList to_be_fwd_;
00388 Prophet::header_result_t result_;
00389 oasys::Time data_sent_;
00390 oasys::Time data_rcvd_;
00391 ProphetTLV* outbound_tlv_;
00392 oasys::SpinLock* state_lock_;
00393 oasys::SpinLock* otlv_lock_;
00394 };
00395
00396 };
00397
00398 #endif // _DTN_PROPHET_ENCOUNTER_