You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2015/08/06 06:06:37 UTC

[01/14] trafficserver git commit: TS-3782: Add normal scenario tests for HTTP/2

Repository: trafficserver
Updated Branches:
  refs/heads/6.0.x 252eb2131 -> 1c2ea99cf


TS-3782: Add normal scenario tests for HTTP/2


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

Branch: refs/heads/6.0.x
Commit: 1cbe7c70bf81b6ba678070670da649de510b7991
Parents: d308606
Author: Masaori Koshiba <mk...@yahoo-corp.jp>
Authored: Mon Aug 3 14:27:04 2015 +0900
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Tue Aug 4 20:14:08 2015 -0600

----------------------------------------------------------------------
 ci/tsqa/requirements.txt    |  1 +
 ci/tsqa/tests/test_http2.py | 98 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1cbe7c70/ci/tsqa/requirements.txt
----------------------------------------------------------------------
diff --git a/ci/tsqa/requirements.txt b/ci/tsqa/requirements.txt
index 5897503..0a44708 100644
--- a/ci/tsqa/requirements.txt
+++ b/ci/tsqa/requirements.txt
@@ -4,3 +4,4 @@
 https://github.com/apache/trafficserver-qa/archive/master.zip
 pyyaml
 pyOpenSSL
+hyper; python_version >= '2.7'

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1cbe7c70/ci/tsqa/tests/test_http2.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_http2.py b/ci/tsqa/tests/test_http2.py
new file mode 100644
index 0000000..732df6c
--- /dev/null
+++ b/ci/tsqa/tests/test_http2.py
@@ -0,0 +1,98 @@
+#  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.
+import logging
+import os
+
+import helpers
+
+import tsqa.endpoint
+import tsqa.test_cases
+import tsqa.utils
+
+try:
+    import hyper
+except ImportError as e:
+    helpers.unittest.SkipTest('Cannot import hyper, skipping tests for HTTP/2')
+
+log = logging.getLogger(__name__)
+
+
+class TestHTTP2(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
+    @classmethod
+    def setUpEnv(cls, env):
+        '''
+        Setting up environment for testing of HTTP2
+        '''
+        # get HTTP/2 server ports
+        cls.http2_port = tsqa.utils.bind_unused_port()[1]
+
+        # HTTP2 configs
+        cls.configs['records.config']['CONFIG']['proxy.config.http2.enabled'] = 1
+        cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.http2_port)
+        cls.configs['records.config']['CONFIG']['proxy.config.ssl.server.cert.path'] = helpers.tests_file_path('rsa_keys')
+        cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.enabled'] = 1
+        cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.tags'] = 'http2.*|ssl.*'
+
+        # configure SSL multicert
+        cls.configs['ssl_multicert.config'].add_line(
+            'dest_ip=* ssl_cert_name={0}\n'.format(helpers.tests_file_path('rsa_keys/www.example.com.pem'))
+        )
+
+        # remap configs
+        cls.configs['remap.config'].add_line(
+            'map / http://127.0.0.1:{0}/'.format(cls.http_endpoint.address[1])
+        )
+
+        # Turn off certificate verification for the tests.
+        # hyper-0.4.0 verify certs in default and can't turn it off without below hack:(
+        hyper.tls._context = hyper.tls.init_context()
+        hyper.tls._context.check_hostname = False
+        hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
+
+    def __cat(self, target_file_path):
+        '''
+        Cat given file
+        '''
+        for line in open(target_file_path).readlines():
+            log.debug(line[:-1])
+
+    def __traffic_out(self):
+        '''
+        Cat traffic.out
+        '''
+        self.__cat(os.path.join(self.environment.layout.logdir, 'traffic.out'))
+
+    def __diags_log(self):
+        '''
+        Cat diags.log
+        '''
+        self.__cat(os.path.join(self.environment.layout.logdir, 'diags.log'))
+
+    def test_http2_request_hyper(self):
+        '''
+        Test HTTP/2 w/ hyper (Normal Scenario)
+        '''
+        try:
+            conn = hyper.HTTPConnection('127.0.0.1', self.http2_port, secure=True)
+            stream_id = conn.request('GET', '/')
+            ret = conn.get_response()
+
+            self.assertNotEqual(stream_id, None)
+            self.assertEqual(ret.status, 200)
+        except Exception as e:
+            log.error(e)
+            self.__traffic_out()
+            self.__diags_log()


[03/14] trafficserver git commit: TS-3799: Fix handling of padding in DATA frames

Posted by zw...@apache.org.
TS-3799: Fix handling of padding in DATA frames


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

Branch: refs/heads/6.0.x
Commit: 7d63eae284d3bbc705d897639957b618fa5ce1b4
Parents: 14f0599
Author: Masakazu Kitajo <m4...@gmail.com>
Authored: Tue Jul 28 06:30:43 2015 +0900
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 09:30:36 2015 -0600

----------------------------------------------------------------------
 proxy/http2/Http2ConnectionState.cc | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7d63eae2/proxy/http2/Http2ConnectionState.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index ca7abeb..3f61b4b 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -91,20 +91,9 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
     return HTTP2_ERROR_NO_ERROR;
   }
 
-  stream->increment_data_length(payload_length);
-  if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
-    if (!stream->change_state(frame.header().type, frame.header().flags)) {
-      cstate.send_rst_stream_frame(id, HTTP2_ERROR_STREAM_CLOSED);
-      return HTTP2_ERROR_NO_ERROR;
-    }
-    if (!stream->payload_length_is_valid()) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
-    }
-  }
-
   if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
     frame.reader()->memcpy(&pad_length, HTTP2_DATA_PADLEN_LEN, nbytes);
-
+    nbytes += HTTP2_DATA_PADLEN_LEN;
     if (pad_length > payload_length) {
       // If the length of the padding is the length of the
       // frame payload or greater, the recipient MUST treat this as a
@@ -113,6 +102,17 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
     }
   }
 
