hybi.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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 err != nil {
  72. return 0, err
  73. }
  74. if frame.header.MaskingKey != nil {
  75. for i := 0; i < n; i++ {
  76. msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
  77. frame.pos++
  78. }
  79. }
  80. return n, err
  81. }
  82. func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
  83. func (frame *hybiFrameReader) HeaderReader() io.Reader {
  84. if frame.header.data == nil {
  85. return nil
  86. }
  87. if frame.header.data.Len() == 0 {
  88. return nil
  89. }
  90. return frame.header.data
  91. }
  92. func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
  93. func (frame *hybiFrameReader) Len() (n int) { return frame.length }
  94. // A hybiFrameReaderFactory creates new frame reader based on its frame type.
  95. type hybiFrameReaderFactory struct {
  96. *bufio.Reader
  97. }
  98. // NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
  99. // See Section 5.2 Base Framing protocol for detail.
  100. // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
  101. func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
  102. hybiFrame := new(hybiFrameReader)
  103. frame = hybiFrame
  104. var header []byte
  105. var b byte
  106. // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
  107. b, err = buf.ReadByte()
  108. if err != nil {
  109. return
  110. }
  111. header = append(header, b)
  112. hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
  113. for i := 0; i < 3; i++ {
  114. j := uint(6 - i)
  115. hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
  116. }
  117. hybiFrame.header.OpCode = header[0] & 0x0f
  118. // Second byte. Mask/Payload len(7bits)
  119. b, err = buf.ReadByte()
  120. if err != nil {
  121. return
  122. }
  123. header = append(header, b)
  124. mask := (b & 0x80) != 0
  125. b &= 0x7f
  126. lengthFields := 0
  127. switch {
  128. case b <= 125: // Payload length 7bits.
  129. hybiFrame.header.Length = int64(b)
  130. case b == 126: // Payload length 7+16bits
  131. lengthFields = 2
  132. case b == 127: // Payload length 7+64bits
  133. lengthFields = 8
  134. }
  135. for i := 0; i < lengthFields; i++ {
  136. b, err = buf.ReadByte()
  137. if err != nil {
  138. return
  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) (r frameReader, err 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:
  264. pingMsg := make([]byte, maxControlFramePayloadLength)
  265. n, err := io.ReadFull(frame, pingMsg)
  266. if err != nil && err != io.ErrUnexpectedEOF {
  267. return nil, err
  268. }
  269. io.Copy(ioutil.Discard, frame)
  270. n, err = handler.WritePong(pingMsg[:n])
  271. if err != nil {
  272. return nil, err
  273. }
  274. return nil, nil
  275. case PongFrame:
  276. return nil, ErrNotImplemented
  277. }
  278. return frame, nil
  279. }
  280. func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
  281. handler.conn.wio.Lock()
  282. defer handler.conn.wio.Unlock()
  283. w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
  284. if err != nil {
  285. return err
  286. }
  287. msg := make([]byte, 2)
  288. binary.BigEndian.PutUint16(msg, uint16(status))
  289. _, err = w.Write(msg)
  290. w.Close()
  291. return err
  292. }
  293. func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
  294. handler.conn.wio.Lock()
  295. defer handler.conn.wio.Unlock()
  296. w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
  297. if err != nil {
  298. return 0, err
  299. }
  300. n, err = w.Write(msg)
  301. w.Close()
  302. return n, err
  303. }
  304. // newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
  305. func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  306. if buf == nil {
  307. br := bufio.NewReader(rwc)
  308. bw := bufio.NewWriter(rwc)
  309. buf = bufio.NewReadWriter(br, bw)
  310. }
  311. ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
  312. frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
  313. frameWriterFactory: hybiFrameWriterFactory{
  314. buf.Writer, request == nil},
  315. PayloadType: TextFrame,
  316. defaultCloseStatus: closeStatusNormal}
  317. ws.frameHandler = &hybiFrameHandler{conn: ws}
  318. return ws
  319. }
  320. // generateMaskingKey generates a masking key for a frame.
  321. func generateMaskingKey() (maskingKey []byte, err error) {
  322. maskingKey = make([]byte, 4)
  323. if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
  324. return
  325. }
  326. return
  327. }
  328. // generateNonce generates a nonce consisting of a randomly selected 16-byte
  329. // value that has been base64-encoded.
  330. func generateNonce() (nonce []byte) {
  331. key := make([]byte, 16)
  332. if _, err := io.ReadFull(rand.Reader, key); err != nil {
  333. panic(err)
  334. }
  335. nonce = make([]byte, 24)
  336. base64.StdEncoding.Encode(nonce, key)
  337. return
  338. }
  339. // getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
  340. // the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
  341. func getNonceAccept(nonce []byte) (expected []byte, err error) {
  342. h := sha1.New()
  343. if _, err = h.Write(nonce); err != nil {
  344. return
  345. }
  346. if _, err = h.Write([]byte(websocketGUID)); err != nil {
  347. return
  348. }
  349. expected = make([]byte, 28)
  350. base64.StdEncoding.Encode(expected, h.Sum(nil))
  351. return
  352. }
  353. // Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
  354. func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
  355. bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
  356. bw.WriteString("Host: " + config.Location.Host + "\r\n")
  357. bw.WriteString("Upgrade: websocket\r\n")
  358. bw.WriteString("Connection: Upgrade\r\n")
  359. nonce := generateNonce()
  360. if config.handshakeData != nil {
  361. nonce = []byte(config.handshakeData["key"])
  362. }
  363. bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
  364. bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
  365. if config.Version != ProtocolVersionHybi13 {
  366. return ErrBadProtocolVersion
  367. }
  368. bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
  369. if len(config.Protocol) > 0 {
  370. bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
  371. }
  372. // TODO(ukai): send Sec-WebSocket-Extensions.
  373. err = config.Header.WriteSubset(bw, handshakeHeader)
  374. if err != nil {
  375. return err
  376. }
  377. bw.WriteString("\r\n")
  378. if err = bw.Flush(); err != nil {
  379. return err
  380. }
  381. resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
  382. if err != nil {
  383. return err
  384. }
  385. if resp.StatusCode != 101 {
  386. return ErrBadStatus
  387. }
  388. if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
  389. strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
  390. return ErrBadUpgrade
  391. }
  392. expectedAccept, err := getNonceAccept(nonce)
  393. if err != nil {
  394. return err
  395. }
  396. if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
  397. return ErrChallengeResponse
  398. }
  399. if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
  400. return ErrUnsupportedExtensions
  401. }
  402. offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
  403. if offeredProtocol != "" {
  404. protocolMatched := false
  405. for i := 0; i < len(config.Protocol); i++ {
  406. if config.Protocol[i] == offeredProtocol {
  407. protocolMatched = true
  408. break
  409. }
  410. }
  411. if !protocolMatched {
  412. return ErrBadWebSocketProtocol
  413. }
  414. config.Protocol = []string{offeredProtocol}
  415. }
  416. return nil
  417. }
  418. // newHybiClientConn creates a client WebSocket connection after handshake.
  419. func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
  420. return newHybiConn(config, buf, rwc, nil)
  421. }
  422. // A HybiServerHandshaker performs a server handshake using hybi draft protocol.
  423. type hybiServerHandshaker struct {
  424. *Config
  425. accept []byte
  426. }
  427. func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
  428. c.Version = ProtocolVersionHybi13
  429. if req.Method != "GET" {
  430. return http.StatusMethodNotAllowed, ErrBadRequestMethod
  431. }
  432. // HTTP version can be safely ignored.
  433. if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
  434. !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
  435. return http.StatusBadRequest, ErrNotWebSocket
  436. }
  437. key := req.Header.Get("Sec-Websocket-Key")
  438. if key == "" {
  439. return http.StatusBadRequest, ErrChallengeResponse
  440. }
  441. version := req.Header.Get("Sec-Websocket-Version")
  442. switch version {
  443. case "13":
  444. c.Version = ProtocolVersionHybi13
  445. default:
  446. return http.StatusBadRequest, ErrBadWebSocketVersion
  447. }
  448. var scheme string
  449. if req.TLS != nil {
  450. scheme = "wss"
  451. } else {
  452. scheme = "ws"
  453. }
  454. c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
  455. if err != nil {
  456. return http.StatusBadRequest, err
  457. }
  458. protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
  459. if protocol != "" {
  460. protocols := strings.Split(protocol, ",")
  461. for i := 0; i < len(protocols); i++ {
  462. c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
  463. }
  464. }
  465. c.accept, err = getNonceAccept([]byte(key))
  466. if err != nil {
  467. return http.StatusInternalServerError, err
  468. }
  469. return http.StatusSwitchingProtocols, nil
  470. }
  471. // Origin parses Origin header in "req".
  472. // If origin is "null", returns (nil, nil).
  473. func Origin(config *Config, req *http.Request) (*url.URL, error) {
  474. var origin string
  475. switch config.Version {
  476. case ProtocolVersionHybi13:
  477. origin = req.Header.Get("Origin")
  478. }
  479. if origin == "null" {
  480. return nil, nil
  481. }
  482. return url.ParseRequestURI(origin)
  483. }
  484. func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
  485. if len(c.Protocol) > 0 {
  486. if len(c.Protocol) != 1 {
  487. // You need choose a Protocol in Handshake func in Server.
  488. return ErrBadWebSocketProtocol
  489. }
  490. }
  491. buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
  492. buf.WriteString("Upgrade: websocket\r\n")
  493. buf.WriteString("Connection: Upgrade\r\n")
  494. buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
  495. if len(c.Protocol) > 0 {
  496. buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
  497. }
  498. // TODO(ukai): send Sec-WebSocket-Extensions.
  499. if c.Header != nil {
  500. err := c.Header.WriteSubset(buf, handshakeHeader)
  501. if err != nil {
  502. return err
  503. }
  504. }
  505. buf.WriteString("\r\n")
  506. return buf.Flush()
  507. }
  508. func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  509. return newHybiServerConn(c.Config, buf, rwc, request)
  510. }
  511. // newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
  512. func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  513. return newHybiConn(config, buf, rwc, request)
  514. }