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 "Registration.h"
00022 #include "bundling/Bundle.h"
00023 #include "bundling/BundleDaemon.h"
00024 #include "bundling/BundleList.h"
00025 #include "session/Session.h"
00026 #include "storage/GlobalStore.h"
00027
00028 namespace dtn {
00029
00030
00031 const char*
00032 Registration::failure_action_toa(failure_action_t action)
00033 {
00034 switch(action) {
00035 case DROP: return "DROP";
00036 case DEFER: return "DEFER";
00037 case EXEC: return "EXEC";
00038 }
00039
00040 return "__INVALID__";
00041 }
00042
00043
00044 Registration::Registration(u_int32_t regid,
00045 const EndpointIDPattern& endpoint,
00046 u_int32_t failure_action,
00047 u_int32_t session_flags,
00048 u_int32_t expiration,
00049 const std::string& script)
00050
00051 : Logger("Registration", "/dtn/registration/%d", regid),
00052 regid_(regid),
00053 endpoint_(endpoint),
00054 failure_action_(failure_action),
00055 session_flags_(session_flags),
00056 script_(script),
00057 expiration_(expiration),
00058 expiration_timer_(NULL),
00059 active_(false),
00060 expired_(false),
00061 delivery_cache_(std::string(logpath()) + "/delivery_cache", 1024)
00062 {
00063 struct timeval now;
00064 ::gettimeofday(&now, 0);
00065 creation_time_ = now.tv_sec;
00066
00067 init_expiration_timer();
00068 }
00069
00070
00071 Registration::Registration(const oasys::Builder&)
00072 : Logger("Registration", "/dtn/registration"),
00073 regid_(0),
00074 endpoint_(),
00075 failure_action_(DEFER),
00076 script_(),
00077 expiration_(0),
00078 creation_time_(0),
00079 expiration_timer_(NULL),
00080 active_(false),
00081 expired_(false),
00082 delivery_cache_(std::string(logpath()) + "/delivery_cache", 1024)
00083 {
00084 }
00085
00086
00087 Registration::~Registration()
00088 {
00089 cleanup_expiration_timer();
00090 }
00091
00092
00093 bool
00094 Registration::deliver_if_not_duplicate(Bundle* bundle)
00095 {
00096 if (! delivery_cache_.add_entry(bundle, EndpointID::NULL_EID())) {
00097 log_debug("suppressing duplicate delivery of bundle *%p", bundle);
00098 return false;
00099 }
00100
00101 log_debug("delivering bundle *%p", bundle);
00102 deliver_bundle(bundle);
00103 return true;
00104 }
00105
00106
00107 void
00108 Registration::session_notify(Bundle* bundle)
00109 {
00110 (void)bundle;
00111 PANIC("generic session_notify implementation should never be called");
00112 }
00113
00114
00115 void
00116 Registration::force_expire()
00117 {
00118 ASSERT(active_);
00119
00120 cleanup_expiration_timer();
00121 set_expired(true);
00122 }
00123
00124
00125 void
00126 Registration::cleanup_expiration_timer()
00127 {
00128 if (expiration_timer_) {
00129
00130
00131
00132
00133 bool pending = expiration_timer_->cancel();
00134
00135 if (! pending) {
00136 ASSERT(expired_);
00137 delete expiration_timer_;
00138 }
00139
00140 expiration_timer_ = NULL;
00141 }
00142 }
00143
00144
00145 void
00146 Registration::serialize(oasys::SerializeAction* a)
00147 {
00148 a->process("endpoint", &endpoint_);
00149 a->process("regid", ®id_);
00150 a->process("failure_action", &failure_action_);
00151 a->process("session_flags", &session_flags_);
00152 a->process("script", &script_);
00153 a->process("creation_time", &creation_time_);
00154 a->process("expiration", &expiration_);
00155
00156
00157 if (a->action_code() == oasys::Serialize::UNMARSHAL) {
00158 init_expiration_timer();
00159 }
00160
00161 logpathf("/dtn/registration/%d", regid_);
00162 }
00163
00164
00165 int
00166 Registration::format(char* buf, size_t sz) const
00167 {
00168 return snprintf(buf, sz,
00169 "id %u: %s %s (%s%s) [expiration %d%s%s%s%s]",
00170 regid(),
00171 active() ? "active" : "passive",
00172 endpoint().c_str(),
00173 failure_action_toa(failure_action()),
00174 failure_action() == Registration::EXEC ?
00175 script().c_str() : "",
00176 expiration(),
00177 session_flags() != 0 ? " session:" : "",
00178 (session_flags() & Session::CUSTODY) ? " custody" : "",
00179 (session_flags() & Session::PUBLISH) ? " publish" : "",
00180 (session_flags() & Session::SUBSCRIBE) ? " subscribe" : ""
00181 );
00182 }
00183
00184
00185 void
00186 Registration::init_expiration_timer()
00187 {
00188 if (expiration_ != 0) {
00189 struct timeval when, now;
00190 when.tv_sec = creation_time_ + expiration_;
00191 when.tv_usec = 0;
00192
00193 ::gettimeofday(&now, 0);
00194
00195 long int in_how_long = TIMEVAL_DIFF_MSEC(when, now);
00196 if (in_how_long < 0) {
00197 log_warn("scheduling IMMEDIATE expiration for registration id %d: "
00198 "[creation_time %u, expiration %u, now %u]",
00199 regid_, creation_time_, expiration_, (u_int)now.tv_sec);
00200 } else {
00201 log_debug("scheduling expiration for registration id %d at %u.%u "
00202 "(in %ld seconds): ", regid_,
00203 (u_int)when.tv_sec, (u_int)when.tv_usec,
00204 in_how_long / 1000);
00205 }
00206
00207 expiration_timer_ = new ExpirationTimer(this);
00208 expiration_timer_->schedule_at(&when);
00209
00210 } else {
00211 set_expired(true);
00212 }
00213 }
00214
00215
00216 void
00217 Registration::ExpirationTimer::timeout(const struct timeval& now)
00218 {
00219 (void)now;
00220
00221 reg_->set_expired(true);
00222
00223 if (! reg_->active()) {
00224 BundleDaemon::post(new RegistrationExpiredEvent(reg_));
00225 }
00226 }
00227
00228 }