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