Compare commits

...

26 Commits

Author SHA1 Message Date
daltoniam df8d82047f 4.0.4 release 2020-08-01 15:04:10 -05:00
Dalton 85c8412646 Merge pull request #807 from varahash/conditional-zlib-dependency
Conditionally include 'swift-nio-zlib-support' dependency to avoid warning on macOS
2020-07-18 19:48:29 -05:00
Dalton 4820831260 Merge pull request #799 from amayers/xcode12
Fix compile error on Xcode 12
2020-07-18 19:47:50 -05:00
Dalton 024a27711e Merge pull request #808 from dvshelley/deployTarget9
move deployment target to iOS 9 to fix compile for archive with Xcode 12
2020-07-18 19:47:10 -05:00
Daniel Shelley 5987db1605 move deployment target to iOS 9 to fix compile for archive with Xcode 12 2020-07-16 16:50:35 -06:00
Mykola Varahash fe5769f2ae Conditionally include 'swift-nio-zlib-support' dependency to avoid warning on macOS 2020-07-13 01:35:26 +03:00
Andrew Mayers 263b9419bb Fix compile error on Xcode 12
Now you can build on both Xcode 11.5 & 12.0 b1.

On 12, the unit tests would fail to compile because it wasn't finding the `Starscream` framework. So I added `Starscream` as a dependency of the test target.

