You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

583 lines
16 KiB

  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package websocket
  5. // This file implements a protocol of hybi draft.
  6. // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
  7. import (
  8. "bufio"
  9. "bytes"
  10. "crypto/rand"
  11. "crypto/sha1"
  12. "encoding/base64"
  13. "encoding/binary"
  14. "fmt"
  15. "io"
  16. "io/ioutil"
  17. "net/http"
  18. "net/url"
  19. "strings"
  20. )
  21. const (
  22. websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
  23. closeStatusNormal = 1000
  24. closeStatusGoingAway = 1001
  25. closeStatusProtocolError = 1002
  26. closeStatusUnsupportedData = 1003
  27. closeStatusFrameTooLarge = 1004
  28. closeStatusNoStatusRcvd = 1005
  29. closeStatusAbnormalClosure = 1006
  30. closeStatusBadMessageData = 1007
  31. closeStatusPolicyViolation = 1008
  32. closeStatusTooBigData = 1009
  33. closeStatusExtensionMismatch = 1010
  34. maxControlFramePayloadLength = 125
  35. )
  36. var (
  37. ErrBadMaskingKey = &ProtocolError{"bad masking key"}
  38. ErrBadPongMessage = &ProtocolError{"bad pong message"}
  39. ErrBadClosingStatus = &ProtocolError{"bad closing status"}
  40. ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
  41. ErrNotImplemented = &ProtocolError{"not implemented"}
  42. handshakeHeader = map[string]bool{
  43. "Host": true,
  44. "Upgrade": true,
  45. "Connection": true,
  46. "Sec-Websocket-Key": true,
  47. "Sec-Websocket-Origin": true,
  48. "Sec-Websocket-Version": true,
  49. "Sec-Websocket-Protocol": true,
  50. "Sec-Websocket-Accept": true,
  51. }
  52. )
  53. // A hybiFrameHeader is a frame header as defined in hybi draft.
  54. type hybiFrameHeader struct {
  55. Fin bool
  56. Rsv [3]bool
  57. OpCode byte
  58. Length int64
  59. MaskingKey []byte
  60. data *bytes.Buffer
  61. }
  62. // A hybiFrameReader is a reader for hybi frame.
  63. type hybiFrameReader struct {
  64. reader io.Reader
  65. header hybiFrameHeader
  66. pos int64
  67. length int
  68. }
  69. func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
  70. n, err = frame.reader.Read(msg)
  71. if frame.header.MaskingKey != nil {
  72. for i := 0; i < n; i++ {
  73. msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
  74. frame.pos++
  75. }
  76. }
  77. return n, err
  78. }
  79. func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
  80. func (frame *hybiFrameReader) HeaderReader() io.Reader {
  81. if frame.header.data == nil {
  82. return nil
  83. }
  84. if frame.header.data.Len() == 0 {
  85. return nil
  86. }
  87. return frame.header.data
  88. }
  89. func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
  90. func (frame *hybiFrameReader) Len() (n int) { return frame.length }
  91. // A hybiFrameReaderFactory creates new frame reader based on its frame type.
  92. type hybiFrameReaderFactory struct {
  93. *bufio.Reader
  94. }
  95. // NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
  96. // See Section 5.2 Base Framing protocol for detail.
  97. // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
  98. func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
  99. hybiFrame := new(hybiFrameReader)
  100. frame = hybiFrame
  101. var header []byte
  102. var b byte
  103. // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
  104. b, err = buf.ReadByte()
  105. if err != nil {
  106. return
  107. }
  108. header = append(header, b)
  109. hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
  110. for i := 0; i < 3; i++ {
  111. j := uint(6 - i)
  112. hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
  113. }
  114. hybiFrame.header.OpCode = header[0] & 0x0f
  115. // Second byte. Mask/Payload len(7bits)
  116. b, err = buf.ReadByte()
  117. if err != nil {
  118. return
  119. }
  120. header = append(header, b)
  121. mask := (b & 0x80) != 0
  122. b &= 0x7f
  123. lengthFields := 0
  124. switch {
  125. case b <= 125: // Payload length 7bits.
  126. hybiFrame.header.Length = int64(b)
  127. case b == 126: // Payload length 7+16bits
  128. lengthFields = 2
  129. case b == 127: // Payload length 7+64bits
  130. lengthFields = 8
  131. }
  132. for i := 0; i < lengthFields; i++ {
  133. b, err = buf.ReadByte()
  134. if err != nil {
  135. return
  136. }
  137. if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits
  138. b &= 0x7f
  139. }
  140. header = append(header, b)
  141. hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
  142. }
  143. if mask {
  144. // Masking key. 4 bytes.
  145. for i := 0; i < 4; i++ {
  146. b, err = buf.ReadByte()
  147. if err != nil {
  148. return
  149. }
  150. header = append(header, b)
  151. hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
  152. }
  153. }
  154. hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
  155. hybiFrame.header.data = bytes.NewBuffer(header)
  156. hybiFrame.length = len(header) + int(hybiFrame.header.Length)
  157. return
  158. }
  159. // A HybiFrameWriter is a writer for hybi frame.
  160. type hybiFrameWriter struct {
  161. writer *bufio.Writer
  162. header *hybiFrameHeader
  163. }
  164. func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
  165. var header []byte
  166. var b byte
  167. if frame.header.Fin {
  168. b |= 0x80
  169. }
  170. for i := 0; i < 3; i++ {
  171. if frame.header.Rsv[i] {
  172. j := uint(6 - i)
  173. b |= 1 << j
  174. }
  175. }
  176. b |= frame.header.OpCode
  177. header = append(header, b)
  178. if frame.header.MaskingKey != nil {
  179. b = 0x80
  180. } else {
  181. b = 0
  182. }
  183. lengthFields := 0
  184. length := len(msg)
  185. switch {
  186. case length <= 125:
  187. b |= byte(length)
  188. case length < 65536:
  189. b |= 126
  190. lengthFields = 2
  191. default:
  192. b |= 127
  193. lengthFields = 8
  194. }
  195. header = append(header, b)
  196. for i := 0; i < lengthFields; i++ {
  197. j := uint((lengthFields - i - 1) * 8)
  198. b = byte((length >> j) & 0xff)
  199. header = append(header, b)
  200. }
  201. if frame.header.MaskingKey != nil {
  202. if len(frame.header.MaskingKey) != 4 {
  203. return 0, ErrBadMaskingKey
  204. }
  205. header = append(header, frame.header.MaskingKey...)
  206. frame.writer.Write(header)
  207. data := make([]byte, length)
  208. for i := range data {
  209. data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
  210. }
  211. frame.writer.Write(data)
  212. err = frame.writer.Flush()
  213. return length, err
  214. }
  215. frame.writer.Write(header)
  216. frame.writer.Write(msg)
  217. err = frame.writer.Flush()
  218. return length, err
  219. }
  220. func (frame *hybiFrameWriter) Close() error { return nil }
  221. type hybiFrameWriterFactory struct {
  222. *bufio.Writer
  223. needMaskingKey bool
  224. }
  225. func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
  226. frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
  227. if buf.needMaskingKey {
  228. frameHeader.MaskingKey, err = generateMaskingKey()
  229. if err != nil {
  230. return nil, err
  231. }
  232. }
  233. return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
  234. }
  235. type hybiFrameHandler struct {
  236. conn *Conn
  237. payloadType byte
  238. }
  239. func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) {
  240. if handler.conn.IsServerConn() {
  241. // The client MUST mask all frames sent to the server.
  242. if frame.(*hybiFrameReader).header.MaskingKey == nil {
  243. handler.WriteClose(closeStatusProtocolError)
  244. return nil, io.EOF
  245. }
  246. } else {
  247. // The server MUST NOT mask all frames.
  248. if frame.(*hybiFrameReader).header.MaskingKey != nil {
  249. handler.WriteClose(closeStatusProtocolError)
  250. return nil, io.EOF
  251. }
  252. }
  253. if header := frame.HeaderReader(); header != nil {
  254. io.Copy(ioutil.Discard, header)
  255. }
  256. switch frame.PayloadType() {
  257. case ContinuationFrame:
  258. frame.(*hybiFrameReader).header.OpCode = handler.payloadType
  259. case TextFrame, BinaryFrame:
  260. handler.payloadType = frame.PayloadType()
  261. case CloseFrame:
  262. return nil, io.EOF
  263. case PingFrame, PongFrame:
  264. b := make([]byte, maxControlFramePayloadLength)
  265. n, err := io.ReadFull(frame, b)
  266. if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
  267. return nil, err
  268. }
  269. io.Copy(ioutil.Discard, frame)
  270. if frame.PayloadType() == PingFrame {
  271. if _, err := handler.WritePong(b[:n]); err != nil {
  272. return nil, err
  273. }
  274. }
  275. return nil, nil
  276. }
  277. return frame, nil
  278. }
  279. func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
  280. handler.conn.wio.Lock()
  281. defer handler.conn.wio.Unlock()
  282. w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
  283. if err != nil {
  284. return err
  285. }
  286. msg := make([]byte, 2)
  287. binary.BigEndian.PutUint16(msg, uint16(status))
  288. _, err = w.Write(msg)
  289. w.Close()
  290. return err
  291. }
  292. func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
  293. handler.conn.wio.Lock()
  294. defer handler.conn.wio.Unlock()
  295. w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
  296. if err != nil {
  297. return 0, err
  298. }
  299. n, err = w.Write(msg)
  300. w.Close()
  301. return n, err
  302. }
  303. // newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
  304. func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  305. if buf == nil {
  306. br := bufio.NewReader(rwc)
  307. bw := bufio.NewWriter(rwc)
  308. buf = bufio.NewReadWriter(br, bw)
  309. }
  310. ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
  311. frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
  312. frameWriterFactory: hybiFrameWriterFactory{
  313. buf.Writer, request == nil},
  314. PayloadType: TextFrame,
  315. defaultCloseStatus: closeStatusNormal}
  316. ws.frameHandler = &hybiFrameHandler{conn: ws}
  317. return ws
  318. }
  319. // generateMaskingKey generates a masking key for a frame.
  320. func generateMaskingKey() (maskingKey []byte, err error) {
  321. maskingKey = make([]byte, 4)
  322. if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
  323. return
  324. }
  325. return
  326. }
  327. // generateNonce generates a nonce consisting of a randomly selected 16-byte
  328. // value that has been base64-encoded.
  329. func generateNonce() (nonce []byte) {
  330. key := make([]byte, 16)
  331. if _, err := io.ReadFull(rand.Reader, key); err != nil {
  332. panic(err)
  333. }
  334. nonce = make([]byte, 24)
  335. base64.StdEncoding.Encode(nonce, key)
  336. return
  337. }
  338. // removeZone removes IPv6 zone identifer from host.
  339. // E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
  340. func removeZone(host string) string {
  341. if !strings.HasPrefix(host, "[") {
  342. return host
  343. }
  344. i := strings.LastIndex(host, "]")
  345. if i < 0 {
  346. return host
  347. }
  348. j := strings.LastIndex(host[:i], "%")
  349. if j < 0 {
  350. return host
  351. }
  352. return host[:j] + host[i:]
  353. }
  354. // getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
  355. // the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
  356. func getNonceAccept(nonce []byte) (expected []byte, err error) {
  357. h := sha1.New()
  358. if _, err = h.Write(nonce); err != nil {
  359. return
  360. }
  361. if _, err = h.Write([]byte(websocketGUID)); err != nil {
  362. return
  363. }
  364. expected = make([]byte, 28)
  365. base64.StdEncoding.Encode(expected, h.Sum(nil))
  366. return
  367. }
  368. // Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
  369. func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
  370. bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
  371. // According to RFC 6874, an HTTP client, proxy, or other
  372. // intermediary must remove any IPv6 zone identifier attached
  373. // to an outgoing URI.
  374. bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n")
  375. bw.WriteString("Upgrade: websocket\r\n")
  376. bw.WriteString("Connection: Upgrade\r\n")
  377. nonce := generateNonce()
  378. if config.handshakeData != nil {
  379. nonce = []byte(config.handshakeData["key"])
  380. }
  381. bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
  382. bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
  383. if config.Version != ProtocolVersionHybi13 {
  384. return ErrBadProtocolVersion
  385. }
  386. bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
  387. if len(config.Protocol) > 0 {
  388. bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
  389. }
  390. // TODO(ukai): send Sec-WebSocket-Extensions.
  391. err = config.Header.WriteSubset(bw, handshakeHeader)
  392. if err != nil {
  393. return err
  394. }
  395. bw.WriteString("\r\n")
  396. if err = bw.Flush(); err != nil {
  397. return err
  398. }
  399. resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
  400. if err != nil {
  401. return err
  402. }
  403. if resp.StatusCode != 101 {
  404. return ErrBadStatus
  405. }
  406. if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
  407. strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
  408. return ErrBadUpgrade
  409. }
  410. expectedAccept, err := getNonceAccept(nonce)
  411. if err != nil {
  412. return err
  413. }
  414. if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
  415. return ErrChallengeResponse
  416. }
  417. if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
  418. return ErrUnsupportedExtensions
  419. }
  420. offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
  421. if offeredProtocol != "" {
  422. protocolMatched := false
  423. for i := 0; i < len(config.Protocol); i++ {
  424. if config.Protocol[i] == offeredProtocol {
  425. protocolMatched = true
  426. break
  427. }
  428. }
  429. if !protocolMatched {
  430. return ErrBadWebSocketProtocol
  431. }
  432. config.Protocol = []string{offeredProtocol}
  433. }
  434. return nil
  435. }
  436. // newHybiClientConn creates a client WebSocket connection after handshake.
  437. func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
  438. return newHybiConn(config, buf, rwc, nil)
  439. }
  440. // A HybiServerHandshaker performs a server handshake using hybi draft protocol.
  441. type hybiServerHandshaker struct {
  442. *Config
  443. accept []byte
  444. }
  445. func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
  446. c.Version = ProtocolVersionHybi13
  447. if req.Method != "GET" {
  448. return http.StatusMethodNotAllowed, ErrBadRequestMethod
  449. }
  450. // HTTP version can be safely ignored.
  451. if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
  452. !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
  453. return http.StatusBadRequest, ErrNotWebSocket
  454. }
  455. key := req.Header.Get("Sec-Websocket-Key")
  456. if key == "" {
  457. return http.StatusBadRequest, ErrChallengeResponse
  458. }
  459. version := req.Header.Get("Sec-Websocket-Version")
  460. switch version {
  461. case "13":
  462. c.Version = ProtocolVersionHybi13
  463. default:
  464. return http.StatusBadRequest, ErrBadWebSocketVersion
  465. }
  466. var scheme string
  467. if req.TLS != nil {
  468. scheme = "wss"
  469. } else {
  470. scheme = "ws"
  471. }
  472. c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
  473. if err != nil {
  474. return http.StatusBadRequest, err
  475. }
  476. protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
  477. if protocol != "" {
  478. protocols := strings.Split(protocol, ",")
  479. for i := 0; i < len(protocols); i++ {
  480. c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
  481. }
  482. }
  483. c.accept, err = getNonceAccept([]byte(key))
  484. if err != nil {
  485. return http.StatusInternalServerError, err
  486. }
  487. return http.StatusSwitchingProtocols, nil
  488. }
  489. // Origin parses the Origin header in req.
  490. // If the Origin header is not set, it returns nil and nil.
  491. func Origin(config *Config, req *http.Request) (*url.URL, error) {
  492. var origin string
  493. switch config.Version {
  494. case ProtocolVersionHybi13:
  495. origin = req.Header.Get("Origin")
  496. }
  497. if origin == "" {
  498. return nil, nil
  499. }
  500. return url.ParseRequestURI(origin)
  501. }
  502. func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
  503. if len(c.Protocol) > 0 {
  504. if len(c.Protocol) != 1 {
  505. // You need choose a Protocol in Handshake func in Server.
  506. return ErrBadWebSocketProtocol
  507. }
  508. }
  509. buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
  510. buf.WriteString("Upgrade: websocket\r\n")
  511. buf.WriteString("Connection: Upgrade\r\n")
  512. buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
  513. if len(c.Protocol) > 0 {
  514. buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
  515. }
  516. // TODO(ukai): send Sec-WebSocket-Extensions.
  517. if c.Header != nil {
  518. err := c.Header.WriteSubset(buf, handshakeHeader)
  519. if err != nil {
  520. return err
  521. }
  522. }
  523. buf.WriteString("\r\n")
  524. return buf.Flush()
  525. }
  526. func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  527. return newHybiServerConn(c.Config, buf, rwc, request)
  528. }
  529. // newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
  530. func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  531. return newHybiConn(config, buf, rwc, request)
  532. }