File: PipeChannel.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (117 lines) | stat: -rw-r--r-- 4,646 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2019 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
//
//===----------------------------------------------------------------------===//

final class PipeChannel: BaseStreamSocketChannel<PipePair> {
    private let pipePair: PipePair

    internal enum Direction {
        case input
        case output
    }

    init(eventLoop: SelectableEventLoop,
         inputPipe: NIOFileHandle,
         outputPipe: NIOFileHandle) throws {
        self.pipePair = try PipePair(inputFD: inputPipe, outputFD: outputPipe)
        try super.init(socket: self.pipePair,
                       parent: nil,
                       eventLoop: eventLoop,
                       recvAllocator: AdaptiveRecvByteBufferAllocator())
    }

    func registrationForInput(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {
        return NIORegistration(channel: .pipeChannel(self, .input),
                               interested: interested,
                               registrationID: registrationID)
    }

    func registrationForOutput(interested: SelectorEventSet, registrationID: SelectorRegistrationID) -> NIORegistration {
        return NIORegistration(channel: .pipeChannel(self, .output),
                               interested: interested,
                               registrationID: registrationID)
    }

    override func connectSocket(to address: SocketAddress) throws -> Bool {
        throw ChannelError.operationUnsupported
    }

    override func finishConnectSocket() throws {
        throw ChannelError.inappropriateOperationForState
    }

    override func register(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {
        try selector.register(selectable: self.pipePair.inputFD,
                              interested: interested.intersection([.read, .reset]),
                              makeRegistration: self.registrationForInput)
        try selector.register(selectable: self.pipePair.outputFD,
                              interested: interested.intersection([.write, .reset]),
                              makeRegistration: self.registrationForOutput)

    }

    override func deregister(selector: Selector<NIORegistration>, mode: CloseMode) throws {
        if (mode == .all || mode == .input) && self.pipePair.inputFD.isOpen {
            try selector.deregister(selectable: self.pipePair.inputFD)
        }
        if (mode == .all || mode == .output) && self.pipePair.outputFD.isOpen {
            try selector.deregister(selectable: self.pipePair.outputFD)
        }
    }

    override func reregister(selector: Selector<NIORegistration>, interested: SelectorEventSet) throws {
        if self.pipePair.inputFD.isOpen {
            try selector.reregister(selectable: self.pipePair.inputFD,
                                    interested: interested.intersection([.read, .reset]))
        }
        if self.pipePair.outputFD.isOpen {
            try selector.reregister(selectable: self.pipePair.outputFD,
                                    interested: interested.intersection([.write, .reset]))
        }
    }

    override func readEOF() {
        super.readEOF()
        guard self.pipePair.inputFD.isOpen else {
            return
        }
        try! self.selectableEventLoop.deregister(channel: self, mode: .input)
        try! self.pipePair.inputFD.close()
    }

    override func writeEOF() {
        guard self.pipePair.outputFD.isOpen else {
            return
        }
        try! self.selectableEventLoop.deregister(channel: self, mode: .output)
        try! self.pipePair.outputFD.close()
    }

    override func shutdownSocket(mode: CloseMode) throws {
        switch mode {
        case .input:
            try! self.selectableEventLoop.deregister(channel: self, mode: .input)
        case .output:
            try! self.selectableEventLoop.deregister(channel: self, mode: .output)
        case .all:
            break
        }
        try super.shutdownSocket(mode: mode)
    }
}

extension PipeChannel: CustomStringConvertible {
    var description: String {
        return "PipeChannel { \(self.socketDescription), active = \(self.isActive), localAddress = \(self.localAddress.debugDescription), remoteAddress = \(self.remoteAddress.debugDescription) }"
    }
}