You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2014/03/29 00:31:23 UTC

[01/13] git commit: TS-2675: minor metalink refactorings

Repository: trafficserver
Updated Branches:
  refs/heads/master 88a0d3bcd -> ad6806ea7


TS-2675: minor metalink refactorings

  - strcasecmp(3) says #include <strings.h>
  - C style casts for consistency
  - Give some variables better names


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/3ba82881
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/3ba82881
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/3ba82881

Branch: refs/heads/master
Commit: 3ba8288154599a7717b6d54ab08df79e5396708e
Parents: 88a0d3b
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 11:15:35 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:53 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 32 ++++++++++++--------------
 1 file changed, 15 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3ba82881/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index ea253dd..be48601 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -30,13 +30,11 @@
 */
 
 
-#include <stdio.h>
-#include <string.h>
+#include <strings.h>
 
 #include <openssl/sha.h>
 
 #include "ts/ts.h"
-#include "ink_defs.h"
 
 /* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transform.
  * Compute the SHA-256 digest of the content, write it to the cache and store
@@ -55,7 +53,7 @@
 
 typedef struct {
   TSVConn connp;
-  TSIOBuffer bufp;
+  TSIOBuffer cache_bufp;
 
 } WriteData;
 
@@ -98,7 +96,7 @@ typedef struct {
   /* Digest header field value index */
   int idx;
 
-  TSIOBuffer read_bufp;
+  TSIOBuffer cache_bufp;
 
 } SendData;
 
@@ -117,7 +115,7 @@ write_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
    * TSVConnClose() */
   TSVConnClose(data->connp);
 
-  TSIOBufferDestroy(data->bufp);
+  TSIOBufferDestroy(data->cache_bufp);
   TSfree(data);
 
   return 0;
@@ -195,10 +193,10 @@ cache_open_write(TSCont contp, void *edata)
   contp = TSContCreate(write_handler, NULL);
   TSContDataSet(contp, write_data);
 
-  write_data->bufp = TSIOBufferCreate();
-  TSIOBufferReader readerp = TSIOBufferReaderAlloc(write_data->bufp);
+  write_data->cache_bufp = TSIOBufferCreate();
+  TSIOBufferReader readerp = TSIOBufferReaderAlloc(write_data->cache_bufp);
 
-  int nbytes = TSIOBufferWrite(write_data->bufp, value, length);
+  int nbytes = TSIOBufferWrite(write_data->cache_bufp, value, length);
 
   TSVConnWrite(write_data->connp, contp, readerp, nbytes);
 
@@ -418,10 +416,10 @@ cache_open_read(TSCont contp, void *edata)
   SendData *data = (SendData *) TSContDataGet(contp);
   TSVConn connp = (TSVConn) edata;
 
-  data->read_bufp = TSIOBufferCreate();
+  data->cache_bufp = TSIOBufferCreate();
 
   /* Reuse the TSCacheRead() continuation */
-  TSVConnRead(connp, contp, data->read_bufp, INT64_MAX);
+  TSVConnRead(connp, contp, data->cache_bufp, INT64_MAX);
 
   return 0;
 }
@@ -497,12 +495,12 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
   TSContDestroy(contp);
 
-  TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->read_bufp);
+  TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp);
   TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
 
   value = TSIOBufferBlockReadStart(blockp, readerp, &length);
   if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + length) != TS_PARSE_DONE) {
-    TSIOBufferDestroy(data->read_bufp);
+    TSIOBufferDestroy(data->cache_bufp);
 
     TSCacheKeyDestroy(data->key);
 
@@ -516,7 +514,7 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     return 0;
   }
 
-  TSIOBufferDestroy(data->read_bufp);
+  TSIOBufferDestroy(data->cache_bufp);
 
   if (TSCacheKeyDigestFromUrlSet(data->key, data->url_loc) != TS_SUCCESS) {
     TSCacheKeyDestroy(data->key);
@@ -764,9 +762,9 @@ TSPluginInit(int /* argc ATS_UNUSED */, const char */* argv ATS_UNUSED */[])
 {
   TSPluginRegistrationInfo info;
 
-  info.plugin_name = const_cast<char*>("metalink");
-  info.vendor_name = const_cast<char*>("Apache Software Foundation");
-  info.support_email = const_cast<char*>("dev@trafficserver.apache.org");
+  info.plugin_name = (char *) "metalink";
+  info.vendor_name = (char *) "Apache Software Foundation";
+  info.support_email = (char *) "dev@trafficserver.apache.org";
 
   if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
     TSError("Plugin registration failed");


[07/13] git commit: TS-2675: metalink: Handle the end of the input independently from the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream

Posted by jp...@apache.org.
TS-2675: metalink: Handle the end of the input independently from the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/52622d28
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/52622d28
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/52622d28

Branch: refs/heads/master
Commit: 52622d2809464ace2ab36e888a19f51a9edb508e
Parents: d25b00c
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 12:56:53 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 170 +++++++++++++------------
 1 file changed, 88 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/52622d28/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 77f62dc..f792d8a 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -225,20 +225,41 @@ write_handler(TSCont contp, TSEvent event, void *edata)
 }
 
 /* Copy content from the input buffer to the output buffer without modification
- * while at the same time feeding it to the message digest */
+ * and feed it through the message digest at the same time.
+ *
+ *   1. Check if any more input is possible before doing anything else to avoid
+ *      failed asserts.
+ *   2. Then deal with any input that's available now.
+ *   3. Check if the input is complete after dealing with any available input
+ *      in case it was the last of it.  If it is complete, do any bookkeeping
+ *      that downstream needs and finish computing the digest.  Otherwise
+ *      either wait for more input or abort if no more input is possible.
+ *
+ * Events are sent from downstream and don't communicate the state of the input
+ * (TS_EVENT_VCONN_WRITE_READY, TS_EVENT_VCONN_WRITE_COMPLETE, and
+ * TS_EVENT_IMMEDIATE?) Clean up the output buffer on
+ * TS_EVENT_VCONN_WRITE_COMPLETE and not before.
+ *
+ * Gather the state of the input from TSVIONTodoGet() and TSVIOReaderGet().
+ * TSVIOReaderGet() is NULL when no more input is possible and the input is
+ * complete only when TSVIONTodoGet() is zero.  Handle the end of the input
+ * independently from the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream. */
 
 static int
 vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 {
   const char *value;
   int64_t length;
-  TransformData *data = (TransformData *) TSContDataGet(contp);
+
+  char digest[32];
+
+  TransformData *transform_data = (TransformData *) TSContDataGet(contp);
 
   TSVIO input_viop = TSVConnWriteVIOGet(contp);
 
   /* Initialize data here because can't call TSVConnWrite() before
    * TS_HTTP_RESPONSE_TRANSFORM_HOOK */
-  if (!data->output_bufp) {
+  if (!transform_data->output_bufp) {
 
     /* Avoid failed assert "sdk_sanity_check_iocore_structure(connp) ==
      * TS_SUCCESS" in TSVConnWrite() if the response is 304 Not Modified */
@@ -246,127 +267,112 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     if (!output_connp) {
       TSContDestroy(contp);
 
-      TSfree(data);
+      TSfree(transform_data);
 
       return 0;
     }
 
-    data->output_bufp = TSIOBufferCreate();
-    TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->output_bufp);
+    transform_data->output_bufp = TSIOBufferCreate();
+    TSIOBufferReader readerp = TSIOBufferReaderAlloc(transform_data->output_bufp);
 
     /* Determines the "Content-Length: ..." header
      * (or "Transfer-Encoding: chunked") */
 
     /* Avoid failed assert "nbytes >= 0" if "Transfer-Encoding: chunked" */
     int nbytes = TSVIONBytesGet(input_viop);
-    data->output_viop = TSVConnWrite(output_connp, contp, readerp, nbytes < 0 ? INT64_MAX : nbytes);
+    transform_data->output_viop = TSVConnWrite(output_connp, contp, readerp, nbytes < 0 ? INT64_MAX : nbytes);
 
-    SHA256_Init(&data->c);
-  }
-
-  /* If the response has a "Content-Length: ..." header then ntodo will never
-   * be zero because there will instead be a TS_EVENT_VCONN_WRITE_COMPLETE
-   * event from downstream after nbytes of content.
-   *
-   * Otherwise (if the response is "Transfer-Encoding: chunked") ntodo will be
-   * zero when the upstream nbytes is known at the end of the content, because
-   * there won't be a TS_EVENT_VCONN_WRITE_COMPLETE event while the downstream
-   * nbytes is INT64_MAX.
-   *
-   * In that case to get it to send a TS_EVENT_VCONN_WRITE_COMPLETE event,
-   * update the downstream nbytes and reenable it.  Zero the downstream nbytes
-   * is a shortcut. */
-  int ntodo = TSVIONTodoGet(input_viop);
-  if (!ntodo) {
-    TSVIONBytesSet(data->output_viop, 0);
-
-    TSVIOReenable(data->output_viop);
-
-    return 0;
+    SHA256_Init(&transform_data->c);
   }
 
   /* Avoid failed assert "sdk_sanity_check_iocore_structure(readerp) ==
    * TS_SUCCESS" in TSIOBufferReaderAvail() if the client or server disconnects
-   * or the content length is zero.
-   *
-   * Don't update the downstream nbytes and reenable it because if not at the
-   * end yet and can't read any more content then can't compute the digest.
-   *
-   * (There hasn't been a TS_EVENT_VCONN_WRITE_COMPLETE event from downstream
-   * yet so if the response has a "Content-Length: ..." header, it is greater
-   * than the content so far.  ntodo is still greater than zero so if the
-   * response is "Transfer-Encoding: chunked", not at the end yet.) */
+   * or the content length is zero */
   TSIOBufferReader readerp = TSVIOReaderGet(input_viop);
-  if (!readerp) {
-    TSContDestroy(contp);
+  if (readerp) {
 
-    TSIOBufferDestroy(data->output_bufp);
-    TSfree(data);
+    int avail = TSIOBufferReaderAvail(readerp);
+    if (avail) {
+      TSIOBufferCopy(transform_data->output_bufp, readerp, avail, 0);
 
-    return 0;
-  }
-
-  int avail = TSIOBufferReaderAvail(readerp);
+      /* Feed content to the message digest */
+      TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
+      while (blockp) {
 
-  if (avail) {
-    TSIOBufferCopy(data->output_bufp, readerp, avail, 0);
+        value = TSIOBufferBlockReadStart(blockp, readerp, &length);
+        SHA256_Update(&transform_data->c, value, length);
 
-    /* Feed content to the message digest */
-    TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
-    while (blockp) {
+        blockp = TSIOBufferBlockNext(blockp);
+      }
 
-      value = TSIOBufferBlockReadStart(blockp, readerp, &length);
-      SHA256_Update(&data->c, value, length);
+      TSIOBufferReaderConsume(readerp, avail);
 
-      blockp = TSIOBufferBlockNext(blockp);
+      /* Call TSVIONDoneSet() for TSVIONTodoGet() condition */
+      int ndone = TSVIONDoneGet(input_viop);
+      TSVIONDoneSet(input_viop, ndone + avail);
     }
+  }
 
-    TSIOBufferReaderConsume(readerp, avail);
+  int ntodo = TSVIONTodoGet(input_viop);
+  if (ntodo) {
 
-    /* Call TSVIONDoneSet() for TSVIONTodoGet() condition */
-    int ndone = TSVIONDoneGet(input_viop);
-    TSVIONDoneSet(input_viop, ndone + avail);
+    /* Don't update the downstream nbytes because the input isn't complete */
+    if (!readerp) {
+      TSContDestroy(contp);
+
+      TSIOBufferDestroy(transform_data->output_bufp);
+      TSfree(transform_data);
 
-    TSVIOReenable(data->output_viop);
+      return 0;
+    }
+
+    TSVIOReenable(transform_data->output_viop);
 
     TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop);
-  }
 
-  return 0;
-}
+  } else {
 
-/* Write the digest to the cache */
+    int ndone = TSVIONDoneGet(input_viop);
+    TSVIONBytesSet(transform_data->output_viop, ndone);
 
-static int
-transform_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
-{
-  char digest[32];
+    TSVIOReenable(transform_data->output_viop);
 
-  TransformData *transform_data = (TransformData *) TSContDataGet(contp);
-  TSContDestroy(contp);
+    /* Write the digest to the cache */
 
-  TSIOBufferDestroy(transform_data->output_bufp);
+    SHA256_Final((unsigned char *) digest, &transform_data->c);
 
-  SHA256_Final((unsigned char *) digest, &transform_data->c);
+    WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
+    write_data->txnp = transform_data->txnp;
 
-  WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
-  write_data->txnp = transform_data->txnp;
+    write_data->key = TSCacheKeyCreate();
+    if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) {
 
-  TSfree(transform_data);
+      TSCacheKeyDestroy(write_data->key);
+      TSfree(write_data);
 
-  write_data->key = TSCacheKeyCreate();
-  if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) {
+      return 0;
+    }
 
-    TSCacheKeyDestroy(write_data->key);
-    TSfree(write_data);
+    /* Can't reuse the TSTransformCreate() continuation because don't know
+     * whether to destroy it in cache_open_write()/cache_open_write_failed() or
+     * transform_vconn_write_complete() */
+    contp = TSContCreate(write_handler, NULL);
+    TSContDataSet(contp, write_data);
 
-    return 0;
+    TSCacheWrite(contp, write_data->key);
   }
 
-  contp = TSContCreate(write_handler, NULL);
-  TSContDataSet(contp, write_data);
+  return 0;
+}
 
-  TSCacheWrite(contp, write_data->key);
+static int
+transform_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
+{
+  TransformData *data = (TransformData *) TSContDataGet(contp);
+  TSContDestroy(contp);
+
+  TSIOBufferDestroy(data->output_bufp);
+  TSfree(data);
 
   return 0;
 }


[09/13] git commit: TS-2675: metalink: Don't finish computing the digest more than once and test that the proxy rewrites the Location header if the file is already cached

Posted by jp...@apache.org.
TS-2675: metalink: Don't finish computing the digest more than once and test that the proxy rewrites the Location header if the file is already cached


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/f9d74b9f
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/f9d74b9f
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/f9d74b9f

Branch: refs/heads/master
Commit: f9d74b9feefa2f7a4c8d59b6633efe9de8415d50
Parents: ea2f6f3
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Mon Mar 17 09:19:31 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc   |  13 ++-
 plugins/experimental/metalink/test/location | 124 +++++++++++++++++++++++
 2 files changed, 136 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/f9d74b9f/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 3ad589d..ae8771c 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -367,7 +367,15 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
 
     TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop);
 
