summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/thrift/lib/swift/Sources
diff options
context:
space:
mode:
Diffstat (limited to 'src/jaegertracing/thrift/lib/swift/Sources')
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/LinuxHelper.swift46
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TApplicationError.swift157
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TBinary.swift32
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift384
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TClient.swift55
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TCompactProtocol.swift571
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TEnum.swift32
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TError.swift77
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TFileHandleTransport.swift56
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TFileTransport.swift101
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TFramedTransport.swift123
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/THTTPSessionTransport.swift184
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TList.swift138
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TMap.swift190
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TMemoryBufferTransport.swift74
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TMultiplexedProtocol.swift47
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TProcessor.swift29
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TProtocol.swift182
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TProtocolError.swift146
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransport.swift236
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransportError.swift48
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSerializable.swift136
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSet.swift189
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSocketServer.swift148
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TSocketTransport.swift216
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TStreamTransport.swift150
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TStruct.swift100
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TTransport.swift64
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TTransportError.swift86
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/TWrappedProtocol.swift208
-rw-r--r--src/jaegertracing/thrift/lib/swift/Sources/Thrift.swift3
31 files changed, 4208 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/LinuxHelper.swift b/src/jaegertracing/thrift/lib/swift/Sources/LinuxHelper.swift
new file mode 100644
index 000000000..66d92bb4d
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/LinuxHelper.swift
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+
+import Foundation
+import CoreFoundation
+
+#if os(Linux)
+/// Extensions for Linux for incomplete Foundation API's.
+/// swift-corelibs-foundation is not yet 1:1 with OSX/iOS Foundation
+
+extension CFSocketError {
+ public static let success = kCFSocketSuccess
+}
+
+extension UInt {
+ public static func &(lhs: UInt, rhs: Int) -> UInt {
+ let cast = unsafeBitCast(rhs, to: UInt.self)
+ return lhs & cast
+ }
+}
+
+#else
+extension CFStreamPropertyKey {
+ static let shouldCloseNativeSocket = CFStreamPropertyKey(kCFStreamPropertyShouldCloseNativeSocket)
+ // Exists as Stream.PropertyKey.socketSecuritylevelKey but doesn't work with CFReadStreamSetProperty
+ static let socketSecurityLevel = CFStreamPropertyKey(kCFStreamPropertySocketSecurityLevel)
+ static let SSLSettings = CFStreamPropertyKey(kCFStreamPropertySSLSettings)
+}
+#endif
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TApplicationError.swift b/src/jaegertracing/thrift/lib/swift/Sources/TApplicationError.swift
new file mode 100644
index 000000000..bc3939680
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TApplicationError.swift
@@ -0,0 +1,157 @@
+/*
+* 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.
+*/
+
+
+public struct TApplicationError : TError {
+ public enum Code : TErrorCode {
+ case unknown
+ case unknownMethod(methodName: String?)
+ case invalidMessageType
+ case wrongMethodName(methodName: String?)
+ case badSequenceId
+ case missingResult(methodName: String?)
+ case internalError
+ case protocolError
+ case invalidTransform
+ case invalidProtocol
+ case unsupportedClientType
+
+
+ /// Initialize a TApplicationError with a Thrift error code
+ /// Normally this would be achieved with RawRepresentable however
+ /// by doing this we can allow for associated properties on enum cases for
+ /// case specific context data in a Swifty, type-safe manner.
+ ///
+ /// - parameter thriftErrorCode: Integer TApplicationError(exception) error code.
+ /// Default to 0 (.unknown)
+ public init(thriftErrorCode: Int) {
+ switch thriftErrorCode {
+ case 1: self = .unknownMethod(methodName: nil)
+ case 2: self = .invalidMessageType
+ case 3: self = .wrongMethodName(methodName: nil)
+ case 4: self = .badSequenceId
+ case 5: self = .missingResult(methodName: nil)
+ case 6: self = .internalError
+ case 7: self = .protocolError
+ case 8: self = .invalidProtocol
+ case 9: self = .invalidTransform
+ case 10: self = .unsupportedClientType
+ default: self = .unknown
+ }
+ }
+ public var thriftErrorCode: Int {
+ switch self {
+ case .unknown: return 0
+ case .unknownMethod: return 1
+ case .invalidMessageType: return 2
+ case .wrongMethodName: return 3
+ case .badSequenceId: return 4
+ case .missingResult: return 5
+ case .internalError: return 6
+ case .protocolError: return 7
+ case .invalidProtocol: return 8
+ case .invalidTransform: return 9
+ case .unsupportedClientType: return 10
+ }
+ }
+
+ public var description: String {
+ /// Output "for #methodName" if method is not nil else empty
+ let methodUnwrap: (String?) -> String = { method in
+ return "\(method == nil ? "" : " for \(method ?? "")")"
+ }
+ switch self {
+ case .unknown: return "Unknown TApplicationError"
+ case .unknownMethod(let method): return "Unknown Method\(methodUnwrap(method))"
+ case .invalidMessageType: return "Invalid Message Type"
+ case .wrongMethodName(let method): return "Wrong Method Name\(methodUnwrap(method))"
+ case .badSequenceId: return "Bad Sequence ID"
+ case .missingResult(let method): return "Missing Result\(methodUnwrap(method))"
+ case .internalError: return "Internal Error"
+ case .protocolError: return "Protocol Error"
+ case .invalidProtocol: return "Invalid Protocol"
+ case .invalidTransform: return "Invalid Transform"
+ case .unsupportedClientType: return "Unsupported Client Type"
+ }
+ }
+ }
+
+ public init() { }
+
+ public init(thriftErrorCode code: Int, message: String? = nil) {
+ self.error = Code(thriftErrorCode: code)
+ self.message = message
+ }
+
+ public var error: Code = .unknown
+ public var message: String? = nil
+ public static var defaultCase: Code { return .unknown }
+}
+
+extension TApplicationError : TSerializable {
+ public static var thriftType: TType { return .struct }
+
+ public static func read(from proto: TProtocol) throws -> TApplicationError {
+ var errorCode: Int = 0
+ var message: String? = nil
+ _ = try proto.readStructBegin()
+ fields: while true {
+ let (_, fieldType, fieldID) = try proto.readFieldBegin()
+
+ switch (fieldID, fieldType) {
+ case (_, .stop):
+ break fields
+ case (1, .string):
+ message = try proto.read()
+ case (2, .i32):
+ errorCode = Int(try proto.read() as Int32)
+
+ case let (_, unknownType):
+ try proto.skip(type: unknownType)
+ }
+
+ try proto.readFieldEnd()
+ }
+ try proto.readStructEnd()
+ return TApplicationError(thriftErrorCode: errorCode, message: message)
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.writeStructBegin(name: "TApplicationException")
+
+ try proto.writeFieldBegin(name: "message", type: .string, fieldID: 1)
+ try proto.write(message ?? "")
+ try proto.writeFieldEnd()
+
+ try proto.writeFieldBegin(name: "type", type: .i32, fieldID: 2)
+ let val = Int32(error.thriftErrorCode)
+ try proto.write(val)
+ try proto.writeFieldEnd()
+ try proto.writeFieldStop()
+ try proto.writeStructEnd()
+ }
+
+ public var hashValue: Int {
+ return error.thriftErrorCode &+ (message?.hashValue ?? 0)
+ }
+}
+
+public func ==(lhs: TApplicationError, rhs: TApplicationError) -> Bool {
+ return lhs.error.thriftErrorCode == rhs.error.thriftErrorCode && lhs.message == rhs.message
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TBinary.swift b/src/jaegertracing/thrift/lib/swift/Sources/TBinary.swift
new file mode 100644
index 000000000..4be56441a
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TBinary.swift
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+import Foundation
+
+extension Data : TSerializable {
+ public static var thriftType: TType { return .string }
+
+ public static func read(from proto: TProtocol) throws -> Data {
+ return try proto.read() as Data
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift
new file mode 100644
index 000000000..85acce045
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ */
+
+import Foundation
+
+public struct TBinaryProtocolVersion {
+ static let version1 = Int32(bitPattern: 0x80010000)
+ static let versionMask = Int32(bitPattern: 0xffff0000)
+}
+
+public class TBinaryProtocol: TProtocol {
+ public var messageSizeLimit: UInt32 = 0
+
+ public var transport: TTransport
+
+ // class level properties for setting global config (useful for server in lieu of Factory design)
+ public static var strictRead: Bool = false
+ public static var strictWrite: Bool = true
+
+ private var strictRead: Bool
+ private var strictWrite: Bool
+
+ var currentMessageName: String?
+ var currentFieldName: String?
+
+
+ public convenience init(transport: TTransport, strictRead: Bool, strictWrite: Bool) {
+ self.init(on: transport)
+ self.strictRead = strictRead
+ self.strictWrite = strictWrite
+ }
+
+ public required init(on transport: TTransport) {
+ self.transport = transport
+ self.strictWrite = TBinaryProtocol.strictWrite
+ self.strictRead = TBinaryProtocol.strictRead
+ }
+
+ func readStringBody(_ size: Int) throws -> String {
+
+ var data = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport read failed")) {
+ data = try self.transport.readAll(size: size)
+ }
+
+ return String(data: data, encoding: String.Encoding.utf8) ?? ""
+ }
+
+ /// Mark: - TProtocol
+
+ public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+ let size: Int32 = try read()
+ var messageName = ""
+ var type = TMessageType.exception
+
+ if size < 0 {
+ let version = size & TBinaryProtocolVersion.versionMask
+ if version != TBinaryProtocolVersion.version1 {
+ throw TProtocolError(error: .badVersion(expected: "\(TBinaryProtocolVersion.version1)",
+ got: "\(version)"))
+ }
+ type = TMessageType(rawValue: Int32(size) & 0x00FF) ?? type
+ messageName = try read()
+ } else {
+ if strictRead {
+ let errorMessage = "Missing message version, old client? Message Name: \(currentMessageName ?? "")"
+ throw TProtocolError(error: .invalidData,
+ message: errorMessage)
+ }
+ if messageSizeLimit > 0 && size > Int32(messageSizeLimit) {
+ throw TProtocolError(error: .sizeLimit(limit: Int(messageSizeLimit), got: Int(size)))
+ }
+
+ messageName = try readStringBody(Int(size))
+ type = TMessageType(rawValue: Int32(try read() as UInt8)) ?? type
+ }
+
+ let seqID: Int32 = try read()
+ return (messageName, type, seqID)
+ }
+
+ public func readMessageEnd() throws {
+ return
+ }
+
+ public func readStructBegin() throws -> String {
+ return ""
+ }
+
+ public func readStructEnd() throws {
+ return
+ }
+
+ public func readFieldBegin() throws -> (String, TType, Int32) {
+
+ let fieldType = TType(rawValue: Int32(try read() as UInt8)) ?? TType.stop
+ var fieldID: Int32 = 0
+
+ if fieldType != .stop {
+ fieldID = Int32(try read() as Int16)
+ }
+
+ return ("", fieldType, fieldID)
+ }
+
+ public func readFieldEnd() throws {
+ return
+ }
+
+ public func readMapBegin() throws -> (TType, TType, Int32) {
+ var raw = Int32(try read() as UInt8)
+ guard let keyType = TType(rawValue: raw) else {
+ throw TProtocolError(message: "Unknown value for keyType TType: \(raw)")
+ }
+
+ raw = Int32(try read() as UInt8)
+ guard let valueType = TType(rawValue: raw) else {
+ throw TProtocolError(message: "Unknown value for valueType TType: \(raw)")
+ }
+ let size: Int32 = try read()
+
+ return (keyType, valueType, size)
+ }
+
+ public func readMapEnd() throws {
+ return
+ }
+
+ public func readSetBegin() throws -> (TType, Int32) {
+ let raw = Int32(try read() as UInt8)
+ guard let elementType = TType(rawValue: raw) else {
+ throw TProtocolError(message: "Unknown value for elementType TType: \(raw)")
+ }
+
+ let size: Int32 = try read()
+
+ return (elementType, size)
+ }
+
+ public func readSetEnd() throws {
+ return
+ }
+
+ public func readListBegin() throws -> (TType, Int32) {
+ let raw = Int32(try read() as UInt8)
+ guard let elementType = TType(rawValue: raw) else {
+ throw TProtocolError(message: "Unknown value for elementType TType: \(raw)")
+ }
+ let size: Int32 = try read()
+
+ return (elementType, size)
+ }
+
+ public func readListEnd() throws {
+ return
+ }
+
+ public func read() throws -> String {
+ let data: Data = try read()
+ guard let str = String.init(data: data, encoding: .utf8) else {
+ throw TProtocolError(error: .invalidData, message: "Couldn't encode UTF-8 from data read")
+ }
+ return str
+ }
+
+ public func read() throws -> Bool {
+ return (try read() as UInt8) == 1
+ }
+
+ public func read() throws -> UInt8 {
+ var buff = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 1)
+ }
+ return buff[0]
+ }
+
+ public func read() throws -> Int16 {
+ var buff = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 2)
+ }
+ var ret = Int16(buff[0] & 0xff) << 8
+ ret |= Int16(buff[1] & 0xff)
+ return ret
+ }
+
+ public func read() throws -> Int32 {
+ var buff = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 4)
+ }
+ var ret = Int32(buff[0] & 0xff) << 24
+ ret |= Int32(buff[1] & 0xff) << 16
+ ret |= Int32(buff[2] & 0xff) << 8
+ ret |= Int32(buff[3] & 0xff)
+
+ return ret
+ }
+
+ public func read() throws -> Int64 {
+ var buff = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 8)
+ }
+ var ret = Int64(buff[0] & 0xff) << 56
+ ret |= Int64(buff[1] & 0xff) << 48
+ ret |= Int64(buff[2] & 0xff) << 40
+ ret |= Int64(buff[3] & 0xff) << 32
+ ret |= Int64(buff[4] & 0xff) << 24
+ ret |= Int64(buff[5] & 0xff) << 16
+ ret |= Int64(buff[6] & 0xff) << 8
+ ret |= Int64(buff[7] & 0xff)
+
+ return ret
+ }
+
+ public func read() throws -> Double {
+ let val = try read() as Int64
+ return Double(bitPattern: UInt64(bitPattern: val))
+ }
+
+ public func read() throws -> Data {
+ let size = Int(try read() as Int32)
+ var data = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ data = try self.transport.readAll(size: size)
+ }
+
+ return data
+ }
+
+ // Write methods
+
+ public func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws {
+ if strictWrite {
+ let version = TBinaryProtocolVersion.version1 | Int32(messageType.rawValue)
+ try write(version)
+ try write(name)
+ try write(sequenceID)
+ } else {
+ try write(name)
+ try write(UInt8(messageType.rawValue))
+ try write(sequenceID)
+ }
+ currentMessageName = name
+ }
+
+ public func writeMessageEnd() throws {
+ currentMessageName = nil
+ }
+
+ public func writeStructBegin(name: String) throws {
+ return
+ }
+
+ public func writeStructEnd() throws {
+ return
+ }
+
+ public func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws {
+ try write(UInt8(fieldType.rawValue))
+ try write(Int16(fieldID))
+ }
+
+ public func writeFieldStop() throws {
+ try write(UInt8(TType.stop.rawValue))
+ }
+
+ public func writeFieldEnd() throws {
+ return
+ }
+
+ public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+ try write(UInt8(keyType.rawValue))
+ try write(UInt8(valueType.rawValue))
+ try write(size)
+ }
+
+ public func writeMapEnd() throws {
+ return
+ }
+
+ public func writeSetBegin(elementType: TType, size: Int32) throws {
+ try write(UInt8(elementType.rawValue))
+ try write(size)
+ }
+
+ public func writeSetEnd() throws {
+ return
+ }
+
+ public func writeListBegin(elementType: TType, size: Int32) throws {
+ try write(UInt8(elementType.rawValue))
+ try write(size)
+ }
+
+ public func writeListEnd() throws {
+ return
+ }
+
+ public func write(_ value: String) throws {
+ try write(value.data(using: .utf8)!)
+ }
+
+ public func write(_ value: Bool) throws {
+ let byteVal: UInt8 = value ? 1 : 0
+ try write(byteVal)
+ }
+
+ public func write(_ value: UInt8) throws {
+ let buff = Data([value])
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+ try self.transport.write(data: buff)
+ }
+ }
+
+ public func write(_ value: Int16) throws {
+ var buff = Data()
+ buff.append(Data([UInt8(0xff & (value >> 8))]))
+ buff.append(Data([UInt8(0xff & (value))]))
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+ try self.transport.write(data: buff)
+ }
+ }
+
+ public func write(_ value: Int32) throws {
+ var buff = Data()
+ buff.append(Data([UInt8(0xff & (value >> 24))]))
+ buff.append(Data([UInt8(0xff & (value >> 16))]))
+ buff.append(Data([UInt8(0xff & (value >> 8))]))
+ buff.append(Data([UInt8(0xff & (value))]))
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+ try self.transport.write(data: buff)
+ }
+ }
+
+ public func write(_ value: Int64) throws {
+ var buff = Data()
+ buff.append(Data([UInt8(0xff & (value >> 56))]))
+ buff.append(Data([UInt8(0xff & (value >> 48))]))
+ buff.append(Data([UInt8(0xff & (value >> 40))]))
+ buff.append(Data([UInt8(0xff & (value >> 32))]))
+ buff.append(Data([UInt8(0xff & (value >> 24))]))
+ buff.append(Data([UInt8(0xff & (value >> 16))]))
+ buff.append(Data([UInt8(0xff & (value >> 8))]))
+ buff.append(Data([UInt8(0xff & (value))]))
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+ try self.transport.write(data: buff)
+ }
+ }
+
+ public func write(_ value: Double) throws {
+ // Notably unsafe, since Double and Int64 are the same size, this should work fine
+ try self.write(Int64(bitPattern: value.bitPattern))
+ }
+
+ public func write(_ data: Data) throws {
+ try write(Int32(data.count))
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+ try self.transport.write(data: data)
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TClient.swift b/src/jaegertracing/thrift/lib/swift/Sources/TClient.swift
new file mode 100644
index 000000000..cc3288a8c
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TClient.swift
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+
+open class TClient {
+ public let inProtocol: TProtocol
+ public let outProtocol: TProtocol
+
+ required public init(inoutProtocol: TProtocol) {
+ self.inProtocol = inoutProtocol
+ self.outProtocol = inoutProtocol
+ }
+
+ required public init(inProtocol: TProtocol, outProtocol: TProtocol) {
+ self.inProtocol = inProtocol
+ self.outProtocol = outProtocol
+ }
+}
+
+
+open class TAsyncClient<Protocol: TProtocol, Factory: TAsyncTransportFactory> {
+ public var factory: Factory
+ public init(with protocol: Protocol.Type, factory: Factory) {
+ self.factory = factory
+ }
+}
+
+
+public enum TAsyncResult<T> {
+ case success(T)
+ case error(Swift.Error)
+
+ public func value() throws -> T {
+ switch self {
+ case .success(let t): return t
+ case .error(let e): throw e
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TCompactProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TCompactProtocol.swift
new file mode 100644
index 000000000..5b302d38f
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TCompactProtocol.swift
@@ -0,0 +1,571 @@
+/*
+* 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.
+*/
+
+import Foundation
+import CoreFoundation
+
+public enum TCType: UInt8 {
+ case stop = 0x00
+ case boolean_TRUE = 0x01
+ case boolean_FALSE = 0x02
+ case i8 = 0x03
+ case i16 = 0x04
+ case i32 = 0x05
+ case i64 = 0x06
+ case double = 0x07
+ case binary = 0x08
+ case list = 0x09
+ case set = 0x0A
+ case map = 0x0B
+ case `struct` = 0x0C
+
+ public static let typeMask: UInt8 = 0xE0 // 1110 0000
+ public static let typeBits: UInt8 = 0x07 // 0000 0111
+ public static let typeShiftAmount = 5
+
+}
+
+
+public class TCompactProtocol: TProtocol {
+ public static let protocolID: UInt8 = 0x82
+ public static let version: UInt8 = 1
+ public static let versionMask: UInt8 = 0x1F // 0001 1111
+
+ public var transport: TTransport
+
+ var lastField: [UInt8] = []
+ var lastFieldId: UInt8 = 0
+
+ var boolFieldName: String?
+ var boolFieldType: TType?
+ var boolFieldId: Int32?
+ var booleanValue: Bool?
+
+ var currentMessageName: String?
+
+ public required init(on transport: TTransport) {
+ self.transport = transport
+ }
+
+
+ /// Mark: - TCompactProtocol helpers
+
+ func writebyteDirect(_ byte: UInt8) throws {
+ let byte = Data([byte])
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+ try self.transport.write(data: byte)
+ }
+ }
+
+ func writeVarint32(_ val: UInt32) throws {
+ var val = val
+ var i32buf = [UInt8](repeating: 0, count: 5)
+ var idx = 0
+ while true {
+ if (val & ~0x7F) == 0 {
+ i32buf[idx] = UInt8(val)
+ idx += 1
+ break
+ } else {
+ i32buf[idx] = UInt8((val & 0x7F) | 0x80)
+ idx += 1
+ val >>= 7
+ }
+ }
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+ try self.transport.write(data: Data(i32buf[0..<idx]))
+ }
+ }
+
+ func writeVarint64(_ val: UInt64) throws {
+ var val = val
+ var varint64out = [UInt8](repeating: 0, count: 10)
+ var idx = 0
+ while true {
+ if (val & ~0x7F) == 0{
+ varint64out[idx] = UInt8(val)
+ idx += 1
+ break
+ } else {
+ varint64out[idx] = UInt8(val & 0x7F) | 0x80
+ idx += 1
+ val >>= 7
+ }
+ }
+
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+ try self.transport.write(data: Data(varint64out[0..<idx]))
+ }
+ }
+
+ func writeCollectionBegin(_ elementType: TType, size: Int32) throws {
+ let ctype = compactType(elementType).rawValue
+ if size <= 14 {
+ try writebyteDirect(UInt8(size << 4) | ctype)
+ } else {
+ try writebyteDirect(0xF0 | ctype)
+ try writeVarint32(UInt32(size))
+ }
+ }
+
+ func readBinary(_ size: Int) throws -> Data {
+ var result = Data()
+ if size != 0 {
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ result = try self.transport.readAll(size: size)
+ }
+ }
+ return result
+ }
+
+ func readVarint32() throws -> UInt32 {
+ var result: UInt32 = 0
+ var shift: UInt32 = 0
+ while true {
+ let byte: UInt8 = try read()
+
+ result |= UInt32(byte & 0x7F) << shift
+ if (byte & 0x80) == 0 {
+ break
+ }
+
+ shift += 7
+ }
+
+ return result
+ }
+
+ func readVarint64() throws -> UInt64 {
+ var result: UInt64 = 0
+ var shift: UInt64 = 0
+
+ while true {
+ let byte: UInt8 = try read()
+
+ result |= UInt64(byte & 0x7F) << shift
+ if (byte & 0x80) == 0 {
+ break
+ }
+
+ shift += 7
+ }
+ return result
+ }
+
+
+ func ttype(_ compactTypeVal: UInt8) throws -> TType {
+ guard let compactType = TCType(rawValue: compactTypeVal) else {
+ throw TProtocolError(message: "Unknown TCType value: \(compactTypeVal)")
+ }
+
+ switch compactType {
+ case .stop: return .stop;
+ case .boolean_FALSE, .boolean_TRUE: return .bool;
+ case .i8: return .i8;
+ case .i16: return .i16;
+ case .i32: return .i32;
+ case .i64: return .i64;
+ case .double: return .double;
+ case .binary: return .string;
+ case .list: return .list;
+ case .set: return .set;
+ case .map: return .map;
+ case .struct: return .struct;
+ }
+ }
+
+ func compactType(_ ttype: TType) -> TCType {
+ switch ttype {
+ case .stop: return .stop
+ case .void: return .i8
+ case .bool: return .boolean_FALSE
+ case .i8: return .i8
+ case .double: return .double
+ case .i16: return .i16
+ case .i32: return .i32
+ case .i64: return .i64
+ case .string: return .binary
+ case .struct: return .struct
+ case .map: return .map
+ case .set: return .set
+ case .list: return .list
+ case .utf8: return .binary
+ case .utf16: return .binary
+ }
+ }
+
+ /// ZigZag encoding maps signed integers to unsigned integers so that
+ /// numbers with a small absolute value (for instance, -1) have
+ /// a small varint encoded value too. It does this in a way that
+ /// "zig-zags" back and forth through the positive and negative integers,
+ /// so that -1 is encoded as 1, 1 is encoded as 2, -2 is encoded as 3, and so
+ ///
+ /// - parameter n: number to zigzag
+ ///
+ /// - returns: zigzaged UInt32
+ func i32ToZigZag(_ n : Int32) -> UInt32 {
+ return UInt32(bitPattern: Int32(n << 1) ^ Int32(n >> 31))
+ }
+
+ func i64ToZigZag(_ n : Int64) -> UInt64 {
+ return UInt64(bitPattern: Int64(n << 1) ^ Int64(n >> 63))
+ }
+
+ func zigZagToi32(_ n: UInt32) -> Int32 {
+ return Int32(n >> 1) ^ (-Int32(n & 1))
+ }
+
+ func zigZagToi64(_ n: UInt64) -> Int64 {
+ return Int64(n >> 1) ^ (-Int64(n & 1))
+ }
+
+
+
+ /// Mark: - TProtocol
+
+ public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+ let protocolId: UInt8 = try read()
+
+ if protocolId != TCompactProtocol.protocolID {
+ let expected = String(format:"%2X", TCompactProtocol.protocolID)
+ let got = String(format:"%2X", protocolId)
+ throw TProtocolError(message: "Wrong Protocol ID \(got)",
+ extendedError: .mismatchedProtocol(expected: expected, got: got))
+ }
+
+ let versionAndType: UInt8 = try read()
+ let version: UInt8 = versionAndType & TCompactProtocol.versionMask
+ if version != TCompactProtocol.version {
+ throw TProtocolError(error: .badVersion(expected: "\(TCompactProtocol.version)",
+ got:"\(version)"))
+ }
+
+ let type = (versionAndType >> UInt8(TCType.typeShiftAmount)) & TCType.typeBits
+ guard let mtype = TMessageType(rawValue: Int32(type)) else {
+ throw TProtocolError(message: "Unknown TMessageType value: \(type)")
+ }
+ let sequenceId = try readVarint32()
+ let name: String = try read()
+
+ return (name, mtype, Int32(sequenceId))
+ }
+
+ public func readMessageEnd() throws { }
+
+ public func readStructBegin() throws -> String {
+ lastField.append(lastFieldId)
+ lastFieldId = 0
+ return ""
+ }
+
+ public func readStructEnd() throws {
+ lastFieldId = lastField.last ?? 0
+ lastField.removeLast()
+ }
+
+ public func readFieldBegin() throws -> (String, TType, Int32) {
+ let byte: UInt8 = try read()
+ guard let type = TCType(rawValue: byte & 0x0F) else {
+ throw TProtocolError(message: "Unknown TCType \(byte & 0x0F)")
+ }
+
+ // if it's a stop, then we can return immediately, as the struct is over
+ if type == .stop {
+ return ("", .stop, 0)
+ }
+
+ var fieldId: Int16 = 0
+
+ // mask off the 4MSB of the type header. it could contain a field id delta
+ let modifier = (byte & 0xF0) >> 4
+ if modifier == 0 {
+ // not a delta. look ahead for the zigzag varint field id
+ fieldId = try read()
+ } else {
+ // has a delta. add the delta to the last Read field id.
+ fieldId = Int16(lastFieldId + modifier)
+ }
+
+ let fieldType = try ttype(type.rawValue)
+
+ // if this happens to be a boolean field, the value is encoded in the type
+ if type == .boolean_TRUE || type == .boolean_FALSE {
+ // save the boolean value in a special instance variable
+ booleanValue = type == .boolean_TRUE
+ }
+
+ // push the new field onto the field stack so we can keep the deltas going
+ lastFieldId = UInt8(fieldId)
+ return ("", fieldType, Int32(fieldId))
+ }
+
+ public func readFieldEnd() throws { }
+
+ public func read() throws -> String {
+ let length = try readVarint32()
+
+ var result: String
+
+ if length != 0 {
+ let data = try readBinary(Int(length))
+ result = String(data: data, encoding: String.Encoding.utf8) ?? ""
+ } else {
+ result = ""
+ }
+
+ return result
+ }
+
+ public func read() throws -> Bool {
+ if let val = booleanValue {
+ self.booleanValue = nil
+ return val
+ } else {
+ let result = try read() as UInt8
+ return TCType(rawValue: result) == .boolean_TRUE
+ }
+ }
+
+ public func read() throws -> UInt8 {
+ var buff: UInt8 = 0
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 1)[0]
+ }
+ return buff
+ }
+
+ public func read() throws -> Int16 {
+ let v = try readVarint32()
+ return Int16(zigZagToi32(v))
+ }
+
+ public func read() throws -> Int32 {
+ let v = try readVarint32()
+ return zigZagToi32(v)
+ }
+
+ public func read() throws -> Int64 {
+ let v = try readVarint64()
+ return zigZagToi64(v)
+ }
+
+ public func read() throws -> Double {
+ var buff = Data()
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+ buff = try self.transport.readAll(size: 8)
+ }
+
+ let i64: UInt64 = buff.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> UInt64 in
+ return UnsafePointer<UInt64>(OpaquePointer(ptr)).pointee
+ }
+ let bits = CFSwapInt64LittleToHost(i64)
+ return Double(bitPattern: bits)
+ }
+
+ public func read() throws -> Data {
+ let length = try readVarint32()
+ return try readBinary(Int(length))
+ }
+
+ public func readMapBegin() throws -> (TType, TType, Int32) {
+ var keyAndValueType: UInt8 = 8
+ let size = try readVarint32()
+ if size != 0 {
+ keyAndValueType = try read()
+ }
+
+ let keyType = try ttype(keyAndValueType >> 4)
+ let valueType = try ttype(keyAndValueType & 0xF)
+
+ return (keyType, valueType, Int32(size))
+ }
+
+ public func readMapEnd() throws { }
+
+ public func readSetBegin() throws -> (TType, Int32) {
+ return try readListBegin()
+ }
+
+ public func readSetEnd() throws { }
+
+ public func readListBegin() throws -> (TType, Int32) {
+ let sizeAndType: UInt8 = try read()
+ var size: UInt32 = UInt32(sizeAndType >> 4) & 0x0f
+ if size == 15 {
+ size = try readVarint32()
+ }
+ let elementType = try ttype(sizeAndType & 0x0F)
+
+ return (elementType, Int32(size))
+ }
+
+ public func readListEnd() throws { }
+
+ public func writeMessageBegin(name: String,
+ type messageType: TMessageType,
+ sequenceID: Int32) throws {
+ try writebyteDirect(TCompactProtocol.protocolID)
+ let nextByte: UInt8 = (TCompactProtocol.version & TCompactProtocol.versionMask) |
+ (UInt8((UInt32(messageType.rawValue) << UInt32(TCType.typeShiftAmount))) &
+ TCType.typeMask)
+ try writebyteDirect(nextByte)
+ try writeVarint32(UInt32(sequenceID))
+ try write(name)
+
+ currentMessageName = name
+ }
+
+ public func writeMessageEnd() throws {
+ currentMessageName = nil
+ }
+
+ public func writeStructBegin(name: String) throws {
+ lastField.append(lastFieldId)
+ lastFieldId = 0
+ }
+
+ public func writeStructEnd() throws {
+ lastFieldId = lastField.last ?? 0
+ lastField.removeLast()
+ }
+
+ public func writeFieldBegin(name: String,
+ type fieldType: TType,
+ fieldID: Int32) throws {
+ if fieldType == .bool {
+ boolFieldName = name
+ boolFieldType = fieldType
+ boolFieldId = fieldID
+ return
+ } else {
+ try writeFieldBeginInternal(name: name,
+ type: fieldType,
+ fieldID: fieldID,
+ typeOverride: 0xFF)
+ }
+ }
+
+ func writeFieldBeginInternal(name: String,
+ type fieldType: TType,
+ fieldID: Int32,
+ typeOverride: UInt8) throws {
+
+ let typeToWrite = typeOverride == 0xFF ? compactType(fieldType).rawValue : typeOverride
+
+ // check if we can use delta encoding for the field id
+ let diff = UInt8(fieldID) - lastFieldId
+ if (UInt8(fieldID) > lastFieldId) && (diff <= 15) {
+ // Write them together
+ try writebyteDirect((UInt8(fieldID) - lastFieldId) << 4 | typeToWrite)
+
+ } else {
+ // Write them separate
+ try writebyteDirect(typeToWrite)
+ try write(Int16(fieldID))
+ }
+
+ lastFieldId = UInt8(fieldID)
+ }
+
+ public func writeFieldStop() throws {
+ try writebyteDirect(TCType.stop.rawValue)
+ }
+
+ public func writeFieldEnd() throws { }
+
+ public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+ if size == 0 {
+ try writebyteDirect(0)
+ } else {
+ try writeVarint32(UInt32(size))
+
+ let compactedTypes = compactType(keyType).rawValue << 4 | compactType(valueType).rawValue
+ try writebyteDirect(compactedTypes)
+ }
+ }
+
+ public func writeMapEnd() throws { }
+
+ public func writeSetBegin(elementType: TType, size: Int32) throws {
+ try writeCollectionBegin(elementType, size: size)
+ }
+
+ public func writeSetEnd() throws { }
+
+ public func writeListBegin(elementType: TType, size: Int32) throws {
+ try writeCollectionBegin(elementType, size: size)
+ }
+
+ public func writeListEnd() throws { }
+
+ public func write(_ value: String) throws {
+ try write(value.data(using: String.Encoding.utf8)!)
+ }
+
+ public func write(_ value: Bool) throws {
+ if let boolFieldId = boolFieldId, let boolFieldType = boolFieldType,
+ let boolFieldName = boolFieldName {
+
+ // we haven't written the field header yet
+ let compactType: TCType = value ? .boolean_TRUE : .boolean_FALSE
+ try writeFieldBeginInternal(name: boolFieldName, type: boolFieldType, fieldID: boolFieldId,
+ typeOverride: compactType.rawValue)
+ self.boolFieldId = nil
+ self.boolFieldType = nil
+ self.boolFieldName = nil
+ } else {
+ // we're not part of a field, so just write the value.
+ try writebyteDirect(value ? TCType.boolean_TRUE.rawValue : TCType.boolean_FALSE.rawValue)
+ }
+ }
+
+ public func write(_ value: UInt8) throws {
+ try writebyteDirect(value)
+ }
+
+ public func write(_ value: Int16) throws {
+ try writeVarint32(i32ToZigZag(Int32(value)))
+ }
+
+ public func write(_ value: Int32) throws {
+ try writeVarint32(i32ToZigZag(value))
+ }
+
+ public func write(_ value: Int64) throws {
+ try writeVarint64(i64ToZigZag(value))
+ }
+
+ public func write(_ value: Double) throws {
+ var bits = CFSwapInt64HostToLittle(value.bitPattern)
+ let data = withUnsafePointer(to: &bits) {
+ return Data(bytes: UnsafePointer<UInt8>(OpaquePointer($0)), count: MemoryLayout<UInt64>.size)
+ }
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+ try self.transport.write(data: data)
+ }
+ }
+
+ public func write(_ data: Data) throws {
+ try writeVarint32(UInt32(data.count))
+ try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+ try self.transport.write(data: data)
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TEnum.swift b/src/jaegertracing/thrift/lib/swift/Sources/TEnum.swift
new file mode 100644
index 000000000..fedfdb124
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TEnum.swift
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+
+public protocol TEnum : TSerializable, Hashable {
+ var rawValue: Int32 { get }
+}
+
+extension TEnum {
+ public static var thriftType: TType { return .i32 }
+ public var hashValue: Int { return rawValue.hashValue }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(rawValue)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TError.swift b/src/jaegertracing/thrift/lib/swift/Sources/TError.swift
new file mode 100644
index 000000000..79edba602
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TError.swift
@@ -0,0 +1,77 @@
+/*
+* 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.
+*/
+
+
+/// TErrorCode
+///
+/// Protocol for TError conformers' enum's to conform to.
+/// Generic Int Thrift error code to allow error cases to have
+/// associated values.
+public protocol TErrorCode : CustomStringConvertible {
+ var thriftErrorCode: Int { get }
+}
+
+/// TError
+///
+/// Base protocol for all Thrift Error(Exception) types to conform to
+public protocol TError : Error, CustomStringConvertible {
+
+ /// Enum for error cases. Can be typealiased to any conforming enum
+ /// or defined nested.
+ associatedtype Code: TErrorCode
+
+ /// Error Case, value from internal enum
+ var error: Code { get set }
+
+ /// Optional additional message
+ var message: String? { get set }
+
+ /// Default error case for the error type, used for generic init()
+ static var defaultCase: Code { get }
+
+ init()
+}
+
+extension TError {
+ /// Human readable description of error. Default provided for you in the
+ /// format \(Self.self): \(error.errorDescription) \n message
+ /// eg:
+ ///
+ /// TApplicationError (1): Invalid Message Type
+ /// An unknown Error has occured.
+ public var description: String {
+ var out = "\(Self.self) (\(error.thriftErrorCode)): " + error.description + "\n"
+ if let message = message {
+ out += "Message: \(message)"
+ }
+ return out
+ }
+
+ /// Simple default Initializer for TError's
+ ///
+ /// - parameter error: ErrorCode value. Default: defaultCase
+ /// - parameter message: Custom message with error. Optional
+ ///
+ /// - returns: <#return value description#>
+ public init(error: Code, message: String? = nil) {
+ self.init()
+ self.error = error
+ self.message = message
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TFileHandleTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TFileHandleTransport.swift
new file mode 100644
index 000000000..f315fefda
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TFileHandleTransport.swift
@@ -0,0 +1,56 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+public class TFileHandleTransport: TTransport {
+ var inputFileHandle: FileHandle
+ var outputFileHandle: FileHandle
+
+ public init(inputFileHandle: FileHandle, outputFileHandle: FileHandle) {
+ self.inputFileHandle = inputFileHandle
+ self.outputFileHandle = outputFileHandle
+ }
+
+ public convenience init(fileHandle: FileHandle) {
+ self.init(inputFileHandle: fileHandle, outputFileHandle: fileHandle)
+ }
+
+ public func read(size: Int) throws -> Data {
+ var data = Data()
+ while data.count < size {
+ let read = inputFileHandle.readData(ofLength: size - data.count)
+ data.append(read)
+ if read.count == 0 {
+ break
+ }
+ }
+ return data
+ }
+
+ public func write(data: Data) throws {
+ outputFileHandle.write(data)
+ }
+
+ public func flush() throws {
+ return
+ }
+}
+
+
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TFileTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TFileTransport.swift
new file mode 100644
index 000000000..fe2253da4
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TFileTransport.swift
@@ -0,0 +1,101 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+ import Darwin
+#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
+ import Glibc
+#endif
+
+/// TFileTransport
+/// Foundation-less Swift File transport.
+/// Uses C fopen/fread/fwrite,
+/// provided by Glibc in linux and Darwin on OSX/iOS
+public class TFileTransport: TTransport {
+ var fileHandle: UnsafeMutablePointer<FILE>? = nil
+
+ public init (fileHandle: UnsafeMutablePointer<FILE>) {
+ self.fileHandle = fileHandle
+ }
+
+ public convenience init(filename: String) throws {
+ var fileHandle: UnsafeMutablePointer<FILE>?
+ filename.withCString({ cFilename in
+ "rw".withCString({ cMode in
+ fileHandle = fopen(cFilename, cMode)
+ })
+ })
+ if let fileHandle = fileHandle {
+ self.init(fileHandle: fileHandle)
+ } else {
+ throw TTransportError(error: .notOpen)
+ }
+ }
+
+ deinit {
+ fclose(self.fileHandle)
+ }
+
+ public func readAll(size: Int) throws -> Data {
+ let read = try self.read(size: size)
+
+ if read.count != size {
+ throw TTransportError(error: .endOfFile)
+ }
+ return read
+ }
+
+ public func read(size: Int) throws -> Data {
+ // set up read buffer, position 0
+ var read = Data(capacity: size)
+ var position = 0
+
+ // read character buffer
+ var nextChar: UInt8 = 0
+
+ // continue until we've read size bytes
+ while read.count < size {
+ if fread(&nextChar, 1, 1, self.fileHandle) == 1 {
+ read[position] = nextChar
+
+ // Increment output byte pointer
+ position += 1
+
+ } else {
+ throw TTransportError(error: .endOfFile)
+ }
+ }
+ return read
+ }
+
+ public func write(data: Data) throws {
+ let bytesWritten = data.withUnsafeBytes {
+ fwrite($0, 1, data.count, self.fileHandle)
+ }
+ if bytesWritten != data.count {
+ throw TTransportError(error: .unknown)
+ }
+ }
+
+ public func flush() throws {
+ return
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TFramedTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TFramedTransport.swift
new file mode 100644
index 000000000..59855eb9c
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TFramedTransport.swift
@@ -0,0 +1,123 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+public class TFramedTransport: TTransport {
+ public static let headerSize = 4
+ public static let initFrameSize = 1024
+ private static let defaultMaxLength = 16384000
+
+ public var transport: TTransport
+ private var writeBuffer = Data()
+
+ private var maxSize = TFramedTransport.defaultMaxLength
+ private var remainingBytes = 0
+
+
+ public init(transport: TTransport, maxSize: Int) {
+ self.transport = transport
+ self.maxSize = maxSize
+ }
+
+ public convenience init(transport: TTransport) {
+ self.init(transport: transport, maxSize: TFramedTransport.defaultMaxLength)
+ }
+
+ func readHeader() throws {
+ let read = try transport.readAll(size: TFramedTransport.headerSize)
+ remainingBytes = Int(decodeFrameSize(data: read))
+ }
+
+ /// Mark: - TTransport
+
+ public func read(size: Int) throws -> Data {
+ while (remainingBytes <= 0) {
+ try readHeader()
+ }
+
+ let toRead = min(size, remainingBytes)
+
+ if toRead < 0 {
+ try close()
+ throw TTransportError(error: .negativeSize,
+ message: "Read a negative frame size (\(toRead))!")
+ }
+
+ if toRead > maxSize {
+ try close()
+ throw TTransportError(error: .sizeLimit(limit: maxSize, got: toRead))
+ }
+
+ return try transport.readAll(size: toRead)
+ }
+
+ public func flush() throws {
+ // copy buffer and reset
+ let buff = writeBuffer
+ writeBuffer = Data()
+
+ if buff.count - TFramedTransport.headerSize < 0 {
+ throw TTransportError(error: .unknown)
+ }
+
+ let frameSize = encodeFrameSize(size: UInt32(buff.count))
+
+ try transport.write(data: frameSize)
+ try transport.write(data: buff)
+ try transport.flush()
+ }
+
+ public func write(data: Data) throws {
+ writeBuffer.append(data)
+ }
+
+
+
+ private func encodeFrameSize(size: UInt32) -> Data {
+ var data = Data()
+ data.append(Data([UInt8(0xff & (size >> 24))]))
+ data.append(Data([UInt8(0xff & (size >> 16))]))
+ data.append(Data([UInt8(0xff & (size >> 8))]))
+ data.append(Data([UInt8(0xff & (size))]))
+
+ return data
+ }
+
+ private func decodeFrameSize(data: Data) -> UInt32 {
+ var size: UInt32
+ size = (UInt32(data[0] & 0xff) << 24)
+ size |= (UInt32(data[1] & 0xff) << 16)
+ size |= (UInt32(data[2] & 0xff) << 8)
+ size |= (UInt32(data[3] & 0xff))
+ return size
+ }
+
+ public func close() throws {
+ try transport.close()
+ }
+
+ public func open() throws {
+ try transport.open()
+ }
+
+ public func isOpen() throws -> Bool {
+ return try transport.isOpen()
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/THTTPSessionTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/THTTPSessionTransport.swift
new file mode 100644
index 000000000..3c0af8eb8
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/THTTPSessionTransport.swift
@@ -0,0 +1,184 @@
+/*
+* 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.
+*/
+
+import Foundation
+import Dispatch
+
+
+public class THTTPSessionTransport: TAsyncTransport {
+ public class Factory : TAsyncTransportFactory {
+ public var responseValidate: ((HTTPURLResponse?, Data?) throws -> Void)?
+
+ var session: URLSession
+ var url: URL
+
+ public class func setupDefaultsForSessionConfiguration(_ config: URLSessionConfiguration, withProtocolName protocolName: String?) {
+ var thriftContentType = "application/x-thrift"
+
+ if let protocolName = protocolName {
+ thriftContentType += "; p=\(protocolName)"
+ }
+
+ config.requestCachePolicy = .reloadIgnoringLocalCacheData
+ config.urlCache = nil
+
+ config.httpShouldUsePipelining = true
+ config.httpShouldSetCookies = true
+ config.httpAdditionalHeaders = ["Content-Type": thriftContentType,
+ "Accept": thriftContentType,
+ "User-Agent": "Thrift/Swift (Session)"]
+
+
+ }
+
+ public init(session: URLSession, url: URL) {
+ self.session = session
+ self.url = url
+ }
+
+ public func newTransport() -> THTTPSessionTransport {
+ return THTTPSessionTransport(factory: self)
+ }
+
+ func validateResponse(_ response: HTTPURLResponse?, data: Data?) throws {
+ try responseValidate?(response, data)
+ }
+
+ func taskWithRequest(_ request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) throws -> URLSessionTask {
+
+ let newTask: URLSessionTask? = session.dataTask(with: request, completionHandler: completionHandler)
+ if let newTask = newTask {
+ return newTask
+ } else {
+ throw TTransportError(error: .unknown, message: "Failed to create session data task")
+ }
+ }
+ }
+
+ var factory: Factory
+ var requestData = Data()
+ var responseData = Data()
+ var responseDataOffset: Int = 0
+
+ init(factory: Factory) {
+ self.factory = factory
+ }
+
+ public func readAll(size: Int) throws -> Data {
+ let read = try self.read(size: size)
+ if read.count != size {
+ throw TTransportError(error: .endOfFile)
+ }
+ return read
+ }
+
+ public func read(size: Int) throws -> Data {
+ let avail = responseData.count - responseDataOffset
+ let (start, stop) = (responseDataOffset, responseDataOffset + min(size, avail))
+ let read = responseData.subdata(in: start..<stop)
+ responseDataOffset += read.count
+ return read
+ }
+
+ public func write(data: Data) throws {
+ requestData.append(data)
+ }
+
+ public func flush(_ completed: @escaping (TAsyncTransport, Error?) -> Void) {
+ var error: Error?
+ var task: URLSessionTask?
+
+ var request = URLRequest(url: factory.url)
+ request.httpMethod = "POST"
+ request.httpBody = requestData
+
+ requestData = Data()
+
+ do {
+ task = try factory.taskWithRequest(request, completionHandler: { (data, response, taskError) in
+
+ // Check if there was an error with the network
+ if taskError != nil {
+ error = TTransportError(error: .timedOut)
+ completed(self, error)
+ return
+ }
+
+ // Check response type
+ if taskError == nil && !(response is HTTPURLResponse) {
+ error = THTTPTransportError(error: .invalidResponse)
+ completed(self, error)
+ return
+ }
+
+ // Check status code
+ if let httpResponse = response as? HTTPURLResponse {
+ if taskError == nil && httpResponse.statusCode != 200 {
+ if httpResponse.statusCode == 401 {
+ error = THTTPTransportError(error: .authentication)
+ } else {
+ error = THTTPTransportError(error: .invalidStatus(statusCode: httpResponse.statusCode))
+ }
+ }
+
+ // Allow factory to check
+ if error != nil {
+ do {
+ try self.factory.validateResponse(httpResponse, data: data)
+ } catch let validateError {
+ error = validateError
+ }
+ }
+
+ self.responseDataOffset = 0
+ if error != nil {
+ self.responseData = Data()
+ } else {
+ self.responseData = data ?? Data()
+ }
+ completed(self, error)
+ }
+ })
+
+ } catch let taskError {
+ error = taskError
+ }
+
+ if let error = error, task == nil {
+ completed(self, error)
+ }
+ task?.resume()
+ }
+
+ public func flush() throws {
+ let completed = DispatchSemaphore(value: 0)
+ var internalError: Error?
+
+ flush() { _, error in
+ internalError = error
+ completed.signal()
+ }
+
+ _ = completed.wait(timeout: DispatchTime.distantFuture)
+
+ if let error = internalError {
+ throw error
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TList.swift b/src/jaegertracing/thrift/lib/swift/Sources/TList.swift
new file mode 100644
index 000000000..c239d10c5
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TList.swift
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+public struct TList<Element : TSerializable> : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable {
+ public typealias Storage = Array<Element>
+ public typealias Indices = Storage.Indices
+
+ internal var storage = Storage()
+ public init() { }
+ public init(arrayLiteral elements: Element...) {
+ self.storage = Storage(elements)
+ }
+ public init<Source : Sequence>(_ sequence: Source) where Source.Iterator.Element == Element {
+ storage = Storage(sequence)
+ }
+
+ /// Mark: Hashable
+ public var hashValue : Int {
+ let prime = 31
+ var result = 1
+ for element in storage {
+ result = prime &* result &+ element.hashValue
+ }
+ return result
+ }
+
+ /// Mark: TSerializable
+ public static var thriftType : TType { return .list }
+
+ public static func read(from proto: TProtocol) throws -> TList {
+ let (elementType, size) = try proto.readListBegin()
+ if elementType != Element.thriftType {
+ throw TProtocolError(error: .invalidData,
+ extendedError: .unexpectedType(type: elementType))
+ }
+ var list = TList()
+ for _ in 0..<size {
+ let element = try Element.read(from: proto)
+ list.storage.append(element)
+ }
+ try proto.readListEnd()
+ return list
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.writeListBegin(elementType: Element.thriftType, size: Int32(self.count))
+ for element in self.storage {
+ try Element.write(element, to: proto)
+ }
+ try proto.writeListEnd()
+ }
+
+ /// Mark: MutableCollection
+
+ public typealias SubSequence = Storage.SubSequence
+ public typealias Index = Storage.Index
+
+ public subscript(position: Storage.Index) -> Element {
+ get {
+ return storage[position]
+ }
+ set {
+ storage[position] = newValue
+ }
+ }
+
+ public subscript(range: Range<Index>) -> SubSequence {
+ get {
+ return storage[range]
+ }
+ set {
+ storage[range] = newValue
+ }
+ }
+
+ public var startIndex: Index {
+ return storage.startIndex
+ }
+ public var endIndex: Index {
+ return storage.endIndex
+ }
+
+ public func formIndex(after i: inout Index) {
+ storage.formIndex(after: &i)
+ }
+
+ public func formIndex(before i: inout Int) {
+ storage.formIndex(before: &i)
+ }
+
+ public func index(after i: Index) -> Index {
+ return storage.index(after: i)
+ }
+
+ public func index(before i: Int) -> Int {
+ return storage.index(before: i)
+ }
+
+}
+
+extension TList : RangeReplaceableCollection {
+ public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C)
+ where C.Iterator.Element == Element {
+ storage.replaceSubrange(subrange, with: newElements)
+ }
+}
+
+extension TList : CustomStringConvertible, CustomDebugStringConvertible {
+
+ public var description : String {
+ return storage.description
+ }
+
+ public var debugDescription : String {
+ return storage.debugDescription
+ }
+
+}
+
+public func ==<Element>(lhs: TList<Element>, rhs: TList<Element>) -> Bool {
+ return lhs.storage.elementsEqual(rhs.storage) { $0 == $1 }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TMap.swift b/src/jaegertracing/thrift/lib/swift/Sources/TMap.swift
new file mode 100644
index 000000000..dcf1481c6
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TMap.swift
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+public struct TMap<Key : TSerializable & Hashable, Value : TSerializable>: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable {
+ public typealias Storage = Dictionary<Key, Value>
+ public typealias Element = Storage.Element
+ public typealias Index = Storage.Index
+ public typealias IndexDistance = Int
+ public typealias Indices = Storage.Indices
+ public typealias SubSequence = Storage.SubSequence
+ internal var storage = Storage()
+
+ /// Mark: Be Like Dictionary
+
+ public func indexForKey(_ key: Key) -> Index? {
+ return storage.index(forKey: key)
+ }
+
+ public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
+ return storage.updateValue(value, forKey: key)
+ }
+
+ public mutating func removeValueForKey(_ key: Key) -> Value? {
+ return storage.removeValue(forKey: key)
+ }
+
+ public init(minimumCapacity: Int) {
+ storage = Storage(minimumCapacity: minimumCapacity)
+ }
+
+ /// init from Dictionary<K,V>
+ public init(_ dict: [Key: Value]) {
+ storage = dict
+ }
+
+ /// read only access to storage if needed as Dictionary<K,V>
+ public var dictionary: [Key: Value] {
+ return storage
+ }
+
+ public subscript (key: Key) -> Value? {
+ get {
+ return storage[key]
+ }
+ set {
+ storage[key] = newValue
+ }
+ }
+
+ /// Mark: Collection
+
+ public var indices: Indices {
+ return storage.indices
+ }
+
+ public func distance(from start: Index, to end: Index) -> IndexDistance {
+ return storage.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+ return storage.index(i, offsetBy: n)
+ }
+
+ public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
+ return storage.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public subscript(position: Index) -> Element {
+ return storage[position]
+ }
+
+ /// Mark: IndexableBase
+
+ public var startIndex: Index { return storage.startIndex }
+ public var endIndex: Index { return storage.endIndex }
+ public func index(after i: Index) -> Index {
+ return storage.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ storage.formIndex(after: &i)
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ return storage[bounds]
+ }
+
+ /// Mark: DictionaryLiteralConvertible
+
+ public init(dictionaryLiteral elements: (Key, Value)...) {
+ storage = Storage()
+ for (key, value) in elements {
+ storage[key] = value
+ }
+ }
+
+ /// Mark: Hashable
+
+ public var hashValue: Int {
+ let prime = 31
+ var result = 1
+ for (key, value) in storage {
+ result = prime &* result &+ key.hashValue
+ result = prime &* result &+ value.hashValue
+ }
+ return result
+ }
+
+ /// Mark: TSerializable
+
+ public static var thriftType : TType { return .map }
+ public init() {
+ storage = Storage()
+ }
+
+ public static func read(from proto: TProtocol) throws -> TMap {
+
+ let (keyType, valueType, size) = try proto.readMapBegin()
+ if size > 0 {
+ if keyType != Key.thriftType {
+ throw TProtocolError(error: .invalidData,
+ message: "Unexpected TMap Key Type",
+ extendedError: .unexpectedType(type: keyType))
+ }
+ if valueType != Value.thriftType {
+ throw TProtocolError(error: .invalidData,
+ message: "Unexpected TMap Value Type",
+ extendedError: .unexpectedType(type: valueType))
+ }
+ }
+
+ var map = TMap()
+ for _ in 0..<size {
+ let key = try Key.read(from: proto)
+ let value = try Value.read(from: proto)
+ map.storage[key] = value
+ }
+ try proto.readMapEnd()
+ return map
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.writeMapBegin(keyType: Key.thriftType,
+ valueType: Value.thriftType, size: Int32(self.count))
+ for (key, value) in self.storage {
+ try Key.write(key, to: proto)
+ try Value.write(value, to: proto)
+ }
+ try proto.writeMapEnd()
+ }
+}
+
+/// Mark: CustomStringConvertible, CustomDebugStringConvertible
+
+extension TMap : CustomStringConvertible, CustomDebugStringConvertible {
+
+ public var description : String {
+ return storage.description
+ }
+
+ public var debugDescription : String {
+ return storage.debugDescription
+ }
+
+}
+
+/// Mark: Equatable
+
+public func ==<Key, Value>(lhs: TMap<Key,Value>, rhs: TMap<Key, Value>) -> Bool {
+ if lhs.count != rhs.count {
+ return false
+ }
+ return lhs.storage.elementsEqual(rhs.storage) { $0.key == $1.key && $0.value == $1.value }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TMemoryBufferTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TMemoryBufferTransport.swift
new file mode 100644
index 000000000..bd58b6ef7
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TMemoryBufferTransport.swift
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+import Foundation
+
+public class TMemoryBufferTransport : TTransport {
+ public private(set) var readBuffer = Data()
+ public private(set) var writeBuffer = Data()
+
+ public private(set) var position = 0
+
+ public var bytesRemainingInBuffer: Int {
+ return readBuffer.count - position
+ }
+
+ public func consumeBuffer(size: Int) {
+ position += size
+ }
+ public func clear() {
+ readBuffer = Data()
+ writeBuffer = Data()
+ }
+
+
+ private var flushHandler: ((TMemoryBufferTransport, Data) -> ())?
+
+ public init(flushHandler: ((TMemoryBufferTransport, Data) -> ())? = nil) {
+ self.flushHandler = flushHandler
+ }
+
+ public convenience init(readBuffer: Data, flushHandler: ((TMemoryBufferTransport, Data) -> ())? = nil) {
+ self.init()
+ self.readBuffer = readBuffer
+ }
+
+ public func reset(readBuffer: Data = Data(), writeBuffer: Data = Data()) {
+ self.readBuffer = readBuffer
+ self.writeBuffer = writeBuffer
+ }
+
+ public func read(size: Int) throws -> Data {
+ let amountToRead = min(bytesRemainingInBuffer, size)
+ if amountToRead > 0 {
+ let ret = readBuffer.subdata(in: Range(uncheckedBounds: (lower: position, upper: position + amountToRead)))
+ position += ret.count
+ return ret
+ }
+ return Data()
+ }
+
+ public func write(data: Data) throws {
+ writeBuffer.append(data)
+ }
+
+ public func flush() throws {
+ flushHandler?(self, writeBuffer)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TMultiplexedProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TMultiplexedProtocol.swift
new file mode 100644
index 000000000..73a8d51ab
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TMultiplexedProtocol.swift
@@ -0,0 +1,47 @@
+/*
+* 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.
+*/
+
+public class TMultiplexedProtocol<Protocol: TProtocol>: TWrappedProtocol<Protocol> {
+ public let separator = ":"
+
+ public var serviceName = ""
+
+ public convenience init(on transport: TTransport, serviceName: String) {
+ self.init(on: transport)
+ self.serviceName = serviceName
+ }
+
+ override public func writeMessageBegin(name: String,
+ type messageType: TMessageType,
+ sequenceID: Int32) throws {
+ switch messageType {
+ case .call, .oneway:
+ var serviceFunction = serviceName
+ serviceFunction += serviceName == "" ? "" : separator
+ serviceFunction += name
+ return try super.writeMessageBegin(name: serviceFunction,
+ type: messageType,
+ sequenceID: sequenceID)
+ default:
+ return try super.writeMessageBegin(name: name,
+ type: messageType,
+ sequenceID: sequenceID)
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TProcessor.swift b/src/jaegertracing/thrift/lib/swift/Sources/TProcessor.swift
new file mode 100644
index 000000000..7ff222e41
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TProcessor.swift
@@ -0,0 +1,29 @@
+/*
+* 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.
+*/
+
+
+public typealias TProcessorMessageHandler<T> = (Int, TProtocol, TProtocol, T) -> Void
+
+public protocol TProcessor {
+ associatedtype Service
+ var service: Service { get set }
+ func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws
+ init(service: Service)
+}
+
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TProtocol.swift
new file mode 100644
index 000000000..b4e5dbe73
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TProtocol.swift
@@ -0,0 +1,182 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+public enum TMessageType: Int32 {
+ case call = 1
+ case reply = 2
+ case exception = 3
+ case oneway = 4
+}
+
+public enum TType: Int32 {
+ case stop = 0
+ case void = 1
+ case bool = 2
+ case i8 = 3
+ case double = 4
+ case i16 = 6
+ case i32 = 8
+ case i64 = 10
+ case string = 11
+ case `struct` = 12
+ case map = 13
+ case set = 14
+ case list = 15
+ case utf8 = 16
+ case utf16 = 17
+}
+
+public protocol TProtocol {
+ var transport: TTransport { get set }
+ init(on transport: TTransport)
+ // Reading Methods
+
+ func readMessageBegin() throws -> (String, TMessageType, Int32)
+ func readMessageEnd() throws
+ func readStructBegin() throws -> String
+ func readStructEnd() throws
+ func readFieldBegin() throws -> (String, TType, Int32)
+ func readFieldEnd() throws
+ func readMapBegin() throws -> (TType, TType, Int32)
+ func readMapEnd() throws
+ func readSetBegin() throws -> (TType, Int32)
+ func readSetEnd() throws
+ func readListBegin() throws -> (TType, Int32)
+ func readListEnd() throws
+
+ func read() throws -> String
+ func read() throws -> Bool
+ func read() throws -> UInt8
+ func read() throws -> Int16
+ func read() throws -> Int32
+ func read() throws -> Int64
+ func read() throws -> Double
+ func read() throws -> Data
+
+ // Writing methods
+
+ func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws
+ func writeMessageEnd() throws
+ func writeStructBegin(name: String) throws
+ func writeStructEnd() throws
+ func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws
+ func writeFieldStop() throws
+ func writeFieldEnd() throws
+ func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws
+ func writeMapEnd() throws
+ func writeSetBegin(elementType: TType, size: Int32) throws
+ func writeSetEnd() throws
+ func writeListBegin(elementType: TType, size: Int32) throws
+ func writeListEnd() throws
+
+ func write(_ value: String) throws
+ func write(_ value: Bool) throws
+ func write(_ value: UInt8) throws
+ func write(_ value: Int16) throws
+ func write(_ value: Int32) throws
+ func write(_ value: Int64) throws
+ func write(_ value: Double) throws
+ func write(_ value: Data) throws
+}
+
+public extension TProtocol {
+ func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
+ try writeFieldBegin(name: name, type: type, fieldID: id)
+ try value.write(to: self)
+ try writeFieldEnd()
+ }
+
+ func validateValue(_ value: Any?, named name: String) throws {
+ if value == nil {
+ throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)")
+ }
+ }
+
+ func readResultMessageBegin() throws {
+ let (_, type, _) = try readMessageBegin();
+ if type == .exception {
+ let x = try readException()
+ throw x
+ }
+ return
+ }
+
+ func readException() throws -> TApplicationError {
+ return try TApplicationError.read(from: self)
+ }
+
+ func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
+ try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID)
+ try ex.write(to: self)
+ try writeMessageEnd()
+ }
+
+ func skip(type: TType) throws {
+ switch type {
+ case .bool: _ = try read() as Bool
+ case .i8: _ = try read() as UInt8
+ case .i16: _ = try read() as Int16
+ case .i32: _ = try read() as Int32
+ case .i64: _ = try read() as Int64
+ case .double: _ = try read() as Double
+ case .string: _ = try read() as String
+
+ case .struct:
+ _ = try readStructBegin()
+ while true {
+ let (_, fieldType, _) = try readFieldBegin()
+ if fieldType == .stop {
+ break
+ }
+ try skip(type: fieldType)
+ try readFieldEnd()
+ }
+ try readStructEnd()
+
+
+ case .map:
+ let (keyType, valueType, size) = try readMapBegin()
+ for _ in 0..<size {
+ try skip(type: keyType)
+ try skip(type: valueType)
+ }
+ try readMapEnd()
+
+
+ case .set:
+ let (elemType, size) = try readSetBegin()
+ for _ in 0..<size {
+ try skip(type: elemType)
+ }
+ try readSetEnd()
+
+ case .list:
+ let (elemType, size) = try readListBegin()
+ for _ in 0..<size {
+ try skip(type: elemType)
+ }
+ try readListEnd()
+
+ default:
+ throw TProtocolError(error: .invalidData, message: "Invalid data")
+ }
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TProtocolError.swift b/src/jaegertracing/thrift/lib/swift/Sources/TProtocolError.swift
new file mode 100644
index 000000000..a5d14f9ea
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TProtocolError.swift
@@ -0,0 +1,146 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+public struct TProtocolError : TError {
+ public init() { }
+
+ public enum Code : TErrorCode {
+ case unknown
+ case invalidData
+ case negativeSize
+ case sizeLimit(limit: Int, got: Int)
+ case badVersion(expected: String, got: String)
+ case notImplemented
+ case depthLimit
+
+ public var thriftErrorCode: Int {
+ switch self {
+ case .unknown: return 0
+ case .invalidData: return 1
+ case .negativeSize: return 2
+ case .sizeLimit: return 3
+ case .badVersion: return 4
+ case .notImplemented: return 5
+ case .depthLimit: return 6
+ }
+
+ }
+ public var description: String {
+ switch self {
+ case .unknown: return "Unknown TProtocolError"
+ case .invalidData: return "Invalid Data"
+ case .negativeSize: return "Negative Size"
+ case .sizeLimit(let limit, let got):
+ return "Message exceeds size limit of \(limit) (received: \(got)"
+ case .badVersion(let expected, let got):
+ return "Bad Version. (Expected: \(expected), Got: \(got)"
+ case .notImplemented: return "Not Implemented"
+ case .depthLimit: return "Depth Limit"
+ }
+ }
+ }
+
+ public enum ExtendedErrorCode : TErrorCode {
+ case unknown
+ case missingRequiredField(fieldName: String)
+ case unexpectedType(type: TType)
+ case mismatchedProtocol(expected: String, got: String)
+ public var thriftErrorCode: Int {
+ switch self {
+ case .unknown: return 1000
+ case .missingRequiredField: return 1001
+ case .unexpectedType: return 1002
+ case .mismatchedProtocol: return 1003
+ }
+ }
+ public var description: String {
+ switch self {
+ case .unknown: return "Unknown TProtocolExtendedError"
+ case .missingRequiredField(let fieldName): return "Missing Required Field: \(fieldName)"
+ case .unexpectedType(let type): return "Unexpected Type \(type.self)"
+ case .mismatchedProtocol(let expected, let got): return "Mismatched Protocol. (Expected: \(expected), got \(got))"
+ }
+ }
+ }
+
+ public var extendedError: ExtendedErrorCode? = nil
+
+ public init(error: Code = .unknown,
+ message: String? = nil,
+ extendedError: ExtendedErrorCode? = nil) {
+ self.error = error
+ self.message = message
+ self.extendedError = extendedError
+ }
+
+ /// Mark: TError
+ public var error: Code = .unknown
+ public var message: String? = nil
+ public static var defaultCase: Code { return .unknown }
+
+ public var description: String {
+ var out = "\(TProtocolError.self): (\(error.thriftErrorCode) \(error.description)\n"
+ if let extendedError = extendedError {
+ out += "TProtocolExtendedError (\(extendedError.thriftErrorCode)): \(extendedError.description)"
+ }
+ if let message = message {
+ out += "Message: \(message)"
+ }
+ return out
+ }
+}
+
+
+/// Wrapper for Transport errors in Protocols. Inspired by Thrift-Cocoa PROTOCOL_TRANSPORT_ERROR
+/// macro. Modified to be more Swift-y. Catches any TError thrown within the block and
+/// rethrows a given TProtocolError, the original error's description is appended to the new
+/// TProtocolError's message. sourceFile, sourceLine, sourceMethod are auto-populated and should
+/// be ignored when calling.
+///
+/// - parameter error: TProtocolError to throw if the block throws
+/// - parameter sourceFile: throwing file, autopopulated
+/// - parameter sourceLine: throwing line, autopopulated
+/// - parameter sourceMethod: throwing method, autopopulated
+/// - parameter block: throwing block
+///
+/// - throws: TProtocolError Default is TProtocolError.ErrorCode.unknown. Underlying
+/// error's description appended to TProtocolError.message
+func ProtocolTransportTry(error: TProtocolError = TProtocolError(),
+ sourceFile: String = #file,
+ sourceLine: Int = #line,
+ sourceMethod: String = #function,
+ block: () throws -> ()) throws {
+ // Need mutable copy
+ var error = error
+ do {
+ try block()
+ } catch let err as TError {
+ var message = error.message ?? ""
+ message += "\nFile: \(sourceFile)\n"
+ message += "Line: \(sourceLine)\n"
+ message += "Method: \(sourceMethod)"
+ message += "\nOriginal Error:\n" + err.description
+ error.message = message
+ throw error
+ }
+}
+
+
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransport.swift
new file mode 100644
index 000000000..d350f821e
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransport.swift
@@ -0,0 +1,236 @@
+/*
+* 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.
+*/
+
+import Foundation
+import CoreFoundation
+
+#if !swift(>=4.2)
+// Swift 3/4 compatibility
+fileprivate extension RunLoopMode {
+ static let `default` = defaultRunLoopMode
+}
+#endif
+
+#if os(Linux)
+public class TSSLSocketTransport {
+ init(hostname: String, port: UInt16) {
+ // FIXME!
+ assert(false, "Security not available in Linux, TSSLSocketTransport Unavilable for now")
+ }
+}
+#else
+let isLittleEndian = Int(OSHostByteOrder()) == OSLittleEndian
+let htons = isLittleEndian ? _OSSwapInt16 : { $0 }
+let htonl = isLittleEndian ? _OSSwapInt32 : { $0 }
+
+public class TSSLSocketTransport: TStreamTransport {
+ var sslHostname: String
+ var sd: Int32 = 0
+
+ public init(hostname: String, port: UInt16) throws {
+ sslHostname = hostname
+ var readStream: Unmanaged<CFReadStream>?
+ var writeStream: Unmanaged<CFWriteStream>?
+
+ /* create a socket structure */
+ var pin: sockaddr_in = sockaddr_in()
+ var hp: UnsafeMutablePointer<hostent>? = nil
+ for i in 0..<10 {
+
+ hp = gethostbyname(hostname.cString(using: String.Encoding.utf8)!)
+ if hp == nil {
+ print("failed to resolve hostname \(hostname)")
+ herror("resolv")
+ if i == 9 {
+ super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+ throw TSSLSocketTransportError(error: .hostanameResolution(hostname: hostname))
+ }
+ Thread.sleep(forTimeInterval: 0.2)
+ } else {
+ break
+ }
+ }
+ pin.sin_family = UInt8(AF_INET)
+ pin.sin_addr = in_addr(s_addr: UInt32((hp?.pointee.h_addr_list.pointee?.pointee)!)) // Is there a better way to get this???
+ pin.sin_port = htons(port)
+
+ /* create the socket */
+ sd = socket(Int32(AF_INET), Int32(SOCK_STREAM), Int32(IPPROTO_TCP))
+ if sd == -1 {
+ super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+ throw TSSLSocketTransportError(error: .socketCreate(port: Int(port)))
+ }
+
+ /* open a connection */
+ // need a non-self ref to sd, otherwise the j complains
+ let sd_local = sd
+ let connectResult = withUnsafePointer(to: &pin) {
+ connect(sd_local, UnsafePointer<sockaddr>(OpaquePointer($0)), socklen_t(MemoryLayout<sockaddr_in>.size))
+ }
+ if connectResult == -1 {
+ super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+ throw TSSLSocketTransportError(error: .connect)
+ }
+
+ CFStreamCreatePairWithSocket(kCFAllocatorDefault, sd, &readStream, &writeStream)
+
+ CFReadStreamSetProperty(readStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
+ CFWriteStreamSetProperty(writeStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
+
+ var inputStream: InputStream? = nil
+ var outputStream: OutputStream? = nil
+ if readStream != nil && writeStream != nil {
+
+ CFReadStreamSetProperty(readStream?.takeRetainedValue(),
+ .socketSecurityLevel,
+ kCFStreamSocketSecurityLevelTLSv1)
+
+ let settings: [String: Bool] = [kCFStreamSSLValidatesCertificateChain as String: true]
+
+ CFReadStreamSetProperty(readStream?.takeRetainedValue(),
+ .SSLSettings,
+ settings as CFTypeRef)
+
+ CFWriteStreamSetProperty(writeStream?.takeRetainedValue(),
+ .SSLSettings,
+ settings as CFTypeRef)
+
+ inputStream = readStream!.takeRetainedValue()
+ inputStream?.schedule(in: .current, forMode: .default)
+ inputStream?.open()
+
+ outputStream = writeStream!.takeRetainedValue()
+ outputStream?.schedule(in: .current, forMode: .default)
+ outputStream?.open()
+
+ readStream?.release()
+ writeStream?.release()
+ }
+
+
+ super.init(inputStream: inputStream, outputStream: outputStream)
+ self.input?.delegate = self
+ self.output?.delegate = self
+ }
+
+ func recoverFromTrustFailure(_ myTrust: SecTrust, lastTrustResult: SecTrustResultType) -> Bool {
+ let trustTime = SecTrustGetVerifyTime(myTrust)
+ let currentTime = CFAbsoluteTimeGetCurrent()
+
+ let timeIncrement = 31536000 // from TSSLSocketTransport.m
+ let newTime = currentTime - Double(timeIncrement)
+
+ if trustTime - newTime != 0 {
+ let newDate = CFDateCreate(nil, newTime)
+ SecTrustSetVerifyDate(myTrust, newDate!)
+
+ var tr = lastTrustResult
+ let success = withUnsafeMutablePointer(to: &tr) { trPtr -> Bool in
+ if SecTrustEvaluate(myTrust, trPtr) != errSecSuccess {
+ return false
+ }
+ return true
+ }
+ if !success { return false }
+ }
+ if lastTrustResult == .proceed || lastTrustResult == .unspecified {
+ return false
+ }
+
+ print("TSSLSocketTransport: Unable to recover certificate trust failure")
+ return true
+ }
+
+ public func isOpen() -> Bool {
+ return sd > 0
+ }
+}
+
+extension TSSLSocketTransport: StreamDelegate {
+ public func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
+
+ switch eventCode {
+ case Stream.Event(): break
+ case Stream.Event.hasBytesAvailable: break
+ case Stream.Event.openCompleted: break
+ case Stream.Event.hasSpaceAvailable:
+ var proceed = false
+ var trustResult: SecTrustResultType = .invalid
+
+ var newPolicies: CFMutableArray?
+
+ repeat {
+ let trust: SecTrust = aStream.property(forKey: .SSLPeerTrust) as! SecTrust
+
+ // Add new policy to current list of policies
+ let policy = SecPolicyCreateSSL(false, sslHostname as CFString?)
+ var ppolicy = policy // mutable for pointer
+ let policies: UnsafeMutablePointer<CFArray?>? = nil
+ if SecTrustCopyPolicies(trust, policies!) != errSecSuccess {
+ break
+ }
+ withUnsafeMutablePointer(to: &ppolicy) { ptr in
+ newPolicies = CFArrayCreateMutableCopy(nil, 0, policies?.pointee)
+ CFArrayAppendValue(newPolicies, ptr)
+ }
+
+ // update trust policies
+ if SecTrustSetPolicies(trust, newPolicies!) != errSecSuccess {
+ break
+ }
+
+ // Evaluate the trust chain
+ let success = withUnsafeMutablePointer(to: &trustResult) { trustPtr -> Bool in
+ if SecTrustEvaluate(trust, trustPtr) != errSecSuccess {
+ return false
+ }
+ return true
+ }
+
+ if !success {
+ break
+ }
+
+
+ switch trustResult {
+ case .proceed: proceed = true
+ case .unspecified: proceed = true
+ case .recoverableTrustFailure:
+ proceed = self.recoverFromTrustFailure(trust, lastTrustResult: trustResult)
+
+ case .deny: break
+ case .fatalTrustFailure: break
+ case .otherError: break
+ case .invalid: break
+ default: break
+ }
+ } while false
+
+ if !proceed {
+ print("TSSLSocketTransport: Cannot trust certificate. Result: \(trustResult)")
+ aStream.close()
+ }
+
+ case Stream.Event.errorOccurred: break
+ case Stream.Event.endEncountered: break
+ default: break
+ }
+ }
+}
+#endif
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransportError.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransportError.swift
new file mode 100644
index 000000000..fda162bd5
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TSSLSocketTransportError.swift
@@ -0,0 +1,48 @@
+/*
+* 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.
+*/
+
+public struct TSSLSocketTransportError: TError {
+ public enum ErrorCode: TErrorCode {
+ case hostanameResolution(hostname: String)
+ case socketCreate(port: Int)
+ case connect
+
+ public var thriftErrorCode: Int {
+ switch self {
+ case .hostanameResolution: return -10000
+ case .socketCreate: return -10001
+ case .connect: return -10002
+ }
+ }
+
+ public var description: String {
+ switch self {
+ case .hostanameResolution(let hostname): return "Failed to resolve hostname: \(hostname)"
+ case .socketCreate(let port): return "Could not create socket on port: \(port)"
+ case .connect: return "Connect error"
+ }
+ }
+
+ }
+ public var error: ErrorCode = .connect
+ public var message: String?
+ public static var defaultCase: ErrorCode { return .connect }
+
+ public init() { }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSerializable.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSerializable.swift
new file mode 100644
index 000000000..b45096b69
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TSerializable.swift
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+import Foundation
+
+
+public protocol TSerializable {
+ var hashValue: Int { get }
+
+ /// TType for instance
+ static var thriftType: TType { get }
+
+ /// Read TSerializable instance from Protocol
+ static func read(from proto: TProtocol) throws -> Self
+
+ /// Write TSerializable instance to Protocol
+ func write(to proto: TProtocol) throws
+
+}
+
+extension TSerializable {
+ public static func write(_ value: Self, to proto: TProtocol) throws {
+ try value.write(to: proto)
+ }
+
+ /// convenience for member access
+ public var thriftType: TType { return Self.thriftType }
+}
+
+public func ==<T>(lhs: T, rhs: T) -> Bool where T : TSerializable {
+ return lhs.hashValue == rhs.hashValue
+}
+
+/// Default read/write for primitave Thrift types:
+/// Bool, Int8 (byte), Int16, Int32, Int64, Double, String
+
+extension Bool : TSerializable {
+ public static var thriftType: TType { return .bool }
+
+ public static func read(from proto: TProtocol) throws -> Bool {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
+
+extension Int8 : TSerializable {
+ public static var thriftType: TType { return .i8 }
+
+ public static func read(from proto: TProtocol) throws -> Int8 {
+ return Int8(try proto.read() as UInt8)
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(UInt8(self))
+ }
+}
+
+extension Int16 : TSerializable {
+ public static var thriftType: TType { return .i16 }
+
+ public static func read(from proto: TProtocol) throws -> Int16 {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
+
+extension Int32 : TSerializable {
+ public static var thriftType: TType { return .i32 }
+
+ public static func read(from proto: TProtocol) throws -> Int32 {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
+
+
+extension Int64 : TSerializable {
+ public static var thriftType: TType { return .i64 }
+
+ public static func read(from proto: TProtocol) throws -> Int64 {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
+
+extension Double : TSerializable {
+ public static var thriftType: TType { return .double }
+
+ public static func read(from proto: TProtocol) throws -> Double {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
+
+extension String : TSerializable {
+ public static var thriftType: TType { return .string }
+
+ public static func read(from proto: TProtocol) throws -> String {
+ return try proto.read()
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.write(self)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSet.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSet.swift
new file mode 100644
index 000000000..6891c11e6
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TSet.swift
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+import Foundation
+
+public struct TSet<Element : TSerializable & Hashable> : SetAlgebra, Hashable, Collection, ExpressibleByArrayLiteral, TSerializable {
+ /// Typealias for Storage type
+ public typealias Storage = Set<Element>
+
+
+ /// Internal Storage used for TSet (Set\<Element\>)
+ internal var storage : Storage
+
+
+ /// Mark: Collection
+
+ public typealias Indices = Storage.Indices
+ public typealias Index = Storage.Index
+ public typealias IndexDistance = Int
+ public typealias SubSequence = Storage.SubSequence
+
+
+ public var indices: Indices { return storage.indices }
+
+ // Must implement isEmpty even though both SetAlgebra and Collection provide it due to their conflciting default implementations
+ public var isEmpty: Bool { return storage.isEmpty }
+
+ public func distance(from start: Index, to end: Index) -> IndexDistance {
+ return storage.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+ return storage.index(i, offsetBy: n)
+ }
+
+ public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
+ return storage.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ #if swift(>=3.2)
+ public subscript (position: Storage.Index) -> Element {
+ return storage[position]
+ }
+ #else
+ public subscript (position: Storage.Index) -> Element? {
+ return storage[position]
+ }
+ #endif
+
+ /// Mark: SetAlgebra
+ internal init(storage: Set<Element>) {
+ self.storage = storage
+ }
+
+ public func contains(_ member: Element) -> Bool {
+ return storage.contains(member)
+ }
+
+ public mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) {
+ return storage.insert(newMember)
+ }
+
+ public mutating func remove(_ member: Element) -> Element? {
+ return storage.remove(member)
+ }
+
+ public func union(_ other: TSet<Element>) -> TSet {
+ return TSet(storage: storage.union(other.storage))
+ }
+
+ public mutating func formIntersection(_ other: TSet<Element>) {
+ return storage.formIntersection(other.storage)
+ }
+
+ public mutating func formSymmetricDifference(_ other: TSet<Element>) {
+ return storage.formSymmetricDifference(other.storage)
+ }
+
+ public mutating func formUnion(_ other: TSet<Element>) {
+ return storage.formUnion(other.storage)
+ }
+
+ public func intersection(_ other: TSet<Element>) -> TSet {
+ return TSet(storage: storage.intersection(other.storage))
+ }
+
+ public func symmetricDifference(_ other: TSet<Element>) -> TSet {
+ return TSet(storage: storage.symmetricDifference(other.storage))
+ }
+
+ public mutating func update(with newMember: Element) -> Element? {
+ return storage.update(with: newMember)
+ }
+
+ /// Mark: IndexableBase
+
+ public var startIndex: Index { return storage.startIndex }
+ public var endIndex: Index { return storage.endIndex }
+ public func index(after i: Index) -> Index {
+ return storage.index(after: i)
+ }
+
+ public func formIndex(after i: inout Storage.Index) {
+ storage.formIndex(after: &i)
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ return storage[bounds]
+ }
+
+
+ /// Mark: Hashable
+ public var hashValue : Int {
+ let prime = 31
+ var result = 1
+ for element in storage {
+ result = prime &* result &+ element.hashValue
+ }
+ return result
+ }
+
+ /// Mark: TSerializable
+ public static var thriftType : TType { return .set }
+
+ public init() {
+ storage = Storage()
+ }
+
+ public init(arrayLiteral elements: Element...) {
+ self.storage = Storage(elements)
+ }
+
+ public init<Source : Sequence>(_ sequence: Source) where Source.Iterator.Element == Element {
+ storage = Storage(sequence)
+ }
+
+ public static func read(from proto: TProtocol) throws -> TSet {
+ let (elementType, size) = try proto.readSetBegin()
+ if elementType != Element.thriftType {
+ throw TProtocolError(error: .invalidData,
+ extendedError: .unexpectedType(type: elementType))
+ }
+ var set = TSet()
+ for _ in 0..<size {
+ let element = try Element.read(from: proto)
+ set.storage.insert(element)
+ }
+ try proto.readSetEnd()
+ return set
+ }
+
+ public func write(to proto: TProtocol) throws {
+ try proto.writeSetBegin(elementType: Element.thriftType, size: Int32(self.count))
+ for element in self.storage {
+ try Element.write(element, to: proto)
+ }
+ try proto.writeSetEnd()
+ }
+}
+
+extension TSet: CustomStringConvertible, CustomDebugStringConvertible {
+ public var description : String {
+ return storage.description
+ }
+ public var debugDescription : String {
+ return storage.debugDescription
+ }
+
+}
+
+public func ==<Element>(lhs: TSet<Element>, rhs: TSet<Element>) -> Bool {
+ return lhs.storage == rhs.storage
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TSocketServer.swift b/src/jaegertracing/thrift/lib/swift/Sources/TSocketServer.swift
new file mode 100644
index 000000000..7367c7edc
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TSocketServer.swift
@@ -0,0 +1,148 @@
+/*
+* 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
+
+public let TSocketServerClientConnectionFinished = "TSocketServerClientConnectionFinished"
+public let TSocketServerProcessorKey = "TSocketServerProcessor"
+public let TSocketServerTransportKey = "TSocketServerTransport"
+
+class TSocketServer<InProtocol: TProtocol, OutProtocol: TProtocol, Processor: TProcessor, Service> where Processor.Service == Service {
+ var socketFileHandle: FileHandle
+ var processingQueue = DispatchQueue(label: "TSocketServer.processing",
+ qos: .background,
+ attributes: .concurrent)
+ var serviceHandler: Service
+
+ public init(port: Int,
+ service: Service,
+ inProtocol: InProtocol.Type,
+ outProtocol: OutProtocol.Type,
+ processor: Processor.Type) throws {
+ // set service handler
+ self.serviceHandler = service
+
+ // create a socket
+ var fd: Int32 = -1
+ #if os(Linux)
+ let sock = CFSocketCreate(kCFAllocatorDefault, PF_INET, Int32(SOCK_STREAM.rawValue), Int32(IPPROTO_TCP), 0, nil, nil)
+ #else
+ let sock = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, nil, nil)
+ #endif
+ if sock != nil {
+ CFSocketSetSocketFlags(sock, CFSocketGetSocketFlags(sock) & ~kCFSocketCloseOnInvalidate)
+
+ fd = CFSocketGetNative(sock)
+ var yes = 1
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, UInt32(MemoryLayout<Int>.size))
+
+ #if os(Linux)
+ var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
+ sin_port: in_port_t(port.bigEndian),
+ sin_addr: in_addr(s_addr: in_addr_t(0)),
+ sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+ #else
+ var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
+ sin_family: sa_family_t(AF_INET),
+ sin_port: in_port_t(port.bigEndian),
+ sin_addr: in_addr(s_addr: in_addr_t(0)),
+ sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+ #endif
+
+ let ptr = withUnsafePointer(to: &addr) {
+ return UnsafePointer<UInt8>(OpaquePointer($0))
+ }
+
+ let address = Data(bytes: ptr, count: MemoryLayout<sockaddr_in>.size)
+
+ let cfaddr = address.withUnsafeBytes {
+ CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0, address.count, nil)
+ }
+ if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess {
+ CFSocketInvalidate(sock)
+ print("TSocketServer: Could not bind to address")
+ throw TTransportError(error: .notOpen, message: "Could not bind to address")
+ }
+
+ } else {
+ print("TSocketServer: No server socket")
+ throw TTransportError(error: .notOpen, message: "Could not create socket")
+ }
+
+ // wrap it in a file handle so we can get messages from it
+ socketFileHandle = FileHandle(fileDescriptor: fd, closeOnDealloc: true)
+
+ // throw away our socket
+ CFSocketInvalidate(sock)
+
+ // register for notifications of accepted incoming connections
+ _ = NotificationCenter.default.addObserver(forName: .NSFileHandleConnectionAccepted,
+ object: nil, queue: nil) {
+ [weak self] notification in
+ guard let strongSelf = self else { return }
+ strongSelf.connectionAccepted(strongSelf.socketFileHandle)
+ }
+
+ // tell socket to listen
+ socketFileHandle.acceptConnectionInBackgroundAndNotify()
+
+ print("TSocketServer: Listening on TCP port \(port)")
+ }
+
+ deinit {
+ NotificationCenter.default.removeObserver(self)
+ }
+
+ func connectionAccepted(_ socket: FileHandle) {
+ // Now that we have a client connected, handle the request on queue
+ processingQueue.async {
+ self.handleClientConnection(socket)
+ }
+ }
+
+ func handleClientConnection(_ clientSocket: FileHandle) {
+
+ let transport = TFileHandleTransport(fileHandle: clientSocket)
+ let processor = Processor(service: serviceHandler)
+
+ let inProtocol = InProtocol(on: transport)
+ let outProtocol = OutProtocol(on: transport)
+
+ do {
+ try processor.process(on: inProtocol, outProtocol: outProtocol)
+ } catch let error {
+ print("Error processign request: \(error)")
+ }
+ DispatchQueue.main.async {
+ NotificationCenter.default
+ .post(name: Notification.Name(rawValue: TSocketServerClientConnectionFinished),
+ object: self,
+ userInfo: [TSocketServerProcessorKey: processor,
+ TSocketServerTransportKey: transport])
+ }
+ }
+}
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)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TStreamTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TStreamTransport.swift
new file mode 100644
index 000000000..d9c957422
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TStreamTransport.swift
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+import Foundation
+import CoreFoundation
+
+#if !swift(>=4.2)
+// Swift 3/4 compatibility
+fileprivate extension RunLoopMode {
+ static let `default` = defaultRunLoopMode
+}
+#endif
+
+#if os(Linux)
+ /// Currently unavailable in Linux
+ /// Remove comments and build to fix
+ /// Currently kConstants for CFSockets don't exist in linux and not all have been moved
+ /// to property structs yet
+#else
+ // Must inherit NSObject for NSStreamDelegate conformance
+ public class TStreamTransport : NSObject, TTransport {
+ public var input: InputStream? = nil
+ public var output: OutputStream? = nil
+
+ public init(inputStream: InputStream?, outputStream: OutputStream?) {
+ input = inputStream
+ output = outputStream
+ }
+
+ public convenience init(inputStream: InputStream?) {
+ self.init(inputStream: inputStream, outputStream: nil)
+ }
+
+ public convenience init(outputStream: OutputStream?) {
+ self.init(inputStream: nil, outputStream: outputStream)
+ }
+
+ deinit {
+ close()
+ }
+
+ public func readAll(size: Int) throws -> Data {
+ guard let input = input else {
+ throw TTransportError(error: .unknown)
+ }
+
+ var read = Data()
+ while read.count < size {
+ var buffer = Array<UInt8>(repeating: 0, count: size - read.count)
+
+ let bytesRead = buffer.withUnsafeMutableBufferPointer { bufferPtr in
+ return input.read(bufferPtr.baseAddress!, maxLength: size - read.count)
+ }
+
+ if bytesRead <= 0 {
+ throw TTransportError(error: .notOpen)
+ }
+ read.append(Data(buffer))
+ }
+ return read
+ }
+
+ public func read(size: Int) throws -> Data {
+ guard let input = input else {
+ throw TTransportError(error: .unknown)
+ }
+
+ var read = Data()
+ while read.count < size {
+ var buffer = Array<UInt8>(repeating: 0, count: size - read.count)
+ let bytesRead = buffer.withUnsafeMutableBufferPointer {
+ input.read($0.baseAddress!, maxLength: size - read.count)
+ }
+
+ if bytesRead <= 0 {
+ break
+ }
+
+ read.append(Data(buffer))
+ }
+ return read
+ }
+
+ public func write(data: Data) throws {
+ guard let output = output else {
+ throw TTransportError(error: .unknown)
+ }
+
+ var bytesWritten = 0
+ while bytesWritten < data.count {
+ bytesWritten = data.withUnsafeBytes {
+ return output.write($0, maxLength: data.count)
+ }
+
+ if bytesWritten == -1 {
+ throw TTransportError(error: .notOpen)
+ } else if bytesWritten == 0 {
+ throw TTransportError(error: .endOfFile)
+ }
+ }
+ }
+
+
+ public func flush() throws {
+ return
+ }
+
+ public func close() {
+
+ if input != nil {
+ // Close and reset inputstream
+ if let cf: CFReadStream = input {
+ CFReadStreamSetProperty(cf, .shouldCloseNativeSocket, kCFBooleanTrue)
+ }
+
+ input?.delegate = nil
+ input?.close()
+ input?.remove(from: .current, forMode: .default)
+ input = nil
+ }
+
+ if output != nil {
+ // Close and reset output stream
+ if let cf: CFWriteStream = output {
+ CFWriteStreamSetProperty(cf, .shouldCloseNativeSocket, kCFBooleanTrue)
+ }
+ output?.delegate = nil
+ output?.close()
+ output?.remove(from: .current, forMode: .default)
+ output = nil
+ }
+ }
+ }
+#endif
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TStruct.swift b/src/jaegertracing/thrift/lib/swift/Sources/TStruct.swift
new file mode 100644
index 000000000..38e51e702
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TStruct.swift
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+
+/// Protocol for Generated Structs to conform to
+/// Dictionary maps field names to internal IDs and uses Reflection
+/// to iterate through all fields.
+/// `writeFieldValue(_:name:type:id:)` calls `TSerializable.write(to:)` internally
+/// giving a nice recursive behavior for nested TStructs, TLists, TMaps, and TSets
+public protocol TStruct : TSerializable {
+ static var fieldIds: [String: Int32] { get }
+ static var structName: String { get }
+}
+
+public extension TStruct {
+ static var fieldIds: [String: (id: Int32, type: TType)] { return [:] }
+ static var thriftType: TType { return .struct }
+
+ func write(to proto: TProtocol) throws {
+ // Write struct name first
+ try proto.writeStructBegin(name: Self.structName)
+
+ try self.forEach { name, value, id in
+ // Write to protocol
+ try proto.writeFieldValue(value, name: name,
+ type: value.thriftType, id: id)
+ }
+ try proto.writeFieldStop()
+ try proto.writeStructEnd()
+ }
+
+ var hashValue: Int {
+ let prime = 31
+ var result = 1
+ self.forEach { _, value, _ in
+ result = prime &* result &+ (value.hashValue)
+ }
+ return result
+ }
+
+ /// Provides a block for handling each (available) thrift property using reflection
+ /// Caveat: Skips over optional values
+
+
+ /// Provides a block for handling each (available) thrift property using reflection
+ ///
+ /// - parameter block: block for handling property
+ ///
+ /// - throws: rethrows any Error thrown in block
+ private func forEach(_ block: (_ name: String, _ value: TSerializable, _ id: Int32) throws -> Void) rethrows {
+ // Mirror the object, getting (name: String?, value: Any) for every property
+ let mirror = Mirror(reflecting: self)
+
+ // Iterate through all children, ignore empty property names
+ for (propName, propValue) in mirror.children {
+ guard let propName = propName else { continue }
+
+ if let tval = unwrap(any: propValue) as? TSerializable, let id = Self.fieldIds[propName] {
+ try block(propName, tval, id)
+ }
+ }
+ }
+
+
+ /// Any can mysteriously be an Optional<Any> at the same time,
+ /// this checks and always returns Optional<Any> without double wrapping
+ /// we then try to bind value as TSerializable to ignore any extension properties
+ /// and the like and verify the property exists and grab the Thrift
+ /// property ID at the same time
+ ///
+ /// - parameter any: Any instance to attempt to unwrap
+ ///
+ /// - returns: Unwrapped Any as Optional<Any>
+ private func unwrap(any: Any) -> Any? {
+ let mi = Mirror(reflecting: any)
+
+ if mi.displayStyle != .optional { return any }
+ if mi.children.count == 0 { return nil }
+
+ let (_, some) = mi.children.first!
+ return some
+ }
+}
+
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TTransport.swift b/src/jaegertracing/thrift/lib/swift/Sources/TTransport.swift
new file mode 100644
index 000000000..e82bbe140
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TTransport.swift
@@ -0,0 +1,64 @@
+/*
+* 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.
+*/
+
+import Foundation
+
+public protocol TTransport {
+
+ // Required
+ func read(size: Int) throws -> Data
+ func write(data: Data) throws
+ func flush() throws
+
+ // Optional (default provided)
+ func readAll(size: Int) throws -> Data
+ func isOpen() throws -> Bool
+ func open() throws
+ func close() throws
+}
+
+public extension TTransport {
+ func isOpen() throws -> Bool { return true }
+ func open() throws { }
+ func close() throws { }
+
+ func readAll(size: Int) throws -> Data {
+ var buff = Data()
+ var have = 0
+ while have < size {
+ let chunk = try self.read(size: size - have)
+ have += chunk.count
+ buff.append(chunk)
+ if chunk.count == 0 {
+ throw TTransportError(error: .endOfFile)
+ }
+ }
+ return buff
+ }
+}
+
+public protocol TAsyncTransport : TTransport {
+ // Factory
+ func flush(_ completion: @escaping (TAsyncTransport, Error?) ->())
+}
+
+public protocol TAsyncTransportFactory {
+ associatedtype Transport : TAsyncTransport
+ func newTransport() -> Transport
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TTransportError.swift b/src/jaegertracing/thrift/lib/swift/Sources/TTransportError.swift
new file mode 100644
index 000000000..3fd005937
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TTransportError.swift
@@ -0,0 +1,86 @@
+/*
+* 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.
+*/
+
+public struct TTransportError: TError {
+ public enum ErrorCode: TErrorCode {
+ case unknown
+ case notOpen
+ case alreadyOpen
+ case timedOut
+ case endOfFile
+ case negativeSize
+ case sizeLimit(limit: Int, got: Int)
+
+ public var thriftErrorCode: Int {
+ switch self {
+ case .unknown: return 0
+ case .notOpen: return 1
+ case .alreadyOpen: return 2
+ case .timedOut: return 3
+ case .endOfFile: return 4
+ case .negativeSize: return 5
+ case .sizeLimit: return 6
+ }
+ }
+ public var description: String {
+ switch self {
+ case .unknown: return "Unknown TTransportError"
+ case .notOpen: return "Not Open"
+ case .alreadyOpen: return "Already Open"
+ case .timedOut: return "Timed Out"
+ case .endOfFile: return "End Of File"
+ case .negativeSize: return "Negative Size"
+ case .sizeLimit(let limit, let got):
+ return "Message exceeds size limit of \(limit) (received: \(got)"
+ }
+ }
+ }
+ public var error: ErrorCode = .unknown
+ public var message: String? = nil
+ public static var defaultCase: ErrorCode { return .unknown }
+
+ public init() { }
+
+}
+
+/// THTTPTransportError
+///
+/// Error's thrown on HTTP Transport
+public struct THTTPTransportError: TError {
+ public enum ErrorCode: TErrorCode {
+ case invalidResponse
+ case invalidStatus(statusCode: Int)
+ case authentication
+
+ public var description: String {
+ switch self {
+ case .invalidResponse: return "Invalid HTTP Response"
+ case .invalidStatus(let statusCode): return "Invalid HTTP Status Code (\(statusCode))"
+ case .authentication: return "Authentication Error"
+ }
+ }
+ public var thriftErrorCode: Int { return 0 }
+ }
+ public var error: ErrorCode = .invalidResponse
+ public var message: String? = nil
+ public static var defaultCase: ErrorCode { return .invalidResponse }
+
+ public init() { }
+}
+
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TWrappedProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TWrappedProtocol.swift
new file mode 100644
index 000000000..8e8577bb5
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/TWrappedProtocol.swift
@@ -0,0 +1,208 @@
+/*
+* 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.
+*/
+
+import Foundation // For (NS)Data
+
+
+/// Generic protocol, implementes TProtocol and wraps a concrete protocol.
+/// Useful for generically subclassing protocols to override specific methods
+/// (i.e. TMultiplexedProtocol)
+open class TWrappedProtocol<Protocol: TProtocol> : TProtocol {
+ var concreteProtocol: Protocol
+
+ public var transport: TTransport {
+ get {
+ return concreteProtocol.transport
+ }
+ set {
+ concreteProtocol.transport = newValue
+ }
+ }
+
+ public required init(on transport: TTransport) {
+ self.concreteProtocol = Protocol(on: transport)
+ }
+
+ // Read methods
+
+ public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+ return try concreteProtocol.readMessageBegin()
+ }
+
+ public func readMessageEnd() throws {
+ try concreteProtocol.readMessageEnd()
+ }
+
+ public func readStructBegin() throws -> String {
+ return try concreteProtocol.readStructBegin()
+ }
+
+ public func readStructEnd() throws {
+ try concreteProtocol.readStructEnd()
+ }
+
+ public func readFieldBegin() throws -> (String, TType, Int32) {
+ return try concreteProtocol.readFieldBegin()
+ }
+
+ public func readFieldEnd() throws {
+ try concreteProtocol.readFieldEnd()
+ }
+
+ public func readMapBegin() throws -> (TType, TType, Int32) {
+ return try concreteProtocol.readMapBegin()
+ }
+
+ public func readMapEnd() throws {
+ try concreteProtocol.readMapEnd()
+ }
+
+ public func readSetBegin() throws -> (TType, Int32) {
+ return try concreteProtocol.readSetBegin()
+ }
+
+ public func readSetEnd() throws {
+ try concreteProtocol.readSetEnd()
+ }
+
+ public func readListBegin() throws -> (TType, Int32) {
+ return try concreteProtocol.readListBegin()
+ }
+
+ public func readListEnd() throws {
+ try concreteProtocol.readListEnd()
+ }
+
+ public func read() throws -> String {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Bool {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> UInt8 {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Int16 {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Int32 {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Int64 {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Double {
+ return try concreteProtocol.read()
+ }
+
+ public func read() throws -> Data {
+ return try concreteProtocol.read()
+ }
+
+ // Write methods
+
+ public func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws {
+ return try concreteProtocol.writeMessageBegin(name: name, type: messageType, sequenceID: sequenceID)
+ }
+
+ public func writeMessageEnd() throws {
+ try concreteProtocol.writeMessageEnd()
+ }
+
+ public func writeStructBegin(name: String) throws {
+ try concreteProtocol.writeStructBegin(name: name)
+ }
+
+ public func writeStructEnd() throws {
+ try concreteProtocol.writeStructEnd()
+ }
+
+ public func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws {
+ try concreteProtocol.writeFieldBegin(name: name, type: fieldType, fieldID: fieldID)
+ }
+
+ public func writeFieldStop() throws {
+ try concreteProtocol.writeFieldStop()
+ }
+
+ public func writeFieldEnd() throws {
+ try concreteProtocol.writeFieldEnd()
+ }
+
+ public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+ try concreteProtocol.writeMapBegin(keyType: keyType, valueType: valueType, size: size)
+ }
+
+ public func writeMapEnd() throws {
+ try concreteProtocol.writeMapEnd()
+ }
+
+ public func writeSetBegin(elementType: TType, size: Int32) throws {
+ try concreteProtocol.writeSetBegin(elementType: elementType, size: size)
+ }
+
+ public func writeSetEnd() throws {
+ try concreteProtocol.writeSetEnd()
+ }
+
+ public func writeListBegin(elementType: TType, size: Int32) throws {
+ try concreteProtocol.writeListBegin(elementType: elementType, size: size)
+ }
+
+ public func writeListEnd() throws {
+ try concreteProtocol.writeListEnd()
+ }
+ public func write(_ value: String) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: Bool) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: UInt8) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: Int16) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: Int32) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: Int64) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ value: Double) throws {
+ try concreteProtocol.write(value)
+ }
+
+ public func write(_ data: Data) throws {
+ try concreteProtocol.write(data)
+ }
+}
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/Thrift.swift b/src/jaegertracing/thrift/lib/swift/Sources/Thrift.swift
new file mode 100644
index 000000000..45c68f2e5
--- /dev/null
+++ b/src/jaegertracing/thrift/lib/swift/Sources/Thrift.swift
@@ -0,0 +1,3 @@
+class Thrift {
+ let version = "0.13.0"
+}