Coverage Report

Created: 2026-10-13 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/swift-nio/Sources/NIOCore/SocketOptionProvider.swift
Line
Count
Source
1
//===----------------------------------------------------------------------===//
2
//
3
// This source file is part of the SwiftNIO open source project
4
//
5
// Copyright (c) 2017-2021 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
#if canImport(Darwin)
15
import Darwin
16
#elseif os(Linux) || os(FreeBSD) || os(Android)
17
#if canImport(Glibc)
18
@preconcurrency import Glibc
19
#elseif canImport(Musl)
20
@preconcurrency import Musl
21
#elseif canImport(Bionic)
22
@preconcurrency import Bionic
23
#endif
24
import CNIOLinux
25
#elseif os(OpenBSD)
26
@preconcurrency import Glibc
27
import CNIOOpenBSD
28
#elseif os(Windows)
29
import WinSDK
30
#elseif canImport(WASILibc)
31
@preconcurrency import WASILibc
32
#else
33
#error("The Socket Option provider module was unable to identify your C library.")
34
#endif
35
36
/// This protocol defines an object, most commonly a `Channel`, that supports
37
/// setting and getting socket options (via `setsockopt`/`getsockopt` or similar).
38
/// It provides a strongly typed API that makes working with larger, less-common
39
/// socket options easier than the `ChannelOption` API allows.
40
///
41
/// The API is divided into two portions. For socket options that NIO has prior
42
/// knowledge about, the API has strongly and safely typed APIs that only allow
43
/// users to use the exact correct type for the socket option. This will ensure
44
/// that the API is safe to use, and these are encouraged where possible.
45
///
46
/// These safe APIs are built on top of an "unsafe" API that is also exposed to
47
/// users as part of this protocol. The "unsafe" API is unsafe in the same way
48
/// that `UnsafePointer` is: incorrect use of the API allows all kinds of
49
/// memory-unsafe behaviour. This API is necessary for socket options that NIO
50
/// does not have prior knowledge of, but wherever possible users are discouraged
51
/// from using it.
52
///
53
/// ### Relationship to SocketOption
54
///
55
/// All `Channel` objects that implement this protocol should also support the
56
/// `SocketOption` `ChannelOption` for simple socket options (those with C `int`
57
/// values). These are the most common socket option types, and so this `ChannelOption`
58
/// represents a convenient shorthand for using this protocol where the type allows,
59
/// as well as avoiding the need to cast to this protocol.
60
///
61
/// - Note: Like the `Channel` protocol, all methods in this protocol are
62
///     thread-safe.
63
public protocol SocketOptionProvider: _NIOPreconcurrencySendable {
64
    /// The `EventLoop` which is used by this `SocketOptionProvider` for execution.
65
    var eventLoop: EventLoop { get }
66
67
    #if !os(Windows)
68
    /// Set a socket option for a given level and name to the specified value.
69
    ///
70
    /// This function is not memory-safe: if you set the generic type parameter incorrectly,
71
    /// this function will still execute, and this can cause you to incorrectly interpret memory
72
    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of
73
    /// the safe functions defined by this protocol.
74
    ///
75
    /// - Parameters:
76
    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.
77
    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.
78
    ///   - value: The value to set the socket option to.
79
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
80
    ///     or if an error has occurred.
81
    @preconcurrency
82
    func unsafeSetSocketOption<Value: Sendable>(
83
        level: SocketOptionLevel,
84
        name: SocketOptionName,
85
        value: Value
86
    ) -> EventLoopFuture<Void>
87
    #endif
88
89
    /// Set a socket option for a given level and name to the specified value.
90
    ///
91
    /// This function is not memory-safe: if you set the generic type parameter incorrectly,
92
    /// this function will still execute, and this can cause you to incorrectly interpret memory
93
    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of
94
    /// the safe functions defined by this protocol.
95
    ///
96
    /// - Parameters:
97
    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.
98
    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.
99
    ///   - value: The value to set the socket option to.
100
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
101
    ///     or if an error has occurred.
102
    @preconcurrency
103
    func unsafeSetSocketOption<Value: Sendable>(
104
        level: NIOBSDSocket.OptionLevel,
105
        name: NIOBSDSocket.Option,
106
        value: Value
107
    ) -> EventLoopFuture<Void>
108
109
    #if !os(Windows)
110
    /// Obtain the value of the socket option for the given level and name.
111
    ///
112
    /// This function is not memory-safe: if you set the generic type parameter incorrectly,
113
    /// this function will still execute, and this can cause you to incorrectly interpret memory
114
    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of
115
    /// the safe functions defined by this protocol.
116
    ///
117
    /// - Parameters:
118
    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.
119
    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.
120
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
121
    ///     any error that occurred while retrieving the socket option.
122
    @preconcurrency
123
    func unsafeGetSocketOption<Value: Sendable>(
124
        level: SocketOptionLevel,
125
        name: SocketOptionName
126
    ) -> EventLoopFuture<Value>
127
    #endif
128
129
    /// Obtain the value of the socket option for the given level and name.
130
    ///
131
    /// This function is not memory-safe: if you set the generic type parameter incorrectly,
132
    /// this function will still execute, and this can cause you to incorrectly interpret memory
133
    /// and thereby read uninitialized or invalid memory. If at all possible, please use one of
134
    /// the safe functions defined by this protocol.
135
    ///
136
    /// - Parameters:
137
    ///   - level: The socket option level, e.g. `SOL_SOCKET` or `IPPROTO_IP`.
138
    ///   - name: The name of the socket option, e.g. `SO_REUSEADDR`.
139
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
140
    ///     any error that occurred while retrieving the socket option.
141
    @preconcurrency
142
    func unsafeGetSocketOption<Value: Sendable>(
143
        level: NIOBSDSocket.OptionLevel,
144
        name: NIOBSDSocket.Option
145
    ) -> EventLoopFuture<Value>
146
}
147
148
#if !os(Windows)
149
extension SocketOptionProvider {
150
    func unsafeSetSocketOption<Value: Sendable>(
151
        level: NIOBSDSocket.OptionLevel,
152
        name: NIOBSDSocket.Option,
153
        value: Value
154
0
    ) -> EventLoopFuture<Void> {
155
0
        self.unsafeSetSocketOption(
156
0
            level: SocketOptionLevel(level.rawValue),
157
0
            name: SocketOptionName(name.rawValue),
158
0
            value: value
159
0
        )
160
0
    }
161
162
    func unsafeGetSocketOption<Value: Sendable>(
163
        level: NIOBSDSocket.OptionLevel,
164
        name: NIOBSDSocket.Option
165
0
    ) -> EventLoopFuture<Value> {
166
0
        self.unsafeGetSocketOption(level: SocketOptionLevel(level.rawValue), name: SocketOptionName(name.rawValue))
167
0
    }
168
}
169
#endif
170
171
enum SocketOptionProviderError: Swift.Error {
172
    case unsupported
173
}
174
175
#if canImport(WASILibc)
176
public typealias NIOLinger = Never
177
#else
178
public typealias NIOLinger = linger
179
#endif
180
181
// MARK:- Safe helper methods.
182
// Hello code reader! All the methods in this extension are "safe" wrapper methods that define the correct
183
// types for `setSocketOption` and `getSocketOption` and call those methods on behalf of the user. These
184
// wrapper methods are memory safe. All of these methods are basically identical, and have been copy-pasted
185
// around. As a result, if you change one, you should probably change them all.
186
//
187
// You are welcome to add more helper methods here, but each helper method you add must be tested.
188
//
189
// Please note that to work around a Swift compiler issue regarding lookup of the Sendability of
190
// libc types across modules, the actual calls to `unsafeSetSocketOption` and `unsafeGetSocketOption`
191
// _must_ be made inside non-`public` non-`@inlinable` methods. Otherwise we'll produce crashes
192
// in release mode. NIO's integration tests are a good canary for this: if you call your method
193
// from an alloc counter test in the integration tests, it'll crash if you messed it up.
194
extension SocketOptionProvider {
195
    /// Sets the socket option SO_LINGER to `value`.
196
    ///
197
    /// - Parameters:
198
    ///   - value: The value to set SO_LINGER to.
199
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
200
    ///     or if an error has occurred.
201
0
    public func setSoLinger(_ value: linger) -> EventLoopFuture<Void> {
202
0
        self._setSoLinger(value)
203
0
    }
204
205
    /// Gets the value of the socket option SO_LINGER.
206
    ///
207
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
208
    ///     any error that occurred while retrieving the socket option.
209
0
    public func getSoLinger() -> EventLoopFuture<NIOLinger> {
210
0
        self._getSoLinger()
211
0
    }
212
213
    /// Sets the socket option IP_MULTICAST_IF to `value`.
214
    ///
215
    /// - Parameters:
216
    ///   - value: The value to set IP_MULTICAST_IF to.
217
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
218
    ///     or if an error has occurred.
219
0
    public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {
220
0
        self._setIPMulticastIF(value)
221
0
    }
222
223
    /// Gets the value of the socket option IP_MULTICAST_IF.
224
    ///
225
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
226
    ///     any error that occurred while retrieving the socket option.
227
0
    public func getIPMulticastIF() -> EventLoopFuture<in_addr> {
228
0
        self._getIPMulticastIF()
229
0
    }
230
231
    /// Sets the socket option IP_MULTICAST_TTL to `value`.
232
    ///
233
    /// - Parameters:
234
    ///   - value: The value to set IP_MULTICAST_TTL to.
235
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
236
    ///     or if an error has occurred.
237
0
    public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
238
0
        self._setIPMulticastTTL(value)
239
0
    }
