gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/websocket/hybi_test.go (about)

     1  // Copyright 2011 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
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"net/url"
    13  	"strings"
    14  	"testing"
    15  
    16  	http "gitee.com/ks-custle/core-gm/gmhttp"
    17  )
    18  
    19  // Test the getNonceAccept function with values in
    20  // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
    21  func TestSecWebSocketAccept(t *testing.T) {
    22  	nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
    23  	expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
    24  	accept, err := getNonceAccept(nonce)
    25  	if err != nil {
    26  		t.Errorf("getNonceAccept: returned error %v", err)
    27  		return
    28  	}
    29  	if !bytes.Equal(expected, accept) {
    30  		t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
    31  	}
    32  }
    33  
    34  func TestHybiClientHandshake(t *testing.T) {
    35  	type test struct {
    36  		url, host string
    37  	}
    38  	tests := []test{
    39  		{"ws://server.example.com/chat", "server.example.com"},
    40  		{"ws://127.0.0.1/chat", "127.0.0.1"},
    41  	}
    42  	if _, err := url.ParseRequestURI("http://[fe80::1%25lo0]"); err == nil {
    43  		tests = append(tests, test{"ws://[fe80::1%25lo0]/chat", "[fe80::1]"})
    44  	}
    45  
    46  	for _, tt := range tests {
    47  		var b bytes.Buffer
    48  		bw := bufio.NewWriter(&b)
    49  		br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
    50  Upgrade: websocket
    51  Connection: Upgrade
    52  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    53  Sec-WebSocket-Protocol: chat
    54  
    55  `))
    56  		var err error
    57  		var config Config
    58  		config.Location, err = url.ParseRequestURI(tt.url)
    59  		if err != nil {
    60  			t.Fatal("location url", err)
    61  		}
    62  		config.Origin, err = url.ParseRequestURI("http://example.com")
    63  		if err != nil {
    64  			t.Fatal("origin url", err)
    65  		}
    66  		config.Protocol = append(config.Protocol, "chat")
    67  		config.Protocol = append(config.Protocol, "superchat")
    68  		config.Version = ProtocolVersionHybi13
    69  		config.handshakeData = map[string]string{
    70  			"key": "dGhlIHNhbXBsZSBub25jZQ==",
    71  		}
    72  		if err := hybiClientHandshake(&config, br, bw); err != nil {
    73  			t.Fatal("handshake", err)
    74  		}
    75  		req, err := http.ReadRequest(bufio.NewReader(&b))
    76  		if err != nil {
    77  			t.Fatal("read request", err)
    78  		}
    79  		if req.Method != "GET" {
    80  			t.Errorf("request method expected GET, but got %s", req.Method)
    81  		}
    82  		if req.URL.Path != "/chat" {
    83  			t.Errorf("request path expected /chat, but got %s", req.URL.Path)
    84  		}
    85  		if req.Proto != "HTTP/1.1" {
    86  			t.Errorf("request proto expected HTTP/1.1, but got %s", req.Proto)
    87  		}
    88  		if req.Host != tt.host {
    89  			t.Errorf("request host expected %s, but got %s", tt.host, req.Host)
    90  		}
    91  		var expectedHeader = map[string]string{
    92  			"Connection":             "Upgrade",
    93  			"Upgrade":                "websocket",
    94  			"Sec-Websocket-Key":      config.handshakeData["key"],
    95  			"Origin":                 config.Origin.String(),
    96  			"Sec-Websocket-Protocol": "chat, superchat",
    97  			"Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi13),
    98  		}
    99  		for k, v := range expectedHeader {
   100  			if req.Header.Get(k) != v {
   101  				t.Errorf("%s expected %s, but got %v", k, v, req.Header.Get(k))
   102  			}
   103  		}
   104  	}
   105  }
   106  
   107  func TestHybiClientHandshakeWithHeader(t *testing.T) {
   108  	b := bytes.NewBuffer([]byte{})
   109  	bw := bufio.NewWriter(b)
   110  	br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
   111  Upgrade: websocket
   112  Connection: Upgrade
   113  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
   114  Sec-WebSocket-Protocol: chat
   115  
   116  `))
   117  	var err error
   118  	config := new(Config)
   119  	config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
   120  	if err != nil {
   121  		t.Fatal("location url", err)
   122  	}
   123  	config.Origin, err = url.ParseRequestURI("http://example.com")
   124  	if err != nil {
   125  		t.Fatal("origin url", err)
   126  	}
   127  	config.Protocol = append(config.Protocol, "chat")
   128  	config.Protocol = append(config.Protocol, "superchat")
   129  	config.Version = ProtocolVersionHybi13
   130  	config.Header = http.Header(make(map[string][]string))
   131  	config.Header.Add("User-Agent", "test")
   132  
   133  	config.handshakeData = map[string]string{
   134  		"key": "dGhlIHNhbXBsZSBub25jZQ==",
   135  	}
   136  	err = hybiClientHandshake(config, br, bw)
   137  	if err != nil {
   138  		t.Errorf("handshake failed: %v", err)
   139  	}
   140  	req, err := http.ReadRequest(bufio.NewReader(b))
   141  	if err != nil {
   142  		t.Fatalf("read request: %v", err)
   143  	}
   144  	if req.Method != "GET" {
   145  		t.Errorf("request method expected GET, but got %q", req.Method)
   146  	}
   147  	if req.URL.Path != "/chat" {
   148  		t.Errorf("request path expected /chat, but got %q", req.URL.Path)
   149  	}
   150  	if req.Proto != "HTTP/1.1" {
   151  		t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
   152  	}
   153  	if req.Host != "server.example.com" {
   154  		t.Errorf("request Host expected server.example.com, but got %v", req.Host)
   155  	}
   156  	var expectedHeader = map[string]string{
   157  		"Connection":             "Upgrade",
   158  		"Upgrade":                "websocket",
   159  		"Sec-Websocket-Key":      config.handshakeData["key"],
   160  		"Origin":                 config.Origin.String(),
   161  		"Sec-Websocket-Protocol": "chat, superchat",
   162  		"Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi13),
   163  		"User-Agent":             "test",
   164  	}
   165  	for k, v := range expectedHeader {
   166  		if req.Header.Get(k) != v {
   167  			t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
   168  		}
   169  	}
   170  }
   171  
   172  func TestHybiServerHandshake(t *testing.T) {
   173  	config := new(Config)
   174  	handshaker := &hybiServerHandshaker{Config: config}
   175  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   176  Host: server.example.com
   177  Upgrade: websocket
   178  Connection: Upgrade
   179  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   180  Origin: http://example.com
   181  Sec-WebSocket-Protocol: chat, superchat
   182  Sec-WebSocket-Version: 13
   183  
   184  `))
   185  	req, err := http.ReadRequest(br)
   186  	if err != nil {
   187  		t.Fatal("request", err)
   188  	}
   189  	code, err := handshaker.ReadHandshake(br, req)
   190  	if err != nil {
   191  		t.Errorf("handshake failed: %v", err)
   192  	}
   193  	if code != http.StatusSwitchingProtocols {
   194  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   195  	}
   196  	expectedProtocols := []string{"chat", "superchat"}
   197  	if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
   198  		t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
   199  	}
   200  	b := bytes.NewBuffer([]byte{})
   201  	bw := bufio.NewWriter(b)
   202  
   203  	config.Protocol = config.Protocol[:1]
   204  
   205  	err = handshaker.AcceptHandshake(bw)
   206  	if err != nil {
   207  		t.Errorf("handshake response failed: %v", err)
   208  	}
   209  	expectedResponse := strings.Join([]string{
   210  		"HTTP/1.1 101 Switching Protocols",
   211  		"Upgrade: websocket",
   212  		"Connection: Upgrade",
   213  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   214  		"Sec-WebSocket-Protocol: chat",
   215  		"", ""}, "\r\n")
   216  
   217  	if b.String() != expectedResponse {
   218  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   219  	}
   220  }
   221  
   222  func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
   223  	config := new(Config)
   224  	handshaker := &hybiServerHandshaker{Config: config}
   225  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   226  Host: server.example.com
   227  Upgrade: websocket
   228  Connection: Upgrade
   229  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   230  Origin: http://example.com
   231  Sec-WebSocket-Version: 13
   232  
   233  `))
   234  	req, err := http.ReadRequest(br)
   235  	if err != nil {
   236  		t.Fatal("request", err)
   237  	}
   238  	code, err := handshaker.ReadHandshake(br, req)
   239  	if err != nil {
   240  		t.Errorf("handshake failed: %v", err)
   241  	}
   242  	if code != http.StatusSwitchingProtocols {
   243  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   244  	}
   245  	if len(config.Protocol) != 0 {
   246  		t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
   247  	}
   248  	b := bytes.NewBuffer([]byte{})
   249  	bw := bufio.NewWriter(b)
   250  
   251  	err = handshaker.AcceptHandshake(bw)
   252  	if err != nil {
   253  		t.Errorf("handshake response failed: %v", err)
   254  	}
   255  	expectedResponse := strings.Join([]string{
   256  		"HTTP/1.1 101 Switching Protocols",
   257  		"Upgrade: websocket",
   258  		"Connection: Upgrade",
   259  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   260  		"", ""}, "\r\n")
   261  
   262  	if b.String() != expectedResponse {
   263  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   264  	}
   265  }
   266  
   267  func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
   268  	config := new(Config)
   269  	handshaker := &hybiServerHandshaker{Config: config}
   270  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   271  Host: server.example.com
   272  Upgrade: websocket
   273  Connection: Upgrade
   274  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   275  Sec-WebSocket-Origin: http://example.com
   276  Sec-WebSocket-Protocol: chat, superchat
   277  Sec-WebSocket-Version: 9
   278  
   279  `))
   280  	req, err := http.ReadRequest(br)
   281  	if err != nil {
   282  		t.Fatal("request", err)
   283  	}
   284  	code, err := handshaker.ReadHandshake(br, req)
   285  	if err != ErrBadWebSocketVersion {
   286  		t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
   287  	}
   288  	if code != http.StatusBadRequest {
   289  		t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
   290  	}
   291  }
   292  
   293  func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
   294  	b := bytes.NewBuffer([]byte{})
   295  	frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
   296  	w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
   297  	w.(*hybiFrameWriter).header = frameHeader
   298  	_, err := w.Write(testPayload)
   299  	w.Close()
   300  	if err != nil {
   301  		t.Errorf("Write error %q", err)
   302  	}
   303  	var expectedFrame []byte
   304  	expectedFrame = append(expectedFrame, testHeader...)
   305  	expectedFrame = append(expectedFrame, testMaskedPayload...)
   306  	if !bytes.Equal(expectedFrame, b.Bytes()) {
   307  		t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
   308  	}
   309  	frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
   310  	r, err := frameReaderFactory.NewFrameReader()
   311  	if err != nil {
   312  		t.Errorf("Read error %q", err)
   313  	}
   314  	if header := r.HeaderReader(); header == nil {
   315  		t.Errorf("no header")
   316  	} else {
   317  		actualHeader := make([]byte, r.Len())
   318  		n, err := header.Read(actualHeader)
   319  		if err != nil {
   320  			t.Errorf("Read header error %q", err)
   321  		} else {
   322  			if n < len(testHeader) {
   323  				t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
   324  			}
   325  			if !bytes.Equal(testHeader, actualHeader[:n]) {
   326  				t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
   327  			}
   328  		}
   329  	}
   330  	if trailer := r.TrailerReader(); trailer != nil {
   331  		t.Errorf("unexpected trailer %q", trailer)
   332  	}
   333  	frame := r.(*hybiFrameReader)
   334  	if frameHeader.Fin != frame.header.Fin ||
   335  		frameHeader.OpCode != frame.header.OpCode ||
   336  		len(testPayload) != int(frame.header.Length) {
   337  		t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
   338  	}
   339  	payload := make([]byte, len(testPayload))
   340  	_, err = r.Read(payload)
   341  	if err != nil && err != io.EOF {
   342  		t.Errorf("read %v", err)
   343  	}
   344  	if !bytes.Equal(testPayload, payload) {
   345  		t.Errorf("payload %q vs %q", testPayload, payload)
   346  	}
   347  }
   348  
   349  func TestHybiShortTextFrame(t *testing.T) {
   350  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
   351  	payload := []byte("hello")
   352  	testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
   353  
   354  	payload = make([]byte, 125)
   355  	testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
   356  }
   357  
   358  func TestHybiShortMaskedTextFrame(t *testing.T) {
   359  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
   360  		MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
   361  	payload := []byte("hello")
   362  	maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
   363  	header := []byte{0x81, 0x85}
   364  	header = append(header, frameHeader.MaskingKey...)
   365  	testHybiFrame(t, header, payload, maskedPayload, frameHeader)
   366  }
   367  
   368  func TestHybiShortBinaryFrame(t *testing.T) {
   369  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
   370  	payload := []byte("hello")
   371  	testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
   372  
   373  	payload = make([]byte, 125)
   374  	testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
   375  }
   376  
   377  func TestHybiControlFrame(t *testing.T) {
   378  	payload := []byte("hello")
   379  
   380  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
   381  	testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
   382  
   383  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: PingFrame}
   384  	testHybiFrame(t, []byte{0x89, 0x00}, nil, nil, frameHeader)
   385  
   386  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
   387  	testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
   388  
   389  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
   390  	testHybiFrame(t, []byte{0x8A, 0x00}, nil, nil, frameHeader)
   391  
   392  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
   393  	payload = []byte{0x03, 0xe8} // 1000
   394  	testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
   395  }
   396  
   397  func TestHybiLongFrame(t *testing.T) {
   398  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
   399  	payload := make([]byte, 126)
   400  	testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
   401  
   402  	payload = make([]byte, 65535)
   403  	testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
   404  
   405  	payload = make([]byte, 65536)
   406  	testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
   407  }
   408  
   409  func TestHybiClientRead(t *testing.T) {
   410  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
   411  		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
   412  		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
   413  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   414  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   415  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   416  
   417  	msg := make([]byte, 512)
   418  	n, err := conn.Read(msg)
   419  	if err != nil {
   420  		t.Errorf("read 1st frame, error %q", err)
   421  	}
   422  	if n != 5 {
   423  		t.Errorf("read 1st frame, expect 5, got %d", n)
   424  	}
   425  	if !bytes.Equal(wireData[2:7], msg[:n]) {
   426  		t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
   427  	}
   428  	n, err = conn.Read(msg)
   429  	if err != nil {
   430  		t.Errorf("read 2nd frame, error %q", err)
   431  	}
   432  	if n != 5 {
   433  		t.Errorf("read 2nd frame, expect 5, got %d", n)
   434  	}
   435  	if !bytes.Equal(wireData[16:21], msg[:n]) {
   436  		t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
   437  	}
   438  	n, err = conn.Read(msg)
   439  	if err == nil {
   440  		t.Errorf("read not EOF")
   441  	}
   442  	if n != 0 {
   443  		t.Errorf("expect read 0, got %d", n)
   444  	}
   445  }
   446  
   447  func TestHybiShortRead(t *testing.T) {
   448  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
   449  		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
   450  		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
   451  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   452  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   453  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   454  
   455  	step := 0
   456  	pos := 0
   457  	expectedPos := []int{2, 5, 16, 19}
   458  	expectedLen := []int{3, 2, 3, 2}
   459  	for {
   460  		msg := make([]byte, 3)
   461  		n, err := conn.Read(msg)
   462  		if step >= len(expectedPos) {
   463  			if err == nil {
   464  				t.Errorf("read not EOF")
   465  			}
   466  			if n != 0 {
   467  				t.Errorf("expect read 0, got %d", n)
   468  			}
   469  			return
   470  		}
   471  		pos = expectedPos[step]
   472  		endPos := pos + expectedLen[step]
   473  		if err != nil {
   474  			t.Errorf("read from %d, got error %q", pos, err)
   475  			return
   476  		}
   477  		if n != endPos-pos {
   478  			t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
   479  		}
   480  		if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
   481  			t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
   482  		}
   483  		step++
   484  	}
   485  }
   486  
   487  func TestHybiServerRead(t *testing.T) {
   488  	wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
   489  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
   490  		0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
   491  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
   492  		0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
   493  		0x9a, 0xec, 0xc6, 0x48, 0x89, // world
   494  	}
   495  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   496  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   497  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
   498  
   499  	expected := [][]byte{[]byte("hello"), []byte("world")}
   500  
   501  	msg := make([]byte, 512)
   502  	n, err := conn.Read(msg)
   503  	if err != nil {
   504  		t.Errorf("read 1st frame, error %q", err)
   505  	}
   506  	if n != 5 {
   507  		t.Errorf("read 1st frame, expect 5, got %d", n)
   508  	}
   509  	if !bytes.Equal(expected[0], msg[:n]) {
   510  		t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
   511  	}
   512  
   513  	n, err = conn.Read(msg)
   514  	if err != nil {
   515  		t.Errorf("read 2nd frame, error %q", err)
   516  	}
   517  	if n != 5 {
   518  		t.Errorf("read 2nd frame, expect 5, got %d", n)
   519  	}
   520  	if !bytes.Equal(expected[1], msg[:n]) {
   521  		t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
   522  	}
   523  
   524  	n, err = conn.Read(msg)
   525  	if err == nil {
   526  		t.Errorf("read not EOF")
   527  	}
   528  	if n != 0 {
   529  		t.Errorf("expect read 0, got %d", n)
   530  	}
   531  }
   532  
   533  func TestHybiServerReadWithoutMasking(t *testing.T) {
   534  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
   535  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   536  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   537  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
   538  	// server MUST close the connection upon receiving a non-masked frame.
   539  	msg := make([]byte, 512)
   540  	_, err := conn.Read(msg)
   541  	if err != io.EOF {
   542  		t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
   543  	}
   544  }
   545  
   546  func TestHybiClientReadWithMasking(t *testing.T) {
   547  	wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
   548  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
   549  	}
   550  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   551  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   552  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   553  
   554  	// client MUST close the connection upon receiving a masked frame.
   555  	msg := make([]byte, 512)
   556  	_, err := conn.Read(msg)
   557  	if err != io.EOF {
   558  		t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
   559  	}
   560  }
   561  
   562  // Test the hybiServerHandshaker supports firefox implementation and
   563  // checks Connection request header include (but it's not necessary
   564  // equal to) "upgrade"
   565  func TestHybiServerFirefoxHandshake(t *testing.T) {
   566  	config := new(Config)
   567  	handshaker := &hybiServerHandshaker{Config: config}
   568  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   569  Host: server.example.com
   570  Upgrade: websocket
   571  Connection: keep-alive, upgrade
   572  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   573  Origin: http://example.com
   574  Sec-WebSocket-Protocol: chat, superchat
   575  Sec-WebSocket-Version: 13
   576  
   577  `))
   578  	req, err := http.ReadRequest(br)
   579  	if err != nil {
   580  		t.Fatal("request", err)
   581  	}
   582  	code, err := handshaker.ReadHandshake(br, req)
   583  	if err != nil {
   584  		t.Errorf("handshake failed: %v", err)
   585  	}
   586  	if code != http.StatusSwitchingProtocols {
   587  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   588  	}
   589  	b := bytes.NewBuffer([]byte{})
   590  	bw := bufio.NewWriter(b)
   591  
   592  	config.Protocol = []string{"chat"}
   593  
   594  	err = handshaker.AcceptHandshake(bw)
   595  	if err != nil {
   596  		t.Errorf("handshake response failed: %v", err)
   597  	}
   598  	expectedResponse := strings.Join([]string{
   599  		"HTTP/1.1 101 Switching Protocols",
   600  		"Upgrade: websocket",
   601  		"Connection: Upgrade",
   602  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   603  		"Sec-WebSocket-Protocol: chat",
   604  		"", ""}, "\r\n")
   605  
   606  	if b.String() != expectedResponse {
   607  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   608  	}
   609  }