| 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 | 9 | 
| 10 import "dart:async"; | 10 import "dart:async"; | 
| 11 import "dart:convert"; | 11 import "dart:convert"; | 
| 12 import "dart:io"; | 12 import "dart:io"; | 
| 13 import "dart:typed_data"; | 13 import "dart:typed_data"; | 
| 14 | 14 | 
| 15 import "package:async_helper/async_helper.dart"; | 15 import "package:async_helper/async_helper.dart"; | 
| 16 import "package:convert/convert.dart"; | 16 import "package:convert/convert.dart"; | 
| 17 import "package:crypto/crypto.dart"; | 17 import "package:crypto/crypto.dart"; | 
| 18 import "package:expect/expect.dart"; | 18 import "package:expect/expect.dart"; | 
| 19 import "package:path/path.dart"; | 19 import "package:path/path.dart"; | 
| 20 | 20 | 
| 21 const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 21 const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 
| 22 | 22 | 
| 23 const String HOST_NAME = 'localhost'; | 23 const String HOST_NAME = 'localhost'; | 
| 24 | 24 | 
| 25 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 25 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 
| 26 | 26 | 
| 27 SecurityContext serverContext = new SecurityContext() | 27 SecurityContext serverContext = new SecurityContext() | 
| 28   ..useCertificateChain(localFile('certificates/server_chain.pem')) | 28   ..useCertificateChain(localFile('certificates/server_chain.pem')) | 
| 29   ..usePrivateKey(localFile('certificates/server_key.pem'), | 29   ..usePrivateKey(localFile('certificates/server_key.pem'), | 
| 30                   password: 'dartdart'); | 30       password: 'dartdart'); | 
| 31 | 31 | 
| 32 SecurityContext clientContext = new SecurityContext() | 32 SecurityContext clientContext = new SecurityContext() | 
| 33   ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 33   ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 
| 34 | 34 | 
| 35 /** | 35 /** | 
| 36  * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. | 36  * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. | 
| 37  */ | 37  */ | 
| 38 class SecurityConfiguration { | 38 class SecurityConfiguration { | 
| 39   final bool secure; | 39   final bool secure; | 
| 40 | 40 | 
| 41   SecurityConfiguration({bool this.secure}); | 41   SecurityConfiguration({bool this.secure}); | 
| 42 | 42 | 
| 43   Future<HttpServer> createServer({int backlog: 0}) => | 43   Future<HttpServer> createServer({int backlog: 0}) => secure | 
| 44       secure ? HttpServer.bindSecure(HOST_NAME, | 44       ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog) | 
| 45                                      0, | 45       : HttpServer.bind(HOST_NAME, 0, backlog: backlog); | 
| 46                                      serverContext, |  | 
| 47                                      backlog: backlog) |  | 
| 48              : HttpServer.bind(HOST_NAME, |  | 
| 49                                0, |  | 
| 50                                backlog: backlog); |  | 
| 51 | 46 | 
| 52   Future<WebSocket> createClient(int port) => | 47   Future<WebSocket> createClient(int port) => | 
| 53     // TODO(whesse): Add client context argument to WebSocket.connect | 48       // TODO(whesse): Add client context argument to WebSocket.connect | 
| 54     WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); | 49       WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); | 
| 55 | 50 | 
| 56   checkCloseStatus(webSocket, closeStatus, closeReason) { | 51   checkCloseStatus(webSocket, closeStatus, closeReason) { | 
| 57     Expect.equals(closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED | 52     Expect.equals( | 
| 58                                       : closeStatus, webSocket.closeCode); | 53         closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED : closeStatus, | 
| 59     Expect.equals(closeReason == null ? "" | 54         webSocket.closeCode); | 
| 60                                       : closeReason, webSocket.closeReason); | 55     Expect.equals( | 
|  | 56         closeReason == null ? "" : closeReason, webSocket.closeReason); | 
| 61   } | 57   } | 
| 62 | 58 | 
| 63   void testRequestResponseClientCloses(int totalConnections, | 59   void testRequestResponseClientCloses(int totalConnections, int closeStatus, | 
| 64                                        int closeStatus, | 60       String closeReason, int numberOfMessages) { | 
| 65                                        String closeReason, | 61     assert(numberOfMessages >= 1); | 
| 66                                        int numberOfMessages) { |  | 
| 67     assert (numberOfMessages >= 1); |  | 
| 68 | 62 | 
| 69     asyncStart(); | 63     asyncStart(); | 
| 70     createServer().then((server) { | 64     createServer().then((server) { | 
| 71       server.transform(new WebSocketTransformer()).listen((webSocket) { | 65       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 72         asyncStart(); | 66         asyncStart(); | 
| 73         webSocket.listen( | 67         webSocket.listen(webSocket.add, onDone: () { | 
| 74             webSocket.add, | 68           checkCloseStatus(webSocket, closeStatus, closeReason); | 
| 75             onDone: () { |  | 
| 76               checkCloseStatus(webSocket, closeStatus, closeReason); |  | 
| 77               asyncEnd(); |  | 
| 78             }); |  | 
| 79         }, onDone: () { |  | 
| 80           asyncEnd(); | 69           asyncEnd(); | 
| 81         }); | 70         }); | 
|  | 71       }, onDone: () { | 
|  | 72         asyncEnd(); | 
|  | 73       }); | 
| 82 | 74 | 
| 83       int closeCount = 0; | 75       int closeCount = 0; | 
| 84       String messageText = "Hello, world!"; | 76       String messageText = "Hello, world!"; | 
| 85       for (int i = 0; i < totalConnections; i++) { | 77       for (int i = 0; i < totalConnections; i++) { | 
| 86         asyncStart(); | 78         asyncStart(); | 
| 87         createClient(server.port).then((webSocket) { | 79         createClient(server.port).then((webSocket) { | 
| 88           webSocket.add(messageText); | 80           webSocket.add(messageText); | 
| 89           webSocket.listen( | 81           webSocket.listen((message) { | 
| 90               (message) { | 82             numberOfMessages--; | 
| 91                 numberOfMessages--; | 83             Expect.equals(messageText, message); | 
| 92                 Expect.equals(messageText, message); |  | 
| 93 | 84 | 
| 94                 if (numberOfMessages > 0) { | 85             if (numberOfMessages > 0) { | 
| 95                   webSocket.add(message); | 86               webSocket.add(message); | 
| 96                 } else { | 87             } else { | 
| 97                   webSocket.close(closeStatus, closeReason); | 88               webSocket.close(closeStatus, closeReason); | 
| 98                 } | 89             } | 
| 99               }, | 90           }, onDone: () { | 
| 100               onDone: () { | 91             checkCloseStatus(webSocket, closeStatus, closeReason); | 
| 101                 checkCloseStatus(webSocket, closeStatus, closeReason); | 92             closeCount++; | 
| 102                 closeCount++; | 93             if (closeCount == totalConnections) { | 
| 103                 if (closeCount == totalConnections) { | 94               server.close(); | 
| 104                   server.close(); | 95             } | 
| 105                 } | 96             asyncEnd(); | 
| 106                 asyncEnd(); |  | 
| 107               }); |  | 
| 108           }); | 97           }); | 
|  | 98         }); | 
| 109       } | 99       } | 
| 110     }); | 100     }); | 
| 111   } | 101   } | 
| 112 | 102 | 
| 113   void testRequestResponseServerCloses(int totalConnections, | 103   void testRequestResponseServerCloses( | 
| 114                                        int closeStatus, | 104       int totalConnections, int closeStatus, String closeReason) { | 
| 115                                        String closeReason) { |  | 
| 116     createServer().then((server) { | 105     createServer().then((server) { | 
| 117       int closeCount = 0; | 106       int closeCount = 0; | 
| 118       server.transform(new WebSocketTransformer()).listen((webSocket) { | 107       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 119         String messageText = "Hello, world!"; | 108         String messageText = "Hello, world!"; | 
| 120         int messageCount = 0; | 109         int messageCount = 0; | 
| 121         webSocket.listen( | 110         webSocket.listen((message) { | 
| 122             (message) { | 111           messageCount++; | 
| 123               messageCount++; | 112           if (messageCount < 10) { | 
| 124               if (messageCount < 10) { | 113             Expect.equals(messageText, message); | 
| 125                 Expect.equals(messageText, message); | 114             webSocket.add(message); | 
| 126                 webSocket.add(message); | 115           } else { | 
| 127               } else { | 116             webSocket.close(closeStatus, closeReason); | 
| 128                 webSocket.close(closeStatus, closeReason); | 117           } | 
| 129               } | 118         }, onDone: () { | 
| 130             }, | 119           checkCloseStatus(webSocket, closeStatus, closeReason); | 
| 131             onDone: () { | 120           closeCount++; | 
| 132               checkCloseStatus(webSocket, closeStatus, closeReason); | 121           if (closeCount == totalConnections) { | 
| 133               closeCount++; | 122             server.close(); | 
| 134               if (closeCount == totalConnections) { | 123           } | 
| 135                 server.close(); | 124         }); | 
| 136               } |  | 
| 137             }); |  | 
| 138         webSocket.add(messageText); | 125         webSocket.add(messageText); | 
| 139       }); | 126       }); | 
| 140 | 127 | 
| 141       for (int i = 0; i < totalConnections; i++) { | 128       for (int i = 0; i < totalConnections; i++) { | 
| 142         createClient(server.port).then((webSocket) { | 129         createClient(server.port).then((webSocket) { | 
| 143             webSocket.listen( | 130           webSocket.listen(webSocket.add, onDone: () { | 
| 144                 webSocket.add, | 131             checkCloseStatus(webSocket, closeStatus, closeReason); | 
| 145                 onDone: () { | 132           }); | 
| 146                   checkCloseStatus(webSocket, closeStatus, closeReason); | 133         }); | 
| 147                 }); |  | 
| 148             }); |  | 
| 149       } | 134       } | 
| 150     }); | 135     }); | 
| 151   } | 136   } | 
| 152 | 137 | 
| 153 |  | 
| 154   void testMessageLength(int messageLength) { | 138   void testMessageLength(int messageLength) { | 
| 155     createServer().then((server) { | 139     createServer().then((server) { | 
| 156       Uint8List originalMessage = new Uint8List(messageLength); | 140       Uint8List originalMessage = new Uint8List(messageLength); | 
| 157       server.transform(new WebSocketTransformer()).listen((webSocket) { | 141       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 158         webSocket.listen( | 142         webSocket.listen((message) { | 
| 159             (message) { | 143           Expect.listEquals(originalMessage, message); | 
| 160               Expect.listEquals(originalMessage, message); | 144           webSocket.add(message); | 
| 161               webSocket.add(message); | 145         }); | 
| 162             }); |  | 
| 163       }); | 146       }); | 
| 164 | 147 | 
| 165       createClient(server.port).then((webSocket) { | 148       createClient(server.port).then((webSocket) { | 
| 166         webSocket.listen( | 149         webSocket.listen((message) { | 
| 167             (message) { | 150           Expect.listEquals(originalMessage, message); | 
| 168               Expect.listEquals(originalMessage, message); | 151           webSocket.close(); | 
| 169               webSocket.close(); | 152         }, onDone: server.close); | 
| 170             }, |  | 
| 171             onDone: server.close); |  | 
| 172         webSocket.add(originalMessage); | 153         webSocket.add(originalMessage); | 
| 173       }); | 154       }); | 
| 174     }); | 155     }); | 
| 175   } | 156   } | 
| 176 | 157 | 
| 177 |  | 
| 178   void testCloseNoListen() { | 158   void testCloseNoListen() { | 
| 179     createServer().then((server) { | 159     createServer().then((server) { | 
| 180       server.transform(new WebSocketTransformer()).listen((webSocket) { | 160       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 181         server.close(); | 161         server.close(); | 
| 182         webSocket.close(); | 162         webSocket.close(); | 
| 183       }); | 163       }); | 
| 184 | 164 | 
| 185       createClient(server.port).then((webSocket) { | 165       createClient(server.port).then((webSocket) { | 
| 186         webSocket.close(); | 166         webSocket.close(); | 
| 187       }); | 167       }); | 
| 188     }); | 168     }); | 
| 189   } | 169   } | 
| 190 | 170 | 
| 191 |  | 
| 192   void testCancelThenClose() { | 171   void testCancelThenClose() { | 
| 193     createServer().then((server) { | 172     createServer().then((server) { | 
| 194       server.transform(new WebSocketTransformer()).listen((webSocket) { | 173       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 195         webSocket.listen(null).cancel(); | 174         webSocket.listen(null).cancel(); | 
| 196         webSocket.close(); | 175         webSocket.close(); | 
| 197         server.close(); | 176         server.close(); | 
| 198       }); | 177       }); | 
| 199 | 178 | 
| 200       createClient(server.port).then((webSocket) { | 179       createClient(server.port).then((webSocket) { | 
| 201         webSocket.close(); | 180         webSocket.close(); | 
| 202       }); | 181       }); | 
| 203     }); | 182     }); | 
| 204   } | 183   } | 
| 205 | 184 | 
| 206   void testCloseThenCancel() { | 185   void testCloseThenCancel() { | 
| 207     createServer().then((server) { | 186     createServer().then((server) { | 
| 208       server.transform(new WebSocketTransformer()).listen((webSocket) { | 187       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 209         var subscription = webSocket.listen(null); | 188         var subscription = webSocket.listen(null); | 
| 210         webSocket.close(); | 189         webSocket.close(); | 
| 211         subscription.cancel(); | 190         subscription.cancel(); | 
| 212         server.close(); | 191         server.close(); | 
| 213       }); | 192       }); | 
| 214 | 193 | 
| 215       createClient(server.port).then((webSocket) { | 194       createClient(server.port).then((webSocket) { | 
| 216         webSocket.close(); | 195         webSocket.close(); | 
| 217       }); | 196       }); | 
| 218     }); | 197     }); | 
| 219   } | 198   } | 
| 220 | 199 | 
| 221 |  | 
| 222   void testListenAfterClose() { | 200   void testListenAfterClose() { | 
| 223     createServer().then((server) { | 201     createServer().then((server) { | 
| 224       server.transform(new WebSocketTransformer()).listen((webSocket) { | 202       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 225         server.close(); | 203         server.close(); | 
| 226         webSocket.close(); | 204         webSocket.close(); | 
| 227         Expect.throws(() => webSocket.drain()); | 205         Expect.throws(() => webSocket.drain()); | 
| 228       }); | 206       }); | 
| 229 | 207 | 
| 230       createClient(server.port).then((webSocket) { | 208       createClient(server.port).then((webSocket) { | 
| 231         webSocket.close(); | 209         webSocket.close(); | 
| 232         Expect.throws(() => webSocket.drain()); | 210         Expect.throws(() => webSocket.drain()); | 
| 233       }); | 211       }); | 
| 234     }); | 212     }); | 
| 235   } | 213   } | 
| 236 | 214 | 
| 237 |  | 
| 238   void testDoubleCloseClient() { | 215   void testDoubleCloseClient() { | 
| 239     createServer().then((server) { | 216     createServer().then((server) { | 
| 240       server.transform(new WebSocketTransformer()).listen((webSocket) { | 217       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 241         server.close(); | 218         server.close(); | 
| 242         webSocket.listen((_) { }, onDone: webSocket.close); | 219         webSocket.listen((_) {}, onDone: webSocket.close); | 
| 243       }); | 220       }); | 
| 244 | 221 | 
| 245       createClient(server.port).then((webSocket) { | 222       createClient(server.port).then((webSocket) { | 
| 246           webSocket.listen((_) { }, onDone: webSocket.close); | 223         webSocket.listen((_) {}, onDone: webSocket.close); | 
| 247           webSocket.close(); | 224         webSocket.close(); | 
| 248         }); | 225       }); | 
| 249     }); | 226     }); | 
| 250   } | 227   } | 
| 251 | 228 | 
| 252 |  | 
| 253   void testDoubleCloseServer() { | 229   void testDoubleCloseServer() { | 
| 254     createServer().then((server) { | 230     createServer().then((server) { | 
| 255       server.transform(new WebSocketTransformer()).listen((webSocket) { | 231       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 256         server.close(); | 232         server.close(); | 
| 257         webSocket.listen((_) { }, onDone: webSocket.close); | 233         webSocket.listen((_) {}, onDone: webSocket.close); | 
| 258         webSocket.close(); | 234         webSocket.close(); | 
| 259       }); | 235       }); | 
| 260 | 236 | 
| 261       createClient(server.port).then((webSocket) { | 237       createClient(server.port).then((webSocket) { | 
| 262           webSocket.listen((_) { }, onDone: webSocket.close); | 238         webSocket.listen((_) {}, onDone: webSocket.close); | 
| 263         }); | 239       }); | 
| 264     }); | 240     }); | 
| 265   } | 241   } | 
| 266 | 242 | 
| 267 |  | 
| 268   void testImmediateCloseServer() { | 243   void testImmediateCloseServer() { | 
| 269     createServer().then((server) { | 244     createServer().then((server) { | 
| 270       server.listen((request) { | 245       server.listen((request) { | 
| 271         WebSocketTransformer.upgrade(request) | 246         WebSocketTransformer.upgrade(request).then((webSocket) { | 
| 272             .then((webSocket) { | 247           webSocket.listen((_) { | 
| 273               webSocket.listen( | 248             Expect.fail("Unexpected message"); | 
| 274                   (_) { Expect.fail("Unexpected message"); }, | 249           }, onDone: server.close); | 
| 275                   onDone: server.close); | 250           webSocket.close(); | 
| 276               webSocket.close(); | 251         }); | 
| 277             }); |  | 
| 278       }); | 252       }); | 
| 279 | 253 | 
| 280       createClient(server.port).then((webSocket) { | 254       createClient(server.port).then((webSocket) { | 
| 281           webSocket.listen( | 255         webSocket.listen((_) { | 
| 282               (_) { Expect.fail("Unexpected message"); }, | 256           Expect.fail("Unexpected message"); | 
| 283               onDone: webSocket.close); | 257         }, onDone: webSocket.close); | 
| 284         }); | 258       }); | 
| 285     }); | 259     }); | 
| 286   } | 260   } | 
| 287 | 261 | 
| 288 |  | 
| 289   void testImmediateCloseClient() { | 262   void testImmediateCloseClient() { | 
| 290     createServer().then((server) { | 263     createServer().then((server) { | 
| 291       server.listen((request) { | 264       server.listen((request) { | 
| 292         WebSocketTransformer.upgrade(request) | 265         WebSocketTransformer.upgrade(request).then((webSocket) { | 
| 293             .then((webSocket) { | 266           webSocket.listen((_) { | 
| 294               webSocket.listen( | 267             Expect.fail("Unexpected message"); | 
| 295                   (_) { Expect.fail("Unexpected message"); }, | 268           }, onDone: () { | 
| 296                   onDone: () { | 269             server.close(); | 
| 297                 server.close(); | 270             webSocket.close(); | 
| 298                 webSocket.close(); | 271           }); | 
| 299               }); | 272         }); | 
| 300             }); |  | 
| 301       }); | 273       }); | 
| 302 | 274 | 
| 303       createClient(server.port).then((webSocket) { | 275       createClient(server.port).then((webSocket) { | 
| 304           webSocket.listen( | 276         webSocket.listen((_) { | 
| 305               (_) { Expect.fail("Unexpected message"); }, | 277           Expect.fail("Unexpected message"); | 
| 306               onDone: webSocket.close); | 278         }, onDone: webSocket.close); | 
| 307           webSocket.close(); | 279         webSocket.close(); | 
| 308         }); | 280       }); | 
| 309     }); | 281     }); | 
| 310   } | 282   } | 
| 311 | 283 | 
| 312 |  | 
| 313   void testNoUpgrade() { | 284   void testNoUpgrade() { | 
| 314     createServer().then((server) { | 285     createServer().then((server) { | 
| 315       // Create a server which always responds with NOT_FOUND. | 286       // Create a server which always responds with NOT_FOUND. | 
| 316       server.listen((request) { | 287       server.listen((request) { | 
| 317         request.response.statusCode = HttpStatus.NOT_FOUND; | 288         request.response.statusCode = HttpStatus.NOT_FOUND; | 
| 318         request.response.close(); | 289         request.response.close(); | 
| 319       }); | 290       }); | 
| 320 | 291 | 
| 321       createClient(server.port).catchError((error) { | 292       createClient(server.port).catchError((error) { | 
| 322         server.close(); | 293         server.close(); | 
| 323       }); | 294       }); | 
| 324     }); | 295     }); | 
| 325   } | 296   } | 
| 326 | 297 | 
| 327 |  | 
| 328   void testUsePOST() { | 298   void testUsePOST() { | 
| 329     asyncStart(); | 299     asyncStart(); | 
| 330     createServer().then((server) { | 300     createServer().then((server) { | 
| 331       server.transform(new WebSocketTransformer()).listen((webSocket) { | 301       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 332         Expect.fail("No connection expected"); | 302         Expect.fail("No connection expected"); | 
| 333       }, onError: (e) { | 303       }, onError: (e) { | 
| 334         asyncEnd(); | 304         asyncEnd(); | 
| 335       }); | 305       }); | 
| 336 | 306 | 
| 337       HttpClient client = new HttpClient(); | 307       HttpClient client = new HttpClient(); | 
| 338       client.postUrl(Uri.parse( | 308       client | 
| 339           "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/")) | 309           .postUrl(Uri.parse( | 
| 340         .then((request) => request.close()) | 310               "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/")) | 
| 341         .then((response) { | 311           .then((request) => request.close()) | 
| 342           Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode); | 312           .then((response) { | 
| 343           client.close(); | 313         Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode); | 
| 344           server.close(); | 314         client.close(); | 
| 345         }); | 315         server.close(); | 
|  | 316       }); | 
| 346     }); | 317     }); | 
| 347   } | 318   } | 
| 348 | 319 | 
| 349   void testConnections(int totalConnections, | 320   void testConnections( | 
| 350                        int closeStatus, | 321       int totalConnections, int closeStatus, String closeReason) { | 
| 351                        String closeReason) { |  | 
| 352     createServer().then((server) { | 322     createServer().then((server) { | 
| 353       int closeCount = 0; | 323       int closeCount = 0; | 
| 354       server.transform(new WebSocketTransformer()).listen((webSocket) { | 324       server.transform(new WebSocketTransformer()).listen((webSocket) { | 
| 355         String messageText = "Hello, world!"; | 325         String messageText = "Hello, world!"; | 
| 356         int messageCount = 0; | 326         int messageCount = 0; | 
| 357         webSocket.listen( | 327         webSocket.listen((message) { | 
| 358             (message) { | 328           messageCount++; | 
| 359               messageCount++; | 329           if (messageCount < 10) { | 
| 360               if (messageCount < 10) { | 330             Expect.equals(messageText, message); | 
| 361                 Expect.equals(messageText, message); | 331             webSocket.add(message); | 
| 362                 webSocket.add(message); | 332           } else { | 
| 363               } else { | 333             webSocket.close(closeStatus, closeReason); | 
| 364                 webSocket.close(closeStatus, closeReason); | 334           } | 
| 365               } | 335         }, onDone: () { | 
| 366             }, | 336           checkCloseStatus(webSocket, closeStatus, closeReason); | 
| 367             onDone: () { | 337           closeCount++; | 
| 368               checkCloseStatus(webSocket, closeStatus, closeReason); | 338           if (closeCount == totalConnections) { | 
| 369               closeCount++; | 339             server.close(); | 
| 370               if (closeCount == totalConnections) { | 340           } | 
| 371                 server.close(); | 341         }); | 
| 372               } |  | 
| 373             }); |  | 
| 374         webSocket.add(messageText); | 342         webSocket.add(messageText); | 
| 375       }); | 343       }); | 
| 376 | 344 | 
| 377       void webSocketConnection() { | 345       void webSocketConnection() { | 
| 378         bool onopenCalled = false; | 346         bool onopenCalled = false; | 
| 379         int onmessageCalled = 0; | 347         int onmessageCalled = 0; | 
| 380         bool oncloseCalled = false; | 348         bool oncloseCalled = false; | 
| 381 | 349 | 
| 382         createClient(server.port).then((webSocket) { | 350         createClient(server.port).then((webSocket) { | 
| 383           Expect.isFalse(onopenCalled); | 351           Expect.isFalse(onopenCalled); | 
| 384           Expect.equals(0, onmessageCalled); | 352           Expect.equals(0, onmessageCalled); | 
| 385           Expect.isFalse(oncloseCalled); | 353           Expect.isFalse(oncloseCalled); | 
| 386           onopenCalled = true; | 354           onopenCalled = true; | 
| 387           Expect.equals(WebSocket.OPEN, webSocket.readyState); | 355           Expect.equals(WebSocket.OPEN, webSocket.readyState); | 
| 388           webSocket.listen( | 356           webSocket.listen((message) { | 
| 389               (message) { | 357             onmessageCalled++; | 
| 390                 onmessageCalled++; | 358             Expect.isTrue(onopenCalled); | 
| 391                 Expect.isTrue(onopenCalled); | 359             Expect.isFalse(oncloseCalled); | 
| 392                 Expect.isFalse(oncloseCalled); | 360             Expect.equals(WebSocket.OPEN, webSocket.readyState); | 
| 393                 Expect.equals(WebSocket.OPEN, webSocket.readyState); | 361             webSocket.add(message); | 
| 394                 webSocket.add(message); | 362           }, onDone: () { | 
| 395               }, | 363             Expect.isTrue(onopenCalled); | 
| 396               onDone: () { | 364             Expect.equals(10, onmessageCalled); | 
| 397                 Expect.isTrue(onopenCalled); | 365             Expect.isFalse(oncloseCalled); | 
| 398                 Expect.equals(10, onmessageCalled); | 366             oncloseCalled = true; | 
| 399                 Expect.isFalse(oncloseCalled); | 367             Expect.equals(3002, webSocket.closeCode); | 
| 400                 oncloseCalled = true; | 368             Expect.equals("Got tired", webSocket.closeReason); | 
| 401                 Expect.equals(3002, webSocket.closeCode); | 369             Expect.equals(WebSocket.CLOSED, webSocket.readyState); | 
| 402                 Expect.equals("Got tired", webSocket.closeReason); | 370           }); | 
| 403                 Expect.equals(WebSocket.CLOSED, webSocket.readyState); |  | 
| 404               }); |  | 
| 405         }); | 371         }); | 
| 406       } | 372       } | 
| 407 | 373 | 
| 408       for (int i = 0; i < totalConnections; i++) { | 374       for (int i = 0; i < totalConnections; i++) { | 
| 409         webSocketConnection(); | 375         webSocketConnection(); | 
| 410       } | 376       } | 
| 411     }); | 377     }); | 
| 412   } | 378   } | 
| 413 | 379 | 
| 414   testIndividualUpgrade(int connections) { | 380   testIndividualUpgrade(int connections) { | 
| 415     asyncStart(); | 381     asyncStart(); | 
| 416     createServer().then((server) { | 382     createServer().then((server) { | 
| 417       server.listen((request) { | 383       server.listen((request) { | 
| 418           if (WebSocketTransformer.isUpgradeRequest(request)) { | 384         if (WebSocketTransformer.isUpgradeRequest(request)) { | 
| 419             WebSocketTransformer.upgrade(request).then((webSocket) { | 385           WebSocketTransformer.upgrade(request).then((webSocket) { | 
| 420                 webSocket.listen((_) { webSocket.close(); }); | 386             webSocket.listen((_) { | 
| 421                 webSocket.add("Hello"); | 387               webSocket.close(); | 
| 422             }); | 388             }); | 
| 423           } else { | 389             webSocket.add("Hello"); | 
| 424             Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request)); | 390           }); | 
| 425             request.response.statusCode = HttpStatus.OK; | 391         } else { | 
| 426             request.response.close(); | 392           Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request)); | 
| 427           } | 393           request.response.statusCode = HttpStatus.OK; | 
|  | 394           request.response.close(); | 
|  | 395         } | 
| 428       }); | 396       }); | 
| 429 | 397 | 
| 430       var futures = []; | 398       var futures = []; | 
| 431 | 399 | 
| 432       var wsProtocol = '${secure ? "wss" : "ws"}'; | 400       var wsProtocol = '${secure ? "wss" : "ws"}'; | 
| 433       var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/'; | 401       var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/'; | 
| 434       var httpProtocol = '${secure ? "https" : "http"}'; | 402       var httpProtocol = '${secure ? "https" : "http"}'; | 
| 435       var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/'; | 403       var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/'; | 
| 436       HttpClient client = new HttpClient(); | 404       HttpClient client = new HttpClient(); | 
| 437 | 405 | 
| 438       for (int i = 0; i < connections; i++) { | 406       for (int i = 0; i < connections; i++) { | 
| 439         var completer = new Completer(); | 407         var completer = new Completer(); | 
| 440         futures.add(completer.future); | 408         futures.add(completer.future); | 
| 441         WebSocket.connect('${baseWsUrl}') | 409         WebSocket.connect('${baseWsUrl}').then((websocket) { | 
| 442             .then((websocket) { | 410           websocket.listen((_) { | 
| 443                 websocket.listen((_) { websocket.close(); }, | 411             websocket.close(); | 
| 444                                onDone: completer.complete); | 412           }, onDone: completer.complete); | 
| 445             }); | 413         }); | 
| 446 | 414 | 
| 447         futures.add(client.openUrl("GET", Uri.parse('${baseHttpUrl}')) | 415         futures.add(client | 
| 448              .then((request) => request.close()) | 416             .openUrl("GET", Uri.parse('${baseHttpUrl}')) | 
| 449              .then((response) { | 417             .then((request) => request.close()) | 
| 450                response.listen((_) { }); | 418             .then((response) { | 
| 451                Expect.equals(HttpStatus.OK, response.statusCode); | 419           response.listen((_) {}); | 
| 452                })); | 420           Expect.equals(HttpStatus.OK, response.statusCode); | 
|  | 421         })); | 
| 453       } | 422       } | 
| 454 | 423 | 
| 455       Future.wait(futures).then((_) { | 424       Future.wait(futures).then((_) { | 
| 456         server.close(); | 425         server.close(); | 
| 457         client.close(); | 426         client.close(); | 
| 458         asyncEnd(); | 427         asyncEnd(); | 
| 459       }); | 428       }); | 
| 460     }); | 429     }); | 
| 461   } | 430   } | 
| 462 | 431 | 
| 463   testFromUpgradedSocket() { | 432   testFromUpgradedSocket() { | 
| 464     asyncStart(); | 433     asyncStart(); | 
| 465     createServer().then((server) { | 434     createServer().then((server) { | 
| 466       server.listen((request) { | 435       server.listen((request) { | 
| 467         Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION)); | 436         Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION)); | 
| 468         Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE)); | 437         Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE)); | 
| 469 | 438 | 
| 470         var key = request.headers.value('Sec-WebSocket-Key'); | 439         var key = request.headers.value('Sec-WebSocket-Key'); | 
| 471         var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits); | 440         var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits); | 
| 472         var accept = BASE64.encode(digest.bytes); | 441         var accept = BASE64.encode(digest.bytes); | 
| 473         request.response | 442         request.response | 
| 474             ..statusCode = HttpStatus.SWITCHING_PROTOCOLS | 443           ..statusCode = HttpStatus.SWITCHING_PROTOCOLS | 
| 475             ..headers.add(HttpHeaders.CONNECTION, "Upgrade") | 444           ..headers.add(HttpHeaders.CONNECTION, "Upgrade") | 
| 476             ..headers.add(HttpHeaders.UPGRADE, "websocket") | 445           ..headers.add(HttpHeaders.UPGRADE, "websocket") | 
| 477             ..headers.add("Sec-WebSocket-Accept", accept); | 446           ..headers.add("Sec-WebSocket-Accept", accept); | 
| 478         request.response.contentLength = 0; | 447         request.response.contentLength = 0; | 
| 479         request.response.detachSocket().then((socket) { | 448         request.response.detachSocket().then((socket) { | 
| 480           return new WebSocket.fromUpgradedSocket(socket, serverSide: true); | 449           return new WebSocket.fromUpgradedSocket(socket, serverSide: true); | 
| 481         }).then((websocket) { | 450         }).then((websocket) { | 
| 482           websocket.add("Hello"); | 451           websocket.add("Hello"); | 
| 483           websocket.close(); | 452           websocket.close(); | 
| 484           asyncEnd(); | 453           asyncEnd(); | 
| 485         }); | 454         }); | 
| 486       }); | 455       }); | 
| 487 | 456 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 499   void testAdditionalHeaders() { | 468   void testAdditionalHeaders() { | 
| 500     asyncStart(); | 469     asyncStart(); | 
| 501     createServer().then((server) { | 470     createServer().then((server) { | 
| 502       server.listen((request) { | 471       server.listen((request) { | 
| 503         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 472         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 
| 504         Expect.equals('my-value', request.headers['My-Header'][0]); | 473         Expect.equals('my-value', request.headers['My-Header'][0]); | 
| 505         var header = request.headers['My-Header-Multiple']; | 474         var header = request.headers['My-Header-Multiple']; | 
| 506         Expect.equals(1, header.length); | 475         Expect.equals(1, header.length); | 
| 507         Expect.equals('my-value-1, my-value-2', header[0]); | 476         Expect.equals('my-value-1, my-value-2', header[0]); | 
| 508         WebSocketTransformer.upgrade(request).then((webSocket) { | 477         WebSocketTransformer.upgrade(request).then((webSocket) { | 
| 509           webSocket.listen((_) { webSocket.close(); }); | 478           webSocket.listen((_) { | 
|  | 479             webSocket.close(); | 
|  | 480           }); | 
| 510           webSocket.add("Hello"); | 481           webSocket.add("Hello"); | 
| 511         }); | 482         }); | 
| 512       }); | 483       }); | 
| 513 | 484 | 
| 514       var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; | 485       var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; | 
| 515       var headers = {'My-Header': 'my-value', | 486       var headers = { | 
| 516                      'My-Header-Multiple': ['my-value-1', 'my-value-2']}; | 487         'My-Header': 'my-value', | 
|  | 488         'My-Header-Multiple': ['my-value-1', 'my-value-2'] | 
|  | 489       }; | 
| 517       WebSocket.connect(url, headers: headers).then((websocket) { | 490       WebSocket.connect(url, headers: headers).then((websocket) { | 
| 518         return websocket.listen((message) { | 491         return websocket.listen((message) { | 
| 519           Expect.equals("Hello", message); | 492           Expect.equals("Hello", message); | 
| 520           websocket.close(); | 493           websocket.close(); | 
| 521         }).asFuture(); | 494         }).asFuture(); | 
| 522       }).then((_) { | 495       }).then((_) { | 
| 523         server.close(); | 496         server.close(); | 
| 524         asyncEnd(); | 497         asyncEnd(); | 
| 525       }); | 498       }); | 
| 526     }); | 499     }); | 
| 527   } | 500   } | 
| 528 | 501 | 
| 529 |  | 
| 530   void testBasicAuthentication() { | 502   void testBasicAuthentication() { | 
| 531     var userInfo = 'user:password'; | 503     var userInfo = 'user:password'; | 
| 532 | 504 | 
| 533     asyncStart(); | 505     asyncStart(); | 
| 534     asyncStart(); | 506     asyncStart(); | 
| 535     createServer().then((server) { | 507     createServer().then((server) { | 
| 536       server.listen((request) { | 508       server.listen((request) { | 
| 537         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 509         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 
| 538         String auth = | 510         String auth = BASE64.encode(UTF8.encode(userInfo)); | 
| 539               BASE64.encode(UTF8.encode(userInfo)); |  | 
| 540         Expect.equals('Basic $auth', request.headers['Authorization'][0]); | 511         Expect.equals('Basic $auth', request.headers['Authorization'][0]); | 
| 541         Expect.equals(1, request.headers['Authorization'].length); | 512         Expect.equals(1, request.headers['Authorization'].length); | 
| 542         WebSocketTransformer.upgrade(request).then((webSocket) { | 513         WebSocketTransformer.upgrade(request).then((webSocket) { | 
| 543           webSocket.listen((_) { throw 'Unexpected'; }, | 514           webSocket.listen((_) { | 
| 544                            onDone: () { asyncEnd(); }); | 515             throw 'Unexpected'; | 
|  | 516           }, onDone: () { | 
|  | 517             asyncEnd(); | 
|  | 518           }); | 
| 545           webSocket.add("Hello"); | 519           webSocket.add("Hello"); | 
| 546         }); | 520         }); | 
| 547       }); | 521       }); | 
| 548 | 522 | 
| 549       var url = | 523       var url = | 
| 550           '${secure ? "wss" : "ws"}://$userInfo@$HOST_NAME:${server.port}/'; | 524           '${secure ? "wss" : "ws"}://$userInfo@$HOST_NAME:${server.port}/'; | 
| 551       WebSocket.connect(url).then((websocket) { | 525       WebSocket.connect(url).then((websocket) { | 
| 552         return websocket.listen((message) { | 526         return websocket.listen((message) { | 
| 553           Expect.equals("Hello", message); | 527           Expect.equals("Hello", message); | 
| 554           return websocket.close(); | 528           return websocket.close(); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 584     testNoUpgrade(); | 558     testNoUpgrade(); | 
| 585     testUsePOST(); | 559     testUsePOST(); | 
| 586     testConnections(10, 3002, "Got tired"); | 560     testConnections(10, 3002, "Got tired"); | 
| 587     testIndividualUpgrade(5); | 561     testIndividualUpgrade(5); | 
| 588     testFromUpgradedSocket(); | 562     testFromUpgradedSocket(); | 
| 589     testAdditionalHeaders(); | 563     testAdditionalHeaders(); | 
| 590     testBasicAuthentication(); | 564     testBasicAuthentication(); | 
| 591   } | 565   } | 
| 592 } | 566 } | 
| 593 | 567 | 
| 594 |  | 
| 595 main() { | 568 main() { | 
| 596   new SecurityConfiguration(secure: false).runTests(); | 569   new SecurityConfiguration(secure: false).runTests(); | 
| 597   // TODO(whesse): Make WebSocket.connect() take an optional context: parameter. | 570   // TODO(whesse): Make WebSocket.connect() take an optional context: parameter. | 
| 598   // new SecurityConfiguration(secure: true).runTests(); | 571   // new SecurityConfiguration(secure: true).runTests(); | 
| 599 } | 572 } | 
| OLD | NEW | 
|---|