+  stream->increment_data_length(payload_length - pad_length - nbytes);
+  if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
+    if (!stream->change_state(frame.header().type, frame.header().flags)) {
+      cstate.send_rst_stream_frame(id, HTTP2_ERROR_STREAM_CLOSED);
+      return HTTP2_ERROR_NO_ERROR;
+    }
+    if (!stream->payload_length_is_valid()) {
+      return HTTP2_ERROR_PROTOCOL_ERROR;
+    }
+  }
+
   // If Data length is 0, do nothing.
   if (payload_length == 0) {
     return HTTP2_ERROR_NO_ERROR;


[08/14] trafficserver git commit: TS-3823 Fix tests for -lpthread since the previous commit breaks on FreeBSD

Posted by zw...@apache.org.
TS-3823 Fix tests for -lpthread since the previous commit breaks on FreeBSD


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

Branch: refs/heads/6.0.x
Commit: fe64607f236ca8bb4a0911eb8ad1d5c17ba90b81
Parents: b4dea28
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 16:46:48 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 16:46:48 2015 -0600

----------------------------------------------------------------------
 configure.ac | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fe64607f/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 22d6464..7f811e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1061,9 +1061,9 @@ dnl We check for dlsym here instead of e.g. dlopen() because ASAN hijacks the la
 AC_SEARCH_LIBS([dlsym], [dl], [], [])
 
 dnl Linux has pthread symbol stubss in both libc and libpthread, so it's important to test
-dnl specifically for pthread_kill() here. In addition, ASAN hijacks pthread_create() so
+dnl specifically for pthread_yield() here. In addition, ASAN hijacks pthread_create() so
 dnl we can't use that anymore.
-AC_SEARCH_LIBS([pthread_kill], [pthread], [], [])
+AC_SEARCH_LIBS([pthread_yield], [pthread], [], [])
 
 dnl XXX The following check incorrectly causes the build to succeed
 dnl on Darwin. We should be using AC_SEARCH_LIBS, but rest_init is


[11/14] trafficserver git commit: TS-3825 epic plugin does not compile on OmniOS

Posted by zw...@apache.org.
TS-3825 epic plugin does not compile on OmniOS


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

Branch: refs/heads/6.0.x
Commit: 4019b970816f33716943e6a38fb4c9b2d70c8bfe
Parents: 0c28aa6
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 20:50:32 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 20:50:32 2015 -0600

----------------------------------------------------------------------
 plugins/experimental/epic/epic.cc | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4019b970/plugins/experimental/epic/epic.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/epic/epic.cc b/plugins/experimental/epic/epic.cc
index 6f6abff..8f4c738 100644
--- a/plugins/experimental/epic/epic.cc
+++ b/plugins/experimental/epic/epic.cc
@@ -301,8 +301,9 @@ epic_flush_stats(TSCont /* contp */, TSEvent /* event */, void * /* edata */)
 void
 TSPluginInit(int argc, const char *argv[])
 {
-  static const struct option longopts[] = {
-    {"directory", required_argument, NULL, 'd'}, {"period", required_argument, NULL, 'p'}, {NULL, 0, NULL, 0}};
+  static const struct option longopts[] = {{const_cast<char *>("directory"), required_argument, NULL, 'd'},
+                                           {const_cast<char *>("period"), required_argument, NULL, 'p'},
+                                           {NULL, 0, NULL, 0}};
 
   TSPluginRegistrationInfo info;
 


[04/14] trafficserver git commit: TS-3497: Define Http2Error to classify errors

Posted by zw...@apache.org.
TS-3497: Define Http2Error to classify errors

This closes #267


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

Branch: refs/heads/6.0.x
Commit: 0fc4dcdea9449929c440e54d301144edefbb721f
Parents: 7d63eae
Author: Masakazu Kitajo <m4...@gmail.com>
Authored: Wed Aug 5 01:08:19 2015 +0900
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 10:03:49 2015 -0600

----------------------------------------------------------------------
 proxy/http2/HTTP2.h                 |  20 +++
 proxy/http2/Http2ConnectionState.cc | 211 ++++++++++++++++++-------------
 2 files changed, 145 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0fc4dcde/proxy/http2/HTTP2.h
----------------------------------------------------------------------
diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h
index a398e0e..3183ec0 100644
--- a/proxy/http2/HTTP2.h
+++ b/proxy/http2/HTTP2.h
@@ -78,6 +78,14 @@ extern RecRawStatBlock *http2_rsb; // Container for statistics.
 // 6.9.1 The Flow Control Window
 static const Http2WindowSize HTTP2_MAX_WINDOW_SIZE = 0x7FFFFFFF;
 
+// 5.4.  Error Handling
+enum Http2ErrorClass {
+  HTTP2_ERROR_CLASS_NONE,
+  HTTP2_ERROR_CLASS_CONNECTION,
+  HTTP2_ERROR_CLASS_STREAM,
+};
+
+// 7.  Error Codes
 enum Http2ErrorCode {
   HTTP2_ERROR_NO_ERROR = 0,
   HTTP2_ERROR_PROTOCOL_ERROR = 1,
@@ -213,6 +221,18 @@ struct Http2FrameHeader {
   Http2StreamId streamid;
 };
 
+// 5.4.  Error Handling
+struct Http2Error {
+  Http2Error(const Http2ErrorClass error_class = HTTP2_ERROR_CLASS_NONE, const Http2ErrorCode error_code = HTTP2_ERROR_NO_ERROR)
+  {
+    cls = error_class;
+    code = error_code;
+  };
+
+  Http2ErrorClass cls;
+  Http2ErrorCode code;
+};
+
 // 6.5.1. SETTINGS Format
 struct Http2SettingsParameter {
   uint16_t id;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0fc4dcde/proxy/http2/Http2ConnectionState.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index 3f61b4b..c30dd7a 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -30,7 +30,7 @@
 // Currently use only HTTP/1.1 for requesting to origin server
 const static char *HTTP2_FETCHING_HTTP_VERSION = "HTTP/1.1";
 
-typedef Http2ErrorCode (*http2_frame_dispatch)(Http2ClientSession &, Http2ConnectionState &, const Http2Frame &);
+typedef Http2Error (*http2_frame_dispatch)(Http2ClientSession &, Http2ConnectionState &, const Http2Frame &);
 
 static const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = {
   BUFFER_SIZE_INDEX_8K,  // HTTP2_FRAME_TYPE_DATA
@@ -60,7 +60,7 @@ read_rcv_buffer(char *buf, size_t bufsize, unsigned &nbytes, const Http2Frame &f
   return end - buf;
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   char buf[BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA])];
@@ -71,24 +71,25 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
 
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] Received DATA frame.", cs.connection_id());
 
+  // If a DATA frame is received whose stream identifier field is 0x0, the recipient MUST
+  // respond with a connection error of type PROTOCOL_ERROR.
   if (!http2_is_client_streamid(id)) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   Http2Stream *stream = cstate.find_stream(id);
   if (stream == NULL) {
     if (id <= cstate.get_latest_stream_id()) {
-      return HTTP2_ERROR_STREAM_CLOSED;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_STREAM_CLOSED);
     } else {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
   // If a DATA frame is received whose stream is not in "open" or "half closed (local)" state,
   // the recipient MUST respond with a stream error of type STREAM_CLOSED.
   if (stream->get_state() != HTTP2_STREAM_STATE_OPEN && stream->get_state() != HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) {
-    cstate.send_rst_stream_frame(id, HTTP2_ERROR_STREAM_CLOSED);
-    return HTTP2_ERROR_NO_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_STREAM_CLOSED);
   }
 
   if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
@@ -98,7 +99,7 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
       // If the length of the padding is the length of the
       // frame payload or greater, the recipient MUST treat this as a
       // connection error of type PROTOCOL_ERROR.
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
@@ -106,21 +107,24 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
   if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
     if (!stream->change_state(frame.header().type, frame.header().flags)) {
       cstate.send_rst_stream_frame(id, HTTP2_ERROR_STREAM_CLOSED);
-      return HTTP2_ERROR_NO_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_NONE);
     }
     if (!stream->payload_length_is_valid()) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
   // If Data length is 0, do nothing.
   if (payload_length == 0) {
-    return HTTP2_ERROR_NO_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_NONE);
   }
 
   // Check whether Window Size is acceptable
-  if (cstate.server_rwnd < payload_length || stream->server_rwnd < payload_length) {
-    return HTTP2_ERROR_FLOW_CONTROL_ERROR;
+  if (cstate.server_rwnd < payload_length) {
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FLOW_CONTROL_ERROR);
+  }
+  if (stream->server_rwnd < payload_length) {
+    return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_FLOW_CONTROL_ERROR);
   }
 
   // Update Window size
