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 <errno.h>
00022 #include <oasys/debug/Log.h>
00023 #include <oasys/io/FileUtils.h>
00024 #include <oasys/io/NetUtils.h>
00025 #include <oasys/tclcmd/ConsoleCommand.h>
00026 #include <oasys/tclcmd/TclCommand.h>
00027 #include <oasys/util/Getopt.h>
00028 #include <oasys/util/OptParser.h>
00029
00030 #include <dtn_api.h>
00031 #include <dtn_ipc.h>
00032 #include <APIEndpointIDOpt.h>
00033
00034 typedef std::map<int, dtn_handle_t> HandleMap;
00035
00036 struct State : public oasys::Singleton<State> {
00037 State() : handle_num_(0) {}
00038
00039 HandleMap handles_;
00040 int handle_num_;
00041 };
00042
00043 template <> State* oasys::Singleton<State>::instance_ = 0;
00044
00045 extern int dtnipc_version;
00046
00047
00048 class DTNOpenCommand : public oasys::TclCommand {
00049 public:
00050 oasys::OptParser parser_;
00051
00052 struct OpenOpts {
00053 u_int16_t version_;
00054 };
00055
00056 OpenOpts opts_;
00057
00058 void init_opts() {
00059 opts_.version_ = DTN_IPC_VERSION;
00060 }
00061
00062 DTNOpenCommand() : TclCommand("dtn_open") {
00063 parser_.addopt(new oasys::UInt16Opt("version", &opts_.version_));
00064 }
00065
00066 int exec(int argc, const char **argv, Tcl_Interp* interp)
00067 {
00068 (void)argc;
00069 (void)argv;
00070 (void)interp;
00071
00072 if (argc < 1 || argc > 2) {
00073 wrong_num_args(argc, argv, 1, 1, 2);
00074 return TCL_ERROR;
00075 }
00076
00077 init_opts();
00078
00079 const char* invalid = 0;
00080 if (! parser_.parse(argc - 1, argv + 1, &invalid)) {
00081 resultf("invalid option '%s'", invalid);
00082 return TCL_ERROR;
00083 }
00084
00085 dtnipc_version = opts_.version_;
00086 dtn_handle_t handle;
00087 int err = dtn_open(&handle);
00088 if (err != DTN_SUCCESS) {
00089 resultf("can't connect to dtn daemon: %s",
00090 dtn_strerror(err));
00091 return TCL_ERROR;
00092 }
00093
00094 int n = State::instance()->handle_num_++;
00095 State::instance()->handles_[n] = handle;
00096
00097 resultf("%d", n);
00098 return TCL_OK;
00099 }
00100 };
00101
00102
00103 class DTNCloseCommand : public oasys::TclCommand {
00104 public:
00105 DTNCloseCommand() : TclCommand("dtn_close") {}
00106 int exec(int argc, const char **argv, Tcl_Interp* interp)
00107 {
00108 (void)argc;
00109 (void)argv;
00110 (void)interp;
00111
00112 if (argc != 2) {
00113 wrong_num_args(argc, argv, 1, 2, 2);
00114 return TCL_ERROR;
00115 }
00116
00117 int n = atoi(argv[1]);
00118 HandleMap::iterator iter = State::instance()->handles_.find(n);
00119 if (iter == State::instance()->handles_.end()) {
00120 resultf("invalid dtn handle %d", n);
00121 return TCL_ERROR;
00122 }
00123
00124 dtn_handle_t h = iter->second;
00125 dtn_close(h);
00126
00127 return TCL_OK;
00128 }
00129 };
00130
00131
00132 oasys::EnumOpt::Case FailureActionCases[] = {
00133 {"drop", DTN_REG_DROP},
00134 {"defer", DTN_REG_DEFER},
00135 {"exec", DTN_REG_EXEC},
00136 {0, 0}
00137 };
00138
00139
00140 oasys::BitFlagOpt::Case SessionFlagCases[] = {
00141 {"subscribe", DTN_SESSION_SUBSCRIBE},
00142 {"publish", DTN_SESSION_PUBLISH},
00143 {"custody", DTN_SESSION_CUSTODY},
00144 {0, 0}
00145 };
00146
00147 class DTNRegisterCommand : public oasys::TclCommand {
00148 public:
00149 oasys::OptParser parser_;
00150
00151 struct RegistrationOpts {
00152 dtn_endpoint_id_t endpoint_;
00153 int failure_action_;
00154 int session_flags_;
00155 u_int expiration_;
00156 std::string script_;
00157 bool init_passive_;
00158 };
00159
00160 RegistrationOpts opts_;
00161
00162 void init_opts() {
00163 memset(&opts_.endpoint_, 0, sizeof(opts_.endpoint_));
00164 opts_.failure_action_ = DTN_REG_DROP;
00165 opts_.session_flags_ = 0;
00166 opts_.expiration_ = 0xffffffff;
00167 opts_.script_ = "";
00168 opts_.init_passive_ = false;
00169 }
00170
00171 DTNRegisterCommand() : TclCommand("dtn_register")
00172 {
00173 parser_.addopt(new dtn::APIEndpointIDOpt("endpoint", &opts_.endpoint_));
00174 parser_.addopt(new oasys::EnumOpt("failure_action",
00175 FailureActionCases,
00176 &opts_.failure_action_));
00177 parser_.addopt(new oasys::BitFlagOpt("session_flags",
00178 SessionFlagCases,
00179 &opts_.session_flags_));
00180 parser_.addopt(new oasys::UIntOpt("expiration", &opts_.expiration_));
00181 parser_.addopt(new oasys::StringOpt("script", &opts_.script_));
00182 parser_.addopt(new oasys::BoolOpt("init_passive",
00183 &opts_.init_passive_));
00184 }
00185
00186 int exec(int argc, const char **argv, Tcl_Interp* interp)
00187 {
00188 (void)argc;
00189 (void)argv;
00190 (void)interp;
00191
00192
00193 if (argc < 4) {
00194 wrong_num_args(argc, argv, 1, 4, INT_MAX);
00195 return TCL_ERROR;
00196 }
00197
00198 int n = atoi(argv[1]);
00199 HandleMap::iterator iter = State::instance()->handles_.find(n);
00200 if (iter == State::instance()->handles_.end()) {
00201 resultf("invalid dtn handle %d", n);
00202 return TCL_ERROR;
00203 }
00204
00205 dtn_handle_t h = iter->second;
00206
00207 init_opts();
00208 const char* invalid = 0;
00209 if (! parser_.parse(argc - 2, argv + 2, &invalid)) {
00210 resultf("invalid option '%s'", invalid);
00211 return TCL_ERROR;
00212 }
00213
00214 if (opts_.endpoint_.uri[0] == 0) {
00215 resultf("must set endpoint id");
00216 return TCL_ERROR;
00217 }
00218
00219 if (opts_.expiration_ == 0xffffffff) {
00220 resultf("must set expiration");
00221 return TCL_ERROR;
00222 }
00223
00224 dtn_reg_info_t reginfo;
00225 memset(®info, 0, sizeof(reginfo));
00226
00227 dtn_copy_eid(®info.endpoint, &opts_.endpoint_);
00228 reginfo.flags = opts_.failure_action_ | opts_.session_flags_;
00229 reginfo.expiration = opts_.expiration_;
00230 reginfo.script.script_len = opts_.script_.length();
00231 reginfo.script.script_val = (char*)opts_.script_.c_str();
00232 reginfo.init_passive = opts_.init_passive_;
00233
00234 dtn_reg_id_t regid = 0;
00235
00236 int ret = dtn_register(h, ®info, ®id);
00237 if (ret != DTN_SUCCESS) {
00238 resultf("error in dtn_register: %s",
00239 dtn_strerror(dtn_errno(h)));
00240 return TCL_ERROR;
00241 }
00242
00243 resultf("%u", regid);
00244 return TCL_OK;
00245 }
00246 };
00247
00248
00249 class DTNUnregisterCommand : public oasys::TclCommand {
00250 public:
00251 DTNUnregisterCommand() : TclCommand("dtn_unregister") {}
00252 int exec(int argc, const char **argv, Tcl_Interp* interp)
00253 {
00254 (void)interp;
00255
00256 if (argc != 3) {
00257 wrong_num_args(argc, argv, 1, 3, 3);
00258 return TCL_ERROR;
00259 }
00260
00261 int n = atoi(argv[1]);
00262 HandleMap::iterator iter = State::instance()->handles_.find(n);
00263 if (iter == State::instance()->handles_.end()) {
00264 resultf("invalid dtn handle %d", n);
00265 return TCL_ERROR;
00266 }
00267
00268 dtn_handle_t h = iter->second;
00269
00270 dtn_reg_id_t regid = atoi(argv[2]);
00271
00272 int err = dtn_unregister(h, regid);
00273 if (err != DTN_SUCCESS) {
00274 resultf("error in dtn_unregister: %s",
00275 dtn_strerror(dtn_errno(h)));
00276 return TCL_ERROR;
00277 }
00278
00279 return TCL_OK;
00280 }
00281 };
00282
00283
00284 oasys::EnumOpt::Case PriorityCases[] = {
00285 {"bulk", COS_BULK},
00286 {"normal", COS_NORMAL},
00287 {"expedited", COS_EXPEDITED},
00288 {0, 0}
00289 };
00290
00291 class DTNSendCommand : public oasys::TclCommand {
00292 public:
00293 struct SendOpts {
00294 int regid_;
00295 dtn_endpoint_id_t source_;
00296 dtn_endpoint_id_t dest_;
00297 dtn_endpoint_id_t replyto_;
00298 int priority_;
00299 bool custody_xfer_;
00300 bool receive_rcpt_;
00301 bool custody_rcpt_;
00302 bool forward_rcpt_;
00303 bool delivery_rcpt_;
00304 bool deletion_rcpt_;
00305 u_int expiration_;
00306 std::string sequence_id_;
00307 std::string obsoletes_id_;
00308 char payload_data_[DTN_MAX_BUNDLE_MEM];
00309 size_t payload_data_len_;
00310 char payload_file_[DTN_MAX_PATH_LEN];
00311 size_t payload_file_len_;
00312 u_int block_type_;
00313 u_int block_flags_;
00314 char block_content_[DTN_MAX_BLOCK_LEN];
00315 size_t block_content_len_;
00316 };
00317
00318
00319
00320 oasys::OptParser parser_;
00321 SendOpts opts_;
00322
00323 void init_opts()
00324 {
00325 opts_.regid_ = DTN_REGID_NONE;
00326
00327 memset(&opts_.source_, 0, sizeof(opts_.source_));
00328 memset(&opts_.dest_, 0, sizeof(opts_.dest_));
00329 memset(&opts_.replyto_, 0, sizeof(opts_.replyto_));
00330
00331 opts_.priority_ = COS_NORMAL;
00332 opts_.custody_xfer_ = 0;
00333 opts_.receive_rcpt_ = 0;
00334 opts_.custody_rcpt_ = 0;
00335 opts_.forward_rcpt_ = 0;
00336 opts_.delivery_rcpt_ = 0;
00337 opts_.deletion_rcpt_ = 0;
00338 opts_.expiration_ = 5 * 60;
00339 opts_.sequence_id_ = "";
00340 opts_.obsoletes_id_ = "";
00341
00342 memset(&opts_.payload_data_, 0, sizeof(opts_.payload_data_));
00343 opts_.payload_data_len_ = 0;
00344 memset(&opts_.payload_file_, 0, sizeof(opts_.payload_file_));
00345 opts_.payload_file_len_ = 0;
00346
00347 opts_.block_type_ = 0;
00348 opts_.block_flags_ = 0;
00349 memset(&opts_.block_content_, 0, sizeof(opts_.block_content_));
00350 opts_.block_content_len_ = 0;
00351 }
00352
00353 DTNSendCommand() : TclCommand("dtn_send")
00354 {
00355 parser_.addopt(new oasys::IntOpt("regid", &opts_.regid_));
00356 parser_.addopt(new dtn::APIEndpointIDOpt("source", &opts_.source_));
00357 parser_.addopt(new dtn::APIEndpointIDOpt("dest", &opts_.dest_));
00358 parser_.addopt(new dtn::APIEndpointIDOpt("replyto", &opts_.replyto_));
00359 parser_.addopt(new oasys::EnumOpt("priority", PriorityCases,
00360 &opts_.priority_));
00361 parser_.addopt(new oasys::BoolOpt("custody_xfer",
00362 &opts_.custody_xfer_));
00363 parser_.addopt(new oasys::BoolOpt("receive_rcpt",
00364 &opts_.receive_rcpt_));
00365 parser_.addopt(new oasys::BoolOpt("custody_rcpt",
00366 &opts_.custody_rcpt_));
00367 parser_.addopt(new oasys::BoolOpt("forward_rcpt",
00368 &opts_.forward_rcpt_));
00369 parser_.addopt(new oasys::BoolOpt("delivery_rcpt",
00370 &opts_.delivery_rcpt_));
00371 parser_.addopt(new oasys::BoolOpt("deletion_rcpt",
00372 &opts_.deletion_rcpt_));
00373 parser_.addopt(new oasys::UIntOpt("expiration",
00374 &opts_.expiration_));
00375 parser_.addopt(new oasys::StringOpt("sequence_id",
00376 &opts_.sequence_id_));
00377 parser_.addopt(new oasys::StringOpt("obsoletes_id",
00378 &opts_.obsoletes_id_));
00379 parser_.addopt(new oasys::CharBufOpt("payload_data",
00380 opts_.payload_data_,
00381 &opts_.payload_data_len_,
00382 sizeof(opts_.payload_data_)));
00383 parser_.addopt(new oasys::CharBufOpt("payload_file",
00384 opts_.payload_file_,
00385 &opts_.payload_file_len_,
00386 sizeof(opts_.payload_file_)));
00387 parser_.addopt(new oasys::UIntOpt("block_type", &opts_.block_type_));
00388 parser_.addopt(new oasys::UIntOpt("block_flags", &opts_.block_flags_));
00389 parser_.addopt(new oasys::CharBufOpt("block_content",
00390 opts_.block_content_,
00391 &opts_.block_content_len_,
00392 sizeof(opts_.block_content_)));
00393 }
00394
00395 int exec(int argc, const char **argv, Tcl_Interp* interp)
00396 {
00397 (void)argc;
00398 (void)argv;
00399 (void)interp;
00400
00401
00402 if (argc < 5) {
00403 wrong_num_args(argc, argv, 1, 5, INT_MAX);
00404 return TCL_ERROR;
00405 }
00406
00407 int n = atoi(argv[1]);
00408 HandleMap::iterator iter = State::instance()->handles_.find(n);
00409 if (iter == State::instance()->handles_.end()) {
00410 resultf("invalid dtn handle %d", n);
00411 return TCL_ERROR;
00412 }
00413
00414 dtn_handle_t h = iter->second;
00415
00416
00417 init_opts();
00418 const char* invalid = 0;
00419 if (! parser_.parse(argc - 2, argv + 2, &invalid)) {
00420 resultf("invalid option '%s'", invalid);
00421 return TCL_ERROR;
00422 }
00423
00424
00425 if (opts_.source_.uri[0] == 0) {
00426 resultf("must set source endpoint id");
00427 return TCL_ERROR;
00428 }
00429 if (opts_.dest_.uri[0] == 0) {
00430 resultf("must set dest endpoint id");
00431 return TCL_ERROR;
00432 }
00433 if (opts_.payload_data_len_ == 0 && opts_.payload_file_len_ == 0) {
00434 resultf("must set payload");
00435 return TCL_ERROR;
00436 }
00437
00438 dtn_bundle_spec_t spec;
00439 memset(&spec, 0, sizeof(spec));
00440 dtn_copy_eid(&spec.source, &opts_.source_);
00441 dtn_copy_eid(&spec.dest, &opts_.dest_);
00442 if (opts_.replyto_.uri[0] != 0) {
00443 dtn_copy_eid(&spec.replyto, &opts_.replyto_);
00444 }
00445 spec.priority = (dtn_bundle_priority_t)opts_.priority_;
00446 if (opts_.custody_xfer_) spec.dopts |= DOPTS_CUSTODY;
00447 if (opts_.receive_rcpt_) spec.dopts |= DOPTS_RECEIVE_RCPT;
00448 if (opts_.custody_rcpt_) spec.dopts |= DOPTS_CUSTODY_RCPT;
00449 if (opts_.forward_rcpt_) spec.dopts |= DOPTS_FORWARD_RCPT;
00450 if (opts_.delivery_rcpt_) spec.dopts |= DOPTS_DELIVERY_RCPT;
00451 if (opts_.deletion_rcpt_) spec.dopts |= DOPTS_DELETE_RCPT;
00452 spec.expiration = opts_.expiration_;
00453
00454 if (opts_.sequence_id_ != "") {
00455 spec.sequence_id.data.data_val = const_cast<char*>(opts_.sequence_id_.c_str());
00456 spec.sequence_id.data.data_len = opts_.sequence_id_.length();
00457 }
00458
00459 if (opts_.obsoletes_id_ != "") {
00460 spec.obsoletes_id.data.data_val = const_cast<char*>(opts_.obsoletes_id_.c_str());
00461 spec.obsoletes_id.data.data_len = opts_.obsoletes_id_.length();
00462 }
00463
00464 dtn_bundle_payload_t payload;
00465 memset(&payload, 0, sizeof(payload));
00466 if (opts_.payload_data_len_ != 0) {
00467 dtn_set_payload(&payload, DTN_PAYLOAD_MEM,
00468 opts_.payload_data_, opts_.payload_data_len_);
00469 } else {
00470 dtn_set_payload(&payload, DTN_PAYLOAD_FILE,
00471 opts_.payload_file_, opts_.payload_file_len_);
00472
00473 }
00474
00475 dtn_extension_block_t block;
00476 memset(&block, 0, sizeof(block));
00477 if (opts_.block_type_ > 0 && opts_.block_type_ < 255) {
00478 block.type = opts_.block_type_;
00479 if (opts_.block_flags_ < 255) {
00480 block.flags = opts_.block_flags_;
00481 }
00482 block.data.data_len = opts_.block_content_len_;
00483 block.data.data_val = opts_.block_content_;
00484
00485 spec.blocks.blocks_len = 1;
00486 spec.blocks.blocks_val = █
00487 }
00488
00489 dtn_bundle_id_t id;
00490 memset(&id, 0, sizeof(id));
00491
00492 int ret = dtn_send(h, opts_.regid_, &spec, &payload, &id);
00493 if (ret != DTN_SUCCESS) {
00494 resultf("error in dtn_send: %s",
00495 dtn_strerror(dtn_errno(h)));
00496 return TCL_ERROR;
00497 }
00498
00499 resultf("%s,%u.%u",
00500 id.source.uri, id.creation_ts.secs, id.creation_ts.seqno);
00501 return TCL_OK;
00502 }
00503 };
00504
00505
00506 class DTNBindCommand : public oasys::TclCommand {
00507 public:
00508 DTNBindCommand() : TclCommand("dtn_bind") {}
00509
00510 int exec(int argc, const char **argv, Tcl_Interp* interp)
00511 {
00512 (void)interp;
00513
00514 if (argc != 3) {
00515 wrong_num_args(argc, argv, 1, 3, 3);
00516 return TCL_ERROR;
00517 }
00518
00519 int n = atoi(argv[1]);
00520 HandleMap::iterator iter = State::instance()->handles_.find(n);
00521 if (iter == State::instance()->handles_.end()) {
00522 resultf("invalid dtn handle %d", n);
00523 return TCL_ERROR;
00524 }
00525
00526 dtn_handle_t h = iter->second;
00527
00528 dtn_reg_id_t regid = atoi(argv[2]);
00529
00530 int err = dtn_bind(h, regid);
00531 if (err != DTN_SUCCESS) {
00532 resultf("error in dtn_bind: %s",
00533 dtn_strerror(dtn_errno(h)));
00534 return TCL_ERROR;
00535 }
00536
00537 return TCL_OK;
00538 }
00539 };
00540
00541
00542 class DTNUnbindCommand : public oasys::TclCommand {
00543 public:
00544 DTNUnbindCommand() : TclCommand("dtn_unbind") {}
00545
00546 int exec(int argc, const char **argv, Tcl_Interp* interp)
00547 {
00548 (void)interp;
00549
00550 if (argc != 3) {
00551 wrong_num_args(argc, argv, 1, 3, 3);
00552 return TCL_ERROR;
00553 }
00554
00555 int n = atoi(argv[1]);
00556 HandleMap::iterator iter = State::instance()->handles_.find(n);
00557 if (iter == State::instance()->handles_.end()) {
00558 resultf("invalid dtn handle %d", n);
00559 return TCL_ERROR;
00560 }
00561
00562 dtn_handle_t h = iter->second;
00563
00564 dtn_reg_id_t regid = atoi(argv[2]);
00565
00566 int err = dtn_unbind(h, regid);
00567 if (err != DTN_SUCCESS) {
00568 resultf("error in dtn_unbind: %s",
00569 dtn_strerror(dtn_errno(h)));
00570 return TCL_ERROR;
00571 }
00572
00573 return TCL_OK;
00574 }
00575 };
00576
00577
00578 class DTNRecvCommand : public oasys::TclCommand {
00579 public:
00580 oasys::OptParser parser_;
00581
00582 struct RecvOpts {
00583 bool payload_mem_;
00584 bool payload_file_;
00585 u_int timeout_;
00586 };
00587
00588 RecvOpts opts_;
00589
00590 void init_opts() {
00591 memset(&opts_, 0, sizeof(opts_));
00592 }
00593
00594 DTNRecvCommand() : TclCommand("dtn_recv")
00595 {
00596 parser_.addopt(new oasys::BoolOpt("payload_mem", &opts_.payload_mem_));
00597 parser_.addopt(new oasys::BoolOpt("payload_file", &opts_.payload_file_));
00598 parser_.addopt(new oasys::UIntOpt("timeout", &opts_.timeout_));
00599 }
00600
00601 int exec(int argc, const char **argv, Tcl_Interp* interp)
00602 {
00603 (void)argc;
00604 (void)argv;
00605 (void)interp;
00606
00607
00608 if (argc < 3) {
00609 wrong_num_args(argc, argv, 1, 3, INT_MAX);
00610 return TCL_ERROR;
00611 }
00612
00613 int n = atoi(argv[1]);
00614 HandleMap::iterator iter = State::instance()->handles_.find(n);
00615 if (iter == State::instance()->handles_.end()) {
00616 resultf("invalid dtn handle %d", n);
00617 return TCL_ERROR;
00618 }
00619
00620 dtn_handle_t h = iter->second;
00621
00622 init_opts();
00623
00624 const char* invalid = 0;
00625 if (! parser_.parse(argc - 2, argv + 2, &invalid)) {
00626 resultf("invalid option '%s'", invalid);
00627 return TCL_ERROR;
00628 }
00629
00630 if (opts_.payload_mem_ == false && opts_.payload_file_ == false) {
00631 resultf("must set payload location");
00632 return TCL_ERROR;
00633 }
00634
00635 dtn_bundle_spec_t spec;
00636 memset(&spec, 0, sizeof(spec));
00637
00638 dtn_bundle_payload_t payload;
00639 memset(&payload, 0, sizeof(payload));
00640
00641 int err = dtn_recv(h, &spec,
00642 opts_.payload_mem_ ? DTN_PAYLOAD_MEM : DTN_PAYLOAD_FILE,
00643 &payload, opts_.timeout_);
00644 if (err != DTN_SUCCESS) {
00645 resultf("error in dtn_recv: %s",
00646 dtn_strerror(dtn_errno(h)));
00647 return TCL_ERROR;
00648 }
00649
00650 int payload_size;
00651 if (opts_.payload_mem_) {
00652
00653 payload_size = payload.buf.buf_len;
00654 } else {
00655 char payload_path[PATH_MAX];
00656 memcpy(payload_path, payload.filename.filename_val,
00657 payload.filename.filename_len);
00658 payload_path[payload.filename.filename_len] = 0;
00659
00660 payload_size = oasys::FileUtils::size(payload_path);
00661
00662 err = unlink(payload_path);
00663 if (err != 0) {
00664 log_err("error unlinking payload file '%s': %s",
00665 payload_path, strerror(errno));
00666 }
00667 }
00668
00669 dtn_free_payload(&payload);
00670
00671 Tcl_Obj* result = Tcl_NewListObj(0, NULL);
00672
00673 #define APPEND_STRING_VAL(key, val, val_len) \
00674 if (Tcl_ListObjAppendElement(interp, result, \
00675 Tcl_NewStringObj(key, -1)) != TCL_OK || \
00676 Tcl_ListObjAppendElement(interp, result, \
00677 Tcl_NewStringObj(val, val_len)) != TCL_OK)\
00678 { \
00679 resultf("error appending list element"); \
00680 return TCL_ERROR; \
00681 }
00682
00683 #define APPEND_INT_VAL(key, val) \
00684 if (Tcl_ListObjAppendElement(interp, result, \
00685 Tcl_NewStringObj(key, -1)) != TCL_OK || \
00686 Tcl_ListObjAppendElement(interp, result, \
00687 Tcl_NewIntObj(val)) != TCL_OK) \
00688 { \
00689 resultf("error appending list element"); \
00690 return TCL_ERROR; \
00691 }
00692
00693 APPEND_STRING_VAL("source", spec.source.uri, -1);
00694 APPEND_STRING_VAL("dest", spec.dest.uri, -1);
00695 APPEND_STRING_VAL("replyto", spec.replyto.uri, -1);
00696
00697 char tmp[256];
00698 snprintf(tmp, 256, "%u.%u", spec.creation_ts.secs, spec.creation_ts.seqno);
00699
00700 APPEND_STRING_VAL("creation_ts", tmp, -1);
00701
00702 APPEND_INT_VAL("payload_size", payload_size);
00703
00704 APPEND_STRING_VAL("sequence_id",
00705 spec.sequence_id.data.data_val,
00706 spec.sequence_id.data.data_len);
00707 APPEND_STRING_VAL("obsoletes_id",
00708 spec.obsoletes_id.data.data_val,
00709 spec.obsoletes_id.data.data_len);
00710
00711 set_objresult(result);
00712
00713 return TCL_OK;
00714 }
00715 };
00716
00717
00718 class DTNSessionUpdateCommand : public oasys::TclCommand {
00719 public:
00720 DTNSessionUpdateCommand() : TclCommand("dtn_session_update")
00721 {
00722 }
00723
00724 int exec(int argc, const char **argv, Tcl_Interp* interp)
00725 {
00726 (void)argc;
00727 (void)argv;
00728 (void)interp;
00729
00730
00731 if (argc != 3) {
00732 wrong_num_args(argc, argv, 1, 3, 3);
00733 return TCL_ERROR;
00734 }
00735
00736 int n = atoi(argv[1]);
00737 HandleMap::iterator iter = State::instance()->handles_.find(n);
00738 if (iter == State::instance()->handles_.end()) {
00739 resultf("invalid dtn handle %d", n);
00740 return TCL_ERROR;
00741 }
00742 dtn_handle_t h = iter->second;
00743
00744 int timeout = atoi(argv[2]);
00745
00746 unsigned int status = 0;
00747 dtn_endpoint_id_t session;
00748 memset(session.uri, 0, sizeof(session.uri));
00749
00750 int err = dtn_session_update(h, &status, &session, timeout);
00751 if (err != DTN_SUCCESS) {
00752 resultf("error in dtn_session_update: %s",
00753 dtn_strerror(dtn_errno(h)));
00754 return TCL_ERROR;
00755 }
00756
00757 resultf("%u %s", status, session.uri);
00758 return TCL_OK;
00759 }
00760 };
00761
00762
00763 class DTNPollChannelCommand : public oasys::TclCommand {
00764 public:
00765 DTNPollChannelCommand() : TclCommand("dtn_poll_channel")
00766 {
00767 }
00768
00769 int exec(int argc, const char **argv, Tcl_Interp* interp)
00770 {
00771 (void)argc;
00772 (void)argv;
00773 (void)interp;
00774
00775
00776 if (argc != 2) {
00777 wrong_num_args(argc, argv, 1, 2, 2);
00778 return TCL_ERROR;
00779 }
00780
00781 int n = atoi(argv[1]);
00782 HandleMap::iterator iter = State::instance()->handles_.find(n);
00783 if (iter == State::instance()->handles_.end()) {
00784 resultf("invalid dtn handle %d", n);
00785 return TCL_ERROR;
00786 }
00787
00788 dtn_handle_t h = iter->second;
00789
00790 int fd = dtn_poll_fd(h);
00791 if (fd < 0) {
00792 resultf("error in dtn_poll_fd: %s",
00793 dtn_strerror(dtn_errno(h)));
00794 return TCL_ERROR;
00795 }
00796
00797 Tcl_Channel chan = oasys::TclCommandInterp::instance()->
00798 register_file_channel((ClientData)fd, TCL_READABLE);
00799 if (!chan) {
00800 resultf("error making tcl channel");
00801 return TCL_ERROR;
00802 }
00803 set_result(Tcl_GetChannelName(chan));
00804
00805 return TCL_OK;
00806 }
00807 };
00808
00809
00810 class DTNBeginPollCommand : public oasys::TclCommand {
00811 public:
00812 DTNBeginPollCommand() : TclCommand("dtn_begin_poll")
00813 {
00814 }
00815
00816 int exec(int argc, const char **argv, Tcl_Interp* interp)
00817 {
00818 (void)argc;
00819 (void)argv;
00820 (void)interp;
00821
00822
00823 if (argc != 3) {
00824 wrong_num_args(argc, argv, 1, 3, 3);
00825 return TCL_ERROR;
00826 }
00827
00828 int n = atoi(argv[1]);
00829 HandleMap::iterator iter = State::instance()->handles_.find(n);
00830 if (iter == State::instance()->handles_.end()) {
00831 resultf("invalid dtn handle %d", n);
00832 return TCL_ERROR;
00833 }
00834
00835 dtn_handle_t h = iter->second;
00836
00837 int timeout = atoi(argv[2]);
00838
00839 int err = dtn_begin_poll(h, timeout);
00840 if (err < 0) {
00841 resultf("error in dtn_begin_poll: %s",
00842 dtn_strerror(dtn_errno(h)));
00843 return TCL_ERROR;
00844 }
00845
00846 return TCL_OK;
00847 }
00848 };
00849
00850
00851 class DTNCancelPollCommand : public oasys::TclCommand {
00852 public:
00853 DTNCancelPollCommand() : TclCommand("dtn_cancel_poll")
00854 {
00855 }
00856
00857 int exec(int argc, const char **argv, Tcl_Interp* interp)
00858 {
00859 (void)argc;
00860 (void)argv;
00861 (void)interp;
00862
00863
00864 if (argc != 2) {
00865 wrong_num_args(argc, argv, 1, 2, 2);
00866 return TCL_ERROR;
00867 }
00868
00869 int n = atoi(argv[1]);
00870 HandleMap::iterator iter = State::instance()->handles_.find(n);
00871 if (iter == State::instance()->handles_.end()) {
00872 resultf("invalid dtn handle %d", n);
00873 return TCL_ERROR;
00874 }
00875
00876 dtn_handle_t h = iter->second;
00877
00878
00879
00880 int err = dtn_cancel_poll(h);
00881 if (err != 0) {
00882 resultf("error in dtn_cancel_poll: %s",
00883 dtn_strerror(dtn_errno(h)));
00884 return TCL_ERROR;
00885 }
00886
00887 return TCL_OK;
00888 }
00889 };
00890
00891
00892 class ShutdownCommand : public oasys::TclCommand {
00893 public:
00894 ShutdownCommand() : TclCommand("shutdown") {}
00895 static void call_exit(void* clientData);
00896 int exec(int argc, const char **argv, Tcl_Interp* interp);
00897 };
00898
00899 void
00900 ShutdownCommand::call_exit(void* clientData)
00901 {
00902 (void)clientData;
00903 exit(0);
00904 }
00905
00906
00907 int
00908 ShutdownCommand::exec(int argc, const char **argv, Tcl_Interp* interp)
00909 {
00910 (void)argc;
00911 (void)argv;
00912 (void)interp;
00913 Tcl_CreateTimerHandler(0, ShutdownCommand::call_exit, 0);
00914 return TCL_OK;
00915 }
00916
00917
00918 int
00919 main(int argc, char** argv)
00920 {
00921 oasys::TclCommandInterp* interp;
00922 oasys::ConsoleCommand* console_cmd;
00923 std::string conf_file;
00924 bool conf_file_set = false;
00925 bool daemon = false;
00926
00927 oasys::Log::init();
00928
00929 oasys::TclCommandInterp::init("dtn-test");
00930 interp = oasys::TclCommandInterp::instance();
00931 interp->logpathf("/dtn-test/tclcmd");
00932
00933 oasys::Getopt opts;
00934 opts.addopt(
00935 new oasys::StringOpt('c', "conf", &conf_file, "<conf>",
00936 "set the configuration file", &conf_file_set));
00937
00938 opts.addopt(
00939 new oasys::BoolOpt('d', "daemon", &daemon,
00940 "run as a daemon"));
00941
00942 int remainder = opts.getopt(argv[0], argc, argv);
00943 if (remainder != argc)
00944 {
00945 fprintf(stderr, "invalid argument '%s'\n", argv[remainder]);
00946 opts.usage("dtn-test");
00947 exit(1);
00948 }
00949
00950 console_cmd = new oasys::ConsoleCommand("dtntest% ");
00951 interp->reg(console_cmd);
00952 interp->reg(new DTNOpenCommand());
00953 interp->reg(new DTNCloseCommand());
00954 interp->reg(new DTNRegisterCommand());
00955 interp->reg(new DTNUnregisterCommand());
00956 interp->reg(new DTNBindCommand());
00957 interp->reg(new DTNUnbindCommand());
00958 interp->reg(new DTNSendCommand());
00959 interp->reg(new DTNRecvCommand());
00960 interp->reg(new DTNSessionUpdateCommand());
00961 interp->reg(new DTNPollChannelCommand());
00962 interp->reg(new DTNBeginPollCommand());
00963 interp->reg(new DTNCancelPollCommand());
00964 interp->reg(new ShutdownCommand());
00965
00966 if (conf_file_set) {
00967 interp->exec_file(conf_file.c_str());
00968 }
00969
00970 log_notice_p("/dtn-test", "dtn-test starting up...");
00971
00972 if (console_cmd->port_ != 0) {
00973 log_notice_p("/dtn-test", "starting console on %s:%d",
00974 intoa(console_cmd->addr_), console_cmd->port_);
00975 interp->command_server("dtn-test", console_cmd->addr_, console_cmd->port_);
00976 }
00977
00978 if (daemon || (console_cmd->stdio_ == false)) {
00979 oasys::TclCommandInterp::instance()->event_loop();
00980 } else {
00981 oasys::TclCommandInterp::instance()->
00982 command_loop(console_cmd->prompt_.c_str());
00983 }
00984
00985 log_notice_p("/dtn-test", "dtn-test shutting down...");
00986 delete State::instance();
00987 oasys::TclCommandInterp::shutdown();
00988 oasys::Log::shutdown();
00989 }