You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bu...@apache.org on 2010/12/15 03:40:50 UTC

svn commit: r780711 - in /websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin: append-transform-plugin.en.html index.en.html sample-buffered-null-transformation-plugin.en.html sample-null-transformation-plugin.en.html

Author: buildbot
Date: Wed Dec 15 02:40:50 2010
New Revision: 780711

Log:
Staging update by buildbot

Modified:
    websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/append-transform-plugin.en.html
    websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/index.en.html
    websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-buffered-null-transformation-plugin.en.html
    websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-null-transformation-plugin.en.html

Modified: websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/append-transform-plugin.en.html
==============================================================================
--- websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/append-transform-plugin.en.html (original)
+++ websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/append-transform-plugin.en.html Wed Dec 15 02:40:50 2010
@@ -8,8 +8,8 @@
     
     <link rel="stylesheet" href="/styles/pygments_style.css">
     
-    <title></title>
-    
+    <title>Apache Traffic Server™ Software Developers Kit</title>
+    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file to you under the Apache License, Version 2.0 (the &quot;License&quot;); you may not use this file except in compliance with the License.  You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License. -->
   </head>
 
   <body>
@@ -17,11 +17,140 @@
 	    <span id="ts_logo">
 		  <a href="http://trafficserver.apache.org/"><img src="/images/ts75.png" /></a>
 	  </span>
-	    <h1></h1>
+	    <h1>Apache Traffic Server™ Software Developers Kit</h1>
     </div>
 
   <div id="content">
-      
+      <p><a href="sample-null-transformation-plugin">Prev</a> - The Sample Null Transform Plugin</p>
+<p>The Sample Buffered Null Transform Plugin - <a href="sample-buffered-null-transformation-plugin">Next</a></p>
+<h2 id="Append-TransformPlugin">The Append-Transform Plugin</h2>
+<p>The append-transform plugin appends text to the body of an HTTP response. It
+obtains this text from a file; the name of the file containing the append text
+is a parameter you specify in <code>plugin.config</code>, as follows:</p>
+<div class="codehilite"><pre><span class="n">append</span><span class="o">-</span><span class="n">transform</span><span class="o">.</span><span class="n">so</span> <span class="n">path</span><span class="sr">/to/</span><span class="n">file</span>
+</pre></div>
+
+
+<p>The append-transform plugin is based on <code>null-transform.c</code>. The only difference
+is that after the plugin feeds the document through the transformation, it
+adds text to the response.</p>
+<p>Below is a list of the functions in <code>append-transform.c</code>, in the order they
+appear in the source code. Below each entry is a description of what the function
+does:</p>
+<ul>
+<li>
+<p><strong><code>my_data_alloc</code></strong></p>
+<p>Allocates and initializes a <code>MyData</code> structure. The plugin defines a struct,
+<code>MyData</code>, as follows:</p>
+<div class="codehilite"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
+    <span class="n">TSVIO</span> <span class="n">output_vio</span><span class="p">;</span>
+    <span class="n">TSIOBuffer</span> <span class="n">output_buffer</span><span class="p">;</span>
+    <span class="n">TSIOBufferReader</span> <span class="n">output_reader</span><span class="p">;</span>
+    <span class="kt">int</span> <span class="n">append_needed</span><span class="p">;</span>
+<span class="p">}</span> <span class="n">MyData</span><span class="p">;</span>
+</pre></div>
+
+
+<p>The <code>MyData</code> structure is used to represent data that the transformation (vconnection)
+needs. The transformation's data pointer is set to a <code>MyData</code> pointer using
+<code>TSContDataSet</code> in the <code>handle_transform</code> routine.</p>
+</li>
+<li>
+<p><strong><code>my_data_destroy</code></strong></p>
+<p>Destroys objects of type <code>MyData</code>. To deallocate the transform's data, the
+<code>append_transform</code> routine (see below) calls <code>my_data_destroy</code> when the transformation
+is complete.</p>
+</li>
+<li>
+<p><strong><code>handle_transform</code></strong></p>
+<p>This function does the actual data transformation. The transformation is created
+in <code>transform_add</code> (see below). <code>handle_transform</code> is called by <code>append_transform</code>.</p>
+</li>
+<li>
+<p><strong><code>append_transform</code></strong></p>
+<p>This is the handler function for the transformation vconnection created in
+<code>transform_add</code>. It is the implementation of the vconnection.</p>
+<ul>
+<li>
+<p>If the transformation vconnection has been closed, then <code>append_transform</code>
+calls <code>my_data_destroy</code> to destroy the vonnection.</p>
+</li>
+<li>
+<p>If <code>append_transform</code> receives an error event, then it calls back the continuation
+to let it know it has completed the write operation.</p>
+</li>
+<li>
+<p>If it receives a <code>WRITE_COMPLETE</code> event, then it shuts down the write portion
+of its vconnection.</p>
+</li>
+<li>
+<p>If it receives a <code>WRITE_READY</code> or any other event (such as <code>TS_HTTP_RESPONSE_TRANSFORM_HOOK</code>),
+then it calls <code>handle_transform</code> to attempt to transform more data.</p>
+</li>
+</ul>
+</li>
+<li>
+<p><strong><code>transformable</code></strong></p>
+<p>The plugin transforms only documents that have a content type of <code>text/html</code>.
+This function examines the <code>Content-Type</code> MIME header field in the response
+header. If the value of the MIME field is <code>text/html</code>, then the function returns
+1; otherwise, it returns zero.</p>
+</li>
+<li>
+<p><strong><code>transform_add</code></strong></p>
+<p>Creates the transformation for the current transaction and sets up a transformation
+hook. The handler function for the transformation is <code>append_transform</code>.</p>
+</li>
+<li>
+<p><strong><code>transform_plugin</code></strong></p>
+<p>This is the handler function for the main continuation for the plugin. Traffic
+Server calls this function whenever it reads an HTTP response header. <code>transform_plugin</code>
+does the following:</p>
+<ul>
+<li>
+<p>Gets a handle to the HTTP transaction being processed</p>
+</li>
+<li>
+<p>Calls <code>transformable</code> to determine whether the response document content is
+of type <code>text/html</code></p>
+</li>
+<li>
+<p>If the content is transformable, then it calls <code>transform_add</code> to create the
+transformation.</p>
+</li>
+<li>
+<p>Calls <code>TSHttpTxnReenable</code> to continue the transaction</p>
+</li>
+</ul>
+</li>
+<li>
+<p><strong><code>load</code></strong></p>
+<p>Opens the file containing the text to be appended and loads the contents of
+the file into an <code>TSIOBuffer</code> called <code>append_buffer</code>.</p>
+</li>
+<li>
+<p><strong><code>TSPluginInit</code></strong></p>
+<p>Does the following:</p>
+<ul>
+<li>
+<p>Checks to make sure that the required configuration information (the append
+text filename) is entered in <code>plugin.config</code> correctly.</p>
+</li>
+<li>
+<p>If there is a filename, then <code>TSPluginInit</code> calls load to load the text.</p>
+</li>
+<li>
+<p>Creates a continuation for the plugin. The handler for this continuation is
+<code>transform_plugin</code>.</p>
+</li>
+<li>
+<p>Adds the plugin's continuation to <code>TS_HTTP_READ_RESPONSE_HDR_HOOK</code>. In other
+words, it sets up a callback of the plugin's continuation when Traffic Server
+reads HTTP response headers.</p>
+</li>
+</ul>
+</li>
+</ul>
   </div>
 
   <div id="footer">

