package org.webpieces.httpfrontend2.api.http2; import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.webpieces.frontend2.api.FrontendConfig; import org.webpieces.frontend2.api.HttpFrontendFactory; import org.webpieces.frontend2.api.HttpFrontendManager; import org.webpieces.frontend2.api.HttpServer; import org.webpieces.httpfrontend2.api.mock2.MockChanMgr; import org.webpieces.httpfrontend2.api.mock2.MockHttp2Channel; import org.webpieces.httpfrontend2.api.mock2.MockHttp2RequestListener; import org.webpieces.httpfrontend2.api.mock2.MockStreamWriter; import org.webpieces.httpfrontend2.api.mock2.MockTcpServerChannel; import org.webpieces.httpfrontend2.api.mock2.MockTimer; import org.webpieces.mock.time.MockTime; import org.webpieces.nio.api.handlers.ConnectionListener; import org.webpieces.nio.api.handlers.DataListener; import org.webpieces.util.threading.DirectExecutor; import com.webpieces.http2engine.api.client.Http2Config; import com.webpieces.http2engine.api.client.InjectionConfig; import com.webpieces.http2engine.impl.shared.HeaderSettings; import com.webpieces.http2parser.api.dto.SettingsFrame; import com.webpieces.http2parser.api.dto.lib.Http2Msg; /** * Test this section of rfc.. * http://httpwg.org/specs/rfc7540.html#starting */ public class TestS3InitialHttpConnections { private MockChanMgr mockChanMgr = new MockChanMgr(); private MockHttp2Channel mockChannel = new MockHttp2Channel(); private HeaderSettings localSettings = Http2Requests.createSomeSettings(); private MockTime mockTime = new MockTime(true); private MockTimer mockTimer = new MockTimer(); private MockHttp2RequestListener mockListener = new MockHttp2RequestListener(); private MockStreamWriter mockStreamWriter = new MockStreamWriter(); @Before public void setUp() throws InterruptedException, ExecutionException, TimeoutException { MockTcpServerChannel svrChannel = new MockTcpServerChannel(); mockChanMgr.addTCPSvrChannelToReturn(svrChannel); mockChannel.setIncomingFrameDefaultReturnValue(CompletableFuture.completedFuture(mockChannel)); mockListener.setDefaultRetVal(mockStreamWriter); mockStreamWriter.setDefaultRetValToThis(); Http2Config config = new Http2Config(); config.setLocalSettings(localSettings); InjectionConfig injConfig = new InjectionConfig(new DirectExecutor(), mockTime, config); FrontendConfig frontendConfig = new FrontendConfig("http", new InetSocketAddress("me", 8080)); HttpFrontendManager manager = HttpFrontendFactory.createFrontEnd(mockChanMgr, mockTimer, injConfig); HttpServer httpServer = manager.createHttpServer(frontendConfig, mockListener); httpServer.start(); ConnectionListener listener = mockChanMgr.getSingleConnectionListener(); CompletableFuture<DataListener> futureList = listener.connected(mockChannel, true); DataListener dataListener = futureList.get(3, TimeUnit.SECONDS); mockChannel.setDataListener(dataListener); } /** * Works with everyone but incurs a round trip overhead * * should send * * GET / HTTP/1.1 * Host: server.example.com * Connection: Upgrade, HTTP2-Settings * Upgrade: h2c * HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload> * * Server sends * HTTP/1.1 101 Switching Protocols * Connection: Upgrade * Upgrade: h2c * * The first HTTP/2 frame sent by the server MUST be a server connection preface (Section 3.5) * consisting of a SETTINGS frame (Section 6.5). Upon * receiving the 101 response, the client MUST send a connection preface * (Section 3.5), which includes a SETTINGS frame. */ @Test public void testSection3_2WithH2cTokenAfterUpgrade() { } /** * Only will work with webpieces and 'jetty with alpn installed' * * should send PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n * and server sends back it's preface... * The server connection preface consists of a potentially empty SETTINGS * frame (Section 6.5) that MUST be the first frame the server sends in the HTTP/2 connection. * * SettingsFrame{streamId=0, ack=false, settings=[{SETTINGS_HEADER_TABLE_SIZE: 4096}, {SETTINGS_MAX_CONCURRENT_STREAMS: 1024}, {SETTINGS_INITIAL_WINDOW_SIZE: 65535}, {SETTINGS_MAX_HEADER_LIST_SIZE: 8192}]} * SettingsFrame{streamId=0, ack=true, settings=[]} */ @Test public void testSection3_4WithH2cTokenPriorKnowledge() { HeaderSettings settings = Http2Requests.createSomeSettings(); mockChannel.sendPrefaceAndSettings(HeaderSettings.createSettingsFrame(settings)); List<Http2Msg> frames = mockChannel.getFramesAndClear(); Assert.assertEquals(2, frames.size()); SettingsFrame serverSettings = (SettingsFrame) frames.get(0); Assert.assertFalse(serverSettings.isAck()); SettingsFrame ackClientSettings = (SettingsFrame) frames.get(1); Assert.assertTrue(ackClientSettings.isAck()); } }