Search in sources :

Example 1 with StreamWriter

use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.

the class TestC5_1StreamStates method testSection5_1ReceiveBadFrameAfterReceiveRstStreamFrame.

/**
	 * An endpoint MUST NOT send frames other than PRIORITY on a closed stream. An endpoint 
	 * that receives any frame other than PRIORITY after receiving a ----RST_STREAM---- MUST 
	 * treat that as a stream error (Section 5.4.2) of type STREAM_CLOSED. Similarly, an 
	 * endpoint that receives any frames after receiving a frame with the 
	 * END_STREAM flag set MUST treat that as a connection error (Section 5.4.1) of 
	 * type STREAM_CLOSED, unless the frame is permitted as described below.
	 * 
	 */
@Test
public void testSection5_1ReceiveBadFrameAfterReceiveRstStreamFrame() {
    MockStreamWriter mockWriter = new MockStreamWriter();
    MockResponseListener listener1 = new MockResponseListener();
    listener1.setIncomingRespDefault(CompletableFuture.<StreamWriter>completedFuture(mockWriter));
    Http2Request request = sendRequestToServer(listener1);
    sendResetFromServer(listener1, request);
    DataFrame dataFrame = new DataFrame(request.getStreamId(), false);
    mockChannel.write(dataFrame);
    //remote receives goAway
    GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear();
    Assert.assertEquals(Http2ErrorCode.STREAM_CLOSED, goAway.getKnownErrorCode());
    DataWrapper debugData = goAway.getDebugData();
    String msg = debugData.createStringFromUtf8(0, debugData.getReadableSize());
    Assert.assertEquals("ConnectionException: MockHttp2Channel1:stream1:(CLOSED_STREAM) " + "Stream must have been closed as it no longer exists.  high mark=1  " + "your frame=DataFrame{streamId=1, endStream=false, data.len=0, padding=0}", msg);
    Assert.assertTrue(mockChannel.isClosed());
    Assert.assertEquals(0, listener1.getReturnValuesIncomingResponse().size());
    //send new request on closed connection
    Http2Request request1 = Requests.createRequest();
    CompletableFuture<StreamWriter> future = httpSocket.openStream().process(request1, listener1);
    ConnectionClosedException intercept = (ConnectionClosedException) TestAssert.intercept(future);
    Assert.assertTrue(intercept.getMessage().contains("Connection closed or closing"));
    Assert.assertEquals(0, mockChannel.getFramesAndClear().size());
}
Also used : DataWrapper(org.webpieces.data.api.DataWrapper) Http2Request(com.webpieces.hpack.api.dto.Http2Request) MockStreamWriter(org.webpieces.http2client.mock.MockStreamWriter) StreamWriter(com.webpieces.http2engine.api.StreamWriter) MockResponseListener(org.webpieces.http2client.mock.MockResponseListener) ConnectionClosedException(com.webpieces.http2engine.api.ConnectionClosedException) DataFrame(com.webpieces.http2parser.api.dto.DataFrame) MockStreamWriter(org.webpieces.http2client.mock.MockStreamWriter) GoAwayFrame(com.webpieces.http2parser.api.dto.GoAwayFrame) Test(org.junit.Test)

Example 2 with StreamWriter

use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.

the class TestC5_1StreamStates method testSection5_1ReceiveValidFramesAfterSendRstStreamFrame.

