Chromium Code Reviews| 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 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A high-level class for communicating securely over a TCP socket, using | 8 * A high-level class for communicating securely over a TCP socket, using |
| 9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an | 9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an |
| 10 * [IOSink] interface, making it ideal for using together with | 10 * [IOSink] interface, making it ideal for using together with |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 bufferedData, | 484 bufferedData, |
| 485 requestClientCertificate, | 485 requestClientCertificate, |
| 486 requireClientCertificate, | 486 requireClientCertificate, |
| 487 sendClientCertificate, | 487 sendClientCertificate, |
| 488 onBadCertificate) | 488 onBadCertificate) |
| 489 ._handshakeComplete.future; | 489 ._handshakeComplete.future; |
| 490 }); | 490 }); |
| 491 } | 491 } |
| 492 | 492 |
| 493 _RawSecureSocket( | 493 _RawSecureSocket( |
| 494 InternetAddress this.address, | 494 this.address, |
| 495 int requestedPort, | 495 int requestedPort, |
| 496 String this.certificateName, | 496 this.certificateName, |
| 497 bool this.is_server, | 497 this.is_server, |
| 498 RawSocket socket, | 498 RawSocket socket, |
| 499 StreamSubscription this._socketSubscription, | 499 this._socketSubscription, |
| 500 List<int> this._bufferedData, | 500 this._bufferedData, |
| 501 bool this.requestClientCertificate, | 501 this.requestClientCertificate, |
| 502 bool this.requireClientCertificate, | 502 this.requireClientCertificate, |
| 503 bool this.sendClientCertificate, | 503 this.sendClientCertificate, |
| 504 bool this.onBadCertificate(X509Certificate certificate)) { | 504 this.onBadCertificate(X509Certificate certificate)) { |
| 505 _controller = new StreamController<RawSocketEvent>( | 505 _controller = new StreamController<RawSocketEvent>( |
| 506 sync: true, | 506 sync: true, |
| 507 onListen: _onSubscriptionStateChange, | 507 onListen: _onSubscriptionStateChange, |
| 508 onPause: _onPauseStateChange, | 508 onPause: _onPauseStateChange, |
| 509 onResume: _onPauseStateChange, | 509 onResume: _onPauseStateChange, |
| 510 onCancel: _onSubscriptionStateChange); | 510 onCancel: _onSubscriptionStateChange); |
| 511 _stream = _controller.stream; | 511 _stream = _controller.stream; |
| 512 // Throw an ArgumentError if any field is invalid. After this, all | 512 // Throw an ArgumentError if any field is invalid. After this, all |
| 513 // errors will be reported through the future or the stream. | 513 // errors will be reported through the future or the stream. |
| 514 _secureFilter.init(); | 514 _secureFilter.init(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 528 _socket = rawSocket; | 528 _socket = rawSocket; |
| 529 _socket.readEventsEnabled = true; | 529 _socket.readEventsEnabled = true; |
| 530 _socket.writeEventsEnabled = false; | 530 _socket.writeEventsEnabled = false; |
| 531 if (_socketSubscription == null) { | 531 if (_socketSubscription == null) { |
| 532 // If a current subscription is provided use this otherwise | 532 // If a current subscription is provided use this otherwise |
| 533 // create a new one. | 533 // create a new one. |
| 534 _socketSubscription = _socket.listen(_eventDispatcher, | 534 _socketSubscription = _socket.listen(_eventDispatcher, |
| 535 onError: _reportError, | 535 onError: _reportError, |
| 536 onDone: _doneHandler); | 536 onDone: _doneHandler); |
| 537 } else { | 537 } else { |
| 538 _socketSubscription.onData(_eventDispatcher); | 538 _socketSubscription |
| 539 _socketSubscription.onError(_reportError); | 539 ..onData(_eventDispatcher) |
| 540 _socketSubscription.onDone(_doneHandler); | 540 ..onError(_reportError) |
| 541 ..onDone(_doneHandler); | |
| 541 } | 542 } |
| 542 _secureFilter.connect(address.host, | 543 _secureFilter.connect(address.host, |
| 543 (address as dynamic)._in_addr, | 544 (address as dynamic)._in_addr, |
| 544 port, | 545 port, |
| 545 is_server, | 546 is_server, |
| 546 certificateName, | 547 certificateName, |
| 547 requestClientCertificate || | 548 requestClientCertificate || |
| 548 requireClientCertificate, | 549 requireClientCertificate, |
| 549 requireClientCertificate, | 550 requireClientCertificate, |
| 550 sendClientCertificate); | 551 sendClientCertificate); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 throw new ArgumentError("onBadCertificate is not null or a Function"); | 601 throw new ArgumentError("onBadCertificate is not null or a Function"); |
| 601 } | 602 } |
| 602 } | 603 } |
| 603 | 604 |
| 604 int get port => _socket.port; | 605 int get port => _socket.port; |
| 605 | 606 |
| 606 InternetAddress get remoteAddress => _socket.remoteAddress; | 607 InternetAddress get remoteAddress => _socket.remoteAddress; |
| 607 | 608 |
| 608 int get remotePort => _socket.remotePort; | 609 int get remotePort => _socket.remotePort; |
| 609 | 610 |
| 610 int available() { | 611 int available() => _status != CONNECTED ? |
|
Lasse Reichstein Nielsen
2014/01/06 09:29:30
I'd prefer the block-and-return here.
| |
| 611 if (_status != CONNECTED) return 0; | 612 0 : |
| 612 return _secureFilter.buffers[READ_PLAINTEXT].length; | 613 _secureFilter.buffers[READ_PLAINTEXT].length; |
| 613 } | |
| 614 | 614 |
| 615 Future<RawSecureSocket> close() { | 615 Future<RawSecureSocket> close() { |
| 616 shutdown(SocketDirection.BOTH); | 616 shutdown(SocketDirection.BOTH); |
| 617 return _closeCompleter.future; | 617 return _closeCompleter.future; |
| 618 } | 618 } |
| 619 | 619 |
| 620 void _completeCloseCompleter([dummy]) { | 620 void _completeCloseCompleter([dummy]) { |
| 621 if (!_closeCompleter.isCompleted) _closeCompleter.complete(this); | 621 if (!_closeCompleter.isCompleted) _closeCompleter.complete(this); |
| 622 } | 622 } |
| 623 | 623 |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1061 } | 1061 } |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 | 1064 |
| 1065 /** | 1065 /** |
| 1066 * A circular buffer backed by an external byte array. Accessed from | 1066 * A circular buffer backed by an external byte array. Accessed from |
| 1067 * both C++ and Dart code in an unsynchronized way, with one reading | 1067 * both C++ and Dart code in an unsynchronized way, with one reading |
| 1068 * and one writing. All updates to start and end are done by Dart code. | 1068 * and one writing. All updates to start and end are done by Dart code. |
| 1069 */ | 1069 */ |
| 1070 class _ExternalBuffer { | 1070 class _ExternalBuffer { |
| 1071 List data; // This will be a ExternalByteArray, backed by C allocated data. | |
| 1072 int start; | |
| 1073 int end; | |
| 1074 final size; | |
| 1075 | |
| 1071 _ExternalBuffer(this.size) { | 1076 _ExternalBuffer(this.size) { |
| 1072 start = size~/2; | 1077 start = end = size ~/ 2; |
| 1073 end = size~/2; | |
| 1074 } | 1078 } |
| 1075 | 1079 |
| 1076 void advanceStart(int bytes) { | 1080 void advanceStart(int bytes) { |
| 1077 assert(start > end || start + bytes <= end); | 1081 assert(start > end || start + bytes <= end); |
| 1078 start += bytes; | 1082 start += bytes; |
| 1079 if (start >= size) { | 1083 if (start >= size) { |
| 1080 start -= size; | 1084 start -= size; |
| 1081 assert(start <= end); | 1085 assert(start <= end); |
| 1082 assert(start < size); | 1086 assert(start < size); |
| 1083 } | 1087 } |
| 1084 } | 1088 } |
| 1085 | 1089 |
| 1086 void advanceEnd(int bytes) { | 1090 void advanceEnd(int bytes) { |
| 1087 assert(start <= end || start > end + bytes); | 1091 assert(start <= end || start > end + bytes); |
| 1088 end += bytes; | 1092 end += bytes; |
| 1089 if (end >= size) { | 1093 if (end >= size) { |
| 1090 end -= size; | 1094 end -= size; |
| 1091 assert(end < start); | 1095 assert(end < start); |
| 1092 assert(end < size); | 1096 assert(end < size); |
| 1093 } | 1097 } |
| 1094 } | 1098 } |
| 1095 | 1099 |
| 1096 bool get isEmpty => end == start; | 1100 bool get isEmpty => end == start; |
| 1097 | 1101 |
| 1098 int get length { | 1102 int get length => start > end ? |
|
Lasse Reichstein Nielsen
2014/01/06 09:29:30
Use block-and-return for these three too.
| |
| 1099 if (start > end) return size + end - start; | 1103 size + end - start : |
| 1100 return end - start; | 1104 end - start; |
| 1101 } | |
| 1102 | 1105 |
| 1103 int get linearLength { | 1106 int get linearLength => start > end ? |
| 1104 if (start > end) return size - start; | 1107 size - start : |
| 1105 return end - start; | 1108 end - start; |
| 1106 } | |
| 1107 | 1109 |
| 1108 int get free { | 1110 int get free => start > end ? |
| 1109 if (start > end) return start - end - 1; | 1111 start - end - 1 : |
| 1110 return size + start - end - 1; | 1112 size + start - end - 1; |
| 1111 } | |
| 1112 | 1113 |
| 1113 int get linearFree { | 1114 int get linearFree { |
| 1114 if (start > end) return start - end - 1; | 1115 if (start > end) return start - end - 1; |
| 1115 if (start == 0) return size - end - 1; | 1116 if (start == 0) return size - end - 1; |
| 1116 return size - end; | 1117 return size - end; |
| 1117 } | 1118 } |
| 1118 | 1119 |
| 1119 List<int> read(int bytes) { | 1120 List<int> read(int bytes) { |
| 1120 if (bytes == null) { | 1121 if (bytes == null) { |
| 1121 bytes = length; | 1122 bytes = length; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1178 var toWrite = linearLength; | 1179 var toWrite = linearLength; |
| 1179 if (toWrite == 0) return false; | 1180 if (toWrite == 0) return false; |
| 1180 int bytes = socket.write(data, start, toWrite); | 1181 int bytes = socket.write(data, start, toWrite); |
| 1181 advanceStart(bytes); | 1182 advanceStart(bytes); |
| 1182 if (bytes < toWrite) { | 1183 if (bytes < toWrite) { |
| 1183 // The socket has blocked while we have data to write. | 1184 // The socket has blocked while we have data to write. |
| 1184 return true; | 1185 return true; |
| 1185 } | 1186 } |
| 1186 } | 1187 } |
| 1187 } | 1188 } |
| 1188 | |
| 1189 List data; // This will be a ExternalByteArray, backed by C allocated data. | |
| 1190 int start; | |
| 1191 int end; | |
| 1192 final size; | |
| 1193 } | 1189 } |
| 1194 | 1190 |
| 1195 | 1191 |
| 1196 abstract class _SecureFilter { | 1192 abstract class _SecureFilter { |
| 1197 external factory _SecureFilter(); | 1193 external factory _SecureFilter(); |
| 1198 | 1194 |
| 1199 void connect(String hostName, | 1195 void connect(String hostName, |
| 1200 Uint8List addr, | 1196 Uint8List addr, |
| 1201 int port, | 1197 int port, |
| 1202 bool is_server, | 1198 bool is_server, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1225 */ | 1221 */ |
| 1226 class TlsException implements IOException { | 1222 class TlsException implements IOException { |
| 1227 final String type; | 1223 final String type; |
| 1228 final String message; | 1224 final String message; |
| 1229 final OSError osError; | 1225 final OSError osError; |
| 1230 | 1226 |
| 1231 const TlsException([String message = "", | 1227 const TlsException([String message = "", |
| 1232 OSError osError = null]) | 1228 OSError osError = null]) |
| 1233 : this._("TlsException", message, osError); | 1229 : this._("TlsException", message, osError); |
| 1234 | 1230 |
| 1235 const TlsException._(String this.type, | 1231 const TlsException._(this.type, this.message, this.osError); |
| 1236 String this.message, | |
| 1237 OSError this.osError); | |
| 1238 | 1232 |
| 1239 String toString() { | 1233 String toString() { |
| 1240 StringBuffer sb = new StringBuffer(); | 1234 StringBuffer sb = new StringBuffer(); |
| 1241 sb.write(type); | 1235 sb.write(type); |
| 1242 if (!message.isEmpty) { | 1236 if (!message.isEmpty) { |
| 1243 sb.write(": $message"); | 1237 sb.write(": $message"); |
| 1244 if (osError != null) { | 1238 if (osError != null) { |
| 1245 sb.write(" ($osError)"); | 1239 sb.write(" ($osError)"); |
| 1246 } | 1240 } |
| 1247 } else if (osError != null) { | 1241 } else if (osError != null) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1266 /** | 1260 /** |
| 1267 * An exception that happens in the handshake phase of establishing | 1261 * An exception that happens in the handshake phase of establishing |
| 1268 * a secure network connection, when looking up or verifying a | 1262 * a secure network connection, when looking up or verifying a |
| 1269 * certificate. | 1263 * certificate. |
| 1270 */ | 1264 */ |
| 1271 class CertificateException extends TlsException { | 1265 class CertificateException extends TlsException { |
| 1272 const CertificateException([String message = "", | 1266 const CertificateException([String message = "", |
| 1273 OSError osError = null]) | 1267 OSError osError = null]) |
| 1274 : super._("CertificateException", message, osError); | 1268 : super._("CertificateException", message, osError); |
| 1275 } | 1269 } |
| OLD | NEW |