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