@Override public DataWrapper encrypt(DataWrapper data) { ByteBuffer b = ByteBuffer.wrap(data.createByteArray()); engine.feedPlainPacket(b); DataWrapper retVal = encryptedData; encryptedData = null; return retVal; } }
@Override public CompletableFuture<List<SslAction>> parseIncoming(DataWrapper dataWrapper) { byte[] bytes = dataWrapper.createByteArray(); ByteBuffer buffer = ByteBuffer.wrap(bytes); encryptedData = null; decryptedData = null; engine.feedEncryptedPacket(buffer); return CompletableFuture.completedFuture(createResult()); }
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); }
void incrementIncomingWindow(int streamId, int length) { log.info("incrementing incoming window for {} by {}", streamId, length); incomingFlowControl.get(0x0).addAndGet(length); incomingFlowControl.get(streamId).addAndGet(length); WindowUpdateFrame frame = new WindowUpdateFrame(); frame.setWindowSizeIncrement(length); frame.setStreamId(0x0); channel.write(ByteBuffer.wrap(marshal(frame).createByteArray())); // reusing the frame! ack. frame.setStreamId(streamId); channel.write(ByteBuffer.wrap(marshal(frame).createByteArray())); log.info("stream {} incoming window is {} and connection window is {}", streamId, incomingFlowControl.get(streamId), incomingFlowControl.get(0)); }
@Override public void run() { PingFrame pingFrame = new PingFrame(); pingFrame.setOpaqueData(System.nanoTime()); channel.write(ByteBuffer.wrap(marshal(pingFrame).createByteArray())); } }
@Override public void sendLocalRequestedSettings() { SettingsFrame settingsFrame = new SettingsFrame(); localRequestedSettings.fillFrame(settingsFrame); log.info("sending settings: " + settingsFrame); channel.write(ByteBuffer.wrap(marshal(settingsFrame).createByteArray())); }
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); }
private void handlePing(PingFrame frame) { if(!frame.isPingResponse()) { // Send the same frame back, setting ping response frame.setIsPingResponse(true); Http2EngineImpl.log.info("sending ping response: " + frame); DataWrapper data = this.http2EngineImpl.marshal(frame); this.http2EngineImpl.channel.write(ByteBuffer.wrap(data.createByteArray())); } else { // measure latency from the ping that was sent. The opaqueData we sent is // System.nanoTime() so we just measure the difference long latency = System.nanoTime() - frame.getOpaqueData(); Http2EngineImpl.log.info("Ping: {} ms", latency * 1e-6); } }
private CompletableFuture<Void> writeDataFrame(DataFrame frame) { int streamId = frame.getStreamId(); log.info("actually writing data frame: " + frame); int dataSize = frame.getData().getReadableSize(); int paddingSize = frame.getPadding().getReadableSize(); if(paddingSize > 0) paddingSize += 1; int totalSize = dataSize + paddingSize; decrementOutgoingWindow(streamId, totalSize); return channel.write(ByteBuffer.wrap(marshal(frame).createByteArray())).thenAccept(c -> {}); }
CompletableFuture<Void> sendPushPromiseFrames(LinkedList<Http2Header> headerList, Stream stream, Stream newStream) { int streamId = stream.getStreamId(); ByteArrayOutputStream out = new ByteArrayOutputStream(); updateMaxHeaderTableSize(out); Http2Push push = new Http2Push(headerList); push.setStreamId(streamId); push.setPromisedStreamId(newStream.getStreamId()); DataWrapper data = marshal(push); // Send all the frames at once log.info("sending push promise frames: " + push); ByteBuffer buf = ByteBuffer.wrap(data.createByteArray()); return channel.write(buf).thenAccept( channel -> newStream.setStatus(Stream.StreamStatus.RESERVED_LOCAL) ); }
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); DataWrapper afterPrefaceData = split.get(1);
CompletableFuture<Void> sendHeaderFrames(LinkedList<Http2Header> headerList, Stream stream) { // TODO: check the status of the stream to ensure we can send HEADER frames ByteArrayOutputStream out = new ByteArrayOutputStream(); updateMaxHeaderTableSize(out); Http2Headers headers = new Http2Headers(headerList); headers.setStreamId(stream.getStreamId()); headers.setEndOfStream(false); DataWrapper data = marshal(headers); ByteBuffer buf = ByteBuffer.wrap(data.createByteArray()); // Send all the frames at once log.info("sending header frames: " + headers); return channel.write(buf).thenAccept( channel -> { switch (stream.getStatus()) { case IDLE: stream.setStatus(Stream.StreamStatus.OPEN); break; case HALF_CLOSED_LOCAL: case HALF_CLOSED_REMOTE: // leave status the same break; case RESERVED_LOCAL: stream.setStatus(HALF_CLOSED_REMOTE); break; default: throw new InternalError(lastClosedRemoteOriginatedStream().orElse(0), wrapperGen.emptyWrapper()); //"should not be sending headers on a stream not open or half closed remote" } } ); }
ParamNode paramNode = paramTree.get(name); if(binder != null && isManagedBy(binder, fieldMeta)) { Object bean = binder.unmarshal(fieldMeta.getFieldClass(), req.body.createByteArray()); result.add(bean); } else {
@Override public RequestId createInitialStream(HttpResponse r, HttpRequest req, ResponseListener listener, DataWrapper leftOverData) { int initialStreamId = getAndIncrementStreamId(); Stream initialStream = new Stream(); initialStream.setStreamId(initialStreamId); initializeFlowControl(initialStreamId); initialStream.setRequest(req); initialStream.setResponseListener(listener); initialStream.setResponse(r); // Since we already sent the entire request as the upgrade, the stream basically starts in // half closed local initialStream.setStatus(Stream.StreamStatus.HALF_CLOSED_LOCAL); activeStreams.put(initialStreamId, initialStream); DataWrapper responseBody = r.getBodyNonNull(); // Send the content of the response to the datalistener, if any // Not likely to happen but just in case if(responseBody.getReadableSize() > 0) { log.info("got a responsebody that we're passing on to the http2 parser"); dataListener.incomingData(getUnderlyingChannel(), ByteBuffer.wrap(responseBody.createByteArray())); } if(leftOverData.getReadableSize() > 0) { log.info("got leftover data (size="+leftOverData.getReadableSize()+") that we're passing on to the http2 parser"); dataListener.incomingData(getUnderlyingChannel(), ByteBuffer.wrap(leftOverData.createByteArray())); } return new RequestId(initialStreamId); }
responseFrame.setAck(true); log.info("sending settings ack: " + responseFrame); channel.write(ByteBuffer.wrap(marshal(responseFrame).createByteArray()));