servlib/prophet/BundleCore.h
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2007 Baylor University
       
     3  *
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  *
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  *
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #ifndef _PROPHET_BUNDLE_CORE_FACADE_H_
       
    18 #define _PROPHET_BUNDLE_CORE_FACADE_H_
       
    19 
       
    20 #include "Alarm.h"
       
    21 #include "Node.h"
       
    22 #include "Bundle.h"
       
    23 #include "BundleImpl.h"
       
    24 #include "BundleList.h"
       
    25 #include "Link.h"
       
    26 #include <stdio.h>
       
    27 #include <stdarg.h>
       
    28 #include <string>
       
    29 #include <list>
       
    30 
       
    31 #if defined(__GNUC__)
       
    32 # define PRINTFLIKE(fmt, arg) __attribute__((format (printf, fmt, arg)))
       
    33 #else
       
    34 # define PRINTFLIKE(a, b)
       
    35 #endif
       
    36 
       
    37 namespace prophet
       
    38 {
       
    39 
       
    40 /**
       
    41  * Prophet facade's abstract interface into DTN host's bundle core.
       
    42  * Prophet requires Bundle handling (create, read, write, send, find), 
       
    43  * routing functions, preferences and parameters, persistent storage,
       
    44  * timers and timeout handling, and debug logging.  BundleCore decouples
       
    45  * the Prophet facade library from its host implementation by abstracting
       
    46  * away the specifics of implmentation for these core functions.
       
    47  */
       
    48 class BundleCore
       
    49 {
       
    50 public:
       
    51 
       
    52     /**
       
    53      * Destructor
       
    54      */
       
    55     virtual ~BundleCore() {}
       
    56 
       
    57     /**
       
    58      * Answers whether dest_id matches route
       
    59      */
       
    60     virtual bool is_route(const std::string& dest_id,
       
    61                           const std::string& route) const = 0;
       
    62 
       
    63     /**
       
    64      * Query the Bundle core for route status
       
    65      */
       
    66     virtual bool should_fwd(const Bundle* bundle,
       
    67                             const Link* link) const = 0;
       
    68 
       
    69     /**
       
    70      * Given a Bundle's destination, return the route
       
    71      */
       
    72     virtual std::string get_route(const std::string& dest_id) const = 0;
       
    73 
       
    74     /**
       
    75      * Given a Bundle's destination, return the route pattern
       
    76      */
       
    77     virtual std::string get_route_pattern(const std::string& dest_id) const = 0;
       
    78 
       
    79     /**
       
    80      * Callback method for Prophet to query storage_quota()
       
    81      */
       
    82     virtual u_int64_t max_bundle_quota() const = 0;
       
    83 
       
    84     /**
       
    85      * Callback method for Prophet to query whether Bundle host
       
    86      * is willing to accept custody transfers
       
    87      */
       
    88     virtual bool custody_accepted() const = 0;
       
    89 
       
    90     /**
       
    91      * Enumerate Bundles in host's store
       
    92      */
       
    93     virtual const BundleList& bundles() const = 0;
       
    94 
       
    95     /**
       
    96      * Callback method for Prophet to request for a bundle to be deleted;
       
    97      * required by Repository's evict() routine
       
    98      */
       
    99     virtual void drop_bundle(const Bundle* bundle) = 0;
       
   100 
       
   101     /**
       
   102      * Given a Bundle and a candidate Link, attempt to send a Bundle
       
   103      */
       
   104     virtual bool send_bundle(const Bundle* bundle,
       
   105                              const Link* link) = 0;
       
   106 
       
   107     /**
       
   108      * Transfer buffer into Bundle's payload
       
   109      * @param bundle bundle metadata object
       
   110      * @param buf Buffer to write into payload
       
   111      * @return success
       
   112      */
       
   113     virtual bool write_bundle(const Bundle* bundle,
       
   114                               const u_char* buf,
       
   115                               size_t len) = 0;
       
   116 
       
   117     /**
       
   118      * Request a Bundle's payload from Bundle host. 
       
   119      * @param bundle bundle metadata object
       
   120      * @param buffer in/out memory into which to write Bundle payload
       
   121      * @param len in/out size of inbound buffer, amount written into
       
   122      *            outbound buffer
       
   123      * @return success
       
   124      */
       
   125     virtual bool read_bundle(const Bundle* bundle,
       
   126                              u_char* buffer,
       
   127                              size_t& len) const = 0;
       
   128 
       
   129     /**
       
   130      * Factory method to request new Bundle from bundle host.
       
   131      * @param src Route of bundle originator
       
   132      * @param dst Route of bundle destination
       
   133      * @param exp Lifespan in seconds
       
   134      */
       
   135     virtual Bundle* create_bundle(const std::string& src,
       
   136                                   const std::string& dst,
       
   137                                   u_int exp) = 0;
       
   138 
       
   139     /**
       
   140      * Given a BundleList, a route, a creation ts, and a sequence number,
       
   141      * find the Bundle
       
   142      */
       
   143     virtual const Bundle* find(const BundleList& list, const std::string& eid,
       
   144                          u_int32_t creation_ts, u_int32_t seqno) const = 0;
       
   145 
       
   146     /**
       
   147      * Update (or create) a persistent Node to reflect handle's info
       
   148      */
       
   149     virtual void update_node(const Node* node) = 0;
       
   150 
       
   151     /**
       
   152      * Remove this Node from persistent storage
       
   153      */
       
   154     virtual void delete_node(const Node* node) = 0;
       
   155 
       
   156     /**
       
   157      * Query the local endpoint ID
       
   158      */
       
   159     virtual std::string local_eid() const = 0;
       
   160 
       
   161     /**
       
   162      * Query for the endpoint ID to the Prophet node on the remote end of
       
   163      * this link
       
   164      */
       
   165     virtual std::string prophet_id(const Link* link) const = 0;
       
   166 
       
   167     /**
       
   168      * Query for the endpoint ID to the local Prophet instance
       
   169      */
       
   170     virtual std::string prophet_id() const = 0;
       
   171 
       
   172     /**
       
   173      * Factory method to allocate memory for and return pointer to new
       
   174      * Alarm object that will invoke handler->handle_timeout() after
       
   175      * timeout milliseconds.
       
   176      */
       
   177     virtual Alarm* create_alarm(ExpirationHandler* handler,
       
   178                                 u_int timeout, bool jitter = false) = 0;
       
   179 
       
   180     ///@{ Log level
       
   181     static const int LOG_DEBUG   = 1;
       
   182     static const int LOG_INFO    = 2;
       
   183     static const int LOG_NOTICE  = 3;
       
   184     static const int LOG_WARN    = 4;
       
   185     static const int LOG_ERR     = 5;
       
   186     static const int LOG_CRIT    = 6;
       
   187     static const int LOG_ALWAYS  = 7;
       
   188     ///@}
       
   189 
       
   190     /**
       
   191      * Defer implementation of logging to host system ... but still
       
   192      * propagate messages up to host system from within prophet namespace
       
   193      */
       
   194     virtual void print_log(const char* name, int level, const char* fmt, ...)
       
   195         PRINTFLIKE(4,5) = 0;
       
   196 
       
   197 }; // class BundleCore
       
   198 
       
   199 /**
       
   200  * Mock object for use in testing
       
   201  */
       
   202 class AlarmImpl : public Alarm
       
   203 {
       
   204 public:
       
   205     AlarmImpl(ExpirationHandler* h)
       
   206         : Alarm(h), pending_(false), cancelled_(false) {}
       
   207 
       
   208     virtual ~AlarmImpl() {}
       
   209 
       
   210     void schedule(u_int) { pending_ = true; }
       
   211     u_int time_remaining() const { return 0; }
       
   212     void cancel() { cancelled_ = true; }
       
   213     bool pending() const { return pending_; }
       
   214     bool cancelled() const { return cancelled_; }
       
   215     bool pending_, cancelled_;
       
   216 }; // class AlarmImpl
       
   217 
       
   218 /**
       
   219  * Mock object for use in unit testing; this doesn't really do 
       
   220  * anything other than capture state for inspection by unit tests
       
   221  */
       
   222 class BundleCoreTestImpl : public BundleCore
       
   223 {
       
   224 public:
       
   225     typedef std::string BundleBuffer;
       
   226     BundleCoreTestImpl(const std::string& str = "dtn://somehost")
       
   227         : str_(str), max_(0xffff) {}
       
   228     virtual ~BundleCoreTestImpl()
       
   229     {
       
   230         while (!alarms_.empty())
       
   231         {
       
   232             delete alarms_.front();
       
   233             alarms_.pop_front();
       
   234         }
       
   235     }
       
   236     ///@{ virtual from BundleCore
       
   237     bool is_route(const std::string& dest,const std::string& route) const
       
   238     {
       
   239         if (route.length() > dest.length()) return false;
       
   240         return route.compare(0,route.length(),dest) == 0;
       
   241     }
       
   242     bool should_fwd(const Bundle*,const Link*) const { return true; }
       
   243     std::string get_route(const std::string& str ) const { return str; }
       
   244     std::string get_route_pattern(const std::string& str ) const { return str + "/*"; }
       
   245     u_int64_t max_bundle_quota() const { return max_; }
       
   246     bool custody_accepted() const { return true; }
       
   247     void drop_bundle(const Bundle* b)
       
   248     {
       
   249         for (std::list<bundle>::iterator i = rcvd_.begin();
       
   250                 i != rcvd_.end(); i++)
       
   251         {
       
   252             if (b->destination_id() == (*i).first->destination_id() &&
       
   253                 b->creation_ts() == (*i).first->creation_ts() &&
       
   254                 b->sequence_num() == (*i).first->sequence_num())
       
   255             {
       
   256                 rcvd_.erase(i);
       
   257                 break;
       
   258             }
       
   259         }
       
   260     }
       
   261     bool send_bundle(const Bundle* b,const Link*)
       
   262     {
       
   263         sent_.push_back(b);
       
   264         return true;
       
   265     }
       
   266     bool write_bundle(const Bundle* b,const u_char* buf,size_t len)
       
   267     { 
       
   268         BundleBuffer bunbuf((char*)buf,len);
       
   269         written_.push_back(std::make_pair<const Bundle*,BundleBuffer>(b,bunbuf));
       
   270         return written_.back().second.size() <= len;
       
   271     }
       
   272     bool read_bundle(const Bundle* b,u_char* buf,size_t& len) const
       
   273     {
       
   274         for (std::list<bundle>::const_iterator i = rcvd_.begin();
       
   275                 i != rcvd_.end(); i++)
       
   276         {
       
   277             if (b->destination_id() == (*i).first->destination_id() &&
       
   278                 b->creation_ts() == (*i).first->creation_ts() &&
       
   279                 b->sequence_num() == (*i).first->sequence_num())
       
   280             {
       
   281                 size_t blen = (*i).second.size();
       
   282                 if (blen < len) return false;
       
   283                 len = blen;
       
   284                 memcpy(buf,(*i).second.data(),len);
       
   285                 return true;
       
   286             }
       
   287         }
       
   288         return false;
       
   289     }
       
   290     Bundle* create_bundle(const std::string& src, const std::string& dst,u_int exp=3600)
       
   291     { return new BundleImpl(src,dst,0,0,exp); }
       
   292     const Bundle* find(const BundleList&,const std::string&,u_int32_t,
       
   293             u_int32_t) const
       
   294     { return NULL; }
       
   295     const BundleList& bundles() const { return list_; }
       
   296     void update_node(const Node*) {}
       
   297     void delete_node(const Node*) {}
       
   298     std::string local_eid() const { return str_; }
       
   299 #define PROPHESY(_str) do { \
       
   300         size_t pos = _str.size() - 1; \
       
   301         if (_str[pos] == '/') \
       
   302             _str += "prophet"; \
       
   303         else \
       
   304             _str += "/prophet"; \
       
   305     } while (0)
       
   306     std::string prophet_id(const Link* link) const
       
   307     {
       
   308         remote_.assign(link->nexthop());
       
   309         PROPHESY(remote_);
       
   310         return remote_;
       
   311     }
       
   312     std::string prophet_id() const
       
   313     {
       
   314         if (local_ == "")
       
   315         {
       
   316             local_.assign(str_);
       
   317             PROPHESY(local_);
       
   318         }
       
   319         return local_;
       
   320     }
       
   321 #undef PROPHESY
       
   322     Alarm* create_alarm(ExpirationHandler* handler, u_int timeout,bool)
       
   323     {
       
   324         AlarmImpl* alarm = new AlarmImpl(handler);
       
   325         alarm->schedule(timeout);
       
   326         alarms_.push_back(alarm);
       
   327         return alarm;
       
   328     }
       
   329     void print_log(const char* name, int level, const char* fmt, ...)
       
   330         PRINTFLIKE(4,5);
       
   331 
       
   332     ///@}
       
   333     void set_max(u_int64_t max) { max_ = max; }
       
   334     void set_eid(const std::string& id) { str_.assign(id); }
       
   335     std::string str_;
       
   336     mutable std::string local_, remote_;
       
   337     u_int64_t max_;
       
   338     std::list<const Bundle*> sent_;
       
   339     typedef std::pair<const Bundle*,BundleBuffer> bundle;
       
   340     std::list<bundle> written_;
       
   341     std::list<bundle> rcvd_;
       
   342     std::list<Alarm*> alarms_;
       
   343     prophet::BundleList list_;
       
   344 }; // class BundleCoreTestImpl
       
   345 
       
   346 inline void 
       
   347 BundleCoreTestImpl::print_log(const char* name, int level, const char* fmt, ...)
       
   348 {
       
   349     printf("[%s][%d]\n",name,level);
       
   350     va_list ap;
       
   351     va_start(ap, fmt);
       
   352     vprintf(fmt, ap);
       
   353     va_end(ap);
       
   354     printf("\n");
       
   355 }
       
   356 
       
   357 }; // namespace prophet
       
   358 
       
   359 #endif // _PROPHET_BUNDLE_CORE_FACADE_H_