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