github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go (about)

     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  
     5  // Package websocket implements a client and server for the WebSocket protocol
     6  // as specified in RFC 6455.
     7  package websocket
     8  
     9  import (
    10  	"bufio"
    11  	"crypto/tls"
    12  	"encoding/json"
    13  	"errors"
    14  	"io"
    15  	"io/ioutil"
    16  	"net"
    17  	"net/http"
    18  	"net/url"
    19  	"sync"
    20  	"time"
    21  )
    22  
    23  const (
    24  	ProtocolVersionHybi13    = 13
    25  	ProtocolVersionHybi      = ProtocolVersionHybi13
    26  	SupportedProtocolVersion = "13"
    27  
    28  	ContinuationFrame = 0
    29  	TextFrame         = 1
    30  	BinaryFrame       = 2
    31  	CloseFrame        = 8
    32  	PingFrame         = 9
    33  	PongFrame         = 10
    34  	UnknownFrame      = 255
    35  )
    36  
    37  // ProtocolError represents WebSocket protocol errors.
    38  type ProtocolError struct {
    39  	ErrorString string
    40  }
    41  
    42  func (err *ProtocolError) Error() string { return err.ErrorString }
    43  
    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  
    61  // Addr is an implementation of net.Addr for WebSocket.
    62  type Addr struct {
    63  	*url.URL
    64  }
    65  
    66  // Network returns the network type for a WebSocket, "websocket".
    67  func (addr *Addr) Network() string { return "websocket" }
    68  
    69  // Config is a WebSocket configuration
    70  type Config struct {
    71  	// A WebSocket server address.
    72  	Location *url.URL
    73  
    74  	// A Websocket client origin.
    75  	Origin *url.URL
    76  
    77  	// WebSocket subprotocols.
    78  	Protocol []string
    79  
    80  	// WebSocket protocol version.
    81  	Version int
    82  
    83  	// TLS config for secure WebSocket (wss).
    84  	TlsConfig *tls.Config
    85  
    86  	// Additional header fields to be sent in WebSocket opening handshake.
    87  	Header http.Header
    88  
    89  	handshakeData map[string]string
    90  }
    91  
    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)
    97  
    98  	// AcceptHandshake accepts the client handshake request and sends
    99  	// handshake response back to client.
   100  	AcceptHandshake(buf *bufio.Writer) (err error)
   101  
   102  	// NewServerConn creates a new WebSocket connection.
   103  	NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
   104  }
   105  
   106  // frameReader is an interface to read a WebSocket frame.
   107  type frameReader interface {
   108  	// Reader is to read payload of the frame.
   109  	io.Reader
   110  
   111  	// PayloadType returns payload type.
   112  	PayloadType() byte
   113  
   114  	// HeaderReader returns a reader to read header of the frame.
   115  	HeaderReader() io.Reader
   116  
   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
   120  
   121  	// Len returns total length of the frame, including header and trailer.
   122  	Len() int
   123  }
   124  
   125  // frameReaderFactory is an interface to creates new frame reader.
   126  type frameReaderFactory interface {
   127  	NewFrameReader() (r frameReader, err error)
   128  }
   129  
   130  // frameWriter is an interface to write a WebSocket frame.
   131  type frameWriter interface {
   132  	// Writer is to write payload of the frame.
   133  	io.WriteCloser
   134  }
   135  
   136  // frameWriterFactory is an interface to create new frame writer.
   137  type frameWriterFactory interface {
   138  	NewFrameWriter(payloadType byte) (w frameWriter, err error)
   139  }
   140  
   141  type frameHandler interface {
   142  	HandleFrame(frame frameReader) (r frameReader, err error)
   143  	WriteClose(status int) (err error)
   144  }
   145  
   146  // Conn represents a WebSocket connection.
   147  type Conn struct {
   148  	config  *Config
   149  	request *http.Request
   150  
   151  	buf *bufio.ReadWriter
   152  	rwc io.ReadWriteCloser
   153  
   154  	rio sync.Mutex
   155  	frameReaderFactory
   156  	frameReader
   157  
   158  	wio sync.Mutex
   159  	frameWriterFactory
   160  
   161  	frameHandler
   162  	PayloadType        byte
   163  	defaultCloseStatus int
   164  }
   165  
   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) {
   172  	ws.rio.Lock()
   173  	defer ws.rio.Unlock()
   174  again:
   175  	if ws.frameReader == nil {
   176  		frame, err := ws.frameReaderFactory.NewFrameReader()
   177  		if err != nil {
   178  			return 0, err
   179  		}
   180  		ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
   181  		if err != nil {
   182  			return 0, err
   183  		}
   184  		if ws.frameReader == nil {
   185  			goto again
   186  		}
   187  	}
   188  	n, err = ws.frameReader.Read(msg)
   189  	if err == io.EOF {
   190  		if trailer := ws.frameReader.TrailerReader(); trailer != nil {
   191  			io.Copy(ioutil.Discard, trailer)
   192  		}
   193  		ws.frameReader = nil
   194  		goto again
   195  	}
   196  	return n, err
   197  }
   198  
   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) {
   202  	ws.wio.Lock()
   203  	defer ws.wio.Unlock()
   204  	w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
   205  	if err != nil {
   206  		return 0, err
   207  	}
   208  	n, err = w.Write(msg)
   209  	w.Close()
   210  	if err != nil {
   211  		return n, err
   212  	}
   213  	return n, err
   214  }
   215  
   216  // Close implements the io.Closer interface.
   217  func (ws *Conn) Close() error {
   218  	err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
   219  	err1 := ws.rwc.Close()
   220  	if err != nil {
   221  		return err
   222  	}
   223  	return err1
   224  }
   225  
   226  func (ws *Conn) IsClientConn() bool { return ws.request == nil }
   227  func (ws *Conn) IsServerConn() bool { return ws.request != nil }
   228  
   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}
   234  	}
   235  	return &Addr{ws.config.Location}
   236  }
   237  
   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}
   243  	}
   244  	return &Addr{ws.config.Origin}
   245  }
   246  
   247  var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
   248  
   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)
   253  	}
   254  	return errSetDeadline
   255  }
   256  
   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)
   261  	}
   262  	return errSetDeadline
   263  }
   264  
   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)
   269  	}
   270  	return errSetDeadline
   271  }
   272  
   273  // Config returns the WebSocket config.
   274  func (ws *Conn) Config() *Config { return ws.config }
   275  
   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 }
   279  
   280  // Codec represents a symmetric pair of functions that implement a codec.
   281  type Codec struct {
   282  	Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
   283  	Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
   284  }
   285  
   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)
   289  	if err != nil {
   290  		return err
   291  	}
   292  	ws.wio.Lock()
   293  	defer ws.wio.Unlock()
   294  	w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
   295  	if err != nil {
   296  		return err
   297  	}
   298  	_, err = w.Write(data)
   299  	w.Close()
   300  	return err
   301  }
   302  
   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) {
   305  	ws.rio.Lock()
   306  	defer ws.rio.Unlock()
   307  	if ws.frameReader != nil {
   308  		_, err = io.Copy(ioutil.Discard, ws.frameReader)
   309  		if err != nil {
   310  			return err
   311  		}
   312  		ws.frameReader = nil
   313  	}
   314  again:
   315  	frame, err := ws.frameReaderFactory.NewFrameReader()
   316  	if err != nil {
   317  		return err
   318  	}
   319  	frame, err = ws.frameHandler.HandleFrame(frame)
   320  	if err != nil {
   321  		return err
   322  	}
   323  	if frame == nil {
   324  		goto again
   325  	}
   326  	payloadType := frame.PayloadType()
   327  	data, err := ioutil.ReadAll(frame)
   328  	if err != nil {
   329  		return err
   330  	}
   331  	return cd.Unmarshal(data, payloadType, v)
   332  }
   333  
   334  func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
   335  	switch data := v.(type) {
   336  	case string:
   337  		return []byte(data), TextFrame, nil
   338  	case []byte:
   339  		return data, BinaryFrame, nil
   340  	}
   341  	return nil, UnknownFrame, ErrNotSupported
   342  }
   343  
   344  func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
   345  	switch data := v.(type) {
   346  	case *string:
   347  		*data = string(msg)
   348  		return nil
   349  	case *[]byte:
   350  		*data = msg
   351  		return nil
   352  	}
   353  	return ErrNotSupported
   354  }
   355  
   356  /*
   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.
   360  
   361  Trivial usage:
   362  
   363  	import "websocket"
   364  
   365  	// receive text frame
   366  	var message string
   367  	websocket.Message.Receive(ws, &message)
   368  
   369  	// send text frame
   370  	message = "hello"
   371  	websocket.Message.Send(ws, message)
   372  
   373  	// receive binary frame
   374  	var data []byte
   375  	websocket.Message.Receive(ws, &data)
   376  
   377  	// send binary frame
   378  	data = []byte{0, 1, 2}
   379  	websocket.Message.Send(ws, data)
   380  
   381  */
   382  var Message = Codec{marshal, unmarshal}
   383  
   384  func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
   385  	msg, err = json.Marshal(v)
   386  	return msg, TextFrame, err
   387  }
   388  
   389  func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
   390  	return json.Unmarshal(msg, v)
   391  }
   392  
   393  /*
   394  JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
   395  
   396  Trivial usage:
   397  
   398  	import "websocket"
   399  
   400  	type T struct {
   401  		Msg string
   402  		Count int
   403  	}
   404  
   405  	// receive JSON type T
   406  	var data T
   407  	websocket.JSON.Receive(ws, &data)
   408  
   409  	// send JSON type T
   410  	websocket.JSON.Send(ws, data)
   411  */
   412  var JSON = Codec{jsonMarshal, jsonUnmarshal}