Files
raspberry/iOS/Wallet/Sources/Network/Service/NetworkServiceWebSockets.swift
2022-12-29 23:24:39 +03:00

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)")
}
}