Protocols

The following protocols are available globally.

  • The core Channel methods that are for internal use of the Channel implementation only.

    Warning

    If you are not implementing a custom Channel type, you should never call any of these.

    Note

    All methods must be called from the EventLoop thread.

    See more

    Declaration

    Swift

    public protocol ChannelCore : AnyObject
  • A Channel is easiest thought of as a network socket. But it can be anything that is capable of I/O operations such as read, write, connect, and bind.

    Note

    All operations on Channel are thread-safe.

    In SwiftNIO, all I/O operations are asynchronous and hence all operations on Channel are asynchronous too. This means that all I/O operations will return immediately, usually before the work has been completed. The EventLoopPromises passed to or returned by the operations are used to retrieve the result of an operation after it has completed.

    A Channel owns its ChannelPipeline which handles all I/O events and requests associated with the Channel.

    See more

    Declaration

    Swift

    public protocol Channel : AnyObject, ChannelOutboundInvoker
  • You should never implement this protocol directly. Please implement one of its sub-protocols.

    See more

    Declaration

    Swift

    public protocol ChannelHandler : AnyObject
  • Untyped ChannelHandler which handles outbound I/O events or intercept an outbound I/O operation.

    Despite the fact that write is one of the methods on this protocol, you should avoid assuming that outbound events are to do with 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 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 the channel source) and bind (please bind the following address), which have nothing to do with sending data.

    We strongly advise against implementing this protocol directly. Please implement ChannelOutboundHandler.

    See more

    Declaration

    Swift

    public protocol _ChannelOutboundHandler : ChannelHandler
  • Untyped ChannelHandler which handles inbound I/O events.

    Despite the fact that channelRead is one of the methods on this protocol, you should avoid assuming that inbound events are to do with reading from channel sources. Instead, inbound events are events that originate from the channel source (e.g. the socket): that is, events that the channel source tells you about. This includes things like channelRead (there is some data to read), but it also includes things like channelWritabilityChanged (this source is no longer marked writable).

    We strongly advise against implementing this protocol directly. Please implement ChannelInboundHandler.

    See more

    Declaration

    Swift

    public protocol _ChannelInboundHandler : ChannelHandler
  • A RemovableChannelHandler is a ChannelHandler that can be dynamically removed from a ChannelPipeline whilst the Channel is operating normally. A RemovableChannelHandler is required to remove itself from the ChannelPipeline (using ChannelHandlerContext.removeHandler) as soon as possible.

    Note

    When a Channel gets torn down, every ChannelHandler in the Channel‘s ChannelPipeline will be removed from the ChannelPipeline. Those removals however happen synchronously and are not going through the methods of this protocol.
    See more

    Declaration

    Swift

    public protocol RemovableChannelHandler : ChannelHandler
  • ByteToMessageDecoders decode bytes in a stream-like fashion from ByteBuffer to another message type.

    To add a ByteToMessageDecoder to the ChannelPipeline use

    channel.pipeline.addHandler(ByteToMessageHandler(MyByteToMessageDecoder()))
    

    ByteToMessageHandler will turn your ByteToMessageDecoder into a ChannelInboundHandler. ByteToMessageHandler also solves a couple of tricky issues for you, most importantly, in a ByteToMessageDecoder you do not need to worry about re-entrancy. You own the passed-in ByteBuffer for the duration of the decode/decodeLast call an can modify it at will.

    If a custom frame decoder is required, then one needs to be careful when implementing one with ByteToMessageDecoder. Ensure there are enough bytes in the buffer for a complete frame by checking buffer.readableBytes. If there are not enough bytes for a complete frame, return without modifying the reader index to allow more bytes to arrive.

    To check for complete frames without modifying the reader index, use methods like buffer.getInteger. One MUST use the reader index when using methods like buffer.getInteger. For example calling buffer.getInteger(at: 0) is assuming the frame starts at the beginning of the buffer, which is not always the case. Use buffer.getInteger(at: buffer.readerIndex) instead.

    If you move the reader index forward, either manually or by using one of buffer.read* methods, you must ensure that you no longer need to see those bytes again as they will not be returned to you the next time decode is called. If you still need those bytes to come back, consider taking a local copy of buffer inside the function to perform your read operations on.

    The ByteBuffer passed in as buffer is a slice of a larger buffer owned by the ByteToMessageDecoder implementation. Some aspects of this buffer are preserved across calls to decode, meaning that any changes to those properties you make in your decode method will be reflected in the next call to decode. In particular, the following operations are have the described effects:

    Moving the reader index forward persists across calls. When your method returns, if the reader index has advanced, those bytes are considered consumed and will not be available in future calls to decode. Please note, however, that the numerical value of the readerIndex itself is not preserved, and may not be the same from one call to the next. Please do not rely on this numerical value: if you need to recall where a byte is relative to the readerIndex, use an offset rather than an absolute value.

    See more

    Declaration

    Swift

    public protocol ByteToMessageDecoder
  • Some ByteToMessageDecoders need to observe writes (which are outbound events). ByteToMessageDecoders which implement the WriteObservingByteToMessageDecoder protocol will be notified about every outbound write.

    WriteObservingByteToMessageDecoder may only observe a write and must not try to transform or block it in any way. After the write method returns the write will be forwarded to the next outbound handler.

    See more

    Declaration

    Swift

    public protocol WriteObservingByteToMessageDecoder : ByteToMessageDecoder
  • An EventLoop processes IO / tasks in an endless loop for Channels until it’s closed.

    Usually multiple Channels share the same EventLoop for processing IO / tasks and so share the same processing NIOThread. For a better understanding of how such an EventLoop works internally the following pseudo code may be helpful:

    while eventLoop.isOpen {
        /// Block until there is something to process for 1...n Channels
        let readyChannels = blockUntilIoOrTasksAreReady()
        /// Loop through all the Channels
        for channel in readyChannels {
            /// Process IO and / or tasks for the Channel.
            /// This may include things like:
            ///    - accept new connection
            ///    - connect to a remote host
            ///    - read from socket
            ///    - write to socket
            ///    - tasks that were submitted via EventLoop methods
            /// and others.
            processIoAndTasks(channel)
        }
    }
    

    Because an EventLoop may be shared between multiple Channels it’s important to NOT block while processing IO / tasks. This also includes long running computations which will have the same effect as blocking in this case.

    See more

    Declaration

    Swift

    public protocol EventLoop : EventLoopGroup
  • Provides an endless stream of EventLoops to use.

    See more

    Declaration

    Swift

    public protocol EventLoopGroup : AnyObject
  • A MulticastChannel is a Channel that supports IP multicast operations: that is, a channel that can join multicast groups.

    Note

    As with Channel, all operations on a MulticastChannel are thread-safe.
    See more

    Declaration

    Swift

    public protocol MulticastChannel : Channel
  • A protocol that covers an object that does DNS lookups.

    In general the rules for the resolver are relatively broad: there are no specific requirements on how it operates. However, the rest of the code assumes that it obeys RFC 6724, particularly section 6 on ordering returned addresses. That is, the IPv6 and IPv4 responses should be ordered by the destination address ordering rules from that RFC. This specification is widely implemented by getaddrinfo implementations, so any implementation based on getaddrinfo will work just fine. In the future, a custom resolver will need also to implement these sorting rules.

    See more

    Declaration

    Swift

    public protocol Resolver
  • This protocol defines an object, most commonly a Channel, that supports setting and getting socket options (via setsockopt/getsockopt or similar). It provides a strongly typed API that makes working with larger, less-common socket options easier than the ChannelOption API allows.

    The API is divided into two portions. For socket options that NIO has prior knowledge about, the API has strongly and safely typed APIs that only allow users to use the exact correct type for the socket option. This will ensure that the API is safe to use, and these are encouraged where possible.

    These safe APIs are built on top of an unsafe API that is also exposed to users as part of this protocol. The unsafe API is unsafe in the same way that UnsafePointer is: incorrect use of the API allows all kinds of memory-unsafe behaviour. This API is necessary for socket options that NIO does not have prior knowledge of, but wherever possible users are discouraged from using it.

    Relationship to SocketOption

    All Channel objects that implement this protocol should also support the SocketOption ChannelOption for simple socket options (those with C int values). These are the most common socket option types, and so this ChannelOption represents a convenient shorthand for using this protocol where the type allows, as well as avoiding the need to cast to this protocol.

    Note

    Like the Channel protocol, all methods in this protocol are thread-safe.
    See more

    Declaration

    Swift

    public protocol SocketOptionProvider