LinkCommand.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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         // link add <name> <nexthop> <type> <clayer> <args>
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         // validate the link type, make sure there's no link of the
00076         // same name, and validate the convergence layer
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         // Create the link, parsing the cl-specific next hop string
00096         // and other arguments
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         // Add the link to contact manager's table, which posts a
00106         // LinkCreatedEvent to the daemon
00107         BundleDaemon::instance()->contactmgr()->add_link(link);
00108         return TCL_OK;
00109 
00110     } else if (strcmp(cmd, "reconfigure") == 0) {
00111         // link set_option <name> <opt=val> <opt2=val2>...
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         // link open <name>
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         // XXX/TODO should change all these to post_and_wait
00163         BundleDaemon::post(new LinkStateChangeRequest(link, Link::OPEN,
00164                                                       ContactEvent::USER));
00165         
00166     } else if (strcmp(cmd, "close") == 0) {
00167         // link close <name>
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         // link set_available <name> <true|false>
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 { // ! set_available
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         // link state <name>
00258         // link stats <name>
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         // link dump <name?>
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         // link set_cl_defaults <cl> <opt=val> <opt2=val2> ...
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 } // namespace dtn

Generated on Thu Jun 7 12:54:28 2007 for DTN Reference Implementation by  doxygen 1.5.1