GitHub PullRequestReviewCommentEvent at 2014-04-17 04:31:54
Repository: netty
Actor: normanmaurer
Payload: {"comment":{"url":"https://api.github.com/repos/netty/netty/pulls/comments/11718395","id":11718395,"diff_hunk":"@@ -0,0 +1,164 @@\n+/*\n+ * Copyright 2014 The Netty Project\n+ *\n+ * The Netty Project licenses this file to you under the Apache License,\n+ * version 2.0 (the \"License\"); you may not use this file except in compliance\n+ * with the License. You may obtain a copy of the License at:\n+ *\n+ *   http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n+ * License for the specific language governing permissions and limitations\n+ * under the License.\n+ */\n+package io.netty.handler.codec.http2.draft10;\n+\n+import io.netty.buffer.ByteBuf;\n+import io.netty.channel.ChannelHandler;\n+import io.netty.channel.ChannelHandlerContext;\n+import io.netty.channel.ChannelPipeline;\n+import io.netty.handler.codec.ByteToMessageDecoder;\n+import io.netty.handler.codec.http.HttpObjectAggregator;\n+import io.netty.handler.codec.http.HttpRequestDecoder;\n+import io.netty.handler.codec.http.HttpResponseEncoder;\n+import io.netty.handler.codec.http2.draft10.connection.Http2ConnectionHandler;\n+import io.netty.handler.codec.http2.draft10.frame.Http2FrameCodec;\n+import io.netty.handler.ssl.SslHandler;\n+\n+import javax.net.ssl.SSLEngine;\n+import java.util.List;\n+\n+/**\n+ * {@link io.netty.channel.ChannelHandler} which is responsible to setup the {@link io.netty.channel.ChannelPipeline}\n+ * either for HTTP or HTTP2. This offers an easy way for users to support both at the same time while not care to much\n+ * about the low-level details.\n+ */\n+public abstract class Http2OrHttpChooser extends ByteToMessageDecoder {\n+\n+    // TODO: Replace with generic NPN handler\n+\n+    public enum SelectedProtocol {\n+        /** Must be updated to match the HTTP/2 draft number. */\n+        HTTP_2(\"h2-10\"),\n+        HTTP_1_1(\"http/1.1\"),\n+        HTTP_1_0(\"http/1.0\"),\n+        UNKNOWN(\"Unknown\");\n+\n+        private final String name;\n+\n+        SelectedProtocol(String defaultName) {\n+            name = defaultName;\n+        }\n+\n+        public String protocolName() {\n+            return name;\n+        }\n+\n+        /**\n+         * Get an instance of this enum based on the protocol name returned by the NPN server provider\n+         *\n+         * @param name\n+         *            the protocol name\n+         * @return the SelectedProtocol instance\n+         */\n+        public static SelectedProtocol protocol(String name) {\n+            for (SelectedProtocol protocol : SelectedProtocol.values()) {\n+                if (protocol.protocolName().equals(name)) {\n+                    return protocol;\n+                }\n+            }\n+            return UNKNOWN;\n+        }\n+    }\n+\n+    private final int maxHttpContentLength;\n+\n+    protected Http2OrHttpChooser(int maxHttpContentLength) {\n+        this.maxHttpContentLength = maxHttpContentLength;\n+    }\n+\n+    /**\n+     * Return the {@link SelectedProtocol} for the {@link javax.net.ssl.SSLEngine}. If its not known yet implementations\n+     * MUST return {@link SelectedProtocol#UNKNOWN}.\n+     *\n+     */\n+    protected abstract SelectedProtocol getProtocol(SSLEngine engine);\n+\n+    @Override\n+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {\n+        if (initPipeline(ctx)) {\n+            // When we reached here we can remove this handler as its now clear\n+            // what protocol we want to use\n+            // from this point on. This will also take care of forward all\n+            // messages.\n+            ctx.pipeline().remove(this);\n+        }\n+    }\n+\n+    private boolean initPipeline(ChannelHandlerContext ctx) {\n+        // Get the SslHandler from the ChannelPipeline so we can obtain the\n+        // SslEngine from it.\n+        SslHandler handler = ctx.pipeline().get(SslHandler.class);\n+        if (handler == null) {\n+            // HTTP2 is negotiated through SSL.\n+            throw new IllegalStateException(\"SslHandler is needed for HTTP2\");\n+        }\n+\n+        SelectedProtocol protocol = getProtocol(handler.engine());\n+        switch (protocol) {\n+            case UNKNOWN:\n+                // Not done with choosing the protocol, so just return here for now,\n+                return false;\n+            case HTTP_2:\n+                addHttp2Handlers(ctx);\n+                break;\n+            case HTTP_1_0:\n+            case HTTP_1_1:\n+                addHttpHandlers(ctx);\n+                break;\n+            default:\n+                throw new IllegalStateException(\"Unknown SelectedProtocol\");\n+        }\n+        return true;\n+    }\n+\n+    /**\n+     * Add all {@link io.netty.channel.ChannelHandler}'s that are needed for HTTP_2.\n+     */\n+    protected void addHttp2Handlers(ChannelHandlerContext ctx) {\n+        ChannelPipeline pipeline = ctx.pipeline();\n+        pipeline.addLast(\"http2FrameCodec\", new Http2FrameCodec());\n+        pipeline.addLast(\"http2ConnectionHandler\", new Http2ConnectionHandler(true));\n+        pipeline.addLast(\"httpRequestHandler\", createHttpRequestHandlerForHttp2());\n+    }\n+\n+    /**\n+     * Add all {@link io.netty.channel.ChannelHandler}'s that are needed for HTTP.\n+     */\n+    protected void addHttpHandlers(ChannelHandlerContext ctx) {\n+        ChannelPipeline pipeline = ctx.pipeline();\n+        pipeline.addLast(\"httpRequestDecoder\", new HttpRequestDecoder());\n+        pipeline.addLast(\"httpResponseEncoder\", new HttpResponseEncoder());\n+        pipeline.addLast(\"httpChunkAggregator\", new HttpObjectAggregator(maxHttpContentLength));\n+        pipeline.addLast(\"httpRequestHandler\", createHttpRequestHandlerForHttp());\n+    }\n+\n+    /**\n+     * Create the {@link io.netty.channel.ChannelHandler} that is responsible for handling the http requests when the\n+     * {@link SelectedProtocol} was {@link SelectedProtocol#HTTP_1_0} or {@link SelectedProtocol#HTTP_1_1}\n+     */\n+    protected abstract ChannelHandler createHttpRequestHandlerForHttp();","path":"codec-http2/src/main/java/io/netty/handler/codec/http2/draft10/Http2OrHttpChooser.java","position":152,"original_position":152,"commit_id":"145eed3d8c471d048886921b94a049fb25d16d1b","original_commit_id":"145eed3d8c471d048886921b94a049fb25d16d1b","user":{"login":"normanmaurer","id":439362,"avatar_url":"https://avatars.githubusercontent.com/u/439362?","gravatar_id":"e521627c18ed3feaf9db41e754a79483","url":"https://api.github.com/users/normanmaurer","html_url":"https://github.com/normanmaurer","followers_url":"https://api.github.com/users/normanmaurer/followers","following_url":"https://api.github.com/users/normanmaurer/following{/other_user}","gists_url":"https://api.github.com/users/normanmaurer/gists{/gist_id}","starred_url":"https://api.github.com/users/normanmaurer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/normanmaurer/subscriptions","organizations_url":"https://api.github.com/users/normanmaurer/orgs","repos_url":"https://api.github.com/users/normanmaurer/repos","events_url":"https://api.github.com/users/normanmaurer/events{/privacy}","received_events_url":"https://api.github.com/users/normanmaurer/received_events","type":"User","site_admin":false},"body":"Maybe we should name it createHttp1RequestHandler?","created_at":"2014-04-17T04:31:54Z","updated_at":"2014-04-17T04:31:54Z","html_url":"https://github.com/netty/netty/pull/2394#discussion_r11718395","pull_request_url":"https://api.github.com/repos/netty/netty/pulls/2394","_links":{"self":{"href":"https://api.github.com/repos/netty/netty/pulls/comments/11718395"},"html":{"href":"https://github.com/netty/netty/pull/2394#discussion_r11718395"},"pull_request":{"href":"https://api.github.com/repos/netty/netty/pulls/2394"}}}}