@@ -151,10 +155,10 @@ rcv_data_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
     cstate.send_window_update_frame(stream->get_id(), diff_size);
   }
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   char buf[BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_HEADERS])];
@@ -166,36 +170,37 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] Received HEADERS frame.", cs.connection_id());
 
   if (!http2_is_client_streamid(id)) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   Http2Stream *stream = cstate.find_stream(id);
-  if (stream == NULL && id <= cstate.get_latest_stream_id()) {
-    return HTTP2_ERROR_STREAM_CLOSED;
+  if (id <= cstate.get_latest_stream_id()) {
+    return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_STREAM_CLOSED);
   }
 
   // Create new stream
   stream = cstate.create_stream(id);
   if (!stream) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // keep track of how many bytes we get in the frame
   stream->request_header_length += payload_length;
   if (stream->request_header_length > Http2::max_request_header_size) {
     Error("HTTP/2 payload for headers exceeded: %u", stream->request_header_length);
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    // XXX Should we respond with 431 (Request Header Fields Too Large) ?
+    return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // A receiver MUST treat the receipt of any other type of frame or
   // a frame on a different stream as a connection error of type PROTOCOL_ERROR.
   if (cstate.get_continued_id() != 0) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // Change state. If changing is invalid, raise PROTOCOL_ERROR
   if (!stream->change_state(frame.header().type, frame.header().flags)) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // Check whether padding exists or not.
@@ -203,14 +208,14 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
     frame.reader()->memcpy(buf, HTTP2_HEADERS_PADLEN_LEN, nbytes);
     nbytes += HTTP2_HEADERS_PADLEN_LEN;
     if (!http2_parse_headers_parameter(make_iovec(buf, HTTP2_HEADERS_PADLEN_LEN), params)) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     if (params.pad_length > payload_length) {
       // If the length of the padding is the length of the
       // frame payload or greater, the recipient MUST treat this as a
       // connection error of type PROTOCOL_ERROR.
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   } else {
     params.pad_length = 0;
@@ -222,7 +227,7 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
     frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, nbytes);
     nbytes += HTTP2_PRIORITY_LEN;
     if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), params.priority)) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
@@ -243,11 +248,11 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
     // connection error of type COMPRESSION_ERROR if it does
     // not decompress a header block.
     if (decoded_bytes == 0 || decoded_bytes == HPACK_ERROR_COMPRESSION_ERROR) {
-      return HTTP2_ERROR_COMPRESSION_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_COMPRESSION_ERROR);
     }
 
     if (decoded_bytes == HPACK_ERROR_HTTP2_PROTOCOL_ERROR) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     remaining_bytes = header_block_fragment.iov_len - decoded_bytes;
@@ -266,10 +271,10 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
     stream->init_fetcher(cstate);
   }
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_priority_frame(Http2ClientSession &cs, Http2ConnectionState & /*cstate*/, const Http2Frame &frame)
 {
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] received PRIORITY frame", cs.connection_id());
@@ -277,22 +282,22 @@ rcv_priority_frame(Http2ClientSession &cs, Http2ConnectionState & /*cstate*/, co
   // If a PRIORITY frame is received with a stream identifier of 0x0, the
   // recipient MUST respond with a connection error of type PROTOCOL_ERROR.
   if (frame.header().streamid == 0) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // A PRIORITY frame with a length other than 5 octets MUST be treated as
   // a stream error (Section 5.4.2) of type FRAME_SIZE_ERROR.
   if (frame.header().length != HTTP2_PRIORITY_LEN) {
-    return HTTP2_ERROR_FRAME_SIZE_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_FRAME_SIZE_ERROR);
   }
 
   // TODO Pick stream dependencies and weight
   // Supporting PRIORITY is not essential so its temporarily ignored.
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_rst_stream_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   Http2RstStream rst_stream;
@@ -301,35 +306,41 @@ rcv_rst_stream_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const
 
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] Received RST_STREAM frame.", cs.connection_id());
 
+  // RST_STREAM frames MUST be associated with a stream.  If a RST_STREAM
+  // frame is received with a stream identifier of 0x0, the recipient MUST
+  // treat this as a connection error (Section 5.4.1) of type
+  // PROTOCOL_ERROR.
   Http2StreamId stream_id = frame.header().streamid;
 
   if (!http2_is_client_streamid(stream_id)) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   Http2Stream *stream = cstate.find_stream(stream_id);
   if (stream == NULL) {
     if (stream_id <= cstate.get_latest_stream_id()) {
-      return HTTP2_ERROR_NO_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_NONE);
     } else {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
+  // A RST_STREAM frame with a length other than 4 octets MUST be treated
+  // as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
   if (frame.header().length != HTTP2_RST_STREAM_LEN) {
-    return HTTP2_ERROR_FRAME_SIZE_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FRAME_SIZE_ERROR);
   }
 
-  if (stream != NULL && !stream->change_state(frame.header().type, frame.header().flags)) {
+  if (stream == NULL || !stream->change_state(frame.header().type, frame.header().flags)) {
     // If a RST_STREAM frame identifying an idle stream is received, the
     // recipient MUST treat this as a connection error of type PROTOCOL_ERROR.
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   end = frame.reader()->memcpy(buf, sizeof(buf), 0);
 
   if (!http2_parse_rst_stream(make_iovec(buf, end - buf), rst_stream)) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   if (stream != NULL) {
@@ -338,10 +349,10 @@ rcv_rst_stream_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const
     cstate.delete_stream(stream);
   }
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_settings_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   Http2SettingsParameter param;
@@ -351,26 +362,44 @@ rcv_settings_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const H
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] Received SETTINGS frame.", cs.connection_id());
 
   // 6.5 The stream identifier for a SETTINGS frame MUST be zero.
+  // If an endpoint receives a SETTINGS frame whose stream identifier field is
+  // anything other than 0x0, the endpoint MUST respond with a connection
+  // error (Section 5.4.1) of type PROTOCOL_ERROR.
   if (frame.header().streamid != 0) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // 6.5 Receipt of a SETTINGS frame with the ACK flag set and a
   // length field value other than 0 MUST be treated as a connection
   // error of type FRAME_SIZE_ERROR.
   if (frame.header().flags & HTTP2_FLAGS_SETTINGS_ACK) {
-    return frame.header().length == 0 ? HTTP2_ERROR_NO_ERROR : HTTP2_ERROR_FRAME_SIZE_ERROR;
+    if (frame.header().length == 0) {
+      return Http2Error(HTTP2_ERROR_CLASS_NONE);
+    } else {
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FRAME_SIZE_ERROR);
+    }
+  }
+
+  // A SETTINGS frame with a length other than a multiple of 6 octets MUST
+  // be treated as a connection error (Section 5.4.1) of type
+  // FRAME_SIZE_ERROR.
+  if (frame.header().length % 6 != 0) {
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FRAME_SIZE_ERROR);
   }
 
   while (nbytes < frame.header().length) {
     unsigned read_bytes = read_rcv_buffer(buf, sizeof(buf), nbytes, frame);
 
     if (!http2_parse_settings_parameter(make_iovec(buf, read_bytes), param)) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     if (!http2_settings_parameter_is_valid(param)) {
-      return param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE ? HTTP2_ERROR_FLOW_CONTROL_ERROR : HTTP2_ERROR_PROTOCOL_ERROR;
+      if (param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
+        return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FLOW_CONTROL_ERROR);
+      } else {
+        return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
+      }
     }
 
     DebugSsn(&cs, "http2_cs", "[%" PRId64 "] setting param=%d value=%u", cs.connection_id(), param.id, param.value);
