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 <oasys/thread/Lock.h>
00022 #include <oasys/util/StringBuffer.h>
00023
00024 #include "LinkCommand.h"
00025 #include "bundling/BundleEvent.h"
00026 #include "bundling/BundleDaemon.h"
00027 #include "contacts/Link.h"
00028 #include "contacts/ContactManager.h"
00029 #include "conv_layers/ConvergenceLayer.h"
00030 #include "naming/Scheme.h"
00031
00032 namespace dtn {
00033
00034 LinkCommand::LinkCommand()
00035 : TclCommand("link")
00036 {
00037 add_to_help("add <name> <next hop> <type> <conv layer> <args>", "add links");
00038 add_to_help("open <name>", "open the link");
00039 add_to_help("close <name>", "close the link");
00040 add_to_help("delete <name>", "delete the link");
00041 add_to_help("set_available <name> <true | false>",
00042 "hacky way to make the link available");
00043 add_to_help("state <name>", "return the state of a link");
00044 add_to_help("stats <name>", "dump link statistics");
00045 add_to_help("names", "print a list of existing link names");
00046 add_to_help("dump <name?>", "print the list of existing links or "
00047 "detailed info about a single link");
00048 add_to_help("reconfigure <name> <opt=val> <opt2=val2>...",
00049 "configure link options after initialization "
00050 "(not all options support this feature)");
00051 add_to_help("set_cl_defaults <cl> <opt=val> <opt2=val2>...",
00052 "configure convergence layer specific default options");
00053 }
00054
00055 int
00056 LinkCommand::exec(int argc, const char** argv, Tcl_Interp* interp)
00057 {
00058 (void)interp;
00059
00060 if (argc < 2) {
00061 resultf("need a link subcommand");
00062 return TCL_ERROR;
00063 }
00064
00065 const char* cmd = argv[1];
00066
00067 if (strcmp(cmd, "add") == 0) {
00068
00069 if (argc < 6) {
00070 wrong_num_args(argc, argv, 2, 6, INT_MAX);
00071 return TCL_ERROR;
00072 }
00073
00074 const char* name = argv[2];
00075 const char* nexthop = argv[3];
00076 const char* type_str = argv[4];
00077 const char* cl_str = argv[5];
00078
00079
00080
00081 Link::link_type_t type = Link::str_to_link_type(type_str);
00082 if (type == Link::LINK_INVALID) {
00083 resultf("invalid link type %s", type_str);
00084 return TCL_ERROR;
00085 }
00086
00087 ConvergenceLayer* cl = ConvergenceLayer::find_clayer(cl_str);
00088 if (!cl) {
00089 resultf("invalid convergence layer %s", cl_str);
00090 return TCL_ERROR;
00091 }
00092
00093
00094
00095 LinkRef link;
00096 const char* invalid_arg = "(unknown)";
00097 link = Link::create_link(name, type, cl, nexthop, argc - 6, &argv[6],
00098 &invalid_arg);
00099 if (link == NULL) {
00100 resultf("invalid link option: %s", invalid_arg);
00101 return TCL_ERROR;
00102 }
00103
00104
00105
00106
00107 if (!BundleDaemon::instance()->contactmgr()->add_new_link(link)) {
00108
00109 link->delete_link();
00110 resultf("link name %s already exists, use different name", name);
00111 return TCL_ERROR;
00112 }
00113 return TCL_OK;
00114
00115 } else if (strcmp(cmd, "reconfigure") == 0) {
00116
00117 if (argc < 4) {
00118 wrong_num_args(argc, argv, 2, 4, INT_MAX);
00119 return TCL_ERROR;
00120 }
00121
00122 const char* name = argv[2];
00123
00124 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00125 if (link == NULL) {
00126 resultf("link %s doesn't exist", name);
00127 return TCL_ERROR;
00128 }
00129
00130 argc -= 3;
00131 argv += 3;
00132
00133 const char* invalid;
00134 int count = link->parse_args(argc, argv, &invalid);
00135 if (count == -1) {
00136 resultf("invalid link option: %s", invalid);
00137 return TCL_ERROR;
00138 }
00139 argc -= count;
00140
00141 if (!link->reconfigure_link(argc, argv)) {
00142 return TCL_ERROR;
00143 }
00144
00145 return TCL_OK;
00146
00147 } else if (strcmp(cmd, "open") == 0) {
00148
00149 if (argc != 3) {
00150 wrong_num_args(argc, argv, 2, 3, 3);
00151 return TCL_ERROR;
00152 }
00153
00154 const char* name = argv[2];
00155
00156 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00157 if (link == NULL) {
00158 resultf("link %s doesn't exist", name);
00159 return TCL_ERROR;
00160 }
00161
00162 if (link->isopen()) {
00163 resultf("link %s already open", name);
00164 return TCL_OK;
00165 }
00166
00167
00168 BundleDaemon::post(new LinkStateChangeRequest(link, Link::OPEN,
00169 ContactEvent::USER));
00170
00171 } else if (strcmp(cmd, "close") == 0) {
00172
00173 if (argc != 3) {
00174 wrong_num_args(argc, argv, 2, 3, 3);
00175 return TCL_ERROR;
00176 }
00177
00178 const char* name = argv[2];
00179
00180 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00181 if (link == NULL) {
00182 resultf("link %s doesn't exist", name);
00183 return TCL_ERROR;
00184 }
00185
00186 if (! link->isopen() && ! link->isopening()) {
00187 resultf("link %s already closed", name);
00188 return TCL_OK;
00189 }
00190
00191 BundleDaemon::instance()->post(
00192 new LinkStateChangeRequest(link, Link::CLOSED,
00193 ContactEvent::USER));
00194
00195 return TCL_OK;
00196
00197 } else if (strcmp(cmd, "delete") == 0) {
00198
00199 if (argc != 3) {
00200 wrong_num_args(argc, argv, 2, 3, 3);
00201 return TCL_ERROR;
00202 }
00203
00204 const char * name = argv[2];
00205
00206 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00207 if (link == NULL) {
00208 resultf("link %s doesn't exist", name);
00209 return TCL_ERROR;
00210 }
00211
00212 BundleDaemon::instance()->post(new LinkDeleteRequest(link));
00213 return TCL_OK;
00214
00215 } else if (strcmp(cmd, "set_available") == 0) {
00216
00217 if (argc != 4) {
00218 wrong_num_args(argc, argv, 2, 4, 4);
00219 return TCL_ERROR;
00220 }
00221
00222 const char* name = argv[2];
00223
00224 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00225 if (link == NULL) {
00226 resultf("link %s doesn't exist", name);
00227 return TCL_ERROR;
00228 }
00229
00230 int len = strlen(argv[3]);
00231 bool set_available;
00232
00233 if (strncmp(argv[3], "1", len) == 0) {
00234 set_available = true;
00235 } else if (strncmp(argv[3], "0", len) == 0) {
00236 set_available = false;
00237 } else if (strncasecmp(argv[3], "true", len) == 0) {
00238 set_available = true;
00239 } else if (strncasecmp(argv[3], "false", len) == 0) {
00240 set_available = false;
00241 } else if (strncasecmp(argv[3], "on", len) == 0) {
00242 set_available = true;
00243 } else if (strncasecmp(argv[3], "off", len) == 0) {
00244 set_available = false;
00245 } else {
00246 resultf("error converting argument %s to boolean value", argv[3]);
00247 return TCL_ERROR;
00248 }
00249
00250 if (set_available) {
00251 if (link->state() != Link::UNAVAILABLE) {
00252 resultf("link %s already in state %s",
00253 name, Link::state_to_str(link->state()));
00254 return TCL_OK;
00255 }
00256
00257 BundleDaemon::post(
00258 new LinkStateChangeRequest(link, Link::AVAILABLE,
00259 ContactEvent::USER));
00260
00261 return TCL_OK;
00262
00263 } else {
00264 if (link->state() != Link::AVAILABLE) {
00265 resultf("link %s can't be set unavailable in state %s",
00266 name, Link::state_to_str(link->state()));
00267 return TCL_OK;
00268 }
00269
00270 BundleDaemon::post(
00271 new LinkStateChangeRequest(link, Link::UNAVAILABLE,
00272 ContactEvent::USER));
00273
00274 return TCL_OK;
00275 }
00276 }
00277 else if ((strcmp(cmd, "state") == 0) ||
00278 (strcmp(cmd, "stats") == 0))
00279 {
00280
00281
00282 if (argc != 3) {
00283 wrong_num_args(argc, argv, 2, 3, 3);
00284 return TCL_ERROR;
00285 }
00286
00287 const char* name = argv[2];
00288
00289 LinkRef link = BundleDaemon::instance()->contactmgr()->find_link(name);
00290 if (link == NULL) {
00291 resultf("link %s doesn't exist", name);
00292 return TCL_ERROR;
00293 }
00294
00295 if (strcmp(cmd, "state") == 0) {
00296 resultf("%s", Link::state_to_str(link->state()));
00297 } else {
00298 oasys::StringBuffer buf;
00299 link->dump_stats(&buf);
00300 set_result(buf.c_str());
00301 }
00302 return TCL_OK;
00303 }
00304 else if (strcmp(cmd, "names") == 0)
00305 {
00306
00307 if (argc != 2) {
00308 wrong_num_args(argc, argv, 2, 2, 2);
00309 return TCL_ERROR;
00310 }
00311
00312 ContactManager* cm = BundleDaemon::instance()->contactmgr();
00313 oasys::ScopeLock l(cm->lock(), "LinkCommand::exec");
00314
00315 const LinkSet* links = cm->links();
00316 for (LinkSet::const_iterator i = links->begin();
00317 i != links->end(); ++i)
00318 {
00319 append_resultf("%s\n", (*i)->name());
00320 }
00321 return TCL_OK;
00322 }
00323 else if (strcmp(cmd, "dump") == 0)
00324 {
00325
00326 if (argc == 2) {
00327 ContactManager* cm = BundleDaemon::instance()->contactmgr();
00328 oasys::ScopeLock l(cm->lock(), "LinkCommand::exec");
00329
00330 const LinkSet* links = cm->links();
00331 for (LinkSet::const_iterator i = links->begin();
00332 i != links->end(); ++i)
00333 {
00334 append_resultf("*%p\n", (*i).object());
00335 }
00336 } else if (argc == 3) {
00337 const char* name = argv[2];
00338
00339 LinkRef link =
00340 BundleDaemon::instance()->contactmgr()->find_link(name);
00341 if (link == NULL) {
00342 resultf("link %s doesn't exist", name);
00343 return TCL_ERROR;
00344 }
00345
00346 oasys::StringBuffer buf;
00347 link->dump(&buf);
00348 set_result(buf.c_str());
00349 return TCL_OK;
00350 } else {
00351 wrong_num_args(argc, argv, 2, 2, 3);
00352 return TCL_ERROR;
00353 }
00354 }
00355 else if (strcmp(cmd, "set_cl_defaults") == 0)
00356 {
00357
00358 if (argc < 4) {
00359 wrong_num_args(argc, argv, 2, 4, INT_MAX);
00360 return TCL_ERROR;
00361 }
00362
00363 ConvergenceLayer* cl = ConvergenceLayer::find_clayer(argv[2]);
00364 if (cl == NULL) {
00365 resultf("unknown convergence layer %s", argv[2]);
00366 return TCL_ERROR;
00367 }
00368
00369 const char* invalid;
00370 if (!cl->set_link_defaults(argc - 3, &argv[3], &invalid)) {
00371 resultf("invalid link option: %s", invalid);
00372 return TCL_ERROR;
00373 }
00374
00375 return TCL_OK;
00376 }
00377 else
00378 {
00379 resultf("unimplemented link subcommand %s", cmd);
00380 return TCL_ERROR;
00381 }
00382
00383 return TCL_OK;
00384 }
00385
00386 }