<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>DTN Reference Implementation: TableBasedRouter.cc Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> <link href="tabs.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.5.6 --> <div class="navigation" id="top"> <div class="tabs"> <ul> <li><a href="main.html"><span>Main Page</span></a></li> <li><a href="namespaces.html"><span>Namespaces</span></a></li> <li><a href="annotated.html"><span>Classes</span></a></li> <li class="current"><a href="files.html"><span>Files</span></a></li> </ul> </div> <h1>TableBasedRouter.cc</h1><a href="TableBasedRouter_8cc.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span> <a name="l00002"></a>00002 <span class="comment"> * Copyright 2005-2006 Intel Corporation</span> <a name="l00003"></a>00003 <span class="comment"> * </span> <a name="l00004"></a>00004 <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License");</span> <a name="l00005"></a>00005 <span class="comment"> * you may not use this file except in compliance with the License.</span> <a name="l00006"></a>00006 <span class="comment"> * You may obtain a copy of the License at</span> <a name="l00007"></a>00007 <span class="comment"> * </span> <a name="l00008"></a>00008 <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span> <a name="l00009"></a>00009 <span class="comment"> * </span> <a name="l00010"></a>00010 <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span> <a name="l00011"></a>00011 <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS,</span> <a name="l00012"></a>00012 <span class="comment"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span> <a name="l00013"></a>00013 <span class="comment"> * See the License for the specific language governing permissions and</span> <a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span> <a name="l00015"></a>00015 <span class="comment"> */</span> <a name="l00016"></a>00016 <a name="l00017"></a>00017 <span class="preprocessor">#ifdef HAVE_CONFIG_H</span> <a name="l00018"></a>00018 <span class="preprocessor"></span><span class="preprocessor"># include <<a class="code" href="dtn-config_8h.html">dtn-config.h</a>></span> <a name="l00019"></a>00019 <span class="preprocessor">#endif</span> <a name="l00020"></a>00020 <span class="preprocessor"></span> <a name="l00021"></a>00021 <span class="preprocessor">#include "<a class="code" href="TableBasedRouter_8h.html">TableBasedRouter.h</a>"</span> <a name="l00022"></a>00022 <span class="preprocessor">#include "<a class="code" href="RouteTable_8h.html">RouteTable.h</a>"</span> <a name="l00023"></a>00023 <span class="preprocessor">#include "<a class="code" href="BundleActions_8h.html">bundling/BundleActions.h</a>"</span> <a name="l00024"></a>00024 <span class="preprocessor">#include "<a class="code" href="BundleDaemon_8h.html">bundling/BundleDaemon.h</a>"</span> <a name="l00025"></a>00025 <span class="preprocessor">#include "<a class="code" href="TempBundle_8h.html">bundling/TempBundle.h</a>"</span> <a name="l00026"></a>00026 <span class="preprocessor">#include "<a class="code" href="Contact_8h.html">contacts/Contact.h</a>"</span> <a name="l00027"></a>00027 <span class="preprocessor">#include "<a class="code" href="ContactManager_8h.html">contacts/ContactManager.h</a>"</span> <a name="l00028"></a>00028 <span class="preprocessor">#include "<a class="code" href="contacts_2Link_8h.html">contacts/Link.h</a>"</span> <a name="l00029"></a>00029 <span class="preprocessor">#include "<a class="code" href="Registration_8h.html">reg/Registration.h</a>"</span> <a name="l00030"></a>00030 <span class="preprocessor">#include "<a class="code" href="Session_8h.html">session/Session.h</a>"</span> <a name="l00031"></a>00031 <a name="l00032"></a>00032 <span class="keyword">namespace </span>dtn { <a name="l00033"></a>00033 <a name="l00034"></a>00034 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00035"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#a1727dca6f2c6bc0cf3f8dc371e93568">00035</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#a1727dca6f2c6bc0cf3f8dc371e93568" title="Constructor -- protected since this class is never instantiated by itself.">TableBasedRouter::TableBasedRouter</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* classname, <a name="l00036"></a>00036 <span class="keyword">const</span> std::string& name) <a name="l00037"></a>00037 : <a class="code" href="classdtn_1_1BundleRouter.html" title="The BundleRouter is the main decision maker for all routing decisions related to...">BundleRouter</a>(classname, name), <a name="l00038"></a>00038 reception_cache_(std::string(logpath()) + <span class="stringliteral">"/reception_cache"</span>, <a name="l00039"></a>00039 1024) <span class="comment">// XXX/demmer configurable??</span> <a name="l00040"></a>00040 { <a name="l00041"></a>00041 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a> = <span class="keyword">new</span> <a class="code" href="classdtn_1_1RouteTable.html" title="Class that implements the routing table, implemented with an stl vector.">RouteTable</a>(name); <a name="l00042"></a>00042 } <a name="l00043"></a>00043 <a name="l00044"></a>00044 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00045"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#2b6549f8eac7612a408703026bd0f8d6">00045</a> TableBasedRouter::~TableBasedRouter() <a name="l00046"></a>00046 { <a name="l00047"></a>00047 <span class="keyword">delete</span> <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>; <a name="l00048"></a>00048 } <a name="l00049"></a>00049 <a name="l00050"></a>00050 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00051"></a>00051 <span class="keywordtype">void</span> <a name="l00052"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#118c2a374824c8ba1fcf2e7388c0af74">00052</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#118c2a374824c8ba1fcf2e7388c0af74" title="Add a route entry to the routing table.">TableBasedRouter::add_route</a>(<a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a> *entry) <a name="l00053"></a>00053 { <a name="l00054"></a>00054 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#f4563da3a4e78c4784a72e790a831469" title="Add a route entry.">add_entry</a>(entry); <a name="l00055"></a>00055 <a class="code" href="classdtn_1_1TableBasedRouter.html#d5d66b2ef80180677d4cf5093bcaf009" title="Update forwarding state due to changed routes.">handle_changed_routes</a>(); <a name="l00056"></a>00056 } <a name="l00057"></a>00057 <a name="l00058"></a>00058 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00059"></a>00059 <span class="keywordtype">void</span> <a name="l00060"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#5cbd7ee9f918a8c833bb0d82f0df9155">00060</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#5cbd7ee9f918a8c833bb0d82f0df9155" title="Remove matrhing route entry(s) from the routing table.">TableBasedRouter::del_route</a>(<span class="keyword">const</span> <a class="code" href="classdtn_1_1EndpointIDPattern.html" title="A Distinct class for endpoint patterns (i.e.">EndpointIDPattern</a>& dest) <a name="l00061"></a>00061 { <a name="l00062"></a>00062 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#f58eb380fc5a9cd31745d353d3f8baea" title="Remove all entries to the given endpoint id pattern.">del_entries</a>(dest); <a name="l00063"></a>00063 <a name="l00064"></a>00064 <span class="comment">// clear the reception cache when the routes change since we might</span> <a name="l00065"></a>00065 <span class="comment">// want to send a bundle back where it came from</span> <a name="l00066"></a>00066 <a class="code" href="classdtn_1_1TableBasedRouter.html#794be5288550f7294907e058fc21a98f" title="Cache to check for duplicates and to implement a simple RPF check.">reception_cache_</a>.<a class="code" href="classdtn_1_1BundleInfoCache.html#50298b94d5cc2c266164e2c75ff6b8b3" title="Flush the cache.">evict_all</a>(); <a name="l00067"></a>00067 <a name="l00068"></a>00068 <span class="comment">// XXX/demmer this should really call handle_changed_routes...</span> <a name="l00069"></a>00069 } <a name="l00070"></a>00070 <a name="l00071"></a>00071 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00072"></a>00072 <span class="keywordtype">void</span> <a name="l00073"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#d5d66b2ef80180677d4cf5093bcaf009">00073</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#d5d66b2ef80180677d4cf5093bcaf009" title="Update forwarding state due to changed routes.">TableBasedRouter::handle_changed_routes</a>() <a name="l00074"></a>00074 { <a name="l00075"></a>00075 <span class="comment">// clear the reception cache when the routes change since we might</span> <a name="l00076"></a>00076 <span class="comment">// want to send a bundle back where it came from</span> <a name="l00077"></a>00077 <a class="code" href="classdtn_1_1TableBasedRouter.html#794be5288550f7294907e058fc21a98f" title="Cache to check for duplicates and to implement a simple RPF check.">reception_cache_</a>.<a class="code" href="classdtn_1_1BundleInfoCache.html#50298b94d5cc2c266164e2c75ff6b8b3" title="Flush the cache.">evict_all</a>(); <a name="l00078"></a>00078 <a class="code" href="classdtn_1_1TableBasedRouter.html#3e5d2926a1b0cf5cabbef44eafd21bb7" title="Go through all known bundles in the system and try to re-route them.">reroute_all_bundles</a>(); <a name="l00079"></a>00079 <a class="code" href="classdtn_1_1TableBasedRouter.html#5a20afd32a3841641b60c8dab2c55986" title="Session management helper functions.">reroute_all_sessions</a>(); <a name="l00080"></a>00080 } <a name="l00081"></a>00081 <a name="l00082"></a>00082 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00083"></a>00083 <span class="keywordtype">void</span> <a name="l00084"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#0a41a70c82d3a58ec0fc044dbe99dfe9">00084</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#0a41a70c82d3a58ec0fc044dbe99dfe9" title="Event handler overridden from BundleRouter / BundleEventHandler that dispatches to...">TableBasedRouter::handle_event</a>(<a class="code" href="classdtn_1_1BundleEvent.html" title="Event base class.">BundleEvent</a>* event) <a name="l00085"></a>00085 { <a name="l00086"></a>00086 <a class="code" href="classdtn_1_1BundleEventHandler.html#ff1afd1aab4f62d6dfccfc855968206d" title="Dispatch the event by type code to one of the event-specific handler functions below...">dispatch_event</a>(event); <a name="l00087"></a>00087 } <a name="l00088"></a>00088 <a name="l00089"></a>00089 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00090"></a>00090 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* <a name="l00091"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#de9f9602a3734518769ac7a4bc324e79">00091</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#de9f9602a3734518769ac7a4bc324e79" title="Session management helper functions.">TableBasedRouter::get_session_for_bundle</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle) <a name="l00092"></a>00092 { <a name="l00093"></a>00093 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>() != 0) <a name="l00094"></a>00094 { <a name="l00095"></a>00095 log_debug(<span class="stringliteral">"get_session_for_bundle: bundle id %d is a subscription msg"</span>, <a name="l00096"></a>00096 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00097"></a>00097 <span class="keywordflow">return</span> NULL; <a name="l00098"></a>00098 } <a name="l00099"></a>00099 <a name="l00100"></a>00100 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>().<a class="code" href="classdtn_1_1SequenceID.html#41640a4837fab3c5ca5fce05f371bbd2" title="Typedefs and wrappers for the entry vector and iterators.">empty</a>() && <a name="l00101"></a>00101 bundle-><a class="code" href="classdtn_1_1Bundle.html#d483159c19f31132c5597de34c9ca409" title="Accessors.">obsoletes_id</a>().<a class="code" href="classdtn_1_1SequenceID.html#41640a4837fab3c5ca5fce05f371bbd2" title="Typedefs and wrappers for the entry vector and iterators.">empty</a>() && <a name="l00102"></a>00102 bundle-><a class="code" href="classdtn_1_1Bundle.html#9bdc5df0500ec9859132c917f48f7bb0" title="Accessors.">session_eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#3ed7639ed8794ea8045bb5d16128c5f5">length</a>() == 0) <a name="l00103"></a>00103 { <a name="l00104"></a>00104 log_debug(<span class="stringliteral">"get_session_for_bundle: bundle id %u not a session bundle"</span>, <a name="l00105"></a>00105 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00106"></a>00106 <span class="keywordflow">return</span> NULL; <a name="l00107"></a>00107 } <a name="l00108"></a>00108 <a name="l00109"></a>00109 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> session_eid = bundle-><a class="code" href="classdtn_1_1Bundle.html#9bdc5df0500ec9859132c917f48f7bb0" title="Accessors.">session_eid</a>(); <a name="l00110"></a>00110 <span class="keywordflow">if</span> (session_eid.<a class="code" href="classdtn_1_1EndpointID.html#3ed7639ed8794ea8045bb5d16128c5f5">length</a>() == 0) <a name="l00111"></a>00111 { <a name="l00112"></a>00112 session_eid.<a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(std::string(<span class="stringliteral">"dtn-unicast-session:"</span>) + <a name="l00113"></a>00113 bundle-><a class="code" href="classdtn_1_1Bundle.html#2dae8a97270a95799acf45d859eaf866" title="Accessors.">source</a>().<a class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>() + <a name="l00114"></a>00114 <span class="stringliteral">","</span> + <a name="l00115"></a>00115 bundle-><a class="code" href="classdtn_1_1Bundle.html#507241e8ac766e1900009ed6243e2aa3" title="Accessors.">dest</a>().<a class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>()); <a name="l00116"></a>00116 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(session_eid.<a class="code" href="classdtn_1_1EndpointID.html#bbf47839fe5cc8cb425af9a257a92ef5">valid</a>()); <a name="l00117"></a>00117 } <a name="l00118"></a>00118 <a name="l00119"></a>00119 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#100acfedb5536efcb57382347ca0a759">get_session</a>(session_eid); <a name="l00120"></a>00120 log_debug(<span class="stringliteral">"get_session_for_bundle: *%p *%p"</span>, bundle, session); <a name="l00121"></a>00121 <span class="keywordflow">return</span> session; <a name="l00122"></a>00122 } <a name="l00123"></a>00123 <a name="l00124"></a>00124 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00125"></a>00125 <span class="keywordtype">bool</span> <a name="l00126"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#c917dc5ba2a3e8d2c73adb3cad6033d3">00126</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#c917dc5ba2a3e8d2c73adb3cad6033d3" title="Session management helper functions.">TableBasedRouter::add_bundle_to_session</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle, <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session) <a name="l00127"></a>00127 { <a name="l00128"></a>00128 <span class="comment">// XXX/demmer is this the right deletion reason for obsoletes??</span> <a name="l00129"></a>00129 <span class="keyword">static</span> <a class="code" href="classdtn_1_1BundleProtocol.html#37b000d94172c06970bb8af32889f917" title="Bundle Status Report &quot;Reason Code&quot; flags.">BundleProtocol::status_report_reason_t</a> deletion_reason = <a name="l00130"></a>00130 <a class="code" href="classdtn_1_1BundleProtocol.html#37b000d94172c06970bb8af32889f9176e886c084e3e545573e435ef04760c1a">BundleProtocol::REASON_DEPLETED_STORAGE</a>; <a name="l00131"></a>00131 <a name="l00132"></a>00132 log_debug(<span class="stringliteral">"adding *%p to *%p"</span>, bundle, session); <a name="l00133"></a>00133 <a name="l00134"></a>00134 <span class="keywordflow">if</span> (! bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>().<a class="code" href="classdtn_1_1SequenceID.html#41640a4837fab3c5ca5fce05f371bbd2" title="Typedefs and wrappers for the entry vector and iterators.">empty</a>()) <a name="l00135"></a>00135 { <a name="l00136"></a>00136 oasys::ScopeLock l(session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#0d0c9f789f0f7f7d1cda3b4ecf32d2bc" title="Return the internal lock on this list.">lock</a>(), <a name="l00137"></a>00137 <span class="stringliteral">"TableBasedRouter::add_subscriber"</span>); <a name="l00138"></a>00138 <a class="code" href="classdtn_1_1BundleList.html#1d52b8d6bb7d8a07e5d4f5fc4b5b61d2" title="Type for an iterator, which just wraps an stl iterator.">BundleList::iterator</a> iter = session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#24cd371acd62f2f9725ff3f92b55badf" title="Iterator used to iterate through the list.">begin</a>(); <a name="l00139"></a>00139 <span class="keywordflow">while</span> (iter != session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#19f95941fe436d25ba49ae0b2d8bf2c1" title="Iterator used to mark the end of the list.">end</a>()) <a name="l00140"></a>00140 { <a name="l00141"></a>00141 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* old_bundle = *iter; <a name="l00142"></a>00142 ++iter; <span class="comment">// in case we remove the bundle from the list</span> <a name="l00143"></a>00143 <a name="l00144"></a>00144 <span class="comment">// make sure the old bundle has a sequence id</span> <a name="l00145"></a>00145 <span class="keywordflow">if</span> (old_bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>().<a class="code" href="classdtn_1_1SequenceID.html#41640a4837fab3c5ca5fce05f371bbd2" title="Typedefs and wrappers for the entry vector and iterators.">empty</a>()) { <a name="l00146"></a>00146 <span class="keywordflow">continue</span>; <a name="l00147"></a>00147 } <a name="l00148"></a>00148 <a name="l00149"></a>00149 <span class="comment">// first check if the newly arriving bundle causes an old one</span> <a name="l00150"></a>00150 <span class="comment">// to be obsolete</span> <a name="l00151"></a>00151 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#d483159c19f31132c5597de34c9ca409" title="Accessors.">obsoletes_id</a>() >= old_bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()) <a name="l00152"></a>00152 { <a name="l00153"></a>00153 log_debug(<span class="stringliteral">"*%p obsoletes *%p... removing old bundle"</span>, <a name="l00154"></a>00154 bundle, old_bundle); <a name="l00155"></a>00155 <a name="l00156"></a>00156 <span class="keywordtype">bool</span> ok = session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#b0171458e14d67307b74f98447062d68" title="Remove the given bundle from the list.">erase</a>(old_bundle); <a name="l00157"></a>00157 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(ok); <a name="l00158"></a>00158 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l00159"></a>00159 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleDeleteRequest.html" title="Event class for requestion deletion of a bundle.">BundleDeleteRequest</a>(old_bundle, deletion_reason)); <a name="l00160"></a>00160 <span class="keywordflow">continue</span>; <a name="l00161"></a>00161 } <a name="l00162"></a>00162 <a name="l00163"></a>00163 <span class="comment">// next check if the existing bundle obsoletes this one</span> <a name="l00164"></a>00164 <span class="keywordflow">if</span> (old_bundle-><a class="code" href="classdtn_1_1Bundle.html#d483159c19f31132c5597de34c9ca409" title="Accessors.">obsoletes_id</a>() >= bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()) <a name="l00165"></a>00165 { <a name="l00166"></a>00166 log_debug(<span class="stringliteral">"*%p obsoletes *%p... ignoring new arrival"</span>, <a name="l00167"></a>00167 old_bundle, bundle); <a name="l00168"></a>00168 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l00169"></a>00169 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleDeleteRequest.html" title="Event class for requestion deletion of a bundle.">BundleDeleteRequest</a>(bundle, deletion_reason)); <a name="l00170"></a>00170 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00171"></a>00171 } <a name="l00172"></a>00172 <a name="l00173"></a>00173 <span class="comment">// now check if the new and existing bundles have the same</span> <a name="l00174"></a>00174 <span class="comment">// sequence id, in which case we discard the new arrival as</span> <a name="l00175"></a>00175 <span class="comment">// well</span> <a name="l00176"></a>00176 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>() == old_bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()) <a name="l00177"></a>00177 { <a name="l00178"></a>00178 log_debug(<span class="stringliteral">"*%p and *%p have same sequence id... "</span> <a name="l00179"></a>00179 <span class="stringliteral">"ignoring new arrival"</span>, <a name="l00180"></a>00180 old_bundle, bundle); <a name="l00181"></a>00181 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l00182"></a>00182 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleDeleteRequest.html" title="Event class for requestion deletion of a bundle.">BundleDeleteRequest</a>(bundle, deletion_reason)); <a name="l00183"></a>00183 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00184"></a>00184 } <a name="l00185"></a>00185 <a name="l00186"></a>00186 log_debug(<span class="stringliteral">"compared *%p and *%p, nothing is obsoleted"</span>, <a name="l00187"></a>00187 old_bundle, bundle); <a name="l00188"></a>00188 } <a name="l00189"></a>00189 } <a name="l00190"></a>00190 <a name="l00191"></a>00191 session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#9f3efd0593739e89ed478fd4bbccd3e0" title="Add a new bundle to the back of the list.">push_back</a>(bundle); <a name="l00192"></a>00192 session-><a class="code" href="classdtn_1_1Session.html#bd799ea58a766a69bcfadf0f1ddef47f">sequence_id</a>()-><a class="code" href="classdtn_1_1SequenceID.html#87b23ed617eafd050b78bff11ddd5e73" title="Update the sequence id to include the max of all current entries and the new one...">update</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()); <a name="l00193"></a>00193 <a name="l00194"></a>00194 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00195"></a>00195 } <a name="l00196"></a>00196 <a name="l00197"></a>00197 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00198"></a>00198 <span class="keywordtype">void</span> <a name="l00199"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#f85d95a59fe4ae2217ed2c9b0c6cb662">00199</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#f85d95a59fe4ae2217ed2c9b0c6cb662" title="Event handlers.">TableBasedRouter::handle_bundle_received</a>(<a class="code" href="classdtn_1_1BundleReceivedEvent.html" title="Event class for new bundle arrivals.">BundleReceivedEvent</a>* event) <a name="l00200"></a>00200 { <a name="l00201"></a>00201 <span class="keywordtype">bool</span> should_route = <span class="keyword">true</span>; <a name="l00202"></a>00202 <a name="l00203"></a>00203 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = <span class="keyword">event</span>->bundleref_.object(); <a name="l00204"></a>00204 log_debug(<span class="stringliteral">"handle bundle received: *%p"</span>, bundle); <a name="l00205"></a>00205 <a name="l00206"></a>00206 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> remote_eid(<a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()); <a name="l00207"></a>00207 <a name="l00208"></a>00208 <span class="keywordflow">if</span> (event-><a class="code" href="classdtn_1_1BundleReceivedEvent.html#b851addef235e605411198e7bb3d9677" title="Link from which bundle was received, if applicable.">link_</a> != NULL) { <a name="l00209"></a>00209 remote_eid = <span class="keyword">event</span>->link_->remote_eid(); <a name="l00210"></a>00210 } <a name="l00211"></a>00211 <a name="l00212"></a>00212 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1TableBasedRouter.html#794be5288550f7294907e058fc21a98f" title="Cache to check for duplicates and to implement a simple RPF check.">reception_cache_</a>.<a class="code" href="classdtn_1_1BundleInfoCache.html#5c7594a62ad46e3b8eb9939092e2167c" title="Try to add the bundle to the cache.">add_entry</a>(bundle, remote_eid)) <a name="l00213"></a>00213 { <a name="l00214"></a>00214 log_info(<span class="stringliteral">"ignoring duplicate bundle: *%p"</span>, bundle); <a name="l00215"></a>00215 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l00216"></a>00216 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleDeleteRequest.html" title="Event class for requestion deletion of a bundle.">BundleDeleteRequest</a>(bundle, <a class="code" href="classdtn_1_1BundleProtocol.html#37b000d94172c06970bb8af32889f917eac137290a0338e66ed4a0c1cc09c2f2">BundleProtocol::REASON_NO_ADDTL_INFO</a>)); <a name="l00217"></a>00217 <span class="keywordflow">return</span>; <a name="l00218"></a>00218 } <a name="l00219"></a>00219 <a name="l00220"></a>00220 <span class="comment">// check if the bundle is part of a session, either because it has</span> <a name="l00221"></a>00221 <span class="comment">// a sequence id and/or obsoletes id, or because it has an</span> <a name="l00222"></a>00222 <span class="comment">// explicit session eid. if it is part of the session, add it to</span> <a name="l00223"></a>00223 <span class="comment">// the session list</span> <a name="l00224"></a>00224 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#de9f9602a3734518769ac7a4bc324e79" title="Session management helper functions.">get_session_for_bundle</a>(bundle); <a name="l00225"></a>00225 <span class="keywordflow">if</span> (session != NULL) <a name="l00226"></a>00226 { <a name="l00227"></a>00227 <span class="comment">// add the bundle to the session list, which checks whether </span> <a name="l00228"></a>00228 <span class="comment">// it obsoletes any existing bundles on the session, as well</span> <a name="l00229"></a>00229 <span class="comment">// as whether the bundle itself is obsolete on arrival.</span> <a name="l00230"></a>00230 should_route = <a class="code" href="classdtn_1_1TableBasedRouter.html#c917dc5ba2a3e8d2c73adb3cad6033d3" title="Session management helper functions.">add_bundle_to_session</a>(bundle, session); <a name="l00231"></a>00231 <span class="keywordflow">if</span> (! should_route) { <a name="l00232"></a>00232 log_debug(<span class="stringliteral">"session bundle %u is DOA"</span>, bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00233"></a>00233 <span class="keywordflow">return</span>; <span class="comment">// don't route it </span> <a name="l00234"></a>00234 } <a name="l00235"></a>00235 } <a name="l00236"></a>00236 <a name="l00237"></a>00237 <span class="comment">// check if the bundle is a session subscription management bundle</span> <a name="l00238"></a>00238 <span class="comment">// XXX/demmer maybe use a registration instead??</span> <a name="l00239"></a>00239 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>() != 0) { <a name="l00240"></a>00240 should_route = <a class="code" href="classdtn_1_1TableBasedRouter.html#14061ba8016fc61a7556d44b1323f36c" title="Session management helper functions.">handle_session_bundle</a>(event); <a name="l00241"></a>00241 } <a name="l00242"></a>00242 <a name="l00243"></a>00243 <span class="keywordflow">if</span> (should_route) { <a name="l00244"></a>00244 <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">route_bundle</a>(bundle); <a name="l00245"></a>00245 } <span class="keywordflow">else</span> { <a name="l00246"></a>00246 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l00247"></a>00247 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleDeleteRequest.html" title="Event class for requestion deletion of a bundle.">BundleDeleteRequest</a>(bundle, <a class="code" href="classdtn_1_1BundleProtocol.html#37b000d94172c06970bb8af32889f917eac137290a0338e66ed4a0c1cc09c2f2">BundleProtocol::REASON_NO_ADDTL_INFO</a>)); <a name="l00248"></a>00248 } <a name="l00249"></a>00249 } <a name="l00250"></a>00250 <a name="l00251"></a>00251 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00252"></a>00252 <span class="keywordtype">void</span> <a name="l00253"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#0999e77477c37efdf9709fd3f0928b05">00253</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#0999e77477c37efdf9709fd3f0928b05" title="Remove matching deferred transmission entries.">TableBasedRouter::remove_from_deferred</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle, <span class="keywordtype">int</span> actions) <a name="l00254"></a>00254 { <a name="l00255"></a>00255 <a class="code" href="classdtn_1_1ContactManager.html" title="A contact manager class.">ContactManager</a>* cm = BundleDaemon::instance()->contactmgr(); <a name="l00256"></a>00256 oasys::ScopeLock l(cm-><a class="code" href="classdtn_1_1ContactManager.html#6edebce9cf6080f854039f8df593cfec" title="Accessor for the ContactManager internal lock.">lock</a>(), <span class="stringliteral">"TableBasedRouter::remove_from_deferred"</span>); <a name="l00257"></a>00257 <a name="l00258"></a>00258 <span class="keyword">const</span> <a class="code" href="classdtn_1_1LinkSet.html" title="Set of links.">LinkSet</a>* links = cm-><a class="code" href="classdtn_1_1ContactManager.html#957c6cfac0575444e0a9a04a12708cf6" title="Return the list of links.">links</a>(); <a name="l00259"></a>00259 LinkSet::const_iterator iter; <a name="l00260"></a>00260 <span class="keywordflow">for</span> (iter = links->begin(); iter != links->end(); ++iter) { <a name="l00261"></a>00261 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link = *iter; <a name="l00262"></a>00262 <a name="l00263"></a>00263 <span class="comment">// a bundle might be deleted immediately after being loaded</span> <a name="l00264"></a>00264 <span class="comment">// from storage, meaning that remove_from_deferred is called</span> <a name="l00265"></a>00265 <span class="comment">// before the deferred list is created (since the link isn't</span> <a name="l00266"></a>00266 <span class="comment">// fully set up yet). so just skip the link if there's no</span> <a name="l00267"></a>00267 <span class="comment">// router info, and therefore no deferred list</span> <a name="l00268"></a>00268 <span class="keywordflow">if</span> (link->router_info() == NULL) { <a name="l00269"></a>00269 <span class="keywordflow">continue</span>; <a name="l00270"></a>00270 } <a name="l00271"></a>00271 <a name="l00272"></a>00272 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>* deferred = <a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6" title="Helper accessor to return the deferred queue for a link.">deferred_list</a>(link); <a name="l00273"></a>00273 <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a> <a class="code" href="dtncat_8c.html#71f51a2e8cbe9a53031fa72596edc09f">info</a>; <a name="l00274"></a>00274 <span class="keywordflow">if</span> (deferred-><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#8a87dfe205964e5eaee333c4b0c4f7c0" title="Check if the bundle is on the list.">find</a>(bundle, &info)) <a name="l00275"></a>00275 { <a name="l00276"></a>00276 <span class="keywordflow">if</span> (info.<a class="code" href="classdtn_1_1ForwardingInfo.html#c6e2356364eb63268f2a80db2287c26c" title="Accessors.">action</a>() & actions) { <a name="l00277"></a>00277 log_debug(<span class="stringliteral">"removing bundle *%p from link *%p deferred list"</span>, <a name="l00278"></a>00278 bundle.object(), (*iter).object()); <a name="l00279"></a>00279 deferred-><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#06552754bfa787fb9ce0361c9007041b" title="Remove the bundle and its associated forwarding info from the list.">del</a>(bundle); <a name="l00280"></a>00280 } <a name="l00281"></a>00281 } <a name="l00282"></a>00282 } <a name="l00283"></a>00283 } <a name="l00284"></a>00284 <a name="l00285"></a>00285 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00286"></a>00286 <span class="keywordtype">void</span> <a name="l00287"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#c021068d7b1e9802cc3507d6825ba245">00287</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#c021068d7b1e9802cc3507d6825ba245" title="Event handlers.">TableBasedRouter::handle_bundle_transmitted</a>(<a class="code" href="classdtn_1_1BundleTransmittedEvent.html" title="Event class for bundle or fragment transmission.">BundleTransmittedEvent</a>* event) <a name="l00288"></a>00288 { <a name="l00289"></a>00289 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle = <span class="keyword">event</span>->bundleref_; <a name="l00290"></a>00290 log_debug(<span class="stringliteral">"handle bundle transmitted: *%p"</span>, bundle.object()); <a name="l00291"></a>00291 <a name="l00292"></a>00292 <span class="comment">// if the bundle has a deferred single-copy transmission for</span> <a name="l00293"></a>00293 <span class="comment">// forwarding on any links, then remove the forwarding log entries</span> <a name="l00294"></a>00294 <a class="code" href="classdtn_1_1TableBasedRouter.html#0999e77477c37efdf9709fd3f0928b05" title="Remove matching deferred transmission entries.">remove_from_deferred</a>(bundle, <a class="code" href="classdtn_1_1ForwardingInfo.html#18ec95dc1b1b8a7e9df9873a0d9b59471efad47dbf6015f5e4458ac355eabbaa" title="Forward the bundle to only this next hop.">ForwardingInfo::FORWARD_ACTION</a>); <a name="l00295"></a>00295 <a name="l00296"></a>00296 <span class="comment">// check if the transmission means that we can send another bundle</span> <a name="l00297"></a>00297 <span class="comment">// on the link</span> <a name="l00298"></a>00298 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link = <span class="keyword">event</span>->contact_->link(); <a name="l00299"></a>00299 <a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97" title="Called when the next hop link is available for transmission (i.e.">check_next_hop</a>(link); <a name="l00300"></a>00300 } <a name="l00301"></a>00301 <a name="l00302"></a>00302 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00303"></a>00303 <span class="keywordtype">bool</span> <a name="l00304"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#feb96189b85d0035ad08874204bdc86b">00304</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#feb96189b85d0035ad08874204bdc86b" title="Hook to ask the router if the bundle can be deleted.">TableBasedRouter::can_delete_bundle</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle) <a name="l00305"></a>00305 { <a name="l00306"></a>00306 log_debug(<span class="stringliteral">"TableBasedRouter::can_delete_bundle: checking if we can delete *%p"</span>, <a name="l00307"></a>00307 bundle.object()); <a name="l00308"></a>00308 <a name="l00309"></a>00309 <span class="comment">// check if we haven't yet done anything with this bundle</span> <a name="l00310"></a>00310 <span class="keywordflow">if</span> (bundle->fwdlog()->get_count(<a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fad4222cd2abd08c71c5b5387cf23ca6193" title="Successfully transmitted.">ForwardingInfo::TRANSMITTED</a> | <a name="l00311"></a>00311 <a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fad6798e2dfb4df40155322b92d6e002fb4" title="Delivered to local registration.">ForwardingInfo::DELIVERED</a>) == 0) <a name="l00312"></a>00312 { <a name="l00313"></a>00313 log_debug(<span class="stringliteral">"TableBasedRouter::can_delete_bundle(%u): "</span> <a name="l00314"></a>00314 <span class="stringliteral">"not yet transmitted or delivered"</span>, <a name="l00315"></a>00315 bundle->bundleid()); <a name="l00316"></a>00316 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00317"></a>00317 } <a name="l00318"></a>00318 <a name="l00319"></a>00319 <span class="comment">// check if we have local custody</span> <a name="l00320"></a>00320 <span class="keywordflow">if</span> (bundle->local_custody()) { <a name="l00321"></a>00321 log_debug(<span class="stringliteral">"TableBasedRouter::can_delete_bundle(%u): "</span> <a name="l00322"></a>00322 <span class="stringliteral">"not deleting because we have custody"</span>, <a name="l00323"></a>00323 bundle->bundleid()); <a name="l00324"></a>00324 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00325"></a>00325 } <a name="l00326"></a>00326 <a name="l00327"></a>00327 <span class="comment">// check if the bundle is part of a session with subscribers</span> <a name="l00328"></a>00328 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#de9f9602a3734518769ac7a4bc324e79" title="Session management helper functions.">get_session_for_bundle</a>(bundle.object()); <a name="l00329"></a>00329 <span class="keywordflow">if</span> (session && !session-><a class="code" href="classdtn_1_1Session.html#f06e7f94d2ed1aeda7dafe18a2dd747e">subscribers</a>().empty()) <a name="l00330"></a>00330 { <a name="l00331"></a>00331 log_debug(<span class="stringliteral">"TableBasedRouter::can_delete_bundle(%u): "</span> <a name="l00332"></a>00332 <span class="stringliteral">"session has subscribers"</span>, <a name="l00333"></a>00333 bundle->bundleid()); <a name="l00334"></a>00334 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00335"></a>00335 } <a name="l00336"></a>00336 <a name="l00337"></a>00337 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00338"></a>00338 } <a name="l00339"></a>00339 <a name="l00340"></a>00340 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00341"></a>00341 <span class="keywordtype">void</span> <a name="l00342"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#469390b9ba77d858ed51d5d80176407e">00342</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#469390b9ba77d858ed51d5d80176407e" title="Hook to tell the router that the bundle should be deleted.">TableBasedRouter::delete_bundle</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle) <a name="l00343"></a>00343 { <a name="l00344"></a>00344 log_debug(<span class="stringliteral">"delete *%p"</span>, bundle.object()); <a name="l00345"></a>00345 <a name="l00346"></a>00346 <a class="code" href="classdtn_1_1TableBasedRouter.html#0999e77477c37efdf9709fd3f0928b05" title="Remove matching deferred transmission entries.">remove_from_deferred</a>(bundle, <a class="code" href="classdtn_1_1ForwardingInfo.html#59d23bb431328004d2c90a42e2b336d3" title="Convenience flag to specify any forwarding action for use in searching the log.">ForwardingInfo::ANY_ACTION</a>); <a name="l00347"></a>00347 <a name="l00348"></a>00348 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#de9f9602a3734518769ac7a4bc324e79" title="Session management helper functions.">get_session_for_bundle</a>(bundle.object()); <a name="l00349"></a>00349 <span class="keywordflow">if</span> (session) <a name="l00350"></a>00350 { <a name="l00351"></a>00351 <span class="keywordtype">bool</span> ok = session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#b0171458e14d67307b74f98447062d68" title="Remove the given bundle from the list.">erase</a>(bundle); <a name="l00352"></a>00352 (void)ok; <a name="l00353"></a>00353 <a name="l00354"></a>00354 log_debug(<span class="stringliteral">"delete_bundle: removing *%p from *%p: %s"</span>, <a name="l00355"></a>00355 bundle.object(), session, ok ? <span class="stringliteral">"success"</span> : <span class="stringliteral">"not in session list"</span>); <a name="l00356"></a>00356 <a name="l00357"></a>00357 <span class="comment">// XXX/demmer adjust sequence id for session??</span> <a name="l00358"></a>00358 } <a name="l00359"></a>00359 <a name="l00360"></a>00360 <a name="l00361"></a>00361 <span class="comment">// XXX/demmer clean up empty sessions?</span> <a name="l00362"></a>00362 } <a name="l00363"></a>00363 <a name="l00364"></a>00364 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00365"></a>00365 <span class="keywordtype">void</span> <a name="l00366"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#8cc4cee7d37567989384b3c70c33f938">00366</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#8cc4cee7d37567989384b3c70c33f938" title="Event handlers.">TableBasedRouter::handle_bundle_cancelled</a>(<a class="code" href="classdtn_1_1BundleSendCancelledEvent.html" title="Event class for succesful cancellation of a bundle send.">BundleSendCancelledEvent</a>* event) <a name="l00367"></a>00367 { <a name="l00368"></a>00368 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = <span class="keyword">event</span>->bundleref_.object(); <a name="l00369"></a>00369 log_debug(<span class="stringliteral">"handle bundle cancelled: *%p"</span>, bundle); <a name="l00370"></a>00370 <a name="l00371"></a>00371 <span class="comment">// if the bundle has expired, we don't want to reroute it.</span> <a name="l00372"></a>00372 <span class="comment">// XXX/demmer this might warrant a more general handling instead?</span> <a name="l00373"></a>00373 <span class="keywordflow">if</span> (!bundle-><a class="code" href="classdtn_1_1Bundle.html#b20ca8b6179e9d103e4239df6191ca61" title="Accessors.">expired</a>()) { <a name="l00374"></a>00374 <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">route_bundle</a>(bundle); <a name="l00375"></a>00375 } <a name="l00376"></a>00376 } <a name="l00377"></a>00377 <a name="l00378"></a>00378 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00379"></a>00379 <span class="keywordtype">void</span> <a name="l00380"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#7ffd58d58cac80337e17c53869d7f6dd">00380</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#7ffd58d58cac80337e17c53869d7f6dd" title="Event handlers.">TableBasedRouter::handle_route_add</a>(<a class="code" href="classdtn_1_1RouteAddEvent.html" title="Event class for route add events.">RouteAddEvent</a>* event) <a name="l00381"></a>00381 { <a name="l00382"></a>00382 <a class="code" href="classdtn_1_1TableBasedRouter.html#118c2a374824c8ba1fcf2e7388c0af74" title="Add a route entry to the routing table.">add_route</a>(event-><a class="code" href="classdtn_1_1RouteAddEvent.html#d8232b538e9a7e47a1ca281deb3090de" title="The route table entry to be added.">entry_</a>); <a name="l00383"></a>00383 } <a name="l00384"></a>00384 <a name="l00385"></a>00385 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00386"></a>00386 <span class="keywordtype">void</span> <a name="l00387"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#aeaa4b9e5557810958ac0e48768a0a28">00387</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#aeaa4b9e5557810958ac0e48768a0a28" title="Event handlers.">TableBasedRouter::handle_route_del</a>(<a class="code" href="classdtn_1_1RouteDelEvent.html" title="Event class for route delete events.">RouteDelEvent</a>* event) <a name="l00388"></a>00388 { <a name="l00389"></a>00389 <a class="code" href="classdtn_1_1TableBasedRouter.html#5cbd7ee9f918a8c833bb0d82f0df9155" title="Remove matrhing route entry(s) from the routing table.">del_route</a>(event-><a class="code" href="classdtn_1_1RouteDelEvent.html#06c9654845c46f06a4518895e990e733" title="The destination eid to be removed.">dest_</a>); <a name="l00390"></a>00390 } <a name="l00391"></a>00391 <a name="l00392"></a>00392 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00393"></a>00393 <span class="keywordtype">void</span> <a name="l00394"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#822c4f8e15dab2c379dad968431c1f27">00394</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#822c4f8e15dab2c379dad968431c1f27" title="When new links are added or opened, and if we&#39;re configured to add nexthop routes...">TableBasedRouter::add_nexthop_route</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link) <a name="l00395"></a>00395 { <a name="l00396"></a>00396 <span class="comment">// If we're configured to do so, create a route entry for the eid</span> <a name="l00397"></a>00397 <span class="comment">// specified by the link when it connected, using the</span> <a name="l00398"></a>00398 <span class="comment">// scheme-specific code to transform the URI to wildcard</span> <a name="l00399"></a>00399 <span class="comment">// the service part</span> <a name="l00400"></a>00400 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> eid = link->remote_eid(); <a name="l00401"></a>00401 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1BundleRouter.html#344d85ef64a884adf9fb173a82674cca" title="Config variables.">config_</a>.<a class="code" href="structdtn_1_1BundleRouter_1_1Config.html#55da03509e99dfeb6918d9114f4c9773" title="Whether or not to add routes for nexthop links that know the remote endpoint id (default...">add_nexthop_routes_</a> && eid != <a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()) <a name="l00402"></a>00402 { <a name="l00403"></a>00403 <a class="code" href="classdtn_1_1EndpointIDPattern.html" title="A Distinct class for endpoint patterns (i.e.">EndpointIDPattern</a> eid_pattern(link->remote_eid()); <a name="l00404"></a>00404 <a name="l00405"></a>00405 <span class="comment">// attempt to build a route pattern from link's remote_eid</span> <a name="l00406"></a>00406 <span class="keywordflow">if</span> (!eid_pattern.append_service_wildcard()) <a name="l00407"></a>00407 <span class="comment">// else assign remote_eid as-is</span> <a name="l00408"></a>00408 eid_pattern.assign(link->remote_eid()); <a name="l00409"></a>00409 <a name="l00410"></a>00410 <span class="comment">// XXX/demmer this shouldn't call get_matching but instead</span> <a name="l00411"></a>00411 <span class="comment">// there should be a RouteTable::lookup or contains() method</span> <a name="l00412"></a>00412 <span class="comment">// to find the entry</span> <a name="l00413"></a>00413 <a class="code" href="classdtn_1_1RouteEntryVec.html" title="Class for a vector of route entries.">RouteEntryVec</a> ignored; <a name="l00414"></a>00414 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#dceb882f843c17db3afd73521bc78c6d" title="Fill in the entry_vec with the list of all entries whose patterns match the given...">get_matching</a>(eid_pattern, link, &ignored) == 0) { <a name="l00415"></a>00415 <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a> *entry = <span class="keyword">new</span> <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>(eid_pattern, link); <a name="l00416"></a>00416 entry-><a class="code" href="classdtn_1_1RouteEntry.html#a9dce0a2ce16974778c61c7d559056bc" title="Setters.">set_action</a>(<a class="code" href="classdtn_1_1ForwardingInfo.html#18ec95dc1b1b8a7e9df9873a0d9b59471efad47dbf6015f5e4458ac355eabbaa" title="Forward the bundle to only this next hop.">ForwardingInfo::FORWARD_ACTION</a>); <a name="l00417"></a>00417 <a class="code" href="classdtn_1_1TableBasedRouter.html#118c2a374824c8ba1fcf2e7388c0af74" title="Add a route entry to the routing table.">add_route</a>(entry); <a name="l00418"></a>00418 } <a name="l00419"></a>00419 } <a name="l00420"></a>00420 } <a name="l00421"></a>00421 <a name="l00422"></a>00422 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00423"></a>00423 <span class="keywordtype">bool</span> <a name="l00424"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#08961b48157a280be9cb160158903a82">00424</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#08961b48157a280be9cb160158903a82" title="Check if the bundle should be forwarded to the given next hop.">TableBasedRouter::should_fwd</a>(<span class="keyword">const</span> <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle, <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>* route) <a name="l00425"></a>00425 { <a name="l00426"></a>00426 <span class="keywordflow">if</span> (route == NULL) <a name="l00427"></a>00427 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00428"></a>00428 <a name="l00429"></a>00429 <span class="comment">// simple RPF check -- if the bundle was received from the given</span> <a name="l00430"></a>00430 <span class="comment">// node, then don't send it back as long as the entry is still in</span> <a name="l00431"></a>00431 <span class="comment">// the reception cache (meaning our routes haven't changed).</span> <a name="l00432"></a>00432 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> prevhop; <a name="l00433"></a>00433 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1TableBasedRouter.html#794be5288550f7294907e058fc21a98f" title="Cache to check for duplicates and to implement a simple RPF check.">reception_cache_</a>.<a class="code" href="classdtn_1_1BundleInfoCache.html#ebcfd7dc9e1e14a37e53713fc7f6259e" title="Check if the given bundle is in the cache, returning the EID of the node from which...">lookup</a>(bundle, &prevhop)) <a name="l00434"></a>00434 { <a name="l00435"></a>00435 <span class="keywordflow">if</span> (prevhop == route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>()->remote_eid() && <a name="l00436"></a>00436 prevhop != <a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()) <a name="l00437"></a>00437 { <a name="l00438"></a>00438 log_debug(<span class="stringliteral">"should_fwd bundle %d: "</span> <a name="l00439"></a>00439 <span class="stringliteral">"skip %s since bundle arrived from the same node"</span>, <a name="l00440"></a>00440 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>(), route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>()->name()); <a name="l00441"></a>00441 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00442"></a>00442 } <a name="l00443"></a>00443 } <a name="l00444"></a>00444 <a name="l00445"></a>00445 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1BundleRouter.html#b30e99f427cc0526fce08b77e0ae95c7" title="Check if the bundle should be forwarded to the given next hop.">BundleRouter::should_fwd</a>(bundle, route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>(), route-><a class="code" href="classdtn_1_1RouteEntry.html#0fe979e29165c5bdad1a126f1a0fb04f" title="Accessors.">action</a>()); <a name="l00446"></a>00446 } <a name="l00447"></a>00447 <a name="l00448"></a>00448 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00449"></a>00449 <span class="keywordtype">void</span> <a name="l00450"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#898f2c517d6c8b0635c2ac19a5c3425a">00450</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#898f2c517d6c8b0635c2ac19a5c3425a" title="Event handlers.">TableBasedRouter::handle_contact_up</a>(<a class="code" href="classdtn_1_1ContactUpEvent.html" title="Event class for contact up events.">ContactUpEvent</a>* event) <a name="l00451"></a>00451 { <a name="l00452"></a>00452 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <span class="keyword">event</span>->contact_->link(); <a name="l00453"></a>00453 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00454"></a>00454 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00455"></a>00455 <a name="l00456"></a>00456 <span class="keywordflow">if</span> (! link->isopen()) { <a name="l00457"></a>00457 log_err(<span class="stringliteral">"contact up(*%p): event delivered but link not open"</span>, <a name="l00458"></a>00458 link.object()); <a name="l00459"></a>00459 } <a name="l00460"></a>00460 <a name="l00461"></a>00461 <a class="code" href="classdtn_1_1TableBasedRouter.html#822c4f8e15dab2c379dad968431c1f27" title="When new links are added or opened, and if we&#39;re configured to add nexthop routes...">add_nexthop_route</a>(link); <a name="l00462"></a>00462 <a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97" title="Called when the next hop link is available for transmission (i.e.">check_next_hop</a>(link); <a name="l00463"></a>00463 <a name="l00464"></a>00464 <span class="comment">// check if there's a pending reroute timer on the link, and if</span> <a name="l00465"></a>00465 <span class="comment">// so, cancel it.</span> <a name="l00466"></a>00466 <span class="comment">// </span> <a name="l00467"></a>00467 <span class="comment">// note that there's a possibility that a link just bounces</span> <a name="l00468"></a>00468 <span class="comment">// between up and down states but can't ever really send a bundle</span> <a name="l00469"></a>00469 <span class="comment">// (or part of one), which we don't handle here since we can't</span> <a name="l00470"></a>00470 <span class="comment">// distinguish that case from one in which the CL is actually</span> <a name="l00471"></a>00471 <span class="comment">// sending data, just taking a long time to do so.</span> <a name="l00472"></a>00472 <a name="l00473"></a>00473 RerouteTimerMap::iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.find(link->name_str()); <a name="l00474"></a>00474 <span class="keywordflow">if</span> (iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.end()) { <a name="l00475"></a>00475 log_debug(<span class="stringliteral">"link %s reopened, cancelling reroute timer"</span>, link->name()); <a name="l00476"></a>00476 <a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html" title="Timer class used to cancel transmission on down links after waiting for them to potentially...">RerouteTimer</a>* t = iter->second; <a name="l00477"></a>00477 <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.erase(iter); <a name="l00478"></a>00478 t->cancel(); <a name="l00479"></a>00479 } <a name="l00480"></a>00480 } <a name="l00481"></a>00481 <a name="l00482"></a>00482 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00483"></a>00483 <span class="keywordtype">void</span> <a name="l00484"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#5b9a452a306adc7f97c998f3e7c585e3">00484</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#5b9a452a306adc7f97c998f3e7c585e3" title="Event handlers.">TableBasedRouter::handle_contact_down</a>(<a class="code" href="classdtn_1_1ContactDownEvent.html" title="Event class for contact down events.">ContactDownEvent</a>* event) <a name="l00485"></a>00485 { <a name="l00486"></a>00486 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <span class="keyword">event</span>->contact_->link(); <a name="l00487"></a>00487 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00488"></a>00488 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00489"></a>00489 <a name="l00490"></a>00490 <span class="comment">// if there are any bundles queued on the link when it goes down,</span> <a name="l00491"></a>00491 <span class="comment">// schedule a timer to cancel those transmissions and reroute the</span> <a name="l00492"></a>00492 <span class="comment">// bundles in case the link takes too long to come back up</span> <a name="l00493"></a>00493 <a name="l00494"></a>00494 <span class="keywordtype">size_t</span> num_queued = link->queue()->size(); <a name="l00495"></a>00495 <span class="keywordflow">if</span> (num_queued != 0) { <a name="l00496"></a>00496 RerouteTimerMap::iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.find(link->name_str()); <a name="l00497"></a>00497 <span class="keywordflow">if</span> (iter == <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.end()) { <a name="l00498"></a>00498 log_debug(<span class="stringliteral">"link %s went down with %zu bundles queued, "</span> <a name="l00499"></a>00499 <span class="stringliteral">"scheduling reroute timer in %u seconds"</span>, <a name="l00500"></a>00500 link->name(), num_queued, <a name="l00501"></a>00501 link->params().potential_downtime_); <a name="l00502"></a>00502 <a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html" title="Timer class used to cancel transmission on down links after waiting for them to potentially...">RerouteTimer</a>* t = <span class="keyword">new</span> <a class="code" href="classdtn_1_1TableBasedRouter.html#e76c969f4f466488fef519f992eef9e6">RerouteTimer</a>(<span class="keyword">this</span>, link); <a name="l00503"></a>00503 t->schedule_in(link->params().potential_downtime_ * 1000); <a name="l00504"></a>00504 <a name="l00505"></a>00505 <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>[link->name_str()] = t; <a name="l00506"></a>00506 } <a name="l00507"></a>00507 } <a name="l00508"></a>00508 } <a name="l00509"></a>00509 <a name="l00510"></a>00510 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00511"></a>00511 <span class="keywordtype">void</span> <a name="l00512"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html#9cb081861b3450eb7ebde4c72525cc52">00512</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html#9cb081861b3450eb7ebde4c72525cc52">TableBasedRouter::RerouteTimer::timeout</a>(<span class="keyword">const</span> <span class="keyword">struct</span> timeval& now) <a name="l00513"></a>00513 { <a name="l00514"></a>00514 (void)now; <a name="l00515"></a>00515 <a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html#ec9285836030a97c1f4deeda5c6f0ec7">router_</a>-><a class="code" href="classdtn_1_1TableBasedRouter.html#7ea4067686f50b1656df26c896aea369" title="Helper function for rerouting.">reroute_bundles</a>(<a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html#99b1577ad6fad4e6dcd98f93c09efaa5">link_</a>); <a name="l00516"></a>00516 } <a name="l00517"></a>00517 <a name="l00518"></a>00518 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00519"></a>00519 <span class="keywordtype">void</span> <a name="l00520"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#7ea4067686f50b1656df26c896aea369">00520</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#7ea4067686f50b1656df26c896aea369" title="Helper function for rerouting.">TableBasedRouter::reroute_bundles</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link) <a name="l00521"></a>00521 { <a name="l00522"></a>00522 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00523"></a>00523 <a name="l00524"></a>00524 <span class="comment">// if the reroute timer fires, the link should be down and there</span> <a name="l00525"></a>00525 <span class="comment">// should be at least one bundle queued on it.</span> <a name="l00526"></a>00526 <span class="keywordflow">if</span> (link->state() != <a class="code" href="classdtn_1_1Link.html#1bf2479a21276737f73204a3c46508a3fcb80aea04644bdc565b13fa371b2e1e" title="The link is closed and not able to be opened currently.">Link::UNAVAILABLE</a>) { <a name="l00527"></a>00527 log_warn(<span class="stringliteral">"reroute timer fired but link *%p state is %s, not UNAVAILABLE"</span>, <a name="l00528"></a>00528 link.object(), <a class="code" href="classdtn_1_1Link.html#9681a1ea52ef3c5db6dcf37b04e5c280" title="Convert a link state into a string.">Link::state_to_str</a>(link->state())); <a name="l00529"></a>00529 <span class="keywordflow">return</span>; <a name="l00530"></a>00530 } <a name="l00531"></a>00531 <a name="l00532"></a>00532 log_debug(<span class="stringliteral">"reroute timer fired -- cancelling %zu bundles on link *%p"</span>, <a name="l00533"></a>00533 link->queue()->size(), link.object()); <a name="l00534"></a>00534 <a name="l00535"></a>00535 <span class="comment">// cancel the queued transmissions and rely on the</span> <a name="l00536"></a>00536 <span class="comment">// BundleSendCancelledEvent handler to actually reroute the</span> <a name="l00537"></a>00537 <span class="comment">// bundles, being careful when iterating through the lists to</span> <a name="l00538"></a>00538 <span class="comment">// avoid STL memory clobbering since cancel_bundle removes from</span> <a name="l00539"></a>00539 <span class="comment">// the list</span> <a name="l00540"></a>00540 oasys::ScopeLock l(link->queue()->lock(), <a name="l00541"></a>00541 <span class="stringliteral">"TableBasedRouter::reroute_bundles"</span>); <a name="l00542"></a>00542 <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a> bundle(<span class="stringliteral">"TableBasedRouter::reroute_bundles"</span>); <a name="l00543"></a>00543 <span class="keywordflow">while</span> (! link->queue()->empty()) { <a name="l00544"></a>00544 bundle = link->queue()->front(); <a name="l00545"></a>00545 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#3835034086b8a07e5a767fa028104830" title="Attempt to cancel transmission of a bundle on the given link.">cancel_bundle</a>(bundle.object(), link); <a name="l00546"></a>00546 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(! bundle->is_queued_on(link->queue())); <a name="l00547"></a>00547 } <a name="l00548"></a>00548 <a name="l00549"></a>00549 <span class="comment">// there should never have been any in flight since the link is</span> <a name="l00550"></a>00550 <span class="comment">// unavailable</span> <a name="l00551"></a>00551 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link->inflight()->empty()); <a name="l00552"></a>00552 } <a name="l00553"></a>00553 <a name="l00554"></a>00554 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00555"></a>00555 <span class="keywordtype">void</span> <a name="l00556"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#32d765a2b27a3e41273884bf521a9122">00556</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#32d765a2b27a3e41273884bf521a9122" title="Event handlers.">TableBasedRouter::handle_link_available</a>(<a class="code" href="classdtn_1_1LinkAvailableEvent.html" title="Event class for link available events.">LinkAvailableEvent</a>* event) <a name="l00557"></a>00557 { <a name="l00558"></a>00558 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <span class="keyword">event</span>->link_; <a name="l00559"></a>00559 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00560"></a>00560 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00561"></a>00561 <a name="l00562"></a>00562 <span class="comment">// if it is a discovered link, we typically open it</span> <a name="l00563"></a>00563 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1BundleRouter.html#344d85ef64a884adf9fb173a82674cca" title="Config variables.">config_</a>.<a class="code" href="structdtn_1_1BundleRouter_1_1Config.html#45c5f4f756fc55c7632ca287b8e79258" title="Whether or not to open discovered opportunistic links when they become available...">open_discovered_links_</a> && <a name="l00564"></a>00564 !link->isopen() && <a name="l00565"></a>00565 link->type() == <a class="code" href="classdtn_1_1Link.html#a93653796d33692c67c415afd1edf61e692792332b57aa903a769cb33e3d366b" title="The link may or may not be available, based on uncontrollable factors.">Link::OPPORTUNISTIC</a> && <a name="l00566"></a>00566 <span class="keyword">event</span>->reason_ == <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7648efe2b249ca6cd507125d819392b8d" title="Dynamically discovered link.">ContactEvent::DISCOVERY</a>) <a name="l00567"></a>00567 { <a name="l00568"></a>00568 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#0cb4ef96c172a1943d32d19747a00438" title="Open a link for bundle transmission.">open_link</a>(link); <a name="l00569"></a>00569 } <a name="l00570"></a>00570 <a name="l00571"></a>00571 <span class="comment">// check if there's anything to be forwarded to the link</span> <a name="l00572"></a>00572 <a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97" title="Called when the next hop link is available for transmission (i.e.">check_next_hop</a>(link); <a name="l00573"></a>00573 } <a name="l00574"></a>00574 <a name="l00575"></a>00575 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00576"></a>00576 <span class="keywordtype">void</span> <a name="l00577"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#15d6e91c5362005ef5f5ee2cc9b667b8">00577</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#15d6e91c5362005ef5f5ee2cc9b667b8" title="Event handlers.">TableBasedRouter::handle_link_created</a>(<a class="code" href="classdtn_1_1LinkCreatedEvent.html" title="Event class for link creation events.">LinkCreatedEvent</a>* event) <a name="l00578"></a>00578 { <a name="l00579"></a>00579 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <span class="keyword">event</span>->link_; <a name="l00580"></a>00580 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00581"></a>00581 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00582"></a>00582 <a name="l00583"></a>00583 link->set_router_info(<span class="keyword">new</span> <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>(logpath(), link)); <a name="l00584"></a>00584 <a name="l00585"></a>00585 <a class="code" href="classdtn_1_1TableBasedRouter.html#822c4f8e15dab2c379dad968431c1f27" title="When new links are added or opened, and if we&#39;re configured to add nexthop routes...">add_nexthop_route</a>(link); <a name="l00586"></a>00586 } <a name="l00587"></a>00587 <a name="l00588"></a>00588 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00589"></a>00589 <span class="keywordtype">void</span> <a name="l00590"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#f18906e5ecdbe1dc6ff76b3d74bc41b0">00590</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#f18906e5ecdbe1dc6ff76b3d74bc41b0" title="Event handlers.">TableBasedRouter::handle_link_deleted</a>(<a class="code" href="classdtn_1_1LinkDeletedEvent.html" title="Event class for link deletion events.">LinkDeletedEvent</a>* event) <a name="l00591"></a>00591 { <a name="l00592"></a>00592 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <span class="keyword">event</span>->link_; <a name="l00593"></a>00593 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00594"></a>00594 <a name="l00595"></a>00595 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#db642a8b6ce784847ba7fa7e633e9cc9" title="Remove all entries that rely on the given next_hop link.">del_entries_for_nexthop</a>(link); <a name="l00596"></a>00596 <a name="l00597"></a>00597 RerouteTimerMap::iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.find(link->name_str()); <a name="l00598"></a>00598 <span class="keywordflow">if</span> (iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.end()) { <a name="l00599"></a>00599 log_debug(<span class="stringliteral">"link %s deleted, cancelling reroute timer"</span>, link->name()); <a name="l00600"></a>00600 <a class="code" href="classdtn_1_1TableBasedRouter_1_1RerouteTimer.html" title="Timer class used to cancel transmission on down links after waiting for them to potentially...">RerouteTimer</a>* t = iter->second; <a name="l00601"></a>00601 <a class="code" href="classdtn_1_1TableBasedRouter.html#601cf75bb9ad55256211e63b3d34b4d9">reroute_timers_</a>.erase(iter); <a name="l00602"></a>00602 t->cancel(); <a name="l00603"></a>00603 } <a name="l00604"></a>00604 } <a name="l00605"></a>00605 <a name="l00606"></a>00606 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00607"></a>00607 <span class="keywordtype">void</span> <a name="l00608"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#4fec130df59945e730febe93bf5b9372">00608</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#4fec130df59945e730febe93bf5b9372" title="Event handlers.">TableBasedRouter::handle_custody_timeout</a>(<a class="code" href="classdtn_1_1CustodyTimeoutEvent.html" title="Event class for custody transfer timeout events.">CustodyTimeoutEvent</a>* event) <a name="l00609"></a>00609 { <a name="l00610"></a>00610 <span class="comment">// the bundle daemon should have recorded a new entry in the</span> <a name="l00611"></a>00611 <span class="comment">// forwarding log for the given link to note that custody transfer</span> <a name="l00612"></a>00612 <span class="comment">// timed out, and of course the bundle should still be in the</span> <a name="l00613"></a>00613 <span class="comment">// pending list.</span> <a name="l00614"></a>00614 <span class="comment">//</span> <a name="l00615"></a>00615 <span class="comment">// therefore, trying again to forward the bundle should match</span> <a name="l00616"></a>00616 <span class="comment">// either the previous link or any other route</span> <a name="l00617"></a>00617 <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">route_bundle</a>(event-><a class="code" href="classdtn_1_1CustodyTimeoutEvent.html#1f5fe801718936a3f70ee7b3ae410323" title="The link it was sent on.">bundle_</a>.object()); <a name="l00618"></a>00618 } <a name="l00619"></a>00619 <a name="l00620"></a>00620 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00621"></a>00621 <span class="keywordtype">void</span> <a name="l00622"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#c7e05bea7fada765cb85bc589e8fe9ab">00622</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#c7e05bea7fada765cb85bc589e8fe9ab" title="Dump the routing state.">TableBasedRouter::get_routing_state</a>(oasys::StringBuffer* <a class="code" href="num2sdnv_8c.html#a81cdcc7ff6987bc85c073253e32715f">buf</a>) <a name="l00623"></a>00623 { <a name="l00624"></a>00624 buf->appendf(<span class="stringliteral">"Route table for %s router:\n\n"</span>, <a class="code" href="classdtn_1_1BundleRouter.html#6e25e98eb6d3a10c75aecd7b7d89e253" title="Name of this particular router.">name_</a>.c_str()); <a name="l00625"></a>00625 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#410e143edbfa9e818b64e005b1aa5169" title="Dump a string representation of the routing table.">dump</a>(buf); <a name="l00626"></a>00626 <a name="l00627"></a>00627 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#21ce4ace49ca5a60eda8f91d51d08fc8">empty</a>()) <a name="l00628"></a>00628 { <a name="l00629"></a>00629 buf->appendf(<span class="stringliteral">"Session table (%zu sessions):\n"</span>, <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#7878235ba9b30c17658a5fb98255d26f">size</a>()); <a name="l00630"></a>00630 <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#9c7d77b014c1de42e6e827924e5835ad">dump</a>(buf); <a name="l00631"></a>00631 buf->appendf(<span class="stringliteral">"\n"</span>); <a name="l00632"></a>00632 } <a name="l00633"></a>00633 <a name="l00634"></a>00634 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.empty()) <a name="l00635"></a>00635 { <a name="l00636"></a>00636 buf->appendf(<span class="stringliteral">"Session custodians (%zu registrations):\n"</span>, <a name="l00637"></a>00637 <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.size()); <a name="l00638"></a>00638 <a name="l00639"></a>00639 <span class="keywordflow">for</span> (RegistrationList::iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.begin(); <a name="l00640"></a>00640 iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.end(); ++iter) <a name="l00641"></a>00641 { <a name="l00642"></a>00642 buf->appendf(<span class="stringliteral">" *%p\n"</span>, *iter); <a name="l00643"></a>00643 } <a name="l00644"></a>00644 buf->appendf(<span class="stringliteral">"\n"</span>); <a name="l00645"></a>00645 } <a name="l00646"></a>00646 } <a name="l00647"></a>00647 <a name="l00648"></a>00648 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00649"></a>00649 <span class="keywordtype">void</span> <a name="l00650"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#b84236fc3f6862121bb83088b2e35d42">00650</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#b84236fc3f6862121bb83088b2e35d42" title="Get a tcl version of the routing state.">TableBasedRouter::tcl_dump_state</a>(oasys::StringBuffer* <a class="code" href="num2sdnv_8c.html#a81cdcc7ff6987bc85c073253e32715f">buf</a>) <a name="l00651"></a>00651 { <a name="l00652"></a>00652 oasys::ScopeLock l(<a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#af649a3531d46d38066fefa3ec9fdc14" title="Accessor for the RouteTable internal lock.">lock</a>(), <a name="l00653"></a>00653 <span class="stringliteral">"TableBasedRouter::tcl_dump_state"</span>); <a name="l00654"></a>00654 <a name="l00655"></a>00655 RouteEntryVec::const_iterator iter; <a name="l00656"></a>00656 <span class="keywordflow">for</span> (iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#581c0578208d828885d211e0ab8381fd" title="Return the routing table.">route_table</a>()->begin(); <a name="l00657"></a>00657 iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#581c0578208d828885d211e0ab8381fd" title="Return the routing table.">route_table</a>()->end(); ++iter) <a name="l00658"></a>00658 { <a name="l00659"></a>00659 <span class="keyword">const</span> <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>* e = *iter; <a name="l00660"></a>00660 buf->appendf(<span class="stringliteral">" {%s %s source_eid %s priority %d} "</span>, <a name="l00661"></a>00661 e-><a class="code" href="classdtn_1_1RouteEntry.html#70826ec32537a2f6b08c8359d59a105d" title="Accessors.">dest_pattern</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), <a name="l00662"></a>00662 e-><a class="code" href="classdtn_1_1RouteEntry.html#41c79b5f1b69681a2ae73dfdf064138f" title="Accessors.">next_hop_str</a>().c_str(), <a name="l00663"></a>00663 e-><a class="code" href="classdtn_1_1RouteEntry.html#ed80ef80b6cfb5c19f128fe346090707" title="Accessors.">source_pattern</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), <a name="l00664"></a>00664 e-><a class="code" href="classdtn_1_1RouteEntry.html#3d1340ea310acb204795bd634893c8f0" title="Accessors.">priority</a>()); <a name="l00665"></a>00665 } <a name="l00666"></a>00666 } <a name="l00667"></a>00667 <a name="l00668"></a>00668 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00669"></a>00669 <span class="keywordtype">bool</span> <a name="l00670"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#4bac86cb57a6b1b7350f8471d890bb2f">00670</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#4bac86cb57a6b1b7350f8471d890bb2f" title="Try to forward a bundle to a next hop route.">TableBasedRouter::fwd_to_nexthop</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle, <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>* route) <a name="l00671"></a>00671 { <a name="l00672"></a>00672 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link = route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>(); <a name="l00673"></a>00673 <a name="l00674"></a>00674 <span class="comment">// if the link is available and not open, open it</span> <a name="l00675"></a>00675 <span class="keywordflow">if</span> (link->isavailable() && (!link->isopen()) && (!link->isopening())) { <a name="l00676"></a>00676 log_debug(<span class="stringliteral">"opening *%p because a message is intended for it"</span>, <a name="l00677"></a>00677 link.object()); <a name="l00678"></a>00678 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#0cb4ef96c172a1943d32d19747a00438" title="Open a link for bundle transmission.">open_link</a>(link); <a name="l00679"></a>00679 } <a name="l00680"></a>00680 <a name="l00681"></a>00681 <span class="comment">// XXX/demmer maybe this should queue_bundle immediately instead</span> <a name="l00682"></a>00682 <span class="comment">// of waiting for the first contact_up event??</span> <a name="l00683"></a>00683 <a name="l00684"></a>00684 <span class="comment">// if the link is open and has space in the queue, then queue the</span> <a name="l00685"></a>00685 <span class="comment">// bundle for transmission there</span> <a name="l00686"></a>00686 <span class="keywordflow">if</span> (link->isopen() && !link->queue_is_full()) { <a name="l00687"></a>00687 log_debug(<span class="stringliteral">"queuing *%p on *%p"</span>, bundle, link.object()); <a name="l00688"></a>00688 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#7a75826fd1b4515b9d9aa2b98acbde68" title="Queue the bundle for transmission on the given link.">queue_bundle</a>(bundle, link, route-><a class="code" href="classdtn_1_1RouteEntry.html#0fe979e29165c5bdad1a126f1a0fb04f" title="Accessors.">action</a>(), <a name="l00689"></a>00689 route-><a class="code" href="classdtn_1_1RouteEntry.html#846eaa2c3a7324662a346c6bc0e5a69b" title="Accessors.">custody_spec</a>()); <a name="l00690"></a>00690 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00691"></a>00691 } <a name="l00692"></a>00692 <a name="l00693"></a>00693 <span class="comment">// otherwise we can't send the bundle now, so put it on the link's</span> <a name="l00694"></a>00694 <span class="comment">// deferred list and log reason why we can't forward it</span> <a name="l00695"></a>00695 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>* deferred = <a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6" title="Helper accessor to return the deferred queue for a link.">deferred_list</a>(link); <a name="l00696"></a>00696 <span class="keywordflow">if</span> (! bundle-><a class="code" href="classdtn_1_1Bundle.html#13d641b5d6a6617a8c37ab28a0a6c843" title="Return true if the bundle is on the given list.">is_queued_on</a>(deferred-><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#90707a646fce8e0af35b99509b14424b" title="Accessor for the bundle list.">list</a>())) { <a name="l00697"></a>00697 <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a> bref(bundle, <span class="stringliteral">"TableBasedRouter::fwd_to_nexthop"</span>); <a name="l00698"></a>00698 <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a> <a class="code" href="dtncat_8c.html#71f51a2e8cbe9a53031fa72596edc09f">info</a>(<a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fadb3e7fba25df11c3fce5b5a88300b0ac6" title="Return value for no entry.">ForwardingInfo::NONE</a>, <a name="l00699"></a>00699 route-><a class="code" href="classdtn_1_1RouteEntry.html#0fe979e29165c5bdad1a126f1a0fb04f" title="Accessors.">action</a>(), <a name="l00700"></a>00700 link->name_str(), <a name="l00701"></a>00701 0xffffffff, <a name="l00702"></a>00702 link->remote_eid(), <a name="l00703"></a>00703 route-><a class="code" href="classdtn_1_1RouteEntry.html#846eaa2c3a7324662a346c6bc0e5a69b" title="Accessors.">custody_spec</a>()); <a name="l00704"></a>00704 deferred-><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#8c32a295ff6543f8f2bf1ece1f983410" title="Add a new bundle/info pair to the deferred list.">add</a>(bref, <a class="code" href="dtncat_8c.html#71f51a2e8cbe9a53031fa72596edc09f">info</a>); <a name="l00705"></a>00705 } <span class="keywordflow">else</span> { <a name="l00706"></a>00706 log_warn(<span class="stringliteral">"bundle *%p already exists on deferred list of link *%p"</span>, <a name="l00707"></a>00707 bundle, link.object()); <a name="l00708"></a>00708 } <a name="l00709"></a>00709 <a name="l00710"></a>00710 <span class="keywordflow">if</span> (!link->isavailable()) { <a name="l00711"></a>00711 log_debug(<span class="stringliteral">"can't forward *%p to *%p because link not available"</span>, <a name="l00712"></a>00712 bundle, link.object()); <a name="l00713"></a>00713 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (! link->isopen()) { <a name="l00714"></a>00714 log_debug(<span class="stringliteral">"can't forward *%p to *%p because link not open"</span>, <a name="l00715"></a>00715 bundle, link.object()); <a name="l00716"></a>00716 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (link->queue_is_full()) { <a name="l00717"></a>00717 log_debug(<span class="stringliteral">"can't forward *%p to *%p because link queue is full"</span>, <a name="l00718"></a>00718 bundle, link.object()); <a name="l00719"></a>00719 } <span class="keywordflow">else</span> { <a name="l00720"></a>00720 log_debug(<span class="stringliteral">"can't forward *%p to *%p"</span>, bundle, link.object()); <a name="l00721"></a>00721 } <a name="l00722"></a>00722 <a name="l00723"></a>00723 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00724"></a>00724 } <a name="l00725"></a>00725 <a name="l00726"></a>00726 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00727"></a>00727 <span class="keywordtype">int</span> <a name="l00728"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734">00728</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">TableBasedRouter::route_bundle</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle) <a name="l00729"></a>00729 { <a name="l00730"></a>00730 <a class="code" href="classdtn_1_1RouteEntryVec.html" title="Class for a vector of route entries.">RouteEntryVec</a> matches; <a name="l00731"></a>00731 RouteEntryVec::iterator iter; <a name="l00732"></a>00732 <a name="l00733"></a>00733 log_debug(<span class="stringliteral">"route_bundle: checking bundle %d"</span>, bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00734"></a>00734 <a name="l00735"></a>00735 <span class="comment">// check to see if forwarding is suppressed to all nodes</span> <a name="l00736"></a>00736 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#249ac137ef76e253d8e0587f2662bca7" title="Accessors.">fwdlog</a>()-><a class="code" href="classdtn_1_1ForwardingLog.html#afa0e50bb2cd435df9f883db9f8e2f20" title="Return the count of matching entries.">get_count</a>(<a class="code" href="classdtn_1_1EndpointIDPattern.html#9f872c8e701944c46b8989257d3188f2" title="Return the special wildcard Endpoint ID.">EndpointIDPattern::WILDCARD_EID</a>(), <a name="l00737"></a>00737 <a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fad7e404e025c65c3b35345a69533ce48a1" title="Transmission suppressed.">ForwardingInfo::SUPPRESSED</a>) > 0) <a name="l00738"></a>00738 { <a name="l00739"></a>00739 log_info(<span class="stringliteral">"route_bundle: "</span> <a name="l00740"></a>00740 <span class="stringliteral">"ignoring bundle %d since forwarding is suppressed"</span>, <a name="l00741"></a>00741 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00742"></a>00742 <span class="keywordflow">return</span> 0; <a name="l00743"></a>00743 } <a name="l00744"></a>00744 <a name="l00745"></a>00745 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> null_link(<span class="stringliteral">"TableBasedRouter::route_bundle"</span>); <a name="l00746"></a>00746 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#dceb882f843c17db3afd73521bc78c6d" title="Fill in the entry_vec with the list of all entries whose patterns match the given...">get_matching</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#507241e8ac766e1900009ed6243e2aa3" title="Accessors.">dest</a>(), null_link, &matches); <a name="l00747"></a>00747 <a name="l00748"></a>00748 <span class="comment">// sort the matching routes by priority, allowing subclasses to</span> <a name="l00749"></a>00749 <span class="comment">// override the way in which the sorting occurs</span> <a name="l00750"></a>00750 <a class="code" href="classdtn_1_1TableBasedRouter.html#33e876c5a09869489c60f892a9fbb909" title="Once a vector of matching routes has been found, sort the vector.">sort_routes</a>(bundle, &matches); <a name="l00751"></a>00751 <a name="l00752"></a>00752 log_debug(<span class="stringliteral">"route_bundle bundle id %d: checking %zu route entry matches"</span>, <a name="l00753"></a>00753 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>(), matches.size()); <a name="l00754"></a>00754 <a name="l00755"></a>00755 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="dtnping_8c.html#d43c3812e6d13e0518d9f8b8f463ffcf">count</a> = 0; <a name="l00756"></a>00756 <span class="keywordflow">for</span> (iter = matches.begin(); iter != matches.end(); ++iter) <a name="l00757"></a>00757 { <a name="l00758"></a>00758 <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>* route = *iter; <a name="l00759"></a>00759 log_debug(<span class="stringliteral">"checking route entry %p link %s (%p)"</span>, <a name="l00760"></a>00760 *iter, route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>()->name(), route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>().object()); <a name="l00761"></a>00761 <a name="l00762"></a>00762 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1TableBasedRouter.html#08961b48157a280be9cb160158903a82" title="Check if the bundle should be forwarded to the given next hop.">should_fwd</a>(bundle, *iter)) { <a name="l00763"></a>00763 <span class="keywordflow">continue</span>; <a name="l00764"></a>00764 } <a name="l00765"></a>00765 <a name="l00766"></a>00766 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6" title="Helper accessor to return the deferred queue for a link.">deferred_list</a>(route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>())->list()->contains(bundle)) { <a name="l00767"></a>00767 log_debug(<span class="stringliteral">"route_bundle bundle %d: "</span> <a name="l00768"></a>00768 <span class="stringliteral">"ignoring link *%p since already deferred"</span>, <a name="l00769"></a>00769 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>(), route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>().object()); <a name="l00770"></a>00770 <span class="keywordflow">continue</span>; <a name="l00771"></a>00771 } <a name="l00772"></a>00772 <a name="l00773"></a>00773 <span class="comment">// because there may be bundles that already have deferred</span> <a name="l00774"></a>00774 <span class="comment">// transmission on the link, we first call check_next_hop to</span> <a name="l00775"></a>00775 <span class="comment">// get them into the queue before trying to route the new</span> <a name="l00776"></a>00776 <span class="comment">// arrival, otherwise it might leapfrog the other deferred</span> <a name="l00777"></a>00777 <span class="comment">// bundles</span> <a name="l00778"></a>00778 <a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97" title="Called when the next hop link is available for transmission (i.e.">check_next_hop</a>(route-><a class="code" href="classdtn_1_1RouteEntry.html#98215fe609f488da2d13fc7c1a0c4059" title="Accessors.">link</a>()); <a name="l00779"></a>00779 <a name="l00780"></a>00780 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1TableBasedRouter.html#4bac86cb57a6b1b7350f8471d890bb2f" title="Try to forward a bundle to a next hop route.">fwd_to_nexthop</a>(bundle, *iter)) { <a name="l00781"></a>00781 <span class="keywordflow">continue</span>; <a name="l00782"></a>00782 } <a name="l00783"></a>00783 <a name="l00784"></a>00784 ++count; <a name="l00785"></a>00785 } <a name="l00786"></a>00786 <a name="l00787"></a>00787 log_debug(<span class="stringliteral">"route_bundle bundle id %d: forwarded on %u links"</span>, <a name="l00788"></a>00788 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>(), count); <a name="l00789"></a>00789 <span class="keywordflow">return</span> count; <a name="l00790"></a>00790 } <a name="l00791"></a>00791 <a name="l00792"></a>00792 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00793"></a>00793 <span class="keywordtype">void</span> <a name="l00794"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#33e876c5a09869489c60f892a9fbb909">00794</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#33e876c5a09869489c60f892a9fbb909" title="Once a vector of matching routes has been found, sort the vector.">TableBasedRouter::sort_routes</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle, <a class="code" href="classdtn_1_1RouteEntryVec.html" title="Class for a vector of route entries.">RouteEntryVec</a>* routes) <a name="l00795"></a>00795 { <a name="l00796"></a>00796 (void)bundle; <a name="l00797"></a>00797 std::sort(routes->begin(), routes->end(), <a class="code" href="structdtn_1_1RoutePrioritySort.html" title="Functor class to sort a vector of routes based on forwarding priority, using the...">RoutePrioritySort</a>()); <a name="l00798"></a>00798 } <a name="l00799"></a>00799 <a name="l00800"></a>00800 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00801"></a>00801 <span class="keywordtype">void</span> <a name="l00802"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97">00802</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#c94ac84e21dbf45fd6ccd8fb37b0bd97" title="Called when the next hop link is available for transmission (i.e.">TableBasedRouter::check_next_hop</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& next_hop) <a name="l00803"></a>00803 { <a name="l00804"></a>00804 <span class="comment">// if the link isn't open, there's nothing to do now</span> <a name="l00805"></a>00805 <span class="keywordflow">if</span> (! next_hop->isopen()) { <a name="l00806"></a>00806 log_debug(<span class="stringliteral">"check_next_hop %s -> %s: link not open..."</span>, <a name="l00807"></a>00807 next_hop->name(), next_hop->nexthop()); <a name="l00808"></a>00808 <span class="keywordflow">return</span>; <a name="l00809"></a>00809 } <a name="l00810"></a>00810 <a name="l00811"></a>00811 <span class="comment">// if the link queue doesn't have space (based on the low water</span> <a name="l00812"></a>00812 <span class="comment">// mark) don't do anything</span> <a name="l00813"></a>00813 <span class="keywordflow">if</span> (! next_hop->queue_has_space()) { <a name="l00814"></a>00814 log_debug(<span class="stringliteral">"check_next_hop %s -> %s: no space in queue..."</span>, <a name="l00815"></a>00815 next_hop->name(), next_hop->nexthop()); <a name="l00816"></a>00816 <span class="keywordflow">return</span>; <a name="l00817"></a>00817 } <a name="l00818"></a>00818 <a name="l00819"></a>00819 log_debug(<span class="stringliteral">"check_next_hop %s -> %s: checking deferred bundle list..."</span>, <a name="l00820"></a>00820 next_hop->name(), next_hop->nexthop()); <a name="l00821"></a>00821 <a name="l00822"></a>00822 <span class="comment">// because the loop below will remove the current bundle from</span> <a name="l00823"></a>00823 <span class="comment">// the deferred list, invalidating any iterators pointing to its</span> <a name="l00824"></a>00824 <span class="comment">// position, make sure to advance the iterator before processing</span> <a name="l00825"></a>00825 <span class="comment">// the current bundle</span> <a name="l00826"></a>00826 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>* deferred = <a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6" title="Helper accessor to return the deferred queue for a link.">deferred_list</a>(next_hop); <a name="l00827"></a>00827 <a name="l00828"></a>00828 oasys::ScopeLock l(deferred->list()->lock(), <a name="l00829"></a>00829 <span class="stringliteral">"TableBasedRouter::check_next_hop"</span>); <a name="l00830"></a>00830 <a class="code" href="classdtn_1_1BundleList.html#1d52b8d6bb7d8a07e5d4f5fc4b5b61d2" title="Type for an iterator, which just wraps an stl iterator.">BundleList::iterator</a> iter = deferred->list()->begin(); <a name="l00831"></a>00831 <span class="keywordflow">while</span> (iter != deferred->list()->end()) <a name="l00832"></a>00832 { <a name="l00833"></a>00833 <span class="keywordflow">if</span> (next_hop->queue_is_full()) { <a name="l00834"></a>00834 log_debug(<span class="stringliteral">"check_next_hop %s: link queue is full, stopping loop"</span>, <a name="l00835"></a>00835 next_hop->name()); <a name="l00836"></a>00836 <span class="keywordflow">break</span>; <a name="l00837"></a>00837 } <a name="l00838"></a>00838 <a name="l00839"></a>00839 <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a> bundle(<span class="stringliteral">"TableBasedRouter::check_next_hop"</span>); <a name="l00840"></a>00840 bundle = *iter; <a name="l00841"></a>00841 ++iter; <a name="l00842"></a>00842 <a name="l00843"></a>00843 <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a> <a class="code" href="dtncat_8c.html#71f51a2e8cbe9a53031fa72596edc09f">info</a> = deferred->info(bundle); <a name="l00844"></a>00844 <a name="l00845"></a>00845 <span class="comment">// if should_fwd returns false, then the bundle was either</span> <a name="l00846"></a>00846 <span class="comment">// already transmitted or is in flight on another node. since</span> <a name="l00847"></a>00847 <span class="comment">// it's possible that one of the other transmissions will</span> <a name="l00848"></a>00848 <span class="comment">// fail, we leave it on the deferred list for now, relying on</span> <a name="l00849"></a>00849 <span class="comment">// the transmitted handlers to clean up the state</span> <a name="l00850"></a>00850 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1BundleRouter.html#b30e99f427cc0526fce08b77e0ae95c7" title="Check if the bundle should be forwarded to the given next hop.">BundleRouter::should_fwd</a>(bundle.object(), next_hop, <a name="l00851"></a>00851 info.<a class="code" href="classdtn_1_1ForwardingInfo.html#c6e2356364eb63268f2a80db2287c26c" title="Accessors.">action</a>())) <a name="l00852"></a>00852 { <a name="l00853"></a>00853 log_debug(<span class="stringliteral">"check_next_hop: not forwarding to link %s"</span>, <a name="l00854"></a>00854 next_hop->name()); <a name="l00855"></a>00855 <span class="keywordflow">continue</span>; <a name="l00856"></a>00856 } <a name="l00857"></a>00857 <a name="l00858"></a>00858 <span class="comment">// if the link is available and not open, open it</span> <a name="l00859"></a>00859 <span class="keywordflow">if</span> (next_hop->isavailable() && <a name="l00860"></a>00860 (!next_hop->isopen()) && (!next_hop->isopening())) <a name="l00861"></a>00861 { <a name="l00862"></a>00862 log_debug(<span class="stringliteral">"check_next_hop: "</span> <a name="l00863"></a>00863 <span class="stringliteral">"opening *%p because a message is intended for it"</span>, <a name="l00864"></a>00864 next_hop.object()); <a name="l00865"></a>00865 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#0cb4ef96c172a1943d32d19747a00438" title="Open a link for bundle transmission.">open_link</a>(next_hop); <a name="l00866"></a>00866 } <a name="l00867"></a>00867 <a name="l00868"></a>00868 <span class="comment">// remove the bundle from the deferred list</span> <a name="l00869"></a>00869 deferred->del(bundle); <a name="l00870"></a>00870 <a name="l00871"></a>00871 log_debug(<span class="stringliteral">"check_next_hop: sending *%p to *%p"</span>, <a name="l00872"></a>00872 bundle.object(), next_hop.object()); <a name="l00873"></a>00873 <a class="code" href="classdtn_1_1BundleRouter.html#cf71e3f1982b36bafa7ac5cd45d38675" title="The actions interface, set by the BundleDaemon when the router is initialized.">actions_</a>-><a class="code" href="classdtn_1_1BundleActions.html#7a75826fd1b4515b9d9aa2b98acbde68" title="Queue the bundle for transmission on the given link.">queue_bundle</a>(bundle.object() , next_hop, <a name="l00874"></a>00874 info.<a class="code" href="classdtn_1_1ForwardingInfo.html#c6e2356364eb63268f2a80db2287c26c" title="Accessors.">action</a>(), info.<a class="code" href="classdtn_1_1ForwardingInfo.html#0c917dfbc2952c2c827609b5a27b5d92" title="Accessors.">custody_spec</a>()); <a name="l00875"></a>00875 } <a name="l00876"></a>00876 } <a name="l00877"></a>00877 <a name="l00878"></a>00878 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00879"></a>00879 <span class="keywordtype">void</span> <a name="l00880"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#3e5d2926a1b0cf5cabbef44eafd21bb7">00880</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#3e5d2926a1b0cf5cabbef44eafd21bb7" title="Go through all known bundles in the system and try to re-route them.">TableBasedRouter::reroute_all_bundles</a>() <a name="l00881"></a>00881 { <a name="l00882"></a>00882 oasys::ScopeLock l(<a class="code" href="classdtn_1_1BundleRouter.html#06ef6e02e26e9a78a9d15619810d56dc" title="The list of all bundles still pending delivery.">pending_bundles_</a>-><a class="code" href="classdtn_1_1BundleList.html#0d0c9f789f0f7f7d1cda3b4ecf32d2bc" title="Return the internal lock on this list.">lock</a>(), <a name="l00883"></a>00883 <span class="stringliteral">"TableBasedRouter::reroute_all_bundles"</span>); <a name="l00884"></a>00884 <a name="l00885"></a>00885 log_debug(<span class="stringliteral">"reroute_all_bundles... %zu bundles on pending list"</span>, <a name="l00886"></a>00886 <a class="code" href="classdtn_1_1BundleRouter.html#06ef6e02e26e9a78a9d15619810d56dc" title="The list of all bundles still pending delivery.">pending_bundles_</a>-><a class="code" href="classdtn_1_1BundleList.html#3c50c6f421631a4dd72b7b77b0660bc3" title="Return the size of the list.">size</a>()); <a name="l00887"></a>00887 <a name="l00888"></a>00888 <span class="comment">// XXX/demmer this should cancel previous scheduled transmissions</span> <a name="l00889"></a>00889 <span class="comment">// if any decisions have changed</span> <a name="l00890"></a>00890 <a name="l00891"></a>00891 <a class="code" href="classdtn_1_1BundleList.html#1d52b8d6bb7d8a07e5d4f5fc4b5b61d2" title="Type for an iterator, which just wraps an stl iterator.">BundleList::iterator</a> iter; <a name="l00892"></a>00892 <span class="keywordflow">for</span> (iter = <a class="code" href="classdtn_1_1BundleRouter.html#06ef6e02e26e9a78a9d15619810d56dc" title="The list of all bundles still pending delivery.">pending_bundles_</a>-><a class="code" href="classdtn_1_1BundleList.html#24cd371acd62f2f9725ff3f92b55badf" title="Iterator used to iterate through the list.">begin</a>(); <a name="l00893"></a>00893 iter != <a class="code" href="classdtn_1_1BundleRouter.html#06ef6e02e26e9a78a9d15619810d56dc" title="The list of all bundles still pending delivery.">pending_bundles_</a>-><a class="code" href="classdtn_1_1BundleList.html#19f95941fe436d25ba49ae0b2d8bf2c1" title="Iterator used to mark the end of the list.">end</a>(); <a name="l00894"></a>00894 ++iter) <a name="l00895"></a>00895 { <a name="l00896"></a>00896 <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">route_bundle</a>(*iter); <a name="l00897"></a>00897 } <a name="l00898"></a>00898 } <a name="l00899"></a>00899 <a name="l00900"></a>00900 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00901"></a>00901 <span class="keywordtype">void</span> <a name="l00902"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#7339ab822d11b9cf8c83ae608e79058e">00902</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#7339ab822d11b9cf8c83ae608e79058e" title="Generic hook in response to the command line indication that we should reroute all...">TableBasedRouter::recompute_routes</a>() <a name="l00903"></a>00903 { <a name="l00904"></a>00904 <a class="code" href="classdtn_1_1TableBasedRouter.html#3e5d2926a1b0cf5cabbef44eafd21bb7" title="Go through all known bundles in the system and try to re-route them.">reroute_all_bundles</a>(); <a name="l00905"></a>00905 } <a name="l00906"></a>00906 <a name="l00907"></a>00907 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00908"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#41c5806479ead8e174a8afce3c52de55">00908</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#41c5806479ead8e174a8afce3c52de55">TableBasedRouter::DeferredList::DeferredList</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* logpath, <a name="l00909"></a>00909 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link) <a name="l00910"></a>00910 : <a class="code" href="classdtn_1_1RouterInfo.html" title="Empty wrapper class to encapsulate router-specific data attached to Links.">RouterInfo</a>(), <a name="l00911"></a>00911 <a class="code" href="classoasys_1_1Logger.html">Logger</a>(<span class="stringliteral">"%s/deferred/%s"</span>, logpath, link->name()), <a name="l00912"></a>00912 list_(link->name_str() + <span class="stringliteral">":deferred"</span>), <a name="l00913"></a>00913 count_(0) <a name="l00914"></a>00914 { <a name="l00915"></a>00915 } <a name="l00916"></a>00916 <a name="l00917"></a>00917 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00918"></a>00918 <span class="keywordtype">void</span> <a name="l00919"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#05eea0fee527d1c00796feb401638ffd">00919</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#05eea0fee527d1c00796feb401638ffd" title="Print out the stats, called from Link::dump_stats.">TableBasedRouter::DeferredList::dump_stats</a>(oasys::StringBuffer* <a class="code" href="num2sdnv_8c.html#a81cdcc7ff6987bc85c073253e32715f">buf</a>) <a name="l00920"></a>00920 { <a name="l00921"></a>00921 buf->appendf(<span class="stringliteral">" -- %zu bundles_deferred"</span>, <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a>); <a name="l00922"></a>00922 } <a name="l00923"></a>00923 <a name="l00924"></a>00924 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00925"></a>00925 <span class="keywordtype">bool</span> <a name="l00926"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#8a87dfe205964e5eaee333c4b0c4f7c0">00926</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#8a87dfe205964e5eaee333c4b0c4f7c0" title="Check if the bundle is on the list.">TableBasedRouter::DeferredList::find</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle, <a name="l00927"></a>00927 <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a>* <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#eff6ba41d141a9c16b0309e410a936ae" title="Accessor for the forwarding info associated with the bundle, which must be on the...">info</a>) <a name="l00928"></a>00928 { <a name="l00929"></a>00929 InfoMap::const_iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.find(bundle->bundleid()); <a name="l00930"></a>00930 <span class="keywordflow">if</span> (iter == <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.end()) { <a name="l00931"></a>00931 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00932"></a>00932 } <a name="l00933"></a>00933 *info = iter->second; <a name="l00934"></a>00934 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00935"></a>00935 } <a name="l00936"></a>00936 <a name="l00937"></a>00937 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00938"></a>00938 <span class="keyword">const</span> <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a>& <a name="l00939"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#eff6ba41d141a9c16b0309e410a936ae">00939</a> <a class="code" href="dtncat_8c.html#71f51a2e8cbe9a53031fa72596edc09f">TableBasedRouter::DeferredList::info</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle) <a name="l00940"></a>00940 { <a name="l00941"></a>00941 InfoMap::const_iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.find(bundle->bundleid()); <a name="l00942"></a>00942 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(iter != <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.end()); <a name="l00943"></a>00943 <span class="keywordflow">return</span> iter->second; <a name="l00944"></a>00944 } <a name="l00945"></a>00945 <a name="l00946"></a>00946 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00947"></a>00947 <span class="keywordtype">bool</span> <a name="l00948"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#8c32a295ff6543f8f2bf1ece1f983410">00948</a> <a class="code" href="dtnperf-client_8c.html#517b0f7cbe789371f38fd9f87f8c807b">TableBasedRouter::DeferredList::add</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle, <a name="l00949"></a>00949 <span class="keyword">const</span> <a class="code" href="classdtn_1_1ForwardingInfo.html" title="Class to encapsulate bundle forwarding information.">ForwardingInfo</a>& <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#eff6ba41d141a9c16b0309e410a936ae" title="Accessor for the forwarding info associated with the bundle, which must be on the...">info</a>) <a name="l00950"></a>00950 { <a name="l00951"></a>00951 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#ba631d00d7e4be0232b21e1c7c13ac35">list_</a>.<a class="code" href="classdtn_1_1BundleList.html#6398bb64194aa88b63e7d0e89e141883" title="Search the list for the given bundle.">contains</a>(bundle)) { <a name="l00952"></a>00952 log_err(<span class="stringliteral">"bundle *%p already in deferred list!"</span>, <a name="l00953"></a>00953 bundle.object()); <a name="l00954"></a>00954 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00955"></a>00955 } <a name="l00956"></a>00956 <a name="l00957"></a>00957 log_debug(<span class="stringliteral">"adding *%p to deferred (length %zu)"</span>, <a name="l00958"></a>00958 bundle.object(), <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a>); <a name="l00959"></a>00959 <a name="l00960"></a>00960 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a>++; <a name="l00961"></a>00961 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#ba631d00d7e4be0232b21e1c7c13ac35">list_</a>.<a class="code" href="classdtn_1_1BundleList.html#9f3efd0593739e89ed478fd4bbccd3e0" title="Add a new bundle to the back of the list.">push_back</a>(bundle); <a name="l00962"></a>00962 <a name="l00963"></a>00963 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.insert(InfoMap::value_type(bundle->bundleid(), info)); <a name="l00964"></a>00964 <a name="l00965"></a>00965 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00966"></a>00966 } <a name="l00967"></a>00967 <a name="l00968"></a>00968 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00969"></a>00969 <span class="keywordtype">bool</span> <a name="l00970"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#06552754bfa787fb9ce0361c9007041b">00970</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#06552754bfa787fb9ce0361c9007041b" title="Remove the bundle and its associated forwarding info from the list.">TableBasedRouter::DeferredList::del</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a>& bundle) <a name="l00971"></a>00971 { <a name="l00972"></a>00972 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#ba631d00d7e4be0232b21e1c7c13ac35">list_</a>.<a class="code" href="classdtn_1_1BundleList.html#b0171458e14d67307b74f98447062d68" title="Remove the given bundle from the list.">erase</a>(bundle)) { <a name="l00973"></a>00973 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00974"></a>00974 } <a name="l00975"></a>00975 <a name="l00976"></a>00976 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a> > 0); <a name="l00977"></a>00977 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a>--; <a name="l00978"></a>00978 <a name="l00979"></a>00979 log_debug(<span class="stringliteral">"removed *%p from deferred (length %zu)"</span>, <a name="l00980"></a>00980 bundle.object(), <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#03fe22b291b586e62d81e1fca52a3983">count_</a>); <a name="l00981"></a>00981 <a name="l00982"></a>00982 <span class="keywordtype">size_t</span> n = <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html#5074c943a1044ad9463b9ffdc8e8e7f1">info_</a>.erase(bundle->bundleid()); <a name="l00983"></a>00983 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(n == 1); <a name="l00984"></a>00984 <a name="l00985"></a>00985 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00986"></a>00986 } <a name="l00987"></a>00987 <a name="l00988"></a>00988 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00989"></a>00989 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">TableBasedRouter::DeferredList</a>* <a name="l00990"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6">00990</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#8b9aa9d3859cb6bbc3a8fc5fa30775c6" title="Helper accessor to return the deferred queue for a link.">TableBasedRouter::deferred_list</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link) <a name="l00991"></a>00991 { <a name="l00992"></a>00992 <a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>* dq = <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1TableBasedRouter_1_1DeferredList.html" title="Per-link class used to store deferred transmission bundles that helps cache route...">DeferredList</a>*<span class="keyword">></span>(link->router_info()); <a name="l00993"></a>00993 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(dq != NULL); <a name="l00994"></a>00994 <span class="keywordflow">return</span> dq; <a name="l00995"></a>00995 } <a name="l00996"></a>00996 <a name="l00997"></a>00997 <a name="l00998"></a>00998 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00999"></a>00999 <span class="keywordtype">void</span> <a name="l01000"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#fab4ded007eddf5b49c3ff75eea74dd8">01000</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#fab4ded007eddf5b49c3ff75eea74dd8" title="Event handlers.">TableBasedRouter::handle_registration_added</a>(<a class="code" href="classdtn_1_1RegistrationAddedEvent.html" title="Event class for new registration arrivals.">RegistrationAddedEvent</a>* event) <a name="l01001"></a>01001 { <a name="l01002"></a>01002 <a class="code" href="classdtn_1_1Registration.html" title="Class used to represent an &quot;application&quot; registration, loosely defined...">Registration</a>* reg = <span class="keyword">event</span>->registration_; <a name="l01003"></a>01003 <a name="l01004"></a>01004 <span class="keywordflow">if</span> (reg == NULL || reg-><a class="code" href="classdtn_1_1Registration.html#577ef221608a47ba828daad128c2b263" title="Accessors.">session_flags</a>() == 0) { <a name="l01005"></a>01005 <span class="keywordflow">return</span>; <a name="l01006"></a>01006 } <a name="l01007"></a>01007 <a name="l01008"></a>01008 log_debug(<span class="stringliteral">"got new session registration %u"</span>, reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01009"></a>01009 <a name="l01010"></a>01010 <span class="keywordflow">if</span> (reg-><a class="code" href="classdtn_1_1Registration.html#577ef221608a47ba828daad128c2b263" title="Accessors.">session_flags</a>() & <a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498c1ccfadd042afba693bbcf1e5980667d9">Session::CUSTODY</a>) { <a name="l01011"></a>01011 log_debug(<span class="stringliteral">"session custodian registration %u"</span>, reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01012"></a>01012 <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.push_back(reg); <a name="l01013"></a>01013 } <a name="l01014"></a>01014 <a name="l01015"></a>01015 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (reg-><a class="code" href="classdtn_1_1Registration.html#577ef221608a47ba828daad128c2b263" title="Accessors.">session_flags</a>() & <a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498cadd5836fef35cca7c207e710e8e13239">Session::SUBSCRIBE</a>) { <a name="l01016"></a>01016 log_debug(<span class="stringliteral">"session subscription registration %u"</span>, reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01017"></a>01017 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#100acfedb5536efcb57382347ca0a759">get_session</a>(reg-><a class="code" href="classdtn_1_1Registration.html#590e683ae3d0a33456e7f0fa0a2a89d5" title="Accessors.">endpoint</a>()); <a name="l01018"></a>01018 session-><a class="code" href="classdtn_1_1Session.html#92b88bd55939a1766a3f2674ce20482c">add_subscriber</a>(<a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a>(reg)); <a name="l01019"></a>01019 <a class="code" href="classdtn_1_1TableBasedRouter.html#8eefa1b03ae7e19a168205af67d4173b" title="Session management helper functions.">subscribe_to_session</a>(<a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498cadd5836fef35cca7c207e710e8e13239">Session::SUBSCRIBE</a>, session); <a name="l01020"></a>01020 } <a name="l01021"></a>01021 <a name="l01022"></a>01022 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (reg-><a class="code" href="classdtn_1_1Registration.html#577ef221608a47ba828daad128c2b263" title="Accessors.">session_flags</a>() & <a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498c1978e38ca305c80fe009dd50fe24a3be">Session::PUBLISH</a>) { <a name="l01023"></a>01023 log_debug(<span class="stringliteral">"session publish registration %u"</span>, reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01024"></a>01024 <a name="l01025"></a>01025 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#100acfedb5536efcb57382347ca0a759">get_session</a>(reg-><a class="code" href="classdtn_1_1Registration.html#590e683ae3d0a33456e7f0fa0a2a89d5" title="Accessors.">endpoint</a>()); <a name="l01026"></a>01026 <span class="keywordflow">if</span> (session->upstream().is_null()) { <a name="l01027"></a>01027 log_debug(<span class="stringliteral">"unknown upstream for publish registration... "</span> <a name="l01028"></a>01028 <span class="stringliteral">"trying to find one"</span>); <a name="l01029"></a>01029 <a class="code" href="classdtn_1_1TableBasedRouter.html#6f94fb99000ba969300ffee06b8a2d84" title="Session management helper functions.">find_session_upstream</a>(session); <a name="l01030"></a>01030 } <a name="l01031"></a>01031 <a name="l01032"></a>01032 <span class="comment">// XXX/demmer do something about publish</span> <a name="l01033"></a>01033 } <a name="l01034"></a>01034 } <a name="l01035"></a>01035 <a name="l01036"></a>01036 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01037"></a>01037 <span class="keywordtype">bool</span> <a name="l01038"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#8eefa1b03ae7e19a168205af67d4173b">01038</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#8eefa1b03ae7e19a168205af67d4173b" title="Session management helper functions.">TableBasedRouter::subscribe_to_session</a>(<span class="keywordtype">int</span> <a class="code" href="num2sdnv_8c.html#1ea5d0cb93f22f7d0fdf804bd68c3326">mode</a>, <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session) <a name="l01039"></a>01039 { <a name="l01040"></a>01040 <span class="keywordflow">if</span> (! session-><a class="code" href="classdtn_1_1Session.html#d483d580e9a1e213e974cb41b875065b">upstream</a>().<a class="code" href="classdtn_1_1Subscriber.html#d9105b34d6fcdb3397b402aebc4f7aef" title="Accessors.">is_local</a>()) { <a name="l01041"></a>01041 <span class="comment">// XXX/demmer should set replyto to handle upstream nodes that</span> <a name="l01042"></a>01042 <span class="comment">// don't understand the session block</span> <a name="l01043"></a>01043 <a name="l01044"></a>01044 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = <span class="keyword">new</span> <a class="code" href="classdtn_1_1TempBundle.html" title="Class to represent a temporary bundle -- i.e.">TempBundle</a>(); <a name="l01045"></a>01045 bundle-><a class="code" href="classdtn_1_1Bundle.html#ce75b35784c110dc09986632e9d9eba1" title="Setters and mutable accessors.">set_do_not_fragment</a>(1); <a name="l01046"></a>01046 bundle-><a class="code" href="classdtn_1_1Bundle.html#69c35928ca050eb4bb2ec67641f1b6bb" title="Setters and mutable accessors.">mutable_source</a>()-><a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(BundleDaemon::instance()->local_eid()); <a name="l01047"></a>01047 bundle-><a class="code" href="classdtn_1_1Bundle.html#fedf6ad0537f7e3a3f958162d1fc935e" title="Setters and mutable accessors.">mutable_dest</a>()-><a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(<span class="stringliteral">"dtn-session:"</span> + session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>()); <a name="l01048"></a>01048 bundle-><a class="code" href="classdtn_1_1Bundle.html#7c2091e44637889b9ad6f94a82ae7f83" title="Setters and mutable accessors.">mutable_replyto</a>()-><a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(<a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()); <a name="l01049"></a>01049 bundle-><a class="code" href="classdtn_1_1Bundle.html#96698085719d88c0b5c86d4cb388324c" title="Setters and mutable accessors.">mutable_custodian</a>()-><a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(<a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()); <a name="l01050"></a>01050 bundle-><a class="code" href="classdtn_1_1Bundle.html#7623ecfe9e47e5dc075ebd872fb9a237" title="Setters and mutable accessors.">set_expiration</a>(<a class="code" href="classdtn_1_1BundleRouter.html#344d85ef64a884adf9fb173a82674cca" title="Config variables.">config_</a>.<a class="code" href="structdtn_1_1BundleRouter_1_1Config.html#6bdb1ed1423affe75f2a50a7d3e159b6" title="Timeout for upstream session subscriptions in seconds (default is ten minutes).">subscription_timeout_</a>); <a name="l01051"></a>01051 bundle-><a class="code" href="classdtn_1_1Bundle.html#3b35e450cfd2504a5980d379f71f222c" title="Setters and mutable accessors.">set_singleton_dest</a>(<span class="keyword">true</span>); <a name="l01052"></a>01052 bundle-><a class="code" href="classdtn_1_1Bundle.html#453f60de16237ff944b5b95951288611" title="Setters and mutable accessors.">mutable_session_eid</a>()-><a class="code" href="classdtn_1_1EndpointID.html#ec39752e4da3107b16ff5da58d2aa5ab" title="Assign this endpoint ID as a copy of the other.">assign</a>(session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>()); <a name="l01053"></a>01053 bundle-><a class="code" href="classdtn_1_1Bundle.html#24e65f2c2ad09ce8bca3409f450df21c" title="Setters and mutable accessors.">set_session_flags</a>(mode); <a name="l01054"></a>01054 bundle-><a class="code" href="classdtn_1_1Bundle.html#39b61082cafee0ad15b30eb0b90fcd9a" title="Setters and mutable accessors.">mutable_sequence_id</a>()-><a class="code" href="classdtn_1_1SequenceID.html#070d80850e92a94691654065a20099bf" title="Reset the SequenceID to be a copy of the other.">assign</a>(*session-><a class="code" href="classdtn_1_1Session.html#bd799ea58a766a69bcfadf0f1ddef47f">sequence_id</a>()); <a name="l01055"></a>01055 <a name="l01056"></a>01056 log_debug(<span class="stringliteral">"sending subscribe bundle to session %s (timeout %u seconds)"</span>, <a name="l01057"></a>01057 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), <a class="code" href="classdtn_1_1BundleRouter.html#344d85ef64a884adf9fb173a82674cca" title="Config variables.">config_</a>.<a class="code" href="structdtn_1_1BundleRouter_1_1Config.html#6bdb1ed1423affe75f2a50a7d3e159b6" title="Timeout for upstream session subscriptions in seconds (default is ten minutes).">subscription_timeout_</a>); <a name="l01058"></a>01058 <a name="l01059"></a>01059 <a class="code" href="classdtn_1_1BundleDaemon.html#c7f41d180e271e74b1c7cd71f2577686" title="Queues the event at the head of the queue for processing by the daemon thread.">BundleDaemon::post_at_head</a>( <a name="l01060"></a>01060 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleReceivedEvent.html" title="Event class for new bundle arrivals.">BundleReceivedEvent</a>(bundle, <a class="code" href="namespacedtn.html#60ee39c9672604f59fe1b12d4e1d142b25abe58c828214d9857f0fa1249db869" title="the routing logic">EVENTSRC_ROUTER</a>)); <a name="l01061"></a>01061 <a name="l01062"></a>01062 <span class="keywordflow">if</span> (session-><a class="code" href="classdtn_1_1Session.html#5bb0b08cf18c10775cf5e40b3d6181a6">resubscribe_timer</a>() != NULL) { <a name="l01063"></a>01063 log_debug(<span class="stringliteral">"cancelling old resubscribe timer"</span>); <a name="l01064"></a>01064 session-><a class="code" href="classdtn_1_1Session.html#5bb0b08cf18c10775cf5e40b3d6181a6">resubscribe_timer</a>()->cancel(); <a name="l01065"></a>01065 } <a name="l01066"></a>01066 <a name="l01067"></a>01067 u_int resubscribe_timeout = <a class="code" href="classdtn_1_1BundleRouter.html#344d85ef64a884adf9fb173a82674cca" title="Config variables.">config_</a>.<a class="code" href="structdtn_1_1BundleRouter_1_1Config.html#6bdb1ed1423affe75f2a50a7d3e159b6" title="Timeout for upstream session subscriptions in seconds (default is ten minutes).">subscription_timeout_</a> * 1000 / 2; <a name="l01068"></a>01068 log_debug(<span class="stringliteral">"scheduling resubscribe timer in %u msecs"</span>, <a name="l01069"></a>01069 resubscribe_timeout); <a name="l01070"></a>01070 <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html" title="Timer class used to periodically refresh subscriptions.">ResubscribeTimer</a>* timer = <span class="keyword">new</span> <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html" title="Timer class used to periodically refresh subscriptions.">ResubscribeTimer</a>(<span class="keyword">this</span>, session); <a name="l01071"></a>01071 timer->schedule_in(resubscribe_timeout); <a name="l01072"></a>01072 session-><a class="code" href="classdtn_1_1Session.html#30bf27ca931dcd41de355a51b2c47c8d">set_resubscribe_timer</a>(timer); <a name="l01073"></a>01073 <a name="l01074"></a>01074 } <span class="keywordflow">else</span> { <a name="l01075"></a>01075 <span class="comment">// XXX/demmer todo</span> <a name="l01076"></a>01076 log_debug(<span class="stringliteral">"local upstream source: notifying registration"</span>); <a name="l01077"></a>01077 } <a name="l01078"></a>01078 <a name="l01079"></a>01079 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01080"></a>01080 } <a name="l01081"></a>01081 <a name="l01082"></a>01082 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01083"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#70c775c353136414ef5ca2fe07f56211">01083</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#70c775c353136414ef5ca2fe07f56211">TableBasedRouter::ResubscribeTimer::ResubscribeTimer</a>(<a class="code" href="classdtn_1_1TableBasedRouter.html" title="This is an abstract class that is intended to be used for all routing algorithms...">TableBasedRouter</a>* router, <a name="l01084"></a>01084 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session) <a name="l01085"></a>01085 : router_(router), session_(session) <a name="l01086"></a>01086 { <a name="l01087"></a>01087 } <a name="l01088"></a>01088 <a name="l01089"></a>01089 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01090"></a>01090 <span class="keywordtype">void</span> <a name="l01091"></a><a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#3feb0d534034706726b2716f93865265">01091</a> <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#3feb0d534034706726b2716f93865265">TableBasedRouter::ResubscribeTimer::timeout</a>(<span class="keyword">const</span> <span class="keyword">struct</span> timeval& now) <a name="l01092"></a>01092 { <a name="l01093"></a>01093 (void)now; <a name="l01094"></a>01094 <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#39d8381ef5d19954dbac055d408c1ba5">router_</a>->logf(oasys::LOG_DEBUG, <span class="stringliteral">"resubscribe timer fired for session *%p"</span>, <a name="l01095"></a>01095 <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#7700eb57fea72d161cef941a021a76c0">session_</a>); <a name="l01096"></a>01096 <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#39d8381ef5d19954dbac055d408c1ba5">router_</a>-><a class="code" href="classdtn_1_1TableBasedRouter.html#8eefa1b03ae7e19a168205af67d4173b" title="Session management helper functions.">subscribe_to_session</a>(<a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498c8ec080183d9e900330780466c77a30be">Session::RESUBSCRIBE</a>, <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#7700eb57fea72d161cef941a021a76c0">session_</a>); <a name="l01097"></a>01097 <a class="code" href="classdtn_1_1TableBasedRouter_1_1ResubscribeTimer.html#7700eb57fea72d161cef941a021a76c0">session_</a>-><a class="code" href="classdtn_1_1Session.html#30bf27ca931dcd41de355a51b2c47c8d">set_resubscribe_timer</a>(NULL); <a name="l01098"></a>01098 <span class="keyword">delete</span> <span class="keyword">this</span>; <a name="l01099"></a>01099 } <a name="l01100"></a>01100 <a name="l01101"></a>01101 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01102"></a>01102 <span class="keywordtype">bool</span> <a name="l01103"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#14061ba8016fc61a7556d44b1323f36c">01103</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#14061ba8016fc61a7556d44b1323f36c" title="Session management helper functions.">TableBasedRouter::handle_session_bundle</a>(<a class="code" href="classdtn_1_1BundleReceivedEvent.html" title="Event class for new bundle arrivals.">BundleReceivedEvent</a>* event) <a name="l01104"></a>01104 { <a name="l01105"></a>01105 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = <span class="keyword">event</span>->bundleref_.object(); <a name="l01106"></a>01106 <a name="l01107"></a>01107 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>() != 0); <a name="l01108"></a>01108 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#9bdc5df0500ec9859132c917f48f7bb0" title="Accessors.">session_eid</a>() != <a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()); <a name="l01109"></a>01109 <a name="l01110"></a>01110 <a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session = <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#100acfedb5536efcb57382347ca0a759">get_session</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#9bdc5df0500ec9859132c917f48f7bb0" title="Accessors.">session_eid</a>()); <a name="l01111"></a>01111 <a name="l01112"></a>01112 log_debug(<span class="stringliteral">"handle_session_bundle: got bundle *%p for session %d"</span>, <a name="l01113"></a>01113 bundle, session->id()); <a name="l01114"></a>01114 <a name="l01115"></a>01115 <span class="comment">// XXX/demmer handle reload from db...</span> <a name="l01116"></a>01116 <span class="keywordflow">if</span> (event-><a class="code" href="classdtn_1_1BundleReceivedEvent.html#c65ff559e593a79e83d71978265a0407" title="The source of the bundle.">source_</a> == <a class="code" href="namespacedtn.html#60ee39c9672604f59fe1b12d4e1d142b8fb8e6004d0ab350daca47bdcc106866" title="the data store">EVENTSRC_STORE</a>) { <a name="l01117"></a>01117 log_err(<span class="stringliteral">"handle_session_bundle: can't handle reload from db yet"</span>); <a name="l01118"></a>01118 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01119"></a>01119 } <a name="l01120"></a>01120 <a name="l01121"></a>01121 <span class="keywordtype">bool</span> should_route = <span class="keyword">true</span>; <a name="l01122"></a>01122 <span class="keywordflow">switch</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>()) { <a name="l01123"></a>01123 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498cadd5836fef35cca7c207e710e8e13239">Session::SUBSCRIBE</a>: <a name="l01124"></a>01124 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1Session.html#a795473f389a203d6e15058da8d9498c8ec080183d9e900330780466c77a30be">Session::RESUBSCRIBE</a>: <a name="l01125"></a>01125 { <a name="l01126"></a>01126 <span class="comment">// look for whether we have an upstream route yet. if not,</span> <a name="l01127"></a>01127 <span class="comment">// keep the bundle in queue to forward onwards towards the</span> <a name="l01128"></a>01128 <span class="comment">// session root</span> <a name="l01129"></a>01129 <span class="keywordflow">if</span> (session->upstream().is_null()) { <a name="l01130"></a>01130 log_debug(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01131"></a>01131 <span class="stringliteral">"unknown upstream... trying to find one"</span>); <a name="l01132"></a>01132 <a name="l01133"></a>01133 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1TableBasedRouter.html#6f94fb99000ba969300ffee06b8a2d84" title="Session management helper functions.">find_session_upstream</a>(session)) <a name="l01134"></a>01134 { <a name="l01135"></a>01135 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!session->upstream().is_null()); <a name="l01136"></a>01136 <a name="l01137"></a>01137 <span class="keyword">const</span> <a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a>& upstream = session->upstream(); <a name="l01138"></a>01138 <span class="keywordflow">if</span> (upstream.is_local()) <a name="l01139"></a>01139 { <a name="l01140"></a>01140 log_debug(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01141"></a>01141 <span class="stringliteral">"forwarding %s bundle to upstream registration"</span>, <a name="l01142"></a>01142 <a class="code" href="classdtn_1_1Session.html#f8421d3cc745b485e316195af331fe37" title="Pretty print function for session flags.">Session::flag_str</a>(bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>())); <a name="l01143"></a>01143 upstream.reg()->session_notify(bundle); <a name="l01144"></a>01144 should_route = <span class="keyword">false</span>; <a name="l01145"></a>01145 } <a name="l01146"></a>01146 <span class="keywordflow">else</span> <a name="l01147"></a>01147 { <a name="l01148"></a>01148 log_debug(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01149"></a>01149 <span class="stringliteral">"found upstream *%p... routing bundle"</span>, <a name="l01150"></a>01150 &upstream); <a name="l01151"></a>01151 } <a name="l01152"></a>01152 } <a name="l01153"></a>01153 <span class="keywordflow">else</span> <a name="l01154"></a>01154 { <a name="l01155"></a>01155 <span class="comment">// XXX/demmer what to do here? maybe if we add</span> <a name="l01156"></a>01156 <span class="comment">// something to ack the subscription then this should</span> <a name="l01157"></a>01157 <span class="comment">// defer the ack?</span> <a name="l01158"></a>01158 log_info(<span class="stringliteral">"can't find an upstream for session %s... "</span> <a name="l01159"></a>01159 <span class="stringliteral">"waiting until route arrives"</span>, <a name="l01160"></a>01160 session->eid().c_str()); <a name="l01161"></a>01161 } <a name="l01162"></a>01162 } <a name="l01163"></a>01163 <span class="keywordflow">else</span> <a name="l01164"></a>01164 { <a name="l01165"></a>01165 <span class="keyword">const</span> <a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a>& upstream = session->upstream(); <a name="l01166"></a>01166 log_debug(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01167"></a>01167 <span class="stringliteral">"already subscribed to session through upstream *%p... "</span> <a name="l01168"></a>01168 <span class="stringliteral">"suppressing subscription bundle %u"</span>, <a name="l01169"></a>01169 &upstream, bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l01170"></a>01170 <a name="l01171"></a>01171 bundle-><a class="code" href="classdtn_1_1Bundle.html#249ac137ef76e253d8e0587f2662bca7" title="Accessors.">fwdlog</a>()-><a class="code" href="classdtn_1_1ForwardingLog.html#3a0080cfb70b95af31a780bf71910004" title="Add a new forwarding info entry for the given link.">add_entry</a>(<a class="code" href="classdtn_1_1EndpointIDPattern.html#9f872c8e701944c46b8989257d3188f2" title="Return the special wildcard Endpoint ID.">EndpointIDPattern::WILDCARD_EID</a>(), <a name="l01172"></a>01172 <a class="code" href="classdtn_1_1ForwardingInfo.html#18ec95dc1b1b8a7e9df9873a0d9b59471efad47dbf6015f5e4458ac355eabbaa" title="Forward the bundle to only this next hop.">ForwardingInfo::FORWARD_ACTION</a>, <a name="l01173"></a>01173 <a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fad7e404e025c65c3b35345a69533ce48a1" title="Transmission suppressed.">ForwardingInfo::SUPPRESSED</a>); <a name="l01174"></a>01174 should_route = <span class="keyword">false</span>; <a name="l01175"></a>01175 } <a name="l01176"></a>01176 <a name="l01177"></a>01177 <span class="comment">// add the new subscriber to the session. if the downstream is</span> <a name="l01178"></a>01178 <span class="comment">// already subscribed, then add_subscriber doesn't do</span> <a name="l01179"></a>01179 <span class="comment">// anything. XXX/demmer it should reset the stale subscription</span> <a name="l01180"></a>01180 <span class="comment">// timer...</span> <a name="l01181"></a>01181 <span class="keywordflow">if</span> (event-><a class="code" href="classdtn_1_1BundleReceivedEvent.html#c65ff559e593a79e83d71978265a0407" title="The source of the bundle.">source_</a> == <a class="code" href="namespacedtn.html#60ee39c9672604f59fe1b12d4e1d142bb0775776e4be46e62a0dcff6cf968059" title="a peer dtn forwarder">EVENTSRC_PEER</a>) <a name="l01182"></a>01182 { <a name="l01183"></a>01183 <span class="keywordflow">if</span> (bundle-><a class="code" href="classdtn_1_1Bundle.html#04a51974754438d555bf8a7b0216cd38" title="Accessors.">prevhop</a>().<a class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>() != <span class="stringliteral">""</span> && <a name="l01184"></a>01184 bundle-><a class="code" href="classdtn_1_1Bundle.html#04a51974754438d555bf8a7b0216cd38" title="Accessors.">prevhop</a>() != <a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()) <a name="l01185"></a>01185 { <a name="l01186"></a>01186 log_debug(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01187"></a>01187 <span class="stringliteral">"adding downstream subscriber %s (seqid *%p)"</span>, <a name="l01188"></a>01188 bundle-><a class="code" href="classdtn_1_1Bundle.html#04a51974754438d555bf8a7b0216cd38" title="Accessors.">prevhop</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), &bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()); <a name="l01189"></a>01189 <a name="l01190"></a>01190 <a class="code" href="classdtn_1_1TableBasedRouter.html#81dfb7a82261a5ee3baa1226c4bc2b1c" title="Session management helper functions.">add_subscriber</a>(session, bundle-><a class="code" href="classdtn_1_1Bundle.html#04a51974754438d555bf8a7b0216cd38" title="Accessors.">prevhop</a>(), bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>()); <a name="l01191"></a>01191 } <a name="l01192"></a>01192 <span class="keywordflow">else</span> <a name="l01193"></a>01193 { <a name="l01194"></a>01194 <span class="comment">// XXX/demmer what to do here??</span> <a name="l01195"></a>01195 log_err(<span class="stringliteral">"handle_session_bundle: "</span> <a name="l01196"></a>01196 <span class="stringliteral">"downstream subscriber with no prevhop!!!!"</span>); <a name="l01197"></a>01197 } <a name="l01198"></a>01198 } <a name="l01199"></a>01199 <span class="keywordflow">break</span>; <a name="l01200"></a>01200 } <a name="l01201"></a>01201 <a name="l01202"></a>01202 <span class="keywordflow">default</span>: <a name="l01203"></a>01203 { <a name="l01204"></a>01204 log_err(<span class="stringliteral">"session flags %x not implemented"</span>, bundle-><a class="code" href="classdtn_1_1Bundle.html#973ca2bfa07da25650c14c0b536b0665" title="Accessors.">session_flags</a>()); <a name="l01205"></a>01205 } <a name="l01206"></a>01206 } <a name="l01207"></a>01207 <a name="l01208"></a>01208 <span class="keywordflow">return</span> should_route; <a name="l01209"></a>01209 } <a name="l01210"></a>01210 <a name="l01211"></a>01211 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01212"></a>01212 <span class="keywordtype">void</span> <a name="l01213"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#5a20afd32a3841641b60c8dab2c55986">01213</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#5a20afd32a3841641b60c8dab2c55986" title="Session management helper functions.">TableBasedRouter::reroute_all_sessions</a>() <a name="l01214"></a>01214 { <a name="l01215"></a>01215 log_debug(<span class="stringliteral">"reroute_all_bundles... %zu sessions"</span>, <a name="l01216"></a>01216 <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#7878235ba9b30c17658a5fb98255d26f">size</a>()); <a name="l01217"></a>01217 <a name="l01218"></a>01218 <span class="keywordflow">for</span> (<a class="code" href="classdtn_1_1SessionTable.html#d1af7ce866796bf34ff9b30f9856373c">SessionTable::iterator</a> iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#4f384f9dbca2bb7cbcb555df66208d00">begin</a>(); <a name="l01219"></a>01219 iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#15781c2af48938de09c75f010e40071a" title="Session state management table.">sessions_</a>.<a class="code" href="classdtn_1_1SessionTable.html#c3afe4607f66eca775fab03ffdbf88f9">end</a>(); ++iter) <a name="l01220"></a>01220 { <a name="l01221"></a>01221 <a class="code" href="classdtn_1_1TableBasedRouter.html#6f94fb99000ba969300ffee06b8a2d84" title="Session management helper functions.">find_session_upstream</a>(iter->second); <a name="l01222"></a>01222 } <a name="l01223"></a>01223 } <a name="l01224"></a>01224 <a name="l01225"></a>01225 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01226"></a>01226 <span class="keywordtype">bool</span> <a name="l01227"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#6f94fb99000ba969300ffee06b8a2d84">01227</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#6f94fb99000ba969300ffee06b8a2d84" title="Session management helper functions.">TableBasedRouter::find_session_upstream</a>(<a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session) <a name="l01228"></a>01228 { <a name="l01229"></a>01229 <span class="comment">// first look for a local custody registration</span> <a name="l01230"></a>01230 <span class="keywordflow">for</span> (RegistrationList::iterator iter = <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.begin(); <a name="l01231"></a>01231 iter != <a class="code" href="classdtn_1_1TableBasedRouter.html#82bda89e14b56877e7b4dce41ebd5261" title="Vector of session custodian registrations.">session_custodians_</a>.end(); ++iter) <a name="l01232"></a>01232 { <a name="l01233"></a>01233 <a class="code" href="classdtn_1_1Registration.html" title="Class used to represent an &quot;application&quot; registration, loosely defined...">Registration</a>* reg = *iter; <a name="l01234"></a>01234 <span class="keywordflow">if</span> (reg-><a class="code" href="classdtn_1_1Registration.html#590e683ae3d0a33456e7f0fa0a2a89d5" title="Accessors.">endpoint</a>().<a class="code" href="classdtn_1_1EndpointIDPattern.html#551ee984666d2079f9ccdc5514dcbdc6" title="Shortcut to the matching functionality implemented by the scheme.">match</a>(session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>())) { <a name="l01235"></a>01235 <a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a> new_upstream(reg); <a name="l01236"></a>01236 <span class="keywordflow">if</span> (session-><a class="code" href="classdtn_1_1Session.html#d483d580e9a1e213e974cb41b875065b">upstream</a>() == new_upstream) { <a name="l01237"></a>01237 log_debug(<span class="stringliteral">"find_session_upstream: "</span> <a name="l01238"></a>01238 <span class="stringliteral">"session %s upstream custody registration %d unchanged"</span>, <a name="l01239"></a>01239 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01240"></a>01240 } <span class="keywordflow">else</span> { <a name="l01241"></a>01241 log_debug(<span class="stringliteral">"find_session_upstream: "</span> <a name="l01242"></a>01242 <span class="stringliteral">"session %s found new custody registration %d"</span>, <a name="l01243"></a>01243 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), reg-><a class="code" href="classdtn_1_1Registration.html#d1cd25dd8e4c512591849f44e7c8090b" title="Accessors.">regid</a>()); <a name="l01244"></a>01244 session-><a class="code" href="classdtn_1_1Session.html#4226535ee200c42854fb5fd040134dbd">set_upstream</a>(new_upstream); <a name="l01245"></a>01245 } <a name="l01246"></a>01246 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01247"></a>01247 } <a name="l01248"></a>01248 } <a name="l01249"></a>01249 <a name="l01250"></a>01250 <span class="comment">// XXX/demmer for now this just looks up the route for the</span> <a name="l01251"></a>01251 <span class="comment">// bundle destination (which should be in the dtn-session: scheme)</span> <a name="l01252"></a>01252 <span class="comment">// and extracts the next hop from that</span> <a name="l01253"></a>01253 <a class="code" href="classdtn_1_1RouteEntryVec.html" title="Class for a vector of route entries.">RouteEntryVec</a> matches; <a name="l01254"></a>01254 RouteEntryVec::iterator iter; <a name="l01255"></a>01255 <a name="l01256"></a>01256 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> subscribe_eid(<span class="stringliteral">"dtn-session:"</span> + session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>()); <a name="l01257"></a>01257 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#dceb882f843c17db3afd73521bc78c6d" title="Fill in the entry_vec with the list of all entries whose patterns match the given...">get_matching</a>(subscribe_eid, &matches); <a name="l01258"></a>01258 <a name="l01259"></a>01259 <span class="comment">// XXX/demmer do something about this...</span> <a name="l01260"></a>01260 <span class="comment">// sort_routes(bundle, &matches);</span> <a name="l01261"></a>01261 <a name="l01262"></a>01262 <span class="keywordflow">for</span> (iter = matches.begin(); iter != matches.end(); ++iter) <a name="l01263"></a>01263 { <a name="l01264"></a>01264 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link = (*iter)->link(); <a name="l01265"></a>01265 <span class="keywordflow">if</span> (link->remote_eid().str() == <span class="stringliteral">""</span> || <a name="l01266"></a>01266 link->remote_eid() == <a class="code" href="classdtn_1_1EndpointID.html#31bd1844cae5e71cc2393a139c9bec4c" title="Return the special endpoint id used for the null endpoint, namely &quot;dtn:none&quot;...">EndpointID::NULL_EID</a>()) <a name="l01267"></a>01267 { <a name="l01268"></a>01268 log_warn(<span class="stringliteral">"find_session_upstream: "</span> <a name="l01269"></a>01269 <span class="stringliteral">"got route match with no remote eid"</span>); <a name="l01270"></a>01270 <span class="comment">// XXX/demmer uh...</span> <a name="l01271"></a>01271 <span class="keywordflow">continue</span>; <a name="l01272"></a>01272 } <a name="l01273"></a>01273 <a name="l01274"></a>01274 <a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a> new_upstream(link->remote_eid()); <a name="l01275"></a>01275 <span class="keywordflow">if</span> (session-><a class="code" href="classdtn_1_1Session.html#d483d580e9a1e213e974cb41b875065b">upstream</a>() == new_upstream) { <a name="l01276"></a>01276 log_debug(<span class="stringliteral">"find_session_upstream: "</span> <a name="l01277"></a>01277 <span class="stringliteral">"session %s found existing upstream %s"</span>, <a name="l01278"></a>01278 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), link->remote_eid().c_str()); <a name="l01279"></a>01279 } <span class="keywordflow">else</span> { <a name="l01280"></a>01280 log_debug(<span class="stringliteral">"find_session_upstream: session %s new upstream %s"</span>, <a name="l01281"></a>01281 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), link->remote_eid().c_str()); <a name="l01282"></a>01282 session-><a class="code" href="classdtn_1_1Session.html#4226535ee200c42854fb5fd040134dbd">set_upstream</a>(<a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a>(link->remote_eid())); <a name="l01283"></a>01283 <a class="code" href="classdtn_1_1TableBasedRouter.html#81dfb7a82261a5ee3baa1226c4bc2b1c" title="Session management helper functions.">add_subscriber</a>(session, link->remote_eid(), <a class="code" href="classdtn_1_1SequenceID.html" title="A bundle SequenceID is a version vector of (EID, counter) and/or (EID, identifier)...">SequenceID</a>()); <a name="l01284"></a>01284 } <a name="l01285"></a>01285 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01286"></a>01286 } <a name="l01287"></a>01287 <a name="l01288"></a>01288 log_warn(<span class="stringliteral">"find_session_upstream: can't find upstream for session %s"</span>, <a name="l01289"></a>01289 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>()); <a name="l01290"></a>01290 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01291"></a>01291 } <a name="l01292"></a>01292 <a name="l01293"></a>01293 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01294"></a>01294 <span class="keywordtype">void</span> <a name="l01295"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#81dfb7a82261a5ee3baa1226c4bc2b1c">01295</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#81dfb7a82261a5ee3baa1226c4bc2b1c" title="Session management helper functions.">TableBasedRouter::add_subscriber</a>(<a class="code" href="classdtn_1_1Session.html" title="Class to manage a session.">Session</a>* session, <a name="l01296"></a>01296 <span class="keyword">const</span> <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a>& peer, <a name="l01297"></a>01297 <span class="keyword">const</span> <a class="code" href="classdtn_1_1SequenceID.html" title="A bundle SequenceID is a version vector of (EID, counter) and/or (EID, identifier)...">SequenceID</a>& known_seqid) <a name="l01298"></a>01298 { <a name="l01299"></a>01299 log_debug(<span class="stringliteral">"adding new subscriber for session %s -> %s"</span>, <a name="l01300"></a>01300 session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), peer.<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>()); <a name="l01301"></a>01301 <a name="l01302"></a>01302 session-><a class="code" href="classdtn_1_1Session.html#92b88bd55939a1766a3f2674ce20482c">add_subscriber</a>(<a class="code" href="classdtn_1_1Subscriber.html" title="A subscriber for a session is either a local registration or a next hop destination...">Subscriber</a>(peer)); <a name="l01303"></a>01303 <a name="l01304"></a>01304 <span class="comment">// XXX/demmer check for duplicates?</span> <a name="l01305"></a>01305 <a name="l01306"></a>01306 <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a> *entry = <span class="keyword">new</span> <a class="code" href="classdtn_1_1RouteEntry.html" title="Class to represent route table entry.">RouteEntry</a>(session-><a class="code" href="classdtn_1_1Session.html#66224a2445e558bacc56d3977909a6d1">eid</a>(), peer); <a name="l01307"></a>01307 entry-><a class="code" href="classdtn_1_1RouteEntry.html#a9dce0a2ce16974778c61c7d559056bc" title="Setters.">set_action</a>(<a class="code" href="classdtn_1_1ForwardingInfo.html#18ec95dc1b1b8a7e9df9873a0d9b594777ba7ba2355d6b87536afc9ef78efeb8" title="Forward a copy of the bundle.">ForwardingInfo::COPY_ACTION</a>); <a name="l01308"></a>01308 <a class="code" href="classdtn_1_1TableBasedRouter.html#83939b60c495ff450a1e95787c811297" title="The routing table.">route_table_</a>-><a class="code" href="classdtn_1_1RouteTable.html#f4563da3a4e78c4784a72e790a831469" title="Add a route entry.">add_entry</a>(entry); <a name="l01309"></a>01309 <a name="l01310"></a>01310 log_debug(<span class="stringliteral">"routing %zu session bundles"</span>, session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#3c50c6f421631a4dd72b7b77b0660bc3" title="Return the size of the list.">size</a>()); <a name="l01311"></a>01311 oasys::ScopeLock l(session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#0d0c9f789f0f7f7d1cda3b4ecf32d2bc" title="Return the internal lock on this list.">lock</a>(), <a name="l01312"></a>01312 <span class="stringliteral">"TableBasedRouter::add_subscriber"</span>); <a name="l01313"></a>01313 <span class="keywordflow">for</span> (<a class="code" href="classdtn_1_1BundleList.html#1d52b8d6bb7d8a07e5d4f5fc4b5b61d2" title="Type for an iterator, which just wraps an stl iterator.">BundleList::iterator</a> iter = session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#24cd371acd62f2f9725ff3f92b55badf" title="Iterator used to iterate through the list.">begin</a>(); <a name="l01314"></a>01314 iter != session-><a class="code" href="classdtn_1_1Session.html#21163251275fc2104de91c66fd9543d8">bundles</a>()-><a class="code" href="classdtn_1_1BundleList.html#19f95941fe436d25ba49ae0b2d8bf2c1" title="Iterator used to mark the end of the list.">end</a>(); ++iter) <a name="l01315"></a>01315 { <a name="l01316"></a>01316 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = *iter; <a name="l01317"></a>01317 <span class="keywordflow">if</span> (! bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>().<a class="code" href="classdtn_1_1SequenceID.html#41640a4837fab3c5ca5fce05f371bbd2" title="Typedefs and wrappers for the entry vector and iterators.">empty</a>() && <a name="l01318"></a>01318 bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>() <= known_seqid) <a name="l01319"></a>01319 { <a name="l01320"></a>01320 log_debug(<span class="stringliteral">"suppressing transmission of bundle %u (seqid *%p) "</span> <a name="l01321"></a>01321 <span class="stringliteral">"to subscriber %s since covered by seqid *%p"</span>, <a name="l01322"></a>01322 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>(), &bundle-><a class="code" href="classdtn_1_1Bundle.html#ce91f55a3fece4d4a562b665a462a5d0" title="Accessors.">sequence_id</a>(), <a name="l01323"></a>01323 peer.<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), &known_seqid); <a name="l01324"></a>01324 bundle-><a class="code" href="classdtn_1_1Bundle.html#249ac137ef76e253d8e0587f2662bca7" title="Accessors.">fwdlog</a>()-><a class="code" href="classdtn_1_1ForwardingLog.html#3a0080cfb70b95af31a780bf71910004" title="Add a new forwarding info entry for the given link.">add_entry</a>(peer, <a class="code" href="classdtn_1_1ForwardingInfo.html#18ec95dc1b1b8a7e9df9873a0d9b594777ba7ba2355d6b87536afc9ef78efeb8" title="Forward a copy of the bundle.">ForwardingInfo::COPY_ACTION</a>, <a name="l01325"></a>01325 <a class="code" href="classdtn_1_1ForwardingInfo.html#acf01ca8a774e80f6f7bf56c2b099fad7e404e025c65c3b35345a69533ce48a1" title="Transmission suppressed.">ForwardingInfo::SUPPRESSED</a>); <a name="l01326"></a>01326 <span class="keywordflow">continue</span>; <a name="l01327"></a>01327 } <a name="l01328"></a>01328 <a name="l01329"></a>01329 <a class="code" href="classdtn_1_1TableBasedRouter.html#2e313494d5804ecac9399a3685e32734" title="Check the route table entries that match the given bundle and have not already been...">route_bundle</a>(*iter); <a name="l01330"></a>01330 } <a name="l01331"></a>01331 } <a name="l01332"></a>01332 <a name="l01333"></a>01333 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01334"></a>01334 <span class="keywordtype">void</span> <a name="l01335"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#14f12535527828c3a8e76f97f00c584c">01335</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#14f12535527828c3a8e76f97f00c584c" title="Event handlers.">TableBasedRouter::handle_registration_removed</a>(<a class="code" href="classdtn_1_1RegistrationRemovedEvent.html" title="Event class for registration removals.">RegistrationRemovedEvent</a>* event) <a name="l01336"></a>01336 { <a name="l01337"></a>01337 (void)event; <a name="l01338"></a>01338 } <a name="l01339"></a>01339 <a name="l01340"></a>01340 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01341"></a>01341 <span class="keywordtype">void</span> <a name="l01342"></a><a class="code" href="classdtn_1_1TableBasedRouter.html#777585bc5c45196cd7426c08f47375d5">01342</a> <a class="code" href="classdtn_1_1TableBasedRouter.html#777585bc5c45196cd7426c08f47375d5" title="Event handlers.">TableBasedRouter::handle_registration_expired</a>(<a class="code" href="classdtn_1_1RegistrationExpiredEvent.html" title="Event class for registration expiration.">RegistrationExpiredEvent</a>* event) <a name="l01343"></a>01343 { <a name="l01344"></a>01344 <span class="comment">// XXX/demmer lookup session and remove reg from subscribers</span> <a name="l01345"></a>01345 <span class="comment">// and/or remove the whole session if reg is the custodian</span> <a name="l01346"></a>01346 (void)event; <a name="l01347"></a>01347 } <a name="l01348"></a>01348 <a name="l01349"></a>01349 <a name="l01350"></a>01350 } <span class="comment">// namespace dtn</span> </pre></div></div> <hr size="1"><address style="text-align: right;"><small>Generated on Mon Jul 21 14:09:47 2008 for DTN Reference Implementation by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.6 </small></address> </body> </html>