Chromium Code Reviews| 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..3b3b10750c4c761f1f12f659248716a034b3b83a |
| --- /dev/null |
| +++ b/components/cronet/android/test/src/org/chromium/net/Http2TestServer.java |
| @@ -0,0 +1,167 @@ |
| +// 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"; |
| + |
| + // Server port. |
| + private static final int PORT = 8443; |
| + |
| + 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; |
| + } |
| + |
| + static boolean shutdownHttp2TestServer() throws Exception { |
|
kapishnikov
2016/01/22 23:19:33
This method does not do anything. Should we gracef
mef
2016/01/25 18:11:25
Done.
|
| + return true; |
| + } |
| + |
| + static String getServerUrl() { |
| + return "https://127.0.0.1:" + PORT + '/'; |
| + } |
| + |
| + static String getServerHost() { |
| + return "127.0.0.1"; |
|
kapishnikov
2016/01/22 23:19:33
We should define 127.0.0.1 as a static constant li
mef
2016/01/25 18:11:25
Done.
|
| + } |
| + |
| + static int getServerPort() { |
| + return PORT; |
| + } |
| + |
| + static String getEchoAllHeadersUrl() { |
| + return getServerUrl() + "echoallheaders"; |
| + } |
| + |
| + static String getEchoHeaderUrl(String headerName) { |
| + return getServerUrl() + "echoheader?" + headerName; |
| + } |
| + |
| + static String getEchoMethodUrl() { |
| + return getServerUrl() + "echomethod"; |
| + } |
| + |
| + static String getEchoStreamUrl() { |
| + return getServerUrl() + "echostream"; |
| + } |
| + |
| + static String getEchoTrailersUrl() { |
| + return getServerUrl() + "echotrailers"; |
| + } |
| + |
| + private static class Http2TestServerRunnable implements Runnable { |
| + private final SslContext mSslCtx; |
| + |
| + Http2TestServerRunnable(File certFile, File keyFile) throws Exception { |
| + ApplicationProtocolConfig applicationProtocolConfig = new ApplicationProtocolConfig( |
| + Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE, |
| + SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2); |
| + |
| + mSslCtx = new OpenSslServerContext(certFile, keyFile, null, null, |
| + Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE, |
| + applicationProtocolConfig, 0, 0); |
| + } |
| + |
| + public void run() { |
| + Log.i(TAG, "Hello from Http2TestServerRunnable!"); |
| + try { |
| + // 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(mSslCtx)); |
| + |
| + Channel ch = b.bind(PORT).sync().channel(); |
| + Log.i(TAG, "Netty HTTP/2 server started on " + getServerUrl()); |
| + sBlock.open(); |
| + ch.closeFuture().sync(); |
| + } finally { |
| + group.shutdownGracefully(); |
| + } |
| + Log.i(TAG, "Stopped Http2TestServerRunnable!"); |
| + } catch (Exception e) { |
| + Log.e(TAG, e.toString()); |
| + } |
| + } |
| + } |
| + |
| + /** |
| + * Sets up the Netty pipeline for the test server. |
| + */ |
| + private 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()); |
| + } |
| + } |
| + |
| + private 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); |
| + } |
| + } |
| + |
| + private Http2TestServer() {} |
| +} |