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