SocketParsable.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. //
  2. // SocketParsable.swift
  3. // Socket.IO-Client-Swift
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. import Foundation
  23. protocol SocketParsable : SocketIOClientSpec {
  24. func parseBinaryData(data: NSData)
  25. func parseSocketMessage(message: String)
  26. }
  27. extension SocketParsable {
  28. private func isCorrectNamespace(nsp: String) -> Bool {
  29. return nsp == self.nsp
  30. }
  31. private func handleConnect(p: SocketPacket) {
  32. if p.nsp == "/" && nsp != "/" {
  33. joinNamespace(nsp)
  34. } else {
  35. didConnect()
  36. }
  37. }
  38. private func handlePacket(pack: SocketPacket) {
  39. switch pack.type {
  40. case .Event where isCorrectNamespace(pack.nsp):
  41. handleEvent(pack.event, data: pack.args, isInternalMessage: false, withAck: pack.id)
  42. case .Ack where isCorrectNamespace(pack.nsp):
  43. handleAck(pack.id, data: pack.data)
  44. case .BinaryEvent where isCorrectNamespace(pack.nsp):
  45. waitingPackets.append(pack)
  46. case .BinaryAck where isCorrectNamespace(pack.nsp):
  47. waitingPackets.append(pack)
  48. case .Connect:
  49. handleConnect(pack)
  50. case .Disconnect:
  51. didDisconnect("Got Disconnect")
  52. case .Error:
  53. handleEvent("error", data: pack.data, isInternalMessage: true, withAck: pack.id)
  54. default:
  55. DefaultSocketLogger.Logger.log("Got invalid packet: %@", type: "SocketParser", args: pack.description)
  56. }
  57. }
  58. /// Parses a messsage from the engine. Returning either a string error or a complete SocketPacket
  59. func parseString(message: String) -> Either<String, SocketPacket> {
  60. var parser = SocketStringReader(message: message)
  61. guard let type = SocketPacket.PacketType(rawValue: Int(parser.read(1)) ?? -1) else {
  62. return .Left("Invalid packet type")
  63. }
  64. if !parser.hasNext {
  65. return .Right(SocketPacket(type: type, nsp: "/"))
  66. }
  67. var namespace = "/"
  68. var placeholders = -1
  69. if type == .BinaryEvent || type == .BinaryAck {
  70. if let holders = Int(parser.readUntilStringOccurence("-")) {
  71. placeholders = holders
  72. } else {
  73. return .Left("Invalid packet")
  74. }
  75. }
  76. if parser.currentCharacter == "/" {
  77. namespace = parser.readUntilStringOccurence(",") ?? parser.readUntilEnd()
  78. }
  79. if !parser.hasNext {
  80. return .Right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
  81. }
  82. var idString = ""
  83. if type == .Error {
  84. parser.advanceIndexBy(-1)
  85. }
  86. while parser.hasNext && type != .Error {
  87. if let int = Int(parser.read(1)) {
  88. idString += String(int)
  89. } else {
  90. parser.advanceIndexBy(-2)
  91. break
  92. }
  93. }
  94. let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
  95. switch parseData(d) {
  96. case let .Left(err):
  97. // Errors aren't always enclosed in an array
  98. if case let .Right(data) = parseData("\([d as AnyObject])") {
  99. return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
  100. nsp: namespace, placeholders: placeholders))
  101. } else {
  102. return .Left(err)
  103. }
  104. case let .Right(data):
  105. return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
  106. nsp: namespace, placeholders: placeholders))
  107. }
  108. }
  109. // Parses data for events
  110. private func parseData(data: String) -> Either<String, [AnyObject]> {
  111. let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
  112. do {
  113. if let arr = try NSJSONSerialization.JSONObjectWithData(stringData!,
  114. options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] {
  115. return .Right(arr)
  116. } else {
  117. return .Left("Expected data array")
  118. }
  119. } catch {
  120. return .Left("Error parsing data for packet")
  121. }
  122. }
  123. // Parses messages recieved
  124. func parseSocketMessage(message: String) {
  125. guard !message.isEmpty else { return }
  126. DefaultSocketLogger.Logger.log("Parsing %@", type: "SocketParser", args: message)
  127. switch parseString(message) {
  128. case let .Left(err):
  129. DefaultSocketLogger.Logger.error("\(err): %@", type: "SocketParser", args: message)
  130. case let .Right(pack):
  131. DefaultSocketLogger.Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
  132. handlePacket(pack)
  133. }
  134. }
  135. func parseBinaryData(data: NSData) {
  136. guard !waitingPackets.isEmpty else {
  137. DefaultSocketLogger.Logger.error("Got data when not remaking packet", type: "SocketParser")
  138. return
  139. }
  140. // Should execute event?
  141. guard waitingPackets[waitingPackets.count - 1].addData(data) else {
  142. return
  143. }
  144. let packet = waitingPackets.removeLast()
  145. if packet.type != .BinaryAck {
  146. handleEvent(packet.event, data: packet.args ?? [],
  147. isInternalMessage: false, withAck: packet.id)
  148. } else {
  149. handleAck(packet.id, data: packet.args)
  150. }
  151. }
  152. }