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
23 ProtocolVersionHixie75 = -75
24 ProtocolVersionHixie76 = -76
25 ProtocolVersionHybi00 = 0
26 ProtocolVersionHybi08 = 8
27 ProtocolVersionHybi13 = 13
28 ProtocolVersionHybi = ProtocolVersionHybi13
29 SupportedProtocolVersion = "13, 8"
40 // WebSocket protocol errors.
41 type ProtocolError struct {
45 func (err *ProtocolError) Error() string { return err.ErrorString }
48 ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
49 ErrBadScheme = &ProtocolError{"bad scheme"}
50 ErrBadStatus = &ProtocolError{"bad status"}
51 ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
52 ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
53 ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
54 ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
55 ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
56 ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
57 ErrBadFrame = &ProtocolError{"bad frame"}
58 ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
59 ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
60 ErrBadRequestMethod = &ProtocolError{"bad method"}
61 ErrNotSupported = &ProtocolError{"not supported"}
64 // Addr is an implementation of net.Addr for WebSocket.
69 // Network returns the network type for a WebSocket, "websocket".
70 func (addr *Addr) Network() string { return "websocket" }
72 // Config is a WebSocket configuration
74 // A WebSocket server address.
77 // A Websocket client origin.
80 // WebSocket subprotocols.
83 // WebSocket protocol version.
86 // TLS config for secure WebSocket (wss).
89 handshakeData map[string]string
92 // serverHandshaker is an interface to handle WebSocket server side handshake.
93 type serverHandshaker interface {
94 // ReadHandshake reads handshake request message from client.
95 // Returns http response code and error if any.
96 ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
98 // AcceptHandshake accepts the client handshake request and sends
99 // handshake response back to client.
100 AcceptHandshake(buf *bufio.Writer) (err error)
102 // NewServerConn creates a new WebSocket connection.
103 NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
106 // frameReader is an interface to read a WebSocket frame.
107 type frameReader interface {
108 // Reader is to read payload of the frame.
111 // PayloadType returns payload type.
114 // HeaderReader returns a reader to read header of the frame.
115 HeaderReader() io.Reader
117 // TrailerReader returns a reader to read trailer of the frame.
118 // If it returns nil, there is no trailer in the frame.
119 TrailerReader() io.Reader
121 // Len returns total length of the frame, including header and trailer.
125 // frameReaderFactory is an interface to creates new frame reader.
126 type frameReaderFactory interface {
127 NewFrameReader() (r frameReader, err error)
130 // frameWriter is an interface to write a WebSocket frame.
131 type frameWriter interface {
132 // Writer is to write playload of the frame.
136 // frameWriterFactory is an interface to create new frame writer.
137 type frameWriterFactory interface {
138 NewFrameWriter(payloadType byte) (w frameWriter, err error)
141 type frameHandler interface {
142 HandleFrame(frame frameReader) (r frameReader, err error)
143 WriteClose(status int) (err error)
146 // Conn represents a WebSocket connection.
149 request *http.Request
151 buf *bufio.ReadWriter
152 rwc io.ReadWriteCloser
163 defaultCloseStatus int
166 // Read implements the io.Reader interface:
167 // it reads data of a frame from the WebSocket connection.
168 // if msg is not large enough for the frame data, it fills the msg and next Read
169 // will read the rest of the frame data.
170 // it reads Text frame or Binary frame.
171 func (ws *Conn) Read(msg []byte) (n int, err error) {
173 defer ws.rio.Unlock()
175 if ws.frameReader == nil {
176 frame, err := ws.frameReaderFactory.NewFrameReader()
180 ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
184 if ws.frameReader == nil {
188 n, err = ws.frameReader.Read(msg)
190 if trailer := ws.frameReader.TrailerReader(); trailer != nil {
191 io.Copy(ioutil.Discard, trailer)
199 // Write implements the io.Writer interface:
200 // it writes data as a frame to the WebSocket connection.
201 func (ws *Conn) Write(msg []byte) (n int, err error) {
203 defer ws.wio.Unlock()
204 w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
208 n, err = w.Write(msg)
216 // Close implements the io.Closer interface.
217 func (ws *Conn) Close() error {
218 err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
222 return ws.rwc.Close()
225 func (ws *Conn) IsClientConn() bool { return ws.request == nil }
226 func (ws *Conn) IsServerConn() bool { return ws.request != nil }
228 // LocalAddr returns the WebSocket Origin for the connection for client, or
229 // the WebSocket location for server.
230 func (ws *Conn) LocalAddr() net.Addr {
231 if ws.IsClientConn() {
232 return &Addr{ws.config.Origin}
234 return &Addr{ws.config.Location}
237 // RemoteAddr returns the WebSocket location for the connection for client, or
238 // the Websocket Origin for server.
239 func (ws *Conn) RemoteAddr() net.Addr {
240 if ws.IsClientConn() {
241 return &Addr{ws.config.Location}
243 return &Addr{ws.config.Origin}
246 // SetTimeout sets the connection's network timeout in nanoseconds.
247 func (ws *Conn) SetTimeout(nsec int64) error {
248 if conn, ok := ws.rwc.(net.Conn); ok {
249 return conn.SetTimeout(nsec)
254 // SetReadTimeout sets the connection's network read timeout in nanoseconds.
255 func (ws *Conn) SetReadTimeout(nsec int64) error {
256 if conn, ok := ws.rwc.(net.Conn); ok {
257 return conn.SetReadTimeout(nsec)
262 // SetWriteTimeout sets the connection's network write timeout in nanoseconds.
263 func (ws *Conn) SetWriteTimeout(nsec int64) error {
264 if conn, ok := ws.rwc.(net.Conn); ok {
265 return conn.SetWriteTimeout(nsec)
270 // Config returns the WebSocket config.
271 func (ws *Conn) Config() *Config { return ws.config }
273 // Request returns the http request upgraded to the WebSocket.
274 // It is nil for client side.
275 func (ws *Conn) Request() *http.Request { return ws.request }
277 // Codec represents a symmetric pair of functions that implement a codec.
279 Marshal func(v interface{}) (data []byte, payloadType byte, err error)
280 Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
283 // Send sends v marshaled by cd.Marshal as single frame to ws.
284 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)
295 _, err = w.Write(data)
300 // Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
301 func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
303 defer ws.rio.Unlock()
304 if ws.frameReader != nil {
305 _, err = io.Copy(ioutil.Discard, ws.frameReader)
312 frame, err := ws.frameReaderFactory.NewFrameReader()
316 frame, err = ws.frameHandler.HandleFrame(frame)
323 payloadType := frame.PayloadType()
324 data, err := ioutil.ReadAll(frame)
328 return cd.Unmarshal(data, payloadType, v)
331 func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
332 switch data := v.(type) {
334 return []byte(data), TextFrame, nil
336 return data, BinaryFrame, nil
338 return nil, UnknownFrame, ErrNotSupported
341 func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
342 switch data := v.(type) {
350 return ErrNotSupported
354 Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
355 To send/receive text frame, use string type.
356 To send/receive binary frame, use []byte type.
362 // receive text frame
364 websocket.Message.Receive(ws, &message)
368 websocket.Message.Send(ws, message)
370 // receive binary frame
372 websocket.Message.Receive(ws, &data)
375 data = []byte{0, 1, 2}
376 websocket.Message.Send(ws, data)
379 var Message = Codec{marshal, unmarshal}
381 func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
382 msg, err = json.Marshal(v)
383 return msg, TextFrame, err
386 func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
387 return json.Unmarshal(msg, v)
391 JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
402 // receive JSON type T
404 websocket.JSON.Receive(ws, &data)
407 websocket.JSON.Send(ws, data)
409 var JSON = Codec{jsonMarshal, jsonUnmarshal}