You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
3.1 KiB
96 lines
3.1 KiB
//
|
|
// NativeEngine.swift
|
|
// Starscream
|
|
//
|
|
// Created by Dalton Cherry on 6/15/19.
|
|
// Copyright © 2019 Vluxe. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
|
|
public class NativeEngine: NSObject, Engine, URLSessionDataDelegate, URLSessionWebSocketDelegate {
|
|
private var task: URLSessionWebSocketTask?
|
|
weak var delegate: EngineDelegate?
|
|
|
|
public func register(delegate: EngineDelegate) {
|
|
self.delegate = delegate
|
|
}
|
|
|
|
public func start(request: URLRequest) {
|
|
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
|
|
task = session.webSocketTask(with: request)
|
|
doRead()
|
|
task?.resume()
|
|
}
|
|
|
|
public func stop(closeCode: UInt16) {
|
|
let closeCode = URLSessionWebSocketTask.CloseCode(rawValue: Int(closeCode)) ?? .normalClosure
|
|
task?.cancel(with: closeCode, reason: nil)
|
|
}
|
|
|
|
public func forceStop() {
|
|
stop(closeCode: UInt16(URLSessionWebSocketTask.CloseCode.abnormalClosure.rawValue))
|
|
}
|
|
|
|
public func write(string: String, completion: (() -> ())?) {
|
|
task?.send(.string(string), completionHandler: { (error) in
|
|
completion?()
|
|
})
|
|
}
|
|
|
|
public func write(data: Data, opcode: FrameOpCode, completion: (() -> ())?) {
|
|
switch opcode {
|
|
case .binaryFrame:
|
|
task?.send(.data(data), completionHandler: { (error) in
|
|
completion?()
|
|
})
|
|
case .textFrame:
|
|
let text = String(data: data, encoding: .utf8)!
|
|
write(string: text, completion: completion)
|
|
case .ping:
|
|
task?.sendPing(pongReceiveHandler: { (error) in
|
|
completion?()
|
|
})
|
|
default:
|
|
break //unsupported
|
|
}
|
|
}
|
|
|
|
private func doRead() {
|
|
task?.receive { [weak self] (result) in
|
|
switch result {
|
|
case .success(let message):
|
|
switch message {
|
|
case .string(let string):
|
|
self?.broadcast(event: .text(string))
|
|
case .data(let data):
|
|
self?.broadcast(event: .binary(data))
|
|
@unknown default:
|
|
break
|
|
}
|
|
break
|
|
case .failure(let error):
|
|
self?.broadcast(event: .error(error))
|
|
}
|
|
self?.doRead()
|
|
}
|
|
}
|
|
|
|
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)))
|
|
}
|
|
}
|