-
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,891 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,6 @@ | |
// | ||
|
||
import Foundation | ||
import Starscream | ||
import SwiftProtobuf | ||
|
||
public enum CentrifugeError: Error { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Compression.swift | ||
// | ||
// Created by Joseph Ross on 7/16/14. | ||
// Copyright © 2017 Joseph Ross. | ||
// | ||
// Licensed 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. | ||
// | ||
////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Compression implementation is implemented in conformance with RFC 7692 Compression Extensions | ||
// for WebSocket: https://tools.ietf.org/html/rfc7692 | ||
// | ||
////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
import Foundation | ||
import zlib | ||
|
||
class Decompressor { | ||
private var strm = z_stream() | ||
private var buffer = [UInt8](repeating: 0, count: 0x2000) | ||
private var inflateInitialized = false | ||
private let windowBits:Int | ||
|
||
init?(windowBits:Int) { | ||
self.windowBits = windowBits | ||
guard initInflate() else { return nil } | ||
} | ||
|
||
private func initInflate() -> Bool { | ||
if Z_OK == inflateInit2_(&strm, -CInt(windowBits), | ||
ZLIB_VERSION, CInt(MemoryLayout<z_stream>.size)) | ||
{ | ||
inflateInitialized = true | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func reset() throws { | ||
teardownInflate() | ||
guard initInflate() else { throw WSError(type: .compressionError, message: "Error for decompressor on reset", code: 0) } | ||
} | ||
|
||
func decompress(_ data: Data, finish: Bool) throws -> Data { | ||
return try data.withUnsafeBytes { (bytes:UnsafePointer<UInt8>) -> Data in | ||
return try decompress(bytes: bytes, count: data.count, finish: finish) | ||
} | ||
} | ||
|
||
func decompress(bytes: UnsafePointer<UInt8>, count: Int, finish: Bool) throws -> Data { | ||
var decompressed = Data() | ||
try decompress(bytes: bytes, count: count, out: &decompressed) | ||
|
||
if finish { | ||
let tail:[UInt8] = [0x00, 0x00, 0xFF, 0xFF] | ||
try decompress(bytes: tail, count: tail.count, out: &decompressed) | ||
} | ||
|
||
return decompressed | ||
|
||
} | ||
|
||
private func decompress(bytes: UnsafePointer<UInt8>, count: Int, out:inout Data) throws { | ||
var res:CInt = 0 | ||
strm.next_in = UnsafeMutablePointer<UInt8>(mutating: bytes) | ||
strm.avail_in = CUnsignedInt(count) | ||
|
||
repeat { | ||
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer) | ||
strm.avail_out = CUnsignedInt(buffer.count) | ||
|
||
res = inflate(&strm, 0) | ||
|
||
let byteCount = buffer.count - Int(strm.avail_out) | ||
out.append(buffer, count: byteCount) | ||
} while res == Z_OK && strm.avail_out == 0 | ||
|
||
guard (res == Z_OK && strm.avail_out > 0) | ||
|| (res == Z_BUF_ERROR && Int(strm.avail_out) == buffer.count) | ||
else { | ||
throw WSError(type: .compressionError, message: "Error on decompressing", code: 0) | ||
} | ||
} | ||
|
||
private func teardownInflate() { | ||
if inflateInitialized, Z_OK == inflateEnd(&strm) { | ||
inflateInitialized = false | ||
} | ||
} | ||
|
||
deinit { | ||
teardownInflate() | ||
} | ||
} | ||
|
||
class Compressor { | ||
private var strm = z_stream() | ||
private var buffer = [UInt8](repeating: 0, count: 0x2000) | ||
private var deflateInitialized = false | ||
private let windowBits:Int | ||
|
||
init?(windowBits: Int) { | ||
self.windowBits = windowBits | ||
guard initDeflate() else { return nil } | ||
} | ||
|
||
private func initDeflate() -> Bool { | ||
if Z_OK == deflateInit2_(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, | ||
-CInt(windowBits), 8, Z_DEFAULT_STRATEGY, | ||
ZLIB_VERSION, CInt(MemoryLayout<z_stream>.size)) | ||
{ | ||
deflateInitialized = true | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func reset() throws { | ||
teardownDeflate() | ||
guard initDeflate() else { throw WSError(type: .compressionError, message: "Error for compressor on reset", code: 0) } | ||
} | ||
|
||
func compress(_ data: Data) throws -> Data { | ||
var compressed = Data() | ||
var res:CInt = 0 | ||
data.withUnsafeBytes { (ptr:UnsafePointer<UInt8>) -> Void in | ||
strm.next_in = UnsafeMutablePointer<UInt8>(mutating: ptr) | ||
strm.avail_in = CUnsignedInt(data.count) | ||
|
||
repeat { | ||
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer) | ||
strm.avail_out = CUnsignedInt(buffer.count) | ||
|
||
res = deflate(&strm, Z_SYNC_FLUSH) | ||
|
||
let byteCount = buffer.count - Int(strm.avail_out) | ||
compressed.append(buffer, count: byteCount) | ||
} | ||
while res == Z_OK && strm.avail_out == 0 | ||
|
||
} | ||
|
||
guard res == Z_OK && strm.avail_out > 0 | ||
|| (res == Z_BUF_ERROR && Int(strm.avail_out) == buffer.count) | ||
else { | ||
throw WSError(type: .compressionError, message: "Error on compressing", code: 0) | ||
} | ||
|
||
compressed.removeLast(4) | ||
return compressed | ||
} | ||
|
||
private func teardownDeflate() { | ||
if deflateInitialized, Z_OK == deflateEnd(&strm) { | ||
deflateInitialized = false | ||
} | ||
} | ||
|
||
deinit { | ||
teardownDeflate() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// | ||
// SSLClientCertificate.swift | ||
// Starscream | ||
// | ||
// Created by Tomasz Trela on 08/03/2018. | ||
// Copyright © 2018 Vluxe. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
struct SSLClientCertificateError: LocalizedError { | ||
var errorDescription: String? | ||
|
||
init(errorDescription: String) { | ||
self.errorDescription = errorDescription | ||
} | ||
} | ||
|
||
class SSLClientCertificate { | ||
internal let streamSSLCertificates: NSArray | ||
|
||
/** | ||
Convenience init. | ||
- parameter pkcs12Path: Path to pkcs12 file containing private key and X.509 ceritifacte (.p12) | ||
- parameter password: file password, see **kSecImportExportPassphrase** | ||
*/ | ||
convenience init(pkcs12Path: String, password: String) throws { | ||
let pkcs12Url = URL(fileURLWithPath: pkcs12Path) | ||
do { | ||
try self.init(pkcs12Url: pkcs12Url, password: password) | ||
} catch { | ||
throw error | ||
} | ||
} | ||
|
||
/** | ||
Designated init. For more information, see SSLSetCertificate() in Security/SecureTransport.h. | ||
- parameter identity: SecIdentityRef, see **kCFStreamSSLCertificates** | ||
- parameter identityCertificate: CFArray of SecCertificateRefs, see **kCFStreamSSLCertificates** | ||
*/ | ||
init(identity: SecIdentity, identityCertificate: SecCertificate) { | ||
self.streamSSLCertificates = NSArray(objects: identity, identityCertificate) | ||
} | ||
|
||
/** | ||
Convenience init. | ||
- parameter pkcs12Url: URL to pkcs12 file containing private key and X.509 ceritifacte (.p12) | ||
- parameter password: file password, see **kSecImportExportPassphrase** | ||
*/ | ||
convenience init(pkcs12Url: URL, password: String) throws { | ||
let importOptions = [kSecImportExportPassphrase as String : password] as CFDictionary | ||
do { | ||
try self.init(pkcs12Url: pkcs12Url, importOptions: importOptions) | ||
} catch { | ||
throw error | ||
} | ||
} | ||
|
||
/** | ||
Designated init. | ||
- parameter pkcs12Url: URL to pkcs12 file containing private key and X.509 ceritifacte (.p12) | ||
- parameter importOptions: A dictionary containing import options. A | ||
kSecImportExportPassphrase entry is required at minimum. Only password-based | ||
PKCS12 blobs are currently supported. See **SecImportExport.h** | ||
*/ | ||
init(pkcs12Url: URL, importOptions: CFDictionary) throws { | ||
do { | ||
let pkcs12Data = try Data(contentsOf: pkcs12Url) | ||
var rawIdentitiesAndCertificates: CFArray? | ||
let pkcs12CFData: CFData = pkcs12Data as CFData | ||
let importStatus = SecPKCS12Import(pkcs12CFData, importOptions, &rawIdentitiesAndCertificates) | ||
|
||
guard importStatus == errSecSuccess else { | ||
throw SSLClientCertificateError(errorDescription: "(Starscream) Error during 'SecPKCS12Import', see 'SecBase.h' - OSStatus: \(importStatus)") | ||
} | ||
guard let identitiyAndCertificate = (rawIdentitiesAndCertificates as? Array<Dictionary<String, Any>>)?.first else { | ||
throw SSLClientCertificateError(errorDescription: "(Starscream) Error - PKCS12 file is empty") | ||
} | ||
|
||
let identity = identitiyAndCertificate[kSecImportItemIdentity as String] as! SecIdentity | ||
var identityCertificate: SecCertificate? | ||
let copyStatus = SecIdentityCopyCertificate(identity, &identityCertificate) | ||
guard copyStatus == errSecSuccess else { | ||
throw SSLClientCertificateError(errorDescription: "(Starscream) Error during 'SecIdentityCopyCertificate', see 'SecBase.h' - OSStatus: \(copyStatus)") | ||
} | ||
self.streamSSLCertificates = NSArray(objects: identity, identityCertificate!) | ||
} catch { | ||
throw error | ||
} | ||
} | ||
} |
Oops, something went wrong.