-  } else {
+  /* Don't finish computing the digest (and tell downstream and thank upstream)
+   * more than once!  There might be multiple TS_EVENT_IMMEDIATE events between
+   * the end of the input and the TS_EVENT_VCONN_WRITE_COMPLETE event from
+   * downstream, e.g. INKVConnInternal::reenable() is called by
+   * HttpTunnel::producer_handler() when more input is available and
+   * TransformVConnection::do_io_shutdown() is called by
+   * HttpSM::tunnel_handler_transform_write() when we send our own
+   * TS_EVENT_VCONN_WRITE_COMPLETE event upstream. */
+  } else if (transform_data->txnp) {
 
     int ndone = TSVIONDoneGet(input_viop);
     TSVIONBytesSet(transform_data->output_viop, ndone);
@@ -388,6 +396,9 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
     WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
     write_data->txnp = transform_data->txnp;
 
+    /* Don't finish computing the digest more than once! */
+    transform_data->txnp = NULL;
+
     write_data->key = TSCacheKeyCreate();
     if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) {
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/f9d74b9f/plugins/experimental/metalink/test/location
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/location b/plugins/experimental/metalink/test/location
new file mode 100755
index 0000000..77b601e
--- /dev/null
+++ b/plugins/experimental/metalink/test/location
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+
+# 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 "License"); 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 "AS IS" 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.
+
+print '''1..2 location
+# The proxy rewrites the Location header if the file is already cached'''
+
+from twisted.internet import error, protocol, reactor, tcp
+from twisted.web import http
+
+def callback():
+  print 'not ok 1 - Why didn\'t the test finish yet?'
+
+  reactor.stop()
+
+reactor.callLater(1, callback)
+
+class factory(http.HTTPFactory):
+  class protocol(http.HTTPChannel):
+    class requestFactory(http.Request):
+      def requestReceived(ctx, method, target, version):
+
+        ctx.client = None
+        ctx.clientproto = version
+
+        if target == '/location':
+
+          ctx.write('location')
+          ctx.finish()
+
+        else:
+
+          ctx.setHeader('Digest', 'SHA-256=5urqGOiF4QeIKbVt80iWvlq1FDno8LoAyxYkssVywQ4=')
+          ctx.setHeader('Location', 'http://example.com')
+          ctx.finish()
+
+origin = tcp.Port(0, factory())
+origin.startListening()
+
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
+
+class factory(protocol.ClientFactory):
+  def clientConnectionFailed(ctx, connector, reason):
+
+    print 'Bail out!'
+    reason.printTraceback()
+
+    reactor.stop()
+
+  class protocol(http.HTTPClient):
+    def connectionLost(ctx, reason):
+      try:
+        reactor.stop()
+
+      except error.ReactorNotRunning:
+        pass
+
+      else:
+        print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
+
+    # Get a response with a Location and a Digest header and check that the
+    # Location header is not rewritten.  Then get the same response after
+    # caching a matching file from a different URL and check that this time the
+    # header is rewritten.
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\nGET {0}:{1}/location HTTP/1.1\r\n\r\nGET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
+
+    def handleResponsePart(ctx, data):
+      try:
+        h, r = data.split('0\r\n\r\n', 1)
+
+      except ValueError:
+        pass
+
+      else:
+
+        ctx.firstLine = True
+        ctx.setLineMode(r)
+
+    def handleStatus(ctx, version, status, message):
+      def handleHeader(k, v):
+        if k.lower() == 'location':
+          if v != 'http://example.com':
+            print 'not',
+
+          print 'ok 1 - Before'
+
+      ctx.handleHeader = handleHeader
+
+      def handleStatus(version, status, message):
+        del ctx.handleHeader
+
+        def handleStatus(version, staus, message):
+          def handleHeader(k, v):
+            if k.lower() == 'location':
+              if v != 'http://{0}:{1}/location'.format(*origin.socket.getsockname()):
+                print 'not',
+
+              print 'ok 2 - After'
+
+              reactor.stop()
+
+          ctx.handleHeader = handleHeader
+
+        ctx.handleStatus = handleStatus
+
+      ctx.handleStatus = handleStatus
+
+tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
+
+reactor.run()


[10/13] git commit: TS-2675: metalink: Drop redundant TSUrlStringGet()

Posted by jp...@apache.org.
TS-2675: metalink: Drop redundant TSUrlStringGet()


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/d25edd9f
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/d25edd9f
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/d25edd9f

Branch: refs/heads/master
Commit: d25edd9fac32e770671297caa6510f8d360aa338
Parents: a31459d
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 13:19:44 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 30 +++++++++++++-------------
 1 file changed, 15 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d25edd9f/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index f18f266..e604272 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -100,6 +100,9 @@ typedef struct {
 
   TSIOBuffer cache_bufp;
 
+  const char *value;
+  int64_t length;
+
 } SendData;
 
 /* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transform */
@@ -468,9 +471,6 @@ cache_open_read_failed(TSCont contp, void * /* edata ATS_UNUSED */)
 static int
 rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
 {
-  char *value;
-  int length;
-
   SendData *data = (SendData *) TSContDataGet(contp);
   TSContDestroy(contp);
 
@@ -479,12 +479,8 @@ rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
   /* Yes: Rewrite the "Location: ..." header and reenable the response */
   case TS_EVENT_CACHE_OPEN_READ:
 
-    /* Allocation!  Must free! */
-    value = TSUrlStringGet(data->resp_bufp, data->url_loc, &length);
     TSMimeHdrFieldValuesClear(data->resp_bufp, data->hdr_loc, data->location_loc);
-    TSMimeHdrFieldValueStringInsert(data->resp_bufp, data->hdr_loc, data->location_loc, -1, value, length);
-
-    TSfree(value);
+    TSMimeHdrFieldValueStringInsert(data->resp_bufp, data->hdr_loc, data->location_loc, -1, data->value, data->length);
 
     break;
 
@@ -496,9 +492,10 @@ rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
     TSAssert(!"Unexpected event");
   }
 
+  TSIOBufferDestroy(data->cache_bufp);
+
   TSCacheKeyDestroy(data->key);
 
-  TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc);
   TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc);
   TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc);
 
@@ -513,8 +510,6 @@ rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
 static int
 vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 {
-  const char *value;
-  int64_t length;
   SendData *data = (SendData *) TSContDataGet(contp);
 
   TSContDestroy(contp);
@@ -523,8 +518,11 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
   TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
 
   /* No allocation, freed with data->cache_bufp? */
-  value = TSIOBufferBlockReadStart(blockp, readerp, &length);
-  if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + length) != TS_PARSE_DONE) {
+  const char *value = data->value = TSIOBufferBlockReadStart(blockp, readerp, &data->length);
+
+  /* The start pointer is both an input and an output parameter.  After a
+   * successful parse the start pointer equals the end pointer. */
+  if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + data->length) != TS_PARSE_DONE) {
     TSIOBufferDestroy(data->cache_bufp);
 
     TSCacheKeyDestroy(data->key);
@@ -539,9 +537,9 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     return 0;
   }
 
-  TSIOBufferDestroy(data->cache_bufp);
-
   if (TSCacheKeyDigestFromUrlSet(data->key, data->url_loc) != TS_SUCCESS) {
+    TSIOBufferDestroy(data->cache_bufp);
+
     TSCacheKeyDestroy(data->key);
 
     TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc);
@@ -554,6 +552,8 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     return 0;
   }
 
+  TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc);
+
   /* Check if the URL stored at the digest is cached */
 
   contp = TSContCreate(rewrite_handler, NULL);


[08/13] git commit: TS-2675: metalink: Plug memory leaks reported by Valgrind

Posted by jp...@apache.org.
TS-2675: metalink: Plug memory leaks reported by Valgrind


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/a31459d4
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/a31459d4
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/a31459d4

Branch: refs/heads/master
Commit: a31459d42c0794bab9cdf46805e97c6abe1ab769
Parents: 52622d2
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 13:07:53 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 28 ++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a31459d4/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index f792d8a..f18f266 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -114,7 +114,7 @@ cache_open_write(TSCont contp, void *edata)
   TSMLoc hdr_loc;
   TSMLoc url_loc;
 
-  const char *value;
+  char *value;
   int length;
 
   WriteData *data = (WriteData *) TSContDataGet(contp);
@@ -142,6 +142,7 @@ cache_open_write(TSCont contp, void *edata)
     return 0;
   }
 
+  /* Allocation!  Must free! */
   value = TSUrlStringGet(req_bufp, url_loc, &length);
   if (!value) {
     TSContDestroy(contp);
@@ -164,6 +165,8 @@ cache_open_write(TSCont contp, void *edata)
 
   int nbytes = TSIOBufferWrite(data->cache_bufp, value, length);
 
+  TSfree(value);
+
   /* Reuse the TSCacheWrite() continuation */
   TSVConnWrite(data->connp, contp, readerp, nbytes);
 
@@ -251,7 +254,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
   const char *value;
   int64_t length;
 
-  char digest[32];
+  char digest[32]; /* SHA-256 */
 
   TransformData *transform_data = (TransformData *) TSContDataGet(contp);
 
@@ -299,6 +302,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
       TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
       while (blockp) {
 
+        /* No allocation? */
         value = TSIOBufferBlockReadStart(blockp, readerp, &length);
         SHA256_Update(&transform_data->c, value, length);
 
@@ -464,7 +468,7 @@ cache_open_read_failed(TSCont contp, void * /* edata ATS_UNUSED */)
 static int
 rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
 {
-  const char *value;
+  char *value;
   int length;
 
   SendData *data = (SendData *) TSContDataGet(contp);
@@ -474,9 +478,14 @@ rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
 
   /* Yes: Rewrite the "Location: ..." header and reenable the response */
   case TS_EVENT_CACHE_OPEN_READ:
+
+    /* Allocation!  Must free! */
     value = TSUrlStringGet(data->resp_bufp, data->url_loc, &length);
     TSMimeHdrFieldValuesClear(data->resp_bufp, data->hdr_loc, data->location_loc);
     TSMimeHdrFieldValueStringInsert(data->resp_bufp, data->hdr_loc, data->location_loc, -1, value, length);
+
+    TSfree(value);
+
     break;
 
   /* No: Do nothing, just reenable the response */
@@ -513,6 +522,7 @@ vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
   TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp);
   TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
 
+  /* No allocation, freed with data->cache_bufp? */
   value = TSIOBufferBlockReadStart(blockp, readerp, &length);
   if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + length) != TS_PARSE_DONE) {
     TSIOBufferDestroy(data->cache_bufp);
@@ -588,8 +598,7 @@ location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
   const char *value;
   int length;
 
-  /* ATS_BASE64_DECODE_DSTLEN() */
-  char digest[33];
+  char digest[33]; /* ATS_BASE64_DECODE_DSTLEN() */
 
   SendData *data = (SendData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -602,17 +611,21 @@ location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
   /* No: Check if the "Digest: SHA-256=..." digest already exists in the cache */
   case TS_EVENT_CACHE_OPEN_READ_FAILED:
 
+    /* No allocation, freed with data->resp_bufp? */
     value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->digest_loc, data->idx, &length);
     if (TSBase64Decode(value + 8, length - 8, (unsigned char *) digest, sizeof(digest), NULL) != TS_SUCCESS
         || TSCacheKeyDigestSet(data->key, digest, 32 /* SHA-256 */ ) != TS_SUCCESS) {
       break;
     }
 
+    TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc);
+
+    /* Check if the "Digest: SHA-256=..." digest already exists in the cache */
+
     contp = TSContCreate(digest_handler, NULL);
     TSContDataSet(contp, data);
 
     TSCacheRead(contp, data->key);
-    TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc);
 
     return 0;
 
@@ -685,6 +698,8 @@ http_send_response_hdr(TSCont contp, void *edata)
   /* If can't parse or lookup the "Location: ..." URL, should still check if
    * the response has a "Digest: SHA-256=..." header?  No: Can't parse or
    * lookup the URL in the "Location: ..." header is an error. */