240
241
    /// Gets the value of the socket option IP_MULTICAST_TTL.
242
    ///
243
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
244
    ///     any error that occurred while retrieving the socket option.
245
0
    public func getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {
246
0
        self._getIPMulticastTTL()
247
0
    }
248
249
    /// Sets the socket option IP_MULTICAST_LOOP to `value`.
250
    ///
251
    /// - Parameters:
252
    ///   - value: The value to set IP_MULTICAST_LOOP to.
253
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
254
    ///     or if an error has occurred.
255
0
    public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
256
0
        self._setIPMulticastLoop(value)
257
0
    }
258
259
    /// Gets the value of the socket option IP_MULTICAST_LOOP.
260
    ///
261
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
262
    ///     any error that occurred while retrieving the socket option.
263
0
    public func getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {
264
0
        self._getIPMulticastLoop()
265
0
    }
266
267
    /// Sets the socket option IPV6_MULTICAST_IF to `value`.
268
    ///
269
    /// - Parameters:
270
    ///   - value: The value to set IPV6_MULTICAST_IF to.
271
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
272
    ///     or if an error has occurred.
273
0
    public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
274
0
        self._setIPv6MulticastIF(value)
275
0
    }
276
277
    /// Gets the value of the socket option IPV6_MULTICAST_IF.
