Files
raspberry/iOS/Wallet/Sources/Network/Service/NetworkServiceWebSockets.swift
T
2022-06-03 16:55:25 +03:00

107 lines
3.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 {
class WebSockets: Common.Service.Provider {
private var timer: Timer?
private var reconectTimer: Timer?
private var collection = [String:Subscription]()
init() {
timer = delayed(45, repeats: true) { self.update() }
reconectTimer = delayed(1, repeats: true) { self.reconect() }
}
}
}
extension Network.Service.WebSockets {
func open(subscription: String, id: String) {
collection[id] = Subscription(id: id, subscription: subscription)
}
func remove(id: String) {
collection[id] = nil
}
func remove(idPrefix prefix: String) {
let toRemoveIds = collection.filter({ $0.key.hasPrefix(prefix) }).map({ $0.key })
for id in toRemoveIds {
collection[id] = nil
}
}
func remove(idSuffix suffix: String) {
let toRemoveIds = collection.filter({ $0.key.hasSuffix(suffix) }).map({ $0.key })
for id in toRemoveIds {
collection[id] = nil
}
}
func removeAll() {
collection = [:]
}
}
extension Network.Service.WebSockets {
private func update() {
for subscription in collection {
if !subscription.value.socket.isConnected {
subscription.value.socket.connect()
} else {
subscription.value.socket.write(ping: Data())
}
}
}
private func reconect() {
for subscription in collection {
if !subscription.value.socket.isConnected {
subscription.value.socket.connect()
}
}
}
}
extension Network.Service.WebSockets {
fileprivate class Subscription {
let socket: WebSocket
let id: String
let subscription: String?
deinit { socket.disconnect() }
init(id: String, subscription: String?) {
self.id = id
self.subscription = subscription
var request = URLRequest(url: URL(string: Network.servers.current.webSocket)!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
}
}
extension Network.Service.WebSockets.Subscription: WebSocketDelegate {
func websocketDidConnect(socket: WebSocketClient) {
if let subscription = subscription { socket.write(string: subscription) }
Notification.post(name: .socketDidConnect, userInfo: ["id": id])
}
func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
socket.connect()
Notification.post(name: .socketDidDisconnect, userInfo: ["id": id])
}
func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
Notification.post(name: .socketDidUpdateValue, userInfo: ["id": id, "data": text])
}
func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
Notification.post(name: .socketDidUpdateValue, userInfo: ["id": id, "data": String(data: data, encoding: .utf8) ?? ""])
}
}