conn.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. // Copyright 2013 The Gorilla WebSocket 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. import (
  6. "bufio"
  7. "encoding/binary"
  8. "errors"
  9. "io"
  10. "io/ioutil"
  11. "math/rand"
  12. "net"
  13. "strconv"
  14. "time"
  15. )
  16. // Close codes defined in RFC 6455, section 11.7.
  17. const (
  18. CloseNormalClosure = 1000
  19. CloseGoingAway = 1001
  20. CloseProtocolError = 1002
  21. CloseUnsupportedData = 1003
  22. CloseNoStatusReceived = 1005
  23. CloseAbnormalClosure = 1006
  24. CloseInvalidFramePayloadData = 1007
  25. ClosePolicyViolation = 1008
  26. CloseMessageTooBig = 1009
  27. CloseMandatoryExtension = 1010
  28. CloseInternalServerErr = 1011
  29. CloseTLSHandshake = 1015
  30. )
  31. // The message types are defined in RFC 6455, section 11.8.
  32. const (
  33. // TextMessage denotes a text data message. The text message payload is
  34. // interpreted as UTF-8 encoded text data.
  35. TextMessage = 1
  36. // BinaryMessage denotes a binary data message.
  37. BinaryMessage = 2
  38. // CloseMessage denotes a close control message. The optional message
  39. // payload contains a numeric code and text. Use the FormatCloseMessage
  40. // function to format a close message payload.
  41. CloseMessage = 8
  42. // PingMessage denotes a ping control message. The optional message payload
  43. // is UTF-8 encoded text.
  44. PingMessage = 9
  45. // PongMessage denotes a ping control message. The optional message payload
  46. // is UTF-8 encoded text.
  47. PongMessage = 10
  48. )
  49. var (
  50. continuationFrame = 0
  51. noFrame = -1
  52. )
  53. var (
  54. ErrCloseSent = errors.New("websocket: close sent")
  55. ErrReadLimit = errors.New("websocket: read limit exceeded")
  56. )
  57. type websocketError struct {
  58. msg string
  59. temporary bool
  60. timeout bool
  61. }
  62. func (e *websocketError) Error() string { return e.msg }
  63. func (e *websocketError) Temporary() bool { return e.temporary }
  64. func (e *websocketError) Timeout() bool { return e.timeout }
  65. var (
  66. errWriteTimeout = &websocketError{msg: "websocket: write timeout", timeout: true}
  67. errBadWriteOpCode = errors.New("websocket: bad write message type")
  68. errWriteClosed = errors.New("websocket: write closed")
  69. errInvalidControlFrame = errors.New("websocket: invalid control frame")
  70. )
  71. const (
  72. maxFrameHeaderSize = 2 + 8 + 4 // Fixed header + length + mask
  73. maxControlFramePayloadSize = 125
  74. finalBit = 1 << 7
  75. maskBit = 1 << 7
  76. writeWait = time.Second
  77. )
  78. func isControl(frameType int) bool {
  79. return frameType == CloseMessage || frameType == PingMessage || frameType == PongMessage
  80. }
  81. func isData(frameType int) bool {
  82. return frameType == TextMessage || frameType == BinaryMessage
  83. }
  84. func maskBytes(key [4]byte, pos int, b []byte) int {
  85. for i := range b {
  86. b[i] ^= key[pos&3]
  87. pos += 1
  88. }
  89. return pos & 3
  90. }
  91. func newMaskKey() [4]byte {
  92. n := rand.Uint32()
  93. return [4]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 32)}
  94. }
  95. // Conn represents a WebSocket connection.
  96. type Conn struct {
  97. conn net.Conn
  98. isServer bool
  99. subprotocol string
  100. // Write fields
  101. mu chan bool // used as mutex to protect write to conn and closeSent
  102. closeSent bool // true if close message was sent
  103. // Message writer fields.
  104. writeErr error
  105. writeBuf []byte // frame is constructed in this buffer.
  106. writePos int // end of data in writeBuf.
  107. writeFrameType int // type of the current frame.
  108. writeSeq int // incremented to invalidate message writers.
  109. writeDeadline time.Time
  110. // Read fields
  111. readErr error
  112. br *bufio.Reader
  113. readRemaining int64 // bytes remaining in current frame.
  114. readFinal bool // true the current message has more frames.
  115. readSeq int // incremented to invalidate message readers.
  116. readLength int64 // Message size.
  117. readLimit int64 // Maximum message size.
  118. readMaskPos int
  119. readMaskKey [4]byte
  120. handlePong func(string) error
  121. handlePing func(string) error
  122. }
  123. func newConn(conn net.Conn, isServer bool, readBufSize, writeBufSize int) *Conn {
  124. mu := make(chan bool, 1)
  125. mu <- true
  126. c := &Conn{
  127. isServer: isServer,
  128. br: bufio.NewReaderSize(conn, readBufSize),
  129. conn: conn,
  130. mu: mu,
  131. readFinal: true,
  132. writeBuf: make([]byte, writeBufSize+maxFrameHeaderSize),
  133. writeFrameType: noFrame,
  134. writePos: maxFrameHeaderSize,
  135. }
  136. c.SetPingHandler(nil)
  137. c.SetPongHandler(nil)
  138. return c
  139. }
  140. // Subprotocol returns the negotiated protocol for the connection.
  141. func (c *Conn) Subprotocol() string {
  142. return c.subprotocol
  143. }
  144. // Close closes the underlying network connection without sending or waiting for a close frame.
  145. func (c *Conn) Close() error {
  146. return c.conn.Close()
  147. }
  148. // LocalAddr returns the local network address.
  149. func (c *Conn) LocalAddr() net.Addr {
  150. return c.conn.LocalAddr()
  151. }
  152. // RemoteAddr returns the remote network address.
  153. func (c *Conn) RemoteAddr() net.Addr {
  154. return c.conn.RemoteAddr()
  155. }
  156. // Write methods
  157. func (c *Conn) write(frameType int, deadline time.Time, bufs ...[]byte) error {
  158. <-c.mu
  159. defer func() { c.mu <- true }()
  160. if c.closeSent {
  161. return ErrCloseSent
  162. } else if frameType == CloseMessage {
  163. c.closeSent = true
  164. }
  165. c.conn.SetWriteDeadline(deadline)
  166. for _, buf := range bufs {
  167. if len(buf) > 0 {
  168. n, err := c.conn.Write(buf)
  169. if n != len(buf) {
  170. // Close on partial write.
  171. c.conn.Close()
  172. }
  173. if err != nil {
  174. return err
  175. }
  176. }
  177. }
  178. return nil
  179. }
  180. // WriteControl writes a control message with the given deadline. The allowed
  181. // message types are CloseMessage, PingMessage and PongMessage.
  182. func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error {
  183. if !isControl(messageType) {
  184. return errBadWriteOpCode
  185. }
  186. if len(data) > maxControlFramePayloadSize {
  187. return errInvalidControlFrame
  188. }
  189. b0 := byte(messageType) | finalBit
  190. b1 := byte(len(data))
  191. if !c.isServer {
  192. b1 |= maskBit
  193. }
  194. buf := make([]byte, 0, maxFrameHeaderSize+maxControlFramePayloadSize)
  195. buf = append(buf, b0, b1)
  196. if c.isServer {
  197. buf = append(buf, data...)
  198. } else {
  199. key := newMaskKey()
  200. buf = append(buf, key[:]...)
  201. buf = append(buf, data...)
  202. maskBytes(key, 0, buf[6:])
  203. }
  204. d := time.Hour * 1000
  205. if !deadline.IsZero() {
  206. d = deadline.Sub(time.Now())
  207. if d < 0 {
  208. return errWriteTimeout
  209. }
  210. }
  211. timer := time.NewTimer(d)
  212. select {
  213. case <-c.mu:
  214. timer.Stop()
  215. case <-timer.C:
  216. return errWriteTimeout
  217. }
  218. defer func() { c.mu <- true }()
  219. if c.closeSent {
  220. return ErrCloseSent
  221. } else if messageType == CloseMessage {
  222. c.closeSent = true
  223. }
  224. c.conn.SetWriteDeadline(deadline)
  225. n, err := c.conn.Write(buf)
  226. if n != 0 && n != len(buf) {
  227. c.conn.Close()
  228. }
  229. return err
  230. }
  231. // NextWriter returns a writer for the next message to send. The writer's
  232. // Close method flushes the complete message to the network.
  233. //
  234. // There can be at most one open writer on a connection. NextWriter closes the
  235. // previous writer if the application has not already done so.
  236. //
  237. // The NextWriter method and the writers returned from the method cannot be
  238. // accessed by more than one goroutine at a time.
  239. func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
  240. if c.writeErr != nil {
  241. return nil, c.writeErr
  242. }
  243. if c.writeFrameType != noFrame {
  244. if err := c.flushFrame(true, nil); err != nil {
  245. return nil, err
  246. }
  247. }
  248. if !isControl(messageType) && !isData(messageType) {
  249. return nil, errBadWriteOpCode
  250. }
  251. c.writeFrameType = messageType
  252. return messageWriter{c, c.writeSeq}, nil
  253. }
  254. func (c *Conn) flushFrame(final bool, extra []byte) error {
  255. length := c.writePos - maxFrameHeaderSize + len(extra)
  256. // Check for invalid control frames.
  257. if isControl(c.writeFrameType) &&
  258. (!final || length > maxControlFramePayloadSize) {
  259. c.writeSeq += 1
  260. c.writeFrameType = noFrame
  261. c.writePos = maxFrameHeaderSize
  262. return errInvalidControlFrame
  263. }
  264. b0 := byte(c.writeFrameType)
  265. if final {
  266. b0 |= finalBit
  267. }
  268. b1 := byte(0)
  269. if !c.isServer {
  270. b1 |= maskBit
  271. }
  272. // Assume that the frame starts at beginning of c.writeBuf.
  273. framePos := 0
  274. if c.isServer {
  275. // Adjust up if mask not included in the header.
  276. framePos = 4
  277. }
  278. switch {
  279. case length >= 65536:
  280. c.writeBuf[framePos] = b0
  281. c.writeBuf[framePos+1] = b1 | 127
  282. binary.BigEndian.PutUint64(c.writeBuf[framePos+2:], uint64(length))
  283. case length > 125:
  284. framePos += 6
  285. c.writeBuf[framePos] = b0
  286. c.writeBuf[framePos+1] = b1 | 126
  287. binary.BigEndian.PutUint16(c.writeBuf[framePos+2:], uint16(length))
  288. default:
  289. framePos += 8
  290. c.writeBuf[framePos] = b0
  291. c.writeBuf[framePos+1] = b1 | byte(length)
  292. }
  293. if !c.isServer {
  294. key := newMaskKey()
  295. copy(c.writeBuf[maxFrameHeaderSize-4:], key[:])
  296. maskBytes(key, 0, c.writeBuf[maxFrameHeaderSize:c.writePos])
  297. if len(extra) > 0 {
  298. c.writeErr = errors.New("websocket: internal error, extra used in client mode")
  299. return c.writeErr
  300. }
  301. }
  302. // Write the buffers to the connection.
  303. c.writeErr = c.write(c.writeFrameType, c.writeDeadline, c.writeBuf[framePos:c.writePos], extra)
  304. // Setup for next frame.
  305. c.writePos = maxFrameHeaderSize
  306. c.writeFrameType = continuationFrame
  307. if final {
  308. c.writeSeq += 1
  309. c.writeFrameType = noFrame
  310. }
  311. return c.writeErr
  312. }
  313. type messageWriter struct {
  314. c *Conn
  315. seq int
  316. }
  317. func (w messageWriter) err() error {
  318. c := w.c
  319. if c.writeSeq != w.seq {
  320. return errWriteClosed
  321. }
  322. if c.writeErr != nil {
  323. return c.writeErr
  324. }
  325. return nil
  326. }
  327. func (w messageWriter) ncopy(max int) (int, error) {
  328. n := len(w.c.writeBuf) - w.c.writePos
  329. if n <= 0 {
  330. if err := w.c.flushFrame(false, nil); err != nil {
  331. return 0, err
  332. }
  333. n = len(w.c.writeBuf) - w.c.writePos
  334. }
  335. if n > max {
  336. n = max
  337. }
  338. return n, nil
  339. }
  340. func (w messageWriter) write(final bool, p []byte) (int, error) {
  341. if err := w.err(); err != nil {
  342. return 0, err
  343. }
  344. if len(p) > 2*len(w.c.writeBuf) && w.c.isServer {
  345. // Don't buffer large messages.
  346. err := w.c.flushFrame(final, p)
  347. if err != nil {
  348. return 0, err
  349. }
  350. return len(p), nil
  351. }
  352. nn := len(p)
  353. for len(p) > 0 {
  354. n, err := w.ncopy(len(p))
  355. if err != nil {
  356. return 0, err
  357. }
  358. copy(w.c.writeBuf[w.c.writePos:], p[:n])
  359. w.c.writePos += n
  360. p = p[n:]
  361. }
  362. return nn, nil
  363. }
  364. func (w messageWriter) Write(p []byte) (int, error) {
  365. return w.write(false, p)
  366. }
  367. func (w messageWriter) WriteString(p string) (int, error) {
  368. if err := w.err(); err != nil {
  369. return 0, err
  370. }
  371. nn := len(p)
  372. for len(p) > 0 {
  373. n, err := w.ncopy(len(p))
  374. if err != nil {
  375. return 0, err
  376. }
  377. copy(w.c.writeBuf[w.c.writePos:], p[:n])
  378. w.c.writePos += n
  379. p = p[n:]
  380. }
  381. return nn, nil
  382. }
  383. func (w messageWriter) ReadFrom(r io.Reader) (nn int64, err error) {
  384. if err := w.err(); err != nil {
  385. return 0, err
  386. }
  387. for {
  388. if w.c.writePos == len(w.c.writeBuf) {
  389. err = w.c.flushFrame(false, nil)
  390. if err != nil {
  391. break
  392. }
  393. }
  394. var n int
  395. n, err = r.Read(w.c.writeBuf[w.c.writePos:])
  396. w.c.writePos += n
  397. nn += int64(n)
  398. if err != nil {
  399. if err == io.EOF {
  400. err = nil
  401. }
  402. break
  403. }
  404. }
  405. return nn, err
  406. }
  407. func (w messageWriter) Close() error {
  408. if err := w.err(); err != nil {
  409. return err
  410. }
  411. return w.c.flushFrame(true, nil)
  412. }
  413. // WriteMessage is a helper method for getting a writer using NextWriter,
  414. // writing the message and closing the writer.
  415. func (c *Conn) WriteMessage(messageType int, data []byte) error {
  416. wr, err := c.NextWriter(messageType)
  417. if err != nil {
  418. return err
  419. }
  420. w := wr.(messageWriter)
  421. if _, err := w.write(true, data); err != nil {
  422. return err
  423. }
  424. if c.writeSeq == w.seq {
  425. if err := c.flushFrame(true, nil); err != nil {
  426. return err
  427. }
  428. }
  429. return nil
  430. }
  431. // SetWriteDeadline sets the deadline for future calls to NextWriter and the
  432. // io.WriteCloser returned from NextWriter. If the deadline is reached, the
  433. // call will fail with a timeout instead of blocking. A zero value for t means
  434. // Write will not time out. Even if Write times out, it may return n > 0,
  435. // indicating that some of the data was successfully written.
  436. func (c *Conn) SetWriteDeadline(t time.Time) error {
  437. c.writeDeadline = t
  438. return nil
  439. }
  440. // Read methods
  441. func (c *Conn) advanceFrame() (int, error) {
  442. // 1. Skip remainder of previous frame.
  443. if c.readRemaining > 0 {
  444. if _, err := io.CopyN(ioutil.Discard, c.br, c.readRemaining); err != nil {
  445. return noFrame, err
  446. }
  447. }
  448. // 2. Read and parse first two bytes of frame header.
  449. var b [8]byte
  450. if err := c.read(b[:2]); err != nil {
  451. return noFrame, err
  452. }
  453. final := b[0]&finalBit != 0
  454. frameType := int(b[0] & 0xf)
  455. reserved := int((b[0] >> 4) & 0x7)
  456. mask := b[1]&maskBit != 0
  457. c.readRemaining = int64(b[1] & 0x7f)
  458. if reserved != 0 {
  459. return noFrame, c.handleProtocolError("unexpected reserved bits " + strconv.Itoa(reserved))
  460. }
  461. switch frameType {
  462. case CloseMessage, PingMessage, PongMessage:
  463. if c.readRemaining > maxControlFramePayloadSize {
  464. return noFrame, c.handleProtocolError("control frame length > 125")
  465. }
  466. if !final {
  467. return noFrame, c.handleProtocolError("control frame not final")
  468. }
  469. case TextMessage, BinaryMessage:
  470. if !c.readFinal {
  471. return noFrame, c.handleProtocolError("message start before final message frame")
  472. }
  473. c.readFinal = final
  474. case continuationFrame:
  475. if c.readFinal {
  476. return noFrame, c.handleProtocolError("continuation after final message frame")
  477. }
  478. c.readFinal = final
  479. default:
  480. return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType))
  481. }
  482. // 3. Read and parse frame length.
  483. switch c.readRemaining {
  484. case 126:
  485. if err := c.read(b[:2]); err != nil {
  486. return noFrame, err
  487. }
  488. c.readRemaining = int64(binary.BigEndian.Uint16(b[:2]))
  489. case 127:
  490. if err := c.read(b[:8]); err != nil {
  491. return noFrame, err
  492. }
  493. c.readRemaining = int64(binary.BigEndian.Uint64(b[:8]))
  494. }
  495. // 4. Handle frame masking.
  496. if mask != c.isServer {
  497. return noFrame, c.handleProtocolError("incorrect mask flag")
  498. }
  499. if mask {
  500. c.readMaskPos = 0
  501. if err := c.read(c.readMaskKey[:]); err != nil {
  502. return noFrame, err
  503. }
  504. }
  505. // 5. For text and binary messages, enforce read limit and return.
  506. if frameType == continuationFrame || frameType == TextMessage || frameType == BinaryMessage {
  507. c.readLength += c.readRemaining
  508. if c.readLimit > 0 && c.readLength > c.readLimit {
  509. c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait))
  510. return noFrame, ErrReadLimit
  511. }
  512. return frameType, nil
  513. }
  514. // 6. Read control frame payload.
  515. payload := make([]byte, c.readRemaining)
  516. c.readRemaining = 0
  517. if err := c.read(payload); err != nil {
  518. return noFrame, err
  519. }
  520. maskBytes(c.readMaskKey, 0, payload)
  521. // 7. Process control frame payload.
  522. switch frameType {
  523. case PongMessage:
  524. if err := c.handlePong(string(payload)); err != nil {
  525. return noFrame, err
  526. }
  527. case PingMessage:
  528. if err := c.handlePing(string(payload)); err != nil {
  529. return noFrame, err
  530. }
  531. case CloseMessage:
  532. c.WriteControl(CloseMessage, []byte{}, time.Now().Add(writeWait))
  533. if len(payload) < 2 {
  534. return noFrame, io.EOF
  535. }
  536. closeCode := binary.BigEndian.Uint16(payload)
  537. switch closeCode {
  538. case CloseNormalClosure, CloseGoingAway:
  539. return noFrame, io.EOF
  540. default:
  541. return noFrame, errors.New("websocket: close " +
  542. strconv.Itoa(int(closeCode)) + " " +
  543. string(payload[2:]))
  544. }
  545. }
  546. return frameType, nil
  547. }
  548. func (c *Conn) handleProtocolError(message string) error {
  549. c.WriteControl(CloseMessage, FormatCloseMessage(CloseProtocolError, message), time.Now().Add(writeWait))
  550. return errors.New("websocket: " + message)
  551. }
  552. func (c *Conn) read(buf []byte) error {
  553. var err error
  554. for len(buf) > 0 && err == nil {
  555. var nn int
  556. nn, err = c.br.Read(buf)
  557. buf = buf[nn:]
  558. }
  559. if err == io.EOF {
  560. if len(buf) == 0 {
  561. err = nil
  562. } else {
  563. err = io.ErrUnexpectedEOF
  564. }
  565. }
  566. return err
  567. }
  568. // NextReader returns the next data message received from the peer. The
  569. // returned messageType is either TextMessage or BinaryMessage.
  570. //
  571. // There can be at most one open reader on a connection. NextReader discards
  572. // the previous message if the application has not already consumed it.
  573. //
  574. // The NextReader method and the readers returned from the method cannot be
  575. // accessed by more than one goroutine at a time.
  576. func (c *Conn) NextReader() (messageType int, r io.Reader, err error) {
  577. c.readSeq += 1
  578. c.readLength = 0
  579. for c.readErr == nil {
  580. var frameType int
  581. frameType, c.readErr = c.advanceFrame()
  582. if frameType == TextMessage || frameType == BinaryMessage {
  583. return frameType, messageReader{c, c.readSeq}, nil
  584. }
  585. }
  586. return noFrame, nil, c.readErr
  587. }
  588. type messageReader struct {
  589. c *Conn
  590. seq int
  591. }
  592. func (r messageReader) Read(b []byte) (n int, err error) {
  593. if r.seq != r.c.readSeq {
  594. return 0, io.EOF
  595. }
  596. for r.c.readErr == nil {
  597. if r.c.readRemaining > 0 {
  598. if int64(len(b)) > r.c.readRemaining {
  599. b = b[:r.c.readRemaining]
  600. }
  601. r.c.readErr = r.c.read(b)
  602. r.c.readMaskPos = maskBytes(r.c.readMaskKey, r.c.readMaskPos, b)
  603. r.c.readRemaining -= int64(len(b))
  604. return len(b), r.c.readErr
  605. }
  606. if r.c.readFinal {
  607. r.c.readSeq += 1
  608. return 0, io.EOF
  609. }
  610. var frameType int
  611. frameType, r.c.readErr = r.c.advanceFrame()
  612. if frameType == TextMessage || frameType == BinaryMessage {
  613. r.c.readErr = errors.New("websocket: internal error, unexpected text or binary in Reader")
  614. }
  615. }
  616. return 0, r.c.readErr
  617. }
  618. // ReadMessage is a helper method for getting a reader using NextReader and
  619. // reading from that reader to a buffer.
  620. func (c *Conn) ReadMessage() (messageType int, p []byte, err error) {
  621. var r io.Reader
  622. messageType, r, err = c.NextReader()
  623. if err != nil {
  624. return messageType, nil, err
  625. }
  626. p, err = ioutil.ReadAll(r)
  627. return messageType, p, err
  628. }
  629. // SetReadDeadline sets the deadline for future calls to NextReader and the
  630. // io.Reader returned from NextReader. If the deadline is reached, the call
  631. // will fail with a timeout instead of blocking. A zero value for t means that
  632. // the methods will not time out.
  633. func (c *Conn) SetReadDeadline(t time.Time) error {
  634. return c.conn.SetReadDeadline(t)
  635. }
  636. // SetReadLimit sets the maximum size for a message read from the peer. If a
  637. // message exceeds the limit, the connection sends a close frame to the peer
  638. // and returns ErrReadLimit to the application.
  639. func (c *Conn) SetReadLimit(limit int64) {
  640. c.readLimit = limit
  641. }
  642. // SetPingHandler sets the handler for ping messages received from the peer.
  643. // The default ping handler sends a pong to the peer.
  644. func (c *Conn) SetPingHandler(h func(string) error) {
  645. if h == nil {
  646. h = func(message string) error {
  647. c.WriteControl(PongMessage, []byte(message), time.Now().Add(writeWait))
  648. return nil
  649. }
  650. }
  651. c.handlePing = h
  652. }
  653. // SetPongHandler sets then handler for pong messages received from the peer.
  654. // The default pong handler does nothing.
  655. func (c *Conn) SetPongHandler(h func(string) error) {
  656. if h == nil {
  657. h = func(string) error { return nil }
  658. }
  659. c.handlePong = h
  660. }
  661. // UnderlyingConn returns the internal net.Conn. This can be used to further
  662. // modifications to connection specific flags.
  663. func (c *Conn) UnderlyingConn() net.Conn {
  664. return c.conn
  665. }
  666. // FormatCloseMessage formats closeCode and text as a WebSocket close message.
  667. func FormatCloseMessage(closeCode int, text string) []byte {
  668. buf := make([]byte, 2+len(text))
  669. binary.BigEndian.PutUint16(buf, uint16(closeCode))
  670. copy(buf[2:], text)
  671. return buf
  672. }