您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

449 行
12 KiB

  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://godoc.org/github.com/gorilla/websocket
  11. //
  12. package websocket // import "golang.org/x/net/websocket"
  13. import (
  14. "bufio"
  15. "crypto/tls"
  16. "encoding/json"
  17. "errors"
  18. "io"
  19. "io/ioutil"
  20. "net"
  21. "net/http"
  22. "net/url"
  23. "sync"
  24. "time"
  25. )
  26. const (
  27. ProtocolVersionHybi13 = 13
  28. ProtocolVersionHybi = ProtocolVersionHybi13
  29. SupportedProtocolVersion = "13"
  30. ContinuationFrame = 0
  31. TextFrame = 1
  32. BinaryFrame = 2
  33. CloseFrame = 8
  34. PingFrame = 9
  35. PongFrame = 10
  36. UnknownFrame = 255
  37. DefaultMaxPayloadBytes = 32 << 20 // 32MB
  38. )
  39. // ProtocolError represents WebSocket protocol errors.
  40. type ProtocolError struct {
  41. ErrorString string
  42. }
  43. func (err *ProtocolError) Error() string { return err.ErrorString }
  44. var (
  45. ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
  46. ErrBadScheme = &ProtocolError{"bad scheme"}
  47. ErrBadStatus = &ProtocolError{"bad status"}
  48. ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
  49. ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
  50. ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
  51. ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
  52. ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
  53. ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
  54. ErrBadFrame = &ProtocolError{"bad frame"}
  55. ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
  56. ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
  57. ErrBadRequestMethod = &ProtocolError{"bad method"}
  58. ErrNotSupported = &ProtocolError{"not supported"}
  59. )
  60. // ErrFrameTooLarge is returned by Codec's Receive method if payload size
  61. // exceeds limit set by Conn.MaxPayloadBytes
  62. var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit")
  63. // Addr is an implementation of net.Addr for WebSocket.
  64. type Addr struct {
  65. *url.URL
  66. }
  67. // Network returns the network type for a WebSocket, "websocket".
  68. func (addr *Addr) Network() string { return "websocket" }
  69. // Config is a WebSocket configuration
  70. type Config struct {
  71. // A WebSocket server address.
  72. Location *url.URL
  73. // A Websocket client origin.
  74. Origin *url.URL
  75. // WebSocket subprotocols.
  76. Protocol []string
  77. // WebSocket protocol version.
  78. Version int
  79. // TLS config for secure WebSocket (wss).
  80. TlsConfig *tls.Config
  81. // Additional header fields to be sent in WebSocket opening handshake.
  82. Header http.Header
  83. // Dialer used when opening websocket connections.
  84. Dialer *net.Dialer
  85. handshakeData map[string]string
  86. }
  87. // serverHandshaker is an interface to handle WebSocket server side handshake.
  88. type serverHandshaker interface {
  89. // ReadHandshake reads handshake request message from client.
  90. // Returns http response code and error if any.
  91. ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
  92. // AcceptHandshake accepts the client handshake request and sends
  93. // handshake response back to client.
  94. AcceptHandshake(buf *bufio.Writer) (err error)
  95. // NewServerConn creates a new WebSocket connection.
  96. NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
  97. }
  98. // frameReader is an interface to read a WebSocket frame.
  99. type frameReader interface {
  100. // Reader is to read payload of the frame.
  101. io.Reader
  102. // PayloadType returns payload type.
  103. PayloadType() byte
  104. // HeaderReader returns a reader to read header of the frame.
  105. HeaderReader() io.Reader
  106. // TrailerReader returns a reader to read trailer of the frame.
  107. // If it returns nil, there is no trailer in the frame.
  108. TrailerReader() io.Reader
  109. // Len returns total length of the frame, including header and trailer.
  110. Len() int
  111. }
  112. // frameReaderFactory is an interface to creates new frame reader.
  113. type frameReaderFactory interface {
  114. NewFrameReader() (r frameReader, err error)
  115. }
  116. // frameWriter is an interface to write a WebSocket frame.
  117. type frameWriter interface {
  118. // Writer is to write payload of the frame.
  119. io.WriteCloser
  120. }
  121. // frameWriterFactory is an interface to create new frame writer.
  122. type frameWriterFactory interface {
  123. NewFrameWriter(payloadType byte) (w frameWriter, err error)
  124. }
  125. type frameHandler interface {
  126. HandleFrame(frame frameReader) (r frameReader, err error)
  127. WriteClose(status int) (err error)
  128. }
  129. // Conn represents a WebSocket connection.
  130. //
  131. // Multiple goroutines may invoke methods on a Conn simultaneously.
  132. type Conn struct {
  133. config *Config
  134. request *http.Request
  135. buf *bufio.ReadWriter
  136. rwc io.ReadWriteCloser
  137. rio sync.Mutex
  138. frameReaderFactory
  139. frameReader
  140. wio sync.Mutex
  141. frameWriterFactory
  142. frameHandler
  143. PayloadType byte
  144. defaultCloseStatus int
  145. // MaxPayloadBytes limits the size of frame payload received over Conn
  146. // by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used.
  147. MaxPayloadBytes int
  148. }
  149. // Read implements the io.Reader interface:
  150. // it reads data of a frame from the WebSocket connection.
  151. // if msg is not large enough for the frame data, it fills the msg and next Read
  152. // will read the rest of the frame data.
  153. // it reads Text frame or Binary frame.
  154. func (ws *Conn) Read(msg []byte) (n int, err error) {
  155. ws.rio.Lock()
  156. defer ws.rio.Unlock()
  157. again:
  158. if ws.frameReader == nil {
  159. frame, err := ws.frameReaderFactory.NewFrameReader()
  160. if err != nil {
  161. return 0, err
  162. }
  163. ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
  164. if err != nil {
  165. return 0, err
  166. }
  167. if ws.frameReader == nil {
  168. goto again
  169. }
  170. }
  171. n, err = ws.frameReader.Read(msg)
  172. if err == io.EOF {
  173. if trailer := ws.frameReader.TrailerReader(); trailer != nil {
  174. io.Copy(ioutil.Discard, trailer)
  175. }
  176. ws.frameReader = nil
  177. goto again
  178. }
  179. return n, err
  180. }
  181. // Write implements the io.Writer interface:
  182. // it writes data as a frame to the WebSocket connection.
  183. func (ws *Conn) Write(msg []byte) (n int, err error) {
  184. ws.wio.Lock()
  185. defer ws.wio.Unlock()
  186. w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
  187. if err != nil {
  188. return 0, err
  189. }
  190. n, err = w.Write(msg)
  191. w.Close()
  192. return n, err
  193. }
  194. // Close implements the io.Closer interface.
  195. func (ws *Conn) Close() error {
  196. err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
  197. err1 := ws.rwc.Close()
  198. if err != nil {
  199. return err
  200. }
  201. return err1
  202. }
  203. func (ws *Conn) IsClientConn() bool { return ws.request == nil }
  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(ioutil.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 := ioutil.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}