/src/swift-nio/Sources/NIOCore/ChannelHandler.swift
Line | Count | Source |
1 | | //===----------------------------------------------------------------------===// |
2 | | // |
3 | | // This source file is part of the SwiftNIO open source project |
4 | | // |
5 | | // Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors |
6 | | // Licensed under Apache License v2.0 |
7 | | // |
8 | | // See LICENSE.txt for license information |
9 | | // See CONTRIBUTORS.txt for the list of SwiftNIO project authors |
10 | | // |
11 | | // SPDX-License-Identifier: Apache-2.0 |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | /// Base protocol for handlers that handle I/O events or intercept an I/O operation. |
16 | | /// |
17 | | /// All methods are called from within the `EventLoop` that is assigned to the `Channel` itself. |
18 | | /// |
19 | | /// You should _never_ implement this protocol directly. Please implement one of its sub-protocols. |
20 | | public protocol ChannelHandler: AnyObject { |
21 | | /// Called when this `ChannelHandler` is added to the `ChannelPipeline`. |
22 | | /// |
23 | | /// - Parameters: |
24 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
25 | | func handlerAdded(context: ChannelHandlerContext) |
26 | | |
27 | | /// Called when this `ChannelHandler` is removed from the `ChannelPipeline`. |
28 | | /// |
29 | | /// - Parameters: |
30 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
31 | | func handlerRemoved(context: ChannelHandlerContext) |
32 | | } |
33 | | |
34 | | /// Untyped `ChannelHandler` which handles outbound I/O events or intercept an outbound I/O operation. |
35 | | /// |
36 | | /// Despite the fact that `write` is one of the methods on this protocol, you should avoid assuming that "outbound" events are to do with |
37 | | /// writing to channel sources. Instead, "outbound" events are events that are passed *to* the channel source (e.g. a socket): that is, things you tell |
38 | | /// the channel source to do. That includes `write` ("write this data to the channel source"), but it also includes `read` ("please begin attempting to read from |
39 | | /// the channel source") and `bind` ("please bind the following address"), which have nothing to do with sending data. |
40 | | /// |
41 | | /// We _strongly_ advise against implementing this protocol directly. Please implement `ChannelOutboundHandler`. |
42 | | public protocol _ChannelOutboundHandler: ChannelHandler { |
43 | | |
44 | | /// Called to request that the `Channel` register itself for I/O events with its `EventLoop`. |
45 | | /// This should call `context.register` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
46 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
47 | | /// |
48 | | /// - Parameters: |
49 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
50 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
51 | | func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) |
52 | | |
53 | | /// Called to request that the `Channel` bind to a specific `SocketAddress`. |
54 | | /// |
55 | | /// This should call `context.bind` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
56 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
57 | | /// |
58 | | /// - Parameters: |
59 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
60 | | /// - to: The `SocketAddress` to which this `Channel` should bind. |
61 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
62 | | func bind(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) |
63 | | |
64 | | /// Called to request that the `Channel` connect to a given `SocketAddress`. |
65 | | /// |
66 | | /// This should call `context.connect` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
67 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
68 | | /// |
69 | | /// - Parameters: |
70 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
71 | | /// - to: The `SocketAddress` to which the the `Channel` should connect. |
72 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
73 | | func connect(context: ChannelHandlerContext, to: SocketAddress, promise: EventLoopPromise<Void>?) |
74 | | |
75 | | /// Called to request a write operation. The write operation will write the messages through the |
76 | | /// `ChannelPipeline`. Those are then ready to be flushed to the actual `Channel` when |
77 | | /// `Channel.flush` or `ChannelHandlerContext.flush` is called. |
78 | | /// |
79 | | /// This should call `context.write` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
80 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
81 | | /// |
82 | | /// - Parameters: |
83 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
84 | | /// - data: The data to write through the `Channel`, wrapped in a `NIOAny`. |
85 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
86 | | func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) |
87 | | |
88 | | /// Called to request that the `Channel` flush all pending writes. The flush operation will try to flush out all previous written messages |
89 | | /// that are pending. |
90 | | /// |
91 | | /// This should call `context.flush` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or just |
92 | | /// discard it if the flush should be suppressed. |
93 | | /// |
94 | | /// - Parameters: |
95 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
96 | | func flush(context: ChannelHandlerContext) |
97 | | |
98 | | /// Called to request that the `Channel` perform a read when data is ready. The read operation will signal that we are ready to read more data. |
99 | | /// |
100 | | /// This should call `context.read` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or just |
101 | | /// discard it if the read should be suppressed. |
102 | | /// |
103 | | /// - Parameters: |
104 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
105 | | func read(context: ChannelHandlerContext) |
106 | | |
107 | | /// Called to request that the `Channel` close itself down. |
108 | | /// |
109 | | /// This should call `context.close` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
110 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
111 | | /// |
112 | | /// - Parameters: |
113 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
114 | | /// - mode: The `CloseMode` to apply |
115 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
116 | | func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) |
117 | | |
118 | | /// Called when an user outbound event is triggered. |
119 | | /// |
120 | | /// This should call `context.triggerUserOutboundEvent` to forward the operation to the next `_ChannelOutboundHandler` in the `ChannelPipeline` or |
121 | | /// complete the `EventLoopPromise` to let the caller know that the operation completed. |
122 | | /// |
123 | | /// - Parameters: |
124 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
125 | | /// - event: The triggered event. |
126 | | /// - promise: The `EventLoopPromise` which should be notified once the operation completes, or nil if no notification should take place. |
127 | | func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) |
128 | | } |
129 | | |
130 | | /// Untyped `ChannelHandler` which handles inbound I/O events. |
131 | | /// |
132 | | /// Despite the fact that `channelRead` is one of the methods on this protocol, you should avoid assuming that "inbound" events are to do with |
133 | | /// reading from channel sources. Instead, "inbound" events are events that originate *from* the channel source (e.g. the socket): that is, events that the |
134 | | /// channel source tells you about. This includes things like `channelRead` ("there is some data to read"), but it also includes things like |
135 | | /// `channelWritabilityChanged` ("this source is no longer marked writable"). |
136 | | /// |
137 | | /// We _strongly_ advise against implementing this protocol directly. Please implement `ChannelInboundHandler`. |
138 | | public protocol _ChannelInboundHandler: ChannelHandler { |
139 | | |
140 | | /// Called when the `Channel` has successfully registered with its `EventLoop` to handle I/O. |
141 | | /// |
142 | | /// This should call `context.fireChannelRegistered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
143 | | /// |
144 | | /// - Parameters: |
145 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
146 | | func channelRegistered(context: ChannelHandlerContext) |
147 | | |
148 | | /// Called when the `Channel` has unregistered from its `EventLoop`, and so will no longer be receiving I/O events. |
149 | | /// |
150 | | /// This should call `context.fireChannelUnregistered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
151 | | /// |
152 | | /// - Parameters: |
153 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
154 | | func channelUnregistered(context: ChannelHandlerContext) |
155 | | |
156 | | /// Called when the `Channel` has become active, and is able to send and receive data. |
157 | | /// |
158 | | /// This should call `context.fireChannelActive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
159 | | /// |
160 | | /// - Parameters: |
161 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
162 | | func channelActive(context: ChannelHandlerContext) |
163 | | |
164 | | /// Called when the `Channel` has become inactive and is no longer able to send and receive data. |
165 | | /// |
166 | | /// This should call `context.fireChannelInactive` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
167 | | /// |
168 | | /// - Parameters: |
169 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
170 | | func channelInactive(context: ChannelHandlerContext) |
171 | | |
172 | | /// Called when some data has been read from the remote peer. |
173 | | /// |
174 | | /// This should call `context.fireChannelRead` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
175 | | /// |
176 | | /// - Parameters: |
177 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
178 | | /// - data: The data read from the remote peer, wrapped in a `NIOAny`. |
179 | | func channelRead(context: ChannelHandlerContext, data: NIOAny) |
180 | | |
181 | | /// Called when the `Channel` has completed its current read loop, either because no more data is available to read from the transport at this time, or because the `Channel` needs to yield to the event loop to process other I/O events for other `Channel`s. |
182 | | /// If `ChannelOptions.autoRead` is `false` no further read attempt will be made until `ChannelHandlerContext.read` or `Channel.read` is explicitly called. |
183 | | /// |
184 | | /// This should call `context.fireChannelReadComplete` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
185 | | /// |
186 | | /// - Parameters: |
187 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
188 | | func channelReadComplete(context: ChannelHandlerContext) |
189 | | |
190 | | /// The writability state of the `Channel` has changed, either because it has buffered more data than the writability high water mark, or because the amount of buffered data has dropped below the writability low water mark. |
191 | | /// You can check the state with `Channel.isWritable`. |
192 | | /// |
193 | | /// This should call `context.fireChannelWritabilityChanged` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
194 | | /// |
195 | | /// - Parameters: |
196 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
197 | | func channelWritabilityChanged(context: ChannelHandlerContext) |
198 | | |
199 | | /// Called when a user inbound event has been triggered. |
200 | | /// |
201 | | /// This should call `context.fireUserInboundEventTriggered` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the event. |
202 | | /// |
203 | | /// - Parameters: |
204 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
205 | | /// - event: The event. |
206 | | func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) |
207 | | |
208 | | /// An error was encountered earlier in the inbound `ChannelPipeline`. |
209 | | /// |
210 | | /// This should call `context.fireErrorCaught` to forward the operation to the next `_ChannelInboundHandler` in the `ChannelPipeline` if you want to allow the next handler to also handle the error. |
211 | | /// |
212 | | /// - Parameters: |
213 | | /// - context: The `ChannelHandlerContext` which this `ChannelHandler` belongs to. |
214 | | /// - error: The `Error` that was encountered. |
215 | | func errorCaught(context: ChannelHandlerContext, error: Error) |
216 | | } |
217 | | |
218 | | // Default implementations for the ChannelHandler protocol |
219 | | extension ChannelHandler { |
220 | | |
221 | | /// Do nothing by default. |
222 | 0 | public func handlerAdded(context: ChannelHandlerContext) { |
223 | 0 | } |
224 | | |
225 | | /// Do nothing by default. |
226 | 886k | public func handlerRemoved(context: ChannelHandlerContext) { |
227 | 886k | } |
228 | | } |
229 | | |
230 | | /// Provides default implementations for all methods defined by `_ChannelOutboundHandler`. |
231 | | /// |
232 | | /// These default implementations will just call `context.methodName` to forward to the next `_ChannelOutboundHandler` in |
233 | | /// the `ChannelPipeline` until the operation is handled by the `Channel` itself. |
234 | | extension _ChannelOutboundHandler { |
235 | | |
236 | 0 | public func register(context: ChannelHandlerContext, promise: EventLoopPromise<Void>?) { |
237 | 0 | context.register(promise: promise) |
238 | 0 | } |
239 | | |
240 | 0 | public func bind(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) { |
241 | 0 | context.bind(to: address, promise: promise) |
242 | 0 | } |
243 | | |
244 | 0 | public func connect(context: ChannelHandlerContext, to address: SocketAddress, promise: EventLoopPromise<Void>?) { |
245 | 0 | context.connect(to: address, promise: promise) |
246 | 0 | } |
247 | | |
248 | 0 | public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) { |
249 | 0 | context.write(data, promise: promise) |
250 | 0 | } |
251 | | |
252 | 0 | public func flush(context: ChannelHandlerContext) { |
253 | 0 | context.flush() |
254 | 0 | } |
255 | | |
256 | 0 | public func read(context: ChannelHandlerContext) { |
257 | 0 | context.read() |
258 | 0 | } |
259 | | |
260 | 0 | public func close(context: ChannelHandlerContext, mode: CloseMode, promise: EventLoopPromise<Void>?) { |
261 | 0 | context.close(mode: mode, promise: promise) |
262 | 0 | } |
263 | | |
264 | 0 | public func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) { |
265 | 0 | context.triggerUserOutboundEvent(event, promise: promise) |
266 | 0 | } |
267 | | } |
268 | | |
269 | | /// Provides default implementations for all methods defined by `_ChannelInboundHandler`. |
270 | | /// |
271 | | /// These default implementations will just `context.fire*` to forward to the next `_ChannelInboundHandler` in |
272 | | /// the `ChannelPipeline` until the operation is handled by the `Channel` itself. |
273 | | extension _ChannelInboundHandler { |
274 | | |
275 | 0 | public func channelRegistered(context: ChannelHandlerContext) { |
276 | 0 | context.fireChannelRegistered() |
277 | 0 | } |
278 | | |
279 | 13.1k | public func channelUnregistered(context: ChannelHandlerContext) { |
280 | 13.1k | context.fireChannelUnregistered() |
281 | 13.1k | } |
282 | | |
283 | 0 | public func channelActive(context: ChannelHandlerContext) { |
284 | 0 | context.fireChannelActive() |
285 | 0 | } |
286 | | |
287 | 0 | public func channelInactive(context: ChannelHandlerContext) { |
288 | 0 | context.fireChannelInactive() |
289 | 0 | } |
290 | | |
291 | 0 | public func channelRead(context: ChannelHandlerContext, data: NIOAny) { |
292 | 0 | context.fireChannelRead(data) |
293 | 0 | } |
294 | | |
295 | 13.1k | public func channelReadComplete(context: ChannelHandlerContext) { |
296 | 13.1k | context.fireChannelReadComplete() |
297 | 13.1k | } |
298 | | |
299 | 0 | public func channelWritabilityChanged(context: ChannelHandlerContext) { |
300 | 0 | context.fireChannelWritabilityChanged() |
301 | 0 | } |
302 | | |
303 | 0 | public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) { |
304 | 0 | context.fireUserInboundEventTriggered(event) |
305 | 0 | } |
306 | | |
307 | 0 | public func errorCaught(context: ChannelHandlerContext, error: Error) { |
308 | 0 | context.fireErrorCaught(error) |
309 | 0 | } |
310 | | } |
311 | | |
312 | | /// A `RemovableChannelHandler` is a `ChannelHandler` that can be dynamically removed from a `ChannelPipeline` whilst |
313 | | /// the `Channel` is operating normally. |
314 | | /// A `RemovableChannelHandler` is required to remove itself from the `ChannelPipeline` (using |
315 | | /// `ChannelHandlerContext.leavePipeline`) as soon as possible. |
316 | | /// |
317 | | /// - Note: When a `Channel` gets torn down, every `ChannelHandler` in the `Channel`'s `ChannelPipeline` will be |
318 | | /// removed from the `ChannelPipeline`. Those removals however happen synchronously and are not going through |
319 | | /// the methods of this protocol. |
320 | | public protocol RemovableChannelHandler: ChannelHandler { |
321 | | /// Ask the receiving `RemovableChannelHandler` to remove itself from the `ChannelPipeline` as soon as possible. |
322 | | /// The receiving `RemovableChannelHandler` may elect to remove itself sometime after this method call, rather than |
323 | | /// immediately, but if it does so it must take the necessary precautions to handle events arriving between the |
324 | | /// invocation of this method and the call to `ChannelHandlerContext.leavePipeline` that triggers the actual |
325 | | /// removal. |
326 | | /// |
327 | | /// - Note: Like the other `ChannelHandler` methods, this method should not be invoked by the user directly. To |
328 | | /// remove a `RemovableChannelHandler` from the `ChannelPipeline`, use `ChannelPipeline.removeHandler`. |
329 | | /// |
330 | | /// - Parameters: |
331 | | /// - context: The `ChannelHandlerContext` of the `RemovableChannelHandler` to be removed from the `ChannelPipeline`. |
332 | | /// - removalToken: The removal token to hand to `ChannelHandlerContext.leavePipeline` to trigger the actual |
333 | | /// removal from the `ChannelPipeline`. |
334 | | func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) |
335 | | } |
336 | | |
337 | | extension RemovableChannelHandler { |
338 | | /// Implements the default behaviour which is to synchronously remove the handler from the pipeline. Thanks to this, |
339 | | /// stateless `ChannelHandler`s can just use `RemovableChannelHandler` as a marker-protocol and declare themselves |
340 | | /// as removable without writing any extra code. |
341 | 0 | public func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) { |
342 | 0 | precondition(context.handler === self) |
343 | 0 | context.leavePipeline(removalToken: removalToken) |
344 | 0 | } |
345 | | } |
346 | | |
347 | | /// A `NIOOutboundByteBufferingChannelHandler` is a `ChannelHandler` that |
348 | | /// reports the number of bytes buffered for outbound direction. |
349 | | public protocol NIOOutboundByteBufferingChannelHandler { |
350 | | /// The number of bytes buffered in the channel handler, which are queued to be sent to |
351 | | /// the next outbound channel handler. |
352 | | var outboundBufferedBytes: Int { get } |
353 | | } |
354 | | |
355 | | /// A `NIOInboundByteBufferingChannelHandler` is a `ChannelHandler` that |
356 | | /// reports the number of bytes buffered for inbound direction. |
357 | | public protocol NIOInboundByteBufferingChannelHandler { |
358 | | /// The number of bytes buffered in the channel handler, which are queued to be sent to |
359 | | /// the next inbound channel handler. |
360 | | var inboundBufferedBytes: Int { get } |
361 | | } |