Protocols

The following protocols are available globally.

  • The core Channel methods for NIO-internal use only.

    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
  • An configuration option that can be set on a Channel to configure different behaviour.

    See more

    Declaration

    Swift

    public protocol ChannelOption
  • AppendableCollection is a protocol partway between Collection and RangeReplaceableCollection. It defines the append method that is present on RangeReplaceableCollection, which makes all RangeReplaceableCollections trivially able to implement this protocol.

    See more

    Declaration

    Swift

    public protocol AppendableCollection : Collection
  • ChannelInboundHandler which decodes bytes in a stream-like fashion from one ByteBuffer to another message type.

    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:

    1. 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.
    2. Mutating the bytes in the buffer will cause undefined behaviour and likely crash your program
    See more

    Declaration

    Swift

    public protocol ByteToMessageDecoder : ChannelInboundHandler where Self.InboundIn == ByteBuffer
  • ChannelOutboundHandler which allows users to encode custom messages to a ByteBuffer easily.

    See more

    Declaration

    Swift

    public protocol MessageToByteEncoder : ChannelOutboundHandler where Self.OutboundOut == ByteBuffer
  • A Collection that is contiguously laid out in memory and can therefore be duplicated using memcpy.

    See more

    Declaration

    Swift

    public protocol ContiguousCollection : Collection
  • 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 Thread. 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