+
+  /* No allocation, freed with data->resp_bufp? */
   value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->location_loc, -1, &length);
   if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + length) != TS_PARSE_DONE) {
 
@@ -719,6 +734,7 @@ http_send_response_hdr(TSCont contp, void *edata)
     int count = TSMimeHdrFieldValuesCount(data->resp_bufp, data->hdr_loc, data->digest_loc);
     for (data->idx = 0; data->idx < count; data->idx += 1) {
 
+      /* No allocation, freed with data->resp_bufp? */
       value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->digest_loc, data->idx, &length);
       if (length < 8 + 44 /* 32 bytes, Base64 */ || strncasecmp(value, "SHA-256=", 8)) {
         continue;


[04/13] git commit: TS-2675: metalink: Fix crash if INKVConnInternal::do_io_close() gets called after a message is already complete

Posted by jp...@apache.org.
TS-2675: metalink: Fix crash if INKVConnInternal::do_io_close() gets called after a message is already complete


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/ccc549e9
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/ccc549e9
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/ccc549e9

Branch: refs/heads/master
Commit: ccc549e9bbc394e95cf7d1852f7d8a73efb1b4db
Parents: 54316fd
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 13:59:01 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc       | 36 ++++----
 .../metalink/test/pipeliningDisconnect          | 93 ++++++++++++++++++++
 2 files changed, 108 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ccc549e9/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 5def165..8ebd2cc 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -261,22 +261,27 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
   TransformData *transform_data = (TransformData *) TSContDataGet(contp);
 
+  int closed = TSVConnClosedGet(contp);
+  if (closed) {
+    TSContDestroy(contp);
+
+    /* Avoid failed assert "sdk_sanity_check_iocore_structure(bufp) ==
+     * TS_SUCCESS" in TSIOBufferDestroy() if the response is 304 Not Modified */
+    if (transform_data->output_bufp) {
+      TSIOBufferDestroy(transform_data->output_bufp);
+    }
+
+    TSfree(transform_data);
+
+    return 0;
+  }
+
   TSVIO input_viop = TSVConnWriteVIOGet(contp);
 
   /* Initialize data here because can't call TSVConnWrite() before
    * TS_HTTP_RESPONSE_TRANSFORM_HOOK */
   if (!transform_data->output_bufp) {
-
-    /* Avoid failed assert "sdk_sanity_check_iocore_structure(connp) ==
-     * TS_SUCCESS" in TSVConnWrite() if the response is 304 Not Modified */
     TSVConn output_connp = TSTransformOutputVConnGet(contp);
-    if (!output_connp) {
-      TSContDestroy(contp);
-
-      TSfree(transform_data);
-
-      return 0;
-    }
 
     transform_data->output_bufp = TSIOBufferCreate();
     TSIOBufferReader readerp = TSIOBufferReaderAlloc(transform_data->output_bufp);
@@ -322,17 +327,6 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
   int ntodo = TSVIONTodoGet(input_viop);
   if (ntodo) {
-
-    /* Don't update the downstream nbytes because the input isn't complete */
-    if (!readerp) {
-      TSContDestroy(contp);
-
-      TSIOBufferDestroy(transform_data->output_bufp);
-      TSfree(transform_data);
-
-      return 0;
-    }
-
     TSVIOReenable(transform_data->output_viop);
 
     TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ccc549e9/plugins/experimental/metalink/test/pipeliningDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/pipeliningDisconnect b/plugins/experimental/metalink/test/pipeliningDisconnect
new file mode 100755
index 0000000..152e2cf
--- /dev/null
+++ b/plugins/experimental/metalink/test/pipeliningDisconnect
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+# 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 "License"); 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 "AS IS" 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.
+
+print '''1..1 pipeliningDisconnect
+# The proxy doesn't crash if INKVConnInternal::do_io_close() gets called after
+# a message is already complete'''
+
+from twisted.internet import error, protocol, reactor, tcp
+from twisted.web import http
+
+def callback():
+  print 'ok 1 - Did the connection close before the proxy made the second request?'
+
+  reactor.stop()
+
+reactor.callLater(2, callback)
+
+class factory(http.HTTPFactory):
+  class protocol(http.HTTPChannel):
+    class requestFactory(http.Request):
+      def requestReceived(ctx, method, target, version):
+        class requestFactory(http.Request):
+          def requestReceived(ctx, method, target, version):
+
+            ctx.client = None
+            ctx.clientproto = version
+
+            ctx.write('pipeliningDisconnect')
+            ctx.finish()
+
+            # Open another connection
+            class factory(protocol.ClientFactory):
+              def clientConnectionFailed(ctx, connector, reason):
+                print 'not ok 1 - Did the proxy crash?  (Can\'t open another connection to it.)'
+
+                reactor.stop()
+
+              class protocol(protocol.Protocol):
+                def connectionMade(ctx):
+                  print 'ok 1 - The proxy didn\'t crash (opened another connection to it)'
+
+                  reactor.stop()
+
+            reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect)
+
+        ctx.channel.requestFactory = requestFactory
+
+        ctx.client = None
+        ctx.clientproto = version
+
+        ctx.write('pipeliningDisconnect')
+        ctx.finish()
+
+origin = tcp.Port(0, factory())
+origin.startListening()
+
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
+
+class factory(protocol.ClientFactory):
+  def clientConnectionFailed(ctx, connector, reason):
+
+    print 'Bail out!'
+    reason.printTraceback()
+
+    reactor.stop()
+
+  class protocol(protocol.Protocol):
+    def connectionMade(ctx):
+
+      # Somehow these magic words frequently cause
+      # INKVConnInternal::do_io_close() to get called after a message is
+      # already complete
+      ctx.transport.write('GET {0}:{1}/pipeliningDisconnect0 HTTP/1.1\r\n\r\nGET {0}:{1}/pipeliningDisconnect1 HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
+      ctx.transport.loseConnection()
+
+tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
+
+reactor.run()


[03/13] git commit: TS-2675: metalink: Simpler to drop http.HTTPClient where not needed and minor edits

Posted by jp...@apache.org.
TS-2675: metalink: Simpler to drop http.HTTPClient where not needed and minor edits


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/54316fd3
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/54316fd3
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/54316fd3

Branch: refs/heads/master
Commit: 54316fd36451b15b209946e99f38cc6d74727280
Parents: d25edd9
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 13:43:10 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc       |  2 +-
 .../experimental/metalink/test/chunkedEncoding  | 38 +++++++++---------
 .../metalink/test/chunkedEncodingDisconnect     | 40 +++++++++----------
 .../experimental/metalink/test/clientDisconnect | 41 +++++++++----------
 .../experimental/metalink/test/contentLength    | 38 +++++++++---------
 .../metalink/test/contentLengthDisconnect       | 40 +++++++++----------
 .../test/finalChunkedEncodingDisconnect         | 42 ++++++++++----------
 plugins/experimental/metalink/test/http09       | 38 +++++++++---------
 plugins/experimental/metalink/test/longer       | 40 +++++++++----------
 plugins/experimental/metalink/test/notModified  | 34 ++++++++--------
 .../test/shortChunkedEncodingDisconnect         | 38 +++++++++---------
 .../metalink/test/shortClientDisconnect         | 41 +++++++++----------
 .../metalink/test/shortContentLengthDisconnect  | 38 +++++++++---------
 plugins/experimental/metalink/test/zero         | 34 ++++++++--------
 14 files changed, 247 insertions(+), 257 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index e604272..5def165 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -292,7 +292,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
   }
 
   /* Avoid failed assert "sdk_sanity_check_iocore_structure(readerp) ==
-   * TS_SUCCESS" in TSIOBufferReaderAvail() if the client or server disconnects
+   * TS_SUCCESS" in TSIOBufferReaderAvail() if the client or origin disconnect
    * or the content length is zero */
   TSIOBufferReader readerp = TSVIOReaderGet(input_viop);
   if (readerp) {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/chunkedEncoding
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/chunkedEncoding b/plugins/experimental/metalink/test/chunkedEncoding
index ece4768..7a2ed37 100755
--- a/plugins/experimental/metalink/test/chunkedEncoding
+++ b/plugins/experimental/metalink/test/chunkedEncoding
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 chunkedEncoding
 # The proxy forwards the final chunk at the end of a chunked response'''
@@ -43,10 +43,10 @@ class factory(http.HTTPFactory):
         # headers, it may send a Content-Length header vs. a chunked response
         reactor.callLater(1, ctx.finish)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -67,7 +67,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -76,11 +76,11 @@ class factory(protocol.ClientFactory):
         # No hope of a final chunk now
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent a Content-Length header vs. a chunked response).
     # (Override connectionLost() when the proxy crashes or stop the reactor.)
     #
-    # The data that was already received will be processed (the end of the
+    # Data that was already received will be processed (the end of the
     # headers), then shutdown events will fire (connections will be closed),
     # and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/chunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/chunkedEncodingDisconnect b/plugins/experimental/metalink/test/chunkedEncodingDisconnect
index 3c0210b..91593d0 100755
--- a/plugins/experimental/metalink/test/chunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/chunkedEncodingDisconnect
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 chunkedEncodingDisconnect
 # The proxy closes the client connection and doesn't send a final chunk if the
-# server disconnects without sending one'''
+# origin disconnects without sending one'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -40,15 +40,15 @@ class factory(http.HTTPFactory):
 
         ctx.write('chunkedEncodingDisconnect')
 
-        # If the server disconnects before the proxy sends the response
+        # If the origin disconnects before the proxy sends the response
         # headers, the proxy may send a Content-Length header vs. a chunked
         # response
         reactor.callLater(1, ctx.transport.loseConnection)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -69,7 +69,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'ok 1 - The client connection closed'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -78,7 +78,7 @@ class factory(protocol.ClientFactory):
         # Who cares what happens now?
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent a Content-Length header vs. a chunked response).
     # (Override connectionLost() when the proxy closes the client connection or
     # stop the reactor.)

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/clientDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/clientDisconnect b/plugins/experimental/metalink/test/clientDisconnect
index b8ee3da..b9ff984 100755
--- a/plugins/experimental/metalink/test/clientDisconnect
+++ b/plugins/experimental/metalink/test/clientDisconnect
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 clientDissconnect
 # The proxy doesn't crash if the client disconnects prematurely'''
@@ -64,10 +64,10 @@ class factory(http.HTTPFactory):
 
         reactor.callLater(1, callback)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -77,18 +77,13 @@ class factory(protocol.ClientFactory):
 
     reactor.stop()
 
-  class protocol(http.HTTPClient):
+  class protocol(protocol.Protocol):
     def connectionMade(ctx):
-      ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+      ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
       # Disconnect after the proxy sends the response headers
       reactor.callLater(1, ctx.transport.loseConnection)
 
-    # Avoid calling undefined handleResponse() at the end of the content or
-    # when the connection closes
-    def handleResponseEnd(ctx):
-      pass
-
 tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
 
 reactor.run()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/contentLength
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/contentLength b/plugins/experimental/metalink/test/contentLength
index c3005ac..92708e7 100755
--- a/plugins/experimental/metalink/test/contentLength
+++ b/plugins/experimental/metalink/test/contentLength
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 contentLength
 # The proxy forwards the Content-Length header to the client'''
@@ -40,10 +40,10 @@ class factory(http.HTTPFactory):
         ctx.setHeader('Content-Length', 13)
         ctx.write('contentLength')
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -64,7 +64,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleEndHeaders(ctx):
       try:
@@ -85,10 +85,10 @@ class factory(protocol.ClientFactory):
 
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content.
+    # Avoid calling undefined handleResponse() at the end of the message.
     # (Override connectionLost() when the proxy crashes or stop the reactor.)
     #
-    # The data that was already received will be processed (the end of the
+    # Data that was already received will be processed (the end of the
     # headers), then shutdown events will fire (connections will be closed),
     # and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/contentLengthDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/contentLengthDisconnect b/plugins/experimental/metalink/test/contentLengthDisconnect
index 2c98ae8..1627d0e 100755
--- a/plugins/experimental/metalink/test/contentLengthDisconnect
+++ b/plugins/experimental/metalink/test/contentLengthDisconnect
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..2 contentLengthDisconnect
-# The proxy closes the client connection if the server disconnects prematurely'''
+# The proxy closes the client connection if the origin disconnects prematurely'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -40,14 +40,14 @@ class factory(http.HTTPFactory):
         ctx.setHeader('Content-Length', 24)
         ctx.write('contentLengthDisconnect')
 
-        # If the server disconnects before the proxy sends the response
+        # If the origin disconnects before the proxy sends the response
         # headers, the proxy may send the wrong Content-Length header
         reactor.callLater(1, ctx.transport.loseConnection)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -68,7 +68,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'ok 2 - The client connection closed'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -80,7 +80,7 @@ class factory(protocol.ClientFactory):
 
         print 'ok 1 - Content-Length header'
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent the wrong Content-Length header).  (Override
     # connectionLost() when the proxy closes the client connection or stop the
     # reactor.)

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect b/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
index 9fa4093..32011bc 100755
--- a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 finalChunkEncodingDisconnect
-# The proxy forwards the final chunk even if the server disconnects immediately
+# The proxy forwards the final chunk even if the origin disconnects immediately
 # afterward'''
 
 from twisted.internet import error, protocol, reactor, tcp
@@ -47,7 +47,7 @@ class factory(http.HTTPFactory):
             ctx.finish()
 
           except RuntimeError:
-            print 'not ok 1 - Did the proxy crash?  (The server connection closed.)'
+            print 'not ok 1 - Did the proxy crash?  (The origin connection closed.)'
 
             reactor.stop()
 
@@ -56,10 +56,10 @@ class factory(http.HTTPFactory):
 
         reactor.callLater(1, callback)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -80,7 +80,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -89,11 +89,11 @@ class factory(protocol.ClientFactory):
         # No hope of a final chunk now
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent a Content-Length header vs. a chunked response).
     # (Override connectionLost() when the proxy crashes or stop the reactor.)
     #
-    # The data that was already received will be processed (the end of the
+    # Data that was already received will be processed (the end of the
     # headers), then shutdown events will fire (connections will be closed),
     # and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/http09
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/http09 b/plugins/experimental/metalink/test/http09
index 9103c8d..e9f7c77 100755
--- a/plugins/experimental/metalink/test/http09
+++ b/plugins/experimental/metalink/test/http09
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 http09
 # The proxy doesn't crash on an HTTP/0.9 response'''
@@ -23,7 +23,7 @@ print '''1..1 http09
 #
 # The proxy crashes only after the response is complete.  It closes the client
 # connection whether it crashes or not because an HTTP/0.9 response is complete
-# only after the server closes its connection, and then the proxy normally does
+# only after the origin closes its connection, and then the proxy normally does
 # the same thing to the client connection (although it upgrades the response to
 # HTTP/1.1).  So the only way to check that the proxy didn't crash is to open
 # another connection.
@@ -46,10 +46,10 @@ class factory(protocol.Factory):
       # The proxy crashes only after the response is complete
       ctx.transport.loseConnection()
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -59,7 +59,7 @@ class factory(protocol.ClientFactory):
 
     reactor.stop()
 
-  class protocol(http.HTTPClient):
+  class protocol(protocol.Protocol):
     def connectionLost(ctx, reason):
 
       # Open another connection
@@ -77,7 +77,7 @@ class factory(protocol.ClientFactory):
 
       reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect)
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
 tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/longer
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/longer b/plugins/experimental/metalink/test/longer
index f08feae..259ad7d 100755
--- a/plugins/experimental/metalink/test/longer
+++ b/plugins/experimental/metalink/test/longer
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 longer
-# The proxy doesn't choke if the server sends more content than it advertised'''
+# The proxy doesn't choke if the origin sends more content than it advertised'''
 
 # Unlike the contentLength test, don't stop the reactor at the end of the
 # headers.  Give the proxy time to choke.
@@ -43,10 +43,10 @@ class factory(http.HTTPFactory):
         ctx.setHeader('Content-Length', 1)
         ctx.write('longer')
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -67,7 +67,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -78,10 +78,10 @@ class factory(protocol.ClientFactory):
 
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content.
+    # Avoid calling undefined handleResponse() at the end of the message.
     # (Override connectionLost() when the proxy crashes or stop the reactor.)
     #
-    # The data that was already received will be processed (the end of the
+    # Data that was already received will be processed (the end of the
     # headers), then shutdown events will fire (connections will be closed),
     # and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/notModified
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/notModified b/plugins/experimental/metalink/test/notModified
index 2854189..90c3a87 100755
--- a/plugins/experimental/metalink/test/notModified
+++ b/plugins/experimental/metalink/test/notModified
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..2 notModified
 # The proxy doesn't crash on a 304 Not Modified response'''
@@ -40,10 +40,10 @@ class factory(http.HTTPFactory):
         ctx.setResponseCode(304)
         ctx.finish()
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -64,7 +64,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleStatus(ctx, version, status, message):
       if status != '304':

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect b/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
index 526b233..3c52858 100755
--- a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 shortChunkedEncodingDisconnect
 # The proxy closes the client connection and doesn't send a final chunk if the
-# server disconnects without sending one, before the proxy sends the response
+# origin disconnects without sending one, before the proxy sends the response
 # headers'''
 
 from twisted.internet import error, protocol, reactor, tcp
@@ -44,10 +44,10 @@ class factory(http.HTTPFactory):
         # Disconnect before the proxy sends the response headers
         ctx.transport.loseConnection()
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -68,7 +68,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'ok 1 - The client connection closed'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -77,7 +77,7 @@ class factory(protocol.ClientFactory):
         # Who cares what happens now?
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent a Content-Length header vs. a chunked response).
     # (Override connectionLost() when the proxy closes the client connection or
     # stop the reactor.)

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/shortClientDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortClientDisconnect b/plugins/experimental/metalink/test/shortClientDisconnect
index 4ab6c83..6956c78 100755
--- a/plugins/experimental/metalink/test/shortClientDisconnect
+++ b/plugins/experimental/metalink/test/shortClientDisconnect
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 shortClientDisconnect
 # The proxy doesn't crash if the client disconnects before the proxy sends the