278
    ///
279
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
280
    ///     any error that occurred while retrieving the socket option.
281
0
    public func getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {
282
0
        self._getIPv6MulticastIF()
283
0
    }
284
285
    /// Sets the socket option IPV6_MULTICAST_HOPS to `value`.
286
    ///
287
    /// - Parameters:
288
    ///   - value: The value to set IPV6_MULTICAST_HOPS to.
289
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
290
    ///     or if an error has occurred.
291
0
    public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {
292
0
        self._setIPv6MulticastHops(value)
293
0
    }
294
295
    /// Gets the value of the socket option IPV6_MULTICAST_HOPS.
296
    ///
297
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
298
    ///     any error that occurred while retrieving the socket option.
299
0
    public func getIPv6MulticastHops() -> EventLoopFuture<CInt> {
300
0
        self._getIPv6MulticastHops()
301
0
    }
302
303
    /// Sets the socket option IPV6_MULTICAST_LOOP to `value`.
304
    ///
305
    /// - Parameters:
306
    ///   - value: The value to set IPV6_MULTICAST_LOOP to.
307
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
308
    ///     or if an error has occurred.
309
0
    public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
310
0
        self._setIPv6MulticastLoop(value)
311
0
    }
312
313
    /// Gets the value of the socket option IPV6_MULTICAST_LOOP.
