diff --git a/example/pom.xml b/example/pom.xml
index 70a2da8cbe..7cc434b794 100644
--- a/example/pom.xml
+++ b/example/pom.xml
@@ -69,6 +69,10 @@
javassistruntime
+
+ org.eclipse.jetty.npn
+ npn-api
+
diff --git a/example/src/main/java/io/netty/example/spdy/SpdyOrHttpHandler.java b/example/src/main/java/io/netty/example/spdy/SpdyOrHttpHandler.java
new file mode 100644
index 0000000000..24329e7122
--- /dev/null
+++ b/example/src/main/java/io/netty/example/spdy/SpdyOrHttpHandler.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project 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.
+ */
+package io.netty.example.spdy;
+
+import javax.net.ssl.SSLEngine;
+
+import io.netty.channel.ChannelInboundHandler;
+import org.eclipse.jetty.npn.NextProtoNego;
+
+import io.netty.handler.codec.spdy.SpdyOrHttpChooser;
+
+/**
+ * Negotiates with the browser if SPDY or HTTP is going to be used. Once decided, the Netty pipeline is setup with
+ * the correct handlers for the selected protocol.
+ */
+public class SpdyOrHttpHandler extends SpdyOrHttpChooser {
+ private static final int MAX_CONTENT_LENGTH = 1024 * 100;
+
+ public SpdyOrHttpHandler() {
+ this(MAX_CONTENT_LENGTH, MAX_CONTENT_LENGTH);
+ }
+
+ public SpdyOrHttpHandler(int maxSpdyContentLength, int maxHttpContentLength) {
+ super(maxSpdyContentLength, maxHttpContentLength);
+ }
+
+ @Override
+ protected SelectedProtocol getProtocol(SSLEngine engine) {
+ SpdyServerProvider provider = (SpdyServerProvider) NextProtoNego.get(engine);
+ String selectedProtocol = provider.getSelectedProtocol();
+
+ System.out.println("Selected Protocol is " + (selectedProtocol == null ? "Unknown" : selectedProtocol));
+
+ if (selectedProtocol == null) {
+ return SpdyOrHttpChooser.SelectedProtocol.UNKNOWN;
+ } else if (selectedProtocol.equalsIgnoreCase("spdy/3.1")) {
+ return SpdyOrHttpChooser.SelectedProtocol.SPDY_3_1;
+ } else if (selectedProtocol.equalsIgnoreCase("spdy/3")) {
+ return SpdyOrHttpChooser.SelectedProtocol.SPDY_3;
+ } else if (selectedProtocol.equalsIgnoreCase("http/1.1")) {
+ return SpdyOrHttpChooser.SelectedProtocol.HTTP_1_1;
+ } else if (selectedProtocol.equalsIgnoreCase("http/1.0")) {
+ return SpdyOrHttpChooser.SelectedProtocol.HTTP_1_0;
+ } else {
+ return SpdyOrHttpChooser.SelectedProtocol.UNKNOWN;
+ }
+ }
+
+ @Override
+ protected ChannelInboundHandler createHttpRequestHandlerForHttp() {
+ return new SpdyServerHandler();
+ }
+
+}
diff --git a/example/src/main/java/io/netty/example/spdy/SpdyServer.java b/example/src/main/java/io/netty/example/spdy/SpdyServer.java
new file mode 100644
index 0000000000..0de13d0481
--- /dev/null
+++ b/example/src/main/java/io/netty/example/spdy/SpdyServer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project 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.
+ */
+package io.netty.example.spdy;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+
+/**
+ * A SPDY Server that responds to a GET request with a Hello World.
+ *
+ * This class must be run with the JVM parameter: {@code java -Xbootclasspath/p: ...}.
+ * The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from
+ * Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions.
+ * See {@link http://www.eclipse.org/jetty/documentation/current/npn-chapter.html Jetty docs} for more information.
+ *
+ * Once started, you can test the server with your
+ * {@link http://en.wikipedia.org/wiki/SPDY#Browser_support_and_usage SPDY enabled web browser} by navigating
+ * to https://localhost:8443/.
+ */
+public class SpdyServer {
+
+ private final int port;
+
+ public SpdyServer(int port) {
+ this.port = port;
+ }
+
+ public void run() throws Exception {
+ // Configure the server.
+ EventLoopGroup bossGroup = new NioEventLoopGroup();
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ ServerBootstrap b = new ServerBootstrap();
+ b.option(ChannelOption.SO_BACKLOG, 1024);
+ b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
+ .childHandler(new SpdyServerInitializer());
+
+ Channel ch = b.bind(port).sync().channel();
+ ch.closeFuture().sync();
+ } finally {
+ bossGroup.shutdownGracefully();
+ workerGroup.shutdownGracefully();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ int port;
+ if (args.length > 0) {
+ port = Integer.parseInt(args[0]);
+ } else {
+ port = 8443;
+ }
+
+ System.out.println("SPDY web server started at port " + port + '.');
+ System.out.println("Open your SPDY enabled browser and navigate to https://localhost:" + port + '/');
+ System.out.println("If using Chrome browser, check your SPDY sessions at chrome://net-internals/#spdy");
+
+ new SpdyServer(port).run();
+ }
+}
diff --git a/example/src/main/java/io/netty/example/spdy/SpdyServerHandler.java b/example/src/main/java/io/netty/example/spdy/SpdyServerHandler.java
new file mode 100644
index 0000000000..9e624b94dd
--- /dev/null
+++ b/example/src/main/java/io/netty/example/spdy/SpdyServerHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project 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.
+ */
+package io.netty.example.spdy;
+
+import java.util.Date;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.util.CharsetUtil;
+
+import static io.netty.handler.codec.http.HttpHeaders.Names.*;
+import static io.netty.handler.codec.http.HttpHeaders.*;
+import static io.netty.handler.codec.http.HttpResponseStatus.*;
+import static io.netty.handler.codec.http.HttpVersion.*;
+
+/**
+ * HTTP handler that responds with a "Hello World"
+ */
+public class SpdyServerHandler extends SimpleChannelInboundHandler