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 <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <unistd.h>
00024
00025 #include <oasys/storage/BerkeleyDBStore.h>
00026 #include <oasys/io/FileUtils.h>
00027
00028 #include "DTNServer.h"
00029
00030 #include "bundling/BundleDaemon.h"
00031
00032 #include "contacts/InterfaceTable.h"
00033 #include "contacts/ContactManager.h"
00034
00035 #include "cmd/CompletionNotifier.h"
00036 #include "cmd/BundleCommand.h"
00037 #include "cmd/InterfaceCommand.h"
00038 #include "cmd/LinkCommand.h"
00039 #include "cmd/ParamCommand.h"
00040 #include "cmd/RegistrationCommand.h"
00041 #include "cmd/RouteCommand.h"
00042 #include "cmd/DiscoveryCommand.h"
00043 #include "cmd/ProphetCommand.h"
00044 #include "cmd/ShutdownCommand.h"
00045 #include "cmd/StorageCommand.h"
00046 #include "cmd/ECLACommand.h"
00047 #include "cmd/SecurityCommand.h"
00048
00049 #include "conv_layers/ConvergenceLayer.h"
00050 #include "discovery/DiscoveryTable.h"
00051
00052 #include "naming/SchemeTable.h"
00053
00054 #include "reg/AdminRegistration.h"
00055 #include "reg/RegistrationTable.h"
00056
00057 #include "routing/BundleRouter.h"
00058
00059 #include "storage/BundleStore.h"
00060 #include "storage/ProphetStore.h"
00061 #include "storage/LinkStore.h"
00062 #include "storage/GlobalStore.h"
00063 #include "storage/RegistrationStore.h"
00064 #include "storage/DTNStorageConfig.h"
00065
00066
00067
00068
00069 namespace dtn {
00070
00071 DTNServer::DTNServer(const char* logpath,
00072 DTNStorageConfig* storage_config)
00073 : Logger("DTNServer", logpath),
00074 init_(false),
00075 in_shutdown_(0),
00076 storage_config_(storage_config),
00077 store_(0)
00078 {}
00079
00080 DTNServer::~DTNServer()
00081 {
00082 log_notice("daemon exiting...");
00083 }
00084
00085 void
00086 DTNServer::init()
00087 {
00088 ASSERT(oasys::Thread::start_barrier_enabled());
00089
00090 init_commands();
00091 init_components();
00092 }
00093
00094 void
00095 DTNServer::start()
00096 {
00097 BundleDaemon* daemon = BundleDaemon::instance();
00098 daemon->start();
00099 log_debug("started dtn server");
00100 }
00101
00102 bool
00103 DTNServer::init_datastore()
00104 {
00105 if (storage_config_->tidy_)
00106 {
00107 storage_config_->init_ = true;
00108 }
00109 store_ = new oasys::DurableStore("/dtn/storage");
00110 int err = store_->create_store(*storage_config_);
00111 if (err != 0) {
00112 log_crit("error creating storage system");
00113 return false;
00114 }
00115
00116 if (storage_config_->tidy_)
00117 {
00118
00119
00120 if (!tidy_dir(storage_config_->payload_dir_.c_str())) {
00121 return false;
00122 }
00123 }
00124
00125 if (storage_config_->init_)
00126 {
00127 if (!init_dir(storage_config_->payload_dir_.c_str())) {
00128 return false;
00129 }
00130 }
00131
00132 if (!validate_dir(storage_config_->payload_dir_.c_str())) {
00133 return false;
00134 }
00135
00136 if ((GlobalStore::init(*storage_config_, store_) != 0) ||
00137 (BundleStore::init(*storage_config_, store_) != 0) ||
00138 (ProphetStore::init(*storage_config_, store_) != 0) ||
00139 (LinkStore::init(*storage_config_, store_) != 0) ||
00140 (RegistrationStore::init(*storage_config_, store_) != 0))
00141 {
00142 log_crit("error initializing data store");
00143 return false;
00144 }
00145
00146
00147
00148 if (!GlobalStore::instance()->load()) {
00149 return false;
00150 }
00151
00152 return true;
00153 }
00154
00155 bool
00156 DTNServer::parse_conf_file(std::string& conf_file,
00157 bool conf_file_set)
00158 {
00159
00160
00161 if (conf_file.size() != 0)
00162 {
00163 if (!oasys::FileUtils::readable(conf_file.c_str(), logpath()))
00164 {
00165 log_err("configuration file \"%s\" not readable",
00166 conf_file.c_str());
00167 return false;
00168 }
00169 }
00170 else if (!conf_file_set)
00171 {
00172 const char* default_conf[] = { INSTALL_SYSCONFDIR "/dtn.conf",
00173 "daemon/dtn.conf",
00174 0 };
00175 conf_file.clear();
00176 for (int i=0; default_conf[i] != 0; ++i)
00177 {
00178 if (oasys::FileUtils::readable(default_conf[i], logpath()))
00179 {
00180 conf_file.assign(default_conf[i]);
00181 break;
00182 }
00183 }
00184 if (conf_file.size() == 0)
00185 {
00186 log_warn("can't read default config file "
00187 "(tried " INSTALL_SYSCONFDIR "/dtn.conf "
00188 "and daemon/dtn.conf)...");
00189 }
00190 }
00191
00192 if (conf_file.size() == 0) {
00193 log_info("No config file specified.");
00194 return false;
00195 }
00196
00197 log_info("parsing configuration file %s...", conf_file.c_str());
00198 if (oasys::TclCommandInterp::instance()->exec_file(conf_file.c_str()) != 0)
00199 {
00200 return false;
00201 }
00202
00203 return true;
00204 }
00205
00206 void
00207 DTNServer::init_commands()
00208 {
00209 oasys::TclCommandInterp* interp = oasys::TclCommandInterp::instance();
00210
00211 CompletionNotifier::create();
00212 interp->reg(new BundleCommand());
00213 interp->reg(new InterfaceCommand());
00214 interp->reg(new LinkCommand());
00215 interp->reg(new ParamCommand());
00216 interp->reg(new RegistrationCommand());
00217 interp->reg(new RouteCommand());
00218 interp->reg(new DiscoveryCommand());
00219 interp->reg(new ProphetCommand());
00220 interp->reg(new ShutdownCommand(this, "shutdown"));
00221 interp->reg(new ShutdownCommand(this, "quit"));
00222 interp->reg(new StorageCommand(storage_config_));
00223
00224 #if defined(XERCES_C_ENABLED) && defined(EXTERNAL_CL_ENABLED)
00225 interp->reg(new ECLACommand());
00226 #endif
00227
00228 #ifdef BSP_ENABLED
00229 interp->reg(new SecurityCommand());
00230 #endif
00231
00232 log_debug("registered dtn commands");
00233 }
00234
00235 void
00236 DTNServer::init_components()
00237 {
00238 SchemeTable::create();
00239 ConvergenceLayer::init_clayers();
00240 InterfaceTable::init();
00241 BundleDaemon::init();
00242 DiscoveryTable::init();
00243
00244 log_debug("intialized dtn components");
00245 }
00246
00247 void
00248 DTNServer::close_datastore()
00249 {
00250 log_notice("closing persistent data store");
00251
00252 RegistrationStore::instance()->close();
00253 LinkStore::instance()->close();
00254 ProphetStore::instance()->close();
00255 BundleStore::instance()->close();
00256 GlobalStore::instance()->close();
00257
00258 delete_z(store_);
00259 }
00260
00261 void
00262 DTNServer::shutdown()
00263 {
00264 log_notice("shutting down dtn server");
00265
00266
00267 u_int32_t old_val = atomic_incr_ret(&in_shutdown_);
00268 if (old_val != 1) {
00269 log_warn("second thread called DTNServer::shutdown... spinning forever");
00270 while (1) {
00271 sleep(1000000);
00272 }
00273 }
00274
00275 oasys::Notifier done("/dtnserver/shutdown");
00276 log_info("DTNServer shutdown called, posting shutdown request to daemon");
00277 BundleDaemon::instance()->post_and_wait(new ShutdownRequest(), &done);
00278
00279 DiscoveryTable::instance()->shutdown();
00280 close_datastore();
00281 }
00282
00283 void
00284 DTNServer::set_app_shutdown(ShutdownProc proc, void* data)
00285 {
00286 BundleDaemon::instance()->set_app_shutdown(proc, data);
00287 }
00288
00289 bool
00290 DTNServer::init_dir(const char* dirname)
00291 {
00292 struct stat st;
00293 int statret;
00294
00295 statret = stat(dirname, &st);
00296 if (statret == -1 && errno == ENOENT)
00297 {
00298 if (mkdir(dirname, 0700) != 0) {
00299 log_crit("can't create directory %s: %s",
00300 dirname, strerror(errno));
00301 return false;
00302 }
00303 }
00304 else if (statret == -1)
00305 {
00306 log_crit("invalid path %s: %s", dirname, strerror(errno));
00307 return false;
00308 }
00309
00310 return true;
00311 }
00312
00313 bool
00314 DTNServer::tidy_dir(const char* dir)
00315 {
00316 char cmd[256];
00317 struct stat st;
00318
00319 std::string dirname(dir);
00320 oasys::FileUtils::abspath(&dirname);
00321
00322 if (stat(dirname.c_str(), &st) == 0)
00323 {
00324 snprintf(cmd, sizeof(cmd), "/bin/rm -rf %s", dirname.c_str());
00325 log_notice("tidy option removing directory '%s'", cmd);
00326
00327 if (system(cmd))
00328 {
00329 log_crit("error removing directory %s", dirname.c_str());
00330 return false;
00331 }
00332
00333 }
00334 else if (errno == ENOENT)
00335 {
00336 log_debug("directory already removed %s", dirname.c_str());
00337 }
00338 else
00339 {
00340 log_crit("invalid directory name %s: %s", dirname.c_str(), strerror(errno));
00341 return false;
00342 }
00343
00344 return true;
00345 }
00346
00347 bool
00348 DTNServer::validate_dir(const char* dirname)
00349 {
00350 struct stat st;
00351
00352 if (stat(dirname, &st) == 0 && S_ISDIR(st.st_mode))
00353 {
00354 log_debug("directory validated: %s", dirname);
00355 }
00356 else
00357 {
00358 log_crit("invalid directory name %s: %s", dirname, strerror(errno));
00359 return false;
00360 }
00361
00362 if (access(dirname, R_OK | W_OK | X_OK) == 0)
00363 {
00364 log_debug("directory access validated: %s", dirname);
00365 }
00366 else
00367 {
00368 log_crit("access failed on directory %s: %s",
00369 dirname, strerror(errno));
00370 return false;
00371 }
00372
00373 return true;
00374 }
00375
00376 }