Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: sdk/lib/io/secure_socket.dart

Issue 11439029: Fix SecureSocket bug where socket was not closed after all data was flushed. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Make sure close() can be called multiple times. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/standalone/standalone.status » ('j') | tests/standalone/standalone.status » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * SecureSocket provides a secure (SSL or TLS) client connection to a server. 6 * SecureSocket provides a secure (SSL or TLS) client connection to a server.
7 * The certificate provided by the server is checked 7 * The certificate provided by the server is checked
8 * using the certificate database provided in setCertificateDatabase. 8 * using the certificate database provided in setCertificateDatabase.
9 */ 9 */
10 abstract class SecureSocket implements Socket { 10 abstract class SecureSocket implements Socket {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 _outputStream = new _SocketOutputStream(this); 211 _outputStream = new _SocketOutputStream(this);
212 } 212 }
213 return _outputStream; 213 return _outputStream;
214 } 214 }
215 215
216 int available() { 216 int available() {
217 throw new UnimplementedError("SecureSocket.available not implemented yet"); 217 throw new UnimplementedError("SecureSocket.available not implemented yet");
218 } 218 }
219 219
220 void close([bool halfClose = false]) { 220 void close([bool halfClose = false]) {
221 if (_status == CLOSED) return;
221 if (halfClose) { 222 if (halfClose) {
222 _closedWrite = true; 223 _closedWrite = true;
223 _writeEncryptedData(); 224 _writeEncryptedData();
224 if (_filterWriteEmpty) { 225 if (_filterWriteEmpty) {
225 _socket.close(true); 226 _socket.close(true);
226 _socketClosedWrite = true; 227 _socketClosedWrite = true;
228 if (_closedRead) {
229 close(false);
230 }
227 } 231 }
228 } else { 232 } else {
229 _closedWrite = true; 233 _closedWrite = true;
230 _closedRead = true; 234 _closedRead = true;
231 _socket.close(false); 235 _socket.close(false);
232 _socketClosedWrite = true; 236 _socketClosedWrite = true;
233 _socketClosedRead = true; 237 _socketClosedRead = true;
234 _secureFilter.destroy(); 238 _secureFilter.destroy();
235 _secureFilter = null; 239 _secureFilter = null;
236 if (scheduledDataEvent != null) { 240 if (scheduledDataEvent != null) {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 void _secureConnectHandler() { 325 void _secureConnectHandler() {
322 _connectPending = true; 326 _connectPending = true;
323 _secureFilter.connect(_host, _port, _is_server, _certificateName); 327 _secureFilter.connect(_host, _port, _is_server, _certificateName);
324 _status = HANDSHAKE; 328 _status = HANDSHAKE;
325 _secureHandshake(); 329 _secureHandshake();
326 } 330 }
327 331
328 void _secureWriteHandler() { 332 void _secureWriteHandler() {
329 _writeEncryptedData(); 333 _writeEncryptedData();
330 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { 334 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) {
331 _socket.close(true); 335 close(true);
332 _sockedClosedWrite = true;
333 } 336 }
334 if (_status == HANDSHAKE) { 337 if (_status == HANDSHAKE) {
335 _secureHandshake(); 338 _secureHandshake();
336 } else if (_status == CONNECTED && 339 } else if (_status == CONNECTED &&
337 _socketWriteHandler != null && 340 _socketWriteHandler != null &&
338 _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) { 341 _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
339 // We must be able to set onWrite from the onWrite callback. 342 // We must be able to set onWrite from the onWrite callback.
340 var handler = _socketWriteHandler; 343 var handler = _socketWriteHandler;
341 // Reset the one-shot handler. 344 // Reset the one-shot handler.
342 _socketWriteHandler = null; 345 _socketWriteHandler = null;
(...skipping 13 matching lines...) Expand all
356 } catch (e) { _reportError(e, "SecureSocket error"); } 359 } catch (e) { _reportError(e, "SecureSocket error"); }
357 if (!_filterReadEmpty) { 360 if (!_filterReadEmpty) {
358 // Call the onData event. 361 // Call the onData event.
359 if (scheduledDataEvent != null) { 362 if (scheduledDataEvent != null) {
360 scheduledDataEvent.cancel(); 363 scheduledDataEvent.cancel();
361 scheduledDataEvent = null; 364 scheduledDataEvent = null;
362 } 365 }
363 if (_socketDataHandler != null) { 366 if (_socketDataHandler != null) {
364 _socketDataHandler(); 367 _socketDataHandler();
365 } 368 }
369 } else if (_socketClosedRead) {
370 _secureCloseHandler();
366 } 371 }
367 } 372 }
368 } 373 }
369 374
370 void _secureErrorHandler(e) { 375 void _secureErrorHandler(e) {
371 _reportError(e, 'Error on underlying Socket'); 376 _reportError(e, 'Error on underlying Socket');
372 } 377 }
373 378
374 void _reportError(error, String message) { 379 void _reportError(error, String message) {
375 // TODO(whesse): Call _reportError from all internal functions that throw. 380 // TODO(whesse): Call _reportError from all internal functions that throw.
(...skipping 14 matching lines...) Expand all
390 if (_inputStream != null) { 395 if (_inputStream != null) {
391 reported = reported || _inputStream._onSocketError(e); 396 reported = reported || _inputStream._onSocketError(e);
392 } 397 }
393 if (_outputStream != null) { 398 if (_outputStream != null) {
394 reported = reported || _outputStream._onSocketError(e); 399 reported = reported || _outputStream._onSocketError(e);
395 } 400 }
396 if (!reported) throw e; 401 if (!reported) throw e;
397 } 402 }
398 403
399 void _secureCloseHandler() { 404 void _secureCloseHandler() {
405 if (_closedRead) return;
400 _socketClosedRead = true; 406 _socketClosedRead = true;
401 if (_filterReadEmpty) { 407 if (_filterReadEmpty) {
402 _closedRead = true; 408 _closedRead = true;
403 _fireCloseEvent(); 409 if (scheduledDataEvent != null) {
410 scheduledDataEvent.cancel();
411 }
412 if (_socketCloseHandler != null) {
413 _socketCloseHandler();
414 }
404 if (_socketClosedWrite) { 415 if (_socketClosedWrite) {
405 _secureFilter.destroy(); 416 close(false);
406 _secureFilter = null;
407 _status = CLOSED;
408 } 417 }
409 } 418 }
410 } 419 }
411 420
412 void _secureHandshake() { 421 void _secureHandshake() {
413 _readEncryptedData(); 422 _readEncryptedData();
414 _secureFilter.handshake(); 423 _secureFilter.handshake();
415 _writeEncryptedData(); 424 _writeEncryptedData();
416 if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) { 425 if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) {
417 _socket.onWrite = _secureWriteHandler; 426 _socket.onWrite = _secureWriteHandler;
418 } 427 }
419 } 428 }
420 429
421 void _secureHandshakeCompleteHandler() { 430 void _secureHandshakeCompleteHandler() {
422 _status = CONNECTED; 431 _status = CONNECTED;
423 if (_connectPending && _socketConnectHandler != null) { 432 if (_connectPending && _socketConnectHandler != null) {
424 _connectPending = false; 433 _connectPending = false;
425 _socketConnectHandler(); 434 _socketConnectHandler();
426 } 435 }
427 if (_socketWriteHandler != null) { 436 if (_socketWriteHandler != null) {
428 _socket.onWrite = _secureWriteHandler; 437 _socket.onWrite = _secureWriteHandler;
429 } 438 }
430 } 439 }
431 440
432 // True if the underlying socket is closed, the filter has been emptied of 441 // True if the underlying socket is closed, the filter has been emptied of
433 // all data, and the close event has been fired. 442 // all data, and the close event has been fired.
434 get _closed => _socketClosed && !_fireCloseEventPending; 443 get _closed => _socketClosed;
435
436 void _fireCloseEvent() {
437 if (scheduledDataEvent != null) {
438 scheduledDataEvent.cancel();
439 }
440 if (_socketCloseHandler != null) {
441 _socketCloseHandler();
442 }
443 }
444 444
445 void _readEncryptedData() { 445 void _readEncryptedData() {
446 // Read from the socket, and push it through the filter as far as 446 // Read from the socket, and push it through the filter as far as
447 // possible. 447 // possible.
448 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; 448 var encrypted = _secureFilter.buffers[READ_ENCRYPTED];
449 var plaintext = _secureFilter.buffers[READ_PLAINTEXT]; 449 var plaintext = _secureFilter.buffers[READ_PLAINTEXT];
450 bool progress = true; 450 bool progress = true;
451 while (progress) { 451 while (progress) {
452 progress = false; 452 progress = false;
453 // Do not try to read plaintext from the filter while handshaking. 453 // Do not try to read plaintext from the filter while handshaking.
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 // _closedRead is false, since we are in a read or readList call. 542 // _closedRead is false, since we are in a read or readList call.
543 if (!_filterReadEmpty) { 543 if (!_filterReadEmpty) {
544 // _filterReadEmpty may be out of date since read and readList empty 544 // _filterReadEmpty may be out of date since read and readList empty
545 // the plaintext buffer after calling _readEncryptedData. 545 // the plaintext buffer after calling _readEncryptedData.
546 // TODO(whesse): Fix this as part of fixing read and readList. 546 // TODO(whesse): Fix this as part of fixing read and readList.
547 _readEncryptedData(); 547 _readEncryptedData();
548 } 548 }
549 if (_filterReadEmpty) { 549 if (_filterReadEmpty) {
550 // This can't be an else clause: the value of _filterReadEmpty changes. 550 // This can't be an else clause: the value of _filterReadEmpty changes.
551 // This must be asynchronous, because we are in a read or readList call. 551 // This must be asynchronous, because we are in a read or readList call.
552 new Timer(0, (_) => _fireCloseEvent()); 552 new Timer(0, (_) => _secureCloseHandler());
553 } 553 }
554 } 554 }
555 } 555 }
556 556
557 bool get _socketClosed => _closedRead; 557 bool get _socketClosed => _closedRead;
558 558
559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. 559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor.
560 Socket _socket; 560 Socket _socket;
561 String _host; 561 String _host;
562 int _port; 562 int _port;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 String certificateName); 614 String certificateName);
615 void destroy(); 615 void destroy();
616 void handshake(); 616 void handshake();
617 void init(); 617 void init();
618 int processBuffer(int bufferIndex); 618 int processBuffer(int bufferIndex);
619 void registerBadCertificateCallback(Function callback); 619 void registerBadCertificateCallback(Function callback);
620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); 620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
621 621
622 List<_ExternalBuffer> get buffers; 622 List<_ExternalBuffer> get buffers;
623 } 623 }
OLDNEW
« no previous file with comments | « no previous file | tests/standalone/standalone.status » ('j') | tests/standalone/standalone.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698