add ping pong
This commit is contained in:
parent
f886386374
commit
41adedee40
@ -39,6 +39,7 @@ final class SocketService {
|
|||||||
private var socket: SocketIOClient?
|
private var socket: SocketIOClient?
|
||||||
private var heartbeatTimer: DispatchSourceTimer?
|
private var heartbeatTimer: DispatchSourceTimer?
|
||||||
private var heartbeatAckInFlight = false
|
private var heartbeatAckInFlight = false
|
||||||
|
private var lastHeartbeatSentAt: Date?
|
||||||
private var consecutiveHeartbeatMisses = 0
|
private var consecutiveHeartbeatMisses = 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -193,6 +194,10 @@ final class SocketService {
|
|||||||
self?.handleHeartbeatSuccess()
|
self?.handleHeartbeatSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.on("message") { [weak self] data, _ in
|
||||||
|
self?.handleMessageEvent(data)
|
||||||
|
}
|
||||||
|
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.socket = socket
|
self.socket = socket
|
||||||
}
|
}
|
||||||
@ -224,6 +229,7 @@ final class SocketService {
|
|||||||
heartbeatTimer = nil
|
heartbeatTimer = nil
|
||||||
heartbeatAckInFlight = false
|
heartbeatAckInFlight = false
|
||||||
consecutiveHeartbeatMisses = 0
|
consecutiveHeartbeatMisses = 0
|
||||||
|
lastHeartbeatSentAt = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func performHeartbeatCheck() {
|
private func performHeartbeatCheck() {
|
||||||
@ -246,43 +252,61 @@ final class SocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func sendHeartbeat(on socket: SocketIOClient) {
|
private func sendHeartbeat(on socket: SocketIOClient) {
|
||||||
guard !heartbeatAckInFlight else { return }
|
if heartbeatAckInFlight {
|
||||||
heartbeatAckInFlight = true
|
if let lastSentAt = lastHeartbeatSentAt,
|
||||||
|
Date().timeIntervalSince(lastSentAt) >= heartbeatTimeout {
|
||||||
socket.emitWithAck(heartbeatEventName, ["timestamp": Date().timeIntervalSince1970])
|
heartbeatAckInFlight = false
|
||||||
.timingOut(after: heartbeatTimeout) { [weak self] data in
|
handleMissedHeartbeat(for: socket)
|
||||||
guard let self else { return }
|
} else {
|
||||||
self.heartbeatAckInFlight = false
|
return
|
||||||
|
|
||||||
if self.isSuccessfulHeartbeatResponse(data) {
|
|
||||||
self.handleHeartbeatSuccess()
|
|
||||||
} else {
|
|
||||||
self.handleMissedHeartbeat(for: socket)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heartbeatAckInFlight = true
|
||||||
|
lastHeartbeatSentAt = Date()
|
||||||
|
|
||||||
|
socket.emit(heartbeatEventName, ["data": "ping"])
|
||||||
}
|
}
|
||||||
|
|
||||||
private func isSuccessfulHeartbeatResponse(_ data: [Any]) -> Bool {
|
private func handleMessageEvent(_ data: [Any]) {
|
||||||
guard !data.isEmpty else { return true }
|
guard let payload = data.first else { return }
|
||||||
|
|
||||||
if let stringValue = data.first as? String, stringValue.uppercased() == "NO ACK" {
|
let messageText: String?
|
||||||
return false
|
|
||||||
|
if let dictionary = payload as? [String: Any] {
|
||||||
|
if let nestedData = dictionary["data"] as? [String: Any],
|
||||||
|
let nestedMessage = nestedData["message"] as? String {
|
||||||
|
messageText = nestedMessage
|
||||||
|
} else {
|
||||||
|
messageText = dictionary["message"] as? String
|
||||||
|
}
|
||||||
|
} else if let stringValue = payload as? String {
|
||||||
|
messageText = stringValue
|
||||||
|
} else {
|
||||||
|
messageText = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ackStatus = data.first as? SocketAckStatus, ackStatus == .noAck {
|
guard let message = messageText?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() else {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
if message == "pong" {
|
||||||
|
handleHeartbeatSuccess()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleHeartbeatSuccess() {
|
private func handleHeartbeatSuccess() {
|
||||||
consecutiveHeartbeatMisses = 0
|
consecutiveHeartbeatMisses = 0
|
||||||
|
heartbeatAckInFlight = false
|
||||||
|
lastHeartbeatSentAt = nil
|
||||||
updateConnectionState(.connected)
|
updateConnectionState(.connected)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleMissedHeartbeat(for socket: SocketIOClient) {
|
private func handleMissedHeartbeat(for socket: SocketIOClient) {
|
||||||
consecutiveHeartbeatMisses += 1
|
consecutiveHeartbeatMisses += 1
|
||||||
|
heartbeatAckInFlight = false
|
||||||
|
lastHeartbeatSentAt = nil
|
||||||
|
updateConnectionState(.connecting)
|
||||||
guard consecutiveHeartbeatMisses > maxHeartbeatMissCount else {
|
guard consecutiveHeartbeatMisses > maxHeartbeatMissCount else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ struct AppConfig {
|
|||||||
static let PROTOCOL = "https"
|
static let PROTOCOL = "https"
|
||||||
static let API_SERVER = "\(PROTOCOL)://api.yobble.org"
|
static let API_SERVER = "\(PROTOCOL)://api.yobble.org"
|
||||||
static let SOCKET_PATH = "/socket.io/"
|
static let SOCKET_PATH = "/socket.io/"
|
||||||
static let SOCKET_HEARTBEAT_EVENT = "ping"
|
static let SOCKET_HEARTBEAT_EVENT = "client_message"
|
||||||
|
|
||||||
static let USER_AGENT = "yobble ios"
|
static let USER_AGENT = "yobble ios"
|
||||||
static let APP_BUILD = "appstore" // appstore / freestore
|
static let APP_BUILD = "appstore" // appstore / freestore
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user