149 lines
4.5 KiB
Swift
149 lines
4.5 KiB
Swift
//
|
|
// NetworkServiceApiWebSockets.swift
|
|
// Wallet
|
|
//
|
|
// Created by Saveliy Stavitsky on 1/15/21.
|
|
// Copyright © 2021 AM. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Starscream
|
|
|
|
extension Notification.Name {
|
|
static let socketDidConnect = Self("Network.Service.WebSockets.socketDidConnect")
|
|
static let socketDidUpdateValue = Self("Network.Service.WebSockets.socketDidUpdateValue")
|
|
static let socketDidDisconnect = Self("Network.Service.WebSockets.socketDidDisconnect")
|
|
}
|
|
|
|
extension Network.Service {
|
|
|
|
final class WebSockets: Common.Service.Provider {
|
|
|
|
private var timer: Timer?
|
|
private var reconectTimer: Timer?
|
|
private var collection = [String: Subscription]()
|
|
|
|
init() {
|
|
self.timer = delayed(45, repeats: true) { self.update() }
|
|
self.reconectTimer = delayed(1, repeats: true) { self.reconect() }
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Network.Service.WebSockets {
|
|
|
|
func open(subscription: String, id: String) {
|
|
self.collection[id] = Subscription(id: id, subscription: subscription)
|
|
}
|
|
|
|
func contains(id: String) -> Bool {
|
|
self.collection[id].isExist
|
|
}
|
|
|
|
func remove(id: String) {
|
|
self.collection[id] = nil
|
|
}
|
|
|
|
func remove(idPrefix prefix: String) {
|
|
self.collection
|
|
.filter { $0.key.hasPrefix(prefix) }
|
|
.map { $0.key }
|
|
.forEach { self.collection[$0] = nil }
|
|
}
|
|
|
|
func remove(idSuffix suffix: String) {
|
|
self.collection
|
|
.filter { $0.key.hasSuffix(suffix) }
|
|
.map { $0.key }
|
|
.forEach { self.collection[$0] = nil }
|
|
}
|
|
|
|
func removeAll() {
|
|
self.collection = [:]
|
|
}
|
|
}
|
|
|
|
extension Network.Service.WebSockets {
|
|
|
|
private func update() {
|
|
|
|
self.collection.forEach { subscription in
|
|
if !subscription.value.socket.isConnected {
|
|
subscription.value.socket.connect()
|
|
} else {
|
|
subscription.value.socket.write(ping: Data())
|
|
}
|
|
}
|
|
}
|
|
private func reconect() {
|
|
|
|
self.collection
|
|
.filter { !$0.value.socket.isConnected }
|
|
.forEach { $0.value.socket.connect() }
|
|
}
|
|
}
|
|
|
|
extension Network.Service.WebSockets {
|
|
|
|
fileprivate final class Subscription {
|
|
|
|
let socket: WebSocket
|
|
let id: String
|
|
let subscription: String?
|
|
|
|
init(id: String, subscription: String?) {
|
|
self.id = id
|
|
self.subscription = subscription
|
|
|
|
let environment = ApplicationEnvironment.shared().current
|
|
var request = URLRequest(url: URL(string: environment.backend.webSocket)!)
|
|
request.timeoutInterval = 5
|
|
environment.headers.forEach { (key, value) in
|
|
request.addValue(value, forHTTPHeaderField: key)
|
|
}
|
|
|
|
self.socket = WebSocket(request: request)
|
|
self.socket.advancedDelegate = self
|
|
self.socket.connect()
|
|
}
|
|
|
|
deinit { self.socket.disconnect() }
|
|
|
|
}
|
|
}
|
|
|
|
extension Network.Service.WebSockets.Subscription: WebSocketAdvancedDelegate {
|
|
|
|
func websocketDidConnect(socket: WebSocket) {
|
|
// print("websocketDidConnect")
|
|
if let subscription = self.subscription {
|
|
socket.write(string: subscription)
|
|
}
|
|
Notification.post(name: .socketDidConnect, userInfo: ["id": self.id])
|
|
}
|
|
|
|
func websocketDidDisconnect(socket: WebSocket, error: Error?) {
|
|
// print("websocketDidDisconnect: \(error)")
|
|
// socket.connect() // do not reconnect continuously
|
|
Notification.post(name: .socketDidDisconnect, userInfo: ["id": self.id])
|
|
}
|
|
|
|
func websocketDidReceiveMessage(socket: WebSocket, text: String, response: WebSocket.WSResponse) {
|
|
Notification.post(name: .socketDidUpdateValue, userInfo: ["id": self.id, "data": text])
|
|
}
|
|
|
|
func websocketDidReceiveData(socket: WebSocket, data: Data, response: WebSocket.WSResponse) {
|
|
// print("websocketDidReceiveData: \(response.code)")
|
|
Notification.post(name: .socketDidUpdateValue, userInfo: ["id": self.id,
|
|
"data": String(data: data, encoding: .utf8) ?? ""])
|
|
}
|
|
|
|
func websocketHttpUpgrade(socket: WebSocket, request: String) {
|
|
// print("websocketHttpUpgrade: \(request)")
|
|
}
|
|
|
|
func websocketHttpUpgrade(socket: WebSocket, response: String) {
|
|
// print("websocketHttpUpgrade: \(response)")
|
|
}
|
|
}
|