websocket.go 12 KB

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