@@ -391,21 +420,21 @@ rcv_settings_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const H
   Http2Frame ackFrame(HTTP2_FRAME_TYPE_SETTINGS, 0, HTTP2_FLAGS_SETTINGS_ACK);
   cstate.ua_session->handleEvent(HTTP2_SESSION_EVENT_XMIT, &ackFrame);
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_push_promise_frame(Http2ClientSession &cs, Http2ConnectionState & /*cstate*/, const Http2Frame & /*frame*/)
 {
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] received PUSH_PROMISE frame", cs.connection_id());
 
   // 8.2. A client cannot push.  Thus, servers MUST treat the receipt of a
   // PUSH_PROMISE frame as a connection error of type PROTOCOL_ERROR.
-  return HTTP2_ERROR_PROTOCOL_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
 }
 
 // 6.7.  PING
-static Http2ErrorCode
+static Http2Error
 rcv_ping_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   uint8_t opaque_data[HTTP2_PING_LEN];
@@ -415,18 +444,18 @@ rcv_ping_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
   //  If a PING frame is received with a stream identifier field value other than
   //  0x0, the recipient MUST respond with a connection error of type PROTOCOL_ERROR.
   if (frame.header().streamid != 0x0) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // Receipt of a PING frame with a length field value other than 8 MUST
   // be treated as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
   if (frame.header().length != HTTP2_PING_LEN) {
-    return HTTP2_ERROR_FRAME_SIZE_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FRAME_SIZE_ERROR);
   }
 
   // An endpoint MUST NOT respond to PING frames containing this flag.
   if (frame.header().flags & HTTP2_FLAGS_PING_ACK) {
-    return HTTP2_ERROR_NO_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_NONE);
   }
 
   frame.reader()->memcpy(opaque_data, HTTP2_PING_LEN, 0);
@@ -434,10 +463,10 @@ rcv_ping_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2
   // ACK (0x1): An endpoint MUST set this flag in PING responses.
   cstate.send_ping_frame(frame.header().streamid, HTTP2_FLAGS_PING_ACK, opaque_data);
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_goaway_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   Http2Goaway goaway;
@@ -449,14 +478,14 @@ rcv_goaway_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Htt
   // An endpoint MUST treat a GOAWAY frame with a stream identifier other
   // than 0x0 as a connection error of type PROTOCOL_ERROR.
   if (frame.header().streamid != 0x0) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   while (nbytes < frame.header().length) {
     unsigned read_bytes = read_rcv_buffer(buf, sizeof(buf), nbytes, frame);
 
     if (!http2_parse_goaway(make_iovec(buf, read_bytes), goaway)) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
@@ -466,10 +495,10 @@ rcv_goaway_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Htt
   cstate.handleEvent(HTTP2_SESSION_EVENT_FINI, NULL);
   // eventProcessor.schedule_imm(&cs, ET_NET, VC_EVENT_ERROR);
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   char buf[HTTP2_WINDOW_UPDATE_LEN];
@@ -481,7 +510,7 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
   //  A WINDOW_UPDATE frame with a length other than 4 octets MUST be
   //  treated as a connection error of type FRAME_SIZE_ERROR.
   if (frame.header().length != HTTP2_WINDOW_UPDATE_LEN) {
-    return HTTP2_ERROR_FRAME_SIZE_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FRAME_SIZE_ERROR);
   }
 
   if (sid == 0) {
@@ -492,7 +521,7 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
     // A receiver MUST treat the receipt of a WINDOW_UPDATE frame with a connection
     // flow control window increment of 0 as a connection error of type PROTOCOL_ERROR;
     if (size == 0) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     cstate.client_rwnd += size;
@@ -503,9 +532,9 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
 
     if (stream == NULL) {
       if (sid <= cstate.get_latest_stream_id()) {
-        return HTTP2_ERROR_NO_ERROR;
+        return Http2Error(HTTP2_ERROR_CLASS_NONE);
       } else {
-        return HTTP2_ERROR_PROTOCOL_ERROR;
+        return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
       }
     }
 
@@ -515,8 +544,7 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
     // A receiver MUST treat the receipt of a WINDOW_UPDATE frame with an
     // flow control window increment of 0 as a stream error of type PROTOCOL_ERROR;
     if (size == 0) {
-      cstate.send_rst_stream_frame(sid, HTTP2_ERROR_PROTOCOL_ERROR);
-      return HTTP2_ERROR_NO_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     stream->client_rwnd += size;
@@ -526,10 +554,10 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
     }
   }
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
-static Http2ErrorCode
+static Http2Error
 rcv_continuation_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Http2Frame &frame)
 {
   char buf[BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_CONTINUATION])];
@@ -539,25 +567,31 @@ rcv_continuation_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, con
   DebugSsn(&cs, "http2_cs", "[%" PRId64 "] Received CONTINUATION frame.", cs.connection_id());
 
   // Find opened stream
+  // CONTINUATION frames MUST be associated with a stream.  If a
+  // CONTINUATION frame is received whose stream identifier field is 0x0,
+  // the recipient MUST respond with a connection error (Section 5.4.1) of
+  // type PROTOCOL_ERROR.
   Http2Stream *stream = cstate.find_stream(stream_id);
   if (stream == NULL) {
     if (stream_id <= cstate.get_latest_stream_id()) {
-      return HTTP2_ERROR_STREAM_CLOSED;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_STREAM_CLOSED);
     } else {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
   }
 
   // A CONTINUATION frame MUST be preceded by a HEADERS, PUSH_PROMISE or
