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
DemoServer.swift:117
    server["/websocket-echo"] = HttpHandlers.websocket({ (session, text) in
( 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
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)
{ 0048 0049 public enum Error
HttpHandlers+WebSockets.swift:139
                default  : throw Error.UnknownOpCode("\(opc)")
HttpHandlers+WebSockets.swift:146
                throw Error.UnMaskedFrame
: ErrorType { case UnknownOpCode
HttpHandlers+WebSockets.swift:139
                default  : throw Error.UnknownOpCode("\(opc)")
(String), UnMaskedFrame
HttpHandlers+WebSockets.swift:146
                throw Error.UnMaskedFrame
} 0050 public enum OpCode
HttpHandlers+WebSockets.swift:53
            public var opcode = OpCode.Close
HttpHandlers+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.Continue
HttpHandlers+WebSockets.swift:132
                case 0x01: frm.opcode = OpCode.Text
HttpHandlers+WebSockets.swift:133
                case 0x02: frm.opcode = OpCode.Binary
HttpHandlers+WebSockets.swift:134
                case 0x08: frm.opcode = OpCode.Close
HttpHandlers+WebSockets.swift:135
                case 0x09: frm.opcode = OpCode.Ping
HttpHandlers+WebSockets.swift:136
                case 0x0A: frm.opcode = OpCode.Pong
{ case Continue
HttpHandlers+WebSockets.swift:91
            case .Continue : encodedByte |= 0x00 & 0x0F;
HttpHandlers+WebSockets.swift:131
                case 0x00: frm.opcode = OpCode.Continue
, Close
HttpHandlers+WebSockets.swift:53
            public var opcode = OpCode.Close
HttpHandlers+WebSockets.swift:94
            case .Close    : encodedByte |= 0x08 & 0x0F;
HttpHandlers+WebSockets.swift:134
                case 0x08: frm.opcode = OpCode.Close
, Ping
HttpHandlers+WebSockets.swift:95
            case .Ping     : encodedByte |= 0x09 & 0x0F;
HttpHandlers+WebSockets.swift:135
                case 0x09: frm.opcode = OpCode.Ping
, Pong
HttpHandlers+WebSockets.swift:96
            case .Pong     : encodedByte |= 0x0A & 0x0F;
HttpHandlers+WebSockets.swift:136
                case 0x0A: frm.opcode = OpCode.Pong
, Text
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
, Binary
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
} 0051 0052 public class Frame
HttpHandlers+WebSockets.swift:125
        public func readFrame() throws -> Frame {
HttpHandlers+WebSockets.swift:126
            let frm = Frame()
{ 0053 public var opcode
HttpHandlers+WebSockets.swift:28
                    switch frame.opcode {
HttpHandlers+WebSockets.swift:131
                case 0x00: frm.opcode = OpCode.Continue
HttpHandlers+WebSockets.swift:132
                case 0x01: frm.opcode = OpCode.Text
HttpHandlers+WebSockets.swift:133
                case 0x02: frm.opcode = OpCode.Binary
HttpHandlers+WebSockets.swift:134
                case 0x08: frm.opcode = OpCode.Close
HttpHandlers+WebSockets.swift:135
                case 0x09: frm.opcode = OpCode.Ping
HttpHandlers+WebSockets.swift:136
                case 0x0A: frm.opcode = OpCode.Pong
= OpCode.Close 0054 public var fin
HttpHandlers+WebSockets.swift:128
            frm.fin = fst & 0x80 != 0
= false 0055 public var payload
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)])
= [UInt8]() 0056 } 0057 0058 private let socket
HttpHandlers+WebSockets.swift:61
            self.socket = socket
HttpHandlers+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 0059 0060 public init
HttpHandlers+WebSockets.swift:26
                let session = WebSocketSession(socket)
(_ socket: Socket) { 0061 self.socket = socket 0062 } 0063 0064 public func writeText
DemoServer.swift:118
        session.writeText(text)
(text: String) -> Void { 0065 self.writeFrame(ArraySlice(text.utf8), OpCode.Text) 0066 } 0067 0068 public func writeBinary
DemoServer.swift:120
        session.writeBinary(binary)
(binary: [UInt8]) -> Void { 0069 self.writeBinary(ArraySlice(binary)) 0070 } 0071 0072 public func writeBinary
HttpHandlers+WebSockets.swift:69
            self.writeBinary(ArraySlice(binary))
(binary: ArraySlice<UInt8>) -> Void { 0073 self.writeFrame(binary, OpCode.Binary) 0074 } 0075 0076 private func writeFrame
HttpHandlers+WebSockets.swift:65
            self.writeFrame(ArraySlice(text.utf8), OpCode.Text)
HttpHandlers+WebSockets.swift:73
            self.writeFrame(binary, OpCode.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:77
            let finAndOpCode = encodeFinAndOpCode(fin, op: op)
(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:78
            let maskAndLngth = encodeLengthAndMaskFlag(UInt64(data.count), false)
(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:27
                while let frame = try? session.readFrame() {
() 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 }