LinkCommand.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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         // link add <name> <nexthop> <type> <clayer> <args>
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         // validate the link type, make sure there's no link of the
00097         // same name, and validate the convergence layer
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         // Create the link, parsing the cl-specific next hop string
00117         // and other arguments
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         // Add the link to contact manager's table, which posts a
00127         // LinkCreatedEvent to the daemon
00128         BundleDaemon::instance()->contactmgr()->add_link(link);
00129         return TCL_OK;
00130 
00131     } else if (strcmp(cmd, "reconfigure") == 0) {
00132         // link set_option <name> <opt=val> <opt2=val2>...
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         // link open <name>
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         // XXX/TODO should change all these to post_and_wait
00184         BundleDaemon::post(new LinkStateChangeRequest(link, Link::OPEN,
00185                                                       ContactEvent::USER));
00186         
00187     } else if (strcmp(cmd, "close") == 0) {
00188         // link close <name>
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         // link set_available <name> <true|false>
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 { // ! set_available
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         // link state <name>
00279         // link stats <name>
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         // link dump <name?>
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         // link set_cl_defaults <cl> <opt=val> <opt2=val2> ...
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 } // namespace dtn

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1