/**
	 * If this state is reached as a result of sending a RST_STREAM frame, the 
	 * peer that receives the RST_STREAM might have already sent — or enqueued for 
	 * sending — frames on the stream that cannot be withdrawn. An endpoint MUST ignore 
	 * frames that it receives on closed streams after it has sent a RST_STREAM frame. An 
	 * endpoint MAY choose to limit the period over which it ignores frames and 
	 * treat frames that arrive after this time as being in error.
	 * @throws TimeoutException 
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 */
@Test
public void testSection5_1ReceiveValidFramesAfterSendRstStreamFrame() throws InterruptedException, ExecutionException, TimeoutException {
    MockResponseListener listener1 = new MockResponseListener();
    listener1.setIncomingRespDefault(CompletableFuture.<StreamWriter>completedFuture(null));
    Http2Request request1 = Requests.createRequest();
    StreamHandle stream = httpSocket.openStream();
    CompletableFuture<StreamWriter> future = stream.process(request1, listener1);
    @SuppressWarnings("unused") StreamWriter writer = future.get(2, TimeUnit.SECONDS);
    Http2Msg req = mockChannel.getFrameAndClear();
    Assert.assertEquals(request1, req);
    RstStreamFrame rst = new RstStreamFrame(request1.getStreamId(), Http2ErrorCode.CANCEL);
    CompletableFuture<Void> cancel = stream.cancel(rst);
    cancel.get(2, TimeUnit.SECONDS);
    Http2Msg svrRst = mockChannel.getFrameAndClear();
    Assert.assertEquals(rst, svrRst);
    //simulate server responding before receiving the cancel
    Http2Response resp1 = Requests.createEosResponse(request1.getStreamId());
    //endOfStream=true
    mockChannel.write(resp1);
//		Assert.assertEquals(0, mockChannel.getFramesAndClear().size());
//		Assert.assertFalse(mockChannel.isClosed());
//		
//		Assert.assertEquals(0, listener1.getReturnValuesIncomingResponse().size());
}
Also used : Http2Response(com.webpieces.hpack.api.dto.Http2Response) Http2Request(com.webpieces.hpack.api.dto.Http2Request) RstStreamFrame(com.webpieces.http2parser.api.dto.RstStreamFrame) StreamHandle(com.webpieces.http2engine.api.StreamHandle) MockStreamWriter(org.webpieces.http2client.mock.MockStreamWriter) StreamWriter(com.webpieces.http2engine.api.StreamWriter) MockResponseListener(org.webpieces.http2client.mock.MockResponseListener) Http2Msg(com.webpieces.http2parser.api.dto.lib.Http2Msg) Test(org.junit.Test)

Example 3 with StreamWriter

use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.

the class ProxyResponse method sendChunkedResponse.

private CompletableFuture<Void> sendChunkedResponse(Http2Response resp, byte[] bytes, final Compression compression) {
    boolean compressed = false;
    Compression usingCompression;
    if (compression == null) {
        usingCompression = new NoCompression();
    } else {
        usingCompression = compression;
        compressed = true;
        resp.addHeader(new Http2Header(Http2HeaderName.CONTENT_ENCODING, usingCompression.getCompressionType()));
    }
    log.info("sending RENDERHTML response. size=" + bytes.length + " code=" + resp + " for domain=" + routerRequest.domain + " path" + routerRequest.relativePath + " responseSender=" + stream);
    boolean isCompressed = compressed;
    // Send the headers and get the responseid.
    return stream.sendResponse(resp).thenCompose(writer -> {
        List<DataFrame> frames = possiblyCompress(bytes, usingCompression, isCompressed);
        CompletableFuture<StreamWriter> future = CompletableFuture.completedFuture(writer);
        for (int i = 0; i < frames.size(); i++) {
            DataFrame f = frames.get(i);
            if (i == frames.size() - 1)
                f.setEndOfStream(true);
            future = future.thenCompose(v -> {
                return writer.processPiece(f);
            });
        }
        return future;
    }).thenApply(w -> null);
}
Also used : TemplateUtil(org.webpieces.templating.api.TemplateUtil) BufferPool(org.webpieces.data.api.BufferPool) BootstrapModalTag(org.webpieces.templating.impl.tags.BootstrapModalTag) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CompletableFuture(java.util.concurrent.CompletableFuture) ResponseEncodingTuple(org.webpieces.webserver.impl.ResponseCreator.ResponseEncodingTuple) Inject(javax.inject.Inject) View(org.webpieces.router.api.dto.View) RouterRequest(org.webpieces.ctx.api.RouterRequest) Charset(java.nio.charset.Charset) Http2Request(com.webpieces.hpack.api.dto.Http2Request) IllegalReturnValueException(org.webpieces.router.api.exceptions.IllegalReturnValueException) CompressionLookup(org.webpieces.router.impl.compression.CompressionLookup) DataWrapperGeneratorFactory(org.webpieces.data.api.DataWrapperGeneratorFactory) MissingPropertyException(groovy.lang.MissingPropertyException) RenderContentResponse(org.webpieces.router.api.dto.RenderContentResponse) OutputStream(java.io.OutputStream) Logger(org.webpieces.util.logging.Logger) RenderStaticResponse(org.webpieces.router.api.dto.RenderStaticResponse) StatusCode(com.webpieces.http2parser.api.dto.StatusCode) StringWriter(java.io.StringWriter) Set(java.util.Set) Http2Header(com.webpieces.http2parser.api.dto.lib.Http2Header) IOException(java.io.IOException) ResponseStreamer(org.webpieces.router.api.ResponseStreamer) Http2HeaderName(com.webpieces.http2parser.api.dto.lib.Http2HeaderName) List(java.util.List) WebServerConfig(org.webpieces.webserver.api.WebServerConfig) StreamWriter(com.webpieces.http2engine.api.StreamWriter) TemplateService(org.webpieces.templating.api.TemplateService) DataWrapperGenerator(org.webpieces.data.api.DataWrapperGenerator) LoggerFactory(org.webpieces.util.logging.LoggerFactory) RedirectResponse(org.webpieces.router.api.dto.RedirectResponse) Http2Response(com.webpieces.hpack.api.dto.Http2Response) ResponseStream(org.webpieces.frontend2.api.ResponseStream) RenderResponse(org.webpieces.router.api.dto.RenderResponse) DataFrame(com.webpieces.http2parser.api.dto.DataFrame) Compression(org.webpieces.router.impl.compression.Compression) Compression(org.webpieces.router.impl.compression.Compression) CompletableFuture(java.util.concurrent.CompletableFuture) Http2Header(com.webpieces.http2parser.api.dto.lib.Http2Header) List(java.util.List) DataFrame(com.webpieces.http2parser.api.dto.DataFrame)

