@@ -111,6 +111,9 @@ open class SocketEngine:
111111 /// The url for WebSockets.
112112 public private( set) var urlWebSocket = URL ( string: " http://localhost/ " ) !
113113
114+ /// The version of engine.io being used. Default is three.
115+ public private( set) var version : SocketIOVersion = . three
116+
114117 /// If `true`, then the engine is currently in WebSockets mode.
115118 @available ( * , deprecated, message: " No longer needed, if we're not polling, then we must be doing websockets " )
116119 public private( set) var websocket = false
@@ -133,8 +136,14 @@ open class SocketEngine:
133136
134137 private var lastCommunication : Date ?
135138 private var pingInterval : Int ?
136- private var pingTimeout = 0
139+ private var pingTimeout = 0 {
140+ didSet {
141+ pongsMissedMax = Int ( pingTimeout / ( pingInterval ?? 25000 ) )
142+ }
143+ }
137144
145+ private var pongsMissed = 0
146+ private var pongsMissedMax = 0
138147 private var probeWait = ProbeWaitQueue ( )
139148 private var secure = false
140149 private var certPinner : CertificatePinning ?
@@ -196,8 +205,9 @@ open class SocketEngine:
196205 }
197206
198207 private func handleBase64( message: String ) {
208+ let offset = version. rawValue >= 3 ? 1 : 2
199209 // binary in base64 string
200- let noPrefix = String ( message [ message. index ( message. startIndex, offsetBy: 1 ) ..< message. endIndex] )
210+ let noPrefix = String ( message [ message. index ( message. startIndex, offsetBy: offset ) ..< message. endIndex] )
201211
202212 if let data = Data ( base64Encoded: noPrefix, options: . ignoreUnknownCharacters) {
203213 client? . parseEngineBinaryData ( data)
@@ -278,6 +288,14 @@ open class SocketEngine:
278288 urlWebSocket. percentEncodedQuery = " transport=websocket " + queryString
279289 urlPolling. percentEncodedQuery = " transport=polling&b64=1 " + queryString
280290
291+ if !urlWebSocket. percentEncodedQuery!. contains ( " EIO " ) {
292+ urlWebSocket. percentEncodedQuery = urlWebSocket. percentEncodedQuery! + engineIOParam
293+ }
294+
295+ if !urlPolling. percentEncodedQuery!. contains ( " EIO " ) {
296+ urlPolling. percentEncodedQuery = urlPolling. percentEncodedQuery! + engineIOParam
297+ }
298+
281299 return ( urlPolling. url!, urlWebSocket. url!)
282300 }
283301
@@ -289,6 +307,8 @@ open class SocketEngine:
289307 includingCookies: session? . configuration. httpCookieStorage? . cookies ( for: urlPollingWithSid)
290308 )
291309
310+ print ( " ws req: \( req) " )
311+
292312 ws = WebSocket ( request: req, certPinner: certPinner, compressionHandler: compress ? WSCompression ( ) : nil )
293313 ws? . callbackQueue = engineQueue
294314 ws? . delegate = self
@@ -413,6 +433,7 @@ open class SocketEngine:
413433
414434 self . sid = sid
415435 connected = true
436+ pongsMissed = 0
416437
417438 if let upgrades = json [ " upgrades " ] as? [ String ] {
418439 upgradeWs = upgrades. contains ( " websocket " )
@@ -429,26 +450,37 @@ open class SocketEngine:
429450 createWebSocketAndConnect ( )
430451 }
431452
453+ if version. rawValue >= 3 {
454+ checkPings ( )
455+ } else {
456+ sendPing ( )
457+ }
458+
432459 if !forceWebsockets {
433460 doPoll ( )
434461 }
435462
436- checkPings ( )
437463 client? . engineDidOpen ( reason: " Connect " )
438464 }
439465
440466 private func handlePong( with message: String ) {
467+ pongsMissed = 0
468+
441469 // We should upgrade
442470 if message == " 3probe " {
443471 DefaultSocketLogger . Logger. log ( " Received probe response, should upgrade to WebSockets " ,
444472 type: SocketEngine . logType)
445473
446474 upgradeTransport ( )
447475 }
476+
477+ client? . engineDidReceivePong ( )
448478 }
449479
450480 private func handlePing( with message: String ) {
451- write ( " " , withType: . pong, withData: [ ] )
481+ if version. rawValue >= 3 {
482+ write ( " " , withType: . pong, withData: [ ] )
483+ }
452484
453485 client? . engineDidReceivePing ( )
454486 }
@@ -478,7 +510,7 @@ open class SocketEngine:
478510
479511 lastCommunication = Date ( )
480512
481- client? . parseEngineBinaryData ( data)
513+ client? . parseEngineBinaryData ( version . rawValue >= 3 ? data : data . subdata ( in : 1 ..< data . endIndex ) )
482514 }
483515
484516 /// Parses a raw engine.io packet.
@@ -489,13 +521,11 @@ open class SocketEngine:
489521
490522 DefaultSocketLogger . Logger. log ( " Got message: \( message) " , type: SocketEngine . logType)
491523
492- let reader = SocketStringReader ( message: message)
493-
494- if message. hasPrefix ( " b " ) {
524+ if message. hasPrefix ( version. rawValue >= 3 ? " b " : " b4 " ) {
495525 return handleBase64 ( message: message)
496526 }
497527
498- guard let type = SocketEnginePacketType ( rawValue: Int ( reader . currentCharacter ) ?? - 1 ) else {
528+ guard let type = SocketEnginePacketType ( rawValue: message . first ? . wholeNumberValue ?? - 1 ) else {
499529 checkAndHandleEngineError ( message)
500530
501531 return
@@ -536,6 +566,34 @@ open class SocketEngine:
536566 waitingForPost = false
537567 }
538568
569+ private func sendPing( ) {
570+ guard connected, let pingInterval = pingInterval else {
571+ print ( " not connected \( self . connected) or no ping interval \( self . pingInterval ?? - 222 ) " )
572+ return
573+ }
574+
575+ // Server is not responding
576+ if pongsMissed > pongsMissedMax {
577+ closeOutEngine ( reason: " Ping timeout " )
578+ return
579+ }
580+
581+ pongsMissed += 1
582+ write ( " " , withType: . ping, withData: [ ] , completion: nil )
583+
584+ engineQueue. asyncAfter ( deadline: . now( ) + . milliseconds( pingInterval) ) { [ weak self, id = self . sid] in
585+ // Make sure not to ping old connections
586+ guard let this = self , this. sid == id else {
587+ print ( " wrong ping? " )
588+ return
589+ }
590+
591+ this. sendPing ( )
592+ }
593+
594+ client? . engineDidSendPing ( )
595+ }
596+
539597 /// Called when the engine should set/update its configs from a given configuration.
540598 ///
541599 /// parameter config: The `SocketIOClientConfiguration` that should be used to set/update configs.
@@ -570,6 +628,8 @@ open class SocketEngine:
570628 self . compress = true
571629 case . enableSOCKSProxy:
572630 self . enableSOCKSProxy = true
631+ case let . version( num) :
632+ version = num
573633 default :
574634 continue
575635 }
0 commit comments