@@ -60,10 +60,10 @@ class factory(http.HTTPFactory):
 
         reactor.callLater(1, callback)
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -73,18 +73,13 @@ class factory(protocol.ClientFactory):
 
     reactor.stop()
 
-  class protocol(http.HTTPClient):
+  class protocol(protocol.Protocol):
     def connectionMade(ctx):
-      ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+      ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
       # Disconnect before the proxy sends the response headers
       ctx.transport.loseConnection()
 
-    # Avoid calling undefined handleResponse() at the end of the content or
-    # when the connection closes
-    def handleResponseEnd(ctx):
-      pass
-
 tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
 
 reactor.run()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/shortContentLengthDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortContentLengthDisconnect b/plugins/experimental/metalink/test/shortContentLengthDisconnect
index 2e1c813..5662650 100755
--- a/plugins/experimental/metalink/test/shortContentLengthDisconnect
+++ b/plugins/experimental/metalink/test/shortContentLengthDisconnect
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..2 shortContentLengthDisconnect
 # The proxy sends the right Content-Length header and closes the client
-# connection if the server disconnects before the proxy sends the response
+# connection if the origin disconnects before the proxy sends the response
 # headers'''
 
 from twisted.internet import error, protocol, reactor, tcp
@@ -45,10 +45,10 @@ class factory(http.HTTPFactory):
         # Disconnect before the proxy sends the response headers
         ctx.transport.loseConnection()
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -69,7 +69,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'ok 2 - The client connection closed'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleHeader(ctx, k, v):
       if k.lower() == 'content-length':
@@ -81,7 +81,7 @@ class factory(protocol.ClientFactory):
 
         print 'ok 1 - Content-Length header'
 
-    # Avoid calling undefined handleResponse() at the end of the content (if
+    # Avoid calling undefined handleResponse() at the end of the message (if
     # the proxy sent the wrong Content-Length header).  (Override
     # connectionLost() when the proxy closes the client connection or stop the
     # reactor.)

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/54316fd3/plugins/experimental/metalink/test/zero
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/zero b/plugins/experimental/metalink/test/zero
index 6d42d56..3605a2b 100755
--- a/plugins/experimental/metalink/test/zero
+++ b/plugins/experimental/metalink/test/zero
@@ -1,20 +1,20 @@
 #!/usr/bin/env python
 
-#  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
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
+# 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 "License"); 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
+#    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 "AS IS" 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.
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" 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.
 
 print '''1..1 zero
 # The proxy doesn't crash if the Content-Length is zero'''
@@ -40,10 +40,10 @@ class factory(http.HTTPFactory):
         ctx.setHeader('Content-Length', 0)
         ctx.finish()
 
-server = tcp.Port(0, factory())
-server.startListening()
+origin = tcp.Port(0, factory())
+origin.startListening()
 
-print '# Listening on {0}:{1}'.format(*server.socket.getsockname())
+print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())
 
 class factory(protocol.ClientFactory):
   def clientConnectionFailed(ctx, connector, reason):
@@ -64,7 +64,7 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*server.socket.getsockname()))
+    connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleEndHeaders(ctx):
       try:


[05/13] git commit: TS-2675: metalink: add missing TSCacheKeyDestroy

Posted by jp...@apache.org.
TS-2675: metalink: add missing TSCacheKeyDestroy


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/441c1c58
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/441c1c58
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/441c1c58

Branch: refs/heads/master
Commit: 441c1c58169b8ada22392adbf3f2ba63046125d4
Parents: 3ba8288
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 11:28:58 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/441c1c58/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index be48601..238bbee 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -345,6 +345,7 @@ transform_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
   if (TSCacheKeyDigestSet(data->key, digest, sizeof(digest)) != TS_SUCCESS) {
     TSContDestroy(contp);
 
+    TSCacheKeyDestroy(data->key);
     TSfree(data);
 
     return 0;


[11/13] git commit: TS-2675: metalink: Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream

Posted by jp...@apache.org.
TS-2675: metalink: Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream

Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream when the
input is complete otherwise HttpSM::update_stats() won't get called
and the transaction won't get logged.  (If there are upstream
transformations they won't get a chance to clean up otherwise!)


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/f88a7260
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/f88a7260
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/f88a7260

Branch: refs/heads/master
Commit: f88a72606610ee79c458cee32b9ea34c16695c6b
Parents: ccc549e
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 14:02:19 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/f88a7260/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 8ebd2cc..c7fafcc 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -338,6 +338,10 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
     TSVIOReenable(transform_data->output_viop);
 
+    if (readerp) {
+      TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_COMPLETE, input_viop);
+    }
+
     /* Write the digest to the cache */
 
     SHA256_Final((unsigned char *) digest, &transform_data->c);


[12/13] git commit: TS-2675: metalink: Reformat comments

Posted by jp...@apache.org.
TS-2675: metalink: Reformat comments

metalink: Clarify that we *must* check TSVConnClosedGet(), if only to clean up allocated data


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/a9a0b7cc
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/a9a0b7cc
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/a9a0b7cc

Branch: refs/heads/master
Commit: a9a0b7ccbbff448fd14ea2b22930ce6fc8b2c95f
Parents: f9d74b9
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Fri Mar 21 12:21:32 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 doc/reference/plugins/metalink.en.rst           |  16 +-
 plugins/experimental/metalink/metalink.cc       | 298 +++++++++++--------
 .../experimental/metalink/test/chunkedEncoding  |  18 +-
 .../metalink/test/chunkedEncodingDisconnect     |  18 +-
 .../experimental/metalink/test/contentLength    |  11 +-
 .../metalink/test/contentLengthDisconnect       |  16 +-
 .../test/finalChunkedEncodingDisconnect         |  22 +-
 plugins/experimental/metalink/test/http09       |  13 +-
 plugins/experimental/metalink/test/location     |   8 +-
 plugins/experimental/metalink/test/longer       |  18 +-
 .../metalink/test/pipeliningDisconnect          |   8 +-
 .../test/shortChunkedEncodingDisconnect         |  14 +-
 .../metalink/test/shortClientDisconnect         |   4 +-
 .../metalink/test/shortContentLengthDisconnect  |  14 +-
 14 files changed, 273 insertions(+), 205 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/doc/reference/plugins/metalink.en.rst
----------------------------------------------------------------------
diff --git a/doc/reference/plugins/metalink.en.rst b/doc/reference/plugins/metalink.en.rst
index 50e1b32..ea71a87 100644
--- a/doc/reference/plugins/metalink.en.rst
+++ b/doc/reference/plugins/metalink.en.rst
@@ -6,7 +6,7 @@
    except in compliance with the License.  You may obtain a copy of
    the License at
 
-   http://www.apache.org/licenses/LICENSE-2.0
+      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 "AS IS" BASIS,
@@ -70,13 +70,13 @@ Implementation Status
 ---------------------
 
 The plugin implements the ``TS_HTTP_SEND_RESPONSE_HDR_HOOK`` hook to
-check and potentially rewrite the :mailheader:`Location: ...` and
-:mailheader:`Digest: SHA-256=...` headers after responses are cached.
-It doesn't do it before they're cached because the contents of the
-cache can change after responses are cached.  It uses
-:c:func:`TSCacheRead` to check if the URL in the
-:mailheader:`Location: ...` header is already cached.  In future, the
-plugin should also check if the URL is fresh or not.
+check and potentially rewrite the :mailheader:`Location` and
+:mailheader:`Digest` headers after responses are cached.  It doesn't
+do it before they're cached because the contents of the cache can
+change after responses are cached.  It uses :c:func:`TSCacheRead` to
+check if the URL in the :mailheader:`Location` header is already
+cached.  In future, the plugin should also check if the URL is fresh
+or not.
 
 The plugin implements the ``TS_HTTP_READ_RESPONSE_HDR_HOOK`` hook and
 `a null transformation`_ to compute the SHA-256 digest for content as

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index ae8771c..207fdf1 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -27,21 +27,22 @@
 
 #include "ts/ts.h"
 
-/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transformation.
- * Compute the SHA-256 digest of the content, write it to the cache and store
- * the request URL at that key.
+/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null
+ * transformation.  Compute the SHA-256 digest of the content, write
+ * it to the cache and store the request URL at that key.
  *
- * Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the "Location: ..." and
- * "Digest: SHA-256=..." headers.  Use TSCacheRead() to check if the URL in the
- * "Location: ..." header is already cached.  If not, potentially rewrite that
- * header.  Do this after responses are cached because the cache will change.
+ * Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the Location and
+ * Digest headers.  Use TSCacheRead() to check if the URL in the
+ * Location header is already cached.  If not, potentially rewrite
+ * that header.  Do this after responses are cached because the cache
+ * will change.
  *
  * More details are on the [wiki page] in the Traffic Server wiki.
  *
  *    [wiki page]   https://cwiki.apache.org/confluence/display/TS/Metalink */
 
