diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift')
-rw-r--r-- | src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift new file mode 100644 index 000000000..21325033b --- /dev/null +++ b/src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift @@ -0,0 +1,216 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + import Darwin +#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) + import Glibc + import Dispatch +#endif + +import Foundation +import CoreFoundation + +#if !swift(>=4.2) +// Swift 3/4 compatibility +fileprivate extension RunLoopMode { + static let `default` = defaultRunLoopMode +} +#endif + +private struct Sys { + #if os(Linux) + static let read = Glibc.read + static let write = Glibc.write + static let close = Glibc.close + #else + static let read = Darwin.read + static let write = Darwin.write + static let close = Darwin.close + #endif +} + +extension in_addr { + public init?(hostent: hostent?) { + guard let host = hostent, host.h_addr_list != nil, host.h_addr_list.pointee != nil else { + return nil + } + self.init() + memcpy(&self, host.h_addr_list.pointee!, Int(host.h_length)) + + } +} + + +#if os(Linux) + /// TCFSocketTransport currently unavailable + /// remove comments and build to see why/fix + /// currently CF[Read|Write]Stream's can't cast to [Input|Output]Streams which breaks thigns +#else +extension Stream.PropertyKey { + static let SSLPeerTrust = Stream.PropertyKey(kCFStreamPropertySSLPeerTrust as String) +} + +/// TCFSocketTransport, uses CFSockets and (NS)Stream's +public class TCFSocketTransport: TStreamTransport { + public init?(hostname: String, port: Int, secure: Bool = false) { + + var inputStream: InputStream + var outputStream: OutputStream + + var readStream: Unmanaged<CFReadStream>? + var writeStream: Unmanaged<CFWriteStream>? + CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, + hostname as CFString, + UInt32(port), + &readStream, + &writeStream) + + if let readStream = readStream?.takeRetainedValue(), + let writeStream = writeStream?.takeRetainedValue() { + CFReadStreamSetProperty(readStream, .shouldCloseNativeSocket, kCFBooleanTrue) + CFWriteStreamSetProperty(writeStream, .shouldCloseNativeSocket, kCFBooleanTrue) + + if secure { + CFReadStreamSetProperty(readStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL.rawValue as CFString) + CFWriteStreamSetProperty(writeStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL.rawValue as CFString) + } + + inputStream = readStream as InputStream + inputStream.schedule(in: .current, forMode: .default) + inputStream.open() + + outputStream = writeStream as OutputStream + outputStream.schedule(in: .current, forMode: .default) + outputStream.open() + + } else { + + if readStream != nil { + readStream?.release() + } + if writeStream != nil { + writeStream?.release() + } + super.init(inputStream: nil, outputStream: nil) + return nil + } + + super.init(inputStream: inputStream, outputStream: outputStream) + + self.input?.delegate = self + self.output?.delegate = self + } +} + +extension TCFSocketTransport: StreamDelegate { } +#endif + + +/// TSocketTransport, posix sockets. Supports IPv4 only for now +public class TSocketTransport : TTransport { + public var socketDescriptor: Int32 + + + + /// Initialize from an already set up socketDescriptor. + /// Expects socket thats already bound/connected (i.e. from listening) + /// + /// - parameter socketDescriptor: posix socket descriptor (Int32) + public init(socketDescriptor: Int32) { + self.socketDescriptor = socketDescriptor + } + + + public convenience init(hostname: String, port: Int) throws { + guard let hp = gethostbyname(hostname.cString(using: .utf8)!)?.pointee, + let hostAddr = in_addr(hostent: hp) else { + throw TTransportError(error: .unknown, message: "Invalid address: \(hostname)") + } + + + #if os(Linux) + let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0) + var addr = sockaddr_in(sin_family: sa_family_t(AF_INET), + sin_port: in_port_t(htons(UInt16(port))), + sin_addr: hostAddr, + sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) + #else + let sock = socket(AF_INET, SOCK_STREAM, 0) + + var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size), + sin_family: sa_family_t(AF_INET), + sin_port: in_port_t(htons(UInt16(port))), + sin_addr: in_addr(s_addr: in_addr_t(0)), + sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) + + #endif + + let addrPtr = withUnsafePointer(to: &addr){ UnsafePointer<sockaddr>(OpaquePointer($0)) } + + let connected = connect(sock, addrPtr, UInt32(MemoryLayout<sockaddr_in>.size)) + if connected != 0 { + throw TTransportError(error: .notOpen, message: "Error binding to host: \(hostname) \(port)") + } + + self.init(socketDescriptor: sock) + } + + deinit { + close() + } + + public func readAll(size: Int) throws -> Data { + var out = Data() + while out.count < size { + out.append(try self.read(size: size)) + } + return out + } + + public func read(size: Int) throws -> Data { + var buff = Array<UInt8>.init(repeating: 0, count: size) + let readBytes = Sys.read(socketDescriptor, &buff, size) + + return Data(buff[0..<readBytes]) + } + + public func write(data: Data) { + var bytesToWrite = data.count + var writeBuffer = data + while bytesToWrite > 0 { + let written = writeBuffer.withUnsafeBytes { + Sys.write(socketDescriptor, $0, writeBuffer.count) + } + writeBuffer = writeBuffer.subdata(in: written ..< writeBuffer.count) + bytesToWrite -= written + } + } + + public func flush() throws { + // nothing to do + } + + public func close() { + shutdown(socketDescriptor, Int32(SHUT_RDWR)) + _ = Sys.close(socketDescriptor) + } +} |