-  // CONTINUATION frame without the END_HEADERS flag set.
+  // CONTINUATION frame without the END_HEADERS flag set. A recipient
+  // that observes violation of this rule MUST respond with a connection
+  // error (Section 5.4.1) of type PROTOCOL_ERROR.
   if (stream->get_state() != HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE && stream->get_state() != HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   // A receiver MUST treat the receipt of any other type of frame or
   // a frame on a different stream as a connection error of type PROTOCOL_ERROR.
   if (stream->get_id() != cstate.get_continued_id()) {
-    return HTTP2_ERROR_PROTOCOL_ERROR;
+    return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
   const IOVec remaining_data = cstate.get_continued_headers();
@@ -575,7 +609,8 @@ rcv_continuation_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, con
     stream->request_header_length += frame.header().length;
     if (stream->request_header_length > Http2::max_request_header_size) {
       Error("HTTP/2 payload for headers exceeded: %u", stream->request_header_length);
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      // XXX Should we respond with 431 (Request Header Fields Too Large) ?
+      return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     bool cont = nbytes < frame.header().length || !(frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS);
@@ -585,11 +620,11 @@ rcv_continuation_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, con
     // connection error of type COMPRESSION_ERROR if it does
     // not decompress a header block.
     if (decoded_bytes == 0 || decoded_bytes == HPACK_ERROR_COMPRESSION_ERROR) {
-      return HTTP2_ERROR_COMPRESSION_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_COMPRESSION_ERROR);
     }
 
     if (decoded_bytes == HPACK_ERROR_HTTP2_PROTOCOL_ERROR) {
-      return HTTP2_ERROR_PROTOCOL_ERROR;
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
     remaining_bytes = header_block_fragment.iov_len - decoded_bytes;
@@ -609,7 +644,7 @@ rcv_continuation_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, con
     stream->init_fetcher(cstate);
   }
 
-  return HTTP2_ERROR_NO_ERROR;
+  return Http2Error(HTTP2_ERROR_CLASS_NONE);
 }
 
 static const http2_frame_dispatch frame_handlers[HTTP2_FRAME_TYPE_MAX] = {
@@ -663,7 +698,7 @@ Http2ConnectionState::main_event_handler(int event, void *edata)
   case HTTP2_SESSION_EVENT_RECV: {
     Http2Frame *frame = (Http2Frame *)edata;
     Http2StreamId last_streamid = frame->header().streamid;
-    Http2ErrorCode error;
+    Http2Error error;
 
     // 5.5 Extending HTTP/2
     //   Implementations MUST discard frames that have unknown or unsupported types.
@@ -676,17 +711,21 @@ Http2ConnectionState::main_event_handler(int event, void *edata)
     if (frame_handlers[frame->header().type]) {
       error = frame_handlers[frame->header().type](*this->ua_session, *this, *frame);
     } else {
-      error = HTTP2_ERROR_INTERNAL_ERROR;
+      error = Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_INTERNAL_ERROR);
     }
 
-    if (error != HTTP2_ERROR_NO_ERROR) {
-      this->send_goaway_frame(last_streamid, error);
-      cleanup_streams();
-      // XXX We need to think a bit harder about how to coordinate the client session and the
-      // protocol connection. At this point, the protocol is shutting down, but there's no way
-      // to tell that to the client session. Perhaps this could be solved by implementing the
-      // half-closed state ...
-      SET_HANDLER(&Http2ConnectionState::state_closed);
+    if (error.cls != HTTP2_ERROR_CLASS_NONE) {
+      if (error.cls == HTTP2_ERROR_CLASS_CONNECTION) {
+        this->send_goaway_frame(last_streamid, error.code);
+        cleanup_streams();
+        // XXX We need to think a bit harder about how to coordinate the client session and the
+        // protocol connection. At this point, the protocol is shutting down, but there's no way
+        // to tell that to the client session. Perhaps this could be solved by implementing the
+        // half-closed state ...
+        SET_HANDLER(&Http2ConnectionState::state_closed);
+      } else if (error.cls == HTTP2_ERROR_CLASS_STREAM) {
+        this->send_rst_stream_frame(last_streamid, error.code);
+      }
     }
 
     return 0;


[10/14] trafficserver git commit: TS-3824 Fix #include of pcre for a couple of plugins

Posted by zw...@apache.org.
TS-3824 Fix #include of pcre for a couple of plugins


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

Branch: refs/heads/6.0.x
Commit: 0c28aa665ddf633171884a9ca0a90e89ade71ce5
Parents: 9e8800c
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 20:18:09 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 20:27:53 2015 -0600

----------------------------------------------------------------------
 plugins/experimental/geoip_acl/acl.h  | 5 +++++
 plugins/header_rewrite/regex_helper.h | 6 ++++++
 2 files changed, 11 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c28aa66/plugins/experimental/geoip_acl/acl.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/geoip_acl/acl.h b/plugins/experimental/geoip_acl/acl.h
index 81c35cf..e9be954 100644
--- a/plugins/experimental/geoip_acl/acl.h
+++ b/plugins/experimental/geoip_acl/acl.h
@@ -21,7 +21,12 @@
 
 #include <ts/ts.h>
 #include <ts/remap.h>
+
+#ifdef HAVE_PCRE_PCRE_H
+#include <pcre/pcre.h>
+#else
 #include <pcre.h>
+#endif
 
 #include <string>
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c28aa66/plugins/header_rewrite/regex_helper.h
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/regex_helper.h b/plugins/header_rewrite/regex_helper.h
index 45b061c..6be153a 100644
--- a/plugins/header_rewrite/regex_helper.h
+++ b/plugins/header_rewrite/regex_helper.h
@@ -18,7 +18,13 @@
 #ifndef REGEX_HELPER_H
 #define REGEX_HELPER_H
 
+#include "ts/ink_defs.h"
+
+#ifdef HAVE_PCRE_PCRE_H
+#include <pcre/pcre.h>
+#else
 #include <pcre.h>
+#endif
 
 #include <string>
 


[14/14] trafficserver git commit: Merge branch 'master' into 6.0.x

Posted by zw...@apache.org.
Merge branch 'master' into 6.0.x

* master:
  TS-3822 clang-analyzer: Value stored to 'stream' during its initialization is never read
  TS-3824 Fix #include of pcre for a couple of plugins
  TS-3825 epic plugin does not compile on OmniOS
  TS-3824 Fix #include of pcre for a couple of plugins
  TS-3658 ASAN triggers when using the escalate.so plugin
  TS-3823 Fix tests for -lpthread since the previous commit breaks on FreeBSD
  TS-3823 Fix tests for -lpthread, and undo some of TS-3308. This retains the support for ASAN in a cleaner way
  TS-3823 ASAN makes us forget to add -ldl on the LIBS
  TS-3811 HTTP/2 window size must not exceed 2^31-1
  TS-3497: Define Http2Error to classify errors
  TS-3799: Fix handling of padding in DATA frames
  TS-3814 Treat requests with Connection header field as malformed, as per specs
  TS-3782: Add normal scenario tests for HTTP/2


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

Branch: refs/heads/6.0.x
Commit: 1c2ea99cff9de7044226fee9c9f02b4273abae53
Parents: 252eb21 5597664
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 21:27:19 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 21:27:19 2015 -0600

----------------------------------------------------------------------
 ci/tsqa/requirements.txt               |   1 +
 ci/tsqa/tests/test_http2.py            |  98 +++++++++++
 cmd/traffic_crashlog/Makefile.am       |   2 +-
 cmd/traffic_layout/Makefile.am         |   2 +-
 cmd/traffic_manager/Makefile.am        |   2 +-
 configure.ac                           |  11 +-
 plugins/experimental/epic/epic.cc      |   5 +-
 plugins/experimental/geoip_acl/acl.h   |   5 +
 plugins/experimental/url_sig/url_sig.c |   1 +
 plugins/experimental/url_sig/url_sig.h |   1 -
 plugins/header_rewrite/regex_helper.h  |   6 +
 proxy/Makefile.am                      |   6 +-
 proxy/http/HttpSM.cc                   |  50 +++---
 proxy/http2/HTTP2.cc                   |  15 +-
 proxy/http2/HTTP2.h                    |  20 +++
 proxy/http2/Http2ConnectionState.cc    | 257 +++++++++++++++++-----------
 16 files changed, 330 insertions(+), 152 deletions(-)
----------------------------------------------------------------------



[09/14] trafficserver git commit: TS-3658 ASAN triggers when using the escalate.so plugin

Posted by zw...@apache.org.
TS-3658 ASAN triggers when using the escalate.so plugin


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

Branch: refs/heads/6.0.x
Commit: 9e8800c5f648e4902c522087e88d9ea806a1de4f
Parents: fe64607
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 20:08:52 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 20:08:56 2015 -0600

----------------------------------------------------------------------
 proxy/http/HttpSM.cc | 50 +++++++++++++++++++----------------------------
 1 file changed, 20 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9e8800c5/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 9da84b5..8ba5eaa 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -7527,38 +7527,33 @@ HttpSM::redirect_request(const char *redirect_url, const int redirect_len)
 
     if (host != NULL) {
       int port = clientUrl.port_get();
-      char buf[host_len + 7];
-
       int redirectSchemeLen;
       const char *redirectScheme = clientUrl.scheme_get(&redirectSchemeLen);
+
       if (redirectScheme == NULL) {
         clientUrl.scheme_set(scheme_str, scheme_len);
-        DebugSM("http_redirect", "[HttpSM::redirect_request] hsot without scheme %s", buf);
+        DebugSM("http_redirect", "[HttpSM::redirect_request] URL without scheme %.*s", redirectSchemeLen, redirectScheme);
       }
 
       if (noPortInHost) {
         int redirectSchemeIdx = clientUrl.scheme_get_wksidx();
-
         bool defaultPort =
           (((redirectSchemeIdx == URL_WKSIDX_HTTP) && (port == 80)) || ((redirectSchemeIdx == URL_WKSIDX_HTTPS) && (port == 443)));
 
-        if (!defaultPort)
+        if (!defaultPort) {
           noPortInHost = false;
+        }
       }
 
-      ink_strlcpy(buf, host, host_len + 1);
-
       if (!noPortInHost) {
-        char port_buf[6]; // handle upto 5 digit port
-        buf[host_len++] = ':';
-        buf[host_len] = '\0';
+        char buf[host_len + 7]; // 5 + 1 + 1 ("12345" + ':' + '\0')
 
-        host_len += ink_small_itoa(port, port_buf, sizeof(port_buf));
-        ink_strlcat(buf, port_buf, sizeof(buf));
+        host_len = snprintf(buf, host_len + 7, "%.*s:%d", host_len, host, port);
+        t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, host_len);
+      } else {
+        t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, host, host_len);
       }
-
       t_state.hdr_info.client_request.m_target_cached = false;
-      t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, host_len);
     } else {
       // the client request didn't have a host, so use the current origin host
       if (valid_origHost) {
@@ -7566,18 +7561,15 @@ HttpSM::redirect_request(const char *redirect_url, const int redirect_len)
 
         // the client request didn't have a host, so use the current origin host
         DebugSM("http_redirect", "[HttpSM::redirect_request] keeping client request host %s://%s", next_hop_scheme, origHost);
-        char *origHost1 = strtok_r(origHost, ":", &saveptr);
-        if (origHost1 == NULL) {
+        char *origHostNoPort = strtok_r(origHost, ":", &saveptr);
+
+        if (origHostNoPort == NULL) {
           goto LhostError;
         }
-        origHost_len = strlen(origHost1);
-        int origHostPort_len = origHost_len;
-        char buf[origHostPort_len + 7];
-        ink_strlcpy(buf, origHost1, origHost_len + 1);
 
+        host_len = strlen(origHostNoPort);
         if (noPortInHost) {
           int redirectSchemeIdx = t_state.next_hop_scheme;
-
           bool defaultPort = (((redirectSchemeIdx == URL_WKSIDX_HTTP) && (origPort == 80)) ||
                               ((redirectSchemeIdx == URL_WKSIDX_HTTPS) && (origPort == 443)));
 
@@ -7586,20 +7578,18 @@ HttpSM::redirect_request(const char *redirect_url, const int redirect_len)
         }
 
         if (!noPortInHost) {
-          char port_buf[6]; // handle upto 5 digit port
-          buf[origHostPort_len++] = ':';
-          buf[origHostPort_len] = '\0';
-          origHostPort_len += ink_small_itoa(origPort, port_buf, sizeof(port_buf));
-          ink_strlcat(buf, port_buf, sizeof(buf));
+          char buf[host_len + 7]; // 5 + 1 + 1 ("12345" + ':' + '\0')
+
+          host_len = snprintf(buf, host_len + 7, "%s:%d", origHostNoPort, origPort);
+          t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, host_len);
+        } else {
+          t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, origHostNoPort, host_len);
         }
 
+        // Cleanup of state etc.
         url_nuke_proxy_stuff(clientUrl.m_url_impl);
         url_nuke_proxy_stuff(t_state.hdr_info.client_request.m_url_cached.m_url_impl);
         t_state.hdr_info.client_request.method_set(origMethod, origMethod_len);
-        if (noPortInHost)
-          t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, origHost_len);
-        else
-          t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, origHostPort_len);
         t_state.hdr_info.client_request.m_target_cached = false;
         clientUrl.scheme_set(scheme_str, scheme_len);
       } else {


[06/14] trafficserver git commit: TS-3823 ASAN makes us forget to add -ldl on the LIBS

Posted by zw...@apache.org.
TS-3823 ASAN makes us forget to add -ldl on the LIBS


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

Branch: refs/heads/6.0.x
Commit: a0a74505e279b69a5ca5a6eb7fa7a3a97136fe90
Parents: 29243ae
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 13:54:38 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 13:54:42 2015 -0600

----------------------------------------------------------------------
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/a0a74505/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 29c0b7e..0205ca5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1052,7 +1052,7 @@ fi
 
 AC_SEARCH_LIBS([exc_capture_context], [exc], [], [])
 AC_SEARCH_LIBS([MLD_demangle_string], [mld], [], [])
-AC_SEARCH_LIBS([dlopen], [dl], [], [])
+AC_SEARCH_LIBS([dlsym], [dl], [], [])
 AC_SEARCH_LIBS([socket], [socket], [], [])
 AC_SEARCH_LIBS([gethostbyname], [nsl], [], [])
 AC_SEARCH_LIBS([clock_gettime], [rt], [], [])


[05/14] trafficserver git commit: TS-3811 HTTP/2 window size must not exceed 2^31-1

Posted by zw...@apache.org.
TS-3811 HTTP/2 window size must not exceed 2^31-1


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

Branch: refs/heads/6.0.x
Commit: 29243aed8a21e0267717bce96187903372489964
Parents: 0fc4dcd
Author: maskit <m4...@gmail.com>
Authored: Wed Aug 5 10:09:28 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 10:09:28 2015 -0600

----------------------------------------------------------------------
 proxy/http2/Http2ConnectionState.cc | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/29243aed/proxy/http2/Http2ConnectionState.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index c30dd7a..4244468 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -524,6 +524,17 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
       return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
+    // A sender MUST NOT allow a flow-control window to exceed 2^31-1
+    // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
+    // control window to exceed this maximum, it MUST terminate either the
+    // stream or the connection, as appropriate.  For streams, the sender
+    // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
+    // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
+    // is sent.
+    if (size > HTTP2_MAX_WINDOW_SIZE - cstate.client_rwnd) {
+      return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_FLOW_CONTROL_ERROR);
+    }
+
     cstate.client_rwnd += size;
     cstate.restart_streams();
   } else {
@@ -547,6 +558,17 @@ rcv_window_update_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, co
       return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_PROTOCOL_ERROR);
     }
 