-/* TSCacheWrite() and TSVConnWrite() data: Write the digest to the cache and
- * store the request URL at that key */
+/* TSCacheWrite() and TSVConnWrite() data: Write the digest to the
+ * cache and store the request URL at that key */
 
 typedef struct {
   TSHttpTxn txnp;
@@ -67,8 +68,8 @@ typedef struct {
 
 } TransformData;
 
-/* TSCacheRead() and TSVConnRead() data: Check the "Location: ..." and
- * "Digest: SHA-256=..." headers */
+/* TSCacheRead() and TSVConnRead() data: Check the Location and Digest
+ * headers */
 
 typedef struct {
   TSHttpTxn txnp;
@@ -76,14 +77,14 @@ typedef struct {
   TSMBuffer resp_bufp;
   TSMLoc hdr_loc;
 
-  /* "Location: ..." header */
+  /* Location header */
   TSMLoc location_loc;
 
   /* Cache key */
   TSMLoc url_loc;
   TSCacheKey key;
 
-  /* "Digest: SHA-256=..." header */
+  /* Digest header */
   TSMLoc digest_loc;
 
   /* Digest header field value index */
@@ -96,7 +97,8 @@ typedef struct {
 
 } SendData;
 
-/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transformation */
+/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null
+ * transformation */
 
 /* Write the digest to the cache and store the request URL at that key */
 
@@ -187,9 +189,9 @@ write_vconn_write_complete(TSCont contp, void */* edata ATS_UNUSED */)
   WriteData *data = (WriteData *) TSContDataGet(contp);
   TSContDestroy(contp);
 
-  /* The object is not committed to the cache until the vconnection is closed.
-   * When all the data has been transferred, the user (contp) must do a
-   * TSVConnClose() */
+  /* The object is not committed to the cache until the VConnection is
+   * closed.  When all the data has been transferred, the user (contp)
+   * must do a TSVConnClose() */
   TSVConnClose(data->connp);
 
   TSIOBufferDestroy(data->cache_bufp);
@@ -198,8 +200,8 @@ write_vconn_write_complete(TSCont contp, void */* edata ATS_UNUSED */)
   return 0;
 }
 
-/* TSCacheWrite() and TSVConnWrite() handler: Write the digest to the cache and
- * store the request URL at that key */
+/* TSCacheWrite() and TSVConnWrite() handler: Write the digest to the
+ * cache and store the request URL at that key */
 
 static int
 write_handler(TSCont contp, TSEvent event, void *edata)
@@ -221,64 +223,113 @@ write_handler(TSCont contp, TSEvent event, void *edata)
   return 0;
 }
 
-/* Copy content from the input buffer to the output buffer without modification
- * and feed it through the message digest at the same time.
+/* Copy content from the input buffer to the output buffer without
+ * modification and feed it through the message digest at the same
+ * time.
  *
- *    1.  Check if we are "closed" before doing anything else to avoid errors.
+ *    1.  Check if we are "closed" before doing anything else to avoid
+ *        errors.
  *    2.  Then deal with any input that's available now.
- *    3.  Check if the input is complete after dealing with any available input
- *        in case it was the last of it.  If it is complete, tell downstream,
- *        thank upstream, and finish computing the digest.  Otherwise either
- *        wait for more input or abort if upstream is "closed".
+ *    3.  Check if the input is complete after dealing with any
+ *        available input in case it was the last of it.  If it is
+ *        complete, tell downstream, thank upstream, and finish
+ *        computing the digest.  Otherwise either wait for more input
+ *        or abort if upstream is "closed".
  *
- * The handler is guaranteed to get called at least once, even if the response
- * is 304 Not Modified, so we are guaranteed an opportunity to clean up e.g.
- * data that we allocated when we called TSTransformCreate().
+ * The handler is guaranteed to get called at least once, even if the
+ * response is 304 Not Modified, so we are guaranteed an opportunity
+ * to clean up e.g. data that we allocated when we called
+ * TSTransformCreate().
  *
- * TS_EVENT_VCONN_WRITE_READY and TS_EVENT_VCONN_WRITE_COMPLETE events are sent
- * from downstream, e.g. by TransformTerminus::handle_event().
- * TS_EVENT_IMMEDIATE events are sent by INKVConnInternal::do_io_write(),
- * INKVConnInternal::do_io_close(), and INKVConnInternal::reenable() which are
- * called from upstream, e.g. by TransformVConnection::do_io_write(),
- * TransformVConnection::do_io_close(), and HttpTunnel::producer_handler().
+ * TS_EVENT_VCONN_WRITE_READY and TS_EVENT_VCONN_WRITE_COMPLETE events
+ * are sent from downstream, e.g. by
+ * TransformTerminus::handle_event().  TS_EVENT_IMMEDIATE events are
+ * sent by INKVConnInternal::do_io_write(),
+ * INKVConnInternal::do_io_close(), and INKVConnInternal::reenable()
+ * which are called from upstream, e.g. by
+ * TransformVConnection::do_io_write(),
+ * TransformVConnection::do_io_close(), and
+ * HttpTunnel::producer_handler().
  *
- * Clean up the output buffer on TS_EVENT_VCONN_WRITE_COMPLETE and not before.
- * We are guaranteed a TS_EVENT_VCONN_WRITE_COMPLETE event *unless* we are
- * "closed".  In that case we instead get a TS_EVENT_IMMEDIATE event where
- * TSVConnClosedGet() is one, so clean up the output buffer in that case as
- * well.  We'll only ever get one event where TSVConnClosedGet() is one and it
- * will be our last, so there's no risk of a double free.
+ * Clean up the output buffer on TS_EVENT_VCONN_WRITE_COMPLETE and not
+ * before.  We are guaranteed a TS_EVENT_VCONN_WRITE_COMPLETE event
+ * *unless* we are "closed".  In that case we instead get a
+ * TS_EVENT_IMMEDIATE event where TSVConnClosedGet() is one.  We'll
+ * only ever get one event where TSVConnClosedGet() is one and it will
+ * be our last, so we *must* check for this case and clean up then
+ * too.  Because we'll only ever get one such event and it will be our
+ * last, there's no risk of double freeing.
  *
- * The response headers get sent when TSVConnWrite() gets called and not
- * before.  (We could potentially edit them until then.)
+ * The response headers get sent when TSVConnWrite() gets called and
+ * not before.  (We could potentially edit them until then.)
  *
- * The events say nothing about the state of the input.  Gather this instead
- * from TSVConnClosedGet(), TSVIOReaderGet(), and TSVIONTodoGet() and handle
- * the end of the input independently from the TS_EVENT_VCONN_WRITE_COMPLETE
- * event from downstream.
+ * The events say nothing about the state of the input.  Gather this
+ * instead from TSVConnClosedGet(), TSVIOReaderGet(), and
+ * TSVIONTodoGet() and handle the end of the input independently from
+ * the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream.
  *
- * When TSVConnClosedGet() is one, *we* are "closed".  Some state is already
- * inconsistent and there's nothing to do except clean up.  (This happens when
- * the response is 304 Not Modified or when the client or origin disconnect
- * before the message is complete.)
+ * When TSVConnClosedGet() is one, *we* are "closed".  We *must* check
+ * for this case, if only to clean up allocated data.  Some state is
+ * already inconsistent.  (This happens when the response is 304 Not
+ * Modified or when the client or origin disconnect before the message
+ * is complete.)
  *
- * When TSVIOReaderGet() is NULL, upstream is "closed".  In that case it's
- * clearly an error to call TSIOBufferReaderAvail(), it's also an error at that
- * point to send any events upstream with TSContCall().  (This happens when the
- * content length is zero or when we get the final chunk of a
- * "Transfer-Encoding: chunked" response.)
+ * When TSVIOReaderGet() is NULL, upstream is "closed".  In that case
+ * it's clearly an error to call TSIOBufferReaderAvail(), it's also an
+ * error at that point to send any events upstream with TSContCall().
+ * (This happens when the content length is zero or when we get the
+ * final chunk of a chunked response.)
  *
- * The input is complete only when TSVIONTodoGet() is zero.  (Don't update the
- * downstream nbytes otherwise!)  Update the downstream nbytes when the input
- * is complete in case the response is "Transfer-Encoding: chunked" (in which
- * case nbytes is unknown until then).  Downstream will (normally) send the
- * TS_EVENT_VCONN_WRITE_COMPLETE event (and the final chunk if the response is
- * "Transfer-Encoding: chunked") when ndone equals nbytes and not before.
+ * The input is complete only when TSVIONTodoGet() is zero.  (Don't
+ * update the downstream nbytes otherwise!)  Update the downstream
+ * nbytes when the input is complete in case the response is chunked
+ * (in which case nbytes is unknown until then).  Downstream will
+ * (normally) send the TS_EVENT_VCONN_WRITE_COMPLETE event (and the
+ * final chunk if the response is chunked) when ndone equals nbytes
+ * and not before.
  *
- * Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream when the input is
- * complete otherwise HttpSM::update_stats() won't get called and the
- * transaction won't get logged.  (If there are upstream transformations they
- * won't get a chance to clean up otherwise!) */
+ * Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream when the
+ * input is complete otherwise HttpSM::update_stats() won't get called
+ * and the transaction won't get logged.  (If there are upstream
+ * transformations they won't get a chance to clean up otherwise!)
+ *
+ * Summary of the cases into which each event can fall:
+ *
+ *    Closed        *We* are "closed".  Clean up allocated data.
+ *
+ *       Start      First (and last) time the handler was called.
+ *                  (This happens when the response is 304 Not Modified.)
+ *
+ *       Not start  (This happens when the client or origin disconnect
+ *                  before the message is complete.)
+ *
+ *    Start         First time the handler was called.  Initialize
+ *                  data here because we can't call TSVConnWrite()
+ *                  before TS_HTTP_RESPONSE_TRANSFORM_HOOK.
+ *
+ *       Content length
+ *
+ *       Chunked response
+ *
+ *    Upstream closed
+ *                  (This happens when the content length is zero or
+ *                  when we get the final chunk of a chunked
+ *                  response.)
+ *
+ *    Available input
+ *
+ *    Input complete
+ *
+ *       Deja vu    There might be multiple TS_EVENT_IMMEDIATE events
+ *                  between the end of the input and the
+ *                  TS_EVENT_VCONN_WRITE_COMPLETE event from
+ *                  downstream.
+ *
+ *       Not deja vu
+ *                  Tell downstream and thank upstream.
+ *
+ *    Downstream complete
+ *                  Clean up the output buffer. */
 
 static int
 vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
@@ -290,16 +341,18 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
 
   TransformData *transform_data = (TransformData *) TSContDataGet(contp);
 
-  /* Check if we are "closed" before doing anything else to avoid errors.  Some
-   * state is already inconsistent and there's nothing to do except clean up.
-   * (This happens if the response is 304 Not Modified or if the client or
+  /* Check if we are "closed" before doing anything else to avoid
+   * errors.  We *must* check for this case, if only to clean up
+   * allocated data.  Some state is already inconsistent.  (This
+   * happens if the response is 304 Not Modified or if the client or
    * origin disconnect before the message is complete.) */
   int closed = TSVConnClosedGet(contp);
   if (closed) {
     TSContDestroy(contp);
 
     /* Avoid failed assert "sdk_sanity_check_iocore_structure(bufp) ==
-     * TS_SUCCESS" in TSIOBufferDestroy() if the response is 304 Not Modified */
+     * TS_SUCCESS" in TSIOBufferDestroy() if the response is 304 Not
+     * Modified */
     if (transform_data->output_bufp) {
       TSIOBufferDestroy(transform_data->output_bufp);
     }
@@ -319,20 +372,19 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
     transform_data->output_bufp = TSIOBufferCreate();
     TSIOBufferReader readerp = TSIOBufferReaderAlloc(transform_data->output_bufp);
 
-    /* Determines the "Content-Length: ..." header
-     * (or "Transfer-Encoding: chunked") */
+    /* Determines the Content-Length header (or a chunked response) */
 
-    /* Avoid failed assert "nbytes >= 0" if "Transfer-Encoding: chunked" */
+    /* Avoid failed assert "nbytes >= 0" if the response is chunked */
     int nbytes = TSVIONBytesGet(input_viop);
     transform_data->output_viop = TSVConnWrite(output_connp, contp, readerp, nbytes < 0 ? INT64_MAX : nbytes);
 
     SHA256_Init(&transform_data->c);
   }
 
-  /* Then deal with any input that's available now.  Avoid failed assert
-   * "sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS" in
-   * TSIOBufferReaderAvail() if the content length is zero or when we get the
-   * final chunk of a "Transfer-Encoding: chunked" response. */
+  /* Then deal with any input that's available now.  Avoid failed
+   * assert "sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS"
+   * in TSIOBufferReaderAvail() if the content length is zero or when
+   * we get the final chunk of a chunked response. */
   TSIOBufferReader readerp = TSVIOReaderGet(input_viop);
   if (readerp) {
 
@@ -359,18 +411,19 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
     }
   }
 
-  /* Check if the input is complete after dealing with any available input in
-   * case it was the last of it */
+  /* Check if the input is complete after dealing with any available
+   * input in case it was the last of it */
   int ntodo = TSVIONTodoGet(input_viop);
   if (ntodo) {
     TSVIOReenable(transform_data->output_viop);
 
     TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop);
 
-  /* Don't finish computing the digest (and tell downstream and thank upstream)
-   * more than once!  There might be multiple TS_EVENT_IMMEDIATE events between
-   * the end of the input and the TS_EVENT_VCONN_WRITE_COMPLETE event from
-   * downstream, e.g. INKVConnInternal::reenable() is called by
+  /* Don't finish computing the digest (and tell downstream and thank
+   * upstream) more than once!  There might be multiple
+   * TS_EVENT_IMMEDIATE events between the end of the input and the
+   * TS_EVENT_VCONN_WRITE_COMPLETE event from downstream, e.g.
+   * INKVConnInternal::reenable() is called by
    * HttpTunnel::producer_handler() when more input is available and
    * TransformVConnection::do_io_shutdown() is called by
    * HttpSM::tunnel_handler_transform_write() when we send our own
@@ -382,9 +435,9 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
 
     TSVIOReenable(transform_data->output_viop);
 
-    /* Avoid failed assert "c->alive == true" in TSContCall() if the content
-     * length is zero or when we get the final chunk of a
-     * "Transfer-Encoding: chunked" response */
+    /* Avoid failed assert "c->alive == true" in TSContCall() if the
+     * content length is zero or when we get the final chunk of a
+     * chunked response */
     if (readerp) {
       TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_COMPLETE, input_viop);
     }
@@ -408,8 +461,9 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
       return 0;
     }
 
-    /* Can't reuse the TSTransformCreate() continuation because we don't know
-     * whether to destroy it in cache_open_write()/cache_open_write_failed() or
+    /* Can't reuse the TSTransformCreate() continuation because we
+     * don't know whether to destroy it in
+     * cache_open_write()/cache_open_write_failed() or
      * transform_vconn_write_complete() */
     contp = TSContCreate(write_handler, NULL);
     TSContDataSet(contp, write_data);
@@ -432,7 +486,8 @@ transform_vconn_write_complete(TSCont contp, void */* edata ATS_UNUSED */)
   return 0;
 }
 
-/* TSTransformCreate() handler: Compute the SHA-256 digest of the content */
+/* TSTransformCreate() handler: Compute the SHA-256 digest of the
+ * content */
 
 static int
 transform_handler(TSCont contp, TSEvent event, void *edata)
@@ -452,8 +507,8 @@ transform_handler(TSCont contp, TSEvent event, void *edata)
   return 0;
 }
 
-/* Compute the SHA-256 digest of the content, write it to the cache and store
- * the request URL at that key */
+/* Compute the SHA-256 digest of the content, write it to the cache
+ * and store the request URL at that key */
 
 static int
 http_read_response_hdr(TSCont /* contp ATS_UNUSED */, void *edata)
@@ -461,8 +516,8 @@ http_read_response_hdr(TSCont /* contp ATS_UNUSED */, void *edata)
   TransformData *data = (TransformData *) TSmalloc(sizeof(TransformData));
   data->txnp = (TSHttpTxn) edata;
 
-  /* Can't initialize data here because we can't call TSVConnWrite() before
-   * TS_HTTP_RESPONSE_TRANSFORM_HOOK */
+  /* Can't initialize data here because we can't call TSVConnWrite()
+   * before TS_HTTP_RESPONSE_TRANSFORM_HOOK */
   data->output_bufp = NULL;
 
   TSVConn connp = TSTransformCreate(transform_handler, data->txnp);
@@ -475,8 +530,8 @@ http_read_response_hdr(TSCont /* contp ATS_UNUSED */, void *edata)
   return 0;
 }
 
-/* Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the "Location: ..." and
- * "Digest: SHA-256=..." headers */
+/* Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the Location and
+ * Digest headers */
 
 /* Read the URL stored at the digest */
 
@@ -515,7 +570,8 @@ cache_open_read_failed(TSCont contp, void */* edata ATS_UNUSED */)
   return 0;
 }
 
-/* TSCacheRead() handler: Check if the URL stored at the digest is cached */
+/* TSCacheRead() handler: Check if the URL stored at the digest is
+ * cached */
 
 static int
 rewrite_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
@@ -525,7 +581,7 @@ rewrite_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
 
   switch (event) {
 
-  /* Yes: Rewrite the "Location: ..." header and reenable the response */
+  /* Yes: Rewrite the Location header and reenable the response */
   case TS_EVENT_CACHE_OPEN_READ:
 
     TSMimeHdrFieldValuesClear(data->resp_bufp, data->hdr_loc, data->location_loc);
@@ -569,8 +625,9 @@ vconn_read_ready(TSCont contp, void */* edata ATS_UNUSED */)
   /* No allocation, freed with data->cache_bufp? */
   const char *value = data->value = TSIOBufferBlockReadStart(blockp, readerp, &data->length);
 
-  /* The start pointer is both an input and an output parameter.  After a
-   * successful parse the start pointer equals the end pointer. */
+  /* The start pointer is both an input and an output parameter.
+   * After a successful parse the start pointer equals the end
+   * pointer. */
   if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + data->length) != TS_PARSE_DONE) {
     TSIOBufferDestroy(data->cache_bufp);
 
@@ -613,8 +670,8 @@ vconn_read_ready(TSCont contp, void */* edata ATS_UNUSED */)
   return 0;
 }
 
-/* TSCacheRead() and TSVConnRead() handler: Check if the "Digest: SHA-256=..."
- * digest already exists in the cache */
+/* TSCacheRead() and TSVConnRead() handler: Check if the digest
+ * already exists in the cache */
 
 static int
 digest_handler(TSCont contp, TSEvent event, void *edata)
@@ -639,7 +696,7 @@ digest_handler(TSCont contp, TSEvent event, void *edata)
   return 0;
 }
 
-/* TSCacheRead() handler: Check if the "Location: ..." URL is already cached */
+/* TSCacheRead() handler: Check if the Location URL is already cached */
 
 static int
 location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
@@ -658,7 +715,7 @@ location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
   case TS_EVENT_CACHE_OPEN_READ:
     break;
 
-  /* No: Check if the "Digest: SHA-256=..." digest already exists in the cache */
+  /* No: Check if the digest already exists in the cache */
   case TS_EVENT_CACHE_OPEN_READ_FAILED:
 
     /* No allocation, freed with data->resp_bufp? */
