public void uncompressBodyAndAssertContainsString(String text) { Header header = getResponse().getHeaderLookupStruct().getHeader(KnownHeaderName.CONTENT_ENCODING); if(header == null) throw new IllegalStateException("Body is not compressed as no CONTENT_ENCODING header field exists"); else if(!"gzip".equals(header.getValue())) throw new IllegalStateException("Body has wrong compression type="+header.getValue()+" in CONTENT_ENCODING header field"); DataWrapper wrapper = getBody(); byte[] compressed = wrapper.createByteArray(); ByteArrayInputStream in = new ByteArrayInputStream(compressed); byte[] out = new byte[10000]; DataWrapper output = dataGen.emptyWrapper(); try (GZIPInputStream str = new GZIPInputStream(in)) { int read = 0; while((read = str.read(out)) > 0) { ByteBuffer buffer = ByteBuffer.wrap(out, 0, read); DataWrapper byteWrapper = dataGen.wrapByteBuffer(buffer); output = dataGen.chainDataWrappers(output, byteWrapper); out = new byte[10000]; } } catch(IOException e) { throw new RuntimeException(e); } Charset charset = extractCharset(); String bodyAsString = output.createStringFrom(0, output.getReadableSize(), charset); if(!bodyAsString.contains(text)) throw new IllegalStateException("Expected compressed body to contain='"+text+"' but body was="+bodyAsString); }
public static HttpRequest createJsonRequest(KnownHttpMethod method, String url) { HttpRequest request = createRequest(method, url); String json = "{ `query`: `cats and dogs`, `meta`: { `numResults`: 4 } }".replace("`", "\""); DataWrapper body = gen.wrapByteArray(json.getBytes()); request.setBody(body); return request; }
@Override public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) { if(encryptedData != null) { DataWrapper newBuf = dataGen.wrapByteBuffer(engineToSocketData); encryptedData = dataGen.chainDataWrappers(encryptedData, newBuf); return CompletableFuture.completedFuture(null); } encryptedData = dataGen.wrapByteBuffer(engineToSocketData); return CompletableFuture.completedFuture(null); }
private ByteBuffer translate(List<Http2Msg> frames) { DataWrapper allData = dataGen.emptyWrapper(); for(Http2Msg f : frames) { DataWrapper data = this.http2EngineImpl.marshal(f); allData = dataGen.chainDataWrappers(allData, data); } byte[] byteArray = allData.createByteArray(); return ByteBuffer.wrap(byteArray); }
@Override public void incomingData(Channel channel, ByteBuffer b) { DataWrapper newData = Http2EngineImpl.wrapperGen.wrapByteBuffer(b); try { DataWrapper combined = Http2EngineImpl.wrapperGen.chainDataWrappers(firstIncomingData, newData); int prefaceLength = Http2EngineImpl.prefaceHexString.length()/2; if(combined.getReadableSize() >= prefaceLength) { List<? extends DataWrapper> split = Http2EngineImpl.wrapperGen.split(combined, prefaceLength); if(Arrays.equals(split.get(0).createByteArray(), (DatatypeConverter.parseHexBinary(Http2EngineImpl.prefaceHexString)))) { gotPreface.set(true); throw new GoAwayError(0, Http2ErrorCode.PROTOCOL_ERROR, Http2EngineImpl.wrapperGen.emptyWrapper());
void incrementOutgoingWindow(int streamId, int length) { log.info("incrementing outgoing window for {} by {}", streamId, length); if(outgoingFlowControl.get(0x0).addAndGet(length) > 2147483647L) throw new GoAwayError(lastClosedRemoteOriginatedStream().orElse(0), Http2ErrorCode.FLOW_CONTROL_ERROR, wrapperGen.emptyWrapper()); if(outgoingFlowControl.get(streamId) == null) initializeFlowControl(streamId); if(outgoingFlowControl.get(streamId).addAndGet(length) > 2147483647L) throw new GoAwayError(lastClosedRemoteOriginatedStream().orElse(0), streamId, Http2ErrorCode.FLOW_CONTROL_ERROR, wrapperGen.emptyWrapper()); log.info("stream {} outgoing window is {} and connection window is {}", streamId, outgoingFlowControl.get(streamId), outgoingFlowControl.get(0)); }
@Override public CompletableFuture<Void> packetUnencrypted(ByteBuffer out) { decryptedData = dataGen.wrapByteBuffer(out); return CompletableFuture.completedFuture(null); }
@Override public CompletableFuture<Void> incomingData(HttpData chunk) { DataWrapper allData = dataGen.chainDataWrappers(response.getData(), chunk.getBodyNonNull()); response.setData(allData); if(chunk.isEndOfData()) { future.complete(response); response = null; } return CompletableFuture.completedFuture(null); } }
private HttpChunk createHttpChunk(MementoImpl memento, int i) { DataWrapper dataToRead = memento.getLeftOverData(); List<? extends DataWrapper> split = dataGen.split(dataToRead, i+2); DataWrapper chunkMetaData = split.get(0); memento.setLeftOverData(split.get(1));
@Override public CompletableFuture<Void> sendEncryptedHandshakeData(ByteBuffer engineToSocketData) { if(encryptedData != null) { DataWrapper newBuf = dataGen.wrapByteBuffer(engineToSocketData); encryptedData = dataGen.chainDataWrappers(encryptedData, newBuf); return CompletableFuture.completedFuture(null); } encryptedData = dataGen.wrapByteBuffer(engineToSocketData); return CompletableFuture.completedFuture(null); }
public Memento prepareToParse() { MementoImpl memento = new MementoImpl(); memento.setLeftOverData(dataGen.emptyWrapper()); return memento; }
public CompletableFuture<Void> incomingData(FrontendSocketImpl socket, ByteBuffer b) { DataWrapper wrapper = dataGen.wrapByteBuffer(b); return incomingData(socket, wrapper); }
DataWrapper allData = dataGen.chainDataWrappers(leftOverData, moreData); memento.setLeftOverData(allData);
private void readInBody(MementoImpl memento, boolean stripAndCompareLastTwo) { HttpPayload message = memento.getHalfParsedMessage(); DataWrapper dataToRead = memento.getLeftOverData(); int readableSize = dataToRead.getReadableSize(); int numBytesNeeded = memento.getNumBytesLeftToRead(); if(numBytesNeeded <= readableSize) { List<? extends DataWrapper> split = dataGen.split(dataToRead, numBytesNeeded); DataWrapper data = split.get(0); if(stripAndCompareLastTwo) { List<? extends DataWrapper> splitPieces = dataGen.split(data, data.getReadableSize()-2); data = splitPieces.get(0); DataWrapper trailer = splitPieces.get(1); String trailerStr = trailer.createStringFrom(0, trailer.getReadableSize(), iso8859_1); if(!TRAILER_STR.equals(trailerStr)) throw new IllegalStateException("The chunk did not end with \\r\\n . The format is invalid"); } message.setBody(data); memento.setLeftOverData(split.get(1)); memento.setNumBytesLeftToRead(0); memento.getParsedMessages().add(message); //clear any cached message we were waiting for more data for memento.setHalfParsedMessage(null); return; } }
@Override public CompletableFuture<DataWriter> incomingResponse(HttpResponse resp, boolean isComplete) { HttpFullResponse resp1 = new HttpFullResponse(resp, dataGen.emptyWrapper()); if(isComplete) { future.complete(resp1); return CompletableFuture.completedFuture(new NullWriter()); } response = resp1; return CompletableFuture.completedFuture(new DataWriterImpl()); }
private Memento parse(FrontendSocketImpl socket, ByteBuffer buf) { DataWrapper moreData = dataGen.wrapByteBuffer(buf); Memento state = socket.getHttp1_1ParseState(); state = httpParser.parse(state, moreData); return state; }
public static HttpRequest createBadJsonRequest(KnownHttpMethod method, String url) { HttpRequest request = createRequest(method, url); String json = "{ `query `cats and dogs`, `meta`: { `numResults`: 4 } }".replace("`", "\""); DataWrapper body = gen.wrapByteArray(json.getBytes()); request.setBody(body); return request; }
List<? extends DataWrapper> tuple = dataGen.split(dataToRead, i+4); DataWrapper toBeParsed = tuple.get(0); memento.setLeftOverData(tuple.get(1));
void decrementIncomingWindow(int streamId, int length) { log.info("decrementing incoming window for {} by {}", streamId, length); if(incomingFlowControl.get(0x0).addAndGet(- length) < 0) { throw new GoAwayError(lastClosedRemoteOriginatedStream().orElse(0), Http2ErrorCode.FLOW_CONTROL_ERROR, wrapperGen.emptyWrapper()); } if(incomingFlowControl.get(streamId).addAndGet(- length) < 0) { throw new RstStreamError(Http2ErrorCode.FLOW_CONTROL_ERROR, streamId); } log.info("stream {} incoming window is {} and connection window is {}", streamId, incomingFlowControl.get(streamId), incomingFlowControl.get(0)); }
@Override public CompletableFuture<Void> incomingData(Channel channel, ByteBuffer b) { DataWrapper wrapper = wrapperGen.wrapByteBuffer(b); int bytesIn = b.remaining(); CompletableFuture<Void> future2 = tracker2.addBytesToTrack(bytesIn); memento = parser.parse(memento, wrapper); List<HttpPayload> parsedMessages = memento.getParsedMessages(); AckAggregator aggregator = new AckAggregator(parsedMessages.size(), memento.getNumBytesJustParsed(), tracker2); //AckAggregator ack = tracker.createTracker(bytesIn, parsedMessages.size(), memento.getNumBytesJustParsed()); for(HttpPayload msg : parsedMessages) { if(msg instanceof HttpData) { HttpData data = (HttpData) msg; if(data.isEndOfData()) responsesToComplete.poll(); future.thenCompose(w -> { return w.incomingData(data).handle((v, t) -> aggregator.ack(v, t)); }); } else if(msg instanceof HttpResponse) { future = processResponse((HttpResponse)msg) .handle((w, t) -> aggregator.ack(w, t)); } else throw new IllegalStateException("invalid payload received="+msg); } return future2; }