Modified: websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/index.en.html
==============================================================================
--- websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/index.en.html (original)
+++ websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/index.en.html Wed Dec 15 02:40:50 2010
@@ -8,8 +8,8 @@
     
     <link rel="stylesheet" href="/styles/pygments_style.css">
     
-    <title></title>
-    
+    <title>Apache Traffic Server™ Software Developers Kit</title>
+    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file to you under the Apache License, Version 2.0 (the &quot;License&quot;); you may not use this file except in compliance with the License.  You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License. -->
   </head>
 
   <body>
@@ -17,11 +17,119 @@
 	    <span id="ts_logo">
 		  <a href="http://trafficserver.apache.org/"><img src="/images/ts75.png" /></a>
 	  </span>
-	    <h1></h1>
+	    <h1>Apache Traffic Server™ Software Developers Kit</h1>
     </div>
 
   <div id="content">
-      
+      <p><a href="../header-based-plugin-examples/basic-authorization-plugin/setting-a-transaction-hook">Prev</a> - Setting a Transaction Hook</p>
+<p>The Sample Null Transform Plugin - <a href="sample-null-transformation-plugin">Next</a></p>
+<h2 id="HTTPTransformationPlugins">HTTP Transformation Plugins</h2>
+<p>Transform plugins examine or transform HTTP message body content. For example,
+transform plugins can:</p>
+<ul>
+<li>
+<p>Append text to HTML documents</p>
+</li>
+<li>
+<p>Compress images</p>
+</li>
+<li>
+<p>Do virus checking (on client <code>POST</code> data or server response data)</p>
+</li>
+<li>
+<p>Do content-based filtering (filter out HTML documents that contain certain
+terms or expressions)</p>
+</li>
+</ul>
+<p>This chapter explains how to write transform plugins. The following examples
+are discussed in detail:</p>
+<ul>
+<li><a href="sample-null-transformation-plugin">Sample Null Transform Plugin</a></li>
+<li><a href="append-transform-plugin">Append-Transform Plugin</a></li>
+<li><a href="sample-buffered-null-transformation-plugin">Sample Buffered Null Transform Plugin</a></li>
+</ul>
+<h2 id="WritingContentTransformPlugins">Writing Content Transform Plugins</h2>
+<p>Content transformation plugins transform HTTP response content (such as images
+or HTML documents) and HTTP request content (such as client <code>POST</code> data). Because
+the data stream to be transformed is of variable length, these plugins must
+use a mechanism that passes data from buffer to buffer <em>and</em> checks to see
+if the end of the data stream is reached. This mechanism is provided by virtual
+connections (<code>VConnection</code>s) and virtual IO descriptors (<code>VIO</code>s).</p>
+<p>A <strong><code>VConnection</code></strong> is an abstraction for a data pipe that allows its users to
+perform asynchronous reads and writes without knowing the underlying implementation.
+A transformation is a specific type of <code>VConnection</code>. A <strong>transformation</strong> connects
+an input data source and an output data sink; this feature enables it to view
+and modify all the data passing through it.</p>
+<p>Transformations can be chained together, one after the other, so that multiple
+transformations can be performed on the same content. The <code>VConnection</code> type,
+<code>TSVConn</code>, is actually a subclass of <code>TSCont</code>, which means that <code>VConnection</code>s
+(and transformations) are continuations. <code>VConnection</code>s and transformations can
+thus exchange events, informing one another that data is available for reading
+or writing, or that the end of a data stream is reached.</p>
+<p>A <strong><code>VIO</code></strong> is a description of an IO operation that is in progress. Every <code>VConnection</code>
+has an associated <em>input VIO</em> and an associated <em>output VIO</em>. When <code>VConnection</code>s
+are transferring data to one another, one <code>VConnection</code>'s input <code>VIO</code> is another
+<code>VConnection</code>'s output <code>VIO</code>. A <code>VConnection</code>'s input <code>VIO</code> is also called its <strong>write
+<code>VIO</code></strong> because the input <code>VIO</code> refers to a write operation performed on the <code>VConnection</code>
+itself. Similarly, the outpt <code>VIO</code> is also called the <strong>read <code>VIO</code></strong>. For transformations,
+which are designed to pass data in one direction, you can picture the relationship
+between the transformation <code>VConnection</code> and its <code>VIO</code>s as follows:</p>
+<p id="TransformationAndVIOs"><strong>Transformation and its <code>VIO</code>s</strong></p>
+<p><img alt="A Transformation and its VIOs" src="/images/sdk/vconnection.jpg" /></p>
+<p>Because the Traffic Server API places transformations directly in the response
+or request data stream, the transformation <code>VConnection</code> is responsible only
+for reading the data from the input buffer, transforming it, and then writing
+it to the output buffer. The upstream <code>VConnection</code> writes the incoming data
+to the transformation's input buffer. In the figure above,
+<a href="#TransformationAndVIOs">A Transformation and its <code>VIO</code>s</a>, the
+input <code>VIO</code> describes the progress of the upstream <code>VConnection</code>'s write operation
+on the transformation, while the output <code>VIO</code> describes the progress of the transformation's
+write operation on the output (downstream) <code>VConnection</code>. The <strong>nbytes</strong> value
+in the <code>VIO</code> is the total number of bytes to be written. The <strong>ndone</strong> value
+is the current progress, or the number of bytes that have been written at a
+specific point in time.</p>
+<p>When writing a transformation plugin, you must understand implementation as
+well as the use of <code>VConnection</code>s. The <em>implementor's side</em> refers to how to
+implement a <code>VConnection</code> that others can use. At minimum, a transform plugin
+creates a transformation that sits in the data stream and must be able to handle
+the events that the upstream and downstream <code>VConnection</code>s send to it. The <em>user's
+side</em> refers to how to use a <code>VConnection</code> to read or write data. At the very
+least, transformations output (write) data.</p>
+<h3 id="Transformations">Transformations</h3>
+<h3 id="VIOs">VIOs</h3>
+<p>A <strong><code>VIO</code></strong> or virtual IO is a description of an in progress IO operation. The
+<code>VIO</code> data structure is used by <code>VConnection</code> users to determine how much progress
+has been made on a particular IO operation, and to reenable an IO operation
+when it stalls due to buffer space. <code>VConnection</code> implementors use <code>VIO</code>s to determine
+the buffer for an IO operation, how much work to do on the IO operation, and
+which continuation to call back when progress on the IO operation is made.</p>
+<p>The <code>TSVIO</code> data structure itself is opaque, but it might have been defined
+as follows:</p>
+<div class="codehilite"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
+     <span class="n">TSCont</span> <span class="n">continuation</span><span class="p">;</span>
+     <span class="n">TSVConn</span> <span class="n">vconnection</span><span class="p">;</span>
+     <span class="n">TSIOBufferReader</span> <span class="n">reader</span><span class="p">;</span>
+     <span class="n">TSMutex</span> <span class="n">mutex</span><span class="p">;</span>
+     <span class="kt">int</span> <span class="n">nbytes</span><span class="p">;</span>
+     <span class="kt">int</span> <span class="n">ndone</span><span class="p">;</span>
+<span class="p">}</span> <span class="o">*</span><span class="n">TSVIO</span><span class="p">;</span>
+</pre></div>
+
+
+<h3 id="IOBuffers">IO Buffers</h3>
+<p>The <strong>IO buffer</strong> data structure is the building block of the <code>VConnection</code> abstraction.
+An IO buffer is composed of a list of buffer blocks which, in turn, point to
+buffer data. Both the <em>buffer block</em> (<code>TSIOBufferBlock</code>) and <em>buffer data</em>
+(<code>TSIOBufferData</code>) data structures are reference counted so they can reside
+in multiple buffers at the same time. This makes it extremely efficient to
+copy data from one IO buffer to another using <code>TSIOBufferCopy</code>, since Traffic
+Server only needs to copy pointers and adjust reference counts appropriately
+(instead of actually copying any data).</p>
+<p>The IO buffer abstraction provides for a single writer and multiple readers.
+In order for the readers to have no knowledge of each other, they manipulate
+IO buffers through the<code>TSIOBufferReader</code> data structure. Since only a single
+writer is allowed, there is no corresponding <code>TSIOBufferWriter</code> data structure.
+The writer simply modifies the IO buffer directly.</p>
   </div>
 
   <div id="footer">