@@ -670,7 +727,7 @@ location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
 
     TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc);
 
-    /* Check if the "Digest: SHA-256=..." digest already exists in the cache */
+    /* Check if the digest already exists in the cache */
 
     contp = TSContCreate(digest_handler, NULL);
     TSContDataSet(contp, data);
@@ -697,9 +754,9 @@ location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
   return 0;
 }
 
-/* Use TSCacheRead() to check if the URL in the "Location: ..." header is
- * already cached.  If not, potentially rewrite that header.  Do this after
- * responses are cached because the cache will change. */
+/* Use TSCacheRead() to check if the URL in the Location header is
+ * already cached.  If not, potentially rewrite that header.  Do this
+ * after responses are cached because the cache will change. */
 
 static int
 http_send_response_hdr(TSCont contp, void *edata)
@@ -719,20 +776,21 @@ http_send_response_hdr(TSCont contp, void *edata)
     return 0;
   }
 
-  /* If Instance Digests are not provided by the Metalink servers, the Link
-   * header fields pertaining to this specification MUST be ignored */
+  /* If Instance Digests are not provided by the Metalink servers, the
+   * Link header fields pertaining to this specification MUST be
+   * ignored */
 
-  /* Metalinks contain whole file hashes as described in Section 6, and MUST
-   * include SHA-256, as specified in [FIPS-180-3] */
+  /* Metalinks contain whole file hashes as described in Section 6,
+   * and MUST include SHA-256, as specified in [FIPS-180-3] */
 
   /* Assumption: We want to minimize cache reads, so check first that
    *
-   *    1.  the response has a "Location: ..." header and
-   *    2.  the response has a "Digest: SHA-256=..." header.
+   *    1.  the response has a Location header and
+   *    2.  the response has a Digest header.
    *
    * Then scan if the URL or digest already exist in the cache. */
 
-  /* If the response has a "Location: ..." header */
+  /* If the response has a Location header */
   data->location_loc = TSMimeHdrFieldFind(data->resp_bufp, data->hdr_loc, TS_MIME_FIELD_LOCATION, TS_MIME_LEN_LOCATION);
   if (!data->location_loc) {
     TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc);
@@ -745,9 +803,9 @@ http_send_response_hdr(TSCont contp, void *edata)
 
   TSUrlCreate(data->resp_bufp, &data->url_loc);
 
-  /* If we can't parse or lookup the "Location: ..." URL, should we still check
-   * if the response has a "Digest: SHA-256=..." header?  No: Can't parse or
-   * lookup the URL in the "Location: ..." header is an error. */
+  /* If we can't parse or lookup the Location URL, should we still
+   * check if the response has a Digest header?  No: Can't parse or
+   * lookup the URL in the Location header is an error. */
 
   /* No allocation, freed with data->resp_bufp? */
   value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->location_loc, -1, &length);
@@ -777,7 +835,7 @@ http_send_response_hdr(TSCont contp, void *edata)
     return 0;
   }
 
-  /* ... and a "Digest: SHA-256=..." header */
+  /* ... and a Digest header */
   data->digest_loc = TSMimeHdrFieldFind(data->resp_bufp, data->hdr_loc, "Digest", 6);
   while (data->digest_loc) {
 
@@ -790,7 +848,7 @@ http_send_response_hdr(TSCont contp, void *edata)
         continue;
       }
 
-      /* Check if the "Location: ..." URL is already cached */
+      /* Check if the Location URL is already cached */
 
       contp = TSContCreate(location_handler, NULL);
       TSContDataSet(contp, data);
@@ -807,7 +865,7 @@ http_send_response_hdr(TSCont contp, void *edata)
     data->digest_loc = next_loc;
   }
 
-  /* Didn't find a "Digest: SHA-256=..." header, just reenable the response */
+  /* Didn't find a Digest header, just reenable the response */
 
   TSCacheKeyDestroy(data->key);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/chunkedEncoding
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/chunkedEncoding b/plugins/experimental/metalink/test/chunkedEncoding
index 7a2ed37..66c8d9b 100755
--- a/plugins/experimental/metalink/test/chunkedEncoding
+++ b/plugins/experimental/metalink/test/chunkedEncoding
@@ -39,8 +39,9 @@ class factory(http.HTTPFactory):
 
         ctx.write('chunkedEncoding')
 
-        # If the proxy reads the final chunk before it sends the response
-        # headers, it may send a Content-Length header vs. a chunked response
+        # If the proxy reads the final chunk before it sends the
+        # response headers, it may send a Content-Length header vs. a
+        # chunked response
         reactor.callLater(1, ctx.finish)
 
 origin = tcp.Port(0, factory())
@@ -76,13 +77,14 @@ class factory(protocol.ClientFactory):
         # No hope of a final chunk now
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent a Content-Length header vs. a chunked response).
-    # (Override connectionLost() when the proxy crashes or stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent a Content-Length header vs. a chunked
+    # response).  (Override connectionLost() when the proxy crashes or
+    # we stop the reactor.)
     #
-    # Data that was already received will be processed (the end of the
-    # headers), then shutdown events will fire (connections will be closed),
-    # and then finally the reactor will grind to a halt.
+    # Data that was already received will get processed (the end of
+    # the headers), then shutdown events will fire (connections will
+    # get closed), and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/chunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/chunkedEncodingDisconnect b/plugins/experimental/metalink/test/chunkedEncodingDisconnect
index 91593d0..e39549f 100755
--- a/plugins/experimental/metalink/test/chunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/chunkedEncodingDisconnect
@@ -17,8 +17,8 @@
 # permissions and limitations under the License.
 
 print '''1..1 chunkedEncodingDisconnect
-# The proxy closes the client connection and doesn't send a final chunk if the
-# origin disconnects without sending one'''
+# The proxy closes the client connection and doesn't send a final
+# chunk if the origin disconnects without sending one'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -40,9 +40,9 @@ class factory(http.HTTPFactory):
 
         ctx.write('chunkedEncodingDisconnect')
 
-        # If the origin disconnects before the proxy sends the response
-        # headers, the proxy may send a Content-Length header vs. a chunked
-        # response
+        # If the origin disconnects before the proxy sends the
+        # response headers, the proxy may send a Content-Length header
+        # vs. a chunked response
         reactor.callLater(1, ctx.transport.loseConnection)
 
 origin = tcp.Port(0, factory())
@@ -78,10 +78,10 @@ class factory(protocol.ClientFactory):
         # Who cares what happens now?
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent a Content-Length header vs. a chunked response).
-    # (Override connectionLost() when the proxy closes the client connection or
-    # stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent a Content-Length header vs. a chunked
+    # response).  (Override connectionLost() when the proxy closes the
+    # client connection or we stop the reactor.)
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/contentLength
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/contentLength b/plugins/experimental/metalink/test/contentLength
index 92708e7..f53efe7 100755
--- a/plugins/experimental/metalink/test/contentLength
+++ b/plugins/experimental/metalink/test/contentLength
@@ -85,12 +85,13 @@ class factory(protocol.ClientFactory):
 
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message.
-    # (Override connectionLost() when the proxy crashes or stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message.  (Override connectionLost() when the proxy crashes or
+    # we stop the reactor.)
     #
-    # Data that was already received will be processed (the end of the
-    # headers), then shutdown events will fire (connections will be closed),
-    # and then finally the reactor will grind to a halt.
+    # Data that was already received will get processed (the end of
+    # the headers), then shutdown events will fire (connections will
+    # get closed), and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/contentLengthDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/contentLengthDisconnect b/plugins/experimental/metalink/test/contentLengthDisconnect
index 1627d0e..17d927f 100755
--- a/plugins/experimental/metalink/test/contentLengthDisconnect
+++ b/plugins/experimental/metalink/test/contentLengthDisconnect
@@ -17,7 +17,8 @@
 # permissions and limitations under the License.
 
 print '''1..2 contentLengthDisconnect
-# The proxy closes the client connection if the origin disconnects prematurely'''
+# The proxy closes the client connection if the origin disconnects
+# prematurely'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -40,8 +41,9 @@ class factory(http.HTTPFactory):
         ctx.setHeader('Content-Length', 24)
         ctx.write('contentLengthDisconnect')
 
-        # If the origin disconnects before the proxy sends the response
-        # headers, the proxy may send the wrong Content-Length header
+        # If the origin disconnects before the proxy sends the
+        # response headers, the proxy may send the wrong
+        # Content-Length header
         reactor.callLater(1, ctx.transport.loseConnection)
 
 origin = tcp.Port(0, factory())
@@ -80,10 +82,10 @@ class factory(protocol.ClientFactory):
 
         print 'ok 1 - Content-Length header'
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent the wrong Content-Length header).  (Override
-    # connectionLost() when the proxy closes the client connection or stop the
-    # reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent the wrong Content-Length header).
+    # (Override connectionLost() when the proxy closes the client
+    # connection or we stop the reactor.)
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect b/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
index 32011bc..6185e9a 100755
--- a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect
@@ -17,8 +17,8 @@
 # permissions and limitations under the License.
 
 print '''1..1 finalChunkEncodingDisconnect
-# The proxy forwards the final chunk even if the origin disconnects immediately
-# afterward'''
+# The proxy forwards the final chunk even if the origin disconnects
+# immediately afterward'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -40,8 +40,9 @@ class factory(http.HTTPFactory):
 
         ctx.write('finalChunkedEncodingDisconnect')
 
-        # If the proxy reads the final chunk before it sends the response
-        # headers, it may send a Content-Length header vs. a chunked response
+        # If the proxy reads the final chunk before it sends the
+        # response headers, it may send a Content-Length header vs. a
+        # chunked response
         def callback():
           try:
             ctx.finish()
@@ -89,13 +90,14 @@ class factory(protocol.ClientFactory):
         # No hope of a final chunk now
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent a Content-Length header vs. a chunked response).
-    # (Override connectionLost() when the proxy crashes or stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent a Content-Length header vs. a chunked
+    # response).  (Override connectionLost() when the proxy crashes or
+    # we stop the reactor.)
     #
-    # Data that was already received will be processed (the end of the
-    # headers), then shutdown events will fire (connections will be closed),
-    # and then finally the reactor will grind to a halt.
+    # Data that was already received will get processed (the end of
+    # the headers), then shutdown events will fire (connections will
+    # get closed), and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/http09
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/http09 b/plugins/experimental/metalink/test/http09
index e9f7c77..b53d200 100755
--- a/plugins/experimental/metalink/test/http09
+++ b/plugins/experimental/metalink/test/http09
@@ -21,12 +21,13 @@ print '''1..1 http09
 
 # http://www.w3.org/Protocols/HTTP/AsImplemented
 #
-# The proxy crashes only after the response is complete.  It closes the client
-# connection whether it crashes or not because an HTTP/0.9 response is complete
-# only after the origin closes its connection, and then the proxy normally does
-# the same thing to the client connection (although it upgrades the response to
-# HTTP/1.1).  So the only way to check that the proxy didn't crash is to open
-# another connection.
+# The proxy crashes only after the response is complete.  It closes
+# the client connection whether it crashes or not because an HTTP/0.9
+# response is complete only after the origin closes its connection,
+# and then the proxy normally does the same thing to the client
+# connection (although it upgrades the response to HTTP/1.1).  So the
+# only way to check that the proxy didn't crash is to open another
+# connection.
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/location
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/location b/plugins/experimental/metalink/test/location
index 77b601e..97eb32a 100755
--- a/plugins/experimental/metalink/test/location
+++ b/plugins/experimental/metalink/test/location
@@ -72,10 +72,10 @@ class factory(protocol.ClientFactory):
       else:
         print 'not ok 1 - Did the proxy crash?  (The client connection closed.)'
 
-    # Get a response with a Location and a Digest header and check that the
-    # Location header is not rewritten.  Then get the same response after
-    # caching a matching file from a different URL and check that this time the
-    # header is rewritten.
+    # Get a response with a Location and a Digest header and check
+    # that the Location header is not rewritten.  Then get the same
+    # response after caching a matching file from a different URL and
+    # check that this time the header is rewritten.
     connectionMade = lambda ctx: ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\nGET {0}:{1}/location HTTP/1.1\r\n\r\nGET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
 
     def handleResponsePart(ctx, data):

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/longer
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/longer b/plugins/experimental/metalink/test/longer
index 259ad7d..d298451 100755
--- a/plugins/experimental/metalink/test/longer
+++ b/plugins/experimental/metalink/test/longer
@@ -17,10 +17,11 @@
 # permissions and limitations under the License.
 
 print '''1..1 longer
-# The proxy doesn't choke if the origin sends more content than it advertised'''
+# The proxy doesn't choke if the origin sends more content than it
+# advertised'''
 
-# Unlike the contentLength test, don't stop the reactor at the end of the
-# headers.  Give the proxy time to choke.
+# Unlike the contentLength test, don't stop the reactor at the end of
+# the headers.  Give the proxy time to choke.
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -78,12 +79,13 @@ class factory(protocol.ClientFactory):
 
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message.
-    # (Override connectionLost() when the proxy crashes or stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message.  (Override connectionLost() when the proxy crashes or
+    # we stop the reactor.)
     #
-    # Data that was already received will be processed (the end of the
-    # headers), then shutdown events will fire (connections will be closed),
-    # and then finally the reactor will grind to a halt.
+    # Data that was already received will get processed (the end of
+    # the headers), then shutdown events will fire (connections will
+    # get closed), and then finally the reactor will grind to a halt.
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/pipeliningDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/pipeliningDisconnect b/plugins/experimental/metalink/test/pipeliningDisconnect
index 152e2cf..2d97dc1 100755
--- a/plugins/experimental/metalink/test/pipeliningDisconnect
+++ b/plugins/experimental/metalink/test/pipeliningDisconnect
@@ -17,8 +17,8 @@
 # permissions and limitations under the License.
 
 print '''1..1 pipeliningDisconnect
-# The proxy doesn't crash if INKVConnInternal::do_io_close() gets called after
-# a message is already complete'''
+# The proxy doesn't crash if INKVConnInternal::do_io_close() gets
+# called after a message is already complete'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -83,8 +83,8 @@ class factory(protocol.ClientFactory):
     def connectionMade(ctx):
 
       # Somehow these magic words frequently cause
