98 lines
2.6 KiB
Swift
98 lines
2.6 KiB
Swift
//
|
|
// CastHeartbeatChannel.swift
|
|
// OpenCastSwift
|
|
//
|
|
// Created by Miles Hollingsworth on 4/22/18
|
|
// Copyright © 2018 Miles Hollingsworth. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftyJSON
|
|
|
|
class HeartbeatChannel: CastChannel {
|
|
private lazy var timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(sendPing), userInfo: nil, repeats: true)
|
|
|
|
private let disconnectTimeout: TimeInterval = 10
|
|
private var disconnectTimer: Timer? {
|
|
willSet {
|
|
disconnectTimer?.invalidate()
|
|
}
|
|
didSet {
|
|
guard let timer = disconnectTimer else { return }
|
|
|
|
RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
|
|
}
|
|
}
|
|
|
|
override weak var requestDispatcher: RequestDispatchable! {
|
|
didSet {
|
|
if let _ = requestDispatcher {
|
|
startBeating()
|
|
} else {
|
|
timer.invalidate()
|
|
}
|
|
}
|
|
}
|
|
|
|
private var delegate: HeartbeatChannelDelegate? {
|
|
return requestDispatcher as? HeartbeatChannelDelegate
|
|
}
|
|
|
|
init() {
|
|
super.init(namespace: CastNamespace.heartbeat)
|
|
}
|
|
|
|
override func handleResponse(_ json: JSON, sourceId: String) {
|
|
delegate?.channelDidConnect(self)
|
|
|
|
guard let rawType = json["type"].string else { return }
|
|
|
|
guard let type = CastMessageType(rawValue: rawType) else {
|
|
print("Unknown type: \(rawType)")
|
|
print(json)
|
|
return
|
|
}
|
|
|
|
if type == .ping {
|
|
sendPong(to: sourceId)
|
|
print("PING from \(sourceId)")
|
|
}
|
|
|
|
disconnectTimer = Timer(timeInterval: disconnectTimeout,
|
|
target: self,
|
|
selector: #selector(handleTimeout),
|
|
userInfo: nil,
|
|
repeats: false)
|
|
}
|
|
|
|
private func startBeating() {
|
|
_ = timer
|
|
sendPing()
|
|
}
|
|
|
|
@objc private func sendPing() {
|
|
let request = requestDispatcher.request(withNamespace: namespace,
|
|
destinationId: CastConstants.transport,
|
|
payload: [CastJSONPayloadKeys.type: CastMessageType.ping.rawValue])
|
|
|
|
send(request)
|
|
}
|
|
|
|
private func sendPong(to destinationId: String) {
|
|
let request = requestDispatcher.request(withNamespace: namespace,
|
|
destinationId: destinationId,
|
|
payload: [CastJSONPayloadKeys.type: CastMessageType.pong.rawValue])
|
|
|
|
send(request)
|
|
}
|
|
|
|
@objc private func handleTimeout() {
|
|
delegate?.channelDidTimeout(self)
|
|
}
|
|
}
|
|
|
|
protocol HeartbeatChannelDelegate: AnyObject {
|
|
func channelDidConnect(_ channel: HeartbeatChannel)
|
|
func channelDidTimeout(_ channel: HeartbeatChannel)
|
|
}
|