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.
5
// Package websocket implements a client and server for the WebSocket protocol.
6
// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
24
ProtocolVersionHixie75 = -75
25
ProtocolVersionHixie76 = -76
26
ProtocolVersionHybi00 = 0
27
ProtocolVersionHybi08 = 8
28
ProtocolVersionHybi13 = 13
29
ProtocolVersionHybi = ProtocolVersionHybi13
30
SupportedProtocolVersion = "13, 8"
41
// ProtocolError represents WebSocket protocol errors.
42
type ProtocolError struct {
46
func (err *ProtocolError) Error() string { return err.ErrorString }
49
ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
50
ErrBadScheme = &ProtocolError{"bad scheme"}
51
ErrBadStatus = &ProtocolError{"bad status"}
52
ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
53
ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
54
ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
55
ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
56
ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
57
ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
58
ErrBadFrame = &ProtocolError{"bad frame"}
59
ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
60
ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
61
ErrBadRequestMethod = &ProtocolError{"bad method"}
62
ErrNotSupported = &ProtocolError{"not supported"}
65
// Addr is an implementation of net.Addr for WebSocket.
70
// Network returns the network type for a WebSocket, "websocket".
71
func (addr *Addr) Network() string { return "websocket" }
73
// Config is a WebSocket configuration
75
// A WebSocket server address.
78
// A Websocket client origin.
81
// WebSocket subprotocols.
84
// WebSocket protocol version.
87
// TLS config for secure WebSocket (wss).
90
handshakeData map[string]string
93
// serverHandshaker is an interface to handle WebSocket server side handshake.
94
type serverHandshaker interface {
95
// ReadHandshake reads handshake request message from client.
96
// Returns http response code and error if any.
97
ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
99
// AcceptHandshake accepts the client handshake request and sends
100
// handshake response back to client.
101
AcceptHandshake(buf *bufio.Writer) (err error)
103
// NewServerConn creates a new WebSocket connection.
104
NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
107
// frameReader is an interface to read a WebSocket frame.
108
type frameReader interface {
109
// Reader is to read payload of the frame.
112
// PayloadType returns payload type.
115
// HeaderReader returns a reader to read header of the frame.
116
HeaderReader() io.Reader
118
// TrailerReader returns a reader to read trailer of the frame.
119
// If it returns nil, there is no trailer in the frame.
120
TrailerReader() io.Reader
122
// Len returns total length of the frame, including header and trailer.
126
// frameReaderFactory is an interface to creates new frame reader.
127
type frameReaderFactory interface {
128
NewFrameReader() (r frameReader, err error)
131
// frameWriter is an interface to write a WebSocket frame.
132
type frameWriter interface {
133
// Writer is to write playload of the frame.
137
// frameWriterFactory is an interface to create new frame writer.
138
type frameWriterFactory interface {
139
NewFrameWriter(payloadType byte) (w frameWriter, err error)
142
type frameHandler interface {
143
HandleFrame(frame frameReader) (r frameReader, err error)
144
WriteClose(status int) (err error)
147
// Conn represents a WebSocket connection.
150
request *http.Request
152
buf *bufio.ReadWriter
153
rwc io.ReadWriteCloser
164
defaultCloseStatus int
167
// Read implements the io.Reader interface:
168
// it reads data of a frame from the WebSocket connection.
169
// if msg is not large enough for the frame data, it fills the msg and next Read
170
// will read the rest of the frame data.
171
// it reads Text frame or Binary frame.
172
func (ws *Conn) Read(msg []byte) (n int, err error) {
174
defer ws.rio.Unlock()
176
if ws.frameReader == nil {
177
frame, err := ws.frameReaderFactory.NewFrameReader()
181
ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
185
if ws.frameReader == nil {
189
n, err = ws.frameReader.Read(msg)
191
if trailer := ws.frameReader.TrailerReader(); trailer != nil {
192
io.Copy(ioutil.Discard, trailer)
200
// Write implements the io.Writer interface:
201
// it writes data as a frame to the WebSocket connection.
202
func (ws *Conn) Write(msg []byte) (n int, err error) {
204
defer ws.wio.Unlock()
205
w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
209
n, err = w.Write(msg)
217
// Close implements the io.Closer interface.
218
func (ws *Conn) Close() error {
219
err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
223
return ws.rwc.Close()
226
func (ws *Conn) IsClientConn() bool { return ws.request == nil }
227
func (ws *Conn) IsServerConn() bool { return ws.request != nil }
229
// LocalAddr returns the WebSocket Origin for the connection for client, or
230
// the WebSocket location for server.
231
func (ws *Conn) LocalAddr() net.Addr {
232
if ws.IsClientConn() {
233
return &Addr{ws.config.Origin}
235
return &Addr{ws.config.Location}
238
// RemoteAddr returns the WebSocket location for the connection for client, or
239
// the Websocket Origin for server.
240
func (ws *Conn) RemoteAddr() net.Addr {
241
if ws.IsClientConn() {
242
return &Addr{ws.config.Location}
244
return &Addr{ws.config.Origin}
247
var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
249
// SetDeadline sets the connection's network read & write deadlines.
250
func (ws *Conn) SetDeadline(t time.Time) error {
251
if conn, ok := ws.rwc.(net.Conn); ok {
252
return conn.SetDeadline(t)
254
return errSetDeadline
257
// SetReadDeadline sets the connection's network read deadline.
258
func (ws *Conn) SetReadDeadline(t time.Time) error {
259
if conn, ok := ws.rwc.(net.Conn); ok {
260
return conn.SetReadDeadline(t)
262
return errSetDeadline
265
// SetWriteDeadline sets the connection's network write deadline.
266
func (ws *Conn) SetWriteDeadline(t time.Time) error {
267
if conn, ok := ws.rwc.(net.Conn); ok {
268
return conn.SetWriteDeadline(t)
270
return errSetDeadline
273
// Config returns the WebSocket config.
274
func (ws *Conn) Config() *Config { return ws.config }
276
// Request returns the http request upgraded to the WebSocket.
277
// It is nil for client side.
278
func (ws *Conn) Request() *http.Request { return ws.request }
280
// Codec represents a symmetric pair of functions that implement a codec.
282
Marshal func(v interface{}) (data []byte, payloadType byte, err error)
283
Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
286
// Send sends v marshaled by cd.Marshal as single frame to ws.
287
func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
288
data, payloadType, err := cd.Marshal(v)
293
defer ws.wio.Unlock()
294
w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
298
_, err = w.Write(data)
303
// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
304
func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
306
defer ws.rio.Unlock()
307
if ws.frameReader != nil {
308
_, err = io.Copy(ioutil.Discard, ws.frameReader)
315
frame, err := ws.frameReaderFactory.NewFrameReader()
319
frame, err = ws.frameHandler.HandleFrame(frame)
326
payloadType := frame.PayloadType()
327
data, err := ioutil.ReadAll(frame)
331
return cd.Unmarshal(data, payloadType, v)
334
func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
335
switch data := v.(type) {
337
return []byte(data), TextFrame, nil
339
return data, BinaryFrame, nil
341
return nil, UnknownFrame, ErrNotSupported
344
func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
345
switch data := v.(type) {
353
return ErrNotSupported
357
Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
358
To send/receive text frame, use string type.
359
To send/receive binary frame, use []byte type.
365
// receive text frame
367
websocket.Message.Receive(ws, &message)
371
websocket.Message.Send(ws, message)
373
// receive binary frame
375
websocket.Message.Receive(ws, &data)
378
data = []byte{0, 1, 2}
379
websocket.Message.Send(ws, data)
382
var Message = Codec{marshal, unmarshal}
384
func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
385
msg, err = json.Marshal(v)
386
return msg, TextFrame, err
389
func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
390
return json.Unmarshal(msg, v)
394
JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
405
// receive JSON type T
407
websocket.JSON.Receive(ws, &data)
410
websocket.JSON.Send(ws, data)
412
var JSON = Codec{jsonMarshal, jsonUnmarshal}