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 |