Example 4 with StreamWriter

use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.

the class StaticFileReader method runAsyncFileRead.

private CompletableFuture<Void> runAsyncFileRead(RequestInfo info, RenderStaticResponse renderStatic) throws IOException {
    boolean isFile = true;
    String fullFilePath = renderStatic.getFilePath();
    if (fullFilePath == null) {
        isFile = false;
        fullFilePath = renderStatic.getDirectory() + renderStatic.getRelativePath();
    }
    String extension = null;
    int lastDirIndex = fullFilePath.lastIndexOf("/");
    int lastDot = fullFilePath.lastIndexOf(".");
    if (lastDot > lastDirIndex) {
        extension = fullFilePath.substring(lastDot + 1);
    }
    ResponseEncodingTuple tuple = responseCreator.createResponse(info.getRequest(), StatusCode.HTTP_200_OK, extension, "application/octet-stream", false);
    Http2Response response = tuple.response;
    //On startup, we protect developers from breaking clients.  In http, all files that change
    //must also change the hash automatically and the %%{ }%% tag generates those hashes so the
    //files loaded are always the latest
    Long timeMs = config.getStaticFileCacheTimeSeconds();
    if (timeMs != null)
        response.addHeader(new Http2Header(Http2HeaderName.CACHE_CONTROL, "max-age=" + timeMs));
    Path file;
    Compression compr = compressionLookup.createCompressionStream(info.getRouterRequest().encodings, extension, tuple.mimeType);
    //during startup as I don't feel like paying a cpu penalty for compressing while live
    if (compr != null && compr.getCompressionType().equals(routerConfig.getStartupCompression())) {
        response.addHeader(new Http2Header(Http2HeaderName.CONTENT_ENCODING, compr.getCompressionType()));
        File routesCache = renderStatic.getTargetCache();
        File fileReference;
        if (isFile) {
            String fileName = fullFilePath.substring(lastDirIndex + 1);
            fileReference = new File(routesCache, fileName);
        } else {
            fileReference = new File(routesCache, renderStatic.getRelativePath());
        }
        fullFilePath = fileReference.getAbsolutePath();
        file = fetchFile("Compressed File from cache=", fullFilePath + ".gz");
    } else {
        file = fetchFile("File=", fullFilePath);
    }
    AsynchronousFileChannel asyncFile = AsynchronousFileChannel.open(file, options, fileExecutor);
    CompletableFuture<StreamWriter> future;
    try {
        log.info(() -> "sending chunked file via async read=" + file);
        long length = file.toFile().length();
        AtomicLong remaining = new AtomicLong(length);
        future = info.getResponseSender().sendResponse(response).thenCompose(s -> readLoop(s, info.getPool(), file, asyncFile, 0, remaining));
    } catch (Throwable e) {
        future = new CompletableFuture<StreamWriter>();
        future.completeExceptionally(e);
    }
    return //our finally block for failures
    future.handle((s, exc) -> handleClose(info, s, exc)).thenAccept(s -> empty());
}
Also used : Path(java.nio.file.Path) BufferPool(org.webpieces.data.api.BufferPool) RouterConfig(org.webpieces.router.api.RouterConfig) AsynchronousFileChannel(java.nio.channels.AsynchronousFileChannel) CompletableFuture(java.util.concurrent.CompletableFuture) ResponseEncodingTuple(org.webpieces.webserver.impl.ResponseCreator.ResponseEncodingTuple) Singleton(javax.inject.Singleton) ByteBuffer(java.nio.ByteBuffer) HashSet(java.util.HashSet) Inject(javax.inject.Inject) DataWrapper(org.webpieces.data.api.DataWrapper) Named(javax.inject.Named) CompressionLookup(org.webpieces.router.impl.compression.CompressionLookup) Path(java.nio.file.Path) DataWrapperGeneratorFactory(org.webpieces.data.api.DataWrapperGeneratorFactory) ExecutorService(java.util.concurrent.ExecutorService) Logger(org.webpieces.util.logging.Logger) RenderStaticResponse(org.webpieces.router.api.dto.RenderStaticResponse) StatusCode(com.webpieces.http2parser.api.dto.StatusCode) OpenOption(java.nio.file.OpenOption) CompletionHandler(java.nio.channels.CompletionHandler) StandardOpenOption(java.nio.file.StandardOpenOption) Set(java.util.Set) HttpFrontendFactory(org.webpieces.frontend2.api.HttpFrontendFactory) Http2Header(com.webpieces.http2parser.api.dto.lib.Http2Header) IOException(java.io.IOException) File(java.io.File) Http2HeaderName(com.webpieces.http2parser.api.dto.lib.Http2HeaderName) AtomicLong(java.util.concurrent.atomic.AtomicLong) BufferCreationPool(org.webpieces.data.api.BufferCreationPool) WebServerConfig(org.webpieces.webserver.api.WebServerConfig) StreamWriter(com.webpieces.http2engine.api.StreamWriter) Paths(java.nio.file.Paths) NotFoundException(org.webpieces.router.api.exceptions.NotFoundException) DataWrapperGenerator(org.webpieces.data.api.DataWrapperGenerator) LoggerFactory(org.webpieces.util.logging.LoggerFactory) Http2Response(com.webpieces.hpack.api.dto.Http2Response) DataFrame(com.webpieces.http2parser.api.dto.DataFrame) Compression(org.webpieces.router.impl.compression.Compression) Http2Response(com.webpieces.hpack.api.dto.Http2Response) Compression(org.webpieces.router.impl.compression.Compression) Http2Header(com.webpieces.http2parser.api.dto.lib.Http2Header) StreamWriter(com.webpieces.http2engine.api.StreamWriter) AsynchronousFileChannel(java.nio.channels.AsynchronousFileChannel) AtomicLong(java.util.concurrent.atomic.AtomicLong) CompletableFuture(java.util.concurrent.CompletableFuture) ResponseEncodingTuple(org.webpieces.webserver.impl.ResponseCreator.ResponseEncodingTuple) AtomicLong(java.util.concurrent.atomic.AtomicLong) File(java.io.File)

