swift-nio/Sources/NIO/SocketProtocols.swift

103 lines
3.5 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
protocol BaseSocketProtocol: CustomStringConvertible {
associatedtype SelectableType: Selectable
var isOpen: Bool { get }
func close() throws
func bind(to address: SocketAddress) throws
func localAddress() throws -> SocketAddress
func remoteAddress() throws -> SocketAddress
func setOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option, value: T) throws
func getOption<T>(level: NIOBSDSocket.OptionLevel, name: NIOBSDSocket.Option) throws -> T
}
protocol ServerSocketProtocol: BaseSocketProtocol {
func listen(backlog: Int32) throws
func accept(setNonBlocking: Bool) throws -> Socket?
}
protocol SocketProtocol: BaseSocketProtocol {
func connect(to address: SocketAddress) throws -> Bool
func finishConnect() throws
func write(pointer: UnsafeRawBufferPointer) throws -> IOResult<Int>
func writev(iovecs: UnsafeBufferPointer<IOVector>) throws -> IOResult<Int>
func read(pointer: UnsafeMutableRawBufferPointer) throws -> IOResult<Int>
func recvmsg(pointer: UnsafeMutableRawBufferPointer,
storage: inout sockaddr_storage,
storageLen: inout socklen_t,
controlBytes: inout UnsafeReceivedControlBytes) throws -> IOResult<Int>
func sendmsg(pointer: UnsafeRawBufferPointer,
destinationPtr: UnsafePointer<sockaddr>,
destinationSize: socklen_t,
controlBytes: UnsafeMutableRawBufferPointer) throws -> IOResult<Int>
func sendFile(fd: Int32, offset: Int, count: Int) throws -> IOResult<Int>
func recvmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>
func sendmmsg(msgs: UnsafeMutableBufferPointer<MMsgHdr>) throws -> IOResult<Int>
func shutdown(how: Shutdown) throws
func ignoreSIGPIPE() throws
}
#if os(Linux)
// This is a lazily initialised global variable that when read for the first time, will ignore SIGPIPE.
private let globallyIgnoredSIGPIPE: Bool = {
/* no F_SETNOSIGPIPE on Linux :( */
_ = Glibc.signal(SIGPIPE, SIG_IGN)
return true
}()
#endif
extension BaseSocketProtocol {
// used by `BaseSocket` and `PipePair`.
internal static func ignoreSIGPIPE(descriptor fd: CInt) throws {
#if os(Linux)
let haveWeIgnoredSIGPIEThisIsHereToTriggerIgnoringIt = globallyIgnoredSIGPIPE
guard haveWeIgnoredSIGPIEThisIsHereToTriggerIgnoringIt else {
fatalError("BUG in NIO. We did not ignore SIGPIPE, this code path should definitely not be reachable.")
}
#else
assert(fd >= 0, "illegal file descriptor \(fd)")
do {
try Posix.fcntl(descriptor: fd, command: F_SETNOSIGPIPE, value: 1)
} catch let error as IOError {
if error.errnoCode == EINVAL {
// Darwin seems to sometimes do this despite the docs claiming it can't happen
throw NIOFcntlFailedError()
}
try? Posix.close(descriptor: fd) // don't care about failure here
throw error
}
#endif
}
}