websocket.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 implements a client and server for the WebSocket protocol
  5. // as specified in RFC 6455.
  6. //
  7. // This package currently lacks some features found in an alternative
  8. // and more actively maintained WebSocket package:
  9. //
  10. // https://pkg.go.dev/nhooyr.io/websocket
  11. package websocket // import "golang.org/x/net/websocket"
  12. import (
  13. "bufio"
  14. "crypto/tls"
  15. "encoding/json"
  16. "errors"
  17. "io"
  18. "io/ioutil"
  19. "net"
  20. "net/http"
  21. "net/url"
  22. "sync"
  23. "time"
  24. )
  25. const (
  26. ProtocolVersionHybi13 = 13
  27. ProtocolVersionHybi = ProtocolVersionHybi13
  28. SupportedProtocolVersion = "13"
  29. ContinuationFrame = 0
  30. TextFrame = 1
  31. BinaryFrame = 2
  32. CloseFrame = 8
  33. PingFrame = 9
  34. PongFrame = 10
  35. UnknownFrame = 255
  36. DefaultMaxPayloadBytes = 32 << 20 // 32MB
  37. )
  38. // ProtocolError represents WebSocket protocol errors.
  39. type ProtocolError struct {
  40. ErrorString string
  41. }
  42. func (err *ProtocolError) Error() string { return err.ErrorString }
  43. var (
  44. ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
  45. ErrBadScheme = &ProtocolError{"bad scheme"}
  46. ErrBadStatus = &ProtocolError{"bad status"}
  47. ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
  48. ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
  49. ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
  50. ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
  51. ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
  52. ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
  53. ErrBadFrame = &ProtocolError{"bad frame"}
  54. ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
  55. ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
  56. ErrBadRequestMethod = &ProtocolError{"bad method"}
  57. ErrNotSupported = &ProtocolError{"not supported"}
  58. )
  59. // ErrFrameTooLarge is returned by Codec's Receive method if payload size
  60. // exceeds limit set by Conn.MaxPayloadBytes
  61. var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit")
  62. // Addr is an implementation of net.Addr for WebSocket.
  63. type Addr struct {
  64. *url.URL
  65. }
  66. // Network returns the network type for a WebSocket, "websocket".
  67. func (addr *Addr) Network() string { return "websocket" }
  68. // Config is a WebSocket configuration
  69. type Config struct {
  70. // A WebSocket server address.
  71. Location *url.URL
  72. // A Websocket client origin.
  73. Origin *url.URL
  74. // WebSocket subprotocols.
  75. Protocol []string
  76. // WebSocket protocol version.
  77. Version int
  78. // TLS config for secure WebSocket (wss).
  79. TlsConfig *tls.Config
  80. // Additional header fields to be sent in WebSocket opening handshake.
  81. Header http.Header
  82. // Dialer used when opening websocket connections.
  83. Dialer *net.Dialer
  84. handshakeData map[string]string
  85. }
  86. // serverHandshaker is an interface to handle WebSocket server side handshake.
  87. type serverHandshaker interface {
  88. // ReadHandshake reads handshake request message from client.
  89. // Returns http response code and error if any.
  90. ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
  91. // AcceptHandshake accepts the client handshake request and sends
  92. // handshake response back to client.
  93. AcceptHandshake(buf *bufio.Writer) (err error)
  94. // NewServerConn creates a new WebSocket connection.
  95. NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
  96. }
  97. // frameReader is an interface to read a WebSocket frame.
  98. type frameReader interface {
  99. // Reader is to read payload of the frame.
  100. io.Reader
  101. // PayloadType returns payload type.
  102. PayloadType() byte
  103. // HeaderReader returns a reader to read header of the frame.
  104. HeaderReader() io.Reader
  105. // TrailerReader returns a reader to read trailer of the frame.
  106. // If it returns nil, there is no trailer in the frame.
  107. TrailerReader() io.Reader
  108. // Len returns total length of the frame, including header and trailer.
  109. Len() int
  110. }
  111. // frameReaderFactory is an interface to creates new frame reader.
  112. type frameReaderFactory interface {
  113. NewFrameReader() (r frameReader, err error)
  114. }
  115. // frameWriter is an interface to write a WebSocket frame.
  116. type frameWriter interface {
  117. // Writer is to write payload of the frame.
  118. io.WriteCloser
  119. }
  120. // frameWriterFactory is an interface to create new frame writer.
  121. type frameWriterFactory interface {
  122. NewFrameWriter(payloadType byte) (w frameWriter, err error)
  123. }
  124. type frameHandler interface {
  125. HandleFrame(frame frameReader) (r frameReader, err error)
  126. WriteClose(status int) (err error)
  127. }
  128. // Conn represents a WebSocket connection.
  129. //
  130. // Multiple goroutines may invoke methods on a Conn simultaneously.
  131. type Conn struct {
  132. config *Config
  133. request *http.Request
  134. buf *bufio.ReadWriter
  135. rwc io.ReadWriteCloser
  136. rio sync.Mutex
  137. frameReaderFactory
  138. frameReader
  139. wio sync.Mutex
  140. frameWriterFactory
  141. frameHandler
  142. PayloadType byte
  143. defaultCloseStatus int
  144. // MaxPayloadBytes limits the size of frame payload received over Conn
  145. // by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used.
  146. MaxPayloadBytes int
  147. }
  148. // Read implements the io.Reader interface:
  149. // it reads data of a frame from the WebSocket connection.
  150. // if msg is not large enough for the frame data, it fills the msg and next Read
  151. // will read the rest of the frame data.
  152. // it reads Text frame or Binary frame.
  153. func (ws *Conn) Read(msg []byte) (n int, err error) {
  154. ws.rio.Lock()
  155. defer ws.rio.Unlock()
  156. again:
  157. if ws.frameReader == nil {
  158. frame, err := ws.frameReaderFactory.NewFrameReader()
  159. if err != nil {
  160. return 0, err
  161. }
  162. ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
  163. if err != nil {
  164. return 0, err
  165. }
  166. if ws.frameReader == nil {
  167. goto again
  168. }
  169. }
  170. n, err = ws.frameReader.Read(msg)
  171. if err == io.EOF {
  172. if trailer := ws.frameReader.TrailerReader(); trailer != nil {
  173. io.Copy(ioutil.Discard, trailer)
  174. }
  175. ws.frameReader = nil
  176. goto again
  177. }
  178. return n, err
  179. }
  180. // Write implements the io.Writer interface:
  181. // it writes data as a frame to the WebSocket connection.
  182. func (ws *Conn) Write(msg []byte) (n int, err error) {
  183. ws.wio.Lock()
  184. defer ws.wio.Unlock()
  185. w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
  186. if err != nil {
  187. return 0, err
  188. }
  189. n, err = w.Write(msg)
  190. w.Close()
  191. return n, err
  192. }
  193. // Close implements the io.Closer interface.
  194. func (ws *Conn) Close() error {
  195. err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
  196. err1 := ws.rwc.Close()
  197. if err != nil {
  198. return err
  199. }
  200. return err1
  201. }
  202. // IsClientConn reports whether ws is a client-side connection.
  203. func (ws *Conn) IsClientConn() bool { return ws.request == nil }
  204. // IsServerConn reports whether ws is a server-side connection.
  205. func (ws *Conn) IsServerConn() bool { return ws.request != nil }
  206. // LocalAddr returns the WebSocket Origin for the connection for client, or
  207. // the WebSocket location for server.
  208. func (ws *Conn) LocalAddr() net.Addr {
  209. if ws.IsClientConn() {
  210. return &Addr{ws.config.Origin}
  211. }
  212. return &Addr{ws.config.Location}
  213. }
  214. // RemoteAddr returns the WebSocket location for the connection for client, or
  215. // the Websocket Origin for server.
  216. func (ws *Conn) RemoteAddr() net.Addr {
  217. if ws.IsClientConn() {
  218. return &Addr{ws.config.Location}
  219. }
  220. return &Addr{ws.config.Origin}
  221. }
  222. var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
  223. // SetDeadline sets the connection's network read & write deadlines.
  224. func (ws *Conn) SetDeadline(t time.Time) error {
  225. if conn, ok := ws.rwc.(net.Conn); ok {
  226. return conn.SetDeadline(t)
  227. }
  228. return errSetDeadline
  229. }
  230. // SetReadDeadline sets the connection's network read deadline.
  231. func (ws *Conn) SetReadDeadline(t time.Time) error {
  232. if conn, ok := ws.rwc.(net.Conn); ok {
  233. return conn.SetReadDeadline(t)
  234. }
  235. return errSetDeadline
  236. }
  237. // SetWriteDeadline sets the connection's network write deadline.
  238. func (ws *Conn) SetWriteDeadline(t time.Time) error {
  239. if conn, ok := ws.rwc.(net.Conn); ok {
  240. return conn.SetWriteDeadline(t)
  241. }
  242. return errSetDeadline
  243. }
  244. // Config returns the WebSocket config.
  245. func (ws *Conn) Config() *Config { return ws.config }
  246. // Request returns the http request upgraded to the WebSocket.
  247. // It is nil for client side.
  248. func (ws *Conn) Request() *http.Request { return ws.request }
  249. // Codec represents a symmetric pair of functions that implement a codec.
  250. type Codec struct {
  251. Marshal func(v interface{}) (data []byte, payloadType byte, err error)
  252. Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
  253. }
  254. // Send sends v marshaled by cd.Marshal as single frame to ws.
  255. func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
  256. data, payloadType, err := cd.Marshal(v)
  257. if err != nil {
  258. return err
  259. }
  260. ws.wio.Lock()
  261. defer ws.wio.Unlock()
  262. w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
  263. if err != nil {
  264. return err
  265. }
  266. _, err = w.Write(data)
  267. w.Close()
  268. return err
  269. }
  270. // Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores
  271. // in v. The whole frame payload is read to an in-memory buffer; max size of
  272. // payload is defined by ws.MaxPayloadBytes. If frame payload size exceeds
  273. // limit, ErrFrameTooLarge is returned; in this case frame is not read off wire
  274. // completely. The next call to Receive would read and discard leftover data of
  275. // previous oversized frame before processing next frame.
  276. func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
  277. ws.rio.Lock()
  278. defer ws.rio.Unlock()
  279. if ws.frameReader != nil {
  280. _, err = io.Copy(ioutil.Discard, ws.frameReader)
  281. if err != nil {
  282. return err
  283. }
  284. ws.frameReader = nil
  285. }
  286. again:
  287. frame, err := ws.frameReaderFactory.NewFrameReader()
  288. if err != nil {
  289. return err
  290. }
  291. frame, err = ws.frameHandler.HandleFrame(frame)
  292. if err != nil {
  293. return err
  294. }
  295. if frame == nil {
  296. goto again
  297. }
  298. maxPayloadBytes := ws.MaxPayloadBytes
  299. if maxPayloadBytes == 0 {
  300. maxPayloadBytes = DefaultMaxPayloadBytes
  301. }
  302. if hf, ok := frame.(*hybiFrameReader); ok && hf.header.Length > int64(maxPayloadBytes) {
  303. // payload size exceeds limit, no need to call Unmarshal
  304. //
  305. // set frameReader to current oversized frame so that
  306. // the next call to this function can drain leftover
  307. // data before processing the next frame
  308. ws.frameReader = frame
  309. return ErrFrameTooLarge
  310. }
  311. payloadType := frame.PayloadType()
  312. data, err := ioutil.ReadAll(frame)
  313. if err != nil {
  314. return err
  315. }
  316. return cd.Unmarshal(data, payloadType, v)
  317. }
  318. func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
  319. switch data := v.(type) {
  320. case string:
  321. return []byte(data), TextFrame, nil
  322. case []byte:
  323. return data, BinaryFrame, nil
  324. }
  325. return nil, UnknownFrame, ErrNotSupported
  326. }
  327. func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
  328. switch data := v.(type) {
  329. case *string:
  330. *data = string(msg)
  331. return nil
  332. case *[]byte:
  333. *data = msg
  334. return nil
  335. }
  336. return ErrNotSupported
  337. }
  338. /*
  339. Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
  340. To send/receive text frame, use string type.
  341. To send/receive binary frame, use []byte type.
  342. Trivial usage:
  343. import "websocket"
  344. // receive text frame
  345. var message string
  346. websocket.Message.Receive(ws, &message)
  347. // send text frame
  348. message = "hello"
  349. websocket.Message.Send(ws, message)
  350. // receive binary frame
  351. var data []byte
  352. websocket.Message.Receive(ws, &data)
  353. // send binary frame
  354. data = []byte{0, 1, 2}
  355. websocket.Message.Send(ws, data)
  356. */
  357. var Message = Codec{marshal, unmarshal}
  358. func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
  359. msg, err = json.Marshal(v)
  360. return msg, TextFrame, err
  361. }
  362. func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
  363. return json.Unmarshal(msg, v)
  364. }
  365. /*
  366. JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
  367. Trivial usage:
  368. import "websocket"
  369. type T struct {
  370. Msg string
  371. Count int
  372. }
  373. // receive JSON type T
  374. var data T
  375. websocket.JSON.Receive(ws, &data)
  376. // send JSON type T
  377. websocket.JSON.Send(ws, data)
  378. */
  379. var JSON = Codec{jsonMarshal, jsonUnmarshal}