View Javadoc
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 }