In `FoundationHTTPServerHandler` the `method` is of type `CFString`, while `getVerb` is `NSString`. Looks like Xcode 12 doesn't like equality comparison between those types without a cast as `NSString`.
2020-06-22 17:23:47 -04:00
Dalton 5fbeab4c12 Merge pull request #777 from jaltreuter/crash_after_disconnect
In FoundationTransport deinit, remove self as a delegate to InputStream and OutputStream to prevent EXC_BAD_ACCESS
2020-06-20 19:20:04 -05:00
Dalton 07bccd9c16 Merge pull request #790 from sdidla/fix_readLoop
Improve conditions for calling readLoop() and prevent infinite looping
2020-06-20 19:18:12 -05:00
Dalton 51b6c789bd Merge pull request #788 from SemyonBaryshev/master
Fix error when trying to convert text message partial payload to UTF-8
2020-06-20 19:15:56 -05:00
Dalton 0c7e7abfd7 Merge pull request #764 from ameyjain/fix/data-extension-swift-version-check
Fix the deadlock issue on iOS 11
2020-06-20 19:13:26 -05:00
Dalton d2f22783b6 Merge pull request #768 from michalsrutek/patch-1
Update README.md
2020-06-20 19:12:03 -05:00
Dalton e6236acc00 Merge pull request #797 from amayers/swift52
Switch SPM to use Swift 5.2
2020-06-20 19:11:18 -05:00
Dalton d003b62b54 Merge pull request #766 from urbanairship/fixUnsafeMutablePointerDeprecation
Fix deprecation warning in WSCompression
2020-06-20 19:07:41 -05:00
Andrew Mayers 70d9e6ec5c Switch SPM to use Swift 5.2 2020-06-17 09:52:36 -04:00
Shammi Didla c0e7d40284 improve conditions for calling readLoop() 2020-06-06 15:27:27 +02:00
Semyon Baryshev 06945ada8b Fix error when trying to convert text message partial payload to UTF-8 2020-06-05 18:39:16 +03:00
Jamie Altreuter 7e5a96341c In FoundationTransport deinit, remove self as a delegate to InputStream and OutputStream to prevent EXC_BAD_ACCESS 2020-05-12 18:14:25 -07:00
Michal Šrůtek ce4fcdc967 Update README.md
Update Autobahn link
2020-04-26 10:00:02 +02:00
Nick Ratelle da1d9c69a7 Fix deprecation warning in WSCompression
Apple recommends using the withUnsafeMutableBytes method on the buffer
to bind an unsafe pointer.
2020-04-21 17:54:17 -04:00
Amey Jain b6630118fe Fix the deadlock issue on iOS 11 2020-04-16 11:47:42 -04:00
daltoniam cfc7b7b8dc version bump 2020-04-08 19:59:30 -05:00
daltoniam 311b6dd9c7 fixes #760 2020-04-08 19:58:07 -05:00
daltoniam 339ca39461 improved native engine and a few bug fixes 2020-04-06 14:29:55 -05:00
Dalton 4e8973e3fc Merge pull request #697 from mikaryyn/feature/v4-refactor
Fix for a buffer overflow when close code has not been received from the socket
2020-04-06 14:16:00 -05:00
Mika Ryynänen 281a49edd8 Fix for a buffer overflow when close code has not been received from the socket. 2019-09-24 13:13:36 +03:00
18 changed files with 136 additions and 53 deletions
+27
View File
@@ -2,6 +2,33 @@
All notable changes to this project will be documented in this file.
`Starscream` adheres to [Semantic Versioning](http://semver.org/).
### [4.0.4](https://github.com/daltoniam/Starscream/tree/4.0.4)
Bug fixes for 4.0.3.
[#808](https://github.com/daltoniam/Starscream/pull/808)
[#807](https://github.com/daltoniam/Starscream/pull/807)
[#799](https://github.com/daltoniam/Starscream/pull/799)
[#797](https://github.com/daltoniam/Starscream/pull/797)
[#790](https://github.com/daltoniam/Starscream/pull/790)
[#788](https://github.com/daltoniam/Starscream/pull/788)
[#777](https://github.com/daltoniam/Starscream/pull/777)
[#768](https://github.com/daltoniam/Starscream/pull/768)
[#766](https://github.com/daltoniam/Starscream/pull/766)
[#764](https://github.com/daltoniam/Starscream/pull/764)
### [4.0.3](https://github.com/daltoniam/Starscream/tree/4.0.3)
Bug fixes for 4.0.2.
[#760](https://github.com/daltoniam/Starscream/issues/760)
### [4.0.2](https://github.com/daltoniam/Starscream/tree/4.0.2)
Bug fixes for 4.0.1. Fixed native engine is connected/disconnected. Native engine isn't the default since the API lacks features.
[#697](https://github.com/daltoniam/Starscream/pull/697)
### [4.0.1](https://github.com/daltoniam/Starscream/tree/4.0.1)
Bug fixes for 4.0.0. Enabled Native engine now that the API is out of beta and works properly.
+6 -4
View File
@@ -1,4 +1,4 @@
// swift-tools-version:4.2
// swift-tools-version:5.2
//
// Package.Swift
@@ -27,11 +27,13 @@ let package = Package(
products: [
.library(name: "Starscream", targets: ["Starscream"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio-zlib-support.git", from: "1.0.0")
],
dependencies: [],
targets: [
.target(name: "Starscream",
path: "Sources")
]
)
#if os(Linux)
package.dependencies.append(.package(url: "https://github.com/apple/swift-nio-zlib-support.git", from: "1.0.0"))
#endif
+1 -1
View File
@@ -4,7 +4,7 @@ Starscream is a conforming WebSocket ([RFC 6455](http://tools.ietf.org/html/rfc6
## Features
- Conforms to all of the base [Autobahn test suite](http://autobahn.ws/testsuite/).
- Conforms to all of the base [Autobahn test suite](https://crossbar.io/autobahn/).
- Nonblocking. Everything happens in the background, thanks to GCD.
- TLS/WSS support.
- Compression Extensions support ([RFC 7692](https://tools.ietf.org/html/rfc7692))
+10 -6
View File
@@ -147,10 +147,12 @@ class Decompressor {
strm.avail_in = CUnsignedInt(count)
repeat {
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer)
strm.avail_out = CUnsignedInt(buffer.count)
buffer.withUnsafeMutableBytes { (bufferPtr) in
strm.next_out = bufferPtr.bindMemory(to: UInt8.self).baseAddress
strm.avail_out = CUnsignedInt(bufferPtr.count)
res = inflate(&strm, 0)
res = inflate(&strm, 0)
}
let byteCount = buffer.count - Int(strm.avail_out)
out.append(buffer, count: byteCount)
@@ -209,10 +211,12 @@ class Compressor {
strm.avail_in = CUnsignedInt(data.count)
repeat {
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer)
strm.avail_out = CUnsignedInt(buffer.count)
buffer.withUnsafeMutableBytes { (bufferPtr) in
strm.next_out = bufferPtr.bindMemory(to: UInt8.self).baseAddress
strm.avail_out = CUnsignedInt(bufferPtr.count)
res = deflate(&strm, Z_SYNC_FLUSH)
res = deflate(&strm, Z_SYNC_FLUSH)
}
let byteCount = buffer.count - Int(strm.avail_out)
compressed.append(buffer, count: byteCount)
+5 -9
View File
@@ -27,22 +27,20 @@ import Foundation
internal extension Data {
struct ByteError: Swift.Error {}
#if swift(>=5.0)
func withUnsafeBytes<ResultType, ContentType>(_ completion: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
#if swift(>=5.0)
return try withUnsafeBytes {
return try withUnsafeBytes {
if let baseAddress = $0.baseAddress, $0.count > 0 {
return try completion(baseAddress.assumingMemoryBound(to: ContentType.self))
} else {
throw ByteError()
}
}
#else
return try withUnsafeBytes(completion)
#endif
}
#endif
#if swift(>=5.0)
mutating func withUnsafeMutableBytes<ResultType, ContentType>(_ completion: (UnsafeMutablePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
#if swift(>=5.0)
return try withUnsafeMutableBytes {
if let baseAddress = $0.baseAddress, $0.count > 0 {
return try completion(baseAddress.assumingMemoryBound(to: ContentType.self))
@@ -50,8 +48,6 @@ internal extension Data {
throw ByteError()
}
}
#else
return try withUnsafeMutableBytes(completion)
#endif
}
#endif
}
+16 -6
View File
@@ -9,20 +9,17 @@
import Foundation
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public class NativeEngine: Engine {
public class NativeEngine: NSObject, Engine, URLSessionDataDelegate, URLSessionWebSocketDelegate {
private var task: URLSessionWebSocketTask?
weak var delegate: EngineDelegate?
public init() {
}
public func register(delegate: EngineDelegate) {
self.delegate = delegate
}
public func start(request: URLRequest) {
task = URLSession.shared.webSocketTask(with: request)
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
task = session.webSocketTask(with: request)
doRead()
task?.resume()
}
@@ -83,4 +80,17 @@ public class NativeEngine: Engine {
private func broadcast(event: WebSocketEvent) {
delegate?.didReceive(event: event)
}
public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
let p = `protocol` ?? ""
broadcast(event: .connected([HTTPWSHeader.protocolName: p]))
}
public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
var r = ""
if let d = reason {
r = String(data: d, encoding: .utf8) ?? ""
}
broadcast(event: .disconnected(r, UInt16(closeCode.rawValue)))
}
}
+6
View File
@@ -157,6 +157,12 @@ FrameCollectorDelegate, HTTPHandlerDelegate {
canSend = true
mutex.signal()
compressionHandler?.load(headers: headers)
if let url = request.url {
HTTPCookie.cookies(withResponseHeaderFields: headers, for: url).forEach {
HTTPCookieStorage.shared.setCookie($0)
}
}
broadcast(event: .connected(headers))
case .failure(let error):
handleError(error)
@@ -74,7 +74,7 @@ public class FoundationHTTPServerHandler: HTTPServerHandler {
return false //not enough data, wait for more
}
if let method = CFHTTPMessageCopyRequestMethod(response)?.takeRetainedValue() {
if method != getVerb {
if (method as NSString) != getVerb {
delegate?.didReceive(event: .failure(HTTPUpgradeError.invalidData))
return true
}
+7 -11
View File
@@ -84,19 +84,15 @@ public class FrameCollector {
}
buffer.append(payload)
frameCount += 1
if isText {
if String(data: buffer, encoding: .utf8) == nil {
let errCode = CloseCode.protocolError.rawValue
delegate?.didForm(event: .error(WSError(type: .protocolError, message: "not valid UTF-8 data", code: errCode)))
reset()
return
}
}
if frame.isFin {
if isText {
let string = String(data: buffer, encoding: .utf8) ?? ""
delegate?.didForm(event: .text(string))
if let string = String(data: buffer, encoding: .utf8) {
delegate?.didForm(event: .text(string))
} else {
let errCode = CloseCode.protocolError.rawValue
delegate?.didForm(event: .error(WSError(type: .protocolError, message: "not valid UTF-8 data", code: errCode)))
}
} else {
delegate?.didForm(event: .binary(buffer))
}
+3
View File
@@ -183,6 +183,9 @@ public class WSFramer: Framer {
closeCode = CloseCode.protocolError.rawValue
dataLength = 0
} else if payloadLen > 1 {
if pointer.count < 4 {
return .needsMoreData
}
let size = MemoryLayout<UInt16>.size
closeCode = pointer.readUint16(offset: offset)
offset += size
+7
View File
@@ -67,6 +67,13 @@ public struct HTTPWSHeader {
req.setValue(HTTPWSHeader.versionValue, forHTTPHeaderField: HTTPWSHeader.versionName)
req.setValue(secKeyValue, forHTTPHeaderField: HTTPWSHeader.keyName)
if let cookies = HTTPCookieStorage.shared.cookies(for: url), !cookies.isEmpty {
let headers = HTTPCookie.requestHeaderFields(with: cookies)
for (key, val) in headers {
req.setValue(val, forHTTPHeaderField: key)
}
}
if supportsCompression {
let val = "permessage-deflate; client_max_window_bits; server_max_window_bits=15"
req.setValue(val, forHTTPHeaderField: HTTPWSHeader.extensionName)
+3 -4
View File
@@ -101,10 +101,9 @@ public class StringHTTPHandler: HTTPHandler {
code = c
}
} else {
let responseSplit = str.components(separatedBy: ":")
guard responseSplit.count > 1 else { break }
let key = responseSplit[0].trimmingCharacters(in: .whitespaces)
let val = responseSplit[1].trimmingCharacters(in: .whitespaces)
guard let separatorIndex = str.firstIndex(of: ":") else { break }
let key = str.prefix(upTo: separatorIndex).trimmingCharacters(in: .whitespaces)
let val = str.suffix(from: str.index(after: separatorIndex)).trimmingCharacters(in: .whitespaces)
headers[key.lowercased()] = val
}
i += 1
+1 -1
View File
@@ -120,7 +120,7 @@ open class WebSocket: WebSocketClient, EngineDelegate {
self.engine = engine
}
public convenience init(request: URLRequest, certPinner: CertificatePinning? = FoundationSecurity(), compressionHandler: CompressionHandler? = nil, useCustomEngine: Bool = false) {
public convenience init(request: URLRequest, certPinner: CertificatePinning? = FoundationSecurity(), compressionHandler: CompressionHandler? = nil, useCustomEngine: Bool = true) {
if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *), !useCustomEngine {
self.init(request: request, engine: NativeEngine())
} else if #available(macOS 10.14, iOS 12.0, watchOS 5.0, tvOS 12.0, *) {
+6 -1
View File
@@ -47,7 +47,12 @@ public class FoundationTransport: NSObject, Transport, StreamDelegate {
onConnect = streamConfiguration
}
public func connect(url: URL, timeout: Double = 10, certificatePinning: CertificatePinning? = nil) {
deinit {
inputStream?.delegate = nil
outputStream?.delegate = nil
}
public func connect(url: URL, timeout: Double = 10, certificatePinning: CertificatePinning? = nil) {
guard let parts = url.getParts() else {
delegate?.connectionChanged(state: .failed(FoundationTransportError.invalidRequest))
return
+10 -1
View File
@@ -141,7 +141,16 @@ public class TCPTransport: Transport {
if let data = data {
s.delegate?.connectionChanged(state: .receive(data))
}
s.readLoop()
// Refer to https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework
if let context = context, context.isFinal, isComplete {
return
}
if error == nil {
s.readLoop()
}
})
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Starscream"
s.version = "4.0.1"
s.version = "4.0.4"
s.summary = "A conforming WebSocket RFC 6455 client library in Swift."
s.homepage = "https://github.com/daltoniam/Starscream"
s.license = 'Apache License, Version 2.0'
+26 -7
View File
@@ -38,6 +38,16 @@
BBB5ABE8215E2217005B48B6 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB5ABE4215E2217005B48B6 /* WebSocket.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
6B0BE7AA24A157BB0051F7A7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6B3E79DD19D48B7F006071F7 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CCF0841F5DDC030099B092;
remoteInfo = Starscream;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
335FA2021F5DF71D00F6D2EC /* Starscream Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Starscream Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
33CCF0921F5DDC030099B092 /* Starscream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Starscream.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -250,6 +260,7 @@
buildRules = (
);
dependencies = (
6B0BE7AB24A157BB0051F7A7 /* PBXTargetDependency */,
);
name = "Starscream Tests";
productName = StarscreamTests;
@@ -298,8 +309,8 @@
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = 6B3E79DC19D48B7F006071F7;
productRefGroup = 6B3E79E719D48B7F006071F7 /* Products */;
@@ -372,6 +383,14 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
6B0BE7AB24A157BB0051F7A7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CCF0841F5DDC030099B092 /* Starscream */;
targetProxy = 6B0BE7AA24A157BB0051F7A7 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
335FA2001F5DF71D00F6D2EC /* Debug */ = {
isa = XCBuildConfiguration;
@@ -428,10 +447,10 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MARKETING_VERSION = 4.0.1;
MARKETING_VERSION = 4.0.4;
OTHER_LDFLAGS = "-all_load";
PRODUCT_BUNDLE_IDENTIFIER = "com.vluxe.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -456,10 +475,10 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MARKETING_VERSION = 4.0.1;
MARKETING_VERSION = 4.0.4;
OTHER_LDFLAGS = "-all_load";
PRODUCT_BUNDLE_IDENTIFIER = "com.vluxe.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -521,7 +540,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator watchsimulator watchos";
@@ -574,7 +593,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator watchsimulator watchos";
SWIFT_VERSION = 5.0;