Example 5 with StreamWriter

use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.

the class Layer2Http1_1Handler method processData.

private CompletableFuture<Void> processData(FrontendSocketImpl socket, DataFrame msg) {
    PermitQueue permitQueue = socket.getPermitQueue();
    return permitQueue.runRequest(() -> {
        Http1_1StreamImpl stream = socket.getCurrentStream();
        StreamWriter requestWriter = stream.getRequestWriter();
        if (msg.isEndOfStream())
            stream.setSentFullRequest(true);
        return requestWriter.processPiece(msg).thenApply(w -> {
            stream.setRequestWriter(w);
            if (!msg.isEndOfStream())
                permitQueue.releasePermit();
            return null;
        });
    });
}
Also used : PermitQueue(com.webpieces.util.locking.PermitQueue) StreamWriter(com.webpieces.http2engine.api.StreamWriter)

Aggregations

StreamWriter (com.webpieces.http2engine.api.StreamWriter)10 DataFrame (com.webpieces.http2parser.api.dto.DataFrame)6 Http2Request (com.webpieces.hpack.api.dto.Http2Request)5 Http2Response (com.webpieces.hpack.api.dto.Http2Response)4 Test (org.junit.Test)4 DataWrapper (org.webpieces.data.api.DataWrapper)4 MockResponseListener (org.webpieces.http2client.mock.MockResponseListener)4 MockStreamWriter (org.webpieces.http2client.mock.MockStreamWriter)4 ConnectionClosedException (com.webpieces.http2engine.api.ConnectionClosedException)3 GoAwayFrame (com.webpieces.http2parser.api.dto.GoAwayFrame)3 Http2Header (com.webpieces.http2parser.api.dto.lib.Http2Header)3 Http2HeaderName (com.webpieces.http2parser.api.dto.lib.Http2HeaderName)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 Logger (org.webpieces.util.logging.Logger)3 LoggerFactory (org.webpieces.util.logging.LoggerFactory)3 StatusCode (com.webpieces.http2parser.api.dto.StatusCode)2 Http2Msg (com.webpieces.http2parser.api.dto.lib.Http2Msg)2 PermitQueue (com.webpieces.util.locking.PermitQueue)2 IOException (java.io.IOException)2 ByteBuffer (java.nio.ByteBuffer)2