0001 // 0002 // HttpHandlers+WebSockets.swift 0003 // Swifter 0004 // 0005 // Copyright © 2014-2016 Damian Kołakowski. All rights reserved. 0006 // 0007 0008 import Foundation 0009 0010 extension HttpHandlers { 0011 0012 public class func websocket( 0013 text: ((WebSocketSession, String) -> Void)?, 0014 _ binary: ((WebSocketSession, [UInt8]) -> Void)?) -> (HttpRequest -> HttpResponse) { 0015 return { r in 0016 guard r.hasTokenForHeader("upgrade", token: "websocket") else { 0017 return .BadRequest(.Text("Invalid value of 'Upgrade' header: \(r.headers["upgrade"])")) 0018 } 0019 guard r.hasTokenForHeader("connection", token: "upgrade") else { 0020 return .BadRequest(.Text("Invalid value of 'Connection' header: \(r.headers["connection"])")) 0021 } 0022 guard let secWebSocketKey = r.headers["sec-websocket-key"] else { 0023 return .BadRequest(.Text("Invalid value of 'Sec-Websocket-Key' header: \(r.headers["sec-websocket-key"])")) 0024 } 0025 let protocolSessionClosure: (Socket -> Void) = { socket in 0026 let session = WebSocketSession(socket) 0027 while let frame = try? session.readFrame() { 0028 switch frame.opcode { 0029 case .Text: 0030 if let handleText = text { 0031 handleText(session, String.fromUInt8(frame.payload)) 0032 } 0033 case .Binary: 0034 if let handleBinary = binary { 0035 handleBinary(session, frame.payload) 0036 } 0037 default: break 0038 } 0039 } 0040 } 0041 let secWebSocketAccept = String.toBase64((secWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").SHA1()) 0042 let headers = [ "Upgrade": "WebSocket", "Connection": "Upgrade", "Sec-WebSocket-Accept": secWebSocketAccept] 0043 return HttpResponse.SwitchProtocols(headers, protocolSessionClosure) 0044 } 0045 } 0046 0047 public class WebSocketSession
DemoServer.swift:117 server["/websocket-echo"] = HttpHandlers.websocket({ (session, text) in{ 0048 0049 public enum Error
HttpHandlers+WebSockets.swift:13 text: ((WebSocketSession, String) -> Void)?,HttpHandlers+WebSockets.swift:14 _ binary: ((WebSocketSession, [UInt8]) -> Void)?) -> (HttpRequest -> HttpResponse) {HttpHandlers+WebSockets.swift:26 let session = WebSocketSession(socket): ErrorType { case UnknownOpCode
HttpHandlers+WebSockets.swift:139 default : throw Error.UnknownOpCode("\(opc)")HttpHandlers+WebSockets.swift:146 throw Error.UnMaskedFrame(String), UnMaskedFrame
HttpHandlers+WebSockets.swift:139 default : throw Error.UnknownOpCode("\(opc)")} 0050 public enum OpCode
HttpHandlers+WebSockets.swift:146 throw Error.UnMaskedFrame{ case Continue
HttpHandlers+WebSockets.swift:53 public var opcode = OpCode.CloseHttpHandlers+WebSockets.swift:65 self.writeFrame(ArraySlice(text.utf8), OpCode.Text)HttpHandlers+WebSockets.swift:73 self.writeFrame(binary, OpCode.Binary)HttpHandlers+WebSockets.swift:76 private func writeFrame(data: ArraySlice<UInt8>, _ op: OpCode, _ fin: Bool = true) {HttpHandlers+WebSockets.swift:88 private func encodeFinAndOpCode(fin: Bool, op: OpCode) -> UInt8 {HttpHandlers+WebSockets.swift:131 case 0x00: frm.opcode = OpCode.ContinueHttpHandlers+WebSockets.swift:132 case 0x01: frm.opcode = OpCode.TextHttpHandlers+WebSockets.swift:133 case 0x02: frm.opcode = OpCode.BinaryHttpHandlers+WebSockets.swift:134 case 0x08: frm.opcode = OpCode.CloseHttpHandlers+WebSockets.swift:135 case 0x09: frm.opcode = OpCode.PingHttpHandlers+WebSockets.swift:136 case 0x0A: frm.opcode = OpCode.Pong, Close
HttpHandlers+WebSockets.swift:91 case .Continue : encodedByte |= 0x00 & 0x0F;HttpHandlers+WebSockets.swift:131 case 0x00: frm.opcode = OpCode.Continue, Ping
HttpHandlers+WebSockets.swift:53 public var opcode = OpCode.CloseHttpHandlers+WebSockets.swift:94 case .Close : encodedByte |= 0x08 & 0x0F;HttpHandlers+WebSockets.swift:134 case 0x08: frm.opcode = OpCode.Close, Pong
HttpHandlers+WebSockets.swift:95 case .Ping : encodedByte |= 0x09 & 0x0F;HttpHandlers+WebSockets.swift:135 case 0x09: frm.opcode = OpCode.Ping, Text
HttpHandlers+WebSockets.swift:96 case .Pong : encodedByte |= 0x0A & 0x0F;HttpHandlers+WebSockets.swift:136 case 0x0A: frm.opcode = OpCode.Pong, Binary
HttpHandlers+WebSockets.swift:29 case .Text:HttpHandlers+WebSockets.swift:65 self.writeFrame(ArraySlice(text.utf8), OpCode.Text)HttpHandlers+WebSockets.swift:92 case .Text : encodedByte |= 0x01 & 0x0F;HttpHandlers+WebSockets.swift:132 case 0x01: frm.opcode = OpCode.Text} 0051 0052 public class Frame
HttpHandlers+WebSockets.swift:33 case .Binary:HttpHandlers+WebSockets.swift:73 self.writeFrame(binary, OpCode.Binary)HttpHandlers+WebSockets.swift:93 case .Binary : encodedByte |= 0x02 & 0x0F;HttpHandlers+WebSockets.swift:133 case 0x02: frm.opcode = OpCode.Binary{ 0053 public var opcode
HttpHandlers+WebSockets.swift:125 public func readFrame() throws -> Frame {HttpHandlers+WebSockets.swift:126 let frm = Frame()= OpCode.Close 0054 public var fin
HttpHandlers+WebSockets.swift:28 switch frame.opcode {HttpHandlers+WebSockets.swift:131 case 0x00: frm.opcode = OpCode.ContinueHttpHandlers+WebSockets.swift:132 case 0x01: frm.opcode = OpCode.TextHttpHandlers+WebSockets.swift:133 case 0x02: frm.opcode = OpCode.BinaryHttpHandlers+WebSockets.swift:134 case 0x08: frm.opcode = OpCode.CloseHttpHandlers+WebSockets.swift:135 case 0x09: frm.opcode = OpCode.PingHttpHandlers+WebSockets.swift:136 case 0x0A: frm.opcode = OpCode.Pong= false 0055 public var payload
HttpHandlers+WebSockets.swift:128 frm.fin = fst & 0x80 != 0= [UInt8]() 0056 } 0057 0058 private let socket
HttpHandlers+WebSockets.swift:31 handleText(session, String.fromUInt8(frame.payload))HttpHandlers+WebSockets.swift:35 handleBinary(session, frame.payload)HttpHandlers+WebSockets.swift:166 frm.payload.append(try socket.read() ^ mask[Int(i % 4)]): Socket 0059 0060 public init
HttpHandlers+WebSockets.swift:61 self.socket = socketHttpHandlers+WebSockets.swift:80 try self.socket.writeUInt8([finAndOpCode])HttpHandlers+WebSockets.swift:81 try self.socket.writeUInt8(maskAndLngth)HttpHandlers+WebSockets.swift:82 try self.socket.writeUInt8(data)HttpHandlers+WebSockets.swift:127 let fst = try socket.read()HttpHandlers+WebSockets.swift:141 let sec = try socket.read()HttpHandlers+WebSockets.swift:150 let b0 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:151 let b1 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:154 let b0 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:155 let b1 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:156 let b2 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:157 let b3 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:158 let b4 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:159 let b5 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:160 let b6 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:161 let b7 = UInt64(try socket.read())HttpHandlers+WebSockets.swift:164 let mask = [try socket.read(), try socket.read(), try socket.read(), try socket.read()]HttpHandlers+WebSockets.swift:164 let mask = [try socket.read(), try socket.read(), try socket.read(), try socket.read()]HttpHandlers+WebSockets.swift:164 let mask = [try socket.read(), try socket.read(), try socket.read(), try socket.read()]HttpHandlers+WebSockets.swift:164 let mask = [try socket.read(), try socket.read(), try socket.read(), try socket.read()]HttpHandlers+WebSockets.swift:166 frm.payload.append(try socket.read() ^ mask[Int(i % 4)])(_ socket: Socket) { 0061 self.socket = socket 0062 } 0063 0064 public func writeText
HttpHandlers+WebSockets.swift:26 let session = WebSocketSession(socket)(text: String) -> Void { 0065 self.writeFrame(ArraySlice(text.utf8), OpCode.Text) 0066 } 0067 0068 public func writeBinary
DemoServer.swift:118 session.writeText(text)(binary: [UInt8]) -> Void { 0069 self.writeBinary(ArraySlice(binary)) 0070 } 0071 0072 public func writeBinary
DemoServer.swift:120 session.writeBinary(binary)(binary: ArraySlice<UInt8>) -> Void { 0073 self.writeFrame(binary, OpCode.Binary) 0074 } 0075 0076 private func writeFrame
HttpHandlers+WebSockets.swift:69 self.writeBinary(ArraySlice(binary))(data: ArraySlice<UInt8>, _ op: OpCode, _ fin: Bool = true) { 0077 let finAndOpCode = encodeFinAndOpCode(fin, op: op) 0078 let maskAndLngth = encodeLengthAndMaskFlag(UInt64(data.count), false) 0079 do { 0080 try self.socket.writeUInt8([finAndOpCode]) 0081 try self.socket.writeUInt8(maskAndLngth) 0082 try self.socket.writeUInt8(data) 0083 } catch { 0084 print(error) 0085 } 0086 } 0087 0088 private func encodeFinAndOpCode
HttpHandlers+WebSockets.swift:65 self.writeFrame(ArraySlice(text.utf8), OpCode.Text)HttpHandlers+WebSockets.swift:73 self.writeFrame(binary, OpCode.Binary)(fin: Bool, op: OpCode) -> UInt8 { 0089 var encodedByte = UInt8(fin ? 0x80 : 0x00); 0090 switch op { 0091 case .Continue : encodedByte |= 0x00 & 0x0F; 0092 case .Text : encodedByte |= 0x01 & 0x0F; 0093 case .Binary : encodedByte |= 0x02 & 0x0F; 0094 case .Close : encodedByte |= 0x08 & 0x0F; 0095 case .Ping : encodedByte |= 0x09 & 0x0F; 0096 case .Pong : encodedByte |= 0x0A & 0x0F; 0097 } 0098 return encodedByte 0099 } 0100 0101 private func encodeLengthAndMaskFlag
HttpHandlers+WebSockets.swift:77 let finAndOpCode = encodeFinAndOpCode(fin, op: op)(len: UInt64, _ masked: Bool) -> [UInt8] { 0102 let encodedLngth = UInt8(masked ? 0x80 : 0x00) 0103 var encodedBytes = [UInt8]() 0104 switch len { 0105 case 0...125: 0106 encodedBytes.append(encodedLngth | UInt8(len)); 0107 case 126...UInt64(UINT16_MAX): 0108 encodedBytes.append(encodedLngth | 0x7E); 0109 encodedBytes.append(UInt8(len >> 8)); 0110 encodedBytes.append(UInt8(len & 0xFF)); 0111 default: 0112 encodedBytes.append(encodedLngth | 0x7F); 0113 encodedBytes.append(UInt8(len >> 56) & 0xFF); 0114 encodedBytes.append(UInt8(len >> 48) & 0xFF); 0115 encodedBytes.append(UInt8(len >> 40) & 0xFF); 0116 encodedBytes.append(UInt8(len >> 32) & 0xFF); 0117 encodedBytes.append(UInt8(len >> 24) & 0xFF); 0118 encodedBytes.append(UInt8(len >> 16) & 0xFF); 0119 encodedBytes.append(UInt8(len >> 08) & 0xFF); 0120 encodedBytes.append(UInt8(len >> 00) & 0xFF); 0121 } 0122 return encodedBytes 0123 } 0124 0125 public func readFrame
HttpHandlers+WebSockets.swift:78 let maskAndLngth = encodeLengthAndMaskFlag(UInt64(data.count), false)() throws -> Frame { 0126 let frm = Frame() 0127 let fst = try socket.read() 0128 frm.fin = fst & 0x80 != 0 0129 let opc = fst & 0x0F 0130 switch opc { 0131 case 0x00: frm.opcode = OpCode.Continue 0132 case 0x01: frm.opcode = OpCode.Text 0133 case 0x02: frm.opcode = OpCode.Binary 0134 case 0x08: frm.opcode = OpCode.Close 0135 case 0x09: frm.opcode = OpCode.Ping 0136 case 0x0A: frm.opcode = OpCode.Pong 0137 // "If an unknown opcode is received, the receiving endpoint MUST _Fail the WebSocket Connection_." 0138 // http://tools.ietf.org/html/rfc6455#section-5.2 ( Page 29 ) 0139 default : throw Error.UnknownOpCode("\(opc)") 0140 } 0141 let sec = try socket.read() 0142 let msk = sec & 0x80 != 0 0143 guard msk else { 0144 // "...a client MUST mask all frames that it sends to the serve.." 0145 // http://tools.ietf.org/html/rfc6455#section-5.1 0146 throw Error.UnMaskedFrame 0147 } 0148 var len = UInt64(sec & 0x7F) 0149 if len == 0x7E { 0150 let b0 = UInt64(try socket.read()) 0151 let b1 = UInt64(try socket.read()) 0152 len = UInt64(littleEndian: b0 << 8 | b1) 0153 } else if len == 0x7F { 0154 let b0 = UInt64(try socket.read()) 0155 let b1 = UInt64(try socket.read()) 0156 let b2 = UInt64(try socket.read()) 0157 let b3 = UInt64(try socket.read()) 0158 let b4 = UInt64(try socket.read()) 0159 let b5 = UInt64(try socket.read()) 0160 let b6 = UInt64(try socket.read()) 0161 let b7 = UInt64(try socket.read()) 0162 len = UInt64(littleEndian: b0 << 54 | b1 << 48 | b2 << 40 | b3 << 32 | b4 << 24 | b5 << 16 | b6 << 8 | b7) 0163 } 0164 let mask = [try socket.read(), try socket.read(), try socket.read(), try socket.read()] 0165 for i in 0..<len { 0166 frm.payload.append(try socket.read() ^ mask[Int(i % 4)]) 0167 } 0168 return frm 0169 } 0170 } 0171 }
HttpHandlers+WebSockets.swift:27 while let frame = try? session.readFrame() {