<html>
 <body>
  <div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
   <table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
    <tr>
     <td>
      This is an automatically generated e-mail. To reply, visit:
      <a href="https://reviewboard.asterisk.org/r/2010/">https://reviewboard.asterisk.org/r/2010/</a>
     </td>
    </tr>
   </table>
   <br />









<div>




<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
 <thead>
  <tr>
   <th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
    <a href="https://reviewboard.asterisk.org/r/2010/diff/1/?file=29618#file29618line67" style="color: black; font-weight: bold; text-decoration: underline;">/trunk/funcs/func_jitterbuffer.c</a>
    <span style="font-weight: normal;">

     (Diff revision 1)

    </span>
   </th>
  </tr>
 </thead>

 <tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
  <tr>

   <td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">ASTERISK_FILE_VERSION(__FILE__, &quot;$Revision$&quot;)</pre></td>

  </tr>
 </tbody>




 
 



 <tbody>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">67</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="cm">                        &lt;para&gt;frame_type: The type of frame this jitter buffer applies to.  Default is audio&lt;/para&gt;</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">68</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="cm">                        &lt;para&gt;Valid values are: &lt;literal&gt;voice&lt;/literal&gt; or &lt;literal&gt;dtmf&lt;/literal&gt;.&lt;/para&gt;</span></pre></td>
  </tr>

 </tbody>

</table>

<pre style="margin-left: 2em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">This says that default is audio, but then gives valid values as &quot;voice&quot; and &quot;dtmf&quot;. Change the wording so that the default is &quot;voice&quot;</pre>
</div>
<br />

<div>




<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
 <thead>
  <tr>
   <th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
    <a href="https://reviewboard.asterisk.org/r/2010/diff/1/?file=29618#file29618line561" style="color: black; font-weight: bold; text-decoration: underline;">/trunk/funcs/func_jitterbuffer.c</a>
    <span style="font-weight: normal;">

     (Diff revision 1)

    </span>
   </th>
  </tr>
 </thead>

 <tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
  <tr>

   <td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)</pre></td>

  </tr>
 </tbody>




 
 



 <tbody>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">514</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="n">tmp_frametype</span> <span class="o">=</span> <span class="n">ast_strdupa</span><span class="p">(</span><span class="n">capability</span><span class="p">);</span></pre></td>
  </tr>

 </tbody>

</table>

<pre style="margin-left: 2em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Minor, but why are you duplicating the string? You don&#39;t make any changes to it.</pre>
</div>
<br />

<div>




<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
 <thead>
  <tr>
   <th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
    <a href="https://reviewboard.asterisk.org/r/2010/diff/1/?file=29618#file29618line624" style="color: black; font-weight: bold; text-decoration: underline;">/trunk/funcs/func_jitterbuffer.c</a>
    <span style="font-weight: normal;">

     (Diff revision 1)

    </span>
   </th>
  </tr>
 </thead>

 <tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
  <tr>

   <td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)</pre></td>

  </tr>
 </tbody>




 
 



 <tbody>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">574</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="cm">/* Framehook does not exist - create it and attach to the channel */</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">575</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">framedata</span> <span class="o">=</span> <span class="n">jb_framedata_create</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">value</span><span class="p">)))</span> <span class="p">{</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">576</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                <span class="k">return</span> <span class="mi">0</span><span class="p">;</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">577</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="p">}</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">578</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="n">interface</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">framedata</span><span class="p">;</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">579</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">580</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">datastore</span> <span class="o">=</span> <span class="n">ast_datastore_alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">jb_datastore</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)))</span> <span class="p">{</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">581</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                <span class="n">jb_framedata_destroy</span><span class="p">(</span><span class="n">framedata</span><span class="p">);</span></pre></td>
  </tr>

 </tbody>





 
 

 <tbody>

  <tr>
    <th bgcolor="#f0f0f0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2">349</font></th>
    <td bgcolor="#ffffff" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span></pre></td>
    <th bgcolor="#f0f0f0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">582</font></th>
    <td bgcolor="#ffffff" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                <span class="k">return</span> <span class="mi">0</span><span class="p">;</span></pre></td>
  </tr>

  <tr>
    <th bgcolor="#f0f0f0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2">350</font></th>
    <td bgcolor="#ffffff" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                <span class="p">}</span></pre></td>
    <th bgcolor="#f0f0f0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">583</font></th>
    <td bgcolor="#ffffff" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">        <span class="p">}</span></pre></td>
  </tr>

 </tbody>

</table>

<pre style="margin-left: 2em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Your change to make the framehook interface file-scoped instead of channel-scoped feels wrong. Specifically, this manipulation of interface.data is dangerous. If multiple channels are using func_jitterbuffer, then the wrong data could end up being manipulated. Plus, it&#39;s easy to leak memory or end up double-freeing memory in the case that multiple channels are using func_jitterbuffer.</pre>
</div>
<br />

<div>




