package com.webpieces.http2engine.impl.client; import java.util.concurrent.CompletableFuture; import javax.xml.bind.DatatypeConverter; import org.webpieces.data.api.DataWrapper; import org.webpieces.data.api.DataWrapperGenerator; import org.webpieces.data.api.DataWrapperGeneratorFactory; import org.webpieces.util.logging.Logger; import org.webpieces.util.logging.LoggerFactory; import org.webpieces.util.threading.SessionExecutor; import com.webpieces.hpack.api.dto.Http2Headers; import com.webpieces.http2engine.api.StreamWriter; import com.webpieces.http2engine.api.client.Http2ResponseListener; import com.webpieces.http2engine.impl.RequestWriterImpl; import com.webpieces.http2engine.impl.shared.Level2Synchro; import com.webpieces.http2engine.impl.shared.Level3ParsingAndRemoteSettings; public class Level2ClientSynchro extends Level2Synchro { private static final Logger log = LoggerFactory.getLogger(Level2ClientSynchro.class); private static final DataWrapperGenerator dataGen = DataWrapperGeneratorFactory.createDataWrapperGenerator(); private static final byte[] preface = DatatypeConverter.parseHexBinary("505249202a20485454502f322e300d0a0d0a534d0d0a0d0a"); private Level8NotifyListeners finalLayer; private Level4ClientStreams streamInit; public Level2ClientSynchro(Level4ClientStreams level3, Level3ParsingAndRemoteSettings parsing, Level8NotifyListeners finalLayer, SessionExecutor executor) { super(level3, parsing, executor); streamInit = level3; this.finalLayer = finalLayer; } public CompletableFuture<Void> sendInitializationToSocket() { //important, this forces the engine to a virtual single thread(each engine/socket has one virtual thread) //this makes it very easy not to have bugs AND very easy to test AND for better throughput, you can //just connect more sockets return executor.executeCall(this, () -> { log.info("sending preface"); DataWrapper prefaceData = dataGen.wrapByteArray(preface); finalLayer.sendPreface(prefaceData); return parsing.sendSettings(); }); } public CompletableFuture<StreamWriter> sendRequestToSocket(Http2Headers headers, Http2ResponseListener responseListener) { //important, this forces the engine to a virtual single thread(each engine/socket has one virtual thread) //this makes it very easy not to have bugs AND very easy to test AND for better throughput, you can //just connect more sockets return executor.executeCall(this, () -> { int streamId = headers.getStreamId(); if(streamId <= 0) throw new IllegalArgumentException("frames for requests must have a streamId > 0"); else if(streamId % 2 == 0) throw new IllegalArgumentException("Client cannot send frames with even stream ids to server per http/2 spec"); return streamInit.createStreamAndSend(headers, responseListener) .thenApply((s) -> new RequestWriterImpl(s, this)); }); } }