hixie.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. // Copyright 2009 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 Hixie draft version 75 and 76
  6. // (draft 76 equals to hybi 00)
  7. import (
  8. "bufio"
  9. "bytes"
  10. "crypto/md5"
  11. "encoding/binary"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "math/rand"
  16. "net/http"
  17. "net/url"
  18. "strconv"
  19. "strings"
  20. )
  21. // An aray of characters to be randomly inserted to construct Sec-WebSocket-Key
  22. // value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
  23. // See Step 21 in Section 4.1 Opening handshake.
  24. // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
  25. var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
  26. func init() {
  27. i := 0
  28. for ch := byte(0x21); ch < 0x30; ch++ {
  29. secKeyRandomChars[i] = ch
  30. i++
  31. }
  32. for ch := byte(0x3a); ch < 0x7F; ch++ {
  33. secKeyRandomChars[i] = ch
  34. i++
  35. }
  36. }
  37. type byteReader interface {
  38. ReadByte() (byte, error)
  39. }
  40. // readHixieLength reads frame length for frame type 0x80-0xFF
  41. // as defined in Hixie draft.
  42. // See section 4.2 Data framing.
  43. // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
  44. func readHixieLength(r byteReader) (length int64, lengthFields []byte, err error) {
  45. for {
  46. c, err := r.ReadByte()
  47. if err != nil {
  48. return 0, nil, err
  49. }
  50. lengthFields = append(lengthFields, c)
  51. length = length*128 + int64(c&0x7f)
  52. if c&0x80 == 0 {
  53. break
  54. }
  55. }
  56. return
  57. }
  58. // A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
  59. // as defined in hixie draft.
  60. type hixieLengthFrameReader struct {
  61. reader io.Reader
  62. FrameType byte
  63. Length int64
  64. header *bytes.Buffer
  65. length int
  66. }
  67. func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err error) {
  68. return frame.reader.Read(msg)
  69. }
  70. func (frame *hixieLengthFrameReader) PayloadType() byte {
  71. if frame.FrameType == '\xff' && frame.Length == 0 {
  72. return CloseFrame
  73. }
  74. return UnknownFrame
  75. }
  76. func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
  77. if frame.header == nil {
  78. return nil
  79. }
  80. if frame.header.Len() == 0 {
  81. frame.header = nil
  82. return nil
  83. }
  84. return frame.header
  85. }
  86. func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
  87. func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
  88. // A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
  89. // as defined in hixie draft.
  90. type hixieSentinelFrameReader struct {
  91. reader *bufio.Reader
  92. FrameType byte
  93. header *bytes.Buffer
  94. data []byte
  95. seenTrailer bool
  96. trailer *bytes.Buffer
  97. }
  98. func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err error) {
  99. if len(frame.data) == 0 {
  100. if frame.seenTrailer {
  101. return 0, io.EOF
  102. }
  103. frame.data, err = frame.reader.ReadSlice('\xff')
  104. if err == nil {
  105. frame.seenTrailer = true
  106. frame.data = frame.data[:len(frame.data)-1] // trim \xff
  107. frame.trailer = bytes.NewBuffer([]byte{0xff})
  108. }
  109. }
  110. n = copy(msg, frame.data)
  111. frame.data = frame.data[n:]
  112. return n, err
  113. }
  114. func (frame *hixieSentinelFrameReader) PayloadType() byte {
  115. if frame.FrameType == 0 {
  116. return TextFrame
  117. }
  118. return UnknownFrame
  119. }
  120. func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
  121. if frame.header == nil {
  122. return nil
  123. }
  124. if frame.header.Len() == 0 {
  125. frame.header = nil
  126. return nil
  127. }
  128. return frame.header
  129. }
  130. func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
  131. if frame.trailer == nil {
  132. return nil
  133. }
  134. if frame.trailer.Len() == 0 {
  135. frame.trailer = nil
  136. return nil
  137. }
  138. return frame.trailer
  139. }
  140. func (frame *hixieSentinelFrameReader) Len() int { return -1 }
  141. // A HixieFrameReaderFactory creates new frame reader based on its frame type.
  142. type hixieFrameReaderFactory struct {
  143. *bufio.Reader
  144. }
  145. func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err error) {
  146. var header []byte
  147. var b byte
  148. b, err = buf.ReadByte()
  149. if err != nil {
  150. return
  151. }
  152. header = append(header, b)
  153. if b&0x80 == 0x80 {
  154. length, lengthFields, err := readHixieLength(buf.Reader)
  155. if err != nil {
  156. return nil, err
  157. }
  158. if length == 0 {
  159. return nil, io.EOF
  160. }
  161. header = append(header, lengthFields...)
  162. return &hixieLengthFrameReader{
  163. reader: io.LimitReader(buf.Reader, length),
  164. FrameType: b,
  165. Length: length,
  166. header: bytes.NewBuffer(header)}, err
  167. }
  168. return &hixieSentinelFrameReader{
  169. reader: buf.Reader,
  170. FrameType: b,
  171. header: bytes.NewBuffer(header)}, err
  172. }
  173. type hixiFrameWriter struct {
  174. writer *bufio.Writer
  175. }
  176. func (frame *hixiFrameWriter) Write(msg []byte) (n int, err error) {
  177. frame.writer.WriteByte(0)
  178. frame.writer.Write(msg)
  179. frame.writer.WriteByte(0xff)
  180. err = frame.writer.Flush()
  181. return len(msg), err
  182. }
  183. func (frame *hixiFrameWriter) Close() error { return nil }
  184. type hixiFrameWriterFactory struct {
  185. *bufio.Writer
  186. }
  187. func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
  188. if payloadType != TextFrame {
  189. return nil, ErrNotSupported
  190. }
  191. return &hixiFrameWriter{writer: buf.Writer}, nil
  192. }
  193. type hixiFrameHandler struct {
  194. conn *Conn
  195. }
  196. func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
  197. if header := frame.HeaderReader(); header != nil {
  198. io.Copy(ioutil.Discard, header)
  199. }
  200. if frame.PayloadType() != TextFrame {
  201. io.Copy(ioutil.Discard, frame)
  202. return nil, nil
  203. }
  204. return frame, nil
  205. }
  206. func (handler *hixiFrameHandler) WriteClose(_ int) (err error) {
  207. handler.conn.wio.Lock()
  208. defer handler.conn.wio.Unlock()
  209. closingFrame := []byte{'\xff', '\x00'}
  210. handler.conn.buf.Write(closingFrame)
  211. return handler.conn.buf.Flush()
  212. }
  213. // newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
  214. func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  215. if buf == nil {
  216. br := bufio.NewReader(rwc)
  217. bw := bufio.NewWriter(rwc)
  218. buf = bufio.NewReadWriter(br, bw)
  219. }
  220. ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
  221. frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
  222. frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
  223. PayloadType: TextFrame}
  224. ws.frameHandler = &hixiFrameHandler{ws}
  225. return ws
  226. }
  227. // getChallengeResponse computes the expected response from the
  228. // challenge as described in section 5.1 Opening Handshake steps 42 to
  229. // 43 of http://www.whatwg.org/specs/web-socket-protocol/
  230. func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err error) {
  231. // 41. Let /challenge/ be the concatenation of /number_1/, expressed
  232. // a big-endian 32 bit integer, /number_2/, expressed in a big-
  233. // endian 32 bit integer, and the eight bytes of /key_3/ in the
  234. // order they were sent to the wire.
  235. challenge := make([]byte, 16)
  236. binary.BigEndian.PutUint32(challenge[0:], number1)
  237. binary.BigEndian.PutUint32(challenge[4:], number2)
  238. copy(challenge[8:], key3)
  239. // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
  240. // endian 128 bit string.
  241. h := md5.New()
  242. if _, err = h.Write(challenge); err != nil {
  243. return
  244. }
  245. expected = h.Sum(nil)
  246. return
  247. }
  248. // Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
  249. // cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
  250. func generateKeyNumber() (key string, number uint32) {
  251. // 16. Let /spaces_n/ be a random integer from 1 to 12 inclusive.
  252. spaces := rand.Intn(12) + 1
  253. // 17. Let /max_n/ be the largest integer not greater than
  254. // 4,294,967,295 divided by /spaces_n/
  255. max := int(4294967295 / uint32(spaces))
  256. // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
  257. number = uint32(rand.Intn(max + 1))
  258. // 19. Let /product_n/ be the result of multiplying /number_n/ and
  259. // /spaces_n/ together.
  260. product := number * uint32(spaces)
  261. // 20. Let /key_n/ be a string consisting of /product_n/, expressed
  262. // in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
  263. // to U+0039 DIGIT NINE (9).
  264. key = fmt.Sprintf("%d", product)
  265. // 21. Insert between one and twelve random characters from the ranges
  266. // U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
  267. // positions.
  268. n := rand.Intn(12) + 1
  269. for i := 0; i < n; i++ {
  270. pos := rand.Intn(len(key)) + 1
  271. ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
  272. key = key[0:pos] + string(ch) + key[pos:]
  273. }
  274. // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
  275. // positions other than the start or end of the string.
  276. for i := 0; i < spaces; i++ {
  277. pos := rand.Intn(len(key)-1) + 1
  278. key = key[0:pos] + " " + key[pos:]
  279. }
  280. return
  281. }
  282. // Generates handshake key_3 as described in 4.1 Opening handshake step 26.
  283. // cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
  284. func generateKey3() (key []byte) {
  285. // 26. Let /key3/ be a string consisting of eight random bytes (or
  286. // equivalently, a random 64 bit integer encoded in big-endian order).
  287. key = make([]byte, 8)
  288. for i := 0; i < 8; i++ {
  289. key[i] = byte(rand.Intn(256))
  290. }
  291. return
  292. }
  293. // Cilent handhake described in (soon obsolete)
  294. // draft-ietf-hybi-thewebsocket-protocol-00
  295. // (draft-hixie-thewebsocket-protocol-76)
  296. func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
  297. switch config.Version {
  298. case ProtocolVersionHixie76, ProtocolVersionHybi00:
  299. default:
  300. panic("wrong protocol version.")
  301. }
  302. // 4.1. Opening handshake.
  303. // Step 5. send a request line.
  304. bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
  305. // Step 6-14. push request headers in fields.
  306. fields := []string{
  307. "Upgrade: WebSocket\r\n",
  308. "Connection: Upgrade\r\n",
  309. "Host: " + config.Location.Host + "\r\n",
  310. "Origin: " + config.Origin.String() + "\r\n",
  311. }
  312. if len(config.Protocol) > 0 {
  313. if len(config.Protocol) != 1 {
  314. return ErrBadWebSocketProtocol
  315. }
  316. fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n")
  317. }
  318. // TODO(ukai): Step 15. send cookie if any.
  319. // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
  320. key1, number1 := generateKeyNumber()
  321. key2, number2 := generateKeyNumber()
  322. if config.handshakeData != nil {
  323. key1 = config.handshakeData["key1"]
  324. n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32)
  325. if err != nil {
  326. panic(err)
  327. }
  328. number1 = uint32(n)
  329. key2 = config.handshakeData["key2"]
  330. n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32)
  331. if err != nil {
  332. panic(err)
  333. }
  334. number2 = uint32(n)
  335. }
  336. fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
  337. fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
  338. // Step 24. shuffle fields and send them out.
  339. for i := 1; i < len(fields); i++ {
  340. j := rand.Intn(i)
  341. fields[i], fields[j] = fields[j], fields[i]
  342. }
  343. for i := 0; i < len(fields); i++ {
  344. bw.WriteString(fields[i])
  345. }
  346. // Step 25. send CRLF.
  347. bw.WriteString("\r\n")
  348. // Step 26. generate 8 bytes random key.
  349. key3 := generateKey3()
  350. if config.handshakeData != nil {
  351. key3 = []byte(config.handshakeData["key3"])
  352. }
  353. // Step 27. send it out.
  354. bw.Write(key3)
  355. if err = bw.Flush(); err != nil {
  356. return
  357. }
  358. // Step 28-29, 32-40. read response from server.
  359. resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
  360. if err != nil {
  361. return err
  362. }
  363. // Step 30. check response code is 101.
  364. if resp.StatusCode != 101 {
  365. return ErrBadStatus
  366. }
  367. // Step 41. check websocket headers.
  368. if resp.Header.Get("Upgrade") != "WebSocket" ||
  369. strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
  370. return ErrBadUpgrade
  371. }
  372. if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
  373. return ErrBadWebSocketOrigin
  374. }
  375. if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
  376. return ErrBadWebSocketLocation
  377. }
  378. if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
  379. return ErrBadWebSocketProtocol
  380. }
  381. // Step 42-43. get expected data from challenge data.
  382. expected, err := getChallengeResponse(number1, number2, key3)
  383. if err != nil {
  384. return err
  385. }
  386. // Step 44. read 16 bytes from server.
  387. reply := make([]byte, 16)
  388. if _, err = io.ReadFull(br, reply); err != nil {
  389. return err
  390. }
  391. // Step 45. check the reply equals to expected data.
  392. if !bytes.Equal(expected, reply) {
  393. return ErrChallengeResponse
  394. }
  395. // WebSocket connection is established.
  396. return
  397. }
  398. // Client Handshake described in (soon obsolete)
  399. // draft-hixie-thewebsocket-protocol-75.
  400. func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
  401. if config.Version != ProtocolVersionHixie75 {
  402. panic("wrong protocol version.")
  403. }
  404. bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
  405. bw.WriteString("Upgrade: WebSocket\r\n")
  406. bw.WriteString("Connection: Upgrade\r\n")
  407. bw.WriteString("Host: " + config.Location.Host + "\r\n")
  408. bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
  409. if len(config.Protocol) > 0 {
  410. if len(config.Protocol) != 1 {
  411. return ErrBadWebSocketProtocol
  412. }
  413. bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
  414. }
  415. bw.WriteString("\r\n")
  416. bw.Flush()
  417. resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
  418. if err != nil {
  419. return
  420. }
  421. if resp.Status != "101 Web Socket Protocol Handshake" {
  422. return ErrBadStatus
  423. }
  424. if resp.Header.Get("Upgrade") != "WebSocket" ||
  425. resp.Header.Get("Connection") != "Upgrade" {
  426. return ErrBadUpgrade
  427. }
  428. if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
  429. return ErrBadWebSocketOrigin
  430. }
  431. if resp.Header.Get("Websocket-Location") != config.Location.String() {
  432. return ErrBadWebSocketLocation
  433. }
  434. if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
  435. return ErrBadWebSocketProtocol
  436. }
  437. return
  438. }
  439. // newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
  440. func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
  441. return newHixieConn(config, buf, rwc, nil)
  442. }
  443. // Gets key number from Sec-WebSocket-Key<n>: field as described
  444. // in 5.2 Sending the server's opening handshake, 4.
  445. func getKeyNumber(s string) (r uint32) {
  446. // 4. Let /key-number_n/ be the digits (characters in the range
  447. // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
  448. // interpreted as a base ten integer, ignoring all other characters
  449. // in /key_n/.
  450. r = 0
  451. for i := 0; i < len(s); i++ {
  452. if s[i] >= '0' && s[i] <= '9' {
  453. r = r*10 + uint32(s[i]) - '0'
  454. }
  455. }
  456. return
  457. }
  458. // A Hixie76ServerHandshaker performs a server handshake using
  459. // hixie draft 76 protocol.
  460. type hixie76ServerHandshaker struct {
  461. *Config
  462. challengeResponse []byte
  463. }
  464. func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
  465. c.Version = ProtocolVersionHybi00
  466. if req.Method != "GET" {
  467. return http.StatusMethodNotAllowed, ErrBadRequestMethod
  468. }
  469. // HTTP version can be safely ignored.
  470. if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
  471. strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
  472. return http.StatusBadRequest, ErrNotWebSocket
  473. }
  474. // TODO(ukai): check Host
  475. c.Origin, err = url.ParseRequestURI(req.Header.Get("Origin"))
  476. if err != nil {
  477. return http.StatusBadRequest, err
  478. }
  479. key1 := req.Header.Get("Sec-Websocket-Key1")
  480. if key1 == "" {
  481. return http.StatusBadRequest, ErrChallengeResponse
  482. }
  483. key2 := req.Header.Get("Sec-Websocket-Key2")
  484. if key2 == "" {
  485. return http.StatusBadRequest, ErrChallengeResponse
  486. }
  487. key3 := make([]byte, 8)
  488. if _, err := io.ReadFull(buf, key3); err != nil {
  489. return http.StatusBadRequest, ErrChallengeResponse
  490. }
  491. var scheme string
  492. if req.TLS != nil {
  493. scheme = "wss"
  494. } else {
  495. scheme = "ws"
  496. }
  497. c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
  498. if err != nil {
  499. return http.StatusBadRequest, err
  500. }
  501. // Step 4. get key number in Sec-WebSocket-Key<n> fields.
  502. keyNumber1 := getKeyNumber(key1)
  503. keyNumber2 := getKeyNumber(key2)
  504. // Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
  505. space1 := uint32(strings.Count(key1, " "))
  506. space2 := uint32(strings.Count(key2, " "))
  507. if space1 == 0 || space2 == 0 {
  508. return http.StatusBadRequest, ErrChallengeResponse
  509. }
  510. // Step 6. key number must be an integral multiple of spaces.
  511. if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
  512. return http.StatusBadRequest, ErrChallengeResponse
  513. }
  514. // Step 7. let part be key number divided by spaces.
  515. part1 := keyNumber1 / space1
  516. part2 := keyNumber2 / space2
  517. // Step 8. let challenge be concatenation of part1, part2 and key3.
  518. // Step 9. get MD5 fingerprint of challenge.
  519. c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
  520. if err != nil {
  521. return http.StatusInternalServerError, err
  522. }
  523. protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
  524. protocols := strings.Split(protocol, ",")
  525. for i := 0; i < len(protocols); i++ {
  526. c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
  527. }
  528. return http.StatusSwitchingProtocols, nil
  529. }
  530. func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
  531. if len(c.Protocol) > 0 {
  532. if len(c.Protocol) != 1 {
  533. return ErrBadWebSocketProtocol
  534. }
  535. }
  536. // Step 10. send response status line.
  537. buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
  538. // Step 11. send response headers.
  539. buf.WriteString("Upgrade: WebSocket\r\n")
  540. buf.WriteString("Connection: Upgrade\r\n")
  541. buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
  542. buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
  543. if len(c.Protocol) > 0 {
  544. buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
  545. }
  546. // Step 12. send CRLF.
  547. buf.WriteString("\r\n")
  548. // Step 13. send response data.
  549. buf.Write(c.challengeResponse)
  550. return buf.Flush()
  551. }
  552. func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
  553. return newHixieServerConn(c.Config, buf, rwc, request)
  554. }
  555. // A hixie75ServerHandshaker performs a server handshake using
  556. // hixie draft 75 protocol.
  557. type hixie75ServerHandshaker struct {
  558. *Config
  559. }
  560. func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
  561. c.Version = ProtocolVersionHixie75
  562. if req.Method != "GET" || req.Proto != "HTTP/1.1" {
  563. return http.StatusMethodNotAllowed, ErrBadRequestMethod
  564. }
  565. if req.Header.Get("Upgrade") != "WebSocket" {
  566. return http.StatusBadRequest, ErrNotWebSocket
  567. }
  568. if req.Header.Get("Connection") != "Upgrade" {
  569. return http.StatusBadRequest, ErrNotWebSocket
  570. }
  571. c.Origin, err = url.ParseRequestURI(strings.TrimSpace(req.Header.Get("Origin")))
  572. if err != nil {
  573. return http.StatusBadRequest, err
  574. }
  575. var scheme string
  576. if req.TLS != nil {
  577. scheme = "wss"
  578. } else {
  579. scheme = "ws"
  580. }
  581. c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
  582. if err != nil {
  583. return http.StatusBadRequest, err
  584. }
  585. protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
  586. protocols := strings.Split(protocol, ",")
  587. for i := 0; i < len(protocols); i++ {
  588. c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
  589. }
  590. return http.StatusSwitchingProtocols, nil
  591. }
  592. func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
  593. if len(c.Protocol) > 0 {
  594. if len(c.Protocol) != 1 {
  595. return ErrBadWebSocketProtocol
  596. }
  597. }
  598. buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
  599. buf.WriteString("Upgrade: WebSocket\r\n")
  600. buf.WriteString("Connection: Upgrade\r\n")
  601. buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
  602. buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
  603. if len(c.Protocol) > 0 {
  604. buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
  605. }
  606. buf.WriteString("\r\n")
  607. return buf.Flush()
  608. }
  609. func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
  610. return newHixieServerConn(c.Config, buf, rwc, request)
  611. }
  612. // newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
  613. func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
  614. return newHixieConn(config, buf, rwc, request)
  615. }