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
00039 #include <oasys/util/HexDumpBuffer.h>
00040 #include <oasys/util/StringBuffer.h>
00041 #include <oasys/util/OptParser.h>
00042
00043 #include "BundleCommand.h"
00044 #include "CompletionNotifier.h"
00045 #include "bundling/Bundle.h"
00046 #include "bundling/BundleEvent.h"
00047 #include "bundling/BundleDaemon.h"
00048 #include "reg/TclRegistration.h"
00049
00050 namespace dtn {
00051
00052 BundleCommand::BundleCommand()
00053 : TclCommand("bundle")
00054 {
00055 add_to_help("inject <src> <dst> <payload> <opt1=val1> .. <optN=valN>",
00056 "valid options:\n"
00057 " custody_xfer\n"
00058 " receive_rcpt\n"
00059 " custody_rcpt\n"
00060 " forward_rcpt\n"
00061 " delivery_rcpt\n"
00062 " deletion_rcpt\n"
00063 " expiration=integer\n"
00064 " length=integer\n");
00065 add_to_help("stats", "get statistics on the bundles");
00066 add_to_help("daemon_stats", "daemon stats");
00067 add_to_help("reset_stats", "reset currently maintained statistics");
00068 add_to_help("list", "list all of the bundles in the system");
00069 add_to_help("info <id>", "get info on a specific bundle");
00070 add_to_help("dump <id>", "dump a specific bundle");
00071 add_to_help("dump_tcl <id>", "dump a bundle as a tcl list");
00072 add_to_help("dump_ascii <id>", "dump the bundle in ascii");
00073 }
00074
00075 BundleCommand::InjectOpts::InjectOpts()
00076 : custody_xfer_(false),
00077 receive_rcpt_(false),
00078 custody_rcpt_(false),
00079 forward_rcpt_(false),
00080 delivery_rcpt_(false),
00081 deletion_rcpt_(false),
00082 expiration_(60),
00083 length_(0),
00084 replyto_("")
00085 {}
00086
00087 bool
00088 BundleCommand::parse_inject_options(InjectOpts* options,
00089 int objc, Tcl_Obj** objv,
00090 const char** invalidp)
00091 {
00092
00093 if (objc < 6) {
00094 return true;
00095 }
00096
00097 oasys::OptParser p;
00098
00099 p.addopt(new oasys::BoolOpt("custody_xfer", &options->custody_xfer_));
00100 p.addopt(new oasys::BoolOpt("receive_rcpt", &options->receive_rcpt_));
00101 p.addopt(new oasys::BoolOpt("custody_rcpt", &options->custody_rcpt_));
00102 p.addopt(new oasys::BoolOpt("forward_rcpt", &options->forward_rcpt_));
00103 p.addopt(new oasys::BoolOpt("delivery_rcpt", &options->delivery_rcpt_));
00104 p.addopt(new oasys::BoolOpt("deletion_rcpt", &options->deletion_rcpt_));
00105 p.addopt(new oasys::UIntOpt("expiration", &options->expiration_));
00106 p.addopt(new oasys::UIntOpt("length", &options->length_));
00107 p.addopt(new oasys::StringOpt("replyto", &options->replyto_));
00108
00109 for (int i=5; i<objc; i++) {
00110 int len;
00111 const char* option_name = Tcl_GetStringFromObj(objv[i], &len);
00112 if (! p.parse_opt(option_name, len)) {
00113 *invalidp = option_name;
00114 return false;
00115 }
00116 }
00117 return true;
00118 }
00119
00120 int
00121 BundleCommand::exec(int objc, Tcl_Obj** objv, Tcl_Interp* interp)
00122 {
00123
00124 if (objc < 2) {
00125 wrong_num_args(objc, objv, 1, 2, INT_MAX);
00126 return TCL_ERROR;
00127 }
00128
00129 const char* cmd = Tcl_GetStringFromObj(objv[1], 0);
00130
00131 if (strcmp(cmd, "inject") == 0) {
00132
00133 if (objc < 5) {
00134 wrong_num_args(objc, objv, 2, 5, INT_MAX);
00135 return TCL_ERROR;
00136 }
00137
00138 Bundle* b = new Bundle();
00139 b->source_.assign(Tcl_GetStringFromObj(objv[2], 0));
00140 b->replyto_.assign(Tcl_GetStringFromObj(objv[2], 0));
00141 b->custodian_.assign(EndpointID::NULL_EID());
00142 b->dest_.assign(Tcl_GetStringFromObj(objv[3], 0));
00143
00144 int payload_len;
00145 u_char* payload_data = Tcl_GetByteArrayFromObj(objv[4], &payload_len);
00146
00147
00148 InjectOpts options;
00149 const char* invalid;
00150 if (!parse_inject_options(&options, objc, objv, &invalid)) {
00151 resultf("error parsing bundle inject options: invalid option '%s'",
00152 invalid);
00153 return TCL_ERROR;
00154 }
00155
00156 b->custody_requested_ = options.custody_xfer_;
00157 b->receive_rcpt_ = options.receive_rcpt_;
00158 b->custody_rcpt_ = options.custody_rcpt_;
00159 b->forward_rcpt_ = options.forward_rcpt_;
00160 b->delivery_rcpt_ = options.delivery_rcpt_;
00161 b->deletion_rcpt_ = options.deletion_rcpt_;
00162 b->expiration_ = options.expiration_;
00163
00164 if (options.length_ != 0) {
00165
00166
00167 b->payload_.set_length(options.length_);
00168 if (payload_len != 0) {
00169 b->payload_.append_data(payload_data, payload_len);
00170 }
00171
00172
00173
00174
00175 u_char byte = 0;
00176 b->payload_.write_data(&byte, options.length_ - 1, 1);
00177 b->payload_.close_file();
00178
00179 payload_len = options.length_;
00180 } else {
00181
00182 b->payload_.set_data(payload_data, payload_len);
00183 }
00184
00185 if (options.replyto_ != "") {
00186 b->replyto_.assign(options.replyto_.c_str());
00187 }
00188
00189 oasys::StringBuffer error;
00190 if (!b->validate(&error)) {
00191 resultf("bundle validation failed: %s", error.data());
00192 return TCL_ERROR;
00193 }
00194
00195 log_debug("inject %d byte bundle %s->%s", payload_len,
00196 b->source_.c_str(), b->dest_.c_str());
00197
00198 BundleDaemon::post(new BundleReceivedEvent(b, EVENTSRC_APP, payload_len));
00199
00200
00201
00202 resultf("%u.%u", b->creation_ts_.seconds_, b->creation_ts_.seqno_);
00203 return TCL_OK;
00204
00205 } else if (!strcmp(cmd, "stats")) {
00206 oasys::StringBuffer buf("Bundle Statistics: ");
00207 BundleDaemon::instance()->get_bundle_stats(&buf);
00208 set_result(buf.c_str());
00209 return TCL_OK;
00210
00211 } else if (!strcmp(cmd, "daemon_stats")) {
00212 oasys::StringBuffer buf("Bundle Daemon Statistics: ");
00213 BundleDaemon::instance()->get_daemon_stats(&buf);
00214 set_result(buf.c_str());
00215 return TCL_OK;
00216 } else if (!strcmp(cmd, "daemon_status")) {
00217 BundleDaemon::post_and_wait(new StatusRequest(),
00218 CompletionNotifier::notifier());
00219 set_result("DTN daemon ok");
00220 return TCL_OK;
00221 } else if (!strcmp(cmd, "reset_stats")) {
00222 BundleDaemon::instance()->reset_stats();
00223 return TCL_OK;
00224
00225 } else if (!strcmp(cmd, "list")) {
00226 Bundle* b;
00227 BundleList::const_iterator iter;
00228 oasys::StringBuffer buf;
00229 BundleList* pending =
00230 BundleDaemon::instance()->pending_bundles();
00231
00232 oasys::ScopeLock l(pending->lock(), "BundleCommand::exec");
00233 buf.appendf("Currently Pending Bundles (%zu): \n", pending->size());
00234
00235 for (iter = pending->begin(); iter != pending->end(); ++iter) {
00236 b = *iter;
00237 buf.appendf("\t%-3d: %s -> %s length %zu\n",
00238 b->bundleid_,
00239 b->source_.c_str(),
00240 b->dest_.c_str(),
00241 b->payload_.length());
00242 }
00243
00244 set_result(buf.c_str());
00245
00246 return TCL_OK;
00247
00248 } else if (!strcmp(cmd, "info") ||
00249 !strcmp(cmd, "dump") ||
00250 !strcmp(cmd, "dump_tcl") ||
00251 !strcmp(cmd, "dump_ascii"))
00252 {
00253
00254 if (objc != 3) {
00255 wrong_num_args(objc, objv, 2, 3, 3);
00256 return TCL_ERROR;
00257 }
00258
00259 int bundleid;
00260 if (Tcl_GetIntFromObj(interp, objv[2], &bundleid) != TCL_OK) {
00261 resultf("invalid bundle id %s",
00262 Tcl_GetStringFromObj(objv[2], 0));
00263 return TCL_ERROR;
00264 }
00265
00266 BundleList* pending =
00267 BundleDaemon::instance()->pending_bundles();
00268
00269 BundleRef bundle = pending->find(bundleid);
00270
00271 if (bundle == NULL) {
00272 resultf("no bundle with id %d", bundleid);
00273 return TCL_ERROR;
00274 }
00275
00276 if (strcmp(cmd, "info") == 0) {
00277 oasys::StringBuffer buf;
00278 bundle->format_verbose(&buf);
00279 buf.append("\n");
00280 bundle->fwdlog_.dump(&buf);
00281 set_result(buf.c_str());
00282
00283 } else if (strcmp(cmd, "dump_tcl") == 0) {
00284 Tcl_Obj* result = NULL;
00285 int ok =
00286 TclRegistration::parse_bundle_data(interp, bundle, &result);
00287
00288 set_objresult(result);
00289 return ok;
00290
00291 } else {
00292 size_t len = bundle->payload_.length();
00293 oasys::HexDumpBuffer buf(len);
00294 const u_char* bp =
00295 bundle->payload_.read_data(0, len, (u_char*)buf.data());
00296
00297
00298 buf.append((const char*)bp, len);
00299 if (!strcmp(cmd, "dump")) {
00300 buf.hexify();
00301 }
00302 set_result(buf.c_str());
00303 }
00304
00305 return TCL_OK;
00306
00307 } else {
00308 resultf("unknown bundle subcommand %s", cmd);
00309 return TCL_ERROR;
00310 }
00311 }
00312
00313
00314 }