OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // VMOptions= | 5 // VMOptions= |
6 // VMOptions=--short_socket_read | 6 // VMOptions=--short_socket_read |
7 // VMOptions=--short_socket_write | 7 // VMOptions=--short_socket_write |
8 // VMOptions=--short_socket_read --short_socket_write | 8 // VMOptions=--short_socket_read --short_socket_write |
9 // OtherResources=certificates/server_chain.pem | 9 // OtherResources=certificates/server_chain.pem |
10 // OtherResources=certificates/server_key.pem | 10 // OtherResources=certificates/server_key.pem |
11 | 11 |
12 library dart.io; | 12 library dart.io; |
13 | 13 |
14 import "dart:async"; | 14 import "dart:async"; |
15 import "dart:io"; | 15 import "dart:io"; |
16 import "dart:math"; | 16 import "dart:math"; |
17 import "dart:typed_data"; | 17 import "dart:typed_data"; |
18 | 18 |
19 import "package:async_helper/async_helper.dart"; | 19 import "package:async_helper/async_helper.dart"; |
20 import "package:expect/expect.dart"; | 20 import "package:expect/expect.dart"; |
21 import "package:path/path.dart"; | 21 import "package:path/path.dart"; |
22 | 22 |
23 part "../../../sdk/lib/io/crypto.dart"; | 23 part "../../../sdk/lib/io/crypto.dart"; |
24 | 24 |
25 | |
26 const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 25 const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
27 const String CERT_NAME = 'localhost_cert'; | 26 const String CERT_NAME = 'localhost_cert'; |
28 const String HOST_NAME = 'localhost'; | 27 const String HOST_NAME = 'localhost'; |
29 | 28 |
30 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 29 String localFile(path) => Platform.script.resolve(path).toFilePath(); |
31 | 30 |
32 SecurityContext serverContext = new SecurityContext() | 31 SecurityContext serverContext = new SecurityContext() |
33 ..useCertificateChain(localFile('certificates/server_chain.pem')) | 32 ..useCertificateChain(localFile('certificates/server_chain.pem')) |
34 ..usePrivateKey(localFile('certificates/server_key.pem'), | 33 ..usePrivateKey(localFile('certificates/server_key.pem'), |
35 password: 'dartdart'); | 34 password: 'dartdart'); |
36 | 35 |
37 SecurityContext clientContext = new SecurityContext() | 36 SecurityContext clientContext = new SecurityContext() |
38 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 37 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); |
39 | 38 |
40 /** | 39 /** |
41 * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. | 40 * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. |
42 */ | 41 */ |
43 class SecurityConfiguration { | 42 class SecurityConfiguration { |
44 final bool secure; | 43 final bool secure; |
45 | 44 |
46 SecurityConfiguration({bool this.secure}); | 45 SecurityConfiguration({bool this.secure}); |
47 | 46 |
48 Future<HttpServer> createServer({int backlog: 0}) => | 47 Future<HttpServer> createServer({int backlog: 0}) => secure |
49 secure ? HttpServer.bindSecure(HOST_NAME, | 48 ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog) |
50 0, | 49 : HttpServer.bind(HOST_NAME, 0, backlog: backlog); |
51 serverContext, | |
52 backlog: backlog) | |
53 : HttpServer.bind(HOST_NAME, | |
54 0, | |
55 backlog: backlog); | |
56 | 50 |
57 Future<WebSocket> createClient(int port) => | 51 Future<WebSocket> createClient(int port) => |
58 // TODO(whesse): Add a client context argument to WebSocket.connect. | 52 // TODO(whesse): Add a client context argument to WebSocket.connect. |
59 WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); | 53 WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); |
60 | |
61 | 54 |
62 void testForceCloseServerEnd(int totalConnections) { | 55 void testForceCloseServerEnd(int totalConnections) { |
63 createServer().then((server) { | 56 createServer().then((server) { |
64 server.listen((request) { | 57 server.listen((request) { |
65 var response = request.response; | 58 var response = request.response; |
66 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; | 59 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; |
67 response.headers.set(HttpHeaders.CONNECTION, "upgrade"); | 60 response.headers.set(HttpHeaders.CONNECTION, "upgrade"); |
68 response.headers.set(HttpHeaders.UPGRADE, "websocket"); | 61 response.headers.set(HttpHeaders.UPGRADE, "websocket"); |
69 String key = request.headers.value("Sec-WebSocket-Key"); | 62 String key = request.headers.value("Sec-WebSocket-Key"); |
70 _SHA1 sha1 = new _SHA1(); | 63 _SHA1 sha1 = new _SHA1(); |
71 sha1.add("$key$webSocketGUID".codeUnits); | 64 sha1.add("$key$webSocketGUID".codeUnits); |
72 String accept = _CryptoUtils.bytesToBase64(sha1.close()); | 65 String accept = _CryptoUtils.bytesToBase64(sha1.close()); |
73 response.headers.add("Sec-WebSocket-Accept", accept); | 66 response.headers.add("Sec-WebSocket-Accept", accept); |
74 response.headers.contentLength = 0; | 67 response.headers.contentLength = 0; |
75 response.detachSocket().then((socket) { | 68 response.detachSocket().then((socket) { |
76 socket.destroy(); | 69 socket.destroy(); |
77 }); | 70 }); |
78 }); | 71 }); |
79 | 72 |
80 int closeCount = 0; | 73 int closeCount = 0; |
81 for (int i = 0; i < totalConnections; i++) { | 74 for (int i = 0; i < totalConnections; i++) { |
82 createClient(server.port).then((webSocket) { | 75 createClient(server.port).then((webSocket) { |
83 webSocket.add("Hello, world!"); | 76 webSocket.add("Hello, world!"); |
84 webSocket.listen( | 77 webSocket.listen((message) { |
85 (message) { | 78 Expect.fail("unexpected message"); |
86 Expect.fail("unexpected message"); | 79 }, onDone: () { |
87 }, | 80 closeCount++; |
88 onDone: () { | 81 if (closeCount == totalConnections) { |
89 closeCount++; | 82 server.close(); |
90 if (closeCount == totalConnections) { | 83 } |
91 server.close(); | |
92 } | |
93 }); | |
94 }); | 84 }); |
| 85 }); |
95 } | 86 } |
96 }); | 87 }); |
97 } | 88 } |
98 | 89 |
99 void runTests() { | 90 void runTests() { |
100 testForceCloseServerEnd(10); | 91 testForceCloseServerEnd(10); |
101 } | 92 } |
102 } | 93 } |
103 | 94 |
104 | |
105 main() { | 95 main() { |
106 asyncStart(); | 96 asyncStart(); |
107 new SecurityConfiguration(secure: false).runTests(); | 97 new SecurityConfiguration(secure: false).runTests(); |
108 // TODO(whesse): WebSocket.connect needs an optional context: parameter | 98 // TODO(whesse): WebSocket.connect needs an optional context: parameter |
109 // new SecurityConfiguration(secure: true).runTests(); | 99 // new SecurityConfiguration(secure: true).runTests(); |
110 asyncEnd(); | 100 asyncEnd(); |
111 } | 101 } |
112 | |
OLD | NEW |