]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / swift / Sources / TSocketTransport.swift
CommitLineData
f67539c2
TL
1
2/*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 */
20
21
22#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
23 import Darwin
24#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
25 import Glibc
26 import Dispatch
27#endif
28
29import Foundation
30import CoreFoundation
31
32#if !swift(>=4.2)
33// Swift 3/4 compatibility
34fileprivate extension RunLoopMode {
35 static let `default` = defaultRunLoopMode
36}
37#endif
38
39private struct Sys {
40 #if os(Linux)
41 static let read = Glibc.read
42 static let write = Glibc.write
43 static let close = Glibc.close
44 #else
45 static let read = Darwin.read
46 static let write = Darwin.write
47 static let close = Darwin.close
48 #endif
49}
50
51extension in_addr {
52 public init?(hostent: hostent?) {
53 guard let host = hostent, host.h_addr_list != nil, host.h_addr_list.pointee != nil else {
54 return nil
55 }
56 self.init()
57 memcpy(&self, host.h_addr_list.pointee!, Int(host.h_length))
58
59 }
60}
61
62
63#if os(Linux)
64 /// TCFSocketTransport currently unavailable
65 /// remove comments and build to see why/fix
66 /// currently CF[Read|Write]Stream's can't cast to [Input|Output]Streams which breaks thigns
67#else
68extension Stream.PropertyKey {
69 static let SSLPeerTrust = Stream.PropertyKey(kCFStreamPropertySSLPeerTrust as String)
70}
71
72/// TCFSocketTransport, uses CFSockets and (NS)Stream's
73public class TCFSocketTransport: TStreamTransport {
74 public init?(hostname: String, port: Int, secure: Bool = false) {
75
76 var inputStream: InputStream
77 var outputStream: OutputStream
78
79 var readStream: Unmanaged<CFReadStream>?
80 var writeStream: Unmanaged<CFWriteStream>?
81 CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
82 hostname as CFString,
83 UInt32(port),
84 &readStream,
85 &writeStream)
86
87 if let readStream = readStream?.takeRetainedValue(),
88 let writeStream = writeStream?.takeRetainedValue() {
89 CFReadStreamSetProperty(readStream, .shouldCloseNativeSocket, kCFBooleanTrue)
90 CFWriteStreamSetProperty(writeStream, .shouldCloseNativeSocket, kCFBooleanTrue)
91
92 if secure {
93 CFReadStreamSetProperty(readStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL.rawValue as CFString)
94 CFWriteStreamSetProperty(writeStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL.rawValue as CFString)
95 }
96
97 inputStream = readStream as InputStream
98 inputStream.schedule(in: .current, forMode: .default)
99 inputStream.open()
100
101 outputStream = writeStream as OutputStream
102 outputStream.schedule(in: .current, forMode: .default)
103 outputStream.open()
104
105 } else {
106
107 if readStream != nil {
108 readStream?.release()
109 }
110 if writeStream != nil {
111 writeStream?.release()
112 }
113 super.init(inputStream: nil, outputStream: nil)
114 return nil
115 }
116
117 super.init(inputStream: inputStream, outputStream: outputStream)
118
119 self.input?.delegate = self
120 self.output?.delegate = self
121 }
122}
123
124extension TCFSocketTransport: StreamDelegate { }
125#endif
126
127
128/// TSocketTransport, posix sockets. Supports IPv4 only for now
129public class TSocketTransport : TTransport {
130 public var socketDescriptor: Int32
131
132
133
134 /// Initialize from an already set up socketDescriptor.
135 /// Expects socket thats already bound/connected (i.e. from listening)
136 ///
137 /// - parameter socketDescriptor: posix socket descriptor (Int32)
138 public init(socketDescriptor: Int32) {
139 self.socketDescriptor = socketDescriptor
140 }
141
142
143 public convenience init(hostname: String, port: Int) throws {
144 guard let hp = gethostbyname(hostname.cString(using: .utf8)!)?.pointee,
145 let hostAddr = in_addr(hostent: hp) else {
146 throw TTransportError(error: .unknown, message: "Invalid address: \(hostname)")
147 }
148
149
150 #if os(Linux)
151 let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
152 var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
153 sin_port: in_port_t(htons(UInt16(port))),
154 sin_addr: hostAddr,
155 sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
156 #else
157 let sock = socket(AF_INET, SOCK_STREAM, 0)
158
159 var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
160 sin_family: sa_family_t(AF_INET),
161 sin_port: in_port_t(htons(UInt16(port))),
162 sin_addr: in_addr(s_addr: in_addr_t(0)),
163 sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
164
165 #endif
166
167 let addrPtr = withUnsafePointer(to: &addr){ UnsafePointer<sockaddr>(OpaquePointer($0)) }
168
169 let connected = connect(sock, addrPtr, UInt32(MemoryLayout<sockaddr_in>.size))
170 if connected != 0 {
171 throw TTransportError(error: .notOpen, message: "Error binding to host: \(hostname) \(port)")
172 }
173
174 self.init(socketDescriptor: sock)
175 }
176
177 deinit {
178 close()
179 }
180
181 public func readAll(size: Int) throws -> Data {
182 var out = Data()
183 while out.count < size {
184 out.append(try self.read(size: size))
185 }
186 return out
187 }
188
189 public func read(size: Int) throws -> Data {
190 var buff = Array<UInt8>.init(repeating: 0, count: size)
191 let readBytes = Sys.read(socketDescriptor, &buff, size)
192
193 return Data(buff[0..<readBytes])
194 }
195
196 public func write(data: Data) {
197 var bytesToWrite = data.count
198 var writeBuffer = data
199 while bytesToWrite > 0 {
200 let written = writeBuffer.withUnsafeBytes {
201 Sys.write(socketDescriptor, $0, writeBuffer.count)
202 }
203 writeBuffer = writeBuffer.subdata(in: written ..< writeBuffer.count)
204 bytesToWrite -= written
205 }
206 }
207
208 public func flush() throws {
209 // nothing to do
210 }
211
212 public func close() {
213 shutdown(socketDescriptor, Int32(SHUT_RDWR))
214 _ = Sys.close(socketDescriptor)
215 }
216}