| Index: components/cronet/android/test/src/org/chromium/net/Http2TestServer.java
|
| diff --git a/components/cronet/android/test/src/org/chromium/net/Http2TestServer.java b/components/cronet/android/test/src/org/chromium/net/Http2TestServer.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..47cf6642d3ed3d7e75f2d7ed5fa7140a917db88f
|
| --- /dev/null
|
| +++ b/components/cronet/android/test/src/org/chromium/net/Http2TestServer.java
|
| @@ -0,0 +1,176 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.net;
|
| +
|
| +import android.content.Context;
|
| +import android.os.ConditionVariable;
|
| +
|
| +import org.chromium.base.Log;
|
| +import org.chromium.net.test.util.CertTestUtil;
|
| +
|
| +import java.io.File;
|
| +
|
| +import io.netty.bootstrap.ServerBootstrap;
|
| +import io.netty.channel.Channel;
|
| +import io.netty.channel.ChannelHandlerContext;
|
| +import io.netty.channel.ChannelInitializer;
|
| +import io.netty.channel.ChannelOption;
|
| +import io.netty.channel.EventLoopGroup;
|
| +import io.netty.channel.nio.NioEventLoopGroup;
|
| +import io.netty.channel.socket.SocketChannel;
|
| +import io.netty.channel.socket.nio.NioServerSocketChannel;
|
| +import io.netty.handler.codec.http2.Http2SecurityUtil;
|
| +import io.netty.handler.logging.LogLevel;
|
| +import io.netty.handler.logging.LoggingHandler;
|
| +import io.netty.handler.ssl.ApplicationProtocolConfig;
|
| +import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
|
| +import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
|
| +import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
|
| +import io.netty.handler.ssl.ApplicationProtocolNames;
|
| +import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
|
| +import io.netty.handler.ssl.OpenSslServerContext;
|
| +import io.netty.handler.ssl.SslContext;
|
| +import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
| +
|
| +/**
|
| + * Wrapper class to start a HTTP/2 test server.
|
| + */
|
| +public final class Http2TestServer {
|
| + private static final ConditionVariable sBlock = new ConditionVariable();
|
| + private static final String TAG = "Http2TestServer";
|
| +
|
| + // Host-based server.
|
| + static final int PORT = 8443;
|
| +
|
| + public static boolean startHttp2TestServer(
|
| + Context context, String certFileName, String keyFileName) throws Exception {
|
| + (new Thread(
|
| + new Http2TestServerRunnable(new File(CertTestUtil.CERTS_DIRECTORY + certFileName),
|
| + new File(CertTestUtil.CERTS_DIRECTORY + keyFileName))))
|
| + .start();
|
| + sBlock.block();
|
| + return true;
|
| + }
|
| +
|
| + public static void shutdownHttp2TestServer() throws Exception {}
|
| +
|
| + public static String getBaseUrl() {
|
| + return "https://127.0.0.1:" + PORT + '/';
|
| + }
|
| +
|
| + public static String getServerHost() {
|
| + return "127.0.0.1";
|
| + }
|
| +
|
| + public static int getServerPort() {
|
| + return PORT;
|
| + }
|
| +
|
| + static String getEchoAllHeadersUrl() {
|
| + return getBaseUrl() + "echoallheaders";
|
| + }
|
| +
|
| + static String getEchoHeaderUrl(String headerName) {
|
| + return getBaseUrl() + "echoheader?" + headerName;
|
| + }
|
| +
|
| + static String getEchoMethodUrl() {
|
| + return getBaseUrl() + "echomethod";
|
| + }
|
| +
|
| + static String getEchoStreamUrl() {
|
| + return getBaseUrl() + "echostream";
|
| + }
|
| +
|
| + static String getEchoTrailersUrl() {
|
| + return getBaseUrl() + "echotrailers";
|
| + }
|
| +
|
| + private static void onServerStarted() {
|
| + Log.i(TAG, "Http2 server started.");
|
| + sBlock.open();
|
| + }
|
| +
|
| + static class Http2TestServerRunnable implements Runnable {
|
| + File mCertFile;
|
| + File mKeyFile;
|
| +
|
| + Http2TestServerRunnable(File certFile, File keyFile) {
|
| + mCertFile = certFile;
|
| + mKeyFile = keyFile;
|
| + }
|
| +
|
| + public void run() {
|
| + Log.i(TAG, "Hello from Http2TestServerRunnable!");
|
| + try {
|
| + runHttp2TestServer(mCertFile, mKeyFile);
|
| + } catch (Exception e) {
|
| + Log.e(TAG, e.toString());
|
| + }
|
| + }
|
| + }
|
| +
|
| + private static void runHttp2TestServer(File certFile, File keyFile) throws Exception {
|
| + ApplicationProtocolConfig applicationProtocolConfig =
|
| + new ApplicationProtocolConfig(Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE,
|
| + SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2);
|
| +
|
| + final SslContext sslCtx =
|
| + new OpenSslServerContext(certFile, keyFile, null, null, Http2SecurityUtil.CIPHERS,
|
| + SupportedCipherSuiteFilter.INSTANCE, applicationProtocolConfig, 0, 0);
|
| +
|
| + // Configure the server.
|
| + EventLoopGroup group = new NioEventLoopGroup();
|
| + try {
|
| + ServerBootstrap b = new ServerBootstrap();
|
| + b.option(ChannelOption.SO_BACKLOG, 1024);
|
| + b.group(group)
|
| + .channel(NioServerSocketChannel.class)
|
| + .handler(new LoggingHandler(LogLevel.INFO))
|
| + .childHandler(new Http2ServerInitializer(sslCtx));
|
| +
|
| + Channel ch = b.bind(PORT).sync().channel();
|
| + Log.i(TAG, "Netty HTTP/2 server started on " + getBaseUrl());
|
| + onServerStarted();
|
| + ch.closeFuture().sync();
|
| + } finally {
|
| + group.shutdownGracefully();
|
| + }
|
| + Log.i(TAG, "Stopped Http2TestServerRunnable!");
|
| + }
|
| +
|
| + /**
|
| + * Sets up the Netty pipeline for the test server.
|
| + */
|
| + static class Http2ServerInitializer extends ChannelInitializer<SocketChannel> {
|
| + private final SslContext mSslCtx;
|
| +
|
| + public Http2ServerInitializer(SslContext sslCtx) {
|
| + this.mSslCtx = sslCtx;
|
| + }
|
| +
|
| + @Override
|
| + public void initChannel(SocketChannel ch) {
|
| + ch.pipeline().addLast(mSslCtx.newHandler(ch.alloc()), new Http2NegotiationHandler());
|
| + }
|
| + }
|
| +
|
| + static class Http2NegotiationHandler extends ApplicationProtocolNegotiationHandler {
|
| + protected Http2NegotiationHandler() {
|
| + super(ApplicationProtocolNames.HTTP_1_1);
|
| + }
|
| +
|
| + @Override
|
| + protected void configurePipeline(ChannelHandlerContext ctx, String protocol)
|
| + throws Exception {
|
| + if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
|
| + ctx.pipeline().addLast(new Http2TestHandler.Builder().build());
|
| + return;
|
| + }
|
| +
|
| + throw new IllegalStateException("unknown protocol: " + protocol);
|
| + }
|
| + }
|
| +}
|
|
|