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
ClientStream.swift:88
        while !ssl.initializationFinished {
ClientStream.swift:90
                try ssl.handshake()
ClientStream.swift:96
                if ssl.initializationFinished {
: 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