<!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: StreamConvergenceLayer.cc Source File</title> <link href="tabs.css" rel="stylesheet" type="text/css"> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.5.8 --> <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> <div class="tabs"> <ul> <li><a href="files.html"><span>File List</span></a></li> <li><a href="globals.html"><span>File Members</span></a></li> </ul> </div> <h1>StreamConvergenceLayer.cc</h1><a href="StreamConvergenceLayer_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 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 <oasys/util/OptParser.h></span> <a name="l00022"></a>00022 <span class="preprocessor">#include "<a class="code" href="StreamConvergenceLayer_8h.html">StreamConvergenceLayer.h</a>"</span> <a name="l00023"></a>00023 <span class="preprocessor">#include "<a class="code" href="BundleDaemon_8h.html">bundling/BundleDaemon.h</a>"</span> <a name="l00024"></a>00024 <span class="preprocessor">#include "<a class="code" href="SDNV_8h.html">bundling/SDNV.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="ContactManager_8h.html">contacts/ContactManager.h</a>"</span> <a name="l00027"></a>00027 <a name="l00028"></a>00028 <span class="keyword">namespace </span>dtn { <a name="l00029"></a>00029 <a name="l00030"></a>00030 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00031"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#2f8152afdfad87f6b57856fe55f770d7">00031</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#2f8152afdfad87f6b57856fe55f770d7">StreamConvergenceLayer::StreamLinkParams::StreamLinkParams</a>(<span class="keywordtype">bool</span> init_defaults) <a name="l00032"></a>00032 : <a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html" title="Tunable parameter structure stored in each Link&#39;s CLInfo slot.">LinkParams</a>(init_defaults), <a name="l00033"></a>00033 segment_ack_enabled_(true), <a name="l00034"></a>00034 negative_ack_enabled_(true), <a name="l00035"></a>00035 keepalive_interval_(10), <a name="l00036"></a>00036 segment_length_(4096) <a name="l00037"></a>00037 { <a name="l00038"></a>00038 } <a name="l00039"></a>00039 <a name="l00040"></a>00040 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00041"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer.html#096660d9de60059df676728759749ac7">00041</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#096660d9de60059df676728759749ac7" title="Constructor.">StreamConvergenceLayer::StreamConvergenceLayer</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* logpath, <a name="l00042"></a>00042 <span class="keyword">const</span> <span class="keywordtype">char</span>* cl_name, <a name="l00043"></a>00043 u_int8_t cl_version) <a name="l00044"></a>00044 : <a class="code" href="classdtn_1_1ConnectionConvergenceLayer.html" title="All convergence layers that maintain a connection (i.e.">ConnectionConvergenceLayer</a>(logpath, cl_name), <a name="l00045"></a>00045 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#431ccce6bc6e45cec1203705791716f3" title="Version of the actual CL protocol.">cl_version_</a>(cl_version) <a name="l00046"></a>00046 { <a name="l00047"></a>00047 } <a name="l00048"></a>00048 <a name="l00049"></a>00049 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00050"></a>00050 <span class="keywordtype">bool</span> <a name="l00051"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7ff0e15422faa7ab806b1945bf598e56">00051</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7ff0e15422faa7ab806b1945bf598e56" title="Virtual from ConnectionConvergenceLayer.">StreamConvergenceLayer::parse_link_params</a>(<a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html" title="Tunable parameter structure stored in each Link&#39;s CLInfo slot.">LinkParams</a>* lparams, <a name="l00052"></a>00052 <span class="keywordtype">int</span> argc, <span class="keyword">const</span> <span class="keywordtype">char</span>** argv, <a name="l00053"></a>00053 <span class="keyword">const</span> <span class="keywordtype">char</span>** invalidp) <a name="l00054"></a>00054 { <a name="l00055"></a>00055 <span class="comment">// all subclasses should create a params structure that derives</span> <a name="l00056"></a>00056 <span class="comment">// from StreamLinkParams</span> <a name="l00057"></a>00057 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>*<span class="keyword">></span>(lparams); <a name="l00058"></a>00058 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(params != NULL); <a name="l00059"></a>00059 <a name="l00060"></a>00060 oasys::OptParser p; <a name="l00061"></a>00061 <a name="l00062"></a>00062 p.addopt(<span class="keyword">new</span> oasys::BoolOpt(<span class="stringliteral">"segment_ack_enabled"</span>, <a name="l00063"></a>00063 &params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a>)); <a name="l00064"></a>00064 <a name="l00065"></a>00065 p.addopt(<span class="keyword">new</span> oasys::BoolOpt(<span class="stringliteral">"negative_ack_enabled"</span>, <a name="l00066"></a>00066 &params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#909f9c1ec500b8bcbe27753150a96435" title="Enable negative acks.">negative_ack_enabled_</a>)); <a name="l00067"></a>00067 <a name="l00068"></a>00068 p.addopt(<span class="keyword">new</span> oasys::UIntOpt(<span class="stringliteral">"keepalive_interval"</span>, <a name="l00069"></a>00069 &params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a>)); <a name="l00070"></a>00070 <a name="l00071"></a>00071 p.addopt(<span class="keyword">new</span> oasys::UIntOpt(<span class="stringliteral">"segment_length"</span>, <a name="l00072"></a>00072 &params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#f84af5832d28b56241e1ca6f23b757b6" title="Maximum size of transmitted segments.">segment_length_</a>)); <a name="l00073"></a>00073 <a name="l00074"></a>00074 p.addopt(<span class="keyword">new</span> oasys::UInt8Opt(<span class="stringliteral">"cl_version"</span>, <a name="l00075"></a>00075 &<a class="code" href="classdtn_1_1StreamConvergenceLayer.html#431ccce6bc6e45cec1203705791716f3" title="Version of the actual CL protocol.">cl_version_</a>)); <a name="l00076"></a>00076 <a name="l00077"></a>00077 <span class="keywordtype">int</span> <a class="code" href="dtnping_8c.html#d43c3812e6d13e0518d9f8b8f463ffcf">count</a> = p.parse_and_shift(argc, argv, invalidp); <a name="l00078"></a>00078 <span class="keywordflow">if</span> (count == -1) { <a name="l00079"></a>00079 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00080"></a>00080 } <a name="l00081"></a>00081 argc -= count; <a name="l00082"></a>00082 <a name="l00083"></a>00083 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7ff0e15422faa7ab806b1945bf598e56" title="Virtual from ConnectionConvergenceLayer.">ConnectionConvergenceLayer::parse_link_params</a>(lparams, argc, argv, <a name="l00084"></a>00084 invalidp); <a name="l00085"></a>00085 } <a name="l00086"></a>00086 <a name="l00087"></a>00087 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00088"></a>00088 <span class="keywordtype">bool</span> <a name="l00089"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer.html#6164b894bc7b0f10951c57484a4c3c43">00089</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#6164b894bc7b0f10951c57484a4c3c43" title="Virtual from ConnectionConvergenceLayer.">StreamConvergenceLayer::finish_init_link</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="l00090"></a>00090 <a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html" title="Tunable parameter structure stored in each Link&#39;s CLInfo slot.">LinkParams</a>* lparams) <a name="l00091"></a>00091 { <a name="l00092"></a>00092 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>*<span class="keyword">></span>(lparams); <a name="l00093"></a>00093 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(params != NULL); <a name="l00094"></a>00094 <a name="l00095"></a>00095 <span class="comment">// make sure to set the reliability bit in the link structure</span> <a name="l00096"></a>00096 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a>) { <a name="l00097"></a>00097 link->set_reliable(<span class="keyword">true</span>); <a name="l00098"></a>00098 } <a name="l00099"></a>00099 <a name="l00100"></a>00100 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00101"></a>00101 } <a name="l00102"></a>00102 <a name="l00103"></a>00103 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00104"></a>00104 <span class="keywordtype">void</span> <a name="l00105"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer.html#a6c4edd67ccbef20b2da705474048fed">00105</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#a6c4edd67ccbef20b2da705474048fed" title="Virtual from ConvergenceLayer.">StreamConvergenceLayer::dump_link</a>(<span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link, oasys::StringBuffer* <a class="code" href="num2sdnv_8c.html#a81cdcc7ff6987bc85c073253e32715f">buf</a>) <a name="l00106"></a>00106 { <a name="l00107"></a>00107 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link != NULL); <a name="l00108"></a>00108 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!link->isdeleted()); <a name="l00109"></a>00109 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(link->cl_info() != NULL); <a name="l00110"></a>00110 <a name="l00111"></a>00111 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#a6c4edd67ccbef20b2da705474048fed" title="Virtual from ConvergenceLayer.">ConnectionConvergenceLayer::dump_link</a>(link, buf); <a name="l00112"></a>00112 <a name="l00113"></a>00113 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <a name="l00114"></a>00114 <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>*<span class="keyword">></span>(link->cl_info()); <a name="l00115"></a>00115 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(params != NULL); <a name="l00116"></a>00116 <a name="l00117"></a>00117 buf->appendf(<span class="stringliteral">"segment_ack_enabled: %u\n"</span>, params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a>); <a name="l00118"></a>00118 buf->appendf(<span class="stringliteral">"negative_ack_enabled: %u\n"</span>, params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#909f9c1ec500b8bcbe27753150a96435" title="Enable negative acks.">negative_ack_enabled_</a>); <a name="l00119"></a>00119 buf->appendf(<span class="stringliteral">"keepalive_interval: %u\n"</span>, params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a>); <a name="l00120"></a>00120 buf->appendf(<span class="stringliteral">"segment_length: %u\n"</span>, params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#f84af5832d28b56241e1ca6f23b757b6" title="Maximum size of transmitted segments.">segment_length_</a>); <a name="l00121"></a>00121 } <a name="l00122"></a>00122 <a name="l00123"></a>00123 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00124"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#589a28b08f149fc893b90a6c25a66b4b">00124</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#589a28b08f149fc893b90a6c25a66b4b" title="Constructor.">StreamConvergenceLayer::Connection::Connection</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* classname, <a name="l00125"></a>00125 <span class="keyword">const</span> <span class="keywordtype">char</span>* logpath, <a name="l00126"></a>00126 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html" title="Another shared-implementation convergence layer class for use with reliable, in-order...">StreamConvergenceLayer</a>* cl, <a name="l00127"></a>00127 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params, <a name="l00128"></a>00128 <span class="keywordtype">bool</span> active_connector) <a name="l00129"></a>00129 : <a class="code" href="classdtn_1_1CLConnection.html" title="Helper class (and thread) that manages an established connection with a peer daemon...">CLConnection</a>(classname, logpath, cl, params, active_connector), <a name="l00130"></a>00130 current_inflight_(NULL), <a name="l00131"></a>00131 send_segment_todo_(0), <a name="l00132"></a>00132 recv_segment_todo_(0), <a name="l00133"></a>00133 breaking_contact_(false), <a name="l00134"></a>00134 contact_initiated_(false) <a name="l00135"></a>00135 { <a name="l00136"></a>00136 } <a name="l00137"></a>00137 <a name="l00138"></a>00138 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00139"></a>00139 <span class="keywordtype">void</span> <a name="l00140"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#db6e45fa1f3fdf6e3e753df0cfb792c8">00140</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#db6e45fa1f3fdf6e3e753df0cfb792c8" title="utility functions used by derived classes">StreamConvergenceLayer::Connection::initiate_contact</a>() <a name="l00141"></a>00141 { <a name="l00142"></a>00142 log_debug(<span class="stringliteral">"initiate_contact called"</span>); <a name="l00143"></a>00143 <a name="l00144"></a>00144 <span class="comment">// format the contact header</span> <a name="l00145"></a>00145 <a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a> contacthdr; <a name="l00146"></a>00146 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#100178e791d70d34681bec8f940eb60d" title="magic word (MAGIC: &quot;dtn!&quot;)">magic</a> = htonl(<a class="code" href="classdtn_1_1ConvergenceLayer.html#ad24e6696bcaced432991049dbfc40c7" title="Magic number used for DTN convergence layers.">MAGIC</a>); <a name="l00147"></a>00147 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#f92367a32a108c3c2eb8b61ffa6bc99a" title="cl protocol version">version</a> = ((<a class="code" href="classdtn_1_1StreamConvergenceLayer.html" title="Another shared-implementation convergence layer class for use with reliable, in-order...">StreamConvergenceLayer</a>*)<a class="code" href="classdtn_1_1CLConnection.html#99b84b09e39381998c5a918579853a30" title="Pointer to the CL.">cl_</a>)->cl_version_; <a name="l00148"></a>00148 <a name="l00149"></a>00149 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> = 0; <a name="l00150"></a>00150 <a name="l00151"></a>00151 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#f143ebd2efeaa6adc4b5fcc0e01e367d" title="Utility function to downcast the params_ pointer that&#39;s stored in the CLConnection...">stream_lparams</a>(); <a name="l00152"></a>00152 <a name="l00153"></a>00153 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a>) <a name="l00154"></a>00154 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> |= <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#22063658b9cd2c7a894688ecca86153680b34f4cf0349121806fbddf754ead76" title="segment acks requested">SEGMENT_ACK_ENABLED</a>; <a name="l00155"></a>00155 <a name="l00156"></a>00156 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#07a52c18ea031a370e2119c9fbd20f96" title="Is reactive fragmentation enabled.">reactive_frag_enabled_</a>) <a name="l00157"></a>00157 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> |= <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#22063658b9cd2c7a894688ecca8615367037a814236c37362d50f76e5d9508d6" title="reactive fragmentation enabled">REACTIVE_FRAG_ENABLED</a>; <a name="l00158"></a>00158 <a name="l00159"></a>00159 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#41a243b98016a50c0f586403030e4e2c" title="seconds between keepalive packets">keepalive_interval</a> = htons(params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a>); <a name="l00160"></a>00160 <a name="l00161"></a>00161 <span class="comment">// copy the contact header into the send buffer</span> <a name="l00162"></a>00162 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fullbytes() == 0); <a name="l00163"></a>00163 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() < <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)) { <a name="l00164"></a>00164 log_warn(<span class="stringliteral">"send buffer too short: %zu < needed %zu"</span>, <a name="l00165"></a>00165 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes(), <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00166"></a>00166 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.reserve(<span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00167"></a>00167 } <a name="l00168"></a>00168 <a name="l00169"></a>00169 memcpy(<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.start(), &contacthdr, <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00170"></a>00170 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(<span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00171"></a>00171 <a name="l00172"></a>00172 <span class="comment">// follow up with the local endpoint id length + data</span> <a name="l00173"></a>00173 <a class="code" href="classdtn_1_1BundleDaemon.html" title="Class that handles the basic event / action mechanism.">BundleDaemon</a>* bd = BundleDaemon::instance(); <a name="l00174"></a>00174 <span class="keywordtype">size_t</span> local_eid_len = bd-><a class="code" href="classdtn_1_1BundleDaemon.html#f606a71844413e32918c9c3e98b8ce3f" title="Return the local endpoint identifier.">local_eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#3ed7639ed8794ea8045bb5d16128c5f5">length</a>(); <a name="l00175"></a>00175 <span class="keywordtype">size_t</span> sdnv_len = <a class="code" href="SDNV_8cc.html#46f4c114c92230c80f6714318251b542">SDNV::encoding_len</a>(local_eid_len); <a name="l00176"></a>00176 <a name="l00177"></a>00177 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() < sdnv_len + local_eid_len) { <a name="l00178"></a>00178 log_warn(<span class="stringliteral">"send buffer too short: %zu < needed %zu"</span>, <a name="l00179"></a>00179 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes(), sdnv_len + local_eid_len); <a name="l00180"></a>00180 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.reserve(sdnv_len + local_eid_len); <a name="l00181"></a>00181 } <a name="l00182"></a>00182 <a name="l00183"></a>00183 sdnv_len = <a class="code" href="SDNV_8cc.html#21c54ef3a5345647ad1cada265a03eb4">SDNV::encode</a>(local_eid_len, <a name="l00184"></a>00184 (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end(), <a name="l00185"></a>00185 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes()); <a name="l00186"></a>00186 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(sdnv_len); <a name="l00187"></a>00187 <a name="l00188"></a>00188 memcpy(<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end(), bd-><a class="code" href="classdtn_1_1BundleDaemon.html#f606a71844413e32918c9c3e98b8ce3f" title="Return the local endpoint identifier.">local_eid</a>().<a class="code" href="classdtn_1_1EndpointID.html#e88d5a7398d69c8deb9730cf8edfcf29">data</a>(), local_eid_len); <a name="l00189"></a>00189 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(local_eid_len); <a name="l00190"></a>00190 <a name="l00191"></a>00191 <span class="comment">// drain the send buffer</span> <a name="l00192"></a>00192 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#9ef41c9f94581292808d7e50472ab07b" title="utility functions used internally in this class">note_data_sent</a>(); <a name="l00193"></a>00193 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bbdabd686c5d5e5a9bf30706a7ab849c" title="Hook used to tell the derived CL class to drain data out of the send buffer.">send_data</a>(); <a name="l00194"></a>00194 <a name="l00195"></a>00195 <span class="comment">/*</span> <a name="l00196"></a>00196 <span class="comment"> * Now we initialize the various timers that are used for</span> <a name="l00197"></a>00197 <span class="comment"> * keepalives / idle timeouts to make sure they're not used</span> <a name="l00198"></a>00198 <span class="comment"> * uninitialized.</span> <a name="l00199"></a>00199 <span class="comment"> */</span><a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00200"></a>00200 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>, 0);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00201"></a>00201 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#40cc6956b2b157b5f4ef4ef9734cead0" title="Timestamp for idle timer.">data_sent_</a>, 0);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00202"></a>00202 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#d7be9e6fb91ba7620f8e5172c4643e1b" title="Timestamp for keepalive timer.">keepalive_sent_</a>, 0); <a name="l00203"></a>00203 <a name="l00204"></a>00204 <a name="l00205"></a>00205 <span class="comment">// XXX/demmer need to add a test for nothing coming back</span> <a name="l00206"></a>00206 <a name="l00207"></a>00207 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#334e73df91eb3303aae9c96c8b7c7301">contact_initiated_</a> = <span class="keyword">true</span>; <a name="l00208"></a>00208 } <a name="l00209"></a>00209 <a name="l00210"></a>00210 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00211"></a>00211 <span class="keywordtype">void</span> <a name="l00212"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#fe8bc46331b10ed587f6c11e2a5be757">00212</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#fe8bc46331b10ed587f6c11e2a5be757" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_contact_initiation</a>() <a name="l00213"></a>00213 { <a name="l00214"></a>00214 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(! <a class="code" href="classdtn_1_1CLConnection.html#5712e80e8d3608ae67709fd8adf53bbe" title="Has contact_up been called.">contact_up_</a>); <a name="l00215"></a>00215 <a name="l00216"></a>00216 <span class="comment">/*</span> <a name="l00217"></a>00217 <span class="comment"> * First check for valid magic number.</span> <a name="l00218"></a>00218 <span class="comment"> */</span> <a name="l00219"></a>00219 u_int32_t magic = 0; <a name="l00220"></a>00220 <span class="keywordtype">size_t</span> len_needed = <span class="keyword">sizeof</span>(magic); <a name="l00221"></a>00221 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() < len_needed) { <a name="l00222"></a>00222 tooshort: <a name="l00223"></a>00223 log_debug(<span class="stringliteral">"handle_contact_initiation: not enough data received "</span> <a name="l00224"></a>00224 <span class="stringliteral">"(need > %zu, got %zu)"</span>, <a name="l00225"></a>00225 len_needed, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l00226"></a>00226 <span class="keywordflow">return</span>; <a name="l00227"></a>00227 } <a name="l00228"></a>00228 <a name="l00229"></a>00229 memcpy(&magic, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(), <span class="keyword">sizeof</span>(magic)); <a name="l00230"></a>00230 magic = ntohl(magic); <a name="l00231"></a>00231 <a name="l00232"></a>00232 <span class="keywordflow">if</span> (magic != <a class="code" href="classdtn_1_1ConvergenceLayer.html#ad24e6696bcaced432991049dbfc40c7" title="Magic number used for DTN convergence layers.">MAGIC</a>) { <a name="l00233"></a>00233 log_warn(<span class="stringliteral">"remote sent magic number 0x%.8x, expected 0x%.8x "</span> <a name="l00234"></a>00234 <span class="stringliteral">"-- disconnecting."</span>, magic, <a class="code" href="classdtn_1_1ConvergenceLayer.html#ad24e6696bcaced432991049dbfc40c7" title="Magic number used for DTN convergence layers.">MAGIC</a>); <a name="l00235"></a>00235 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l00236"></a>00236 oasys::Breaker::break_here(); <a name="l00237"></a>00237 <span class="keywordflow">return</span>; <a name="l00238"></a>00238 } <a name="l00239"></a>00239 <a name="l00240"></a>00240 <span class="comment">/*</span> <a name="l00241"></a>00241 <span class="comment"> * Now check that we got a full contact header</span> <a name="l00242"></a>00242 <span class="comment"> */</span> <a name="l00243"></a>00243 len_needed = <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>); <a name="l00244"></a>00244 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() < len_needed) { <a name="l00245"></a>00245 <span class="keywordflow">goto</span> tooshort; <a name="l00246"></a>00246 } <a name="l00247"></a>00247 <a name="l00248"></a>00248 <span class="comment">/*</span> <a name="l00249"></a>00249 <span class="comment"> * Now check for enough data for the peer's eid</span> <a name="l00250"></a>00250 <span class="comment"> */</span> <a name="l00251"></a>00251 u_int64_t peer_eid_len; <a name="l00252"></a>00252 <span class="keywordtype">int</span> sdnv_len = <a class="code" href="SDNV_8cc.html#151d178617a7c2f598cfd7630ebeb7b4">SDNV::decode</a>((u_char*)<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start() + <a name="l00253"></a>00253 <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>), <a name="l00254"></a>00254 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() - <a name="l00255"></a>00255 <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>), <a name="l00256"></a>00256 &peer_eid_len); <a name="l00257"></a>00257 <span class="keywordflow">if</span> (sdnv_len < 0) { <a name="l00258"></a>00258 <span class="keywordflow">goto</span> tooshort; <a name="l00259"></a>00259 } <a name="l00260"></a>00260 <a name="l00261"></a>00261 len_needed = <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>) + sdnv_len + peer_eid_len; <a name="l00262"></a>00262 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() < len_needed) { <a name="l00263"></a>00263 <span class="keywordflow">goto</span> tooshort; <a name="l00264"></a>00264 } <a name="l00265"></a>00265 <a name="l00266"></a>00266 <span class="comment">/*</span> <a name="l00267"></a>00267 <span class="comment"> * Ok, we have enough data, parse the contact header.</span> <a name="l00268"></a>00268 <span class="comment"> */</span> <a name="l00269"></a>00269 <a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a> contacthdr; <a name="l00270"></a>00270 memcpy(&contacthdr, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(), <span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00271"></a>00271 <a name="l00272"></a>00272 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#100178e791d70d34681bec8f940eb60d" title="magic word (MAGIC: &quot;dtn!&quot;)">magic</a> = ntohl(contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#100178e791d70d34681bec8f940eb60d" title="magic word (MAGIC: &quot;dtn!&quot;)">magic</a>); <a name="l00273"></a>00273 contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#41a243b98016a50c0f586403030e4e2c" title="seconds between keepalive packets">keepalive_interval</a> = ntohs(contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#41a243b98016a50c0f586403030e4e2c" title="seconds between keepalive packets">keepalive_interval</a>); <a name="l00274"></a>00274 <a name="l00275"></a>00275 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(<span class="keyword">sizeof</span>(<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html" title="Contact initiation header.">ContactHeader</a>)); <a name="l00276"></a>00276 <a name="l00277"></a>00277 <span class="comment">/*</span> <a name="l00278"></a>00278 <span class="comment"> * In this implementation, we can't handle other versions than our</span> <a name="l00279"></a>00279 <span class="comment"> * own, but if the other side presents a higher version, we allow</span> <a name="l00280"></a>00280 <span class="comment"> * it to go through and thereby allow them to downgrade to this</span> <a name="l00281"></a>00281 <span class="comment"> * version.</span> <a name="l00282"></a>00282 <span class="comment"> */</span> <a name="l00283"></a>00283 u_int8_t cl_version = ((<a class="code" href="classdtn_1_1StreamConvergenceLayer.html" title="Another shared-implementation convergence layer class for use with reliable, in-order...">StreamConvergenceLayer</a>*)<a class="code" href="classdtn_1_1CLConnection.html#99b84b09e39381998c5a918579853a30" title="Pointer to the CL.">cl_</a>)->cl_version_; <a name="l00284"></a>00284 <span class="keywordflow">if</span> (contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#f92367a32a108c3c2eb8b61ffa6bc99a" title="cl protocol version">version</a> < cl_version) { <a name="l00285"></a>00285 log_warn(<span class="stringliteral">"remote sent version %d, expected version %d "</span> <a name="l00286"></a>00286 <span class="stringliteral">"-- disconnecting."</span>, contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#f92367a32a108c3c2eb8b61ffa6bc99a" title="cl protocol version">version</a>, cl_version); <a name="l00287"></a>00287 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f704fb70b2e32b5f6f3e3707dc12958787" title="Convergence layer version mismatch.">ContactEvent::CL_VERSION</a>); <a name="l00288"></a>00288 <span class="keywordflow">return</span>; <a name="l00289"></a>00289 } <a name="l00290"></a>00290 <a name="l00291"></a>00291 <span class="comment">/*</span> <a name="l00292"></a>00292 <span class="comment"> * Now do parameter negotiation.</span> <a name="l00293"></a>00293 <span class="comment"> */</span> <a name="l00294"></a>00294 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#f143ebd2efeaa6adc4b5fcc0e01e367d" title="Utility function to downcast the params_ pointer that&#39;s stored in the CLConnection...">stream_lparams</a>(); <a name="l00295"></a>00295 <a name="l00296"></a>00296 params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> = <a name="l00297"></a>00297 std::min(params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a>, <a name="l00298"></a>00298 (u_int)contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#41a243b98016a50c0f586403030e4e2c" title="seconds between keepalive packets">keepalive_interval</a>); <a name="l00299"></a>00299 <a name="l00300"></a>00300 params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a> = params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#4a217be895b5445882f426d690268ce0" title="Use per-segment acks.">segment_ack_enabled_</a> && <a name="l00301"></a>00301 (contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#22063658b9cd2c7a894688ecca86153680b34f4cf0349121806fbddf754ead76" title="segment acks requested">SEGMENT_ACK_ENABLED</a>); <a name="l00302"></a>00302 <a name="l00303"></a>00303 params-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#07a52c18ea031a370e2119c9fbd20f96" title="Is reactive fragmentation enabled.">reactive_frag_enabled_</a> = params-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#07a52c18ea031a370e2119c9fbd20f96" title="Is reactive fragmentation enabled.">reactive_frag_enabled_</a> && <a name="l00304"></a>00304 (contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#22063658b9cd2c7a894688ecca8615367037a814236c37362d50f76e5d9508d6" title="reactive fragmentation enabled">REACTIVE_FRAG_ENABLED</a>); <a name="l00305"></a>00305 <a name="l00306"></a>00306 params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#909f9c1ec500b8bcbe27753150a96435" title="Enable negative acks.">negative_ack_enabled_</a> = params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#909f9c1ec500b8bcbe27753150a96435" title="Enable negative acks.">negative_ack_enabled_</a> && <a name="l00307"></a>00307 (contacthdr.<a class="code" href="structdtn_1_1StreamConvergenceLayer_1_1ContactHeader.html#ed32bf95f52fd9137ffaddb74b7cf55a" title="connection flags (see above)">flags</a> & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#22063658b9cd2c7a894688ecca861536b71e6c1a74eeee3534bd4a35c6621f68" title="refuse bundle enabled">NEGATIVE_ACK_ENABLED</a>); <a name="l00308"></a>00308 <a name="l00309"></a>00309 <span class="comment">/*</span> <a name="l00310"></a>00310 <span class="comment"> * Make sure to readjust poll_timeout in case we have a smaller</span> <a name="l00311"></a>00311 <span class="comment"> * keepalive interval than data timeout</span> <a name="l00312"></a>00312 <span class="comment"> */</span> <a name="l00313"></a>00313 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> != 0 && <a name="l00314"></a>00314 (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> * 1000) < params-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#7f819ba8a1caa690ff86ce4484ba7329" title="Msecs to wait for data arrival.">data_timeout_</a>) <a name="l00315"></a>00315 { <a name="l00316"></a>00316 <a class="code" href="classdtn_1_1CLConnection.html#b9b601dae1312020426d0d57daca19da" title="Timeout to wait for poll data.">poll_timeout_</a> = params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> * 1000; <a name="l00317"></a>00317 } <a name="l00318"></a>00318 <a name="l00319"></a>00319 <span class="comment">/*</span> <a name="l00320"></a>00320 <span class="comment"> * Now skip the sdnv that encodes the peer's eid length since we</span> <a name="l00321"></a>00321 <span class="comment"> * parsed it above.</span> <a name="l00322"></a>00322 <span class="comment"> */</span> <a name="l00323"></a>00323 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(sdnv_len); <a name="l00324"></a>00324 <a name="l00325"></a>00325 <span class="comment">/*</span> <a name="l00326"></a>00326 <span class="comment"> * Finally, parse the peer node's eid and give it to the base</span> <a name="l00327"></a>00327 <span class="comment"> * class to handle (i.e. by linking us to a Contact if we don't</span> <a name="l00328"></a>00328 <span class="comment"> * have one).</span> <a name="l00329"></a>00329 <span class="comment"> */</span> <a name="l00330"></a>00330 <a class="code" href="classdtn_1_1EndpointID.html">EndpointID</a> peer_eid; <a name="l00331"></a>00331 <span class="keywordflow">if</span> (! peer_eid.<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_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(), peer_eid_len)) { <a name="l00332"></a>00332 log_err(<span class="stringliteral">"protocol error: invalid endpoint id '%s' (len %llu)"</span>, <a name="l00333"></a>00333 peer_eid.<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>(), U64FMT(peer_eid_len)); <a name="l00334"></a>00334 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l00335"></a>00335 <span class="keywordflow">return</span>; <a name="l00336"></a>00336 } <a name="l00337"></a>00337 <a name="l00338"></a>00338 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1CLConnection.html#46186272ffc0c76aedd5e2035e8865b7">find_contact</a>(peer_eid)) { <a name="l00339"></a>00339 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a> == NULL); <a name="l00340"></a>00340 log_debug(<span class="stringliteral">"StreamConvergenceLayer::Connection::"</span> <a name="l00341"></a>00341 <span class="stringliteral">"handle_contact_initiation: failed to find contact"</span>); <a name="l00342"></a>00342 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l00343"></a>00343 <span class="keywordflow">return</span>; <a name="l00344"></a>00344 } <a name="l00345"></a>00345 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(peer_eid_len); <a name="l00346"></a>00346 <a name="l00347"></a>00347 <span class="comment">/*</span> <a name="l00348"></a>00348 <span class="comment"> * Make sure that the link's remote eid field is properly set.</span> <a name="l00349"></a>00349 <span class="comment"> */</span> <a name="l00350"></a>00350 <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a> link = <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link(); <a name="l00351"></a>00351 <span class="keywordflow">if</span> (link->remote_eid().str() == <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 class="code" href="classdtn_1_1EndpointID.html#e214dda88bf43a3576cfcdf76c77c5a9">str</a>()) { <a name="l00352"></a>00352 link->set_remote_eid(peer_eid); <a name="l00353"></a>00353 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (link->remote_eid() != peer_eid) { <a name="l00354"></a>00354 log_warn(<span class="stringliteral">"handle_contact_initiation: remote eid mismatch: "</span> <a name="l00355"></a>00355 <span class="stringliteral">"link remote eid was set to %s but peer eid is %s"</span>, <a name="l00356"></a>00356 link->remote_eid().c_str(), peer_eid.<a class="code" href="classdtn_1_1EndpointID.html#c9d8a72806359621f4d2850c1e78269c">c_str</a>()); <a name="l00357"></a>00357 } <a name="l00358"></a>00358 <a name="l00359"></a>00359 <span class="comment">/*</span> <a name="l00360"></a>00360 <span class="comment"> * Finally, we note that the contact is now up.</span> <a name="l00361"></a>00361 <span class="comment"> */</span> <a name="l00362"></a>00362 <a class="code" href="classdtn_1_1CLConnection.html#1214075456352961d8a70f82f69be0bf">contact_up</a>(); <a name="l00363"></a>00363 } <a name="l00364"></a>00364 <a name="l00365"></a>00365 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00366"></a>00366 <span class="keywordtype">void</span> <a name="l00367"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4efc34a816975a771ef5e9fd48dd1d50">00367</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4efc34a816975a771ef5e9fd48dd1d50" title="virtual from CLConnection">StreamConvergenceLayer::Connection::handle_bundles_queued</a>() <a name="l00368"></a>00368 { <a name="l00369"></a>00369 <span class="comment">// since the main run loop checks the link queue to see if there</span> <a name="l00370"></a>00370 <span class="comment">// are bundles that should be put in flight, we simply log a debug</span> <a name="l00371"></a>00371 <span class="comment">// message here. the point of the message is to kick the thread</span> <a name="l00372"></a>00372 <span class="comment">// out of poll() which forces the main loop to check the queue</span> <a name="l00373"></a>00373 log_debug(<span class="stringliteral">"handle_bundles_queued: %u bundles on link queue"</span>, <a name="l00374"></a>00374 <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link()->bundles_queued()); <a name="l00375"></a>00375 } <a name="l00376"></a>00376 <a name="l00377"></a>00377 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00378"></a>00378 <span class="keywordtype">bool</span> <a name="l00379"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#e7bfa4ed0a7c2a98d06e6e5273ff5a1e">00379</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#e7bfa4ed0a7c2a98d06e6e5273ff5a1e" title="virtual from CLConnection">StreamConvergenceLayer::Connection::send_pending_data</a>() <a name="l00380"></a>00380 { <a name="l00381"></a>00381 <span class="comment">// if the outgoing data buffer is full, we can't do anything until</span> <a name="l00382"></a>00382 <span class="comment">// we poll()</span> <a name="l00383"></a>00383 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() == 0) { <a name="l00384"></a>00384 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00385"></a>00385 } <a name="l00386"></a>00386 <a name="l00387"></a>00387 <span class="comment">// if we're in the middle of sending a segment, we need to continue</span> <a name="l00388"></a>00388 <span class="comment">// sending it. only if we completely send the segment do we fall</span> <a name="l00389"></a>00389 <span class="comment">// through to send acks, otherwise we return to try to finish it</span> <a name="l00390"></a>00390 <span class="comment">// again later.</span> <a name="l00391"></a>00391 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0) { <a name="l00392"></a>00392 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> != NULL); <a name="l00393"></a>00393 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#69b0db2a6c9456baac7c14a04c6b8c46" title="utility functions used internally in this class">send_data_todo</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a>); <a name="l00394"></a>00394 } <a name="l00395"></a>00395 <a name="l00396"></a>00396 <span class="comment">// see if we're broken or write blocked</span> <a name="l00397"></a>00397 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#a61b296b02812f04b3df0c8fb09919b8" title="Contact has been broken.">contact_broken_</a> || (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0)) { <a name="l00398"></a>00398 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#e3408a135a49d68ab36fd8de5805b1fe" title="Pointer to Link parameters, or to defaults until Link is bound.">params_</a>-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#9b77847034f59f7688f281c78d040000" title="Msecs to sleep between write calls.">test_write_delay_</a> != 0) { <a name="l00399"></a>00399 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00400"></a>00400 } <a name="l00401"></a>00401 <a name="l00402"></a>00402 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00403"></a>00403 } <a name="l00404"></a>00404 <a name="l00405"></a>00405 <span class="comment">// now check if there are acks we need to send -- even if it</span> <a name="l00406"></a>00406 <span class="comment">// returns true (i.e. we sent an ack), we continue on and try to</span> <a name="l00407"></a>00407 <span class="comment">// send some real payload data, otherwise we could get starved by</span> <a name="l00408"></a>00408 <span class="comment">// arriving data and never send anything out.</span> <a name="l00409"></a>00409 <span class="keywordtype">bool</span> sent_ack = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#07b8a28fbb18258b3727aed3c8e98815" title="utility functions used internally in this class">send_pending_acks</a>(); <a name="l00410"></a>00410 <a name="l00411"></a>00411 <span class="comment">// if the connection failed during ack transmission, stop</span> <a name="l00412"></a>00412 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#a61b296b02812f04b3df0c8fb09919b8" title="Contact has been broken.">contact_broken_</a>) <a name="l00413"></a>00413 { <a name="l00414"></a>00414 <span class="keywordflow">return</span> sent_ack; <a name="l00415"></a>00415 } <a name="l00416"></a>00416 <a name="l00417"></a>00417 <span class="comment">// check if we need to start a new bundle. if we do, then</span> <a name="l00418"></a>00418 <span class="comment">// start_next_bundle handles the correct return code</span> <a name="l00419"></a>00419 <span class="keywordtype">bool</span> sent_data; <a name="l00420"></a>00420 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> == NULL) { <a name="l00421"></a>00421 sent_data = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4c167905aa71be2b4d4aac383344c240" title="utility functions used internally in this class">start_next_bundle</a>(); <a name="l00422"></a>00422 } <span class="keywordflow">else</span> { <a name="l00423"></a>00423 <span class="comment">// otherwise send the next segment of the current bundle</span> <a name="l00424"></a>00424 sent_data = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#10e5a054fe260ebd06e5daf3095c1d52" title="utility functions used internally in this class">send_next_segment</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a>); <a name="l00425"></a>00425 } <a name="l00426"></a>00426 <a name="l00427"></a>00427 <span class="keywordflow">return</span> sent_ack || sent_data; <a name="l00428"></a>00428 } <a name="l00429"></a>00429 <a name="l00430"></a>00430 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00431"></a>00431 <span class="keywordtype">bool</span> <a name="l00432"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#07b8a28fbb18258b3727aed3c8e98815">00432</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#07b8a28fbb18258b3727aed3c8e98815" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::send_pending_acks</a>() <a name="l00433"></a>00433 { <a name="l00434"></a>00434 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#a61b296b02812f04b3df0c8fb09919b8" title="Contact has been broken.">contact_broken_</a> || <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.empty()) { <a name="l00435"></a>00435 <span class="keywordflow">return</span> <span class="keyword">false</span>; <span class="comment">// nothing to do</span> <a name="l00436"></a>00436 } <a name="l00437"></a>00437 <a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>* incoming = <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.front(); <a name="l00438"></a>00438 DataBitmap::iterator iter = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.begin(); <a name="l00439"></a>00439 <span class="keywordtype">bool</span> generated_ack = <span class="keyword">false</span>; <a name="l00440"></a>00440 <a name="l00441"></a>00441 <span class="comment">// when data segment headers are received, the last bit of the</span> <a name="l00442"></a>00442 <span class="comment">// segment is marked in ack_data, thus if there's nothing in</span> <a name="l00443"></a>00443 <span class="comment">// there, we don't need to send out an ack.</span> <a name="l00444"></a>00444 <span class="keywordflow">if</span> (iter == incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.end() || incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.empty()) { <a name="l00445"></a>00445 <span class="keywordflow">goto</span> check_done; <a name="l00446"></a>00446 } <a name="l00447"></a>00447 <a name="l00448"></a>00448 <span class="comment">// however, we have to be careful to check the recv_data as well</span> <a name="l00449"></a>00449 <span class="comment">// to make sure we've actually gotten the segment, since the bit</span> <a name="l00450"></a>00450 <span class="comment">// in ack_data is marked when the segment is begun, not when it's</span> <a name="l00451"></a>00451 <span class="comment">// completed</span> <a name="l00452"></a>00452 <span class="keywordflow">while</span> (1) { <a name="l00453"></a>00453 <span class="keywordtype">size_t</span> rcvd_bytes = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.num_contiguous(); <a name="l00454"></a>00454 <span class="keywordtype">size_t</span> ack_len = *iter + 1; <a name="l00455"></a>00455 <span class="keywordtype">size_t</span> segment_len = ack_len - incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#4457cbde07512253dfbb91ce12214faa">acked_length_</a>; <a name="l00456"></a>00456 (void)segment_len; <a name="l00457"></a>00457 <a name="l00458"></a>00458 <span class="keywordflow">if</span> (ack_len > rcvd_bytes) { <a name="l00459"></a>00459 log_debug(<span class="stringliteral">"send_pending_acks: "</span> <a name="l00460"></a>00460 <span class="stringliteral">"waiting to send ack length %zu for %zu byte segment "</span> <a name="l00461"></a>00461 <span class="stringliteral">"since only received %zu"</span>, <a name="l00462"></a>00462 ack_len, segment_len, rcvd_bytes); <a name="l00463"></a>00463 <span class="keywordflow">break</span>; <a name="l00464"></a>00464 } <a name="l00465"></a>00465 <a name="l00466"></a>00466 <span class="comment">// make sure we have space in the send buffer</span> <a name="l00467"></a>00467 <span class="keywordtype">size_t</span> <a class="code" href="SDNV_8cc.html#46f4c114c92230c80f6714318251b542">encoding_len</a> = 1 + <a class="code" href="SDNV_8cc.html#46f4c114c92230c80f6714318251b542">SDNV::encoding_len</a>(ack_len); <a name="l00468"></a>00468 <span class="keywordflow">if</span> (encoding_len > <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes()) { <a name="l00469"></a>00469 log_debug(<span class="stringliteral">"send_pending_acks: "</span> <a name="l00470"></a>00470 <span class="stringliteral">"no space for ack in buffer (need %zu, have %zu)"</span>, <a name="l00471"></a>00471 encoding_len, <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes()); <a name="l00472"></a>00472 <span class="keywordflow">break</span>; <a name="l00473"></a>00473 } <a name="l00474"></a>00474 <a name="l00475"></a>00475 log_debug(<span class="stringliteral">"send_pending_acks: "</span> <a name="l00476"></a>00476 <span class="stringliteral">"sending ack length %zu for %zu byte segment "</span> <a name="l00477"></a>00477 <span class="stringliteral">"[range %u..%u] ack_data *%p"</span>, <a name="l00478"></a>00478 ack_len, segment_len, incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#4457cbde07512253dfbb91ce12214faa">acked_length_</a>, *iter, <a name="l00479"></a>00479 &incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>); <a name="l00480"></a>00480 <a name="l00481"></a>00481 *<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end() = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53ac288e2ceefe0dd8461d944e0b88531d05" title="acknowledgement of a segment (followed by a SDNV ack length)">ACK_SEGMENT</a>; <a name="l00482"></a>00482 <span class="keywordtype">int</span> <a class="code" href="num2sdnv_8c.html#fed088663f8704004425cdae2120b9b3">len</a> = <a class="code" href="SDNV_8cc.html#21c54ef3a5345647ad1cada265a03eb4">SDNV::encode</a>(ack_len, (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end() + 1, <a name="l00483"></a>00483 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() - 1); <a name="l00484"></a>00484 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(encoding_len = len + 1); <a name="l00485"></a>00485 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(encoding_len); <a name="l00486"></a>00486 <a name="l00487"></a>00487 generated_ack = <span class="keyword">true</span>; <a name="l00488"></a>00488 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#4457cbde07512253dfbb91ce12214faa">acked_length_</a> = ack_len; <a name="l00489"></a>00489 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.clear(*iter); <a name="l00490"></a>00490 iter = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.begin(); <a name="l00491"></a>00491 <a name="l00492"></a>00492 <span class="keywordflow">if</span> (iter == incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.end()) { <a name="l00493"></a>00493 <span class="comment">// XXX/demmer this should check if there's another bundle</span> <a name="l00494"></a>00494 <span class="comment">// with acks we could send</span> <a name="l00495"></a>00495 <span class="keywordflow">break</span>; <a name="l00496"></a>00496 } <a name="l00497"></a>00497 <a name="l00498"></a>00498 log_debug(<span class="stringliteral">"send_pending_acks: "</span> <a name="l00499"></a>00499 <span class="stringliteral">"found another segment (%u)"</span>, *iter); <a name="l00500"></a>00500 } <a name="l00501"></a>00501 <a name="l00502"></a>00502 <span class="keywordflow">if</span> (generated_ack) { <a name="l00503"></a>00503 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bbdabd686c5d5e5a9bf30706a7ab849c" title="Hook used to tell the derived CL class to drain data out of the send buffer.">send_data</a>(); <a name="l00504"></a>00504 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#9ef41c9f94581292808d7e50472ab07b" title="utility functions used internally in this class">note_data_sent</a>(); <a name="l00505"></a>00505 } <a name="l00506"></a>00506 <a name="l00507"></a>00507 <span class="comment">// now, check if a) we've gotten everything we're supposed to</span> <a name="l00508"></a>00508 <span class="comment">// (i.e. total_length_ isn't zero), and b) we're done with all the</span> <a name="l00509"></a>00509 <span class="comment">// acks we need to send</span> <a name="l00510"></a>00510 check_done: <a name="l00511"></a>00511 <span class="keywordflow">if</span> ((incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> != 0) && <a name="l00512"></a>00512 (incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> == incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#4457cbde07512253dfbb91ce12214faa">acked_length_</a>)) <a name="l00513"></a>00513 { <a name="l00514"></a>00514 log_debug(<span class="stringliteral">"send_pending_acks: acked all %u bytes of bundle %d"</span>, <a name="l00515"></a>00515 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>, incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#7e868dff33d6868d5e42582fac3f4109">bundle_</a>->bundleid()); <a name="l00516"></a>00516 <a name="l00517"></a>00517 <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.pop_front(); <a name="l00518"></a>00518 <span class="keyword">delete</span> incoming; <a name="l00519"></a>00519 } <a name="l00520"></a>00520 <span class="keywordflow">else</span> <a name="l00521"></a>00521 { <a name="l00522"></a>00522 log_debug(<span class="stringliteral">"send_pending_acks: "</span> <a name="l00523"></a>00523 <span class="stringliteral">"still need to send acks -- acked_range %u"</span>, <a name="l00524"></a>00524 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.num_contiguous()); <a name="l00525"></a>00525 } <a name="l00526"></a>00526 <a name="l00527"></a>00527 <span class="comment">// return true if we've sent something</span> <a name="l00528"></a>00528 <span class="keywordflow">return</span> generated_ack; <a name="l00529"></a>00529 } <a name="l00530"></a>00530 <a name="l00531"></a>00531 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00532"></a>00532 <span class="keywordtype">bool</span> <a name="l00533"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4c167905aa71be2b4d4aac383344c240">00533</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4c167905aa71be2b4d4aac383344c240" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::start_next_bundle</a>() <a name="l00534"></a>00534 { <a name="l00535"></a>00535 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> == NULL); <a name="l00536"></a>00536 <a name="l00537"></a>00537 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1CLConnection.html#5712e80e8d3608ae67709fd8adf53bbe" title="Has contact_up been called.">contact_up_</a>) { <a name="l00538"></a>00538 log_debug(<span class="stringliteral">"start_next_bundle: contact not yet set up"</span>); <a name="l00539"></a>00539 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00540"></a>00540 } <a name="l00541"></a>00541 <a name="l00542"></a>00542 <span class="keyword">const</span> <a class="code" href="namespacedtn.html#6efb37e503f8062c537b022eb755b94e" title="Typedef for a reference on a link.">LinkRef</a>& link = <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link(); <a name="l00543"></a>00543 <a class="code" href="namespacedtn.html#87094f3b26b9f1d469e616d311ae57b1" title="Class definition for a Bundle reference.">BundleRef</a> bundle(<span class="stringliteral">"StreamCL::Connection::start_next_bundle"</span>); <a name="l00544"></a>00544 <a name="l00545"></a>00545 <span class="comment">// try to pop the next bundle off the link queue and put it in</span> <a name="l00546"></a>00546 <span class="comment">// flight, making sure to hold the link queue lock until it's</span> <a name="l00547"></a>00547 <span class="comment">// safely on the link's inflight queue</span> <a name="l00548"></a>00548 oasys::ScopeLock l(link->queue()->lock(), <a name="l00549"></a>00549 <span class="stringliteral">"StreamCL::Connection::start_next_bundle"</span>); <a name="l00550"></a>00550 <a name="l00551"></a>00551 bundle = link->queue()->front(); <a name="l00552"></a>00552 <span class="keywordflow">if</span> (bundle == NULL) { <a name="l00553"></a>00553 log_debug(<span class="stringliteral">"start_next_bundle: nothing to start"</span>); <a name="l00554"></a>00554 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00555"></a>00555 } <a name="l00556"></a>00556 <a name="l00557"></a>00557 <a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight = <span class="keyword">new</span> <a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>(bundle.object()); <a name="l00558"></a>00558 log_debug(<span class="stringliteral">"trying to find xmit blocks for bundle id:%d on link %s"</span>, <a name="l00559"></a>00559 bundle->bundleid(), link->name()); <a name="l00560"></a>00560 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#d35f95a5a58b157fa3d4caa2a746d02b">blocks_</a> = bundle->xmit_blocks()->find_blocks(<a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link()); <a name="l00561"></a>00561 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#d35f95a5a58b157fa3d4caa2a746d02b">blocks_</a> != NULL); <a name="l00562"></a>00562 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a> = <a class="code" href="classdtn_1_1BundleProtocol.html#a1dedd9ea4300339bc2a3f7a231ca5dd" title="Return the total length of the formatted bundle block data.">BundleProtocol::total_length</a>(inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#d35f95a5a58b157fa3d4caa2a746d02b">blocks_</a>); <a name="l00563"></a>00563 <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.push_back(inflight); <a name="l00564"></a>00564 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> = inflight; <a name="l00565"></a>00565 <a name="l00566"></a>00566 link->add_to_inflight(bundle, inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a>); <a name="l00567"></a>00567 link->del_from_queue(bundle, inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a>); <a name="l00568"></a>00568 <a name="l00569"></a>00569 <span class="comment">// release the lock before calling send_next_segment since it</span> <a name="l00570"></a>00570 <span class="comment">// might take a while</span> <a name="l00571"></a>00571 l.unlock(); <a name="l00572"></a>00572 <a name="l00573"></a>00573 <span class="comment">// now send the first segment for the bundle</span> <a name="l00574"></a>00574 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#10e5a054fe260ebd06e5daf3095c1d52" title="utility functions used internally in this class">send_next_segment</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a>); <a name="l00575"></a>00575 } <a name="l00576"></a>00576 <a name="l00577"></a>00577 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00578"></a>00578 <span class="keywordtype">bool</span> <a name="l00579"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#10e5a054fe260ebd06e5daf3095c1d52">00579</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#10e5a054fe260ebd06e5daf3095c1d52" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::send_next_segment</a>(<a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight) <a name="l00580"></a>00580 { <a name="l00581"></a>00581 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() == 0) { <a name="l00582"></a>00582 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00583"></a>00583 } <a name="l00584"></a>00584 <a name="l00585"></a>00585 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> == 0); <a name="l00586"></a>00586 <a name="l00587"></a>00587 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#f143ebd2efeaa6adc4b5fcc0e01e367d" title="Utility function to downcast the params_ pointer that&#39;s stored in the CLConnection...">stream_lparams</a>(); <a name="l00588"></a>00588 <a name="l00589"></a>00589 <span class="keywordtype">size_t</span> bytes_sent = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.empty() ? 0 : <a name="l00590"></a>00590 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.last() + 1; <a name="l00591"></a>00591 <a name="l00592"></a>00592 <span class="keywordflow">if</span> (bytes_sent == inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a>) { <a name="l00593"></a>00593 log_debug(<span class="stringliteral">"send_next_segment: "</span> <a name="l00594"></a>00594 <span class="stringliteral">"already sent all %zu bytes, finishing bundle"</span>, <a name="l00595"></a>00595 bytes_sent); <a name="l00596"></a>00596 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#cdd5a56f7932848e06a339194d04c29b">send_complete_</a>); <a name="l00597"></a>00597 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#361c9432800358728e78a0289775429a" title="utility functions used internally in this class">finish_bundle</a>(inflight); <a name="l00598"></a>00598 } <a name="l00599"></a>00599 <a name="l00600"></a>00600 u_int8_t flags = 0; <a name="l00601"></a>00601 <span class="keywordtype">size_t</span> segment_len; <a name="l00602"></a>00602 <a name="l00603"></a>00603 <span class="keywordflow">if</span> (bytes_sent == 0) { <a name="l00604"></a>00604 flags |= <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#d0516828cb1330f808cf3c7df91a6a9b1ce5167d70b177595c4e42c826c3e225" title="First segment of a bundle.">BUNDLE_START</a>; <a name="l00605"></a>00605 } <a name="l00606"></a>00606 <a name="l00607"></a>00607 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#f84af5832d28b56241e1ca6f23b757b6" title="Maximum size of transmitted segments.">segment_length_</a> >= inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a> - bytes_sent) { <a name="l00608"></a>00608 flags |= <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#d0516828cb1330f808cf3c7df91a6a9b0ca0531933393d66d0e47170956ea5d9" title="Last segment of a bundle.">BUNDLE_END</a>; <a name="l00609"></a>00609 segment_len = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a> - bytes_sent; <a name="l00610"></a>00610 } <span class="keywordflow">else</span> { <a name="l00611"></a>00611 segment_len = params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#f84af5832d28b56241e1ca6f23b757b6" title="Maximum size of transmitted segments.">segment_length_</a>; <a name="l00612"></a>00612 } <a name="l00613"></a>00613 <a name="l00614"></a>00614 <span class="keywordtype">size_t</span> sdnv_len = <a class="code" href="SDNV_8cc.html#46f4c114c92230c80f6714318251b542">SDNV::encoding_len</a>(segment_len); <a name="l00615"></a>00615 <a name="l00616"></a>00616 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() < 1 + sdnv_len) { <a name="l00617"></a>00617 log_debug(<span class="stringliteral">"send_next_segment: "</span> <a name="l00618"></a>00618 <span class="stringliteral">"not enough space for segment header [need %zu, have %zu]"</span>, <a name="l00619"></a>00619 1 + sdnv_len, <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes()); <a name="l00620"></a>00620 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l00621"></a>00621 } <a name="l00622"></a>00622 <a name="l00623"></a>00623 log_debug(<span class="stringliteral">"send_next_segment: "</span> <a name="l00624"></a>00624 <span class="stringliteral">"starting %zu byte segment [block byte range %zu..%zu]"</span>, <a name="l00625"></a>00625 segment_len, bytes_sent, bytes_sent + segment_len); <a name="l00626"></a>00626 <a name="l00627"></a>00627 u_char* bp = (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end(); <a name="l00628"></a>00628 *bp++ = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53ac1c7865f9e31769ff99ffd0f395fb4dd6" title="a segment of bundle data (followed by a SDNV segment length)">DATA_SEGMENT</a> | flags; <a name="l00629"></a>00629 <span class="keywordtype">int</span> cc = <a class="code" href="SDNV_8cc.html#21c54ef3a5345647ad1cada265a03eb4">SDNV::encode</a>(segment_len, bp, <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() - 1); <a name="l00630"></a>00630 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(cc == (<span class="keywordtype">int</span>)sdnv_len); <a name="l00631"></a>00631 bp += sdnv_len; <a name="l00632"></a>00632 <a name="l00633"></a>00633 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(1 + sdnv_len); <a name="l00634"></a>00634 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> = segment_len; <a name="l00635"></a>00635 <a name="l00636"></a>00636 <span class="comment">// send_data_todo actually does the deed</span> <a name="l00637"></a>00637 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#69b0db2a6c9456baac7c14a04c6b8c46" title="utility functions used internally in this class">send_data_todo</a>(inflight); <a name="l00638"></a>00638 } <a name="l00639"></a>00639 <a name="l00640"></a>00640 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00641"></a>00641 <span class="keywordtype">bool</span> <a name="l00642"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#69b0db2a6c9456baac7c14a04c6b8c46">00642</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#69b0db2a6c9456baac7c14a04c6b8c46" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::send_data_todo</a>(<a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight) <a name="l00643"></a>00643 { <a name="l00644"></a>00644 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0); <a name="l00645"></a>00645 <a name="l00646"></a>00646 <span class="comment">// loop since it may take multiple calls to send on the socket</span> <a name="l00647"></a>00647 <span class="comment">// before we can actually drain the todo amount</span> <a name="l00648"></a>00648 <span class="keywordflow">while</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0 && <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() != 0) { <a name="l00649"></a>00649 <span class="keywordtype">size_t</span> bytes_sent = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.empty() ? 0 : <a name="l00650"></a>00650 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.last() + 1; <a name="l00651"></a>00651 <span class="keywordtype">size_t</span> send_len = std::min(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a>, <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes()); <a name="l00652"></a>00652 <a name="l00653"></a>00653 <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a>.object(); <a name="l00654"></a>00654 <a class="code" href="classdtn_1_1BlockInfoVec.html" title="Class for a vector of BlockInfo structures.">BlockInfoVec</a>* blocks = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#d35f95a5a58b157fa3d4caa2a746d02b">blocks_</a>; <a name="l00655"></a>00655 <a name="l00656"></a>00656 <span class="keywordtype">size_t</span> ret = <a name="l00657"></a>00657 <a class="code" href="classdtn_1_1BundleProtocol.html#98a0ecbc789e7f84006909b884e70439" title="Copies out a chunk of formatted bundle data at a specified offset from the provided...">BundleProtocol::produce</a>(bundle, blocks, (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end(), <a name="l00658"></a>00658 bytes_sent, send_len, <a name="l00659"></a>00659 &inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#cdd5a56f7932848e06a339194d04c29b">send_complete_</a>); <a name="l00660"></a>00660 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(ret == send_len); <a name="l00661"></a>00661 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(send_len); <a name="l00662"></a>00662 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.set(bytes_sent, send_len); <a name="l00663"></a>00663 <a name="l00664"></a>00664 log_debug(<span class="stringliteral">"send_data_todo: "</span> <a name="l00665"></a>00665 <span class="stringliteral">"sent %zu/%zu of current segment from block offset %zu "</span> <a name="l00666"></a>00666 <span class="stringliteral">"(%zu todo), updated sent_data *%p"</span>, <a name="l00667"></a>00667 send_len, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a>, bytes_sent, <a name="l00668"></a>00668 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> - send_len, &inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>); <a name="l00669"></a>00669 <a name="l00670"></a>00670 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> -= send_len; <a name="l00671"></a>00671 <a name="l00672"></a>00672 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#9ef41c9f94581292808d7e50472ab07b" title="utility functions used internally in this class">note_data_sent</a>(); <a name="l00673"></a>00673 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bbdabd686c5d5e5a9bf30706a7ab849c" title="Hook used to tell the derived CL class to drain data out of the send buffer.">send_data</a>(); <a name="l00674"></a>00674 <a name="l00675"></a>00675 <span class="comment">// XXX/demmer once send_complete_ is true, we could post an</span> <a name="l00676"></a>00676 <span class="comment">// event to free up space in the queue for more bundles to be</span> <a name="l00677"></a>00677 <span class="comment">// sent down. note that it's possible the bundle isn't really</span> <a name="l00678"></a>00678 <span class="comment">// out on the wire yet, but we don't have any way of knowing</span> <a name="l00679"></a>00679 <span class="comment">// when it gets out of the sendbuf_ and into the kernel (nor</span> <a name="l00680"></a>00680 <span class="comment">// for that matter actually onto the wire), so this is the</span> <a name="l00681"></a>00681 <span class="comment">// best we can do for now.</span> <a name="l00682"></a>00682 <a name="l00683"></a>00683 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#a61b296b02812f04b3df0c8fb09919b8" title="Contact has been broken.">contact_broken_</a>) <a name="l00684"></a>00684 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00685"></a>00685 <a name="l00686"></a>00686 <span class="comment">// if test_write_delay is set, then we only send one segment</span> <a name="l00687"></a>00687 <span class="comment">// at a time before bouncing back to poll</span> <a name="l00688"></a>00688 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#e3408a135a49d68ab36fd8de5805b1fe" title="Pointer to Link parameters, or to defaults until Link is bound.">params_</a>-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#9b77847034f59f7688f281c78d040000" title="Msecs to sleep between write calls.">test_write_delay_</a> != 0) { <a name="l00689"></a>00689 log_debug(<span class="stringliteral">"send_data_todo done, returning more to send "</span> <a name="l00690"></a>00690 <span class="stringliteral">"(send_segment_todo_==%zu) since test_write_delay is non-zero"</span>, <a name="l00691"></a>00691 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a>); <a name="l00692"></a>00692 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00693"></a>00693 } <a name="l00694"></a>00694 } <a name="l00695"></a>00695 <a name="l00696"></a>00696 <span class="keywordflow">return</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> == 0); <a name="l00697"></a>00697 } <a name="l00698"></a>00698 <a name="l00699"></a>00699 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00700"></a>00700 <span class="keywordtype">bool</span> <a name="l00701"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#361c9432800358728e78a0289775429a">00701</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#361c9432800358728e78a0289775429a" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::finish_bundle</a>(<a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight) <a name="l00702"></a>00702 { <a name="l00703"></a>00703 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#cdd5a56f7932848e06a339194d04c29b">send_complete_</a>); <a name="l00704"></a>00704 <a name="l00705"></a>00705 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> == inflight); <a name="l00706"></a>00706 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> = NULL; <a name="l00707"></a>00707 <a name="l00708"></a>00708 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d" title="utility functions used internally in this class">check_completed</a>(inflight); <a name="l00709"></a>00709 <a name="l00710"></a>00710 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l00711"></a>00711 } <a name="l00712"></a>00712 <a name="l00713"></a>00713 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00714"></a>00714 <span class="keywordtype">void</span> <a name="l00715"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d">00715</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::check_completed</a>(<a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight) <a name="l00716"></a>00716 { <a name="l00717"></a>00717 <span class="comment">// we can pop the inflight bundle off of the queue and clean it up</span> <a name="l00718"></a>00718 <span class="comment">// only when both finish_bundle is called (so current_inflight_ no</span> <a name="l00719"></a>00719 <span class="comment">// longer points to the inflight bundle), and after the final ack</span> <a name="l00720"></a>00720 <span class="comment">// for the bundle has been received (determined by looking at</span> <a name="l00721"></a>00721 <span class="comment">// inflight->ack_data_)</span> <a name="l00722"></a>00722 <a name="l00723"></a>00723 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> == inflight) { <a name="l00724"></a>00724 log_debug(<span class="stringliteral">"check_completed: bundle %d still waiting for finish_bundle"</span>, <a name="l00725"></a>00725 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a>->bundleid()); <a name="l00726"></a>00726 <span class="keywordflow">return</span>; <a name="l00727"></a>00727 } <a name="l00728"></a>00728 <a name="l00729"></a>00729 u_int32_t acked_len = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>.num_contiguous(); <a name="l00730"></a>00730 <span class="keywordflow">if</span> (acked_len < inflight->total_length_) { <a name="l00731"></a>00731 log_debug(<span class="stringliteral">"check_completed: bundle %d only acked %u/%u"</span>, <a name="l00732"></a>00732 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a>->bundleid(), <a name="l00733"></a>00733 acked_len, inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a>); <a name="l00734"></a>00734 <span class="keywordflow">return</span>; <a name="l00735"></a>00735 } <a name="l00736"></a>00736 <a name="l00737"></a>00737 log_debug(<span class="stringliteral">"check_completed: bundle %d transmission complete"</span>, <a name="l00738"></a>00738 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a>->bundleid()); <a name="l00739"></a>00739 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(inflight == <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.front()); <a name="l00740"></a>00740 <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.pop_front(); <a name="l00741"></a>00741 <span class="keyword">delete</span> inflight; <a name="l00742"></a>00742 } <a name="l00743"></a>00743 <a name="l00744"></a>00744 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00745"></a>00745 <span class="keywordtype">void</span> <a name="l00746"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#0c93d13277062f931c16baeb819197a7">00746</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#0c93d13277062f931c16baeb819197a7" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::send_keepalive</a>() <a name="l00747"></a>00747 { <a name="l00748"></a>00748 <span class="comment">// there's no point in putting another byte in the buffer if</span> <a name="l00749"></a>00749 <span class="comment">// there's already data waiting to go out, since the arrival of</span> <a name="l00750"></a>00750 <span class="comment">// that data on the other end will do the same job as the</span> <a name="l00751"></a>00751 <span class="comment">// keepalive byte</span> <a name="l00752"></a>00752 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fullbytes() != 0) { <a name="l00753"></a>00753 log_debug(<span class="stringliteral">"send_keepalive: "</span> <a name="l00754"></a>00754 <span class="stringliteral">"send buffer has %zu bytes queued, suppressing keepalive"</span>, <a name="l00755"></a>00755 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fullbytes()); <a name="l00756"></a>00756 <span class="keywordflow">return</span>; <a name="l00757"></a>00757 } <a name="l00758"></a>00758 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.tailbytes() > 0); <a name="l00759"></a>00759 <a name="l00760"></a>00760 <span class="comment">// similarly, we must not send a keepalive if send_segment_todo_ is</span> <a name="l00761"></a>00761 <span class="comment">// nonzero, because that would likely insert the keepalive in the middle</span> <a name="l00762"></a>00762 <span class="comment">// of a bundle currently being sent -- verified in check_keepalive</span> <a name="l00763"></a>00763 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> == 0);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00764"></a>00764 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00765"></a>00765 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#d7be9e6fb91ba7620f8e5172c4643e1b" title="Timestamp for keepalive timer.">keepalive_sent_</a>, 0); <a name="l00766"></a>00766 <a name="l00767"></a>00767 *(<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end()) = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53accfc2440c0ffff7d31b53c4ee810fcecf" title="keepalive packet">KEEPALIVE</a>; <a name="l00768"></a>00768 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(1); <a name="l00769"></a>00769 <a name="l00770"></a>00770 <span class="comment">// don't note_data_sent() here since keepalive messages shouldn't</span> <a name="l00771"></a>00771 <span class="comment">// be counted for keeping an idle link open</span> <a name="l00772"></a>00772 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bbdabd686c5d5e5a9bf30706a7ab849c" title="Hook used to tell the derived CL class to drain data out of the send buffer.">send_data</a>(); <a name="l00773"></a>00773 } <a name="l00774"></a>00774 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00775"></a>00775 <span class="keywordtype">void</span> <a name="l00776"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#2c11a5f0a2b7d0641db35223c3f1ee19">00776</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#2c11a5f0a2b7d0641db35223c3f1ee19" title="virtual from CLConnection">StreamConvergenceLayer::Connection::handle_cancel_bundle</a>(<a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>* bundle) <a name="l00777"></a>00777 { <a name="l00778"></a>00778 <span class="comment">// if the bundle is already actually in flight (i.e. we've already</span> <a name="l00779"></a>00779 <span class="comment">// sent all or part of it), we can't currently cancel it. however,</span> <a name="l00780"></a>00780 <span class="comment">// in the case where it's not already in flight, we can cancel it</span> <a name="l00781"></a>00781 <span class="comment">// and accordingly signal with an event</span> <a name="l00782"></a>00782 InFlightList::iterator iter; <a name="l00783"></a>00783 <span class="keywordflow">for</span> (iter = <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.begin(); iter != <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.end(); ++iter) { <a name="l00784"></a>00784 <a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight = *iter; <a name="l00785"></a>00785 <span class="keywordflow">if</span> (inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a> == bundle) <a name="l00786"></a>00786 { <a name="l00787"></a>00787 <span class="keywordflow">if</span> (inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.empty()) { <a name="l00788"></a>00788 <span class="comment">// this bundle might be current_inflight_ but with no</span> <a name="l00789"></a>00789 <span class="comment">// data sent yet; check for this case so we do not have</span> <a name="l00790"></a>00790 <span class="comment">// a dangling pointer</span> <a name="l00791"></a>00791 <span class="keywordflow">if</span> (inflight == <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a>) { <a name="l00792"></a>00792 <span class="comment">// we may have sent a segment length without any bundle</span> <a name="l00793"></a>00793 <span class="comment">// data; if so we must send the segment so we can't</span> <a name="l00794"></a>00794 <span class="comment">// cancel the send now</span> <a name="l00795"></a>00795 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0) { <a name="l00796"></a>00796 log_debug(<span class="stringliteral">"handle_cancel_bundle: bundle %d "</span> <a name="l00797"></a>00797 <span class="stringliteral">"already in flight, can't cancel send"</span>, <a name="l00798"></a>00798 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00799"></a>00799 <span class="keywordflow">return</span>; <a name="l00800"></a>00800 } <a name="l00801"></a>00801 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3305960e367d4413a8529cc3266c2922" title="Current bundle that&#39;s in flight.">current_inflight_</a> = NULL; <a name="l00802"></a>00802 } <a name="l00803"></a>00803 <a name="l00804"></a>00804 log_debug(<span class="stringliteral">"handle_cancel_bundle: "</span> <a name="l00805"></a>00805 <span class="stringliteral">"bundle %d not yet in flight, cancelling send"</span>, <a name="l00806"></a>00806 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00807"></a>00807 <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.erase(iter); <a name="l00808"></a>00808 <span class="keyword">delete</span> inflight; <a name="l00809"></a>00809 <a class="code" href="classdtn_1_1BundleDaemon.html#370a80f7dd9fd9297e76d7f830d737a8" title="Queues the event at the tail of the queue for processing by the daemon thread.">BundleDaemon::post</a>( <a name="l00810"></a>00810 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleSendCancelledEvent.html" title="Event class for succesful cancellation of a bundle send.">BundleSendCancelledEvent</a>(bundle, <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link())); <a name="l00811"></a>00811 <span class="keywordflow">return</span>; <a name="l00812"></a>00812 } <span class="keywordflow">else</span> { <a name="l00813"></a>00813 log_debug(<span class="stringliteral">"handle_cancel_bundle: "</span> <a name="l00814"></a>00814 <span class="stringliteral">"bundle %d already in flight, can't cancel send"</span>, <a name="l00815"></a>00815 bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <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 } <a name="l00820"></a>00820 <a name="l00821"></a>00821 log_warn(<span class="stringliteral">"handle_cancel_bundle: "</span> <a name="l00822"></a>00822 <span class="stringliteral">"can't find bundle %d in the in flight list"</span>, bundle-><a class="code" href="classdtn_1_1Bundle.html#7031e2e5e4078445bf4ad39cdcdea3b2" title="Accessors.">bundleid</a>()); <a name="l00823"></a>00823 } <a name="l00824"></a>00824 <a name="l00825"></a>00825 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00826"></a>00826 <span class="keywordtype">void</span> <a name="l00827"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#39c37dca585724b5c41a8759d9cc5741">00827</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#39c37dca585724b5c41a8759d9cc5741" title="virtual from CLConnection">StreamConvergenceLayer::Connection::handle_poll_timeout</a>() <a name="l00828"></a>00828 { <a name="l00829"></a>00829 <span class="comment">// Allow the BundleDaemon to call for a close of the connection if</span> <a name="l00830"></a>00830 <span class="comment">// a shutdown is in progress. This must be done to avoid a</span> <a name="l00831"></a>00831 <span class="comment">// deadlock caused by simultaneous poll_timeout and close_contact</span> <a name="l00832"></a>00832 <span class="comment">// activities.</span> <a name="l00833"></a>00833 <span class="comment">//</span> <a name="l00834"></a>00834 <span class="comment">// Before we return, sleep a bit to avoid continuous</span> <a name="l00835"></a>00835 <span class="comment">// handle_poll_timeout calls</span> <a name="l00836"></a>00836 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1BundleDaemon.html#a688176818706912fbd49e751d98e565" title="Accessor for the BundleDaemon&#39;s shutdown status.">BundleDaemon::shutting_down</a>()) <a name="l00837"></a>00837 { <a name="l00838"></a>00838 sleep(1); <a name="l00839"></a>00839 <span class="keywordflow">return</span>; <a name="l00840"></a>00840 } <a name="l00841"></a>00841 <a name="l00842"></a>00842 <span class="comment">// avoid performing connection timeout operations on</span> <a name="l00843"></a>00843 <span class="comment">// connections which have not been initiated yet</span> <a name="l00844"></a>00844 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#334e73df91eb3303aae9c96c8b7c7301">contact_initiated_</a>) <a name="l00845"></a>00845 { <a name="l00846"></a>00846 <span class="keywordflow">return</span>; <a name="l00847"></a>00847 } <a name="l00848"></a>00848 <a name="l00849"></a>00849 <span class="keyword">struct </span>timeval now; <a name="l00850"></a>00850 u_int elapsed, elapsed2; <a name="l00851"></a>00851 <a name="l00852"></a>00852 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>*<span class="keyword">></span>(<a class="code" href="classdtn_1_1CLConnection.html#e3408a135a49d68ab36fd8de5805b1fe" title="Pointer to Link parameters, or to defaults until Link is bound.">params_</a>); <a name="l00853"></a>00853 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(params != NULL);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00854"></a>00854 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> </a> <a name="l00855"></a>00855 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&now, 0); <a name="l00856"></a>00856 <a name="l00857"></a>00857 <span class="comment">// check that it hasn't been too long since we got some data from</span> <a name="l00858"></a>00858 <span class="comment">// the other side</span> <a name="l00859"></a>00859 elapsed = <a class="code" href="dtnping_8h.html#78237999c2659b5d28c1a90a2123607f">TIMEVAL_DIFF_MSEC</a>(now, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>); <a name="l00860"></a>00860 <span class="keywordflow">if</span> (elapsed > params-><a class="code" href="classdtn_1_1ConnectionConvergenceLayer_1_1LinkParams.html#7f819ba8a1caa690ff86ce4484ba7329" title="Msecs to wait for data arrival.">data_timeout_</a>) { <a name="l00861"></a>00861 log_info(<span class="stringliteral">"handle_poll_timeout: no data heard for %d msecs "</span> <a name="l00862"></a>00862 <span class="stringliteral">"(keepalive_sent %u.%u, data_rcvd %u.%u, now %u.%u, poll_timeout %d) "</span> <a name="l00863"></a>00863 <span class="stringliteral">"-- closing contact"</span>, <a name="l00864"></a>00864 elapsed, <a name="l00865"></a>00865 (u_int)<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#d7be9e6fb91ba7620f8e5172c4643e1b" title="Timestamp for keepalive timer.">keepalive_sent_</a>.tv_sec, <a name="l00866"></a>00866 (u_int)<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#d7be9e6fb91ba7620f8e5172c4643e1b" title="Timestamp for keepalive timer.">keepalive_sent_</a>.tv_usec, <a name="l00867"></a>00867 (u_int)<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>.tv_sec, (u_int)<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>.tv_usec, <a name="l00868"></a>00868 (u_int)now.tv_sec, (u_int)now.tv_usec, <a name="l00869"></a>00869 <a class="code" href="classdtn_1_1CLConnection.html#b9b601dae1312020426d0d57daca19da" title="Timeout to wait for poll data.">poll_timeout_</a>); <a name="l00870"></a>00870 <a name="l00871"></a>00871 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7f0c1475c056a0f72e11b5ba8466a27f7" title="Unexpected session interruption.">ContactEvent::BROKEN</a>); <a name="l00872"></a>00872 <span class="keywordflow">return</span>; <a name="l00873"></a>00873 } <a name="l00874"></a>00874 <a name="l00875"></a>00875 <span class="comment">//make sure the contact still exists</span> <a name="l00876"></a>00876 <a class="code" href="classdtn_1_1ContactManager.html" title="A contact manager class.">ContactManager</a>* cm = BundleDaemon::instance()->contactmgr(); <a name="l00877"></a>00877 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">"StreamConvergenceLayer::Connection::handle_poll_timeout"</span>); <a name="l00878"></a>00878 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a> == NULL) <a name="l00879"></a>00879 { <a name="l00880"></a>00880 <span class="keywordflow">return</span>; <a name="l00881"></a>00881 } <a name="l00882"></a>00882 <a name="l00883"></a>00883 <span class="comment">// check if the connection has been idle for too long</span> <a name="l00884"></a>00884 <span class="comment">// (on demand links only)</span> <a name="l00885"></a>00885 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link()->type() == <a class="code" href="classdtn_1_1Link.html#a93653796d33692c67c415afd1edf61eeacf2159ea9fd169ca07c9f9891309ec" title="The link is expected to be either always available, or can be made available easily...">Link::ONDEMAND</a>) { <a name="l00886"></a>00886 u_int idle_close_time = <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link()->params().idle_close_time_; <a name="l00887"></a>00887 <a name="l00888"></a>00888 elapsed = <a class="code" href="dtnping_8h.html#78237999c2659b5d28c1a90a2123607f">TIMEVAL_DIFF_MSEC</a>(now, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>); <a name="l00889"></a>00889 elapsed2 = <a class="code" href="dtnping_8h.html#78237999c2659b5d28c1a90a2123607f">TIMEVAL_DIFF_MSEC</a>(now, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#40cc6956b2b157b5f4ef4ef9734cead0" title="Timestamp for idle timer.">data_sent_</a>); <a name="l00890"></a>00890 <a name="l00891"></a>00891 <span class="keywordflow">if</span> (idle_close_time != 0 && <a name="l00892"></a>00892 (elapsed > idle_close_time * 1000) && <a name="l00893"></a>00893 (elapsed2 > idle_close_time * 1000)) <a name="l00894"></a>00894 { <a name="l00895"></a>00895 log_info(<span class="stringliteral">"closing idle connection "</span> <a name="l00896"></a>00896 <span class="stringliteral">"(no data received for %d msecs or sent for %d msecs)"</span>, <a name="l00897"></a>00897 elapsed, elapsed2); <a name="l00898"></a>00898 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7cc4b8963a82f22c0d9b61c37e06e877e" title="Idle connection shut down by the CL.">ContactEvent::IDLE</a>); <a name="l00899"></a>00899 <span class="keywordflow">return</span>; <a name="l00900"></a>00900 } <span class="keywordflow">else</span> { <a name="l00901"></a>00901 log_debug(<span class="stringliteral">"connection not idle: recvd %d / sent %d <= timeout %d"</span>, <a name="l00902"></a>00902 elapsed, elapsed2, idle_close_time * 1000); <a name="l00903"></a>00903 } <a name="l00904"></a>00904 } <a name="l00905"></a>00905 <a name="l00906"></a>00906 <span class="comment">// check if it's time for us to send a keepalive (i.e. that we</span> <a name="l00907"></a>00907 <span class="comment">// haven't sent some data or another keepalive in at least the</span> <a name="l00908"></a>00908 <span class="comment">// configured keepalive_interval)</span> <a name="l00909"></a>00909 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#a7f82a1ad41a82f47cebf230ac0b5036" title="utility functions used by derived classes">check_keepalive</a>(); <a name="l00910"></a>00910 } <a name="l00911"></a>00911 <a name="l00912"></a>00912 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00913"></a>00913 <span class="keywordtype">void</span> <a name="l00914"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#a7f82a1ad41a82f47cebf230ac0b5036">00914</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#a7f82a1ad41a82f47cebf230ac0b5036" title="utility functions used by derived classes">StreamConvergenceLayer::Connection::check_keepalive</a>() <a name="l00915"></a>00915 { <a name="l00916"></a>00916 <span class="keyword">struct </span>timeval now; <a name="l00917"></a>00917 u_int elapsed, elapsed2; <a name="l00918"></a>00918 <a name="l00919"></a>00919 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>* params = <span class="keyword">dynamic_cast<</span><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html" title="Link parameters shared among all stream based convergence layers.">StreamLinkParams</a>*<span class="keyword">></span>(<a class="code" href="classdtn_1_1CLConnection.html#e3408a135a49d68ab36fd8de5805b1fe" title="Pointer to Link parameters, or to defaults until Link is bound.">params_</a>); <a name="l00920"></a>00920 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(params != NULL);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00921"></a>00921 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l00922"></a>00922 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&now, 0); <a name="l00923"></a>00923 <a name="l00924"></a>00924 <span class="keywordflow">if</span> (params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> != 0) { <a name="l00925"></a>00925 elapsed = <a class="code" href="dtnping_8h.html#78237999c2659b5d28c1a90a2123607f">TIMEVAL_DIFF_MSEC</a>(now, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#40cc6956b2b157b5f4ef4ef9734cead0" title="Timestamp for idle timer.">data_sent_</a>); <a name="l00926"></a>00926 elapsed2 = <a class="code" href="dtnping_8h.html#78237999c2659b5d28c1a90a2123607f">TIMEVAL_DIFF_MSEC</a>(now, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#d7be9e6fb91ba7620f8e5172c4643e1b" title="Timestamp for keepalive timer.">keepalive_sent_</a>); <a name="l00927"></a>00927 <a name="l00928"></a>00928 <span class="comment">// XXX/demmer this is bogus -- we should really adjust</span> <a name="l00929"></a>00929 <span class="comment">// poll_timeout to take into account the next time we should</span> <a name="l00930"></a>00930 <span class="comment">// send a keepalive</span> <a name="l00931"></a>00931 <span class="comment">// </span> <a name="l00932"></a>00932 <span class="comment">// give a 500ms fudge to the keepalive interval to make sure</span> <a name="l00933"></a>00933 <span class="comment">// we send it when we should</span> <a name="l00934"></a>00934 <span class="keywordflow">if</span> (std::min(elapsed, elapsed2) > ((params-><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1StreamLinkParams.html#5513a46ac82f99427efb3f1f46e9cb7e" title="Seconds between keepalive packets.">keepalive_interval_</a> * 1000) - 500)) <a name="l00935"></a>00935 { <a name="l00936"></a>00936 <span class="comment">// it's possible that the link is blocked while in the</span> <a name="l00937"></a>00937 <span class="comment">// middle of a segment, triggering a poll timeout, so make</span> <a name="l00938"></a>00938 <span class="comment">// sure not to send a keepalive in this case</span> <a name="l00939"></a>00939 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> != 0) { <a name="l00940"></a>00940 log_debug(<span class="stringliteral">"not issuing keepalive in the middle of a segment"</span>); <a name="l00941"></a>00941 <span class="keywordflow">return</span>; <a name="l00942"></a>00942 } <a name="l00943"></a>00943 <a name="l00944"></a>00944 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#0c93d13277062f931c16baeb819197a7" title="utility functions used internally in this class">send_keepalive</a>(); <a name="l00945"></a>00945 } <a name="l00946"></a>00946 } <a name="l00947"></a>00947 } <a name="l00948"></a>00948 <a name="l00949"></a>00949 <span class="comment">//----------------------------------------------------------------------</span> <a name="l00950"></a>00950 <span class="keywordtype">void</span> <a name="l00951"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5e611627d2caa87dbce0e3affc5b5c68">00951</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5e611627d2caa87dbce0e3affc5b5c68" title="utility functions used by derived classes">StreamConvergenceLayer::Connection::process_data</a>() <a name="l00952"></a>00952 { <a name="l00953"></a>00953 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() == 0) { <a name="l00954"></a>00954 <span class="keywordflow">return</span>; <a name="l00955"></a>00955 } <a name="l00956"></a>00956 <a name="l00957"></a>00957 log_debug(<span class="stringliteral">"processing up to %zu bytes from receive buffer"</span>, <a name="l00958"></a>00958 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l00959"></a>00959 <a name="l00960"></a>00960 <span class="comment">// all data (keepalives included) should be noted since the last</span> <a name="l00961"></a>00961 <span class="comment">// reception time is used to determine when to generate new</span> <a name="l00962"></a>00962 <span class="comment">// keepalives</span> <a name="l00963"></a>00963 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3467dd32c5c8da24266290d9b2e95377" title="utility functions used internally in this class">note_data_rcvd</a>(); <a name="l00964"></a>00964 <a name="l00965"></a>00965 <span class="comment">// the first thing we need to do is handle the contact initiation</span> <a name="l00966"></a>00966 <span class="comment">// sequence, i.e. the contact header and the announce bundle. we</span> <a name="l00967"></a>00967 <span class="comment">// know we need to do this if we haven't yet called contact_up()</span> <a name="l00968"></a>00968 <span class="keywordflow">if</span> (! <a class="code" href="classdtn_1_1CLConnection.html#5712e80e8d3608ae67709fd8adf53bbe" title="Has contact_up been called.">contact_up_</a>) { <a name="l00969"></a>00969 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#fe8bc46331b10ed587f6c11e2a5be757" title="utility functions used internally in this class">handle_contact_initiation</a>(); <a name="l00970"></a>00970 <span class="keywordflow">return</span>; <a name="l00971"></a>00971 } <a name="l00972"></a>00972 <a name="l00973"></a>00973 <span class="comment">// if a data segment is bigger than the receive buffer. when</span> <a name="l00974"></a>00974 <span class="comment">// processing a data segment, we mark the unread amount in the</span> <a name="l00975"></a>00975 <span class="comment">// recv_segment_todo__ field, so if that's not zero, we need to</span> <a name="l00976"></a>00976 <span class="comment">// drain it, then fall through to handle the rest of the buffer</span> <a name="l00977"></a>00977 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a> != 0) { <a name="l00978"></a>00978 <span class="keywordtype">bool</span> ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#11cd8cb07dd92f8577b109a60b680cc5" title="utility functions used internally in this class">handle_data_todo</a>(); <a name="l00979"></a>00979 <a name="l00980"></a>00980 <span class="keywordflow">if</span> (!ok) { <a name="l00981"></a>00981 <span class="keywordflow">return</span>; <a name="l00982"></a>00982 } <a name="l00983"></a>00983 } <a name="l00984"></a>00984 <a name="l00985"></a>00985 <span class="comment">// now, drain cl messages from the receive buffer. we peek at the</span> <a name="l00986"></a>00986 <span class="comment">// first byte and dispatch to the correct handler routine</span> <a name="l00987"></a>00987 <span class="comment">// depending on the type of the CL message. we don't consume the</span> <a name="l00988"></a>00988 <span class="comment">// byte yet since there's a possibility that we need to read more</span> <a name="l00989"></a>00989 <span class="comment">// from the remote side to handle the whole message</span> <a name="l00990"></a>00990 <span class="keywordflow">while</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() != 0) { <a name="l00991"></a>00991 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#a61b296b02812f04b3df0c8fb09919b8" title="Contact has been broken.">contact_broken_</a>) <span class="keywordflow">return</span>; <a name="l00992"></a>00992 <a name="l00993"></a>00993 u_int8_t type = *<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start() & 0xf0; <a name="l00994"></a>00994 u_int8_t flags = *<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start() & 0x0f; <a name="l00995"></a>00995 <a name="l00996"></a>00996 log_debug(<span class="stringliteral">"recvbuf has %zu full bytes, dispatching to handler routine"</span>, <a name="l00997"></a>00997 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l00998"></a>00998 <span class="keywordtype">bool</span> ok; <a name="l00999"></a>00999 <span class="keywordflow">switch</span> (type) { <a name="l01000"></a>01000 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53ac1c7865f9e31769ff99ffd0f395fb4dd6" title="a segment of bundle data (followed by a SDNV segment length)">DATA_SEGMENT</a>: <a name="l01001"></a>01001 ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#2820112f480a485501737eb2962c12e9" title="utility functions used internally in this class">handle_data_segment</a>(flags); <a name="l01002"></a>01002 <span class="keywordflow">break</span>; <a name="l01003"></a>01003 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53ac288e2ceefe0dd8461d944e0b88531d05" title="acknowledgement of a segment (followed by a SDNV ack length)">ACK_SEGMENT</a>: <a name="l01004"></a>01004 ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4e953071e0c7ee2e9157c11b7f998bd6" title="utility functions used internally in this class">handle_ack_segment</a>(flags); <a name="l01005"></a>01005 <span class="keywordflow">break</span>; <a name="l01006"></a>01006 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53accec1bcb080fccd4ed408e519539cda92" title="reject reception of current bundle">REFUSE_BUNDLE</a>: <a name="l01007"></a>01007 ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#c6509bf3539fc74f5bcb128379acf8dd" title="utility functions used internally in this class">handle_refuse_bundle</a>(flags); <a name="l01008"></a>01008 <span class="keywordflow">break</span>; <a name="l01009"></a>01009 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53accfc2440c0ffff7d31b53c4ee810fcecf" title="keepalive packet">KEEPALIVE</a>: <a name="l01010"></a>01010 ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#71fc76a4d77152e025c1e5246894a656" title="utility functions used internally in this class">handle_keepalive</a>(flags); <a name="l01011"></a>01011 <span class="keywordflow">break</span>; <a name="l01012"></a>01012 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53acfdbe69c942f3d92b9f503c9ba5c87a37" title="about to shutdown">SHUTDOWN</a>: <a name="l01013"></a>01013 ok = <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#62654499c48ef4b7815333db6813689f" title="utility functions used internally in this class">handle_shutdown</a>(flags); <a name="l01014"></a>01014 <span class="keywordflow">break</span>; <a name="l01015"></a>01015 <span class="keywordflow">default</span>: <a name="l01016"></a>01016 log_err(<span class="stringliteral">"invalid CL message type code 0x%x (flags 0x%x)"</span>, <a name="l01017"></a>01017 type >> 4, flags); <a name="l01018"></a>01018 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01019"></a>01019 <span class="keywordflow">return</span>; <a name="l01020"></a>01020 } <a name="l01021"></a>01021 <a name="l01022"></a>01022 <span class="comment">// if there's not enough data in the buffer to handle the</span> <a name="l01023"></a>01023 <span class="comment">// message, make sure there's space to receive more</span> <a name="l01024"></a>01024 <span class="keywordflow">if</span> (! ok) { <a name="l01025"></a>01025 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() == <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.size()) { <a name="l01026"></a>01026 log_warn(<span class="stringliteral">"process_data: "</span> <a name="l01027"></a>01027 <span class="stringliteral">"%zu byte recv buffer full but too small for msg %u... "</span> <a name="l01028"></a>01028 <span class="stringliteral">"doubling buffer size"</span>, <a name="l01029"></a>01029 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.size(), type); <a name="l01030"></a>01030 <a name="l01031"></a>01031 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.reserve(<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.size() * 2); <a name="l01032"></a>01032 <a name="l01033"></a>01033 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.tailbytes() == 0) { <a name="l01034"></a>01034 <span class="comment">// force it to move the full bytes up to the front</span> <a name="l01035"></a>01035 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.reserve(<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.size() - <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l01036"></a>01036 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.tailbytes() != 0); <a name="l01037"></a>01037 } <a name="l01038"></a>01038 <a name="l01039"></a>01039 <span class="keywordflow">return</span>; <a name="l01040"></a>01040 } <a name="l01041"></a>01041 } <a name="l01042"></a>01042 } <a name="l01043"></a>01043 <a name="l01044"></a>01044 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01045"></a>01045 <span class="keywordtype">void</span> <a name="l01046"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3467dd32c5c8da24266290d9b2e95377">01046</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#3467dd32c5c8da24266290d9b2e95377" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::note_data_rcvd</a>() <a name="l01047"></a>01047 { <a name="l01048"></a>01048 log_debug(<span class="stringliteral">"noting data_rcvd"</span>);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l01049"></a>01049 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#906480a8d18388e12f207611a7bdecad" title="Timestamp for idle/keepalive timer.">data_rcvd_</a>, 0); <a name="l01050"></a>01050 } <a name="l01051"></a>01051 <a name="l01052"></a>01052 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01053"></a>01053 <span class="keywordtype">void</span> <a name="l01054"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#9ef41c9f94581292808d7e50472ab07b">01054</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#9ef41c9f94581292808d7e50472ab07b" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::note_data_sent</a>() <a name="l01055"></a>01055 { <a name="l01056"></a>01056 log_debug(<span class="stringliteral">"noting data_sent"</span>);<a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."></a> <a name="l01057"></a>01057 <a class="code" href="namespacedtnsim.html#372b0bd474085f20b38efbbade7ce72a" title="Override gettimeofday to return the simulator time."> ::gettimeofday</a>(&<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#40cc6956b2b157b5f4ef4ef9734cead0" title="Timestamp for idle timer.">data_sent_</a>, 0); <a name="l01058"></a>01058 } <a name="l01059"></a>01059 <a name="l01060"></a>01060 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01061"></a>01061 <span class="keywordtype">bool</span> <a name="l01062"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#2820112f480a485501737eb2962c12e9">01062</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#2820112f480a485501737eb2962c12e9" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_data_segment</a>(u_int8_t flags) <a name="l01063"></a>01063 { <a name="l01064"></a>01064 <a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>* incoming = NULL; <a name="l01065"></a>01065 <span class="keywordflow">if</span> (flags & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#d0516828cb1330f808cf3c7df91a6a9b1ce5167d70b177595c4e42c826c3e225" title="First segment of a bundle.">BUNDLE_START</a>) <a name="l01066"></a>01066 { <a name="l01067"></a>01067 <span class="comment">// make sure we're done with the last bundle if we got a new</span> <a name="l01068"></a>01068 <span class="comment">// BUNDLE_START flag... note that we need to be careful in</span> <a name="l01069"></a>01069 <span class="comment">// case there's not enough data to decode the length of the</span> <a name="l01070"></a>01070 <span class="comment">// segment, since we'll be called again</span> <a name="l01071"></a>01071 <span class="keywordtype">bool</span> create_new_incoming = <span class="keyword">true</span>; <a name="l01072"></a>01072 <span class="keywordflow">if</span> (!<a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.empty()) { <a name="l01073"></a>01073 incoming = <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.back(); <a name="l01074"></a>01074 <a name="l01075"></a>01075 <span class="keywordflow">if</span> (incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.empty() && <a name="l01076"></a>01076 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.empty()) <a name="l01077"></a>01077 { <a name="l01078"></a>01078 log_debug(<span class="stringliteral">"found empty incoming bundle for BUNDLE_START"</span>); <a name="l01079"></a>01079 create_new_incoming = <span class="keyword">false</span>; <a name="l01080"></a>01080 } <a name="l01081"></a>01081 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> == 0) <a name="l01082"></a>01082 { <a name="l01083"></a>01083 log_err(<span class="stringliteral">"protocol error: "</span> <a name="l01084"></a>01084 <span class="stringliteral">"got BUNDLE_START before bundle completed"</span>); <a name="l01085"></a>01085 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01086"></a>01086 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01087"></a>01087 } <a name="l01088"></a>01088 } <a name="l01089"></a>01089 <a name="l01090"></a>01090 <span class="keywordflow">if</span> (create_new_incoming) { <a name="l01091"></a>01091 log_debug(<span class="stringliteral">"got BUNDLE_START segment, creating new IncomingBundle"</span>); <a name="l01092"></a>01092 <a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>* incoming = <span class="keyword">new</span> <a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>(<span class="keyword">new</span> <a class="code" href="classdtn_1_1Bundle.html" title="The internal representation of a bundle.">Bundle</a>()); <a name="l01093"></a>01093 <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.push_back(incoming); <a name="l01094"></a>01094 } <a name="l01095"></a>01095 } <a name="l01096"></a>01096 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.empty()) <a name="l01097"></a>01097 { <a name="l01098"></a>01098 log_err(<span class="stringliteral">"protocol error: "</span> <a name="l01099"></a>01099 <span class="stringliteral">"first data segment doesn't have BUNDLE_START flag set"</span>); <a name="l01100"></a>01100 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01101"></a>01101 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01102"></a>01102 } <a name="l01103"></a>01103 <a name="l01104"></a>01104 <span class="comment">// Note that there may be more than one incoming bundle on the</span> <a name="l01105"></a>01105 <span class="comment">// IncomingList, but it's the one at the back that we're reading</span> <a name="l01106"></a>01106 <span class="comment">// in data for. Others are waiting for acks to be sent.</span> <a name="l01107"></a>01107 incoming = <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.back(); <a name="l01108"></a>01108 u_char* bp = (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(); <a name="l01109"></a>01109 <a name="l01110"></a>01110 <span class="comment">// Decode the segment length and then call handle_data_todo</span> <a name="l01111"></a>01111 u_int32_t segment_len; <a name="l01112"></a>01112 <span class="keywordtype">int</span> sdnv_len = <a class="code" href="SDNV_8cc.html#151d178617a7c2f598cfd7630ebeb7b4">SDNV::decode</a>(bp + 1, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() - 1, <a name="l01113"></a>01113 &segment_len); <a name="l01114"></a>01114 <a name="l01115"></a>01115 <span class="keywordflow">if</span> (sdnv_len < 0) { <a name="l01116"></a>01116 log_debug(<span class="stringliteral">"handle_data_segment: "</span> <a name="l01117"></a>01117 <span class="stringliteral">"too few bytes in buffer for sdnv (%zu)"</span>, <a name="l01118"></a>01118 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l01119"></a>01119 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01120"></a>01120 } <a name="l01121"></a>01121 <a name="l01122"></a>01122 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(1 + sdnv_len); <a name="l01123"></a>01123 <a name="l01124"></a>01124 <span class="keywordflow">if</span> (segment_len == 0) { <a name="l01125"></a>01125 log_err(<span class="stringliteral">"protocol error -- zero length segment"</span>); <a name="l01126"></a>01126 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01127"></a>01127 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01128"></a>01128 } <a name="l01129"></a>01129 <a name="l01130"></a>01130 <span class="keywordtype">size_t</span> segment_offset = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.num_contiguous(); <a name="l01131"></a>01131 log_debug(<span class="stringliteral">"handle_data_segment: "</span> <a name="l01132"></a>01132 <span class="stringliteral">"got segment of length %u at offset %zu "</span>, <a name="l01133"></a>01133 segment_len, segment_offset); <a name="l01134"></a>01134 <a name="l01135"></a>01135 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>.set(segment_offset + segment_len - 1); <a name="l01136"></a>01136 <a name="l01137"></a>01137 log_debug(<span class="stringliteral">"handle_data_segment: "</span> <a name="l01138"></a>01138 <span class="stringliteral">"updated ack_data (segment_offset %zu) *%p ack_data *%p"</span>, <a name="l01139"></a>01139 segment_offset, &incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>, &incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>); <a name="l01140"></a>01140 <a name="l01141"></a>01141 <a name="l01142"></a>01142 <span class="comment">// if this is the last segment for the bundle, we calculate and</span> <a name="l01143"></a>01143 <span class="comment">// store the total length in the IncomingBundle structure so</span> <a name="l01144"></a>01144 <span class="comment">// send_pending_acks knows when we're done.</span> <a name="l01145"></a>01145 <span class="keywordflow">if</span> (flags & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#d0516828cb1330f808cf3c7df91a6a9b0ca0531933393d66d0e47170956ea5d9" title="Last segment of a bundle.">BUNDLE_END</a>) <a name="l01146"></a>01146 { <a name="l01147"></a>01147 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.num_contiguous() + <a name="l01148"></a>01148 segment_len; <a name="l01149"></a>01149 <a name="l01150"></a>01150 log_debug(<span class="stringliteral">"got BUNDLE_END: total length %u"</span>, <a name="l01151"></a>01151 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>); <a name="l01152"></a>01152 } <a name="l01153"></a>01153 <a name="l01154"></a>01154 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a> = segment_len; <a name="l01155"></a>01155 <span class="keywordflow">return</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#11cd8cb07dd92f8577b109a60b680cc5" title="utility functions used internally in this class">handle_data_todo</a>(); <a name="l01156"></a>01156 } <a name="l01157"></a>01157 <a name="l01158"></a>01158 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01159"></a>01159 <span class="keywordtype">bool</span> <a name="l01160"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#11cd8cb07dd92f8577b109a60b680cc5">01160</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#11cd8cb07dd92f8577b109a60b680cc5" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_data_todo</a>() <a name="l01161"></a>01161 { <a name="l01162"></a>01162 <span class="comment">// We shouldn't get ourselves here unless there's something</span> <a name="l01163"></a>01163 <span class="comment">// incoming and there's something left to read</span> <a name="l01164"></a>01164 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(!<a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.empty()); <a name="l01165"></a>01165 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a> != 0); <a name="l01166"></a>01166 <a name="l01167"></a>01167 <span class="comment">// Note that there may be more than one incoming bundle on the</span> <a name="l01168"></a>01168 <span class="comment">// IncomingList. There's always only one (at the back) that we're</span> <a name="l01169"></a>01169 <span class="comment">// reading in data for, the rest are waiting for acks to go out</span> <a name="l01170"></a>01170 <a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>* incoming = <a class="code" href="classdtn_1_1CLConnection.html#d228b2004768c4ee6027823f270a816c" title="Bundles arriving on the wire.">incoming_</a>.back(); <a name="l01171"></a>01171 <span class="keywordtype">size_t</span> rcvd_offset = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.num_contiguous(); <a name="l01172"></a>01172 <span class="keywordtype">size_t</span> rcvd_len = <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes(); <a name="l01173"></a>01173 <span class="keywordtype">size_t</span> chunk_len = std::min(rcvd_len, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a>); <a name="l01174"></a>01174 <a name="l01175"></a>01175 <span class="keywordflow">if</span> (rcvd_len == 0) { <a name="l01176"></a>01176 <span class="keywordflow">return</span> <span class="keyword">false</span>; <span class="comment">// nothing to do</span> <a name="l01177"></a>01177 } <a name="l01178"></a>01178 <a name="l01179"></a>01179 log_debug(<span class="stringliteral">"handle_data_todo: "</span> <a name="l01180"></a>01180 <span class="stringliteral">"reading todo segment %zu/%zu at offset %zu"</span>, <a name="l01181"></a>01181 chunk_len, <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a>, rcvd_offset); <a name="l01182"></a>01182 <a name="l01183"></a>01183 <span class="keywordtype">bool</span> last; <a name="l01184"></a>01184 <span class="keywordtype">int</span> cc = <a class="code" href="classdtn_1_1BundleProtocol.html#b1641c2fd8771fbda02c9ee59a1474df" title="Parse the supplied chunk of arriving data and append it to the rcvd_blocks_ list...">BundleProtocol::consume</a>(incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#7e868dff33d6868d5e42582fac3f4109">bundle_</a>.object(), <a name="l01185"></a>01185 (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(), <a name="l01186"></a>01186 chunk_len, &last); <a name="l01187"></a>01187 <span class="keywordflow">if</span> (cc < 0) { <a name="l01188"></a>01188 log_err(<span class="stringliteral">"protocol error parsing bundle data segment"</span>); <a name="l01189"></a>01189 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01190"></a>01190 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01191"></a>01191 } <a name="l01192"></a>01192 <a name="l01193"></a>01193 <a class="code" href="SDNV_8cc.html#ca68c0d4ac8df0838e209fb5300f7be3">ASSERT</a>(cc == (<span class="keywordtype">int</span>)chunk_len); <a name="l01194"></a>01194 <a name="l01195"></a>01195 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a> -= chunk_len; <a name="l01196"></a>01196 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(chunk_len); <a name="l01197"></a>01197 <a name="l01198"></a>01198 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.set(rcvd_offset, chunk_len); <a name="l01199"></a>01199 <a name="l01200"></a>01200 log_debug(<span class="stringliteral">"handle_data_todo: "</span> <a name="l01201"></a>01201 <span class="stringliteral">"updated recv_data (rcvd_offset %zu) *%p ack_data *%p"</span>, <a name="l01202"></a>01202 rcvd_offset, &incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>, &incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#ec95d04d452ca75f28de4ba845e0a856">ack_data_</a>); <a name="l01203"></a>01203 <a name="l01204"></a>01204 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#ba8fdf9ef5426b99c0215d6e210c2e13" title="Bytes left to recv of current segment.">recv_segment_todo_</a> == 0) { <a name="l01205"></a>01205 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d" title="utility functions used internally in this class">check_completed</a>(incoming); <a name="l01206"></a>01206 <span class="keywordflow">return</span> <span class="keyword">true</span>; <span class="comment">// completed segment</span> <a name="l01207"></a>01207 } <a name="l01208"></a>01208 <a name="l01209"></a>01209 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01210"></a>01210 } <a name="l01211"></a>01211 <a name="l01212"></a>01212 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01213"></a>01213 <span class="keywordtype">void</span> <a name="l01214"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#f416ffa9b2ccd83d41cf8eec72856e4b">01214</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::check_completed</a>(<a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html" title="Struct used to record bundles that are in the process of being received along with...">IncomingBundle</a>* incoming) <a name="l01215"></a>01215 { <a name="l01216"></a>01216 u_int32_t rcvd_len = incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.num_contiguous(); <a name="l01217"></a>01217 <a name="l01218"></a>01218 <span class="comment">// if we don't know the total length yet, we haven't seen the</span> <a name="l01219"></a>01219 <span class="comment">// BUNDLE_END message</span> <a name="l01220"></a>01220 <span class="keywordflow">if</span> (incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> == 0) { <a name="l01221"></a>01221 <span class="keywordflow">return</span>; <a name="l01222"></a>01222 } <a name="l01223"></a>01223 <a name="l01224"></a>01224 u_int32_t formatted_len = <a name="l01225"></a>01225 <a class="code" href="classdtn_1_1BundleProtocol.html#a1dedd9ea4300339bc2a3f7a231ca5dd" title="Return the total length of the formatted bundle block data.">BundleProtocol::total_length</a>(&incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#7e868dff33d6868d5e42582fac3f4109">bundle_</a>->recv_blocks()); <a name="l01226"></a>01226 <a name="l01227"></a>01227 log_debug(<span class="stringliteral">"check_completed: rcvd %u / %u (formatted length %u)"</span>, <a name="l01228"></a>01228 rcvd_len, incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>, formatted_len); <a name="l01229"></a>01229 <a name="l01230"></a>01230 <span class="keywordflow">if</span> (rcvd_len < incoming->total_length_) { <a name="l01231"></a>01231 <span class="keywordflow">return</span>; <a name="l01232"></a>01232 } <a name="l01233"></a>01233 <a name="l01234"></a>01234 <span class="keywordflow">if</span> (rcvd_len > incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>) { <a name="l01235"></a>01235 log_err(<span class="stringliteral">"protocol error: received too much data -- "</span> <a name="l01236"></a>01236 <span class="stringliteral">"got %u, total length %u"</span>, <a name="l01237"></a>01237 rcvd_len, incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>); <a name="l01238"></a>01238 <a name="l01239"></a>01239 <span class="comment">// we pretend that we got nothing so the cleanup code in</span> <a name="l01240"></a>01240 <span class="comment">// ConnectionCL::close_contact doesn't try to post a received</span> <a name="l01241"></a>01241 <span class="comment">// event for the bundle</span> <a name="l01242"></a>01242 protocol_err: <a name="l01243"></a>01243 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#414686f37abb161c1e5bc3ca9c02ad48">rcvd_data_</a>.clear(); <a name="l01244"></a>01244 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01245"></a>01245 <span class="keywordflow">return</span>; <a name="l01246"></a>01246 } <a name="l01247"></a>01247 <a name="l01248"></a>01248 <span class="comment">// validate that the total length as conveyed by the convergence</span> <a name="l01249"></a>01249 <span class="comment">// layer matches the length according to the bundle protocol</span> <a name="l01250"></a>01250 <span class="keywordflow">if</span> (incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a> != formatted_len) { <a name="l01251"></a>01251 log_err(<span class="stringliteral">"protocol error: CL total length %u "</span> <a name="l01252"></a>01252 <span class="stringliteral">"doesn't match bundle protocol total %u"</span>, <a name="l01253"></a>01253 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>, formatted_len); <a name="l01254"></a>01254 <span class="keywordflow">goto</span> protocol_err; <a name="l01255"></a>01255 <a name="l01256"></a>01256 } <a name="l01257"></a>01257 <a name="l01258"></a>01258 <a class="code" href="classdtn_1_1BundleDaemon.html#370a80f7dd9fd9297e76d7f830d737a8" title="Queues the event at the tail of the queue for processing by the daemon thread.">BundleDaemon::post</a>( <a name="l01259"></a>01259 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleReceivedEvent.html" title="Event class for new bundle arrivals.">BundleReceivedEvent</a>(incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#7e868dff33d6868d5e42582fac3f4109">bundle_</a>.object(), <a name="l01260"></a>01260 <a class="code" href="namespacedtn.html#60ee39c9672604f59fe1b12d4e1d142bb0775776e4be46e62a0dcff6cf968059" title="a peer dtn forwarder">EVENTSRC_PEER</a>, <a name="l01261"></a>01261 incoming-><a class="code" href="classdtn_1_1CLConnection_1_1IncomingBundle.html#2f9d5b3f0487449503664a0429f59d33">total_length_</a>, <a name="l01262"></a>01262 <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link()->remote_eid(), <a name="l01263"></a>01263 <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link().object())); <a name="l01264"></a>01264 } <a name="l01265"></a>01265 <a name="l01266"></a>01266 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01267"></a>01267 <span class="keywordtype">bool</span> <a name="l01268"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4e953071e0c7ee2e9157c11b7f998bd6">01268</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#4e953071e0c7ee2e9157c11b7f998bd6" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_ack_segment</a>(u_int8_t flags) <a name="l01269"></a>01269 { <a name="l01270"></a>01270 (void)flags; <a name="l01271"></a>01271 u_char* bp = (u_char*)<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(); <a name="l01272"></a>01272 u_int32_t acked_len; <a name="l01273"></a>01273 <span class="keywordtype">int</span> sdnv_len = <a class="code" href="SDNV_8cc.html#151d178617a7c2f598cfd7630ebeb7b4">SDNV::decode</a>(bp + 1, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() - 1, &acked_len); <a name="l01274"></a>01274 <a name="l01275"></a>01275 <span class="keywordflow">if</span> (sdnv_len < 0) { <a name="l01276"></a>01276 log_debug(<span class="stringliteral">"handle_ack_segment: too few bytes for sdnv (%zu)"</span>, <a name="l01277"></a>01277 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes()); <a name="l01278"></a>01278 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01279"></a>01279 } <a name="l01280"></a>01280 <a name="l01281"></a>01281 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(1 + sdnv_len); <a name="l01282"></a>01282 <a name="l01283"></a>01283 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.empty()) { <a name="l01284"></a>01284 log_err(<span class="stringliteral">"protocol error: got ack segment with no inflight bundle"</span>); <a name="l01285"></a>01285 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01286"></a>01286 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01287"></a>01287 } <a name="l01288"></a>01288 <a name="l01289"></a>01289 <a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html" title="Struct used to record bundles that are in-flight along with their transmission state...">InFlightBundle</a>* inflight = <a class="code" href="classdtn_1_1CLConnection.html#bb337ec089b627c417864a01a095319e" title="Bundles going out the wire.">inflight_</a>.front(); <a name="l01290"></a>01290 <a name="l01291"></a>01291 <span class="keywordtype">size_t</span> ack_begin; <a name="l01292"></a>01292 DataBitmap::iterator i = inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>.begin(); <a name="l01293"></a>01293 <span class="keywordflow">if</span> (i == inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>.end()) { <a name="l01294"></a>01294 ack_begin = 0; <a name="l01295"></a>01295 } <span class="keywordflow">else</span> { <a name="l01296"></a>01296 i.skip_contiguous(); <a name="l01297"></a>01297 ack_begin = *i + 1; <a name="l01298"></a>01298 } <a name="l01299"></a>01299 <a name="l01300"></a>01300 <span class="keywordflow">if</span> (acked_len < ack_begin) { <a name="l01301"></a>01301 log_err(<span class="stringliteral">"protocol error: got ack for length %u but already acked up to %zu"</span>, <a name="l01302"></a>01302 acked_len, ack_begin); <a name="l01303"></a>01303 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01304"></a>01304 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01305"></a>01305 } <a name="l01306"></a>01306 <a name="l01307"></a>01307 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>.set(0, acked_len); <a name="l01308"></a>01308 <a name="l01309"></a>01309 <span class="comment">// now check if this was the last ack for the bundle, in which</span> <a name="l01310"></a>01310 <span class="comment">// case we can pop it off the list and post a</span> <a name="l01311"></a>01311 <span class="comment">// BundleTransmittedEvent</span> <a name="l01312"></a>01312 <span class="keywordflow">if</span> (acked_len == inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#fde31db0c5211defbb1e58d66efb8a68">total_length_</a>) { <a name="l01313"></a>01313 log_debug(<span class="stringliteral">"handle_ack_segment: got final ack for %zu byte range -- "</span> <a name="l01314"></a>01314 <span class="stringliteral">"acked_len %u, ack_data *%p"</span>, <a name="l01315"></a>01315 (<span class="keywordtype">size_t</span>)acked_len - ack_begin, <a name="l01316"></a>01316 acked_len, &inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>); <a name="l01317"></a>01317 <a name="l01318"></a>01318 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#c9159f7ebd46e2427c4095d5bcc1d3e9">transmit_event_posted_</a> = <span class="keyword">true</span>; <a name="l01319"></a>01319 <a name="l01320"></a>01320 <a class="code" href="classdtn_1_1BundleDaemon.html#370a80f7dd9fd9297e76d7f830d737a8" title="Queues the event at the tail of the queue for processing by the daemon thread.">BundleDaemon::post</a>( <a name="l01321"></a>01321 <span class="keyword">new</span> <a class="code" href="classdtn_1_1BundleTransmittedEvent.html" title="Event class for bundle or fragment transmission.">BundleTransmittedEvent</a>(inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#e0fb72eeccee446eccf8b17a3cc84b94">bundle_</a>.object(), <a name="l01322"></a>01322 <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>, <a name="l01323"></a>01323 <a class="code" href="classdtn_1_1CLConnection.html#29c0707d21c5347919186a8e14728ed0" title="Ref to the Contact.">contact_</a>->link(), <a name="l01324"></a>01324 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#f4f89ea9800c7eefe41e51018188180a">sent_data_</a>.num_contiguous(), <a name="l01325"></a>01325 inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>.num_contiguous())); <a name="l01326"></a>01326 <a name="l01327"></a>01327 <span class="comment">// might delete inflight</span> <a name="l01328"></a>01328 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bd92299ff0aa3ba935cfdc180a29855d" title="utility functions used internally in this class">check_completed</a>(inflight); <a name="l01329"></a>01329 <a name="l01330"></a>01330 } <span class="keywordflow">else</span> { <a name="l01331"></a>01331 log_debug(<span class="stringliteral">"handle_ack_segment: "</span> <a name="l01332"></a>01332 <span class="stringliteral">"got acked_len %u (%zu byte range) -- ack_data *%p"</span>, <a name="l01333"></a>01333 acked_len, (<span class="keywordtype">size_t</span>)acked_len - ack_begin, &inflight-><a class="code" href="classdtn_1_1CLConnection_1_1InFlightBundle.html#7ba3f112c83aea033fab72f7759ce7f2">ack_data_</a>); <a name="l01334"></a>01334 } <a name="l01335"></a>01335 <a name="l01336"></a>01336 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01337"></a>01337 } <a name="l01338"></a>01338 <a name="l01339"></a>01339 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01340"></a>01340 <span class="keywordtype">bool</span> <a name="l01341"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#c6509bf3539fc74f5bcb128379acf8dd">01341</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#c6509bf3539fc74f5bcb128379acf8dd" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_refuse_bundle</a>(u_int8_t flags) <a name="l01342"></a>01342 { <a name="l01343"></a>01343 (void)flags; <a name="l01344"></a>01344 log_debug(<span class="stringliteral">"got refuse_bundle message"</span>); <a name="l01345"></a>01345 log_err(<span class="stringliteral">"REFUSE_BUNDLE not implemented"</span>); <a name="l01346"></a>01346 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>); <a name="l01347"></a>01347 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01348"></a>01348 } <a name="l01349"></a>01349 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01350"></a>01350 <span class="keywordtype">bool</span> <a name="l01351"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#71fc76a4d77152e025c1e5246894a656">01351</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#71fc76a4d77152e025c1e5246894a656" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_keepalive</a>(u_int8_t flags) <a name="l01352"></a>01352 { <a name="l01353"></a>01353 (void)flags; <a name="l01354"></a>01354 log_debug(<span class="stringliteral">"got keepalive message"</span>); <a name="l01355"></a>01355 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(1); <a name="l01356"></a>01356 <span class="keywordflow">return</span> <span class="keyword">true</span>; <a name="l01357"></a>01357 } <a name="l01358"></a>01358 <a name="l01359"></a>01359 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01360"></a>01360 <span class="keywordtype">void</span> <a name="l01361"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b">01361</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">StreamConvergenceLayer::Connection::break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7" title="Reason codes for contact state operations.">ContactEvent::reason_t</a> reason) <a name="l01362"></a>01362 { <a name="l01363"></a>01363 <span class="comment">// it's possible that we can end up calling break_contact multiple</span> <a name="l01364"></a>01364 <span class="comment">// times, if for example we have an error when sending out the</span> <a name="l01365"></a>01365 <span class="comment">// shutdown message below. we simply ignore the multiple calls</span> <a name="l01366"></a>01366 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#592661b95051f90a7b390cafee133a9f" title="Bit to catch multiple calls to break_contact.">breaking_contact_</a>) { <a name="l01367"></a>01367 <span class="keywordflow">return</span>; <a name="l01368"></a>01368 } <a name="l01369"></a>01369 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#592661b95051f90a7b390cafee133a9f" title="Bit to catch multiple calls to break_contact.">breaking_contact_</a> = <span class="keyword">true</span>; <a name="l01370"></a>01370 <a name="l01371"></a>01371 <span class="comment">// we can only send a shutdown byte if we're not in the middle</span> <a name="l01372"></a>01372 <span class="comment">// of sending a segment, otherwise the shutdown byte could be</span> <a name="l01373"></a>01373 <span class="comment">// interpreted as a part of the payload</span> <a name="l01374"></a>01374 <span class="keywordtype">bool</span> send_shutdown = <span class="keyword">false</span>; <a name="l01375"></a>01375 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b38" title="Values for the SHUTDOWN reason codes.">shutdown_reason_t</a> shutdown_reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>; <a name="l01376"></a>01376 <a name="l01377"></a>01377 <span class="keywordflow">switch</span> (reason) { <a name="l01378"></a>01378 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f72e449a76cefd484940a3f3bfc07d188e" title="User action (i.e. console / config).">ContactEvent::USER</a>: <a name="l01379"></a>01379 <span class="comment">// if the user is closing this link, we say that we're busy</span> <a name="l01380"></a>01380 send_shutdown = <span class="keyword">true</span>; <a name="l01381"></a>01381 shutdown_reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b389bcc936ab6b796dbc92b92b9c5327e6b" title="node is busy">SHUTDOWN_BUSY</a>; <a name="l01382"></a>01382 <span class="keywordflow">break</span>; <a name="l01383"></a>01383 <a name="l01384"></a>01384 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7cc4b8963a82f22c0d9b61c37e06e877e" title="Idle connection shut down by the CL.">ContactEvent::IDLE</a>: <a name="l01385"></a>01385 <span class="comment">// if we're idle, indicate as such</span> <a name="l01386"></a>01386 send_shutdown = <span class="keyword">true</span>; <a name="l01387"></a>01387 shutdown_reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b381fca6e7cc76836e4ae89e179fb4cff90" title="idle connection">SHUTDOWN_IDLE_TIMEOUT</a>; <a name="l01388"></a>01388 <span class="keywordflow">break</span>; <a name="l01389"></a>01389 <a name="l01390"></a>01390 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f72e018ae4b4ab30873b97e51e26e2baf2" title="Clean connection shutdown.">ContactEvent::SHUTDOWN</a>: <a name="l01391"></a>01391 <span class="comment">// if the other side shuts down first, we send the</span> <a name="l01392"></a>01392 <span class="comment">// corresponding SHUTDOWN byte for a clean handshake, but</span> <a name="l01393"></a>01393 <span class="comment">// don't give any more reason</span> <a name="l01394"></a>01394 send_shutdown = <span class="keyword">true</span>; <a name="l01395"></a>01395 <span class="keywordflow">break</span>; <a name="l01396"></a>01396 <a name="l01397"></a>01397 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7f0c1475c056a0f72e11b5ba8466a27f7" title="Unexpected session interruption.">ContactEvent::BROKEN</a>: <a name="l01398"></a>01398 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f793b4b30e007a04676c706a0b749ef033" title="Convergence layer protocol error.">ContactEvent::CL_ERROR</a>: <a name="l01399"></a>01399 <span class="comment">// no shutdown </span> <a name="l01400"></a>01400 send_shutdown = <span class="keyword">false</span>; <a name="l01401"></a>01401 <span class="keywordflow">break</span>; <a name="l01402"></a>01402 <a name="l01403"></a>01403 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f704fb70b2e32b5f6f3e3707dc12958787" title="Convergence layer version mismatch.">ContactEvent::CL_VERSION</a>: <a name="l01404"></a>01404 <span class="comment">// version mismatch</span> <a name="l01405"></a>01405 send_shutdown = <span class="keyword">true</span>; <a name="l01406"></a>01406 shutdown_reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b38a623d9b20734c83802ea80dc8df1489e" title="version mismatch">SHUTDOWN_VERSION_MISMATCH</a>; <a name="l01407"></a>01407 <span class="keywordflow">break</span>; <a name="l01408"></a>01408 <a name="l01409"></a>01409 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f73a8badb37c6d8128d816779957448c61" title="Should not be used.">ContactEvent::INVALID</a>: <a name="l01410"></a>01410 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7745e7897b68d73fa05257424c8746ded" title="No additional info.">ContactEvent::NO_INFO</a>: <a name="l01411"></a>01411 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7fe3939848fd2dc31d31aec1c8c1f3c2a" title="Re-establish link after failure.">ContactEvent::RECONNECT</a>: <a name="l01412"></a>01412 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7eb788e67896aff756d499766183ff6d8" title="Scheduled link ended duration.">ContactEvent::TIMEOUT</a>: <a name="l01413"></a>01413 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f7648efe2b249ca6cd507125d819392b8d" title="Dynamically discovered link.">ContactEvent::DISCOVERY</a>: <a name="l01414"></a>01414 NOTREACHED; <a name="l01415"></a>01415 <span class="keywordflow">break</span>; <a name="l01416"></a>01416 } <a name="l01417"></a>01417 <a name="l01418"></a>01418 <span class="comment">// of course, we can't send anything if we were interrupted in the</span> <a name="l01419"></a>01419 <span class="comment">// middle of sending a block.</span> <a name="l01420"></a>01420 <span class="comment">//</span> <a name="l01421"></a>01421 <span class="comment">// XXX/demmer if we receive a SHUTDOWN byte from the other side,</span> <a name="l01422"></a>01422 <span class="comment">// we don't have any way of continuing to transmit our own blocks</span> <a name="l01423"></a>01423 <span class="comment">// and then shut down afterwards</span> <a name="l01424"></a>01424 <span class="keywordflow">if</span> (send_shutdown && <a name="l01425"></a>01425 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fullbytes() == 0 && <a name="l01426"></a>01426 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#5fb1d3c5c5069a8142d4ac8c6303212c" title="Bytes left to send of current segment.">send_segment_todo_</a> == 0) <a name="l01427"></a>01427 { <a name="l01428"></a>01428 log_debug(<span class="stringliteral">"break_contact: sending shutdown"</span>); <a name="l01429"></a>01429 <span class="keywordtype">char</span> typecode = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#183d0df09b1791083a921382569f53acfdbe69c942f3d92b9f503c9ba5c87a37" title="about to shutdown">SHUTDOWN</a>; <a name="l01430"></a>01430 <span class="keywordflow">if</span> (shutdown_reason != <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>) { <a name="l01431"></a>01431 typecode |= <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7a4e7b19ccf485147cd8ab341f7f642c4053159703ea6ea3c8de5045f73e12f7" title="Has reason code.">SHUTDOWN_HAS_REASON</a>; <a name="l01432"></a>01432 } <a name="l01433"></a>01433 <a name="l01434"></a>01434 <span class="comment">// XXX/demmer should we send a reconnect delay??</span> <a name="l01435"></a>01435 <a name="l01436"></a>01436 *<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end() = typecode; <a name="l01437"></a>01437 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(1); <a name="l01438"></a>01438 <a name="l01439"></a>01439 <span class="keywordflow">if</span> (shutdown_reason != <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>) { <a name="l01440"></a>01440 *<a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.end() = shutdown_reason; <a name="l01441"></a>01441 <a class="code" href="classdtn_1_1CLConnection.html#95f89064268605c6183fa4c436a12071" title="Buffer for outgoing data.">sendbuf_</a>.fill(1); <a name="l01442"></a>01442 } <a name="l01443"></a>01443 <a name="l01444"></a>01444 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#bbdabd686c5d5e5a9bf30706a7ab849c" title="Hook used to tell the derived CL class to drain data out of the send buffer.">send_data</a>(); <a name="l01445"></a>01445 } <a name="l01446"></a>01446 <a name="l01447"></a>01447 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">CLConnection::break_contact</a>(reason); <a name="l01448"></a>01448 } <a name="l01449"></a>01449 <a name="l01450"></a>01450 <span class="comment">//----------------------------------------------------------------------</span> <a name="l01451"></a>01451 <span class="keywordtype">bool</span> <a name="l01452"></a><a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#62654499c48ef4b7815333db6813689f">01452</a> <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#62654499c48ef4b7815333db6813689f" title="utility functions used internally in this class">StreamConvergenceLayer::Connection::handle_shutdown</a>(u_int8_t flags) <a name="l01453"></a>01453 { <a name="l01454"></a>01454 log_debug(<span class="stringliteral">"got SHUTDOWN byte"</span>); <a name="l01455"></a>01455 <span class="keywordtype">size_t</span> shutdown_len = 1; <a name="l01456"></a>01456 <a name="l01457"></a>01457 <span class="keywordflow">if</span> (flags & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7a4e7b19ccf485147cd8ab341f7f642c4053159703ea6ea3c8de5045f73e12f7" title="Has reason code.">SHUTDOWN_HAS_REASON</a>) <a name="l01458"></a>01458 { <a name="l01459"></a>01459 shutdown_len += 1; <a name="l01460"></a>01460 } <a name="l01461"></a>01461 <a name="l01462"></a>01462 <span class="keywordflow">if</span> (flags & <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7a4e7b19ccf485147cd8ab341f7f642c478975a37cc3b9079370e8581b595070" title="Has reconnect delay.">SHUTDOWN_HAS_DELAY</a>) <a name="l01463"></a>01463 { <a name="l01464"></a>01464 shutdown_len += 2; <a name="l01465"></a>01465 } <a name="l01466"></a>01466 <a name="l01467"></a>01467 <span class="keywordflow">if</span> (<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes() < shutdown_len) <a name="l01468"></a>01468 { <a name="l01469"></a>01469 <span class="comment">// rare case where there's not enough data in the buffer</span> <a name="l01470"></a>01470 <span class="comment">// to handle the shutdown message data</span> <a name="l01471"></a>01471 log_debug(<span class="stringliteral">"got %zu/%zu bytes for shutdown data... waiting for more"</span>, <a name="l01472"></a>01472 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.fullbytes(), shutdown_len); <a name="l01473"></a>01473 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01474"></a>01474 } <a name="l01475"></a>01475 <a name="l01476"></a>01476 <span class="comment">// now handle the message, first skipping the typecode byte</span> <a name="l01477"></a>01477 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(1); <a name="l01478"></a>01478 <a name="l01479"></a>01479 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b38" title="Values for the SHUTDOWN reason codes.">shutdown_reason_t</a> reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>; <a name="l01480"></a>01480 <span class="keywordflow">if</span> (flags & SHUTDOWN_HAS_REASON) <a name="l01481"></a>01481 { <a name="l01482"></a>01482 <span class="keywordflow">switch</span> (*<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start()) { <a name="l01483"></a>01483 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>: <a name="l01484"></a>01484 reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b3869622c46041eb62e40fea1813a48971c" title="no reason code (never sent)">SHUTDOWN_NO_REASON</a>; <a name="l01485"></a>01485 <span class="keywordflow">break</span>; <a name="l01486"></a>01486 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b381fca6e7cc76836e4ae89e179fb4cff90" title="idle connection">SHUTDOWN_IDLE_TIMEOUT</a>: <a name="l01487"></a>01487 reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b381fca6e7cc76836e4ae89e179fb4cff90" title="idle connection">SHUTDOWN_IDLE_TIMEOUT</a>; <a name="l01488"></a>01488 <span class="keywordflow">break</span>; <a name="l01489"></a>01489 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b38a623d9b20734c83802ea80dc8df1489e" title="version mismatch">SHUTDOWN_VERSION_MISMATCH</a>: <a name="l01490"></a>01490 reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b38a623d9b20734c83802ea80dc8df1489e" title="version mismatch">SHUTDOWN_VERSION_MISMATCH</a>; <a name="l01491"></a>01491 <span class="keywordflow">break</span>; <a name="l01492"></a>01492 <span class="keywordflow">case</span> <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b389bcc936ab6b796dbc92b92b9c5327e6b" title="node is busy">SHUTDOWN_BUSY</a>: <a name="l01493"></a>01493 reason = <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#7b1454224520c3344536c8d5fcc07b389bcc936ab6b796dbc92b92b9c5327e6b" title="node is busy">SHUTDOWN_BUSY</a>; <a name="l01494"></a>01494 <span class="keywordflow">break</span>; <a name="l01495"></a>01495 <span class="keywordflow">default</span>: <a name="l01496"></a>01496 log_err(<span class="stringliteral">"invalid shutdown reason code 0x%x"</span>, *<a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start()); <a name="l01497"></a>01497 } <a name="l01498"></a>01498 <a name="l01499"></a>01499 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(1); <a name="l01500"></a>01500 } <a name="l01501"></a>01501 <a name="l01502"></a>01502 u_int16_t delay = 0; <a name="l01503"></a>01503 <span class="keywordflow">if</span> (flags & SHUTDOWN_HAS_DELAY) <a name="l01504"></a>01504 { <a name="l01505"></a>01505 memcpy(&delay, <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.start(), 2); <a name="l01506"></a>01506 delay = ntohs(delay); <a name="l01507"></a>01507 <a class="code" href="classdtn_1_1CLConnection.html#483ff0dd2871a812491c16aa8d3f9124" title="Buffer for incoming data.">recvbuf_</a>.consume(2); <a name="l01508"></a>01508 } <a name="l01509"></a>01509 <a name="l01510"></a>01510 log_info(<span class="stringliteral">"got SHUTDOWN (%s) [reconnect delay %u]"</span>, <a name="l01511"></a>01511 <a class="code" href="classdtn_1_1StreamConvergenceLayer.html#196057db7dfae4139d9f7913eb610db1" title="Convert a reason code to a string.">shutdown_reason_to_str</a>(reason), delay); <a name="l01512"></a>01512 <a name="l01513"></a>01513 <a class="code" href="classdtn_1_1StreamConvergenceLayer_1_1Connection.html#b06d1276d10f66d40f04da6bd824e54b" title="virtual from CLConnection">break_contact</a>(<a class="code" href="classdtn_1_1ContactEvent.html#e20f7357509a2bcca3d8e6c8daf552f72e018ae4b4ab30873b97e51e26e2baf2" title="Clean connection shutdown.">ContactEvent::SHUTDOWN</a>); <a name="l01514"></a>01514 <a name="l01515"></a>01515 <span class="keywordflow">return</span> <span class="keyword">false</span>; <a name="l01516"></a>01516 } <a name="l01517"></a>01517 <a name="l01518"></a>01518 } <span class="comment">// namespace dtn</span> </pre></div></div> <hr size="1"><address style="text-align: right;"><small>Generated on Fri Jan 30 09:26:58 2009 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.8 </small></address> </body> </html>