-      # INKVConnInternal::do_io_close() to get called after a message is
-      # already complete
+      # INKVConnInternal::do_io_close() to get called after a message
+      # is already complete
       ctx.transport.write('GET {0}:{1}/pipeliningDisconnect0 HTTP/1.1\r\n\r\nGET {0}:{1}/pipeliningDisconnect1 HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))
       ctx.transport.loseConnection()
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect b/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
index 3c52858..14e5a6f 100755
--- a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
+++ b/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect
@@ -17,9 +17,9 @@
 # permissions and limitations under the License.
 
 print '''1..1 shortChunkedEncodingDisconnect
-# The proxy closes the client connection and doesn't send a final chunk if the
-# origin disconnects without sending one, before the proxy sends the response
-# headers'''
+# The proxy closes the client connection and doesn't send a final
+# chunk if the origin disconnects without sending one, before the
+# proxy sends the response headers'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -77,10 +77,10 @@ class factory(protocol.ClientFactory):
         # Who cares what happens now?
         reactor.stop()
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent a Content-Length header vs. a chunked response).
-    # (Override connectionLost() when the proxy closes the client connection or
-    # stop the reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent a Content-Length header vs. a chunked
+    # response).  (Override connectionLost() when the proxy closes the
+    # client connection or we stop the reactor.)
     def handleResponseEnd(ctx):
       pass
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/shortClientDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortClientDisconnect b/plugins/experimental/metalink/test/shortClientDisconnect
index 6956c78..a36169e 100755
--- a/plugins/experimental/metalink/test/shortClientDisconnect
+++ b/plugins/experimental/metalink/test/shortClientDisconnect
@@ -17,8 +17,8 @@
 # permissions and limitations under the License.
 
 print '''1..1 shortClientDisconnect
-# The proxy doesn't crash if the client disconnects before the proxy sends the
-# response headers'''
+# The proxy doesn't crash if the client disconnects before the proxy
+# sends the response headers'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a9a0b7cc/plugins/experimental/metalink/test/shortContentLengthDisconnect
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/shortContentLengthDisconnect b/plugins/experimental/metalink/test/shortContentLengthDisconnect
index 5662650..b2a74fa 100755
--- a/plugins/experimental/metalink/test/shortContentLengthDisconnect
+++ b/plugins/experimental/metalink/test/shortContentLengthDisconnect
@@ -17,9 +17,9 @@
 # permissions and limitations under the License.
 
 print '''1..2 shortContentLengthDisconnect
-# The proxy sends the right Content-Length header and closes the client
-# connection if the origin disconnects before the proxy sends the response
-# headers'''
+# The proxy sends the right Content-Length header and closes the
+# client connection if the origin disconnects before the proxy sends
+# the response headers'''
 
 from twisted.internet import error, protocol, reactor, tcp
 from twisted.web import http
@@ -81,10 +81,10 @@ class factory(protocol.ClientFactory):
 
         print 'ok 1 - Content-Length header'
 
-    # Avoid calling undefined handleResponse() at the end of the message (if
-    # the proxy sent the wrong Content-Length header).  (Override
-    # connectionLost() when the proxy closes the client connection or stop the
-    # reactor.)
+    # Avoid calling undefined handleResponse() at the end of the
+    # message (if the proxy sent the wrong Content-Length header).
+    # (Override connectionLost() when the proxy closes the client
+    # connection or we stop the reactor.)
     def handleResponseEnd(ctx):
       pass
 


[06/13] git commit: TS-2675: metalink: Reuse TSCacheWrite() vs. TSTransformCreate() continuation

Posted by jp...@apache.org.
TS-2675: metalink: Reuse TSCacheWrite() vs. TSTransformCreate() continuation


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/d25b00c2
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/d25b00c2
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/d25b00c2

Branch: refs/heads/master
Commit: d25b00c2f82701f8de51cc96d941049c2f63b739
Parents: 441c1c5
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 11:57:17 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 plugins/experimental/metalink/metalink.cc | 166 +++++++++++++------------
 1 file changed, 87 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d25b00c2/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 238bbee..77f62dc 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -49,16 +49,20 @@
  *
  * [wiki page]  https://cwiki.apache.org/confluence/display/TS/Metalink */
 
-/* TSVConnWrite() data: Store the request URL */
+/* TSCacheWrite() and TSVConnWrite() data: Write the digest to the cache and
+ * store the request URL at that key */
 
 typedef struct {
+  TSHttpTxn txnp;
+
+  TSCacheKey key;
+
   TSVConn connp;
   TSIOBuffer cache_bufp;
 
 } WriteData;
 
-/* TSTransformCreate() and TSCacheWrite() data: Compute the SHA-256 digest of
- * the content and write it to the cache */
+/* TSTransformCreate() data: Compute the SHA-256 digest of the content */
 
 typedef struct {
   TSHttpTxn txnp;
@@ -70,8 +74,6 @@ typedef struct {
   /* Message digest handle */
   SHA256_CTX c;
 
-  TSCacheKey key;
-
 } TransformData;
 
 /* TSCacheRead() and TSVConnRead() data: Check the "Location: ..." and
@@ -102,43 +104,7 @@ typedef struct {
 
 /* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transform */
 
-/* Store the request URL */
-
-static int
-write_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
-{
-  WriteData *data = (WriteData *) TSContDataGet(contp);
-  TSContDestroy(contp);
-
-  /* The object is not committed to the cache until the vconnection is closed.
-   * When all the data has been transferred, the user (contp) must do a
-   * TSVConnClose() */
-  TSVConnClose(data->connp);
-
-  TSIOBufferDestroy(data->cache_bufp);
-  TSfree(data);
-
-  return 0;
-}
-
-/* TSVConnWrite() handler: Store the request URL */
-
-static int
-write_handler(TSCont contp, TSEvent event, void *edata)
-{
-  switch (event) {
-  case TS_EVENT_VCONN_WRITE_COMPLETE:
-    return write_vconn_write_complete(contp, edata);
-
-  default:
-    TSAssert(!"Unexpected event");
-  }
-
-  return 0;
-}
-
-/* Compute the SHA-256 digest of the content, write it to the cache and store
- * the request URL at that key */
+/* Write the digest to the cache and store the request URL at that key */
 
 static int
 cache_open_write(TSCont contp, void *edata)
@@ -151,22 +117,26 @@ cache_open_write(TSCont contp, void *edata)
   const char *value;
   int length;
 
-  TransformData *transform_data = (TransformData *) TSContDataGet(contp);
-  TSContDestroy(contp);
+  WriteData *data = (WriteData *) TSContDataGet(contp);
+  data->connp = (TSVConn) edata;
 
-  TSCacheKeyDestroy(transform_data->key);
+  TSCacheKeyDestroy(data->key);
 
-  if (TSHttpTxnClientReqGet(transform_data->txnp, &req_bufp, &hdr_loc) != TS_SUCCESS) {
+  if (TSHttpTxnClientReqGet(data->txnp, &req_bufp, &hdr_loc) != TS_SUCCESS) {
     TSError("Couldn't retrieve client request header");
 
-    TSfree(transform_data);
+    TSContDestroy(contp);
+
+    TSfree(data);
 
     return 0;
   }
 
-  TSfree(transform_data);
-
   if (TSHttpHdrUrlGet(req_bufp, hdr_loc, &url_loc) != TS_SUCCESS) {
+    TSContDestroy(contp);
+
+    TSfree(data);
+
     TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, hdr_loc);
 
     return 0;
@@ -174,6 +144,10 @@ cache_open_write(TSCont contp, void *edata)
 
   value = TSUrlStringGet(req_bufp, url_loc, &length);
   if (!value) {
+    TSContDestroy(contp);
+
+    TSfree(data);
+
     TSHandleMLocRelease(req_bufp, hdr_loc, url_loc);
     TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, hdr_loc);
 
@@ -185,20 +159,13 @@ cache_open_write(TSCont contp, void *edata)
 
   /* Store the request URL */
 
-  WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
-  write_data->connp = (TSVConn) edata;
-
-  /* Can't reuse TSTransformCreate() continuation because it already implements
-   * TS_EVENT_VCONN_WRITE_COMPLETE */
-  contp = TSContCreate(write_handler, NULL);
-  TSContDataSet(contp, write_data);
-
-  write_data->cache_bufp = TSIOBufferCreate();
-  TSIOBufferReader readerp = TSIOBufferReaderAlloc(write_data->cache_bufp);
+  data->cache_bufp = TSIOBufferCreate();
+  TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp);
 
-  int nbytes = TSIOBufferWrite(write_data->cache_bufp, value, length);
+  int nbytes = TSIOBufferWrite(data->cache_bufp, value, length);
 
-  TSVConnWrite(write_data->connp, contp, readerp, nbytes);
+  /* Reuse the TSCacheWrite() continuation */
+  TSVConnWrite(data->connp, contp, readerp, nbytes);
 
   return 0;
 }
@@ -208,7 +175,7 @@ cache_open_write(TSCont contp, void *edata)
 static int
 cache_open_write_failed(TSCont contp, void * /* edata ATS_UNUSED */)
 {
-  TransformData *data = (TransformData *) TSContDataGet(contp);
+  WriteData *data = (WriteData *) TSContDataGet(contp);
   TSContDestroy(contp);
 
   TSCacheKeyDestroy(data->key);
@@ -217,6 +184,46 @@ cache_open_write_failed(TSCont contp, void * /* edata ATS_UNUSED */)
   return 0;
 }
 
+static int
+write_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
+{
+  WriteData *data = (WriteData *) TSContDataGet(contp);
+  TSContDestroy(contp);
+
+  /* The object is not committed to the cache until the vconnection is closed.
+   * When all the data has been transferred, the user (contp) must do a
+   * TSVConnClose() */
+  TSVConnClose(data->connp);
+
+  TSIOBufferDestroy(data->cache_bufp);
+  TSfree(data);
+
+  return 0;
+}
+
+/* TSCacheWrite() and TSVConnWrite() handler: Write the digest to the cache and
+ * store the request URL at that key */
+
+static int
+write_handler(TSCont contp, TSEvent event, void *edata)
+{
+  switch (event) {
+  case TS_EVENT_CACHE_OPEN_WRITE:
+    return cache_open_write(contp, edata);
+
+  case TS_EVENT_CACHE_OPEN_WRITE_FAILED:
+    return cache_open_write_failed(contp, edata);
+
+  case TS_EVENT_VCONN_WRITE_COMPLETE:
+    return write_vconn_write_complete(contp, edata);
+
+  default:
+    TSAssert(!"Unexpected event");
+  }
+
+  return 0;
+}
+
 /* Copy content from the input buffer to the output buffer without modification
  * while at the same time feeding it to the message digest */
 
@@ -335,40 +342,41 @@ transform_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
 {
   char digest[32];
 
-  TransformData *data = (TransformData *) TSContDataGet(contp);
+  TransformData *transform_data = (TransformData *) TSContDataGet(contp);
+  TSContDestroy(contp);
 
-  TSIOBufferDestroy(data->output_bufp);
+  TSIOBufferDestroy(transform_data->output_bufp);
 
-  SHA256_Final((unsigned char *) digest, &data->c);
+  SHA256_Final((unsigned char *) digest, &transform_data->c);
 
-  data->key = TSCacheKeyCreate();
-  if (TSCacheKeyDigestSet(data->key, digest, sizeof(digest)) != TS_SUCCESS) {
-    TSContDestroy(contp);
+  WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
+  write_data->txnp = transform_data->txnp;
 
-    TSCacheKeyDestroy(data->key);
-    TSfree(data);
+  TSfree(transform_data);
+
+  write_data->key = TSCacheKeyCreate();
+  if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) {
+
+    TSCacheKeyDestroy(write_data->key);
+    TSfree(write_data);
 
     return 0;
   }
 
-  /* Reuse the TSTransformCreate() continuation */
-  TSCacheWrite(contp, data->key);
+  contp = TSContCreate(write_handler, NULL);
+  TSContDataSet(contp, write_data);
+
+  TSCacheWrite(contp, write_data->key);
 
   return 0;
 }
 
-/* TSTransformCreate() and TSCacheWrite() handler */
+/* TSTransformCreate() handler: Compute the SHA-256 digest of the content */
 
 static int
 transform_handler(TSCont contp, TSEvent event, void *edata)
 {
   switch (event) {
-  case TS_EVENT_CACHE_OPEN_WRITE:
-    return cache_open_write(contp, edata);
-
-  case TS_EVENT_CACHE_OPEN_WRITE_FAILED:
-    return cache_open_write_failed(contp, edata);
-
   case TS_EVENT_IMMEDIATE:
   case TS_EVENT_VCONN_WRITE_READY:
     return vconn_write_ready(contp, edata);


[02/13] git commit: Update CHANGES for TS-2675

Posted by jp...@apache.org.
Update CHANGES for TS-2675


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/ad6806ea
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/ad6806ea
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/ad6806ea

Branch: refs/heads/master
Commit: ad6806ea71218e760e64e658909bd202177e65de
Parents: a9a0b7c
Author: James Peach <jp...@apache.org>
Authored: Fri Mar 28 16:22:07 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 CHANGES | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ad6806ea/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 3523452..f3b6149 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.0.0
 
+  *) [TS-2675] metalink: Fix crash and plug memory leaks.
+   Author: Jack Bates <ja...@nottheoilrig.com>
+
   *) [TS-2674] Remove debug printf() from traffic_top.
 
   *) [TS-2652] atscppapi: Providing a cancel() in asyncproviders 


[13/13] git commit: TS-2675: metalink: Improve comments and whitespace

Posted by jp...@apache.org.
TS-2675: metalink: Improve comments and whitespace


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/ea2f6f38
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/ea2f6f38
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/ea2f6f38

Branch: refs/heads/master
Commit: ea2f6f3836221727c43be2257028a2c2ad5c2966
Parents: f88a726
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Thu Mar 13 14:48:28 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700

----------------------------------------------------------------------
 doc/reference/plugins/metalink.en.rst     |   6 +-
 plugins/experimental/metalink/metalink.cc | 183 +++++++++++++++----------
 2 files changed, 115 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ea2f6f38/doc/reference/plugins/metalink.en.rst
----------------------------------------------------------------------
diff --git a/doc/reference/plugins/metalink.en.rst b/doc/reference/plugins/metalink.en.rst
index 8ba10dc..50e1b32 100644
--- a/doc/reference/plugins/metalink.en.rst
+++ b/doc/reference/plugins/metalink.en.rst
@@ -79,8 +79,8 @@ cache can change after responses are cached.  It uses
 plugin should also check if the URL is fresh or not.
 
 The plugin implements the ``TS_HTTP_READ_RESPONSE_HDR_HOOK`` hook and
-`a null transform`_ to compute the SHA-256 digest for content as it's
-added to the cache.  It uses SHA256_Init(), SHA256_Update(), and
+`a null transformation`_ to compute the SHA-256 digest for content as
+it's added to the cache.  It uses SHA256_Init(), SHA256_Update(), and
 SHA256_Final() from OpenSSL to compute the digest, then it uses
 :c:func:`TSCacheWrite` to associate the digest with the request URL.
 This adds a new cache object where the key is the digest and the
