servlib/conv_layers/ExternalConvergenceLayer.h
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /* Copyright 2004-2006 BBN Technologies Corporation
       
     2  *
       
     3  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
       
     4  * use this file except in compliance with the License. You may obtain a copy
       
     5  * of the License at http://www.apache.org/licenses/LICENSE-2.0
       
     6  *
       
     7  * Unless required by applicable law or agreed to in writing, software
       
     8  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
       
     9  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    10  *
       
    11  * See the License for the specific language governing permissions and
       
    12  * limitations under the License.
       
    13  *
       
    14  */
       
    15 
       
    16 #ifndef _EXTERNAL_CONVERGENCE_LAYER_H_
       
    17 #define _EXTERNAL_CONVERGENCE_LAYER_H_
       
    18 
       
    19 #ifndef DTN_CONFIG_STATE
       
    20 #error "MUST INCLUDE dtn-config.h before including this file"
       
    21 #endif
       
    22 
       
    23 #if defined(XERCES_C_ENABLED) && defined(EXTERNAL_CL_ENABLED)
       
    24 
       
    25 #include <string>
       
    26 #include <list>
       
    27 
       
    28 /* Note that these classes are now deprecated, we'll need to rewrite */
       
    29 /* the code at some point to use the new standard classes. In the */
       
    30 /*  meantime, quiet the warnings. */
       
    31 /* undefine __DEPRECATED and remember it was set*/
       
    32 #ifdef __DEPRECATED
       
    33 # define __DEPRECATED_save
       
    34 # undef __DEPRECATED
       
    35 #endif
       
    36 
       
    37 #include <ext/hash_map>
       
    38 
       
    39 /* re-define __DEPRECATED if it was set */
       
    40 #ifdef __DEPRECATED_save
       
    41 # define __DEPRECATED
       
    42 #endif
       
    43 
       
    44 #include <oasys/thread/Thread.h>
       
    45 #include <oasys/thread/Mutex.h>
       
    46 #include <oasys/io/TCPServer.h>
       
    47 
       
    48 #include "ConvergenceLayer.h"
       
    49 #include "clevent.h"
       
    50 #include "bundling/BundleList.h"
       
    51 #include "bundling/BundleEvent.h"
       
    52 #include "contacts/NamedAttribute.h"
       
    53 
       
    54 namespace dtn {
       
    55 
       
    56 // g++ 4.3.x needs this unrolled, can't use a forward decl of the form
       
    57 //   class dtn::clmessage::bundle_attributes;
       
    58 namespace clmessage {
       
    59     class bundle_attributes;
       
    60     class link_config_parameters;
       
    61 };
       
    62 
       
    63 using __gnu_cxx::hash_multimap;
       
    64 using __gnu_cxx::hash;
       
    65 
       
    66 class Interface;
       
    67 class Contact;
       
    68 class ECLModule;
       
    69 
       
    70 typedef ::xsd::cxx::tree::sequence<clmessage::key_value_pair> KeyValueSequence;
       
    71 
       
    72 /** Base class for resources that should be owned by an ECLModule.
       
    73  * 
       
    74  * Classes derived from this class are used for keeping track of various
       
    75  * resources (interfaces and links, for instance) that belong to a particular
       
    76  * module.  This base class holds info about the owner module as well as a copy
       
    77  * of the CLEvent that tells the external module to create the resource.
       
    78  */
       
    79 class ECLResource : public CLInfo {
       
    80 public:
       
    81     virtual ~ECLResource() {
       
    82         delete create_message_;
       
    83     }
       
    84     
       
    85     /// The protocol that this resource is intended for.
       
    86     std::string protocol_;
       
    87     
       
    88     /// The CLEvent that will create this resource, in case we must send
       
    89     /// it again.
       
    90     clmessage::cl_message* create_message_;
       
    91     
       
    92     /// The module that owns this resource (this will be NULL if the resource
       
    93     /// is unclaimed).
       
    94     ECLModule* module_;
       
    95     
       
    96     oasys::Mutex lock_;
       
    97     
       
    98     bool should_delete_;
       
    99     
       
   100 protected:
       
   101     ECLResource(std::string p, clmessage::cl_message* create) :
       
   102     lock_("ECLResource") {
       
   103         protocol_ = p;
       
   104         create_message_ = create;
       
   105         module_ = NULL;
       
   106         should_delete_ = true;
       
   107     }
       
   108 };
       
   109 
       
   110 
       
   111 /** Represents a single Interface.
       
   112  */
       
   113 class ECLInterfaceResource : public ECLResource {
       
   114 public:
       
   115     ECLInterfaceResource(std::string p, clmessage::cl_message* create,
       
   116     Interface* i) : ECLResource(p, create) {
       
   117         interface_ = i;
       
   118     }
       
   119     
       
   120     Interface* interface_;
       
   121 };
       
   122 
       
   123 
       
   124 /** Represents a single Link.
       
   125  */
       
   126 class ECLLinkResource : public ECLResource {
       
   127 public:
       
   128     ECLLinkResource(std::string p, clmessage::cl_message* create,
       
   129                     const LinkRef& l, bool disc);
       
   130     
       
   131     /// Reference to the link that this Resource represents.
       
   132     LinkRef link_;
       
   133     
       
   134     /// The state that the ECLModule knows the link to be in, independent of
       
   135     /// the state in the link itself. This is useful for state changes that
       
   136     /// originate at the CL rather than the BPA. 
       
   137     Link::state_t known_state_;
       
   138     
       
   139     /// True if this link was discovered rather than created by the BPA.
       
   140     bool is_discovered_;
       
   141     
       
   142     
       
   143     /** Add a bundle to this link's outgoing bundle list.
       
   144      *
       
   145      * @param bundle  The bundle to be placed on the outgoing list. A new
       
   146      *                BundleRef will be created for the bundle.
       
   147      */
       
   148     void add_outgoing_bundle(Bundle* bundle);
       
   149     
       
   150     
       
   151     /** Retrieve a bundle from this link's outgoing bundle list.
       
   152      *
       
   153      * @param bundleid  The ID of the bundle to retrieve.
       
   154      * 
       
   155      * @return The OutgoingBundle object for the requested bundle if it
       
   156      *         exists on the outgoing bundle list, NULL if it does not.
       
   157      */
       
   158     BundleRef get_outgoing_bundle(clmessage::bundle_attributes bundle_attribs);
       
   159     
       
   160     bool has_outgoing_bundle(Bundle* bundle);
       
   161     
       
   162     
       
   163     /** Erase a bundle from this link's outgoing bundle list.
       
   164      * 
       
   165      * @param outgoing_bundle  The bundle to be removed from the outgoing list.
       
   166      */
       
   167     bool erase_outgoing_bundle(Bundle* bundle);
       
   168     
       
   169     
       
   170     /** Get the actual outgoing bundle list.
       
   171      * 
       
   172      * This is used in ECLModule::cleanup() to iterate through the list.
       
   173      */
       
   174     BundleList& get_bundle_set();
       
   175     
       
   176     /** Set the link's high-water mark.
       
   177      */
       
   178     void set_high_water_mark(int high_water_mark) {
       
   179         high_water_mark_ = high_water_mark;
       
   180     }
       
   181 
       
   182     /** Check if the high-water mark would be crossed.
       
   183      * @param queued_bytes  The number of bytes queued on the link.
       
   184      * @return  True if queued_bytes is greater than or equal to the link's
       
   185      *          high-water mark; false otherwise.
       
   186      */
       
   187     bool high_water_mark_crossed(int queued_bytes) const {
       
   188         return (high_water_mark_ > 0 && queued_bytes >= high_water_mark_);
       
   189     }
       
   190     
       
   191     /** Set the link's low-water mark.
       
   192      */
       
   193     void set_low_water_mark(int low_water_mark) {
       
   194         low_water_mark_ = low_water_mark;
       
   195     }
       
   196     
       
   197     /** Check if the low-water mark would be crossed.
       
   198      * @param queued_bytes  The number of bytes queued on the link.
       
   199      * @return  True if queued_bytes is greater than or equal to the link's
       
   200      *          low-water mark; false otherwise.
       
   201     */
       
   202     bool low_water_mark_crossed(int queued_bytes) const {
       
   203         return (queued_bytes <= low_water_mark_);
       
   204     }
       
   205     
       
   206 private:
       
   207     /// The list of bundles going out on this link.
       
   208     BundleList outgoing_bundles_;
       
   209     
       
   210     /// The high-water mark for this link.
       
   211     int high_water_mark_;
       
   212     
       
   213     /// The low-water mark for this link.
       
   214     int low_water_mark_;
       
   215 };
       
   216 
       
   217 
       
   218 /** Hash function for a std::string.
       
   219  */
       
   220 struct StringHash {
       
   221     size_t operator()(std::string s) const {
       
   222         size_t h = 0;
       
   223         for (unsigned i = 0; i < s.length(); ++i)
       
   224             h = h * 5 + s[i];
       
   225         
       
   226         return h;
       
   227     }
       
   228 };
       
   229 
       
   230 typedef hash_multimap<std::string, ECLLinkResource*, StringHash>
       
   231         LinkHashMap;
       
   232 
       
   233 
       
   234 /** The external convergence layer proxy on the DTN2 side.
       
   235  * 
       
   236  * This class interacts with DTN2 as any other conventional convergence layer.
       
   237  * All interfaces and links on an external CLA appear to DTN2 to be on this
       
   238  * CL.
       
   239  * 
       
   240  * Every Interface or Link intended for an external module must specify this
       
   241  * convergence layer's name ('extcl') as its convergence layer at startup.  A
       
   242  * parameter 'protocol={module name}' must appear before any CL-specific
       
   243  * parameters for the resource to indicate which external module it is for.
       
   244  * A list of any resources intended for an external module that has not yet
       
   245  * connected to DTN2 is maintained (this is known as the 'unclaimed resource
       
   246  * list').
       
   247  */
       
   248 class ExternalConvergenceLayer : public ConvergenceLayer {
       
   249 public:
       
   250     ExternalConvergenceLayer();
       
   251     ~ExternalConvergenceLayer();
       
   252 
       
   253     /** Start the ECLA listener thread.
       
   254      * 
       
   255      * This should be called before an instance of ExternalConvergenceLayer is
       
   256      * given to ConvergenceLayer.
       
   257      */
       
   258     void start();
       
   259     
       
   260     bool set_cla_parameters(AttributeVector &params);
       
   261     bool set_interface_defaults(int argc, const char* argv[],
       
   262                                 const char** invalidp);
       
   263     bool interface_up(Interface* iface, int argc, const char* argv[]);
       
   264     bool interface_down(Interface* iface);
       
   265     void dump_interface(Interface* iface, oasys::StringBuffer* buf);
       
   266     bool set_link_defaults(int argc, const char* argv[], const char** invalidp);
       
   267     bool init_link(const LinkRef& link, int argc, const char* argv[]);
       
   268     void delete_link(const LinkRef& link);
       
   269     void dump_link(const LinkRef& link, oasys::StringBuffer* buf);
       
   270     bool reconfigure_link(const LinkRef& link, int argc, const char* argv[]);
       
   271     void reconfigure_link(const LinkRef& link, AttributeVector& params);
       
   272     bool open_contact(const ContactRef& contact);
       
   273     bool close_contact(const ContactRef& contact);
       
   274     void bundle_queued(const LinkRef& link, const BundleRef& bundle);
       
   275     void cancel_bundle(const LinkRef& link, const BundleRef& bundle);
       
   276     bool is_queued(const LinkRef& link, Bundle* bundle);
       
   277     void is_eid_reachable(const std::string& query_id, Interface* iface,
       
   278                           const std::string& endpoint);
       
   279     void query_link_attributes(const std::string& query_id,const LinkRef& link,
       
   280                                const AttributeNameVector& attributes);
       
   281     void query_iface_attributes(const std::string& query_id, Interface* iface,
       
   282                                 const AttributeNameVector& attributes);
       
   283     void query_cla_parameters(const std::string& query_id,
       
   284                               const AttributeNameVector& parameters);
       
   285     void shutdown();
       
   286 
       
   287     
       
   288     /** Take unclaimed resources intended for a given protocol.
       
   289      * 
       
   290      * This will assign to the given module any resource on the unclaimed
       
   291      * resource list matching the given protocol by setting the
       
   292      * ECLResource::module field.  All matching resources are removed from the
       
   293      * unclaimed resource list and returned.
       
   294      * 
       
   295      * @param protocol - The name of the protocol to match.
       
   296      * @param owner - The module that will own the matching resources.
       
   297      * 
       
   298      * @return A list containing all resources that matched the protocol. 
       
   299      */
       
   300     std::list<ECLResource*> take_resources(std::string protocol);
       
   301     
       
   302     
       
   303     /** Give a list of Interface resources back to the unclaimed resource list.
       
   304      * 
       
   305      * The resources will be placed back on the unclaimed resource list and
       
   306      * the ECLResource::module field set to NULL.
       
   307      */
       
   308     void give_resources(std::list<ECLInterfaceResource*>& list);
       
   309     
       
   310     
       
   311     /** Give a list of Interface resources back to the unclaimed resource list.
       
   312      * 
       
   313      * The resources will be placed back on the unclaimed resource list and
       
   314      * the ECLResource::module field set to NULL.
       
   315      */
       
   316     void give_resources(LinkHashMap& list);
       
   317     
       
   318     
       
   319     /** Delete a resource.
       
   320      * 
       
   321      * This will remove the resource from the list of unclaimed resources and
       
   322      * call 'delete' on the pointer.
       
   323      */
       
   324     void delete_resource(ECLResource* resource);
       
   325     
       
   326     
       
   327     /** Add a module to the active module list.
       
   328      */
       
   329     void add_module(ECLModule* module);
       
   330     
       
   331     
       
   332     /** Remove a module from the active module list.
       
   333      */
       
   334     void remove_module(ECLModule* module);
       
   335     
       
   336     
       
   337     /** Retrieve a module matching the given protocol name.
       
   338      * 
       
   339      * @param protocol - The name of the protocol to match.
       
   340      * @return A pointer to the module matching the protocol, or NULL if no
       
   341      *      such module exists.
       
   342      */
       
   343     ECLModule* get_module(const std::string& protocol);
       
   344     
       
   345     /// The path to the XSD file that specifies the XML messages between the
       
   346     /// BPA and the CLA. This is set with the command 'ecla set xsd_file'
       
   347     static std::string schema_;
       
   348     
       
   349     static bool client_validation_;
       
   350     
       
   351     /// The address on which the Listener thread will listen. This is set with
       
   352     /// the command 'ecla set listen_addr'
       
   353     static in_addr_t server_addr_;
       
   354     
       
   355     /// The address on which the Listener thread will listen. This is set with
       
   356     /// the command 'ecla set listen_port'
       
   357     static u_int16_t server_port_;
       
   358     
       
   359     static bool create_discovered_links_;
       
   360     
       
   361     static bool discovered_prev_hop_header_;
       
   362     
       
   363     /// This is used in ECLModule::send_message() to generate the XML
       
   364     /// namespace/schema info at the start of every message.
       
   365     static xml_schema::namespace_infomap namespace_map_;
       
   366 
       
   367     
       
   368     /// ECLModule locks this when it enters ECLModule::cleanup() to prevent
       
   369     /// race conditions on resources that are being cleaned up.
       
   370     oasys::Mutex global_resource_lock_;
       
   371     
       
   372     
       
   373 private:
       
   374     /** Thread to listen for connections from new external modules.
       
   375      * 
       
   376      * This thread will wait on accept() for connections on the designated
       
   377      * port (where this port is specified is TBD) on localhost for connections
       
   378      * from new external modules.  For each new connection, an ECLModule is
       
   379      * created and started.
       
   380      */
       
   381     class Listener : public oasys::TCPServerThread {
       
   382     public:
       
   383         Listener(ExternalConvergenceLayer& cl);
       
   384         virtual ~Listener();
       
   385 
       
   386         void start();
       
   387         virtual void accepted(int fd, in_addr_t addr, u_int16_t port);
       
   388 
       
   389     private:
       
   390         /// Reference back to the convergence layer.
       
   391         ExternalConvergenceLayer& cl_;
       
   392     }; // class Listener
       
   393     
       
   394     
       
   395     /** Add a resource to the unclaimed resource list.
       
   396      */
       
   397     void add_resource(ECLResource* resource);
       
   398     
       
   399     /** Convert an arg vector to a KeyValueSequence.
       
   400      * 
       
   401      * This will take a number of strings (in argv) in the form 'name=value'
       
   402      * and convert them to a KeyValueSequence suitable for XML messages.
       
   403      * 
       
   404      * @param argc  Number of arguments in argv.
       
   405      * @param argv  The vector of arguments.
       
   406      * @param param_sequence  An instance of KeyValueSequence that will be
       
   407      *                        populated with the parameters.
       
   408      */
       
   409     void build_param_sequence(int argc, const char* argv[],
       
   410                               KeyValueSequence& param_sequence);
       
   411     
       
   412     /** Fill in the fields of a bundle_attributes object.
       
   413      * 
       
   414      * This will complete the bundle_attributes instance based on the given
       
   415      * bundle.
       
   416      */
       
   417     void fill_bundle_attributes(const BundleRef& bundle,
       
   418                                 clmessage::bundle_attributes& attribs);
       
   419         
       
   420     /// The list of active modules.
       
   421     std::list<ECLModule*> module_list_;
       
   422     
       
   423     /// Mutex for module_list_ access.
       
   424     oasys::Mutex module_mutex_;
       
   425     
       
   426     /// The unclaimed resource list.
       
   427     std::list<ECLResource*> resource_list_;
       
   428     
       
   429     /// Mutex for resource_list_ access.
       
   430     oasys::Mutex resource_mutex_;
       
   431     
       
   432     /// The thread listening for new modules.
       
   433     Listener listener_;
       
   434 };
       
   435 
       
   436 
       
   437 /** Functions for converting between various DTN2 types and their corresponding
       
   438  * value in the clmessage namespace.
       
   439  */
       
   440 class XMLConvert {
       
   441 public:
       
   442     static clmessage::linkTypeType convert_link_type(Link::link_type_t type);
       
   443     static Link::link_type_t convert_link_type(clmessage::linkTypeType type);
       
   444     
       
   445     static Link::state_t convert_link_state(clmessage::linkStateType state);
       
   446     
       
   447     static ContactEvent::reason_t convert_link_reason(
       
   448             clmessage::linkReasonType reason);
       
   449 };
       
   450 
       
   451 } // namespace dtn
       
   452 
       
   453 #endif // XERCES_C_ENABLED && EXTERNAL_CL_ENABLED
       
   454 #endif // _EXTERNAL_CONVERGENCE_LAYER_H_
       
   455