0001 // SSLClientStream.swift 0002 // 0003 // The MIT License (MIT) 0004 // 0005 // Copyright (c) 2015 Zewo 0006 // 0007 // Permission is hereby granted, free of charge, to any person obtaining a copy 0008 // of this software and associated documentation files (the "Software"), to deal 0009 // in the Software without restriction, including without limitation the rights 0010 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0011 // copies of the Software, and to permit persons to whom the Software is 0012 // furnished to do so, subject to the following conditions: 0013 // 0014 // The above copyright notice and this permission notice shall be included in all 0015 // copies or substantial portions of the Software. 0016 // 0017 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0018 // IMPLIED, INCLUDINbG BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0019 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0020 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0021 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0022 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 0023 // SOFTWARE. 0024 0025 import COpenSSL 0026 @_exported import Stream 0027 0028 public final class SSLClientStream: StreamType { 0029 private(set) public var metadata: [String: Any] = [:] 0030 private let context: SSLClientContext 0031 private let rawStream: StreamType 0032 private let ssl: Session 0033 private let readIO: IO 0034 private let writeIO: IO 0035 0036 public var closed: Bool = false 0037 0038 public init(context: SSLClientContext, rawStream: StreamType) throws { 0039 OpenSSL.initialize() 0040 0041 metadata = rawStream.metadata 0042 0043 self.context = context 0044 self.rawStream = rawStream 0045 0046 readIO = try IO(method: .Memory) 0047 writeIO = try IO(method: .Memory) 0048 0049 ssl = try Session(context: context) 0050 ssl.setIO(readIO: readIO, writeIO: writeIO) 0051 0052 ssl.setConnectState() 0053 } 0054 0055 public func receive() throws -> Data { 0056 let data: Data 0057 do { 0058 data = try rawStream.receive() 0059 } catch StreamError.ClosedStream(let _data) { 0060 data = _data 0061 } 0062 0063 try readIO.write(data) 0064 0065 var decriptedData = Data() 0066 0067 while true { 0068 do { 0069 decriptedData += try ssl.read() 0070 } catch Session.Error.WantRead { 0071 if decriptedData.count > 0 { 0072 return decriptedData 0073 } 0074 0075 do { 0076 let data = try rawStream.receive() 0077 try readIO.write(data) 0078 } catch StreamError.ClosedStream(let _data) { 0079 return decriptedData + _data 0080 } 0081 } catch Session.Error.ZeroReturn { 0082 return decriptedData 0083 } 0084 } 0085 } 0086 0087 public func send(data: Data) throws { 0088 while !ssl.initializationFinished { 0089 do { 0090 try ssl.handshake() 0091 } catch Session.Error.WantRead { 0092 } 0093 do { 0094 try send() 0095 } catch IO.Error.ShouldRetry { 0096 if ssl.initializationFinished { 0097 break 0098 } 0099 } 0100 try rawStream.flush() 0101 let data = try rawStream.receive() 0102 try readIO.write(data) 0103 } 0104 0105 if data.count > 0 { 0106 ssl.write(data) 0107 do { 0108 try send() 0109 } catch IO.Error.ShouldRetry {} 0110 } else { 0111 try rawStream.send(data) 0112 } 0113 } 0114 0115 public func flush() throws { 0116 try rawStream.flush() 0117 } 0118 0119 public func close() -> Bool { 0120 return rawStream.close() 0121 } 0122 0123 private func send() throws { 0124 let data = try writeIO.read() 0125 try rawStream.send(data) 0126 } 0127 } 0128
ClientStream.swift:88 while !ssl.initializationFinished {ClientStream.swift:90 try ssl.handshake()ClientStream.swift:96 if ssl.initializationFinished {