Modified: websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-buffered-null-transformation-plugin.en.html
==============================================================================
--- websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-buffered-null-transformation-plugin.en.html (original)
+++ websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-buffered-null-transformation-plugin.en.html Wed Dec 15 02:40:50 2010
@@ -8,8 +8,8 @@
     
     <link rel="stylesheet" href="/styles/pygments_style.css">
     
-    <title></title>
-    
+    <title>Apache Traffic Server™ Software Developers Kit</title>
+    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file to you under the Apache License, Version 2.0 (the &quot;License&quot;); you may not use this file except in compliance with the License.  You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License. -->
   </head>
 
   <body>
@@ -17,11 +17,181 @@
 	    <span id="ts_logo">
 		  <a href="http://trafficserver.apache.org/"><img src="/images/ts75.png" /></a>
 	  </span>
-	    <h1></h1>
+	    <h1>Apache Traffic Server™ Software Developers Kit</h1>
     </div>
 
   <div id="content">
-      
+      <p><a href="append-transform-plugin">Prev</a> - The Append-Transform Plugin</p>
+<p>New Protocol Plugins - <a href="../new-protocol-plugins">Next</a></p>
+<h2 id="SampleBufferedNullTransformPlugin">The Sample Buffered Null Transform Plugin</h2>
+<p>The buffered null transform, <code>bnull-transform.c</code>, reads the response content
+into a buffer and then writes the full buffer out to the client. Many examples
+of transformations, such as compression, require you to gather the full response
+content in order to perform the transformation.</p>
+<p>The buffered null transform uses a state variable to keep track of when it
+is (a) reading data into the buffer and (b) writing the data from the buffer
+to the downstream vconnection.</p>
+<p>The following is a step-by-step walk through the buffered null transform:</p>
+<ol>
+<li>
+<p>Gets a handle to HTTP transactions.</p>
+<div class="codehilite"><pre><span class="kt">void</span>
+<span class="nf">TSPluginInit</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
+    <span class="n">TSHttpHookAdd</span> <span class="p">(</span><span class="n">TS_HTTP_READ_RESPONSE_HDR_HOOK</span><span class="p">,</span>
+            <span class="n">TSContCreate</span> <span class="p">(</span><span class="n">transform_plugin</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">));</span> <span class="p">}</span>
+</pre></div>
+
+
+<p>With this <code>TSPluginInit</code> routine, the plugin is called back every time Traffic
+Server reads a response header.</p>
+</li>
+<li>
+<p>Checks to see if the transaction response is transformable.</p>
+<div class="codehilite"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">transform_plugin</span> <span class="p">(</span><span class="n">TSCont</span> <span class="n">contp</span><span class="p">,</span> <span class="n">TSEvent</span> <span class="n">event</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">edata</span><span class="p">)</span> <span class="p">{</span>
+    <span class="n">TSHttpTxn</span> <span class="n">txnp</span> <span class="o">=</span> <span class="p">(</span><span class="n">TSHttpTxn</span><span class="p">)</span> <span class="n">edata</span><span class="p">;</span>
+    <span class="k">switch</span> <span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="p">{</span>
+        <span class="k">case</span> <span class="n">TS_EVENT_HTTP_READ_RESPONSE_HDR</span>:
+            <span class="k">if</span> <span class="p">(</span><span class="n">transformable</span> <span class="p">(</span><span class="n">txnp</span><span class="p">))</span> <span class="p">{</span>
+                <span class="n">transform_add</span> <span class="p">(</span><span class="n">txnp</span><span class="p">);</span>
+            <span class="p">}</span>
+</pre></div>
+
+
+<p>The default behavior for transformations is to cache the transformed content
+(if desired, you also can tell Traffic Server to cache untransformed content).
+Therefore, only responses received directly from an origin server need to be
+transformed. Objects served from the cache are already transformed. To determine
+whether the response is from the origin server, the routine transformable checks
+the response header for the "200 OK" server response.</p>
+<div class="codehilite"><pre><span class="p">{</span>
+    <span class="n">TSMBuffer</span> <span class="n">bufp</span><span class="p">;</span>
+    <span class="n">TSMLoc</span> <span class="n">hdr_loc</span><span class="p">;</span>
+    <span class="n">TSHttpStatus</span> <span class="n">resp_status</span><span class="p">;</span>
+
+    <span class="n">TSHttpTxnServerRespGet</span> <span class="p">(</span><span class="n">txnp</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bufp</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">hdr_loc</span><span class="p">);</span>
+
+    <span class="k">if</span><span class="p">(</span><span class="n">TS_HTTP_STATUS_OK</span><span class="o">==</span>
+            <span class="p">(</span><span class="n">resp_status</span><span class="o">=</span><span class="n">TSHttpHdrStatusGet</span><span class="p">(</span><span class="n">bufp</span><span class="p">,</span><span class="n">hdr_loc</span><span class="p">)))</span>
+    <span class="p">{</span>
+        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
+    <span class="p">}</span>
+    <span class="k">else</span> <span class="p">{</span>
+        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>If the response is transformable, then the plugin creates a transformation
+vconnection that gets called back when the response data is ready to be transformed
+(as it is streaming from the origin server).</p>
+<div class="codehilite"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">transform_add</span> <span class="p">(</span><span class="n">TSHttpTxn</span> <span class="n">txnp</span><span class="p">)</span>
+<span class="p">{</span>
+    <span class="n">TSVConn</span> <span class="n">connp</span><span class="p">;</span>
+    <span class="n">connp</span> <span class="o">=</span> <span class="n">TSTransformCreate</span> <span class="p">(</span><span class="n">bnull_transform</span><span class="p">,</span> <span class="n">txnp</span><span class="p">);</span>
+    <span class="n">TSHttpTxnHookAdd</span> <span class="p">(</span><span class="n">txnp</span><span class="p">,</span> <span class="n">TS_HTTP_RESPONSE_TRANSFORM_HOOK</span><span class="p">,</span> <span class="n">connp</span><span class="p">);</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The previous code fragment shows that the handler function for the transformation
+vconnection is <code>bnull_transform</code>.</p>
+</li>
+<li>
+<p>The <code>bnull_transform</code> function has to handle <code>ERROR</code>, <code>WRITE_COMPLETE</code>, <code>WRITE_READY</code>,
+and <code>IMMEDIATE</code> events. If the transform is just beginning, the event received
+is probably <code>IMMEDIATE</code>. The <code>bnull_transform</code> function calls <code>handle_transform</code>
+to handle <code>WRITE_READY</code> and <code>IMMEDIATE</code>.</p>
+</li>
+<li>
+<p>The <code>handle_transform</code> function examines the data parameter for the continuation
+passed to it (the continuation passed to <code>handle_transform</code> is the transformation
+vconnection). The data structure keeps track of two states: copying the data
+into the buffer (<code>STATE_BUFFER_DATA</code>) and writing the contents of the buffer
+to the output vconnection (<code>STATE_OUTPUT_DATA</code>).</p>
+</li>
+<li>
+<p>Get a handle to the input VIO (see the <code>handle_buffering</code> function).
+<code>input_vio = TSVConnWriteVIOGet (contp);</code>
+This is so that the transformation can get information about the upstream vconnection's
+write operation to the input buffer.</p>
+</li>
+<li>
+<p>Copy data from the input buffer to the output buffer. See the <code>handle_buffering</code>
+function for the following code fragment:</p>
+<div class="codehilite"><pre><span class="n">TSIOBufferCopy</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_buffer</span><span class="p">,</span>
+        <span class="n">TSVIOReaderGet</span> <span class="p">(</span><span class="n">write_vio</span><span class="p">),</span> <span class="n">towrite</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>Tell the input buffer that the transformation has read the data. See the <code>handle_buffering</code>
+function for the following code fragment:
+<code>TSIOBufferReaderConsume (TSVIOReaderGet (write_vio), towrite);</code></p>
+</li>
+<li>
+<p>Modify the input VIO to tell it how much data has been read (increase the value
+of <code>ndone</code>). See the <code>handle_buffering</code> function for the following code fragment:
+<code>TSVIONDoneSet (write_vio, TSVIONDoneGet (write_vio) + towrite); }</code></p>
+</li>
+<li>
+<p>If there is more data left to read ( if ndone &lt; nbytes), then the
+<code>handle_buffering</code> function wakes up the upstream vconnection by sending it <code>WRITE_READY</code>:</p>
+<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">TSVIONTodoGet</span> <span class="p">(</span><span class="n">write_vio</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">if</span> <span class="p">(</span><span class="n">towrite</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">TSContCall</span> <span class="p">(</span><span class="n">TSVIOContGet</span> <span class="p">(</span><span class="n">write_vio</span><span class="p">),</span>
+                <span class="n">TS_EVENT_VCONN_WRITE_READY</span><span class="p">,</span> <span class="n">write_vio</span><span class="p">);</span>
+    <span class="p">}</span>
+<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</pre></div>
+
+
+<p>The process of passing data through the transformation is illustrated in the
+following diagram. The transformation sends <code>WRITE_READY</code> events when it needs
+more data; when data is available, the upstream vconnection reenables the transformation
+with an <code>IMMEDIATE</code> event.</p>
+<p>The following diagram illustrates the read from an input vconnection:</p>
+<p id="ReadingDataIntoBuffer"><strong>Reading Data Into the Buffer (the <code>STATE_BUFFER_DATA</code> State)</strong></p>
+<p><img alt="Reading Data Into the Buffer the STATE_BUFFER_DATA State" src="/images/sdk/vconn_buffer.jpg" /></p>
+</li>
+<li>
+<p>When the data is read into the output buffer, the <code>handle_buffering</code> function
+sets the state of the transformation's data structure to <code>STATE_OUTPUT_DATA</code>
+and calls the upstream vconnection back with the <code>WRITE_COMPLETE</code> event.</p>
+<div class="codehilite"><pre><span class="n">data</span><span class="o">-&gt;</span><span class="n">state</span> <span class="o">=</span> <span class="n">STATE_OUTPUT_DATA</span><span class="p">;</span>
+<span class="n">TSContCall</span> <span class="p">(</span><span class="n">TSVIOContGet</span> <span class="p">(</span><span class="n">write_vio</span><span class="p">),</span>
+         <span class="n">TS_EVENT_VCONN_WRITE_COMPLETE</span><span class="p">,</span> <span class="n">write_vio</span><span class="p">);</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>The upstream vconnection will probably shut down the write operation when it
+receives the <code>WRITE_COMPLETE</code> event. The handler function of the transformation,
+<code>bnull_transform</code>, receives an <code>IMMEDIATE</code> event and calls the <code>handle_transform</code>
+function. This time, the state is <code>STATE_OUTPUT_DATA</code>, so <code>handle_transform</code>
+calls <code>handle_output</code>.</p>
+</li>
+<li>
+<p>The <code>handle_output</code> function gets a handle to the output vconnection:
+<code>output_conn = TSTransformOutputVConnGet (contp);</code></p>
+</li>
+<li>
+<p>The <code>handle_output</code> function writes the buffer to the output vconnection:</p>
+<div class="codehilite"><pre><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span> <span class="o">=</span>
+<span class="n">TSVConnWrite</span> <span class="p">(</span><span class="n">output_conn</span><span class="p">,</span> <span class="n">contp</span><span class="p">,</span> <span class="n">data</span><span class="o">-&gt;</span><span class="n">output_reader</span><span class="p">,</span>
+<span class="n">TSIOBufferReaderAvail</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_reader</span><span class="p">)</span> <span class="p">);</span>
+</pre></div>
+
+
+<p>The following diagram illustrates the write to the output vconnection:</p>
+<p><strong>Writing the Buffered Data to the Output Vconnection</strong> {#WritingBufferedtDataIntoVConnection)</p>
+<p><img alt="Writing the Buffered Data to the Output Vconnection" src="/images/sdk/vconn_buf_output.jpg" /></p>
+</li>
+</ol>
   </div>
 
   <div id="footer">

Modified: websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-null-transformation-plugin.en.html
==============================================================================
--- websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-null-transformation-plugin.en.html (original)
+++ websites/staging/trafficserver/trunk/content/docs/trunk/sdk/http-transformation-plugin/sample-null-transformation-plugin.en.html Wed Dec 15 02:40:50 2010
@@ -8,8 +8,8 @@
     
     <link rel="stylesheet" href="/styles/pygments_style.css">
     
-    <title></title>
-    
+    <title>Apache Traffic Server™ Software Developers Kit</title>
+    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file to you under the Apache License, Version 2.0 (the &quot;License&quot;); you may not use this file except in compliance with the License.  You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License. -->
   </head>
 
   <body>
@@ -17,11 +17,197 @@
 	    <span id="ts_logo">
 		  <a href="http://trafficserver.apache.org/"><img src="/images/ts75.png" /></a>
 	  </span>
-	    <h1></h1>
+	    <h1>Apache Traffic Server™ Software Developers Kit</h1>
     </div>
 
   <div id="content">
-      
+      <p><a href="../http-transformation-plugin">Prev</a> - HTTP Transformation Plugins</p>
+<p>The Append-Transform Plugin - <a href="append-transform-plugin">Next</a></p>
+<h2 id="SampleNullTransformPlugin">The Sample Null Transform Plugin</h2>
+<p>This section provides a step-by-step description of what the null transform
+plugin does, along with sections of code that apply. For context, you can find
+each code snippet in the complete source code. Some of the error checking details
+are left out - to give the description a step-by-step flow, only the highlights
+of the transform are included.</p>
+<p>Below is an overview of the null transform plugin:</p>
+<ol>
+<li>
+<p>Gets a handle to HTTP transactions.</p>
+<div class="codehilite"><pre><span class="kt">void</span>
+<span class="nf">TSPluginInit</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
+    <span class="n">TSHttpHookAdd</span> <span class="p">(</span><span class="n">TS_HTTP_READ_RESPONSE_HDR_HOOK</span><span class="p">,</span>
+            <span class="n">TSContCreate</span> <span class="p">(</span><span class="n">transform_plugin</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">));</span>
+</pre></div>
+
+
+<p>With this <code>TSPluginInit</code> routine, the plugin is called back every time Traffic
+Server reads a response header.</p>
+</li>
+<li>
+<p>Checks to see if the transaction response is transformable.</p>
+<div class="codehilite"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">transform_plugin</span> <span class="p">(</span><span class="n">TSCont</span> <span class="n">contp</span><span class="p">,</span> <span class="n">TSEvent</span> <span class="n">event</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">edata</span><span class="p">)</span> <span class="p">{</span>
+    <span class="n">TSHttpTxn</span> <span class="n">txnp</span> <span class="o">=</span> <span class="p">(</span><span class="n">TSHttpTxn</span><span class="p">)</span> <span class="n">edata</span><span class="p">;</span>
+    <span class="k">switch</span> <span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="p">{</span>
+        <span class="k">case</span> <span class="n">TS_EVENT_HTTP_READ_RESPONSE_HDR</span>:
+            <span class="k">if</span> <span class="p">(</span><span class="n">transformable</span> <span class="p">(</span><span class="n">txnp</span><span class="p">))</span> <span class="p">{</span>
+                <span class="n">transform_add</span> <span class="p">(</span><span class="n">txnp</span><span class="p">);</span>
+            <span class="p">}</span>
+</pre></div>
+
+
+<p>The default behavior for transformations is to cache the transformed content
+(you can also tell Traffic Server to cache untransformed content, if you want).
+Therefore, only responses received directly from an origin server need to be
+transformed. Objects served from cache are already transformed. To determine
+whether the response is from the origin server, the routine <code>transformable</code>
+checks the response header for the "200 OK" server response.</p>
+<div class="codehilite"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">transformable</span> <span class="p">(</span><span class="n">TSHttpTxn</span> <span class="n">txnp</span><span class="p">)</span>
+<span class="p">{</span>
+    <span class="n">TSMBuffer</span> <span class="n">bufp</span><span class="p">;</span>
+    <span class="n">TSMLoc</span> <span class="n">hdr_loc</span><span class="p">;</span>
+    <span class="n">TSHttpStatus</span> <span class="n">resp_status</span><span class="p">;</span>
+    <span class="n">TSHttpTxnServerRespGet</span> <span class="p">(</span><span class="n">txnp</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bufp</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">hdr_loc</span><span class="p">);</span>
+
+    <span class="k">if</span> <span class="p">(</span><span class="n">TS_HTTP_STATUS_OK</span> <span class="o">==</span> <span class="p">(</span><span class="n">resp_status</span> <span class="o">=</span>
+                <span class="n">TSHttpHdrStatusGet</span> <span class="p">(</span><span class="n">bufp</span><span class="p">,</span> <span class="n">hdr_loc</span><span class="p">))</span> <span class="p">)</span> <span class="p">{</span>
+        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
+    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>If the response is transformable, then the plugin creates a transformation
+vconnection that gets called back when the response data is ready to be transformed
+(as it is streaming from the origin server).</p>
+<div class="codehilite"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">transform_add</span> <span class="p">(</span><span class="n">TSHttpTxn</span> <span class="n">txnp</span><span class="p">)</span>
+<span class="p">{</span>
+    <span class="n">TSVConn</span> <span class="n">connp</span><span class="p">;</span>
+    <span class="n">connp</span> <span class="o">=</span> <span class="n">TSTransformCreate</span> <span class="p">(</span><span class="n">null_transform</span><span class="p">,</span> <span class="n">txnp</span><span class="p">);</span>
+    <span class="n">TSHttpTxnHookAdd</span> <span class="p">(</span><span class="n">txnp</span><span class="p">,</span> <span class="n">TS_HTTP_RESPONSE_TRANSFORM_HOOK</span><span class="p">,</span> <span class="n">connp</span><span class="p">);</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The previous code fragment shows that the handler function for the transformation
+vconnection is <code>null_transform</code>.</p>
+</li>
+<li>
+<p>Get a handle to the output vconnection (that receives data from the tranformation).</p>
+<div class="codehilite"><pre><span class="n">output_conn</span> <span class="o">=</span> <span class="n">TSTransformOutputVConnGet</span> <span class="p">(</span><span class="n">con</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>Get a handle to the input VIO. (See the <code>handle_transform</code> function.)</p>
+<div class="codehilite"><pre><span class="n">input_vio</span> <span class="o">=</span> <span class="n">TSVConnWriteVIOGet</span> <span class="p">(</span><span class="n">contp</span><span class="p">);</span>
+</pre></div>
+
+
+<p>This is so that the transformation can get information about the upstream vconnection's
+write operation to the input buffer.</p>
+</li>
+<li>
+<p>Initiate a write to the output vconnection of the specified number of bytes.
+When the write is initiated, the transformation expects to receive <code>WRITE_READY</code>,
+<code>WRITE_COMPLETE</code>, or <code>ERROR</code> events from the output vconnection.
+See the <code>handle_transform</code> function for the following code fragment:</p>
+<div class="codehilite"><pre><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span> <span class="o">=</span> <span class="n">TSVConnWrite</span> <span class="p">(</span><span class="n">output_conn</span><span class="p">,</span> <span class="n">contp</span><span class="p">,</span>
+    <span class="n">data</span><span class="o">-&gt;</span><span class="n">output_reader</span><span class="p">,</span> <span class="n">TSVIONBytesGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">));</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>Copy data from the input buffer to the output buffer. See the <code>handle_transform</code>
+function for the following code fragment:</p>
+<div class="codehilite"><pre><span class="n">TSIOBufferCopy</span> <span class="p">(</span><span class="n">TSVIOBufferGet</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span><span class="p">),</span>
+        <span class="n">TSVIOReaderGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">),</span> <span class="n">towrite</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>Tell the input buffer that the transformation has read the data. See the <code>handle_transform</code>
+function for the following code fragment:</p>
+<div class="codehilite"><pre><span class="n">TSIOBufferReaderConsume</span> <span class="p">(</span><span class="n">TSVIOReaderGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">),</span> <span class="n">towrite</span><span class="p">);</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>Modify the input VIO to tell it how much data has been read (increase the value
+of <code>ndone</code>). See the <code>handle_transform</code> function for the following code fragment:</p>
+<div class="codehilite"><pre><span class="n">TSVIONDoneSet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">,</span> <span class="n">TSVIONDoneGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">)</span> <span class="o">+</span> <span class="n">towrite</span><span class="p">);</span>
+</pre></div>
+
+
+</li>
+<li>
+<p>If there is more data left to read ( if ndone &lt; nbytes), then the
+<code>handle_transform</code> function wakes up the downstream vconnection with a reenable
+and wakes up the upstream vconnection by sending it <code>WRITE_READY</code>:</p>
+<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">TSVIONTodoGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">if</span> <span class="p">(</span><span class="n">towrite</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">TSVIOReenable</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span><span class="p">);</span>
+
+        <span class="n">TSContCall</span> <span class="p">(</span><span class="n">TSVIOContGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">),</span>
+                <span class="n">TS_EVENT_VCONN_WRITE_READY</span><span class="p">,</span> <span class="n">input_vio</span><span class="p">);</span>
+    <span class="p">}</span>
+    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</pre></div>
+
+
+<p>The process of passing data through the transformation is illustrated in the
+following diagram. The downstream vconnections send <code>WRITE_READY</code> events when
+they need more data; when data is available, the upstream vconnections reenable
+the downstream vconnections. In this instance, the <code>TSVIOReenable</code> function
+sends <code>TS_EVENT_IMMEDIATE</code>.</p>
+<p id="PassingDataThroughaTransformation"><strong>Passing Data Through a Transformation</strong></p>
+</li>
+</ol>
+<p><img alt="Passing Data Through a Transformation" src="/images/sdk/vconnection1.jpg" /></p>
+<ol>
+<li>
+<p>If the <code>handle_transform</code> function finds there is no more data to read, then
+it sets <code>nbytes</code> to <code>ndone</code> on the output (downstream) VIO and wakes up the
+output vconnection with a reenable. It then triggers the end of the write operation
+from the upstream vconnection by sending the upstream vconnection a <code>WRITE_COMPLETE</code>
+event.</p>
+<div class="codehilite"><pre><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+
+    <span class="n">TSVIONBytesSet</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span><span class="p">,</span> <span class="n">TSVIONDoneGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">));</span>
+    <span class="n">TSVIOReenable</span> <span class="p">(</span><span class="n">data</span><span class="o">-&gt;</span><span class="n">output_vio</span><span class="p">);</span>
+    <span class="n">TSContCall</span> <span class="p">(</span><span class="n">TSVIOContGet</span> <span class="p">(</span><span class="n">input_vio</span><span class="p">),</span>
+            <span class="n">TS_EVENT_VCONN_WRITE_COMPLETE</span><span class="p">,</span> <span class="n">input_vio</span><span class="p">);</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>When the upstream vconnection receives the <code>WRITE_COMPLETE</code> event, it will
+probably shut down the write operation.</p>
+</li>
+<li>
+<p>Similarly, when the downstream vconnection has consumed all of the data, it
+sends the transformation a <code>WRITE_COMPLETE</code> event. The transformation handles
+this event with a shut down (the transformation shuts down the write operation
+to the downstream vconnection). See the <code>null_plugin</code> function for the following
+code fragment:</p>
+<div class="codehilite"><pre><span class="k">case</span> <span class="n">TS_EVENT_VCONN_WRITE_COMPLETE</span>:
+    <span class="n">TSVConnShutdown</span> <span class="p">(</span><span class="n">TSTransformOutputVConnGet</span> <span class="p">(</span><span class="n">contp</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
+    <span class="k">break</span><span class="p">;</span>
+</pre></div>
+
+
+<p>The following diagram illustrates the flow of events:</p>
+<p id="EndingTransformation"><strong>Ending the Transformation</strong></p>
+<p><img alt="Ending the Transformation" src="/images/sdk/vconnection2.jpg" /></p>
+</li>
+</ol>
   </div>
 
   <div id="footer">