314
    ///
315
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
316
    ///     any error that occurred while retrieving the socket option.
317
0
    public func getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
318
0
        self._getIPv6MulticastLoop()
319
0
    }
320
321
    #if os(Linux) || os(FreeBSD) || os(Android)
322
    /// Gets the value of the socket option TCP_INFO.
323
    ///
324
    /// This socket option cannot be set.
325
    ///
326
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
327
    ///     any error that occurred while retrieving the socket option.
328
0
    public func getTCPInfo() -> EventLoopFuture<tcp_info> {
329
0
        self._getTCPInfo()
330
0
    }
331
    #endif
332
333
    #if canImport(Darwin)
334
    /// Gets the value of the socket option TCP_CONNECTION_INFO.
335
    ///
336
    /// This socket option cannot be set.
337
    ///
338
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
339
    ///     any error that occurred while retrieving the socket option.
340
    public func getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
341
        self._getTCPConnectionInfo()
342
    }
343
    #endif
344
345
    #if os(Linux)
346
    /// Gets the value of the socket option MPTCP_INFO.
347
    ///
348
    /// This socket option cannot be set.
349
    ///
350
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
351
    ///     any error that occurred while retrieving the socket option.
352
0
    public func getMPTCPInfo() -> EventLoopFuture<mptcp_info> {
353
0
        self._getMPTCPInfo()
354
0
    }
355
    #endif
356
357
    // MARK: Non-public non-inlinable actual implementations for the above.
358
    //
359
    // As discussed above, these are needed to work around a compiler issue
360
    // that was present at least up to the 6.0 compiler series. This prevents
361
    // the specialization being emitted in the caller code, which is unfortunate,
362
    // but it also ensures that we avoid the crash. We should remove these when
363
    // they're no longer needed.
364
365
    /// Sets the socket option SO_LINGER to `value`.
366
    ///
367
    /// - Parameters:
368
    ///   - value: The value to set SO_LINGER to.
369
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
370
    ///     or if an error has occurred.
371
0
    private func _setSoLinger(_ value: linger) -> EventLoopFuture<Void> {
372
        #if os(WASI)
373
        self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)
374
        #else
375
0
        self.unsafeSetSocketOption(level: .socket, name: .so_linger, value: value)
376
        #endif
377
0
    }
378
379
    /// Gets the value of the socket option SO_LINGER.
380
    ///
381
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
382
    ///     any error that occurred while retrieving the socket option.
383
0
    private func _getSoLinger() -> EventLoopFuture<NIOLinger> {
384
        #if os(WASI)
385
        self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported)
386
        #else
387
0
        self.unsafeGetSocketOption(level: .socket, name: .so_linger)
388
        #endif
389
0
    }
390
391
    /// Sets the socket option IP_MULTICAST_IF to `value`.
392
    ///
393
    /// - Parameters:
394
    ///   - value: The value to set IP_MULTICAST_IF to.
395
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
396
    ///     or if an error has occurred.
397
0
    private func _setIPMulticastIF(_ value: in_addr) -> EventLoopFuture<Void> {
398
0
        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_if, value: value)
399
0
    }
400
401
    /// Gets the value of the socket option IP_MULTICAST_IF.
402
    ///
403
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
404
    ///     any error that occurred while retrieving the socket option.
405
0
    private func _getIPMulticastIF() -> EventLoopFuture<in_addr> {
406
0
        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_if)
407
0
    }
408
409
    /// Sets the socket option IP_MULTICAST_TTL to `value`.
410
    ///
411
    /// - Parameters:
412
    ///   - value: The value to set IP_MULTICAST_TTL to.
413
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
414
    ///     or if an error has occurred.
415
0
    private func _setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
416
0
        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_ttl, value: value)
417
0
    }
418
419
    /// Gets the value of the socket option IP_MULTICAST_TTL.
420
    ///
421
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
422
    ///     any error that occurred while retrieving the socket option.
423
0
    private func _getIPMulticastTTL() -> EventLoopFuture<CUnsignedChar> {
424
0
        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_ttl)
425
0
    }
