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