summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/net/websocket
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/net/websocket')
-rw-r--r--vendor/golang.org/x/net/websocket/client.go106
-rw-r--r--vendor/golang.org/x/net/websocket/dial.go24
-rw-r--r--vendor/golang.org/x/net/websocket/dial_test.go43
-rw-r--r--vendor/golang.org/x/net/websocket/exampledial_test.go31
-rw-r--r--vendor/golang.org/x/net/websocket/examplehandler_test.go26
-rw-r--r--vendor/golang.org/x/net/websocket/hybi.go583
-rw-r--r--vendor/golang.org/x/net/websocket/hybi_test.go608
-rw-r--r--vendor/golang.org/x/net/websocket/server.go113
-rw-r--r--vendor/golang.org/x/net/websocket/websocket.go448
-rw-r--r--vendor/golang.org/x/net/websocket/websocket_test.go665
10 files changed, 0 insertions, 2647 deletions
diff --git a/vendor/golang.org/x/net/websocket/client.go b/vendor/golang.org/x/net/websocket/client.go
deleted file mode 100644
index 69a4ac7ee..000000000
--- a/vendor/golang.org/x/net/websocket/client.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "io"
- "net"
- "net/http"
- "net/url"
-)
-
-// DialError is an error that occurs while dialling a websocket server.
-type DialError struct {
- *Config
- Err error
-}
-
-func (e *DialError) Error() string {
- return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
-}
-
-// NewConfig creates a new WebSocket config for client connection.
-func NewConfig(server, origin string) (config *Config, err error) {
- config = new(Config)
- config.Version = ProtocolVersionHybi13
- config.Location, err = url.ParseRequestURI(server)
- if err != nil {
- return
- }
- config.Origin, err = url.ParseRequestURI(origin)
- if err != nil {
- return
- }
- config.Header = http.Header(make(map[string][]string))
- return
-}
-
-// NewClient creates a new WebSocket client connection over rwc.
-func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- err = hybiClientHandshake(config, br, bw)
- if err != nil {
- return
- }
- buf := bufio.NewReadWriter(br, bw)
- ws = newHybiClientConn(config, buf, rwc)
- return
-}
-
-// Dial opens a new client connection to a WebSocket.
-func Dial(url_, protocol, origin string) (ws *Conn, err error) {
- config, err := NewConfig(url_, origin)
- if err != nil {
- return nil, err
- }
- if protocol != "" {
- config.Protocol = []string{protocol}
- }
- return DialConfig(config)
-}
-
-var portMap = map[string]string{
- "ws": "80",
- "wss": "443",
-}
-
-func parseAuthority(location *url.URL) string {
- if _, ok := portMap[location.Scheme]; ok {
- if _, _, err := net.SplitHostPort(location.Host); err != nil {
- return net.JoinHostPort(location.Host, portMap[location.Scheme])
- }
- }
- return location.Host
-}
-
-// DialConfig opens a new client connection to a WebSocket with a config.
-func DialConfig(config *Config) (ws *Conn, err error) {
- var client net.Conn
- if config.Location == nil {
- return nil, &DialError{config, ErrBadWebSocketLocation}
- }
- if config.Origin == nil {
- return nil, &DialError{config, ErrBadWebSocketOrigin}
- }
- dialer := config.Dialer
- if dialer == nil {
- dialer = &net.Dialer{}
- }
- client, err = dialWithDialer(dialer, config)
- if err != nil {
- goto Error
- }
- ws, err = NewClient(config, client)
- if err != nil {
- client.Close()
- goto Error
- }
- return
-
-Error:
- return nil, &DialError{config, err}
-}
diff --git a/vendor/golang.org/x/net/websocket/dial.go b/vendor/golang.org/x/net/websocket/dial.go
deleted file mode 100644
index 2dab943a4..000000000
--- a/vendor/golang.org/x/net/websocket/dial.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "crypto/tls"
- "net"
-)
-
-func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) {
- switch config.Location.Scheme {
- case "ws":
- conn, err = dialer.Dial("tcp", parseAuthority(config.Location))
-
- case "wss":
- conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig)
-
- default:
- err = ErrBadScheme
- }
- return
-}
diff --git a/vendor/golang.org/x/net/websocket/dial_test.go b/vendor/golang.org/x/net/websocket/dial_test.go
deleted file mode 100644
index aa03e30dd..000000000
--- a/vendor/golang.org/x/net/websocket/dial_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "crypto/tls"
- "fmt"
- "log"
- "net"
- "net/http/httptest"
- "testing"
- "time"
-)
-
-// This test depend on Go 1.3+ because in earlier versions the Dialer won't be
-// used in TLS connections and a timeout won't be triggered.
-func TestDialConfigTLSWithDialer(t *testing.T) {
- tlsServer := httptest.NewTLSServer(nil)
- tlsServerAddr := tlsServer.Listener.Addr().String()
- log.Print("Test TLS WebSocket server listening on ", tlsServerAddr)
- defer tlsServer.Close()
- config, _ := NewConfig(fmt.Sprintf("wss://%s/echo", tlsServerAddr), "http://localhost")
- config.Dialer = &net.Dialer{
- Deadline: time.Now().Add(-time.Minute),
- }
- config.TlsConfig = &tls.Config{
- InsecureSkipVerify: true,
- }
- _, err := DialConfig(config)
- dialerr, ok := err.(*DialError)
- if !ok {
- t.Fatalf("DialError expected, got %#v", err)
- }
- neterr, ok := dialerr.Err.(*net.OpError)
- if !ok {
- t.Fatalf("net.OpError error expected, got %#v", dialerr.Err)
- }
- if !neterr.Timeout() {
- t.Fatalf("expected timeout error, got %#v", neterr)
- }
-}
diff --git a/vendor/golang.org/x/net/websocket/exampledial_test.go b/vendor/golang.org/x/net/websocket/exampledial_test.go
deleted file mode 100644
index 72bb9d48e..000000000
--- a/vendor/golang.org/x/net/websocket/exampledial_test.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket_test
-
-import (
- "fmt"
- "log"
-
- "golang.org/x/net/websocket"
-)
-
-// This example demonstrates a trivial client.
-func ExampleDial() {
- origin := "http://localhost/"
- url := "ws://localhost:12345/ws"
- ws, err := websocket.Dial(url, "", origin)
- if err != nil {
- log.Fatal(err)
- }
- if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
- log.Fatal(err)
- }
- var msg = make([]byte, 512)
- var n int
- if n, err = ws.Read(msg); err != nil {
- log.Fatal(err)
- }
- fmt.Printf("Received: %s.\n", msg[:n])
-}
diff --git a/vendor/golang.org/x/net/websocket/examplehandler_test.go b/vendor/golang.org/x/net/websocket/examplehandler_test.go
deleted file mode 100644
index f22a98fcd..000000000
--- a/vendor/golang.org/x/net/websocket/examplehandler_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket_test
-
-import (
- "io"
- "net/http"
-
- "golang.org/x/net/websocket"
-)
-
-// Echo the data received on the WebSocket.
-func EchoServer(ws *websocket.Conn) {
- io.Copy(ws, ws)
-}
-
-// This example demonstrates a trivial echo server.
-func ExampleHandler() {
- http.Handle("/echo", websocket.Handler(EchoServer))
- err := http.ListenAndServe(":12345", nil)
- if err != nil {
- panic("ListenAndServe: " + err.Error())
- }
-}
diff --git a/vendor/golang.org/x/net/websocket/hybi.go b/vendor/golang.org/x/net/websocket/hybi.go
deleted file mode 100644
index 8cffdd16c..000000000
--- a/vendor/golang.org/x/net/websocket/hybi.go
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-// This file implements a protocol of hybi draft.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-
-import (
- "bufio"
- "bytes"
- "crypto/rand"
- "crypto/sha1"
- "encoding/base64"
- "encoding/binary"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "strings"
-)
-
-const (
- websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
- closeStatusNormal = 1000
- closeStatusGoingAway = 1001
- closeStatusProtocolError = 1002
- closeStatusUnsupportedData = 1003
- closeStatusFrameTooLarge = 1004
- closeStatusNoStatusRcvd = 1005
- closeStatusAbnormalClosure = 1006
- closeStatusBadMessageData = 1007
- closeStatusPolicyViolation = 1008
- closeStatusTooBigData = 1009
- closeStatusExtensionMismatch = 1010
-
- maxControlFramePayloadLength = 125
-)
-
-var (
- ErrBadMaskingKey = &ProtocolError{"bad masking key"}
- ErrBadPongMessage = &ProtocolError{"bad pong message"}
- ErrBadClosingStatus = &ProtocolError{"bad closing status"}
- ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
- ErrNotImplemented = &ProtocolError{"not implemented"}
-
- handshakeHeader = map[string]bool{
- "Host": true,
- "Upgrade": true,
- "Connection": true,
- "Sec-Websocket-Key": true,
- "Sec-Websocket-Origin": true,
- "Sec-Websocket-Version": true,
- "Sec-Websocket-Protocol": true,
- "Sec-Websocket-Accept": true,
- }
-)
-
-// A hybiFrameHeader is a frame header as defined in hybi draft.
-type hybiFrameHeader struct {
- Fin bool
- Rsv [3]bool
- OpCode byte
- Length int64
- MaskingKey []byte
-
- data *bytes.Buffer
-}
-
-// A hybiFrameReader is a reader for hybi frame.
-type hybiFrameReader struct {
- reader io.Reader
-
- header hybiFrameHeader
- pos int64
- length int
-}
-
-func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
- n, err = frame.reader.Read(msg)
- if frame.header.MaskingKey != nil {
- for i := 0; i < n; i++ {
- msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
- frame.pos++
- }
- }
- return n, err
-}
-
-func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
-
-func (frame *hybiFrameReader) HeaderReader() io.Reader {
- if frame.header.data == nil {
- return nil
- }
- if frame.header.data.Len() == 0 {
- return nil
- }
- return frame.header.data
-}
-
-func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hybiFrameReader) Len() (n int) { return frame.length }
-
-// A hybiFrameReaderFactory creates new frame reader based on its frame type.
-type hybiFrameReaderFactory struct {
- *bufio.Reader
-}
-
-// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
-// See Section 5.2 Base Framing protocol for detail.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
-func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
- hybiFrame := new(hybiFrameReader)
- frame = hybiFrame
- var header []byte
- var b byte
- // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
- for i := 0; i < 3; i++ {
- j := uint(6 - i)
- hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
- }
- hybiFrame.header.OpCode = header[0] & 0x0f
-
- // Second byte. Mask/Payload len(7bits)
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- mask := (b & 0x80) != 0
- b &= 0x7f
- lengthFields := 0
- switch {
- case b <= 125: // Payload length 7bits.
- hybiFrame.header.Length = int64(b)
- case b == 126: // Payload length 7+16bits
- lengthFields = 2
- case b == 127: // Payload length 7+64bits
- lengthFields = 8
- }
- for i := 0; i < lengthFields; i++ {
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits
- b &= 0x7f
- }
- header = append(header, b)
- hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
- }
- if mask {
- // Masking key. 4 bytes.
- for i := 0; i < 4; i++ {
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
- }
- }
- hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
- hybiFrame.header.data = bytes.NewBuffer(header)
- hybiFrame.length = len(header) + int(hybiFrame.header.Length)
- return
-}
-
-// A HybiFrameWriter is a writer for hybi frame.
-type hybiFrameWriter struct {
- writer *bufio.Writer
-
- header *hybiFrameHeader
-}
-
-func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
- var header []byte
- var b byte
- if frame.header.Fin {
- b |= 0x80
- }
- for i := 0; i < 3; i++ {
- if frame.header.Rsv[i] {
- j := uint(6 - i)
- b |= 1 << j
- }
- }
- b |= frame.header.OpCode
- header = append(header, b)
- if frame.header.MaskingKey != nil {
- b = 0x80
- } else {
- b = 0
- }
- lengthFields := 0
- length := len(msg)
- switch {
- case length <= 125:
- b |= byte(length)
- case length < 65536:
- b |= 126
- lengthFields = 2
- default:
- b |= 127
- lengthFields = 8
- }
- header = append(header, b)
- for i := 0; i < lengthFields; i++ {
- j := uint((lengthFields - i - 1) * 8)
- b = byte((length >> j) & 0xff)
- header = append(header, b)
- }
- if frame.header.MaskingKey != nil {
- if len(frame.header.MaskingKey) != 4 {
- return 0, ErrBadMaskingKey
- }
- header = append(header, frame.header.MaskingKey...)
- frame.writer.Write(header)
- data := make([]byte, length)
- for i := range data {
- data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
- }
- frame.writer.Write(data)
- err = frame.writer.Flush()
- return length, err
- }
- frame.writer.Write(header)
- frame.writer.Write(msg)
- err = frame.writer.Flush()
- return length, err
-}
-
-func (frame *hybiFrameWriter) Close() error { return nil }
-
-type hybiFrameWriterFactory struct {
- *bufio.Writer
- needMaskingKey bool
-}
-
-func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
- if buf.needMaskingKey {
- frameHeader.MaskingKey, err = generateMaskingKey()
- if err != nil {
- return nil, err
- }
- }
- return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
-}
-
-type hybiFrameHandler struct {
- conn *Conn
- payloadType byte
-}
-
-func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) {
- if handler.conn.IsServerConn() {
- // The client MUST mask all frames sent to the server.
- if frame.(*hybiFrameReader).header.MaskingKey == nil {
- handler.WriteClose(closeStatusProtocolError)
- return nil, io.EOF
- }
- } else {
- // The server MUST NOT mask all frames.
- if frame.(*hybiFrameReader).header.MaskingKey != nil {
- handler.WriteClose(closeStatusProtocolError)
- return nil, io.EOF
- }
- }
- if header := frame.HeaderReader(); header != nil {
- io.Copy(ioutil.Discard, header)
- }
- switch frame.PayloadType() {
- case ContinuationFrame:
- frame.(*hybiFrameReader).header.OpCode = handler.payloadType
- case TextFrame, BinaryFrame:
- handler.payloadType = frame.PayloadType()
- case CloseFrame:
- return nil, io.EOF
- case PingFrame, PongFrame:
- b := make([]byte, maxControlFramePayloadLength)
- n, err := io.ReadFull(frame, b)
- if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
- return nil, err
- }
- io.Copy(ioutil.Discard, frame)
- if frame.PayloadType() == PingFrame {
- if _, err := handler.WritePong(b[:n]); err != nil {
- return nil, err
- }
- }
- return nil, nil
- }
- return frame, nil
-}
-
-func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
- handler.conn.wio.Lock()
- defer handler.conn.wio.Unlock()
- w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
- if err != nil {
- return err
- }
- msg := make([]byte, 2)
- binary.BigEndian.PutUint16(msg, uint16(status))
- _, err = w.Write(msg)
- w.Close()
- return err
-}
-
-func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
- handler.conn.wio.Lock()
- defer handler.conn.wio.Unlock()
- w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
- if err != nil {
- return 0, err
- }
- n, err = w.Write(msg)
- w.Close()
- return n, err
-}
-
-// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
-func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- if buf == nil {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- buf = bufio.NewReadWriter(br, bw)
- }
- ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
- frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
- frameWriterFactory: hybiFrameWriterFactory{
- buf.Writer, request == nil},
- PayloadType: TextFrame,
- defaultCloseStatus: closeStatusNormal}
- ws.frameHandler = &hybiFrameHandler{conn: ws}
- return ws
-}
-
-// generateMaskingKey generates a masking key for a frame.
-func generateMaskingKey() (maskingKey []byte, err error) {
- maskingKey = make([]byte, 4)
- if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
- return
- }
- return
-}
-
-// generateNonce generates a nonce consisting of a randomly selected 16-byte
-// value that has been base64-encoded.
-func generateNonce() (nonce []byte) {
- key := make([]byte, 16)
- if _, err := io.ReadFull(rand.Reader, key); err != nil {
- panic(err)
- }
- nonce = make([]byte, 24)
- base64.StdEncoding.Encode(nonce, key)
- return
-}
-
-// removeZone removes IPv6 zone identifer from host.
-// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
-func removeZone(host string) string {
- if !strings.HasPrefix(host, "[") {
- return host
- }
- i := strings.LastIndex(host, "]")
- if i < 0 {
- return host
- }
- j := strings.LastIndex(host[:i], "%")
- if j < 0 {
- return host
- }
- return host[:j] + host[i:]
-}
-
-// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
-// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
-func getNonceAccept(nonce []byte) (expected []byte, err error) {
- h := sha1.New()
- if _, err = h.Write(nonce); err != nil {
- return
- }
- if _, err = h.Write([]byte(websocketGUID)); err != nil {
- return
- }
- expected = make([]byte, 28)
- base64.StdEncoding.Encode(expected, h.Sum(nil))
- return
-}
-
-// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
-func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
- bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-
- // According to RFC 6874, an HTTP client, proxy, or other
- // intermediary must remove any IPv6 zone identifier attached
- // to an outgoing URI.
- bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n")
- bw.WriteString("Upgrade: websocket\r\n")
- bw.WriteString("Connection: Upgrade\r\n")
- nonce := generateNonce()
- if config.handshakeData != nil {
- nonce = []byte(config.handshakeData["key"])
- }
- bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
- bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
-
- if config.Version != ProtocolVersionHybi13 {
- return ErrBadProtocolVersion
- }
-
- bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
- if len(config.Protocol) > 0 {
- bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
- }
- // TODO(ukai): send Sec-WebSocket-Extensions.
- err = config.Header.WriteSubset(bw, handshakeHeader)
- if err != nil {
- return err
- }
-
- bw.WriteString("\r\n")
- if err = bw.Flush(); err != nil {
- return err
- }
-
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return err
- }
- if resp.StatusCode != 101 {
- return ErrBadStatus
- }
- if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
- strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
- return ErrBadUpgrade
- }
- expectedAccept, err := getNonceAccept(nonce)
- if err != nil {
- return err
- }
- if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
- return ErrChallengeResponse
- }
- if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
- return ErrUnsupportedExtensions
- }
- offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
- if offeredProtocol != "" {
- protocolMatched := false
- for i := 0; i < len(config.Protocol); i++ {
- if config.Protocol[i] == offeredProtocol {
- protocolMatched = true
- break
- }
- }
- if !protocolMatched {
- return ErrBadWebSocketProtocol
- }
- config.Protocol = []string{offeredProtocol}
- }
-
- return nil
-}
-
-// newHybiClientConn creates a client WebSocket connection after handshake.
-func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
- return newHybiConn(config, buf, rwc, nil)
-}
-
-// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
-type hybiServerHandshaker struct {
- *Config
- accept []byte
-}
-
-func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
- c.Version = ProtocolVersionHybi13
- if req.Method != "GET" {
- return http.StatusMethodNotAllowed, ErrBadRequestMethod
- }
- // HTTP version can be safely ignored.
-
- if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
- !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
- return http.StatusBadRequest, ErrNotWebSocket
- }
-
- key := req.Header.Get("Sec-Websocket-Key")
- if key == "" {
- return http.StatusBadRequest, ErrChallengeResponse
- }
- version := req.Header.Get("Sec-Websocket-Version")
- switch version {
- case "13":
- c.Version = ProtocolVersionHybi13
- default:
- return http.StatusBadRequest, ErrBadWebSocketVersion
- }
- var scheme string
- if req.TLS != nil {
- scheme = "wss"
- } else {
- scheme = "ws"
- }
- c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
- if err != nil {
- return http.StatusBadRequest, err
- }
- protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
- if protocol != "" {
- protocols := strings.Split(protocol, ",")
- for i := 0; i < len(protocols); i++ {
- c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
- }
- }
- c.accept, err = getNonceAccept([]byte(key))
- if err != nil {
- return http.StatusInternalServerError, err
- }
- return http.StatusSwitchingProtocols, nil
-}
-
-// Origin parses the Origin header in req.
-// If the Origin header is not set, it returns nil and nil.
-func Origin(config *Config, req *http.Request) (*url.URL, error) {
- var origin string
- switch config.Version {
- case ProtocolVersionHybi13:
- origin = req.Header.Get("Origin")
- }
- if origin == "" {
- return nil, nil
- }
- return url.ParseRequestURI(origin)
-}
-
-func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
- if len(c.Protocol) > 0 {
- if len(c.Protocol) != 1 {
- // You need choose a Protocol in Handshake func in Server.
- return ErrBadWebSocketProtocol
- }
- }
- buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
- buf.WriteString("Upgrade: websocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
- if len(c.Protocol) > 0 {
- buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
- }
- // TODO(ukai): send Sec-WebSocket-Extensions.
- if c.Header != nil {
- err := c.Header.WriteSubset(buf, handshakeHeader)
- if err != nil {
- return err
- }
- }
- buf.WriteString("\r\n")
- return buf.Flush()
-}
-
-func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- return newHybiServerConn(c.Config, buf, rwc, request)
-}
-
-// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
-func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- return newHybiConn(config, buf, rwc, request)
-}
diff --git a/vendor/golang.org/x/net/websocket/hybi_test.go b/vendor/golang.org/x/net/websocket/hybi_test.go
deleted file mode 100644
index 9504aa2d3..000000000
--- a/vendor/golang.org/x/net/websocket/hybi_test.go
+++ /dev/null
@@ -1,608 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
- "testing"
-)
-
-// Test the getNonceAccept function with values in
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-func TestSecWebSocketAccept(t *testing.T) {
- nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
- expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
- accept, err := getNonceAccept(nonce)
- if err != nil {
- t.Errorf("getNonceAccept: returned error %v", err)
- return
- }
- if !bytes.Equal(expected, accept) {
- t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
- }
-}
-
-func TestHybiClientHandshake(t *testing.T) {
- type test struct {
- url, host string
- }
- tests := []test{
- {"ws://server.example.com/chat", "server.example.com"},
- {"ws://127.0.0.1/chat", "127.0.0.1"},
- }
- if _, err := url.ParseRequestURI("http://[fe80::1%25lo0]"); err == nil {
- tests = append(tests, test{"ws://[fe80::1%25lo0]/chat", "[fe80::1]"})
- }
-
- for _, tt := range tests {
- var b bytes.Buffer
- bw := bufio.NewWriter(&b)
- br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
- var err error
- var config Config
- config.Location, err = url.ParseRequestURI(tt.url)
- if err != nil {
- t.Fatal("location url", err)
- }
- config.Origin, err = url.ParseRequestURI("http://example.com")
- if err != nil {
- t.Fatal("origin url", err)
- }
- config.Protocol = append(config.Protocol, "chat")
- config.Protocol = append(config.Protocol, "superchat")
- config.Version = ProtocolVersionHybi13
- config.handshakeData = map[string]string{
- "key": "dGhlIHNhbXBsZSBub25jZQ==",
- }
- if err := hybiClientHandshake(&config, br, bw); err != nil {
- t.Fatal("handshake", err)
- }
- req, err := http.ReadRequest(bufio.NewReader(&b))
- if err != nil {
- t.Fatal("read request", err)
- }
- if req.Method != "GET" {
- t.Errorf("request method expected GET, but got %s", req.Method)
- }
- if req.URL.Path != "/chat" {
- t.Errorf("request path expected /chat, but got %s", req.URL.Path)
- }
- if req.Proto != "HTTP/1.1" {
- t.Errorf("request proto expected HTTP/1.1, but got %s", req.Proto)
- }
- if req.Host != tt.host {
- t.Errorf("request host expected %s, but got %s", tt.host, req.Host)
- }
- var expectedHeader = map[string]string{
- "Connection": "Upgrade",
- "Upgrade": "websocket",
- "Sec-Websocket-Key": config.handshakeData["key"],
- "Origin": config.Origin.String(),
- "Sec-Websocket-Protocol": "chat, superchat",
- "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
- }
- for k, v := range expectedHeader {
- if req.Header.Get(k) != v {
- t.Errorf("%s expected %s, but got %v", k, v, req.Header.Get(k))
- }
- }
- }
-}
-
-func TestHybiClientHandshakeWithHeader(t *testing.T) {
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
- br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
- var err error
- config := new(Config)
- config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
- if err != nil {
- t.Fatal("location url", err)
- }
- config.Origin, err = url.ParseRequestURI("http://example.com")
- if err != nil {
- t.Fatal("origin url", err)
- }
- config.Protocol = append(config.Protocol, "chat")
- config.Protocol = append(config.Protocol, "superchat")
- config.Version = ProtocolVersionHybi13
- config.Header = http.Header(make(map[string][]string))
- config.Header.Add("User-Agent", "test")
-
- config.handshakeData = map[string]string{
- "key": "dGhlIHNhbXBsZSBub25jZQ==",
- }
- err = hybiClientHandshake(config, br, bw)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- req, err := http.ReadRequest(bufio.NewReader(b))
- if err != nil {
- t.Fatalf("read request: %v", err)
- }
- if req.Method != "GET" {
- t.Errorf("request method expected GET, but got %q", req.Method)
- }
- if req.URL.Path != "/chat" {
- t.Errorf("request path expected /chat, but got %q", req.URL.Path)
- }
- if req.Proto != "HTTP/1.1" {
- t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
- }
- if req.Host != "server.example.com" {
- t.Errorf("request Host expected server.example.com, but got %v", req.Host)
- }
- var expectedHeader = map[string]string{
- "Connection": "Upgrade",
- "Upgrade": "websocket",
- "Sec-Websocket-Key": config.handshakeData["key"],
- "Origin": config.Origin.String(),
- "Sec-Websocket-Protocol": "chat, superchat",
- "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
- "User-Agent": "test",
- }
- for k, v := range expectedHeader {
- if req.Header.Get(k) != v {
- t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
- }
- }
-}
-
-func TestHybiServerHandshake(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- expectedProtocols := []string{"chat", "superchat"}
- if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
- t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- config.Protocol = config.Protocol[:1]
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "Sec-WebSocket-Protocol: chat",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
-
-func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Version: 13
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- if len(config.Protocol) != 0 {
- t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
-
-func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 9
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != ErrBadWebSocketVersion {
- t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
- }
- if code != http.StatusBadRequest {
- t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
- }
-}
-
-func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
- b := bytes.NewBuffer([]byte{})
- frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
- w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
- w.(*hybiFrameWriter).header = frameHeader
- _, err := w.Write(testPayload)
- w.Close()
- if err != nil {
- t.Errorf("Write error %q", err)
- }
- var expectedFrame []byte
- expectedFrame = append(expectedFrame, testHeader...)
- expectedFrame = append(expectedFrame, testMaskedPayload...)
- if !bytes.Equal(expectedFrame, b.Bytes()) {
- t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
- }
- frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
- r, err := frameReaderFactory.NewFrameReader()
- if err != nil {
- t.Errorf("Read error %q", err)
- }
- if header := r.HeaderReader(); header == nil {
- t.Errorf("no header")
- } else {
- actualHeader := make([]byte, r.Len())
- n, err := header.Read(actualHeader)
- if err != nil {
- t.Errorf("Read header error %q", err)
- } else {
- if n < len(testHeader) {
- t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
- }
- if !bytes.Equal(testHeader, actualHeader[:n]) {
- t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
- }
- }
- }
- if trailer := r.TrailerReader(); trailer != nil {
- t.Errorf("unexpected trailer %q", trailer)
- }
- frame := r.(*hybiFrameReader)
- if frameHeader.Fin != frame.header.Fin ||
- frameHeader.OpCode != frame.header.OpCode ||
- len(testPayload) != int(frame.header.Length) {
- t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
- }
- payload := make([]byte, len(testPayload))
- _, err = r.Read(payload)
- if err != nil && err != io.EOF {
- t.Errorf("read %v", err)
- }
- if !bytes.Equal(testPayload, payload) {
- t.Errorf("payload %q vs %q", testPayload, payload)
- }
-}
-
-func TestHybiShortTextFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
- payload := []byte("hello")
- testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
-
- payload = make([]byte, 125)
- testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiShortMaskedTextFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
- MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
- payload := []byte("hello")
- maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
- header := []byte{0x81, 0x85}
- header = append(header, frameHeader.MaskingKey...)
- testHybiFrame(t, header, payload, maskedPayload, frameHeader)
-}
-
-func TestHybiShortBinaryFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
- payload := []byte("hello")
- testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
-
- payload = make([]byte, 125)
- testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiControlFrame(t *testing.T) {
- payload := []byte("hello")
-
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
- testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: PingFrame}
- testHybiFrame(t, []byte{0x89, 0x00}, nil, nil, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
- testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
- testHybiFrame(t, []byte{0x8A, 0x00}, nil, nil, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
- payload = []byte{0x03, 0xe8} // 1000
- testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
-}
-
-func TestHybiLongFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
- payload := make([]byte, 126)
- testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
-
- payload = make([]byte, 65535)
- testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
-
- payload = make([]byte, 65536)
- testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
-}
-
-func TestHybiClientRead(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
- 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
- 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- msg := make([]byte, 512)
- n, err := conn.Read(msg)
- if err != nil {
- t.Errorf("read 1st frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 1st frame, expect 5, got %d", n)
- }
- if !bytes.Equal(wireData[2:7], msg[:n]) {
- t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
- }
- n, err = conn.Read(msg)
- if err != nil {
- t.Errorf("read 2nd frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 2nd frame, expect 5, got %d", n)
- }
- if !bytes.Equal(wireData[16:21], msg[:n]) {
- t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
- }
- n, err = conn.Read(msg)
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
-}
-
-func TestHybiShortRead(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
- 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
- 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- step := 0
- pos := 0
- expectedPos := []int{2, 5, 16, 19}
- expectedLen := []int{3, 2, 3, 2}
- for {
- msg := make([]byte, 3)
- n, err := conn.Read(msg)
- if step >= len(expectedPos) {
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
- return
- }
- pos = expectedPos[step]
- endPos := pos + expectedLen[step]
- if err != nil {
- t.Errorf("read from %d, got error %q", pos, err)
- return
- }
- if n != endPos-pos {
- t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
- }
- if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
- t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
- }
- step++
- }
-}
-
-func TestHybiServerRead(t *testing.T) {
- wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
- 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
- 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
- 0x9a, 0xec, 0xc6, 0x48, 0x89, // world
- }
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
-
- expected := [][]byte{[]byte("hello"), []byte("world")}
-
- msg := make([]byte, 512)
- n, err := conn.Read(msg)
- if err != nil {
- t.Errorf("read 1st frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 1st frame, expect 5, got %d", n)
- }
- if !bytes.Equal(expected[0], msg[:n]) {
- t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
- }
-
- n, err = conn.Read(msg)
- if err != nil {
- t.Errorf("read 2nd frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 2nd frame, expect 5, got %d", n)
- }
- if !bytes.Equal(expected[1], msg[:n]) {
- t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
- }
-
- n, err = conn.Read(msg)
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
-}
-
-func TestHybiServerReadWithoutMasking(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
- // server MUST close the connection upon receiving a non-masked frame.
- msg := make([]byte, 512)
- _, err := conn.Read(msg)
- if err != io.EOF {
- t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
- }
-}
-
-func TestHybiClientReadWithMasking(t *testing.T) {
- wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
- }
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- // client MUST close the connection upon receiving a masked frame.
- msg := make([]byte, 512)
- _, err := conn.Read(msg)
- if err != io.EOF {
- t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
- }
-}
-
-// Test the hybiServerHandshaker supports firefox implementation and
-// checks Connection request header include (but it's not necessary
-// equal to) "upgrade"
-func TestHybiServerFirefoxHandshake(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: keep-alive, upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- config.Protocol = []string{"chat"}
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "Sec-WebSocket-Protocol: chat",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
diff --git a/vendor/golang.org/x/net/websocket/server.go b/vendor/golang.org/x/net/websocket/server.go
deleted file mode 100644
index 0895dea19..000000000
--- a/vendor/golang.org/x/net/websocket/server.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "fmt"
- "io"
- "net/http"
-)
-
-func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
- var hs serverHandshaker = &hybiServerHandshaker{Config: config}
- code, err := hs.ReadHandshake(buf.Reader, req)
- if err == ErrBadWebSocketVersion {
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
- buf.WriteString("\r\n")
- buf.WriteString(err.Error())
- buf.Flush()
- return
- }
- if err != nil {
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- buf.WriteString("\r\n")
- buf.WriteString(err.Error())
- buf.Flush()
- return
- }
- if handshake != nil {
- err = handshake(config, req)
- if err != nil {
- code = http.StatusForbidden
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- buf.WriteString("\r\n")
- buf.Flush()
- return
- }
- }
- err = hs.AcceptHandshake(buf.Writer)
- if err != nil {
- code = http.StatusBadRequest
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- buf.WriteString("\r\n")
- buf.Flush()
- return
- }
- conn = hs.NewServerConn(buf, rwc, req)
- return
-}
-
-// Server represents a server of a WebSocket.
-type Server struct {
- // Config is a WebSocket configuration for new WebSocket connection.
- Config
-
- // Handshake is an optional function in WebSocket handshake.
- // For example, you can check, or don't check Origin header.
- // Another example, you can select config.Protocol.
- Handshake func(*Config, *http.Request) error
-
- // Handler handles a WebSocket connection.
- Handler
-}
-
-// ServeHTTP implements the http.Handler interface for a WebSocket
-func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- s.serveWebSocket(w, req)
-}
-
-func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
- rwc, buf, err := w.(http.Hijacker).Hijack()
- if err != nil {
- panic("Hijack failed: " + err.Error())
- }
- // The server should abort the WebSocket connection if it finds
- // the client did not send a handshake that matches with protocol
- // specification.
- defer rwc.Close()
- conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
- if err != nil {
- return
- }
- if conn == nil {
- panic("unexpected nil conn")
- }
- s.Handler(conn)
-}
-
-// Handler is a simple interface to a WebSocket browser client.
-// It checks if Origin header is valid URL by default.
-// You might want to verify websocket.Conn.Config().Origin in the func.
-// If you use Server instead of Handler, you could call websocket.Origin and
-// check the origin in your Handshake func. So, if you want to accept
-// non-browser clients, which do not send an Origin header, set a
-// Server.Handshake that does not check the origin.
-type Handler func(*Conn)
-
-func checkOrigin(config *Config, req *http.Request) (err error) {
- config.Origin, err = Origin(config, req)
- if err == nil && config.Origin == nil {
- return fmt.Errorf("null origin")
- }
- return err
-}
-
-// ServeHTTP implements the http.Handler interface for a WebSocket
-func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- s := Server{Handler: h, Handshake: checkOrigin}
- s.serveWebSocket(w, req)
-}
diff --git a/vendor/golang.org/x/net/websocket/websocket.go b/vendor/golang.org/x/net/websocket/websocket.go
deleted file mode 100644
index e242c89a7..000000000
--- a/vendor/golang.org/x/net/websocket/websocket.go
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package websocket implements a client and server for the WebSocket protocol
-// as specified in RFC 6455.
-//
-// This package currently lacks some features found in an alternative
-// and more actively maintained WebSocket package:
-//
-// https://godoc.org/github.com/gorilla/websocket
-//
-package websocket // import "golang.org/x/net/websocket"
-
-import (
- "bufio"
- "crypto/tls"
- "encoding/json"
- "errors"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "sync"
- "time"
-)
-
-const (
- ProtocolVersionHybi13 = 13
- ProtocolVersionHybi = ProtocolVersionHybi13
- SupportedProtocolVersion = "13"
-
- ContinuationFrame = 0
- TextFrame = 1
- BinaryFrame = 2
- CloseFrame = 8
- PingFrame = 9
- PongFrame = 10
- UnknownFrame = 255
-
- DefaultMaxPayloadBytes = 32 << 20 // 32MB
-)
-
-// ProtocolError represents WebSocket protocol errors.
-type ProtocolError struct {
- ErrorString string
-}
-
-func (err *ProtocolError) Error() string { return err.ErrorString }
-
-var (
- ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
- ErrBadScheme = &ProtocolError{"bad scheme"}
- ErrBadStatus = &ProtocolError{"bad status"}
- ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
- ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
- ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
- ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
- ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
- ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
- ErrBadFrame = &ProtocolError{"bad frame"}
- ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
- ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
- ErrBadRequestMethod = &ProtocolError{"bad method"}
- ErrNotSupported = &ProtocolError{"not supported"}
-)
-
-// ErrFrameTooLarge is returned by Codec's Receive method if payload size
-// exceeds limit set by Conn.MaxPayloadBytes
-var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit")
-
-// Addr is an implementation of net.Addr for WebSocket.
-type Addr struct {
- *url.URL
-}
-
-// Network returns the network type for a WebSocket, "websocket".
-func (addr *Addr) Network() string { return "websocket" }
-
-// Config is a WebSocket configuration
-type Config struct {
- // A WebSocket server address.
- Location *url.URL
-
- // A Websocket client origin.
- Origin *url.URL
-
- // WebSocket subprotocols.
- Protocol []string
-
- // WebSocket protocol version.
- Version int
-
- // TLS config for secure WebSocket (wss).
- TlsConfig *tls.Config
-
- // Additional header fields to be sent in WebSocket opening handshake.
- Header http.Header
-
- // Dialer used when opening websocket connections.
- Dialer *net.Dialer
-
- handshakeData map[string]string
-}
-
-// serverHandshaker is an interface to handle WebSocket server side handshake.
-type serverHandshaker interface {
- // ReadHandshake reads handshake request message from client.
- // Returns http response code and error if any.
- ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
-
- // AcceptHandshake accepts the client handshake request and sends
- // handshake response back to client.
- AcceptHandshake(buf *bufio.Writer) (err error)
-
- // NewServerConn creates a new WebSocket connection.
- NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
-}
-
-// frameReader is an interface to read a WebSocket frame.
-type frameReader interface {
- // Reader is to read payload of the frame.
- io.Reader
-
- // PayloadType returns payload type.
- PayloadType() byte
-
- // HeaderReader returns a reader to read header of the frame.
- HeaderReader() io.Reader
-
- // TrailerReader returns a reader to read trailer of the frame.
- // If it returns nil, there is no trailer in the frame.
- TrailerReader() io.Reader
-
- // Len returns total length of the frame, including header and trailer.
- Len() int
-}
-
-// frameReaderFactory is an interface to creates new frame reader.
-type frameReaderFactory interface {
- NewFrameReader() (r frameReader, err error)
-}
-
-// frameWriter is an interface to write a WebSocket frame.
-type frameWriter interface {
- // Writer is to write payload of the frame.
- io.WriteCloser
-}
-
-// frameWriterFactory is an interface to create new frame writer.
-type frameWriterFactory interface {
- NewFrameWriter(payloadType byte) (w frameWriter, err error)
-}
-
-type frameHandler interface {
- HandleFrame(frame frameReader) (r frameReader, err error)
- WriteClose(status int) (err error)
-}
-
-// Conn represents a WebSocket connection.
-//
-// Multiple goroutines may invoke methods on a Conn simultaneously.
-type Conn struct {
- config *Config
- request *http.Request
-
- buf *bufio.ReadWriter
- rwc io.ReadWriteCloser
-
- rio sync.Mutex
- frameReaderFactory
- frameReader
-
- wio sync.Mutex
- frameWriterFactory
-
- frameHandler
- PayloadType byte
- defaultCloseStatus int
-
- // MaxPayloadBytes limits the size of frame payload received over Conn
- // by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used.
- MaxPayloadBytes int
-}
-
-// Read implements the io.Reader interface:
-// it reads data of a frame from the WebSocket connection.
-// if msg is not large enough for the frame data, it fills the msg and next Read
-// will read the rest of the frame data.
-// it reads Text frame or Binary frame.
-func (ws *Conn) Read(msg []byte) (n int, err error) {
- ws.rio.Lock()
- defer ws.rio.Unlock()
-again:
- if ws.frameReader == nil {
- frame, err := ws.frameReaderFactory.NewFrameReader()
- if err != nil {
- return 0, err
- }
- ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
- if err != nil {
- return 0, err
- }
- if ws.frameReader == nil {
- goto again
- }
- }
- n, err = ws.frameReader.Read(msg)
- if err == io.EOF {
- if trailer := ws.frameReader.TrailerReader(); trailer != nil {
- io.Copy(ioutil.Discard, trailer)
- }
- ws.frameReader = nil
- goto again
- }
- return n, err
-}
-
-// Write implements the io.Writer interface:
-// it writes data as a frame to the WebSocket connection.
-func (ws *Conn) Write(msg []byte) (n int, err error) {
- ws.wio.Lock()
- defer ws.wio.Unlock()
- w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
- if err != nil {
- return 0, err
- }
- n, err = w.Write(msg)
- w.Close()
- return n, err
-}
-
-// Close implements the io.Closer interface.
-func (ws *Conn) Close() error {
- err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
- err1 := ws.rwc.Close()
- if err != nil {
- return err
- }
- return err1
-}
-
-func (ws *Conn) IsClientConn() bool { return ws.request == nil }
-func (ws *Conn) IsServerConn() bool { return ws.request != nil }
-
-// LocalAddr returns the WebSocket Origin for the connection for client, or
-// the WebSocket location for server.
-func (ws *Conn) LocalAddr() net.Addr {
- if ws.IsClientConn() {
- return &Addr{ws.config.Origin}
- }
- return &Addr{ws.config.Location}
-}
-
-// RemoteAddr returns the WebSocket location for the connection for client, or
-// the Websocket Origin for server.
-func (ws *Conn) RemoteAddr() net.Addr {
- if ws.IsClientConn() {
- return &Addr{ws.config.Location}
- }
- return &Addr{ws.config.Origin}
-}
-
-var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
-
-// SetDeadline sets the connection's network read & write deadlines.
-func (ws *Conn) SetDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetDeadline(t)
- }
- return errSetDeadline
-}
-
-// SetReadDeadline sets the connection's network read deadline.
-func (ws *Conn) SetReadDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetReadDeadline(t)
- }
- return errSetDeadline
-}
-
-// SetWriteDeadline sets the connection's network write deadline.
-func (ws *Conn) SetWriteDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetWriteDeadline(t)
- }
- return errSetDeadline
-}
-
-// Config returns the WebSocket config.
-func (ws *Conn) Config() *Config { return ws.config }
-
-// Request returns the http request upgraded to the WebSocket.
-// It is nil for client side.
-func (ws *Conn) Request() *http.Request { return ws.request }
-
-// Codec represents a symmetric pair of functions that implement a codec.
-type Codec struct {
- Marshal func(v interface{}) (data []byte, payloadType byte, err error)
- Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
-}
-
-// Send sends v marshaled by cd.Marshal as single frame to ws.
-func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
- data, payloadType, err := cd.Marshal(v)
- if err != nil {
- return err
- }
- ws.wio.Lock()
- defer ws.wio.Unlock()
- w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
- if err != nil {
- return err
- }
- _, err = w.Write(data)
- w.Close()
- return err
-}
-
-// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores
-// in v. The whole frame payload is read to an in-memory buffer; max size of
-// payload is defined by ws.MaxPayloadBytes. If frame payload size exceeds
-// limit, ErrFrameTooLarge is returned; in this case frame is not read off wire
-// completely. The next call to Receive would read and discard leftover data of
-// previous oversized frame before processing next frame.
-func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
- ws.rio.Lock()
- defer ws.rio.Unlock()
- if ws.frameReader != nil {
- _, err = io.Copy(ioutil.Discard, ws.frameReader)
- if err != nil {
- return err
- }
- ws.frameReader = nil
- }
-again:
- frame, err := ws.frameReaderFactory.NewFrameReader()
- if err != nil {
- return err
- }
- frame, err = ws.frameHandler.HandleFrame(frame)
- if err != nil {
- return err
- }
- if frame == nil {
- goto again
- }
- maxPayloadBytes := ws.MaxPayloadBytes
- if maxPayloadBytes == 0 {
- maxPayloadBytes = DefaultMaxPayloadBytes
- }
- if hf, ok := frame.(*hybiFrameReader); ok && hf.header.Length > int64(maxPayloadBytes) {
- // payload size exceeds limit, no need to call Unmarshal
- //
- // set frameReader to current oversized frame so that
- // the next call to this function can drain leftover
- // data before processing the next frame
- ws.frameReader = frame
- return ErrFrameTooLarge
- }
- payloadType := frame.PayloadType()
- data, err := ioutil.ReadAll(frame)
- if err != nil {
- return err
- }
- return cd.Unmarshal(data, payloadType, v)
-}
-
-func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
- switch data := v.(type) {
- case string:
- return []byte(data), TextFrame, nil
- case []byte:
- return data, BinaryFrame, nil
- }
- return nil, UnknownFrame, ErrNotSupported
-}
-
-func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
- switch data := v.(type) {
- case *string:
- *data = string(msg)
- return nil
- case *[]byte:
- *data = msg
- return nil
- }
- return ErrNotSupported
-}
-
-/*
-Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
-To send/receive text frame, use string type.
-To send/receive binary frame, use []byte type.
-
-Trivial usage:
-
- import "websocket"
-
- // receive text frame
- var message string
- websocket.Message.Receive(ws, &message)
-
- // send text frame
- message = "hello"
- websocket.Message.Send(ws, message)
-
- // receive binary frame
- var data []byte
- websocket.Message.Receive(ws, &data)
-
- // send binary frame
- data = []byte{0, 1, 2}
- websocket.Message.Send(ws, data)
-
-*/
-var Message = Codec{marshal, unmarshal}
-
-func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
- msg, err = json.Marshal(v)
- return msg, TextFrame, err
-}
-
-func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
- return json.Unmarshal(msg, v)
-}
-
-/*
-JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
-
-Trivial usage:
-
- import "websocket"
-
- type T struct {
- Msg string
- Count int
- }
-
- // receive JSON type T
- var data T
- websocket.JSON.Receive(ws, &data)
-
- // send JSON type T
- websocket.JSON.Send(ws, data)
-*/
-var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/vendor/golang.org/x/net/websocket/websocket_test.go b/vendor/golang.org/x/net/websocket/websocket_test.go
deleted file mode 100644
index 2054ce85a..000000000
--- a/vendor/golang.org/x/net/websocket/websocket_test.go
+++ /dev/null
@@ -1,665 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bytes"
- "crypto/rand"
- "fmt"
- "io"
- "log"
- "net"
- "net/http"
- "net/http/httptest"
- "net/url"
- "reflect"
- "runtime"
- "strings"
- "sync"
- "testing"
- "time"
-)
-
-var serverAddr string
-var once sync.Once
-
-func echoServer(ws *Conn) {
- defer ws.Close()
- io.Copy(ws, ws)
-}
-
-type Count struct {
- S string
- N int
-}
-
-func countServer(ws *Conn) {
- defer ws.Close()
- for {
- var count Count
- err := JSON.Receive(ws, &count)
- if err != nil {
- return
- }
- count.N++
- count.S = strings.Repeat(count.S, count.N)
- err = JSON.Send(ws, count)
- if err != nil {
- return
- }
- }
-}
-
-type testCtrlAndDataHandler struct {
- hybiFrameHandler
-}
-
-func (h *testCtrlAndDataHandler) WritePing(b []byte) (int, error) {
- h.hybiFrameHandler.conn.wio.Lock()
- defer h.hybiFrameHandler.conn.wio.Unlock()
- w, err := h.hybiFrameHandler.conn.frameWriterFactory.NewFrameWriter(PingFrame)
- if err != nil {
- return 0, err
- }
- n, err := w.Write(b)
- w.Close()
- return n, err
-}
-
-func ctrlAndDataServer(ws *Conn) {
- defer ws.Close()
- h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
- ws.frameHandler = h
-
- go func() {
- for i := 0; ; i++ {
- var b []byte
- if i%2 != 0 { // with or without payload
- b = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-SERVER", i))
- }
- if _, err := h.WritePing(b); err != nil {
- break
- }
- if _, err := h.WritePong(b); err != nil { // unsolicited pong
- break
- }
- time.Sleep(10 * time.Millisecond)
- }
- }()
-
- b := make([]byte, 128)
- for {
- n, err := ws.Read(b)
- if err != nil {
- break
- }
- if _, err := ws.Write(b[:n]); err != nil {
- break
- }
- }
-}
-
-func subProtocolHandshake(config *Config, req *http.Request) error {
- for _, proto := range config.Protocol {
- if proto == "chat" {
- config.Protocol = []string{proto}
- return nil
- }
- }
- return ErrBadWebSocketProtocol
-}
-
-func subProtoServer(ws *Conn) {
- for _, proto := range ws.Config().Protocol {
- io.WriteString(ws, proto)
- }
-}
-
-func startServer() {
- http.Handle("/echo", Handler(echoServer))
- http.Handle("/count", Handler(countServer))
- http.Handle("/ctrldata", Handler(ctrlAndDataServer))
- subproto := Server{
- Handshake: subProtocolHandshake,
- Handler: Handler(subProtoServer),
- }
- http.Handle("/subproto", subproto)
- server := httptest.NewServer(nil)
- serverAddr = server.Listener.Addr().String()
- log.Print("Test WebSocket server listening on ", serverAddr)
-}
-
-func newConfig(t *testing.T, path string) *Config {
- config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
- return config
-}
-
-func TestEcho(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- msg := []byte("hello, world\n")
- if _, err := conn.Write(msg); err != nil {
- t.Errorf("Write: %v", err)
- }
- var actual_msg = make([]byte, 512)
- n, err := conn.Read(actual_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- actual_msg = actual_msg[0:n]
- if !bytes.Equal(msg, actual_msg) {
- t.Errorf("Echo: expected %q got %q", msg, actual_msg)
- }
- conn.Close()
-}
-
-func TestAddr(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- ra := conn.RemoteAddr().String()
- if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
- t.Errorf("Bad remote addr: %v", ra)
- }
- la := conn.LocalAddr().String()
- if !strings.HasPrefix(la, "http://") {
- t.Errorf("Bad local addr: %v", la)
- }
- conn.Close()
-}
-
-func TestCount(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/count"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- var count Count
- count.S = "hello"
- if err := JSON.Send(conn, count); err != nil {
- t.Errorf("Write: %v", err)
- }
- if err := JSON.Receive(conn, &count); err != nil {
- t.Errorf("Read: %v", err)
- }
- if count.N != 1 {
- t.Errorf("count: expected %d got %d", 1, count.N)
- }
- if count.S != "hello" {
- t.Errorf("count: expected %q got %q", "hello", count.S)
- }
- if err := JSON.Send(conn, count); err != nil {
- t.Errorf("Write: %v", err)
- }
- if err := JSON.Receive(conn, &count); err != nil {
- t.Errorf("Read: %v", err)
- }
- if count.N != 2 {
- t.Errorf("count: expected %d got %d", 2, count.N)
- }
- if count.S != "hellohello" {
- t.Errorf("count: expected %q got %q", "hellohello", count.S)
- }
- conn.Close()
-}
-
-func TestWithQuery(t *testing.T) {
- once.Do(startServer)
-
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
-
- config := newConfig(t, "/echo")
- config.Location, err = url.ParseRequestURI(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
- if err != nil {
- t.Fatal("location url", err)
- }
-
- ws, err := NewClient(config, client)
- if err != nil {
- t.Errorf("WebSocket handshake: %v", err)
- return
- }
- ws.Close()
-}
-
-func testWithProtocol(t *testing.T, subproto []string) (string, error) {
- once.Do(startServer)
-
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
-
- config := newConfig(t, "/subproto")
- config.Protocol = subproto
-
- ws, err := NewClient(config, client)
- if err != nil {
- return "", err
- }
- msg := make([]byte, 16)
- n, err := ws.Read(msg)
- if err != nil {
- return "", err
- }
- ws.Close()
- return string(msg[:n]), nil
-}
-
-func TestWithProtocol(t *testing.T) {
- proto, err := testWithProtocol(t, []string{"chat"})
- if err != nil {
- t.Errorf("SubProto: unexpected error: %v", err)
- }
- if proto != "chat" {
- t.Errorf("SubProto: expected %q, got %q", "chat", proto)
- }
-}
-
-func TestWithTwoProtocol(t *testing.T) {
- proto, err := testWithProtocol(t, []string{"test", "chat"})
- if err != nil {
- t.Errorf("SubProto: unexpected error: %v", err)
- }
- if proto != "chat" {
- t.Errorf("SubProto: expected %q, got %q", "chat", proto)
- }
-}
-
-func TestWithBadProtocol(t *testing.T) {
- _, err := testWithProtocol(t, []string{"test"})
- if err != ErrBadStatus {
- t.Errorf("SubProto: expected %v, got %v", ErrBadStatus, err)
- }
-}
-
-func TestHTTP(t *testing.T) {
- once.Do(startServer)
-
- // If the client did not send a handshake that matches the protocol
- // specification, the server MUST return an HTTP response with an
- // appropriate error code (such as 400 Bad Request)
- resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
- if err != nil {
- t.Errorf("Get: error %#v", err)
- return
- }
- if resp == nil {
- t.Error("Get: resp is null")
- return
- }
- if resp.StatusCode != http.StatusBadRequest {
- t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
- }
-}
-
-func TestTrailingSpaces(t *testing.T) {
- // http://code.google.com/p/go/issues/detail?id=955
- // The last runs of this create keys with trailing spaces that should not be
- // generated by the client.
- once.Do(startServer)
- config := newConfig(t, "/echo")
- for i := 0; i < 30; i++ {
- // body
- ws, err := DialConfig(config)
- if err != nil {
- t.Errorf("Dial #%d failed: %v", i, err)
- break
- }
- ws.Close()
- }
-}
-
-func TestDialConfigBadVersion(t *testing.T) {
- once.Do(startServer)
- config := newConfig(t, "/echo")
- config.Version = 1234
-
- _, err := DialConfig(config)
-
- if dialerr, ok := err.(*DialError); ok {
- if dialerr.Err != ErrBadProtocolVersion {
- t.Errorf("dial expected err %q but got %q", ErrBadProtocolVersion, dialerr.Err)
- }
- }
-}
-
-func TestDialConfigWithDialer(t *testing.T) {
- once.Do(startServer)
- config := newConfig(t, "/echo")
- config.Dialer = &net.Dialer{
- Deadline: time.Now().Add(-time.Minute),
- }
- _, err := DialConfig(config)
- dialerr, ok := err.(*DialError)
- if !ok {
- t.Fatalf("DialError expected, got %#v", err)
- }
- neterr, ok := dialerr.Err.(*net.OpError)
- if !ok {
- t.Fatalf("net.OpError error expected, got %#v", dialerr.Err)
- }
- if !neterr.Timeout() {
- t.Fatalf("expected timeout error, got %#v", neterr)
- }
-}
-
-func TestSmallBuffer(t *testing.T) {
- // http://code.google.com/p/go/issues/detail?id=1145
- // Read should be able to handle reading a fragment of a frame.
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- msg := []byte("hello, world\n")
- if _, err := conn.Write(msg); err != nil {
- t.Errorf("Write: %v", err)
- }
- var small_msg = make([]byte, 8)
- n, err := conn.Read(small_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(msg[:len(small_msg)], small_msg) {
- t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
- }
- var second_msg = make([]byte, len(msg))
- n, err = conn.Read(second_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- second_msg = second_msg[0:n]
- if !bytes.Equal(msg[len(small_msg):], second_msg) {
- t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
- }
- conn.Close()
-}
-
-var parseAuthorityTests = []struct {
- in *url.URL
- out string
-}{
- {
- &url.URL{
- Scheme: "ws",
- Host: "www.google.com",
- },
- "www.google.com:80",
- },
- {
- &url.URL{
- Scheme: "wss",
- Host: "www.google.com",
- },
- "www.google.com:443",
- },
- {
- &url.URL{
- Scheme: "ws",
- Host: "www.google.com:80",
- },
- "www.google.com:80",
- },
- {
- &url.URL{
- Scheme: "wss",
- Host: "www.google.com:443",
- },
- "www.google.com:443",
- },
- // some invalid ones for parseAuthority. parseAuthority doesn't
- // concern itself with the scheme unless it actually knows about it
- {
- &url.URL{
- Scheme: "http",
- Host: "www.google.com",
- },
- "www.google.com",
- },
- {
- &url.URL{
- Scheme: "http",
- Host: "www.google.com:80",
- },
- "www.google.com:80",
- },
- {
- &url.URL{
- Scheme: "asdf",
- Host: "127.0.0.1",
- },
- "127.0.0.1",
- },
- {
- &url.URL{
- Scheme: "asdf",
- Host: "www.google.com",
- },
- "www.google.com",
- },
-}
-
-func TestParseAuthority(t *testing.T) {
- for _, tt := range parseAuthorityTests {
- out := parseAuthority(tt.in)
- if out != tt.out {
- t.Errorf("got %v; want %v", out, tt.out)
- }
- }
-}
-
-type closerConn struct {
- net.Conn
- closed int // count of the number of times Close was called
-}
-
-func (c *closerConn) Close() error {
- c.closed++
- return c.Conn.Close()
-}
-
-func TestClose(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("see golang.org/issue/11454")
- }
-
- once.Do(startServer)
-
- conn, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
-
- cc := closerConn{Conn: conn}
-
- client, err := NewClient(newConfig(t, "/echo"), &cc)
- if err != nil {
- t.Fatalf("WebSocket handshake: %v", err)
- }
-
- // set the deadline to ten minutes ago, which will have expired by the time
- // client.Close sends the close status frame.
- conn.SetDeadline(time.Now().Add(-10 * time.Minute))
-
- if err := client.Close(); err == nil {
- t.Errorf("ws.Close(): expected error, got %v", err)
- }
- if cc.closed < 1 {
- t.Fatalf("ws.Close(): expected underlying ws.rwc.Close to be called > 0 times, got: %v", cc.closed)
- }
-}
-
-var originTests = []struct {
- req *http.Request
- origin *url.URL
-}{
- {
- req: &http.Request{
- Header: http.Header{
- "Origin": []string{"http://www.example.com"},
- },
- },
- origin: &url.URL{
- Scheme: "http",
- Host: "www.example.com",
- },
- },
- {
- req: &http.Request{},
- },
-}
-
-func TestOrigin(t *testing.T) {
- conf := newConfig(t, "/echo")
- conf.Version = ProtocolVersionHybi13
- for i, tt := range originTests {
- origin, err := Origin(conf, tt.req)
- if err != nil {
- t.Error(err)
- continue
- }
- if !reflect.DeepEqual(origin, tt.origin) {
- t.Errorf("#%d: got origin %v; want %v", i, origin, tt.origin)
- continue
- }
- }
-}
-
-func TestCtrlAndData(t *testing.T) {
- once.Do(startServer)
-
- c, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal(err)
- }
- ws, err := NewClient(newConfig(t, "/ctrldata"), c)
- if err != nil {
- t.Fatal(err)
- }
- defer ws.Close()
-
- h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
- ws.frameHandler = h
-
- b := make([]byte, 128)
- for i := 0; i < 2; i++ {
- data := []byte(fmt.Sprintf("#%d-DATA-FRAME-FROM-CLIENT", i))
- if _, err := ws.Write(data); err != nil {
- t.Fatalf("#%d: %v", i, err)
- }
- var ctrl []byte
- if i%2 != 0 { // with or without payload
- ctrl = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-CLIENT", i))
- }
- if _, err := h.WritePing(ctrl); err != nil {
- t.Fatalf("#%d: %v", i, err)
- }
- n, err := ws.Read(b)
- if err != nil {
- t.Fatalf("#%d: %v", i, err)
- }
- if !bytes.Equal(b[:n], data) {
- t.Fatalf("#%d: got %v; want %v", i, b[:n], data)
- }
- }
-}
-
-func TestCodec_ReceiveLimited(t *testing.T) {
- const limit = 2048
- var payloads [][]byte
- for _, size := range []int{
- 1024,
- 2048,
- 4096, // receive of this message would be interrupted due to limit
- 2048, // this one is to make sure next receive recovers discarding leftovers
- } {
- b := make([]byte, size)
- rand.Read(b)
- payloads = append(payloads, b)
- }
- handlerDone := make(chan struct{})
- limitedHandler := func(ws *Conn) {
- defer close(handlerDone)
- ws.MaxPayloadBytes = limit
- defer ws.Close()
- for i, p := range payloads {
- t.Logf("payload #%d (size %d, exceeds limit: %v)", i, len(p), len(p) > limit)
- var recv []byte
- err := Message.Receive(ws, &recv)
- switch err {
- case nil:
- case ErrFrameTooLarge:
- if len(p) <= limit {
- t.Fatalf("unexpected frame size limit: expected %d bytes of payload having limit at %d", len(p), limit)
- }
- continue
- default:
- t.Fatalf("unexpected error: %v (want either nil or ErrFrameTooLarge)", err)
- }
- if len(recv) > limit {
- t.Fatalf("received %d bytes of payload having limit at %d", len(recv), limit)
- }
- if !bytes.Equal(p, recv) {
- t.Fatalf("received payload differs:\ngot:\t%v\nwant:\t%v", recv, p)
- }
- }
- }
- server := httptest.NewServer(Handler(limitedHandler))
- defer server.CloseClientConnections()
- defer server.Close()
- addr := server.Listener.Addr().String()
- ws, err := Dial("ws://"+addr+"/", "", "http://localhost/")
- if err != nil {
- t.Fatal(err)
- }
- defer ws.Close()
- for i, p := range payloads {
- if err := Message.Send(ws, p); err != nil {
- t.Fatalf("payload #%d (size %d): %v", i, len(p), err)
- }
- }
- <-handlerDone
-}