From eb1d9324667988ed0dcb39ce94a5de4c90ce8988 Mon Sep 17 00:00:00 2001 From: Sina Tadayon Date: Wed, 8 Jun 2016 01:56:02 +0430 Subject: [PATCH] Support WebSocket data chunked transfer Motivation: Support fetches data chunk by chunk for use with WebSocket chunked transfers. Modifications: Create a WebSocketChunkedInput.java that add to io.netty.handler.codec.http.websocketx package Result: The WebSocket transfers/fetches data chunk by chunk. --- .../websocketx/WebSocketChunkedInput.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketChunkedInput.java diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketChunkedInput.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketChunkedInput.java new file mode 100644 index 0000000000..c1069de3c1 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketChunkedInput.java @@ -0,0 +1,114 @@ +/* + * Copyright 2016 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.stream.ChunkedInput; +import io.netty.util.internal.ObjectUtil; + +/** + * A {@link ChunkedInput} that fetches data chunk by chunk for use with WebSocket chunked transfers. + *

+ * Each chunk from the input data will be wrapped within a {@link ContinuationWebSocketFrame}. + * At the end of the input data, {@link ContinuationWebSocketFrame} with finalFragment will be written. + *

+ */ +public final class WebSocketChunkedInput implements ChunkedInput { + private final ChunkedInput input; + private final int rsv; + + /** + * Creates a new instance using the specified input. + * @param input {@link ChunkedInput} containing data to write + */ + public WebSocketChunkedInput(ChunkedInput input) { + this(input, 0); + } + + /** + * Creates a new instance using the specified input. + * @param input {@link ChunkedInput} containing data to write + * @param rsv RSV1, RSV2, RSV3 used for extensions + * + * @throws NullPointerException if {@code input} is null + */ + public WebSocketChunkedInput(ChunkedInput input, int rsv) { + this.input = ObjectUtil.checkNotNull(input, "input"); + this.rsv = rsv; + } + + /** + * @return {@code true} if and only if there is no data left in the stream + * and the stream has reached at its end. + */ + @Override + public boolean isEndOfInput() throws Exception { + return input.isEndOfInput(); + } + + /** + * Releases the resources associated with the input. + */ + @Override + public void close() throws Exception { + input.close(); + } + + /** + * @deprecated Use {@link #readChunk(ByteBufAllocator)}. + * + * Fetches a chunked data from the stream. Once this method returns the last chunk + * and thus the stream has reached at its end, any subsequent {@link #isEndOfInput()} + * call must return {@code true}. + * + * @param ctx {@link ChannelHandlerContext} context of channelHandler + * @return {@link WebSocketFrame} contain chunk of data + */ + @Deprecated + @Override + public WebSocketFrame readChunk(ChannelHandlerContext ctx) throws Exception { + return readChunk(ctx.alloc()); + } + + /** + * Fetches a chunked data from the stream. Once this method returns the last chunk + * and thus the stream has reached at its end, any subsequent {@link #isEndOfInput()} + * call must return {@code true}. + * + * @param allocator {@link ByteBufAllocator} + * @return {@link WebSocketFrame} contain chunk of data + */ + @Override + public WebSocketFrame readChunk(ByteBufAllocator allocator) throws Exception { + ByteBuf buf = input.readChunk(allocator); + if (buf == null) { + return null; + } + return new ContinuationWebSocketFrame(input.isEndOfInput(), rsv, buf); + } + + @Override + public long length() { + return input.length(); + } + + @Override + public long progress() { + return input.progress(); + } +}