package org.webpieces.http2client;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
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.mock.Preface;
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.SettingsFrame;
import com.webpieces.http2parser.api.dto.lib.Http2Msg;
/**
* Test this section of rfc..
* http://httpwg.org/specs/rfc7540.html#starting
*/
public class TestC3InitialHttpConnections {
private MockChanMgr mockChanMgr = new MockChanMgr();
private MockHttp2Channel mockChannel = new MockHttp2Channel();;
private Http2Socket socket;
private HeaderSettings localSettings = Requests.createSomeSettings();
private MockTime mockTime = new MockTime(true);
@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());
}
/**
* 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() {
//not sure we need ever so implement only when we need it
}
/**
* 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() {
//verify settings on connect were sent
List<Http2Msg> frames = mockChannel.getFramesAndClear();
Preface preface = (Preface) frames.get(0);
preface.verify();
Http2Msg settings1 = frames.get(1);
Assert.assertEquals(HeaderSettings.createSettingsFrame(localSettings), settings1);
//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.write(new SettingsFrame(true)); //ack client frame
SettingsFrame clientAck = (SettingsFrame) mockChannel.getFrameAndClear();
Assert.assertEquals(true, clientAck.isAck());
}
@Test
public void testSection3_4WithH2cTokenFailsIfHttp1_1() {
//do we want to implement? basically some weird parse error happens and we could catch
//and say this appears not to be http2 to the client
}
}