+    // A sender MUST NOT allow a flow-control window to exceed 2^31-1
+    // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
+    // control window to exceed this maximum, it MUST terminate either the
+    // stream or the connection, as appropriate.  For streams, the sender
+    // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
+    // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
+    // is sent.
+    if (size > HTTP2_MAX_WINDOW_SIZE - stream->client_rwnd) {
+      return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_FLOW_CONTROL_ERROR);
+    }
+
     stream->client_rwnd += size;
     ssize_t wnd = min(cstate.client_rwnd, stream->client_rwnd);
     if (wnd > 0) {


[13/14] trafficserver git commit: TS-3822 clang-analyzer: Value stored to 'stream' during its initialization is never read

Posted by zw...@apache.org.
TS-3822 clang-analyzer: Value stored to 'stream' during its initialization is never read


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

Branch: refs/heads/6.0.x
Commit: 559766411410f36a82f28632f8308cc2d20e74b0
Parents: 8939a3c
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 21:25:17 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 21:25:17 2015 -0600

----------------------------------------------------------------------
 proxy/http2/Http2ConnectionState.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/55976641/proxy/http2/Http2ConnectionState.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index 4244468..3d94dfd 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -173,13 +173,13 @@ rcv_headers_frame(Http2ClientSession &cs, Http2ConnectionState &cstate, const Ht
     return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }
 
-  Http2Stream *stream = cstate.find_stream(id);
   if (id <= cstate.get_latest_stream_id()) {
     return Http2Error(HTTP2_ERROR_CLASS_STREAM, HTTP2_ERROR_STREAM_CLOSED);
   }
 
   // Create new stream
-  stream = cstate.create_stream(id);
+  Http2Stream *stream = cstate.create_stream(id);
+
   if (!stream) {
     return Http2Error(HTTP2_ERROR_CLASS_CONNECTION, HTTP2_ERROR_PROTOCOL_ERROR);
   }


[02/14] trafficserver git commit: TS-3814 Treat requests with Connection header field as malformed, as per specs

Posted by zw...@apache.org.
TS-3814 Treat requests with Connection header field as malformed, as per specs


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

Branch: refs/heads/6.0.x
Commit: 14f0599e6342ae4944c95a052fc27c3c895b0d94
Parents: 1cbe7c7
Author: Ryo Okubo <ro...@yahoo-corp.jp>
Authored: Tue Aug 4 20:18:49 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Tue Aug 4 20:18:49 2015 -0600

----------------------------------------------------------------------
 proxy/http2/HTTP2.cc | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14f0599e/proxy/http2/HTTP2.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index 3b4ad96..3a84a59 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -534,16 +534,6 @@ convert_from_2_to_1_1_header(HTTPHdr *headers)
     headers->field_delete(HPACK_VALUE_STATUS, HPACK_LEN_STATUS);
   }
 