@@ -121,5 +121,5 @@ rel=duplicate` headers MUST be ignored:
 
 .. _Metalink:    http://en.wikipedia.org/wiki/Metalink
 
-.. _a null transform:
+.. _a null transformation:
                  /sdk/http-transformation-plugin/sample-null-transformation-plugin

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ea2f6f38/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index c7fafcc..3ad589d 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -1,34 +1,25 @@
 /** @file
-
-    Implement the Metalink protocol to "dedup" cache entries for
-    equivalent content. This can for example improve the cache hit
-    ratio for content with many different (unique) URLs.
-
-    @section license License
-
-    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
-    "License"); 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 "AS IS" 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.
-*/
-
-
-/*
-  This plugin was originally developed by Jack Bates during his Google
-  Summer of Code 2012 project for Metalinker.
-*/
-
+ *
+ * Try not to download the same file twice.  Improve cache efficiency
+ * and speed up downloads.
+ *
+ * @section license License
+ *
+ * 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 "License"); 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 "AS IS" 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. */
 
 #include <strings.h>
 
@@ -36,7 +27,7 @@
 
 #include "ts/ts.h"
 
-/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transform.
+/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transformation.
  * Compute the SHA-256 digest of the content, write it to the cache and store
  * the request URL at that key.
  *
@@ -47,7 +38,7 @@
  *
  * More details are on the [wiki page] in the Traffic Server wiki.
  *
- * [wiki page]  https://cwiki.apache.org/confluence/display/TS/Metalink */
+ *    [wiki page]   https://cwiki.apache.org/confluence/display/TS/Metalink */
 
 /* TSCacheWrite() and TSVConnWrite() data: Write the digest to the cache and
  * store the request URL at that key */
@@ -67,7 +58,7 @@ typedef struct {
 typedef struct {
   TSHttpTxn txnp;
 
-  /* Null transform */
+  /* Null transformation */
   TSIOBuffer output_bufp;
   TSVIO output_viop;
 
@@ -105,7 +96,7 @@ typedef struct {
 
 } SendData;
 
-/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transform */
+/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null transformation */
 
 /* Write the digest to the cache and store the request URL at that key */
 
@@ -179,7 +170,7 @@ cache_open_write(TSCont contp, void *edata)
 /* Do nothing */
 
 static int
-cache_open_write_failed(TSCont contp, void * /* edata ATS_UNUSED */)
+cache_open_write_failed(TSCont contp, void */* edata ATS_UNUSED */)
 {
   WriteData *data = (WriteData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -191,7 +182,7 @@ cache_open_write_failed(TSCont contp, void * /* edata ATS_UNUSED */)
 }
 
 static int
-write_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
+write_vconn_write_complete(TSCont contp, void */* edata ATS_UNUSED */)
 {
   WriteData *data = (WriteData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -233,26 +224,64 @@ write_handler(TSCont contp, TSEvent event, void *edata)
 /* Copy content from the input buffer to the output buffer without modification
  * and feed it through the message digest at the same time.
  *
- *   1. Check if any more input is possible before doing anything else to avoid
- *      failed asserts.
- *   2. Then deal with any input that's available now.
- *   3. Check if the input is complete after dealing with any available input
- *      in case it was the last of it.  If it is complete, do any bookkeeping
- *      that downstream needs and finish computing the digest.  Otherwise
- *      either wait for more input or abort if no more input is possible.
+ *    1.  Check if we are "closed" before doing anything else to avoid errors.
+ *    2.  Then deal with any input that's available now.
+ *    3.  Check if the input is complete after dealing with any available input
+ *        in case it was the last of it.  If it is complete, tell downstream,
+ *        thank upstream, and finish computing the digest.  Otherwise either
+ *        wait for more input or abort if upstream is "closed".
  *
- * Events are sent from downstream and don't communicate the state of the input
- * (TS_EVENT_VCONN_WRITE_READY, TS_EVENT_VCONN_WRITE_COMPLETE, and
- * TS_EVENT_IMMEDIATE?) Clean up the output buffer on
- * TS_EVENT_VCONN_WRITE_COMPLETE and not before.
+ * The handler is guaranteed to get called at least once, even if the response
+ * is 304 Not Modified, so we are guaranteed an opportunity to clean up e.g.
+ * data that we allocated when we called TSTransformCreate().
  *
- * Gather the state of the input from TSVIONTodoGet() and TSVIOReaderGet().
- * TSVIOReaderGet() is NULL when no more input is possible and the input is
- * complete only when TSVIONTodoGet() is zero.  Handle the end of the input
- * independently from the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream. */
+ * TS_EVENT_VCONN_WRITE_READY and TS_EVENT_VCONN_WRITE_COMPLETE events are sent
+ * from downstream, e.g. by TransformTerminus::handle_event().
+ * TS_EVENT_IMMEDIATE events are sent by INKVConnInternal::do_io_write(),
+ * INKVConnInternal::do_io_close(), and INKVConnInternal::reenable() which are
+ * called from upstream, e.g. by TransformVConnection::do_io_write(),
+ * TransformVConnection::do_io_close(), and HttpTunnel::producer_handler().
+ *
+ * Clean up the output buffer on TS_EVENT_VCONN_WRITE_COMPLETE and not before.
+ * We are guaranteed a TS_EVENT_VCONN_WRITE_COMPLETE event *unless* we are
+ * "closed".  In that case we instead get a TS_EVENT_IMMEDIATE event where
+ * TSVConnClosedGet() is one, so clean up the output buffer in that case as
+ * well.  We'll only ever get one event where TSVConnClosedGet() is one and it
+ * will be our last, so there's no risk of a double free.
+ *
+ * The response headers get sent when TSVConnWrite() gets called and not
+ * before.  (We could potentially edit them until then.)
+ *
+ * The events say nothing about the state of the input.  Gather this instead
+ * from TSVConnClosedGet(), TSVIOReaderGet(), and TSVIONTodoGet() and handle
+ * the end of the input independently from the TS_EVENT_VCONN_WRITE_COMPLETE
+ * event from downstream.
+ *
+ * When TSVConnClosedGet() is one, *we* are "closed".  Some state is already
+ * inconsistent and there's nothing to do except clean up.  (This happens when
+ * the response is 304 Not Modified or when the client or origin disconnect
+ * before the message is complete.)
+ *
+ * When TSVIOReaderGet() is NULL, upstream is "closed".  In that case it's
+ * clearly an error to call TSIOBufferReaderAvail(), it's also an error at that
+ * point to send any events upstream with TSContCall().  (This happens when the
+ * content length is zero or when we get the final chunk of a
+ * "Transfer-Encoding: chunked" response.)
+ *
+ * The input is complete only when TSVIONTodoGet() is zero.  (Don't update the
+ * downstream nbytes otherwise!)  Update the downstream nbytes when the input
+ * is complete in case the response is "Transfer-Encoding: chunked" (in which
+ * case nbytes is unknown until then).  Downstream will (normally) send the
+ * TS_EVENT_VCONN_WRITE_COMPLETE event (and the final chunk if the response is
+ * "Transfer-Encoding: chunked") when ndone equals nbytes and not before.
+ *
+ * Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream when the input is
+ * complete otherwise HttpSM::update_stats() won't get called and the
+ * transaction won't get logged.  (If there are upstream transformations they
+ * won't get a chance to clean up otherwise!) */
 
 static int
-vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
+vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
 {
   const char *value;
   int64_t length;
@@ -261,6 +290,10 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
   TransformData *transform_data = (TransformData *) TSContDataGet(contp);
 
+  /* Check if we are "closed" before doing anything else to avoid errors.  Some
+   * state is already inconsistent and there's nothing to do except clean up.
+   * (This happens if the response is 304 Not Modified or if the client or
+   * origin disconnect before the message is complete.) */
   int closed = TSVConnClosedGet(contp);
   if (closed) {
     TSContDestroy(contp);
@@ -278,7 +311,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
   TSVIO input_viop = TSVConnWriteVIOGet(contp);
 
-  /* Initialize data here because can't call TSVConnWrite() before
+  /* Initialize data here because we can't call TSVConnWrite() before
    * TS_HTTP_RESPONSE_TRANSFORM_HOOK */
   if (!transform_data->output_bufp) {
     TSVConn output_connp = TSTransformOutputVConnGet(contp);
@@ -296,9 +329,10 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     SHA256_Init(&transform_data->c);
   }
 
-  /* Avoid failed assert "sdk_sanity_check_iocore_structure(readerp) ==
-   * TS_SUCCESS" in TSIOBufferReaderAvail() if the client or origin disconnect
-   * or the content length is zero */
+  /* Then deal with any input that's available now.  Avoid failed assert
+   * "sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS" in
+   * TSIOBufferReaderAvail() if the content length is zero or when we get the
+   * final chunk of a "Transfer-Encoding: chunked" response. */
   TSIOBufferReader readerp = TSVIOReaderGet(input_viop);
   if (readerp) {
 
@@ -325,6 +359,8 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
     }
   }
 
+  /* Check if the input is complete after dealing with any available input in
+   * case it was the last of it */
   int ntodo = TSVIONTodoGet(input_viop);
   if (ntodo) {
     TSVIOReenable(transform_data->output_viop);
@@ -338,6 +374,9 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 
     TSVIOReenable(transform_data->output_viop);
 
+    /* Avoid failed assert "c->alive == true" in TSContCall() if the content
+     * length is zero or when we get the final chunk of a
+     * "Transfer-Encoding: chunked" response */
     if (readerp) {
       TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_COMPLETE, input_viop);
     }
@@ -358,7 +397,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
       return 0;
     }
 
-    /* Can't reuse the TSTransformCreate() continuation because don't know
+    /* Can't reuse the TSTransformCreate() continuation because we don't know
      * whether to destroy it in cache_open_write()/cache_open_write_failed() or
      * transform_vconn_write_complete() */
     contp = TSContCreate(write_handler, NULL);
@@ -371,7 +410,7 @@ vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */)
 }
 
 static int
-transform_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */)
+transform_vconn_write_complete(TSCont contp, void */* edata ATS_UNUSED */)
 {
   TransformData *data = (TransformData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -411,7 +450,7 @@ http_read_response_hdr(TSCont /* contp ATS_UNUSED */, void *edata)
   TransformData *data = (TransformData *) TSmalloc(sizeof(TransformData));
   data->txnp = (TSHttpTxn) edata;
 
-  /* Can't initialize data here because can't call TSVConnWrite() before
+  /* Can't initialize data here because we can't call TSVConnWrite() before
    * TS_HTTP_RESPONSE_TRANSFORM_HOOK */
   data->output_bufp = NULL;
 
@@ -434,6 +473,7 @@ static int
 cache_open_read(TSCont contp, void *edata)
 {
   SendData *data = (SendData *) TSContDataGet(contp);
+
   TSVConn connp = (TSVConn) edata;
 
   data->cache_bufp = TSIOBufferCreate();
@@ -447,7 +487,7 @@ cache_open_read(TSCont contp, void *edata)
 /* Do nothing, just reenable the response */
 
 static int
-cache_open_read_failed(TSCont contp, void * /* edata ATS_UNUSED */)
+cache_open_read_failed(TSCont contp, void */* edata ATS_UNUSED */)
 {
   SendData *data = (SendData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -467,7 +507,7 @@ cache_open_read_failed(TSCont contp, void * /* edata ATS_UNUSED */)
 /* TSCacheRead() handler: Check if the URL stored at the digest is cached */
 
 static int
-rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
+rewrite_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
 {
   SendData *data = (SendData *) TSContDataGet(contp);
   TSContDestroy(contp);
@@ -506,13 +546,13 @@ rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
 /* Read the URL stored at the digest */
 
 static int
-vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */)
+vconn_read_ready(TSCont contp, void */* edata ATS_UNUSED */)
 {
   SendData *data = (SendData *) TSContDataGet(contp);
-
   TSContDestroy(contp);
 
   TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp);
+
   TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
 
   /* No allocation, freed with data->cache_bufp? */
@@ -591,7 +631,7 @@ digest_handler(TSCont contp, TSEvent event, void *edata)
 /* TSCacheRead() handler: Check if the "Location: ..." URL is already cached */
 
 static int
-location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
+location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
 {
   const char *value;
   int length;
@@ -602,6 +642,7 @@ location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
   TSContDestroy(contp);
 
   switch (event) {
+
   /* Yes: Do nothing, just reenable the response */
   case TS_EVENT_CACHE_OPEN_READ:
     break;
@@ -656,8 +697,8 @@ http_send_response_hdr(TSCont contp, void *edata)
   int length;
 
   SendData *data = (SendData *) TSmalloc(sizeof(SendData));
-
   data->txnp = (TSHttpTxn) edata;
+
   if (TSHttpTxnClientRespGet(data->txnp, &data->resp_bufp, &data->hdr_loc) != TS_SUCCESS) {
     TSError("Couldn't retrieve client response header");
 
@@ -673,12 +714,12 @@ http_send_response_hdr(TSCont contp, void *edata)
   /* Metalinks contain whole file hashes as described in Section 6, and MUST
    * include SHA-256, as specified in [FIPS-180-3] */
 
-  /* Assumption: Want to minimize cache read, so check first that:
+  /* Assumption: We want to minimize cache reads, so check first that
    *
-   *   1. response has a "Location: ..." header
-   *   2. response has a "Digest: SHA-256=..." header
+   *    1.  the response has a "Location: ..." header and
+   *    2.  the response has a "Digest: SHA-256=..." header.
    *
-   * Then scan if the URL or digest already exist in the cache */
+   * Then scan if the URL or digest already exist in the cache. */
 
   /* If the response has a "Location: ..." header */
   data->location_loc = TSMimeHdrFieldFind(data->resp_bufp, data->hdr_loc, TS_MIME_FIELD_LOCATION, TS_MIME_LEN_LOCATION);
@@ -693,8 +734,8 @@ http_send_response_hdr(TSCont contp, void *edata)
 
   TSUrlCreate(data->resp_bufp, &data->url_loc);
 
-  /* If can't parse or lookup the "Location: ..." URL, should still check if
-   * the response has a "Digest: SHA-256=..." header?  No: Can't parse or
+  /* If we can't parse or lookup the "Location: ..." URL, should we still check
+   * if the response has a "Digest: SHA-256=..." header?  No: Can't parse or
    * lookup the URL in the "Location: ..." header is an error. */
 
   /* No allocation, freed with data->resp_bufp? */