You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by no...@apache.org on 2014/07/22 17:50:40 UTC

[2/2] git commit: TS-2939 Metalink: Fix crash when checking the digest of a file that wasn't cacheable

TS-2939 Metalink: Fix crash when checking the digest of a file that wasn't cacheable


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

Branch: refs/heads/master
Commit: fd7365db20cda8d0ef120723f22baed0afb64288
Parents: 74a9a6b
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Wed Jul 16 13:50:56 2014 -0700
Committer: Jack Bates <ja...@nottheoilrig.com>
Committed: Tue Jul 22 08:39:20 2014 -0700

----------------------------------------------------------------------
 CHANGES                                         |   7 +-
 plugins/experimental/metalink/metalink.cc       |  22 ++--
 plugins/experimental/metalink/test/location     |   4 +
 plugins/experimental/metalink/test/notCacheable | 104 +++++++++++++++++++
 4 files changed, 129 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fd7365db/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index e5baca6..48c127b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.1.0
 
+  *) [TS-2939] Metalink: Fix crash when checking the digest of a file
+   that wasn't cacheable
+
   *) [TS-2922] Support the new ppc64le platform. Author: Breno Leitao
 
   *) [TS-2944] Remove the proxy.config.http.record_tcp_mem_hit configuration variable.
@@ -426,7 +429,7 @@ Changes with Apache Traffic Server 5.0.0
 
   *) [TS-2679] background_fetch plugin can use uninitialized cont pointer.
 
-  *) [TS-2675] metalink: Fix crash and plug memory leaks.
+  *) [TS-2675] Metalink: Fix crash and plug memory leaks.
    Author: Jack Bates <ja...@nottheoilrig.com>
 
   *) [TS-2674] Remove debug printf() from traffic_top.
@@ -1468,7 +1471,7 @@ Changes with Apache Traffic Server 3.3.3 (never released)
 
   *) [TS-1925] Remove obsolete MMH hash API.
 
-  *) [TS-1924] Add metalink plugin documentation.
+  *) [TS-1924] Add Metalink plugin documentation.
     Author: Jack Bates <ja...@nottheoilrig.com>
 
   *) [TS-1913] Fix memory issue caused by resolve_logfield_string()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fd7365db/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 6461121..6c13df8 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -90,6 +90,7 @@ typedef struct {
   /* Digest header field value index */
   int idx;
 
+  TSVConn connp;
   TSIOBuffer cache_bufp;
 
   const char *value;
@@ -163,7 +164,7 @@ cache_open_write(TSCont contp, void *edata)
 
   TSfree(value);
 
-  /* Reuse the TSCacheWrite() continuation */
+  /* Reentrant!  Reuse the TSCacheWrite() continuation. */
   TSVConnWrite(data->connp, contp, readerp, nbytes);
 
   return 0;
@@ -377,7 +378,8 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
 
     /* Determines the Content-Length header (or a chunked response) */
 
-    /* Avoid failed assert "nbytes >= 0" if the response is chunked */
+    /* Reentrant!  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);
 
@@ -471,6 +473,7 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
     contp = TSContCreate(write_handler, NULL);
     TSContDataSet(contp, write_data);
 
+    /* Reentrant! */
     TSCacheWrite(contp, write_data->key);
   }
 
@@ -542,13 +545,12 @@ static int
 cache_open_read(TSCont contp, void *edata)
 {
   SendData *data = (SendData *) TSContDataGet(contp);
-
-  TSVConn connp = (TSVConn) edata;
+  data->connp = (TSVConn) edata;
 
   data->cache_bufp = TSIOBufferCreate();
 
-  /* Reuse the TSCacheRead() continuation */
-  TSVConnRead(connp, contp, data->cache_bufp, INT64_MAX);
+  /* Reentrant!  Reuse the TSCacheRead() continuation. */
+  TSVConnRead(data->connp, contp, data->cache_bufp, INT64_MAX);
 
   return 0;
 }
@@ -621,6 +623,8 @@ vconn_read_ready(TSCont contp, void */* edata ATS_UNUSED */)
   SendData *data = (SendData *) TSContDataGet(contp);
   TSContDestroy(contp);
 
+  TSVConnClose(data->connp);
+
   TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp);
 
   TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
@@ -668,6 +672,10 @@ vconn_read_ready(TSCont contp, void */* edata ATS_UNUSED */)
   contp = TSContCreate(rewrite_handler, NULL);
   TSContDataSet(contp, data);
 
+  /* Reentrant!  (Particularly in case of a cache miss.)
+   * rewrite_handler() will clean up the TSVConnRead() buffer so be
+   * sure to close this virtual connection or CacheVC::openReadMain()
+   * will continue operating on it! */
   TSCacheRead(contp, data->key);
 
   return 0;
@@ -735,6 +743,7 @@ location_handler(TSCont contp, TSEvent event, void */* edata ATS_UNUSED */)
     contp = TSContCreate(digest_handler, NULL);
     TSContDataSet(contp, data);
 
+    /* Reentrant! */
     TSCacheRead(contp, data->key);
 
     return 0;
@@ -857,6 +866,7 @@ http_send_response_hdr(TSCont contp, void *edata)
       contp = TSContCreate(location_handler, NULL);
       TSContDataSet(contp, data);
 
+      /* Reentrant! */
       TSCacheRead(contp, data->key);
 
       return 0;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fd7365db/plugins/experimental/metalink/test/location
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/location b/plugins/experimental/metalink/test/location
index b1f4710..6e293a6 100755
--- a/plugins/experimental/metalink/test/location
+++ b/plugins/experimental/metalink/test/location
@@ -39,6 +39,10 @@ class factory(http.HTTPFactory):
 
         if target == '/location':
 
+          # Satisfy every case of
+          # proxy.config.http.cache.required_headers
+          ctx.setHeader('Cache-Control', 'max-age=1')
+
           ctx.write('location')
           ctx.finish()
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fd7365db/plugins/experimental/metalink/test/notCacheable
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/notCacheable b/plugins/experimental/metalink/test/notCacheable
new file mode 100755
index 0000000..33d8184
--- /dev/null
+++ b/plugins/experimental/metalink/test/notCacheable
@@ -0,0 +1,104 @@
+#!/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 notCacheable
+# The digest of a file that wasn't cacheable doesn't crash the proxy'''
+
+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 == '/notCacheable':
+
+          ctx.write('notCacheable')
+          ctx.finish()
+
+        else:
+
+          ctx.setHeader('Digest', 'SHA-256=BSg5n9c6XBC3jySKsXViB71jhPIoRo3AbCC/gtNlt6k=')
+          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.)'
+
+    def connectionMade(ctx):
+
+      # A cache MUST NOT store a response to any request, unless: The
+      # request method is understood by the cache and defined as being
+      # cacheable,
+      ctx.transport.write('NOTCACHEABLE {0}:{1}/notCacheable 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 handleStatus(version, status, message):
+        print 'ok 1 - The proxy didn\'t crash (got a response status)'
+
+        reactor.stop()
+
+      ctx.handleStatus = handleStatus
+
+tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()
+
+reactor.run()