-  // Intermediaries SHOULD also remove other connection-
-  // specific header fields, such as Keep-Alive, Proxy-Connection,
-  // Transfer-Encoding and Upgrade, even if they are not nominated by
-  // Connection.
-  headers->field_delete(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
-  headers->field_delete(MIME_FIELD_KEEP_ALIVE, MIME_LEN_KEEP_ALIVE);
-  headers->field_delete(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);
-  headers->field_delete(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING);
-  headers->field_delete(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE);
-
   return PARSE_DONE;
 }
 
@@ -710,6 +700,11 @@ http2_parse_header_fragment(HTTPHdr *hdr, IOVec iov, Http2DynamicTable &dynamic_
       return HPACK_ERROR_HTTP2_PROTOCOL_ERROR;
     }
 
+    // rfc7540,sec8.1.2.2: Any message containing connection-specific header fields MUST be treated as malformed
+    if (name == MIME_FIELD_CONNECTION) {
+      return HPACK_ERROR_HTTP2_PROTOCOL_ERROR;
+    }
+
     // :path pseudo header MUST NOT empty for http or https URIs
     if (static_cast<unsigned>(name_len) == HPACK_LEN_PATH && strncmp(name, HPACK_VALUE_PATH, name_len) == 0) {
       int value_len = 0;


[07/14] trafficserver git commit: TS-3823 Fix tests for -lpthread, and undo some of TS-3308. This retains the support for ASAN in a cleaner way

Posted by zw...@apache.org.
TS-3823 Fix tests for -lpthread, and undo some of TS-3308. This retains the support for ASAN in a cleaner way


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

Branch: refs/heads/6.0.x
Commit: b4dea28aaed390f1def4248a79361099cbb0b717
Parents: a0a7450
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 14:33:40 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 14:33:40 2015 -0600

----------------------------------------------------------------------
 cmd/traffic_crashlog/Makefile.am |  2 +-
 cmd/traffic_layout/Makefile.am   |  2 +-
 cmd/traffic_manager/Makefile.am  |  2 +-
 configure.ac                     | 11 +++++++----
 proxy/Makefile.am                |  6 ++----
 5 files changed, 12 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b4dea28a/cmd/traffic_crashlog/Makefile.am
----------------------------------------------------------------------
diff --git a/cmd/traffic_crashlog/Makefile.am b/cmd/traffic_crashlog/Makefile.am
index e127b65..b977f51 100644
--- a/cmd/traffic_crashlog/Makefile.am
+++ b/cmd/traffic_crashlog/Makefile.am
@@ -42,4 +42,4 @@ traffic_crashlog_LDADD = \
   $(top_builddir)/proxy/shared/libUglyLogStubs.a \
   $(top_builddir)/mgmt/api/libtsmgmt.la \
   $(top_builddir)/lib/ts/libtsutil.la \
-  @LIBTCL@ @HWLOC_LIBS@ @LIBPTHREAD@
+  @LIBTCL@ @HWLOC_LIBS@

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b4dea28a/cmd/traffic_layout/Makefile.am
----------------------------------------------------------------------
diff --git a/cmd/traffic_layout/Makefile.am b/cmd/traffic_layout/Makefile.am
index f0da43a..a9f714e 100644
--- a/cmd/traffic_layout/Makefile.am
+++ b/cmd/traffic_layout/Makefile.am
@@ -38,4 +38,4 @@ traffic_layout_LDADD = \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/proxy/shared/libUglyLogStubs.a \
   $(top_builddir)/lib/ts/libtsutil.la \
-  @LIBTCL@ @HWLOC_LIBS@ @LIBPTHREAD@
+  @LIBTCL@ @HWLOC_LIBS@

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b4dea28a/cmd/traffic_manager/Makefile.am
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/Makefile.am b/cmd/traffic_manager/Makefile.am
index 6c3b448..fecdd49 100644
--- a/cmd/traffic_manager/Makefile.am
+++ b/cmd/traffic_manager/Makefile.am
@@ -60,7 +60,7 @@ traffic_manager_LDADD = \
   $(top_builddir)/proxy/shared/liberror.a \
   $(top_builddir)/proxy/shared/libdiagsconfig.a \
   $(LIBUNWIND_LIBS) \
-  @LIBRESOLV@ @LIBEXPAT@ @LIBPCRE@ @LIBTCL@ @LIBCAP@ @HWLOC_LIBS@ @LIBPTHREAD@ \
+  @LIBRESOLV@ @LIBEXPAT@ @LIBPCRE@ @LIBTCL@ @LIBCAP@ @HWLOC_LIBS@ \
   -lm
 
 # Must do it this way or the dependencies aren't detected.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b4dea28a/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 0205ca5..22d6464 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1052,15 +1052,18 @@ fi
 
 AC_SEARCH_LIBS([exc_capture_context], [exc], [], [])
 AC_SEARCH_LIBS([MLD_demangle_string], [mld], [], [])
-AC_SEARCH_LIBS([dlsym], [dl], [], [])
 AC_SEARCH_LIBS([socket], [socket], [], [])
 AC_SEARCH_LIBS([gethostbyname], [nsl], [], [])
 AC_SEARCH_LIBS([clock_gettime], [rt], [], [])
 AC_SEARCH_LIBS([clock_gettime], [posix4], [], [])
 
-dnl Linux has pthread symbol stubss in both libc ad libpthread, so it's important to test
-dnl specifically for pthread_create() here.
-AC_SEARCH_LIBS([pthread_create], [pthread],[AC_SUBST([LIBPTHREAD],["-lpthread"])], [])
+dnl We check for dlsym here instead of e.g. dlopen() because ASAN hijacks the latter.
+AC_SEARCH_LIBS([dlsym], [dl], [], [])
+
+dnl Linux has pthread symbol stubss in both libc and libpthread, so it's important to test
+dnl specifically for pthread_kill() here. In addition, ASAN hijacks pthread_create() so
+dnl we can't use that anymore.
+AC_SEARCH_LIBS([pthread_kill], [pthread], [], [])
 
 dnl XXX The following check incorrectly causes the build to succeed
 dnl on Darwin. We should be using AC_SEARCH_LIBS, but rest_init is

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b4dea28a/proxy/Makefile.am
----------------------------------------------------------------------
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 6dc0f6f..0160294 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -233,7 +233,6 @@ traffic_server_LDADD = \
   @LIBPROFILER@ \
   @SPDYLAY_LIBS@ \
   @OPENSSL_LIBS@ \
-  @LIBPTHREAD@ \
   -lm
 
 if BUILD_LUAJIT
@@ -255,7 +254,7 @@ traffic_logcat_LDADD = \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/lib/ts/libtsutil.la \
   @LIBRESOLV@ @LIBPCRE@ @LIBTCL@ @HWLOC_LIBS@\
-  @LIBEXPAT@ @LIBPROFILER@ @LIBPTHREAD@ -lm
+  @LIBEXPAT@ @LIBPROFILER@ -lm
 
 traffic_logstats_SOURCES = logstats.cc
 traffic_logstats_LDADD = \
@@ -268,7 +267,7 @@ traffic_logstats_LDADD = \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/lib/ts/libtsutil.la \
   @LIBRESOLV@ @LIBPCRE@ @LIBTCL@ @HWLOC_LIBS@ \
-  @LIBEXPAT@ @LIBPROFILER@ @LIBPTHREAD@ -lm
+  @LIBEXPAT@ @LIBPROFILER@ -lm
 
 traffic_sac_SOURCES = \
   sac.cc \
@@ -331,7 +330,6 @@ traffic_sac_LDADD = \
   @LIBPROFILER@ \
   @SPDYLAY_LIBS@ \
   @OPENSSL_LIBS@ \
-  @LIBPTHREAD@ \
   -lm
 
 if BUILD_TESTS


[12/14] trafficserver git commit: TS-3824 Fix #include of pcre for a couple of plugins

Posted by zw...@apache.org.
TS-3824 Fix #include of pcre for a couple of plugins


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

Branch: refs/heads/6.0.x
Commit: 8939a3c68691137751fa11687b4b891505d8e510
Parents: 4019b97
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Aug 5 21:08:10 2015 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Wed Aug 5 21:08:10 2015 -0600

----------------------------------------------------------------------
 plugins/experimental/url_sig/url_sig.c | 1 +
 plugins/experimental/url_sig/url_sig.h | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8939a3c6/plugins/experimental/url_sig/url_sig.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c
index 046800d..fe90ee7 100644
--- a/plugins/experimental/url_sig/url_sig.c
+++ b/plugins/experimental/url_sig/url_sig.c
@@ -16,6 +16,7 @@
   limitations under the License.
  */
 
+#include "ts/ink_defs.h"
 #include "url_sig.h"
 
 #include <stdio.h>

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8939a3c6/plugins/experimental/url_sig/url_sig.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/url_sig/url_sig.h b/plugins/experimental/url_sig/url_sig.h
index d2f4cd0..6e22600 100644
--- a/plugins/experimental/url_sig/url_sig.h
+++ b/plugins/experimental/url_sig/url_sig.h
@@ -19,7 +19,6 @@
 #ifndef URL_SIG_H_
 #define URL_SIG_H_
 
-#define VERSION "1.0"
 /* in the query string that we add to sign the url: */
 #define CIP_QSTRING "C" /* C=24.0.33.12 designates the client IP address */
 #define EXP_QSTRING "E" /* E=1356128799 means expires at (seconds since Unix epoch) */