1 /* 2 * Copyright 2014 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, version 2.0 (the 5 * "License"); you may not use this file except in compliance with the License. You may obtain a 6 * copy of the License at: 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software distributed under the License 11 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 12 * or implied. See the License for the specific language governing permissions and limitations under 13 * the License. 14 */ 15 package io.netty5.handler.codec.http2; 16 17 import io.netty5.channel.ChannelHandlerContext; 18 import io.netty5.util.internal.UnstableApi; 19 20 /** 21 * A {@link Http2FlowController} for controlling the flow of outbound {@code DATA} frames to the remote 22 * endpoint. 23 */ 24 @UnstableApi 25 public interface Http2RemoteFlowController extends Http2FlowController { 26 /** 27 * Get the {@link ChannelHandlerContext} for which to apply flow control on. 28 * <p> 29 * This is intended for us by {@link FlowControlled} implementations only. Use with caution. 30 * @return The {@link ChannelHandlerContext} for which to apply flow control on. 31 */ 32 ChannelHandlerContext channelHandlerContext(); 33 34 /** 35 * Queues a payload for transmission to the remote endpoint. There is no guarantee as to when the data 36 * will be written or how it will be assigned to frames. 37 * before sending. 38 * <p> 39 * Writes do not actually occur until {@link #writePendingBytes()} is called. 40 * 41 * @param stream the subject stream. Must not be the connection stream object. 42 * @param payload payload to write subject to flow-control accounting and ordering rules. 43 */ 44 void addFlowControlled(Http2Stream stream, FlowControlled payload); 45 46 /** 47 * Determine if {@code stream} has any {@link FlowControlled} frames currently queued. 48 * @param stream the stream to check if it has flow controlled frames. 49 * @return {@code true} if {@code stream} has any {@link FlowControlled} frames currently queued. 50 */ 51 boolean hasFlowControlled(Http2Stream stream); 52 53 /** 54 * Write all data pending in the flow controller up to the flow-control limits. 55 * 56 * @throws Http2Exception throws if a protocol-related error occurred. 57 */ 58 void writePendingBytes() throws Http2Exception; 59 60 /** 61 * Set the active listener on the flow-controller. 62 * 63 * @param listener to notify when the a write occurs, can be {@code null}. 64 */ 65 void listener(Listener listener); 66 67 /** 68 * Determine if the {@code stream} has bytes remaining for use in the flow control window. 69 * <p> 70 * Note that this method respects channel writability. The channel must be writable for this method to 71 * return {@code true}. 72 * 73 * @param stream The stream to test. 74 * @return {@code true} if the {@code stream} has bytes remaining for use in the flow control window and the 75 * channel is writable, {@code false} otherwise. 76 */ 77 boolean isWritable(Http2Stream stream); 78 79 /** 80 * Notification that the writability of {@link #channelHandlerContext()} has changed. 81 * @throws Http2Exception If any writes occur as a result of this call and encounter errors. 82 */ 83 void channelWritabilityChanged() throws Http2Exception; 84 85 /** 86 * Explicitly update the dependency tree. This method is called independently of stream state changes. 87 * @param childStreamId The stream identifier associated with the child stream. 88 * @param parentStreamId The stream identifier associated with the parent stream. May be {@code 0}, 89 * to make {@code childStreamId} and immediate child of the connection. 90 * @param weight The weight which is used relative to other child streams for {@code parentStreamId}. This value 91 * must be between 1 and 256 (inclusive). 92 * @param exclusive If {@code childStreamId} should be the exclusive dependency of {@code parentStreamId}. 93 */ 94 void updateDependencyTree(int childStreamId, int parentStreamId, short weight, boolean exclusive); 95 96 /** 97 * Implementations of this interface are used to progressively write chunks of the underlying 98 * payload to the stream. A payload is considered to be fully written if {@link #write} has 99 * been called at least once and it's {@link #size} is now zero. 100 */ 101 interface FlowControlled { 102 /** 103 * The size of the payload in terms of bytes applied to the flow-control window. 104 * Some payloads like {@code HEADER} frames have no cost against flow control and would 105 * return 0 for this value even though they produce a non-zero number of bytes on 106 * the wire. Other frames like {@code DATA} frames have both their payload and padding count 107 * against flow-control. 108 */ 109 int size(); 110 111 /** 112 * Called to indicate that an error occurred before this object could be completely written. 113 * <p> 114 * The {@link Http2RemoteFlowController} will make exactly one call to either 115 * this method or {@link #writeComplete()}. 116 * </p> 117 * 118 * @param ctx The context to use if any communication needs to occur as a result of the error. 119 * This may be {@code null} if an exception occurs when the connection has not been established yet. 120 * @param cause of the error. 121 */ 122 void error(ChannelHandlerContext ctx, Throwable cause); 123 124 /** 125 * Called after this object has been successfully written. 126 * <p> 127 * The {@link Http2RemoteFlowController} will make exactly one call to either 128 * this method or {@link #error(ChannelHandlerContext, Throwable)}. 129 * </p> 130 */ 131 void writeComplete(); 132 133 /** 134 * Writes up to {@code allowedBytes} of the encapsulated payload to the stream. Note that 135 * a value of 0 may be passed which will allow payloads with flow-control size == 0 to be 136 * written. The flow-controller may call this method multiple times with different values until 137 * the payload is fully written, i.e it's size after the write is 0. 138 * <p> 139 * When an exception is thrown the {@link Http2RemoteFlowController} will make a call to 140 * {@link #error(ChannelHandlerContext, Throwable)}. 141 * </p> 142 * 143 * @param ctx The context to use for writing. 144 * @param allowedBytes an upper bound on the number of bytes the payload can write at this time. 145 */ 146 void write(ChannelHandlerContext ctx, int allowedBytes); 147 148 /** 149 * Merge the contents of the {@code next} message into this message so they can be written out as one unit. 150 * This allows many small messages to be written as a single DATA frame. 151 * 152 * @return {@code true} if {@code next} was successfully merged and does not need to be enqueued, 153 * {@code false} otherwise. 154 */ 155 boolean merge(ChannelHandlerContext ctx, FlowControlled next); 156 } 157 158 /** 159 * Listener to the number of flow-controlled bytes written per stream. 160 */ 161 interface Listener { 162 /** 163 * Notification that {@link Http2RemoteFlowController#isWritable(Http2Stream)} has changed for {@code stream}. 164 * <p> 165 * This method should not throw. Any thrown exceptions are considered a programming error and are ignored. 166 * @param stream The stream which writability has changed for. 167 */ 168 void writabilityChanged(Http2Stream stream); 169 } 170 }