HttpHandlers+WebSockets.swift 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. //
  2. // HttpHandlers+WebSockets.swift
  3. // Swifter
  4. //
  5. // Copyright © 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. extension HttpHandlers {
  9. public class func websocket(handle:(String) -> ()) -> (HttpRequest -> HttpResponse) {
  10. return { r in
  11. guard r.headers["upgrade"] == "websocket" else {
  12. return .BadRequest
  13. }
  14. guard r.headers["connection"] == "Upgrade" else {
  15. return .BadRequest
  16. }
  17. guard let secWebSocketKey = r.headers["sec-websocket-key"] else {
  18. return .BadRequest
  19. }
  20. let accept = String.encodeToBase64((secWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").SHA1())
  21. let upgradeHeaders = [ "Upgrade": "WebSocket", "Connection": "Upgrade", "Sec-WebSocket-Accept": accept]
  22. return HttpResponse.SwitchProtocols(upgradeHeaders) { socket in
  23. let parser = WebSocketParser()
  24. while let frame = try? parser.readFrame(socket) {
  25. handle(String.fromUInt8(frame.payload))
  26. }
  27. }
  28. }
  29. }
  30. public class WebSocketParser {
  31. enum Error: ErrorType {
  32. case UnknownOpCode(String)
  33. }
  34. public enum OpCode { case CONTINUE, CLOSE, PING, PONG, TEXT, BINARY }
  35. public class Frame {
  36. public var opcode = OpCode.CLOSE
  37. public var fin = false
  38. public var payload = [UInt8]()
  39. }
  40. public func readFrame(socket: Socket) throws -> Frame {
  41. let frm = Frame()
  42. let fst = try socket.read()
  43. frm.fin = fst & 0x80 != 0
  44. let opc = fst & 0x0F
  45. switch opc {
  46. case 0x00: frm.opcode = OpCode.CONTINUE
  47. case 0x01: frm.opcode = OpCode.TEXT
  48. case 0x02: frm.opcode = OpCode.BINARY
  49. case 0x08: frm.opcode = OpCode.CLOSE
  50. case 0x09: frm.opcode = OpCode.PING
  51. case 0x0A: frm.opcode = OpCode.PONG
  52. default : throw Error.UnknownOpCode("\(opc)")
  53. }
  54. let sec = try socket.read()
  55. let msk = sec & 0x0F != 0
  56. var len = UInt64(sec & 0x7F)
  57. if len == 0x7E {1
  58. let b0 = UInt64(try socket.read())
  59. let b1 = UInt64(try socket.read())
  60. len = UInt64(littleEndian: b0 << 8 | b1)
  61. } else if len == 0x7F {
  62. let b0 = UInt64(try socket.read())
  63. let b1 = UInt64(try socket.read())
  64. let b2 = UInt64(try socket.read())
  65. let b3 = UInt64(try socket.read())
  66. let b4 = UInt64(try socket.read())
  67. let b5 = UInt64(try socket.read())
  68. let b6 = UInt64(try socket.read())
  69. let b7 = UInt64(try socket.read())
  70. len = UInt64(littleEndian: b0 << 54 | b1 << 48 | b2 << 40 | b3 << 32 | b4 << 24 | b5 << 16 | b6 << 8 | b7)
  71. }
  72. let mask = msk ? [try socket.read(), try socket.read(), try socket.read(), try socket.read()] : []
  73. for i in 0..<len {
  74. let byte = try socket.read()
  75. frm.payload.append(msk ? byte ^ mask[Int(i % 4)] : byte)
  76. }
  77. return frm
  78. }
  79. }
  80. }