| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // BSD-style license that can be found in the LICENSE file. | 
|  | 4 // | 
|  | 5 // VMOptions= | 
|  | 6 // VMOptions=--short_socket_read | 
|  | 7 // VMOptions=--short_socket_write | 
|  | 8 // VMOptions=--short_socket_read --short_socket_write | 
|  | 9 | 
|  | 10 import "dart:async"; | 
|  | 11 import "dart:convert"; | 
|  | 12 import "dart:io"; | 
|  | 13 import "dart:typed_data"; | 
|  | 14 | 
|  | 15 import "package:async_helper/async_helper.dart"; | 
|  | 16 import "package:crypto/crypto.dart"; | 
|  | 17 import "package:expect/expect.dart"; | 
|  | 18 import "package:path/path.dart"; | 
|  | 19 | 
|  | 20 const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 
|  | 21 | 
|  | 22 const String HOST_NAME = 'localhost'; | 
|  | 23 | 
|  | 24 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 
|  | 25 | 
|  | 26 SecurityContext serverContext = new SecurityContext() | 
|  | 27   ..useCertificateChain(localFile('certificates/server_chain.pem')) | 
|  | 28   ..usePrivateKey(localFile('certificates/server_key.pem'), | 
|  | 29                   password: 'dartdart'); | 
|  | 30 | 
|  | 31 class SecurityConfiguration { | 
|  | 32   final bool secure; | 
|  | 33 | 
|  | 34   SecurityConfiguration({bool this.secure}); | 
|  | 35 | 
|  | 36   Future<HttpServer> createServer({int backlog: 0}) => | 
|  | 37       secure ? HttpServer.bindSecure(HOST_NAME, | 
|  | 38           0, | 
|  | 39           serverContext, | 
|  | 40           backlog: backlog) | 
|  | 41           : HttpServer.bind(HOST_NAME, | 
|  | 42           0, | 
|  | 43           backlog: backlog); | 
|  | 44 | 
|  | 45   Future<WebSocket> createClient(int port) => | 
|  | 46       // TODO(whesse): Add client context argument to WebSocket.connect | 
|  | 47       WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); | 
|  | 48 | 
|  | 49   void testCompressionSupport({server: false, | 
|  | 50         client: false, | 
|  | 51         contextTakeover: false}) { | 
|  | 52     asyncStart(); | 
|  | 53 | 
|  | 54     var clientOptions = new CompressionOptions( | 
|  | 55         enabled: client, | 
|  | 56         serverNoContextTakeover: contextTakeover, | 
|  | 57         clientNoContextTakeover: contextTakeover); | 
|  | 58     var serverOptions = new CompressionOptions( | 
|  | 59         enabled: server, | 
|  | 60         serverNoContextTakeover: contextTakeover, | 
|  | 61         clientNoContextTakeover: contextTakeover); | 
|  | 62 | 
|  | 63     createServer().then((server) { | 
|  | 64       server.listen((request) { | 
|  | 65         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 
|  | 66         WebSocketTransformer.upgrade(request, compression: serverOptions) | 
|  | 67                             .then((webSocket) { | 
|  | 68             webSocket.listen((message) { | 
|  | 69               Expect.equals("Hello World", message); | 
|  | 70 | 
|  | 71               webSocket.add(message); | 
|  | 72               webSocket.close(); | 
|  | 73             }); | 
|  | 74             webSocket.add("Hello World"); | 
|  | 75         }); | 
|  | 76       }); | 
|  | 77 | 
|  | 78       var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; | 
|  | 79       WebSocket.connect(url, compression: clientOptions).then((websocket) { | 
|  | 80         var future = websocket.listen((message) { | 
|  | 81           Expect.equals("Hello World", message); | 
|  | 82         }).asFuture(); | 
|  | 83         websocket.add("Hello World"); | 
|  | 84         return future; | 
|  | 85       }).then((_) { | 
|  | 86         server.close(); | 
|  | 87         asyncEnd(); | 
|  | 88       }); | 
|  | 89     }); | 
|  | 90   } | 
|  | 91 | 
|  | 92   void testCompressionHeaders() { | 
|  | 93     asyncStart(); | 
|  | 94     createServer().then((server) { | 
|  | 95       server.listen((request) { | 
|  | 96         Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION)); | 
|  | 97         Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE)); | 
|  | 98 | 
|  | 99         var key = request.headers.value('Sec-WebSocket-Key'); | 
|  | 100         var sha1 = new SHA1()..add("$key$WEB_SOCKET_GUID".codeUnits); | 
|  | 101         var accept = CryptoUtils.bytesToBase64(sha1.close()); | 
|  | 102         request.response | 
|  | 103             ..statusCode = HttpStatus.SWITCHING_PROTOCOLS | 
|  | 104             ..headers.add(HttpHeaders.CONNECTION, "Upgrade") | 
|  | 105             ..headers.add(HttpHeaders.UPGRADE, "websocket") | 
|  | 106             ..headers.add("Sec-WebSocket-Accept", accept) | 
|  | 107             ..headers.add("Sec-WebSocket-Extensions", | 
|  | 108               "permessage-deflate;" | 
|  | 109               // Test quoted values and space padded = | 
|  | 110               'server_max_window_bits="10"; client_max_window_bits = 12' | 
|  | 111               'client_no_context_takeover; server_no_context_takeover'); | 
|  | 112         request.response.contentLength = 0; | 
|  | 113         request.response.detachSocket().then((socket) { | 
|  | 114           return new WebSocket.fromUpgradedSocket(socket, serverSide: true); | 
|  | 115         }).then((websocket) { | 
|  | 116           websocket.add("Hello"); | 
|  | 117           websocket.close(); | 
|  | 118           asyncEnd(); | 
|  | 119         }); | 
|  | 120       }); | 
|  | 121 | 
|  | 122       var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; | 
|  | 123 | 
|  | 124       WebSocket.connect(url).then((websocket) { | 
|  | 125         return websocket.listen((message) { | 
|  | 126           Expect.equals("Hello", message); | 
|  | 127           websocket.close(); | 
|  | 128         }).asFuture(); | 
|  | 129       }).then((_) => server.close()); | 
|  | 130     }); | 
|  | 131   } | 
|  | 132 | 
|  | 133   void runTests() { | 
|  | 134     // No compression or takeover | 
|  | 135     testCompressionSupport(); | 
|  | 136     // compression no takeover | 
|  | 137     testCompressionSupport(server: true, client: true); | 
|  | 138     // compression and context takeover. | 
|  | 139     testCompressionSupport(server: true, client: true, contextTakeover: true); | 
|  | 140     // Compression on client but not server. No take over | 
|  | 141     testCompressionSupport(client: true); | 
|  | 142     // Compression on server but not client. | 
|  | 143     testCompressionSupport(server: true); | 
|  | 144 | 
|  | 145     testCompressionHeaders(); | 
|  | 146   } | 
|  | 147 } | 
|  | 148 | 
|  | 149 main() { | 
|  | 150   new SecurityConfiguration(secure: false).runTests(); | 
|  | 151   // TODO(whesse): Make WebSocket.connect() take an optional context: parameter. | 
|  | 152   // new SecurityConfiguration(secure: true).runTests(); | 
|  | 153 } | 
| OLD | NEW | 
|---|