package org.webpieces.http2client; import java.net.InetSocketAddress; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.webpieces.data.api.DataWrapper; import org.webpieces.http2client.api.Http2Client; import org.webpieces.http2client.api.Http2ClientFactory; import org.webpieces.http2client.api.Http2Socket; import org.webpieces.http2client.mock.MockChanMgr; import org.webpieces.http2client.mock.MockHttp2Channel; import org.webpieces.http2client.util.Requests; import org.webpieces.mock.time.MockTime; 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.GoAwayFrame; import com.webpieces.http2parser.api.dto.lib.Http2ErrorCode; /** * Test this section of rfc.. * http://httpwg.org/specs/rfc7540.html#SETTINGS */ public class TestC6_5SettingsFrameErrors { private MockChanMgr mockChanMgr = new MockChanMgr();; private MockHttp2Channel mockChannel = new MockHttp2Channel(); private HeaderSettings localSettings = Requests.createSomeSettings(); private MockTime mockTime = new MockTime(true); private Http2Socket socket; @Before public void setUp() throws InterruptedException, ExecutionException { mockChannel.setIncomingFrameDefaultReturnValue(CompletableFuture.completedFuture(mockChannel)); Http2Config config = new Http2Config(); config.setInitialRemoteMaxConcurrent(1); //start with 1 max concurrent config.setLocalSettings(localSettings); InjectionConfig injConfig = new InjectionConfig(new DirectExecutor(), mockTime, config); Http2Client client = Http2ClientFactory.createHttpClient(mockChanMgr, injConfig); mockChanMgr.addTCPChannelToReturn(mockChannel); socket = client.createHttpSocket("simple"); CompletableFuture<Http2Socket> connect = socket.connect(new InetSocketAddress(555)); Assert.assertTrue(connect.isDone()); Assert.assertEquals(socket, connect.get()); //clear preface and settings frame from client mockChannel.getFramesAndClear(); } @Ignore @Test public void testSection6_5_3SettingsAckNotReceivedInReasonableTime() { } @Test public void testSection6_5AckNonEmptyPayload() { //server's settings frame is finally coming in as well with maxConcurrent=1 HeaderSettings settings = new HeaderSettings(); settings.setMaxConcurrentStreams(1L); mockChannel.write(HeaderSettings.createSettingsFrame(settings)); mockChannel.getFrameAndClear(); //clear the ack frame String badAckFrame = "00 00 01" + // length "04" + // type "01" + // flags (ack) "00 00 00 00" + // R + streamid "00"; //payload mockChannel.writeHexBack(badAckFrame); //ack client frame //remote receives goAway GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear(); DataWrapper debugData = goAway.getDebugData(); String msg = debugData.createStringFromUtf8(0, debugData.getReadableSize()); Assert.assertEquals("size of payload of a settings frame ack must be 0 but was=1 reason=FRAME_SIZE_INCORRECT stream=0", msg); Assert.assertTrue(mockChannel.isClosed()); } @Test public void testSection6_5SettingsStreamIdNonZeroValue() { //server's settings frame is finally coming in as well with maxConcurrent=1 String badStreamIdSettings = "00 00 0C" + // length "04" + // type "00" + //flags "00 00 00 01" + //R + streamid "00 02 00 00 00 01" + //setting 1 (enable push) "00 03 00 00 01 00"; //setting 2 (max streams) mockChannel.writeHexBack(badStreamIdSettings); //remote receives goAway GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear(); Assert.assertEquals(Http2ErrorCode.PROTOCOL_ERROR, goAway.getKnownErrorCode()); Assert.assertTrue(mockChannel.isClosed()); } @Test public void testSection6_5SettingsFrameLengthMultipleNotSixOctects() { //server's settings frame is finally coming in as well with maxConcurrent=1 String badStreamIdSettings = "00 00 0B" + // length "04" + // type "00" + //flags "00 00 00 00" + //R + streamid "00 02 00 00 00 01" + //setting 1 (enable push) "00 03 00 00 01"; //setting 2 (max streams) mockChannel.writeHexBack(badStreamIdSettings); //remote receives goAway GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear(); Assert.assertEquals(Http2ErrorCode.FRAME_SIZE_ERROR, goAway.getKnownErrorCode()); Assert.assertTrue(mockChannel.isClosed()); } @Test public void testSection6_5_2PushPromiseOffButServerSentIt() { } @Test public void testSection6_5_2InitialWindowSizeTooLarge() { //server's settings frame is finally coming in as well with maxConcurrent=1 String badStreamIdSettings = "00 00 0C" + // length "04" + // type "00" + //flags "00 00 00 00" + //R + streamid "00 02 00 00 00 01" + //setting 1 (enable push) "00 04 FF FF FF FF"; //setting 2 (initial window size) mockChannel.writeHexBack(badStreamIdSettings); //remote receives goAway GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear(); Assert.assertEquals(Http2ErrorCode.FLOW_CONTROL_ERROR, goAway.getKnownErrorCode()); Assert.assertTrue(mockChannel.isClosed()); } @Test public void testSection6_5_2MaxFrameSizeOutsideAllowedRange() { //server's settings frame is finally coming in as well with maxConcurrent=1 String badStreamIdSettings = "00 00 0C" + // length "04" + // type "00" + //flags "00 00 00 00" + //R + streamid "00 02 00 00 00 01" + //setting 1 (enable push) "00 05 00 00 00 00"; //setting 2 (initial window size) mockChannel.writeHexBack(badStreamIdSettings); //remote receives goAway GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear(); Assert.assertEquals(Http2ErrorCode.PROTOCOL_ERROR, goAway.getKnownErrorCode()); Assert.assertTrue(mockChannel.isClosed()); } }