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