| 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"; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 clientEnd.shutdown(SocketDirection.SEND); | 126 clientEnd.shutdown(SocketDirection.SEND); |
| 127 serverEnd.shutdown(SocketDirection.SEND); | 127 serverEnd.shutdown(SocketDirection.SEND); |
| 128 server.close(); | 128 server.close(); |
| 129 port.close(); | 129 port.close(); |
| 130 }); | 130 }); |
| 131 }); | 131 }); |
| 132 }); | 132 }); |
| 133 }); | 133 }); |
| 134 } | 134 } |
| 135 | 135 |
| 136 void testSimpleReadWrite() { | 136 // This test creates a server and a client connects. The client then |
| 137 // This test creates a server and a client connects. The client then | 137 // writes and the server echos. When the server has finished its echo |
| 138 // writes and the server echos. When the server has finished its | 138 // it half-closes. When the client gets the close event is closes |
| 139 // echo it half-closes. When the client gets the close event is | 139 // fully. |
| 140 // closes fully. | 140 // |
| 141 // The test can be run in different configurations based on |
| 142 // the boolean arguments: |
| 143 // |
| 144 // listenSecure |
| 145 // When this argument is true a secure server is used. When this is false |
| 146 // a non-secure server is used and the connections are secured after beeing |
| 147 // connected. |
| 148 // |
| 149 // connectSecure |
| 150 // When this argument is true a secure client connection is used. When this |
| 151 // is false a non-secure client connection is used and the connection is |
| 152 // secured after being connected. |
| 153 // |
| 154 // handshakeBeforeSecure |
| 155 // When this argument is true some initial clear text handshake is done |
| 156 // between client and server before the connection is secured. This argument |
| 157 // only makes sense when both listenSecure and connectSecure are false. |
| 158 // |
| 159 // postponeSecure |
| 160 // When this argument is false the securing of the server end will |
| 161 // happen as soon as the last byte of the handshake before securing |
| 162 // has been written. When this argument is true the securing of the |
| 163 // server will not happen until the first TLS handshake data has been |
| 164 // received from the client. This argument only takes effect when |
| 165 // handshakeBeforeSecure is true. |
| 166 void testSimpleReadWrite(bool listenSecure, |
| 167 bool connectSecure, |
| 168 bool handshakeBeforeSecure, |
| 169 [bool postponeSecure = false]) { |
| 170 if (handshakeBeforeSecure == true && |
| 171 (listenSecure == true || connectSecure == true)) { |
| 172 Expect.fails("Invalid arguments to testSimpleReadWrite"); |
| 173 } |
| 174 |
| 141 ReceivePort port = new ReceivePort(); | 175 ReceivePort port = new ReceivePort(); |
| 142 | 176 |
| 143 const messageSize = 1000; | 177 const messageSize = 1000; |
| 178 const handshakeMessageSize = 100; |
| 144 | 179 |
| 145 List<int> createTestData() { | 180 List<int> createTestData() { |
| 146 List<int> data = new List<int>(messageSize); | 181 List<int> data = new List<int>(messageSize); |
| 147 for (int i = 0; i < messageSize; i++) { | 182 for (int i = 0; i < messageSize; i++) { |
| 148 data[i] = i & 0xff; | 183 data[i] = i & 0xff; |
| 149 } | 184 } |
| 150 return data; | 185 return data; |
| 151 } | 186 } |
| 152 | 187 |
| 188 List<int> createHandshakeTestData() { |
| 189 List<int> data = new List<int>(handshakeMessageSize); |
| 190 for (int i = 0; i < handshakeMessageSize; i++) { |
| 191 data[i] = i & 0xff; |
| 192 } |
| 193 return data; |
| 194 } |
| 195 |
| 153 void verifyTestData(List<int> data) { | 196 void verifyTestData(List<int> data) { |
| 154 Expect.equals(messageSize, data.length); | 197 Expect.equals(messageSize, data.length); |
| 155 List<int> expected = createTestData(); | 198 List<int> expected = createTestData(); |
| 156 for (int i = 0; i < messageSize; i++) { | 199 for (int i = 0; i < messageSize; i++) { |
| 157 Expect.equals(expected[i], data[i]); | 200 Expect.equals(expected[i], data[i]); |
| 158 } | 201 } |
| 159 } | 202 } |
| 160 | 203 |
| 161 RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) { | 204 void verifyHandshakeTestData(List<int> data) { |
| 205 Expect.equals(handshakeMessageSize, data.length); |
| 206 List<int> expected = createHandshakeTestData(); |
| 207 for (int i = 0; i < handshakeMessageSize; i++) { |
| 208 Expect.equals(expected[i], data[i]); |
| 209 } |
| 210 } |
| 211 |
| 212 Future runServer(RawSocket client) { |
| 213 var completer = new Completer(); |
| 214 int bytesRead = 0; |
| 215 int bytesWritten = 0; |
| 216 List<int> data = new List<int>(messageSize); |
| 217 client.writeEventsEnabled = false; |
| 218 var subscription; |
| 219 subscription = client.listen((event) { |
| 220 switch (event) { |
| 221 case RawSocketEvent.READ: |
| 222 Expect.isTrue(bytesWritten == 0); |
| 223 Expect.isTrue(client.available() > 0); |
| 224 var buffer = client.read(); |
| 225 if (buffer != null) { |
| 226 data.setRange(bytesRead, buffer.length, buffer); |
| 227 bytesRead += buffer.length; |
| 228 for (var value in buffer) { |
| 229 Expect.isTrue(value is int); |
| 230 Expect.isTrue(value < 256 && value >= 0); |
| 231 } |
| 232 } |
| 233 if (bytesRead == data.length) { |
| 234 verifyTestData(data); |
| 235 client.writeEventsEnabled = true; |
| 236 } |
| 237 break; |
| 238 case RawSocketEvent.WRITE: |
| 239 Expect.isFalse(client.writeEventsEnabled); |
| 240 Expect.equals(bytesRead, data.length); |
| 241 for (int i = bytesWritten; i < data.length; ++i) { |
| 242 Expect.isTrue(data[i] is int); |
| 243 Expect.isTrue(data[i] < 256 && data[i] >= 0); |
| 244 } |
| 245 bytesWritten += client.write( |
| 246 data, bytesWritten, data.length - bytesWritten); |
| 247 if (bytesWritten < data.length) { |
| 248 client.writeEventsEnabled = true; |
| 249 } |
| 250 if (bytesWritten == data.length) { |
| 251 client.shutdown(SocketDirection.SEND); |
| 252 } |
| 253 break; |
| 254 case RawSocketEvent.READ_CLOSED: |
| 255 completer.complete(null); |
| 256 break; |
| 257 default: throw "Unexpected event $event"; |
| 258 } |
| 259 }); |
| 260 return completer.future; |
| 261 } |
| 262 |
| 263 Future<RawSocket> runClient(RawSocket socket) { |
| 264 var completer = new Completer(); |
| 265 int bytesRead = 0; |
| 266 int bytesWritten = 0; |
| 267 List<int> dataSent = createTestData(); |
| 268 List<int> dataReceived = new List<int>(dataSent.length); |
| 269 socket.listen((event) { |
| 270 switch (event) { |
| 271 case RawSocketEvent.READ: |
| 272 Expect.isTrue(socket.available() > 0); |
| 273 var buffer = socket.read(); |
| 274 if (buffer != null) { |
| 275 dataReceived.setRange(bytesRead, buffer.length, buffer); |
| 276 bytesRead += buffer.length; |
| 277 } |
| 278 break; |
| 279 case RawSocketEvent.WRITE: |
| 280 Expect.isTrue(bytesRead == 0); |
| 281 Expect.isFalse(socket.writeEventsEnabled); |
| 282 bytesWritten += socket.write( |
| 283 dataSent, bytesWritten, dataSent.length - bytesWritten); |
| 284 if (bytesWritten < dataSent.length) { |
| 285 socket.writeEventsEnabled = true; |
| 286 } |
| 287 break; |
| 288 case RawSocketEvent.READ_CLOSED: |
| 289 verifyTestData(dataReceived); |
| 290 completer.complete(socket); |
| 291 break; |
| 292 default: throw "Unexpected event $event"; |
| 293 } |
| 294 }); |
| 295 return completer.future; |
| 296 } |
| 297 |
| 298 Future runServerHandshake(RawSocket client) { |
| 299 var completer = new Completer(); |
| 300 int bytesRead = 0; |
| 301 int bytesWritten = 0; |
| 302 List<int> data = new List<int>(handshakeMessageSize); |
| 303 client.writeEventsEnabled = false; |
| 304 var subscription; |
| 305 subscription = client.listen((event) { |
| 306 switch (event) { |
| 307 case RawSocketEvent.READ: |
| 308 if (bytesRead < data.length) { |
| 309 Expect.isTrue(bytesWritten == 0); |
| 310 } |
| 311 Expect.isTrue(client.available() > 0); |
| 312 var buffer = client.read(); |
| 313 if (buffer != null) { |
| 314 if (bytesRead == data.length) { |
| 315 // Read first part of TLS handshake from client. |
| 316 Expect.isTrue(postponeSecure); |
| 317 completer.complete([subscription, buffer]); |
| 318 return; |
| 319 } |
| 320 data.setRange(bytesRead, buffer.length, buffer); |
| 321 bytesRead += buffer.length; |
| 322 for (var value in buffer) { |
| 323 Expect.isTrue(value is int); |
| 324 Expect.isTrue(value < 256 && value >= 0); |
| 325 } |
| 326 } |
| 327 if (bytesRead == data.length) { |
| 328 verifyHandshakeTestData(data); |
| 329 client.writeEventsEnabled = true; |
| 330 } |
| 331 if (bytesRead > data.length) print("XXX"); |
| 332 break; |
| 333 case RawSocketEvent.WRITE: |
| 334 Expect.isFalse(client.writeEventsEnabled); |
| 335 Expect.equals(bytesRead, data.length); |
| 336 for (int i = bytesWritten; i < data.length; ++i) { |
| 337 Expect.isTrue(data[i] is int); |
| 338 Expect.isTrue(data[i] < 256 && data[i] >= 0); |
| 339 } |
| 340 bytesWritten += client.write( |
| 341 data, bytesWritten, data.length - bytesWritten); |
| 342 if (bytesWritten < data.length) { |
| 343 client.writeEventsEnabled = true; |
| 344 } |
| 345 if (bytesWritten == data.length) { |
| 346 if (!postponeSecure) { |
| 347 completer.complete([subscription, null]); |
| 348 } |
| 349 } |
| 350 break; |
| 351 case RawSocketEvent.READ_CLOSED: |
| 352 Expect.fail("Unexpected close"); |
| 353 break; |
| 354 default: throw "Unexpected event $event"; |
| 355 } |
| 356 }); |
| 357 return completer.future; |
| 358 } |
| 359 |
| 360 Future<RawSocket> runClientHandshake(RawSocket socket) { |
| 361 var completer = new Completer(); |
| 362 int bytesRead = 0; |
| 363 int bytesWritten = 0; |
| 364 List<int> dataSent = createHandshakeTestData(); |
| 365 List<int> dataReceived = new List<int>(dataSent.length); |
| 366 var subscription; |
| 367 subscription = socket.listen((event) { |
| 368 switch (event) { |
| 369 case RawSocketEvent.READ: |
| 370 Expect.isTrue(socket.available() > 0); |
| 371 var buffer = socket.read(); |
| 372 if (buffer != null) { |
| 373 dataReceived.setRange(bytesRead, buffer.length, buffer); |
| 374 bytesRead += buffer.length; |
| 375 if (bytesRead == dataSent.length) { |
| 376 verifyHandshakeTestData(dataReceived); |
| 377 completer.complete(subscription); |
| 378 } |
| 379 } |
| 380 break; |
| 381 case RawSocketEvent.WRITE: |
| 382 Expect.isTrue(bytesRead == 0); |
| 383 Expect.isFalse(socket.writeEventsEnabled); |
| 384 bytesWritten += socket.write( |
| 385 dataSent, bytesWritten, dataSent.length - bytesWritten); |
| 386 if (bytesWritten < dataSent.length) { |
| 387 socket.writeEventsEnabled = true; |
| 388 } |
| 389 break; |
| 390 case RawSocketEvent.READ_CLOSED: |
| 391 Expect.fail("Unexpected close"); |
| 392 break; |
| 393 default: throw "Unexpected event $event"; |
| 394 } |
| 395 }); |
| 396 return completer.future; |
| 397 } |
| 398 |
| 399 Future<RawSecureSocket> connectClient(int port) { |
| 400 if (connectSecure) { |
| 401 return RawSecureSocket.connect(HOST_NAME, port); |
| 402 } else if (!handshakeBeforeSecure) { |
| 403 return RawSocket.connect(HOST_NAME, port).then((socket) { |
| 404 return RawSecureSocket.secure(socket); |
| 405 }); |
| 406 } else { |
| 407 return RawSocket.connect(HOST_NAME, port).then((socket) { |
| 408 return runClientHandshake(socket).then((subscription) { |
| 409 return RawSecureSocket.secure(socket, subscription: subscription); |
| 410 }); |
| 411 }); |
| 412 } |
| 413 } |
| 414 |
| 415 serverReady(server) { |
| 162 server.listen((client) { | 416 server.listen((client) { |
| 163 int bytesRead = 0; | 417 if (listenSecure) { |
| 164 int bytesWritten = 0; | 418 runServer(client).then((_) => server.close()); |
| 165 List<int> data = new List<int>(messageSize); | 419 } else if (!handshakeBeforeSecure) { |
| 166 | 420 RawSecureSocket.secureServer(client, CERTIFICATE).then((client) { |
| 167 client.writeEventsEnabled = false; | 421 runServer(client).then((_) => server.close()); |
| 168 client.listen((event) { | 422 }); |
| 169 switch (event) { | 423 } else { |
| 170 case RawSocketEvent.READ: | 424 runServerHandshake(client).then((secure) { |
| 171 Expect.isTrue(bytesWritten == 0); | 425 RawSecureSocket.secureServer( |
| 172 Expect.isTrue(client.available() > 0); | 426 client, |
| 173 var buffer = client.read(); | 427 CERTIFICATE, |
| 174 if (buffer != null) { | 428 subscription: secure[0], |
| 175 data.setRange(bytesRead, buffer.length, buffer); | 429 carryOverData: secure[1]).then((client) { |
| 176 bytesRead += buffer.length; | 430 runServer(client).then((_) => server.close()); |
| 177 for (var value in buffer) { | 431 }); |
| 178 Expect.isTrue(value is int); | 432 }); |
| 179 Expect.isTrue(value < 256 && value >= 0); | 433 } |
| 180 } | 434 }); |
| 181 } | 435 |
| 182 if (bytesRead == data.length) { | 436 connectClient(server.port).then(runClient).then((socket) { |
| 183 verifyTestData(data); | 437 socket.close(); |
| 184 client.writeEventsEnabled = true; | 438 port.close(); |
| 185 } | 439 }); |
| 186 break; | 440 } |
| 187 case RawSocketEvent.WRITE: | 441 |
| 188 Expect.isFalse(client.writeEventsEnabled); | 442 if (listenSecure) { |
| 189 Expect.equals(bytesRead, data.length); | 443 RawSecureServerSocket.bind( |
| 190 for (int i = bytesWritten; i < data.length; ++i) { | 444 SERVER_ADDRESS, 0, 5, CERTIFICATE).then(serverReady); |
| 191 Expect.isTrue(data[i] is int); | 445 } else { |
| 192 Expect.isTrue(data[i] < 256 && data[i] >= 0); | 446 RawServerSocket.bind(SERVER_ADDRESS, 0, 5).then(serverReady); |
| 193 } | 447 } |
| 194 bytesWritten += client.write( | |
| 195 data, bytesWritten, data.length - bytesWritten); | |
| 196 if (bytesWritten < data.length) { | |
| 197 client.writeEventsEnabled = true; | |
| 198 } | |
| 199 if (bytesWritten == data.length) { | |
| 200 client.shutdown(SocketDirection.SEND); | |
| 201 } | |
| 202 break; | |
| 203 case RawSocketEvent.READ_CLOSED: | |
| 204 server.close(); | |
| 205 break; | |
| 206 default: throw "Unexpected event $event"; | |
| 207 } | |
| 208 }); | |
| 209 }); | |
| 210 | |
| 211 RawSecureSocket.connect(HOST_NAME, server.port).then((socket) { | |
| 212 int bytesRead = 0; | |
| 213 int bytesWritten = 0; | |
| 214 List<int> dataSent = createTestData(); | |
| 215 List<int> dataReceived = new List<int>(dataSent.length); | |
| 216 socket.listen((event) { | |
| 217 switch (event) { | |
| 218 case RawSocketEvent.READ: | |
| 219 Expect.isTrue(socket.available() > 0); | |
| 220 var buffer = socket.read(); | |
| 221 if (buffer != null) { | |
| 222 dataReceived.setRange(bytesRead, buffer.length, buffer); | |
| 223 bytesRead += buffer.length; | |
| 224 } | |
| 225 break; | |
| 226 case RawSocketEvent.WRITE: | |
| 227 Expect.isTrue(bytesRead == 0); | |
| 228 Expect.isFalse(socket.writeEventsEnabled); | |
| 229 bytesWritten += socket.write( | |
| 230 dataSent, bytesWritten, dataSent.length - bytesWritten); | |
| 231 if (bytesWritten < dataSent.length) { | |
| 232 socket.writeEventsEnabled = true; | |
| 233 } | |
| 234 break; | |
| 235 case RawSocketEvent.READ_CLOSED: | |
| 236 verifyTestData(dataReceived); | |
| 237 socket.close(); | |
| 238 port.close(); | |
| 239 break; | |
| 240 default: throw "Unexpected event $event"; | |
| 241 } | |
| 242 }); | |
| 243 }); | |
| 244 }); | |
| 245 } | 448 } |
| 246 | 449 |
| 247 main() { | 450 main() { |
| 248 Path scriptDir = new Path(new Options().script).directoryPath; | 451 Path scriptDir = new Path(new Options().script).directoryPath; |
| 249 Path certificateDatabase = scriptDir.append('pkcert'); | 452 Path certificateDatabase = scriptDir.append('pkcert'); |
| 250 SecureSocket.initialize(database: certificateDatabase.toNativePath(), | 453 SecureSocket.initialize(database: certificateDatabase.toNativePath(), |
| 251 password: 'dartdart', | 454 password: 'dartdart', |
| 252 useBuiltinRoots: false); | 455 useBuiltinRoots: false); |
| 253 testArguments(); | 456 testArguments(); |
| 254 testSimpleBind(); | 457 testSimpleBind(); |
| 255 testInvalidBind(); | 458 testInvalidBind(); |
| 256 testSimpleConnect(CERTIFICATE); | 459 testSimpleConnect(CERTIFICATE); |
| 257 testSimpleConnect("CN=localhost"); | 460 testSimpleConnect("CN=localhost"); |
| 258 testSimpleConnectFail("not_a_nickname"); | 461 testSimpleConnectFail("not_a_nickname"); |
| 259 testSimpleConnectFail("CN=notARealDistinguishedName"); | 462 testSimpleConnectFail("CN=notARealDistinguishedName"); |
| 260 testServerListenAfterConnect(); | 463 testServerListenAfterConnect(); |
| 261 testSimpleReadWrite(); | 464 testSimpleReadWrite(true, true, false); |
| 465 testSimpleReadWrite(true, false, false); |
| 466 testSimpleReadWrite(false, true, false); |
| 467 testSimpleReadWrite(false, false, false); |
| 468 testSimpleReadWrite(false, false, true, true); |
| 469 testSimpleReadWrite(false, false, true, false); |
| 262 } | 470 } |
| OLD | NEW |