426
427
    /// Sets the socket option IP_MULTICAST_LOOP to `value`.
428
    ///
429
    /// - Parameters:
430
    ///   - value: The value to set IP_MULTICAST_LOOP to.
431
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
432
    ///     or if an error has occurred.
433
0
    private func _setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture<Void> {
434
0
        self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_loop, value: value)
435
0
    }
436
437
    /// Gets the value of the socket option IP_MULTICAST_LOOP.
438
    ///
439
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
440
    ///     any error that occurred while retrieving the socket option.
441
0
    private func _getIPMulticastLoop() -> EventLoopFuture<CUnsignedChar> {
442
0
        self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_loop)
443
0
    }
444
445
    /// Sets the socket option IPV6_MULTICAST_IF to `value`.
446
    ///
447
    /// - Parameters:
448
    ///   - value: The value to set IPV6_MULTICAST_IF to.
449
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
450
    ///     or if an error has occurred.
451
0
    private func _setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
452
0
        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_if, value: value)
453
0
    }
454
455
    /// Gets the value of the socket option IPV6_MULTICAST_IF.
456
    ///
457
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
458
    ///     any error that occurred while retrieving the socket option.
459
0
    private func _getIPv6MulticastIF() -> EventLoopFuture<CUnsignedInt> {
460
0
        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_if)
461
0
    }
462
463
    /// Sets the socket option IPV6_MULTICAST_HOPS to `value`.
464
    ///
465
    /// - Parameters:
466
    ///   - value: The value to set IPV6_MULTICAST_HOPS to.
467
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
468
    ///     or if an error has occurred.
469
0
    private func _setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture<Void> {
470
0
        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_hops, value: value)
471
0
    }
472
473
    /// Gets the value of the socket option IPV6_MULTICAST_HOPS.
474
    ///
475
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
476
    ///     any error that occurred while retrieving the socket option.
477
0
    private func _getIPv6MulticastHops() -> EventLoopFuture<CInt> {
478
0
        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_hops)
479
0
    }
480
481
    /// Sets the socket option IPV6_MULTICAST_LOOP to `value`.
482
    ///
483
    /// - Parameters:
484
    ///   - value: The value to set IPV6_MULTICAST_LOOP to.
485
    /// - Returns: An `EventLoopFuture` that fires when the option has been set,
486
    ///     or if an error has occurred.
487
0
    private func _setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture<Void> {
488
0
        self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_loop, value: value)
489
0
    }
490
491
    /// Gets the value of the socket option IPV6_MULTICAST_LOOP.
492
    ///
493
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
494
    ///     any error that occurred while retrieving the socket option.
495
0
    private func _getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
496
0
        self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_loop)
497
0
    }
498
499
    #if os(Linux) || os(FreeBSD) || os(Android)
500
    /// Gets the value of the socket option TCP_INFO.
501
    ///
502
    /// This socket option cannot be set.
503
    ///
504
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
505
    ///     any error that occurred while retrieving the socket option.
506
0
    private func _getTCPInfo() -> EventLoopFuture<tcp_info> {
507
0
        self.unsafeGetSocketOption(level: .tcp, name: .tcp_info)
508
0
    }
509
    #endif
510
511
    #if canImport(Darwin)
512
    /// Gets the value of the socket option TCP_CONNECTION_INFO.
513
    ///
514
    /// This socket option cannot be set.
515
    ///
516
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
517
    ///     any error that occurred while retrieving the socket option.
518
    private func _getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
519
        self.unsafeGetSocketOption(level: .tcp, name: .tcp_connection_info)
520
    }
521
    #endif
522
523
    #if os(Linux)
524
    /// Gets the value of the socket option MPTCP_INFO.
525
    ///
526
    /// This socket option cannot be set.
527
    ///
528
    /// - Returns: An `EventLoopFuture` containing the value of the socket option, or
529
    ///     any error that occurred while retrieving the socket option.
530
0
    private func _getMPTCPInfo() -> EventLoopFuture<mptcp_info> {
531
0
        self.unsafeGetSocketOption(level: .mptcp, name: .mptcp_info)
532
0
    }
533
    #endif
534
}