<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
 <thead>
  <tr>
   <th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
    <a href="https://reviewboard.asterisk.org/r/2010/diff/1/?file=29629#file29629line2286" style="color: black; font-weight: bold; text-decoration: underline;">/trunk/res/res_rtp_asterisk.c</a>
    <span style="font-weight: normal;">

     (Diff revision 1)

    </span>
   </th>
  </tr>
 </thead>

 <tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
  <tr>

   <td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark, struct frame_list *frames)</pre></td>

  </tr>
 </tbody>




 
 



 <tbody>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">2286</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">                                        <span class="n">f</span><span class="o">-&gt;</span><span class="n">ts</span> <span class="o">=</span> <span class="n">timestamp</span> <span class="o">/</span> <span class="p">(</span><span class="n">rtp_get_rate</span><span class="p">(</span><span class="o">&amp;</span><span class="n">f</span><span class="o">-&gt;</span><span class="n">subclass</span><span class="p">.</span><span class="n">format</span><span class="p">)</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">)</span><span class="cm">/* + new_duration*/</span><span class="p">;</span></pre></td>
  </tr>

 </tbody>

</table>

<pre style="margin-left: 2em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Does this comment indicate there&#39;s more to be done here?</pre>
</div>
<br />



<p>- Mark</p>


<br />
<p>On July 5th, 2012, 11:43 a.m., Matt Jordan wrote:</p>






<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('https://reviewboard.asterisk.org/media/rb/images/review_request_box_top_bg.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
 <tr>
  <td>

<div>Review request for Asterisk Developers.</div>
<div>By Matt Jordan.</div>


<p style="color: grey;"><i>Updated July 5, 2012, 11:43 a.m.</i></p>




<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">The current RTP stack in Asterisk does not have any inbound buffering capabilities.  For RFC 2833 DTMF packets that arrive out of order, the RTP layer does the best it can, and - if it detects packets that have arrived out of order, or, in general, don&#39;t make &quot;sense&quot; (packets marked as an &#39;end&#39; when no &#39;begin&#39; occurred, etc.) - it attempts to prevent duplicate DTMF or other weird scenarios.  This may include dropping the packets.  Unfortunately, this means that - in some situations - some DTMF digits may have very odd durations or may not occur at all, if a sufficient number of packets arrive out of order.

Providing buffering in the RTP layer isn&#39;t really the correct answer here - putting a buffer on the receiving side of the RTP stack would have some fairly large ramifications on channel read operations.  Since we already have the capability to put a jitter buffer on the read side of a channel in Asterisk 10/11, this patch expands the capabilities of these jitter buffers to &#39;understand&#39; DTMF.

This works in the following way:
1. If no Jitter Buffer exists on the channel that owns the RTP instance, the behavior of the RTP instance is unchanged (it will drop out of order RFC 2833 DTMF)
2. When a Jitter Buffer is placed on a channel using func_jitterbuffer, a new control frame is sent to the channel.  The channel, if it supports RTP, lets its RTP instance know that a jitter buffer it cares about may be in existance.
3. The RTP instance queries the frame hooks to see if a jitter buffer capable of handling DTMF exists.  If it does, it sets a flag to allow out of order DTMF packets to flow up into the channel technology (and from there, into the bridging core)
4. The abstract jitter buffer code now handles the DTMF that flows in and out of it.  This includes handling multiple END frames, handling BEGIN frames without END frames - the usual stuff that the RTP layer would have taken care of for us.</pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Unit testing: This patch includes a new abstract_jb test.  This checks the following:
 1. Nominal creation of fixed/adaptive voice/dtmf jitter buffers
 2. Nominal putting/retrieval of frames from fixed/adaptive voice/dtmf jitter buffers
 3. Overflow in said jitter buffers
 4. Out of order handling in said jitter buffers
 5. Multiple DTMF END packets in DTMF jitter buffers

Functional testing in the Asterisk Test Suite: A new func_jitterbuffer test was written.  RFC2833_dtmf_detect passed with no modifications, showing that the RTP layer - without a DTMF jitter buffer - worked the same.  A new test, RFC2833_dtmf_jitterbuffer, was written that also successfully re-ordered the out of order DTMF.  These tests will be put up on a separate review. 

System testing: lots of smashing on IVRs with a DTMF jitter buffer.  Successfully handled lots of short DTMF durations, long DTMF durations, etc.
</pre>
  </td>
 </tr>
</table>



<div style="margin-top: 1.5em;">
 <b style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Bugs: </b>


 <a href="https://issues.asterisk.org/jira/browse/ASTERISK-18404">ASTERISK-18404</a>


</div>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">

 <li>/trunk/addons/chan_ooh323.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_alsa.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_console.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_dahdi.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_gtalk.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_h323.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_jingle.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_local.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_mgcp.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_oss.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_sip.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_skinny.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/chan_unistim.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/channels/misdn_config.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/funcs/func_frame_trace.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/funcs/func_jitterbuffer.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/include/asterisk/abstract_jb.h <span style="color: grey">(369624)</span></li>

 <li>/trunk/include/asterisk/frame.h <span style="color: grey">(369624)</span></li>

 <li>/trunk/include/asterisk/framehook.h <span style="color: grey">(369624)</span></li>

 <li>/trunk/include/asterisk/rtp_engine.h <span style="color: grey">(369624)</span></li>

 <li>/trunk/tests/test_abstract_jb.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/trunk/res/res_rtp_asterisk.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/rtp_engine.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/jitterbuf.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/framehook.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/abstract_jb.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/channel.c <span style="color: grey">(369624)</span></li>

 <li>/trunk/main/file.c <span style="color: grey">(369624)</span></li>

</ul>

<p><a href="https://reviewboard.asterisk.org/r/2010/diff/" style="margin-left: 3em;">View Diff</a></p>




  </td>
 </tr>
</table>








  </div>
 </body>
</html>