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

Unified Diff: sdk/lib/io/tls_socket.dart

Issue 11419138: Rename TlsSocket to SecureSocket, and all other Tls... items to Secure.... (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rename C++ class from Filter to SSLFilter. Created 8 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/io/tls_server_socket.dart ('k') | tests/standalone/io/secure_server_stream_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/tls_socket.dart
diff --git a/sdk/lib/io/tls_socket.dart b/sdk/lib/io/tls_socket.dart
deleted file mode 100644
index 051e63a144da453f187d7dd5a04cb40adc1107cb..0000000000000000000000000000000000000000
--- a/sdk/lib/io/tls_socket.dart
+++ /dev/null
@@ -1,539 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * TlsSocket provides a secure (SSL or TLS) client connection to a server.
- * The certificate provided by the server is checked
- * using the certificate database provided in setCertificateDatabase.
- */
-abstract class TlsSocket implements Socket {
- /**
- * Constructs a new secure client socket and connect it to the given
- * host on the given port. The returned socket is not yet connected
- * but ready for registration of callbacks.
- */
- factory TlsSocket(String host, int port) => new _TlsSocket(host, port);
-
- /**
- * Initializes the TLS library with the path to a certificate database
- * containing root certificates for verifying certificate paths on
- * client connections, and server certificates to provide on server
- * connections. The password argument should be used when creating
- * secure server sockets, to allow the private key of the server
- * certificate to be fetched.
- *
- * The database should be an NSS certificate database directory
- * containing a cert9.db file, not a cert8.db file. This version of
- * the database can be created using the NSS certutil tool with "sql:" in
- * front of the absolute path of the database directory, or setting the
- * environment variable NSS_DEFAULT_DB_TYPE to "sql".
- */
- external static void setCertificateDatabase(String certificateDatabase,
- [String password]);
-}
-
-
-class _TlsSocket implements TlsSocket {
- // Status states
- static final int NOT_CONNECTED = 200;
- static final int HANDSHAKE = 201;
- static final int CONNECTED = 202;
- static final int CLOSED = 203;
-
- // Buffer identifiers.
- // These must agree with those in the native C++ implementation.
- static final int READ_PLAINTEXT = 0;
- static final int WRITE_PLAINTEXT = 1;
- static final int READ_ENCRYPTED = 2;
- static final int WRITE_ENCRYPTED = 3;
- static final int NUM_BUFFERS = 4;
-
- int _count = 0;
- // Constructs a new secure client socket.
- factory _TlsSocket(String host, int port) =>
- new _TlsSocket.internal(host, port, false);
-
- // Constructs a new secure server socket, with the named server certificate.
- factory _TlsSocket.server(String host,
- int port,
- Socket socket,
- String certificateName) =>
- new _TlsSocket.internal(host, port, true, socket, certificateName);
-
- _TlsSocket.internal(String host,
- int port,
- bool is_server,
- [Socket socket,
- String certificateName])
- : _host = host,
- _port = port,
- _socket = socket,
- _certificateName = certificateName,
- _is_server = is_server,
- _tlsFilter = new _TlsFilter() {
- if (_socket == null) {
- _socket = new Socket(host, port);
- }
- _socket.onConnect = _tlsConnectHandler;
- _socket.onData = _tlsDataHandler;
- _socket.onClosed = _tlsCloseHandler;
- _tlsFilter.init();
- _tlsFilter.registerHandshakeCompleteCallback(_tlsHandshakeCompleteHandler);
- }
-
- int get port => _socket.port;
-
- String get remoteHost => _socket.remoteHost;
-
- int get remotePort => _socket.remotePort;
-
- void set onClosed(void callback()) {
- if (_inputStream != null) {
- throw new StreamException(
- "Cannot set close handler when input stream is used");
- }
- _onClosed = callback;
- }
-
- void set _onClosed(void callback()) {
- _socketCloseHandler = callback;
- }
-
- void set onConnect(void callback()) {
- if (_outputStream != null) {
- throw new StreamException(
- "Cannot set connect handler when output stream is used");
- }
- if (_status == CONNECTED || _status == CLOSED) {
- throw new StreamException(
- "Cannot set connect handler when already connected");
- }
- _onConnect = callback;
- }
-
- void set _onConnect(void callback()) {
- _socketConnectHandler = callback;
- }
-
- void set onData(void callback()) {
- if (_outputStream != null) {
- throw new StreamException(
- "Cannot set data handler when input stream is used");
- }
- _onData = callback;
- }
-
- void set _onData(void callback()) {
- _socketDataHandler = callback;
- }
-
- void set onWrite(void callback()) {
- if (_outputStream != null) {
- throw new StreamException(
- "Cannot set write handler when output stream is used");
- }
- _onWrite = callback;
- }
-
- void set _onWrite(void callback()) {
- _socketWriteHandler = callback;
- // Reset the one-shot onWrite handler.
- _socket.onWrite = _tlsWriteHandler;
- }
-
- InputStream get inputStream {
- if (_inputStream == null) {
- if (_socketDataHandler != null || _socketCloseHandler != null) {
- throw new StreamException(
- "Cannot get input stream when socket handlers are used");
- }
- _inputStream = new _SocketInputStream(this);
- }
- return _inputStream;
- }
-
- OutputStream get outputStream {
- if (_outputStream == null) {
- if (_socketConnectHandler != null || _socketWriteHandler != null) {
- throw new StreamException(
- "Cannot get output stream when socket handlers are used");
- }
- _outputStream = new _SocketOutputStream(this);
- }
- return _outputStream;
- }
-
- int available() {
- throw new UnimplementedError("TlsSocket.available not implemented yet");
- }
-
- void close([bool halfClose]) {
- if (halfClose) {
- _closedWrite = true;
- _writeEncryptedData();
- if (_filterWriteEmpty) {
- _socket.close(true);
- _socketClosedWrite = true;
- }
- } else {
- _closedWrite = true;
- _closedRead = true;
- _socket.close(false);
- _socketClosedWrite = true;
- _socketClosedRead = true;
- _tlsFilter.destroy();
- _tlsFilter = null;
- if (scheduledDataEvent != null) {
- scheduledDataEvent.cancel();
- }
- _status = CLOSED;
- }
- }
-
- void _closeWrite() => close(true);
-
- List<int> read([int len]) {
- if (_closedRead) {
- throw new SocketException("Reading from a closed socket");
- }
- if (_status != CONNECTED) {
- return new List<int>(0);
- }
- var buffer = _tlsFilter.buffers[READ_PLAINTEXT];
- _readEncryptedData();
- int toRead = buffer.length;
- if (len != null) {
- if (len is! int || len < 0) {
- throw new ArgumentError(
- "Invalid len parameter in TlsSocket.read (len: $len)");
- }
- if (len < toRead) {
- toRead = len;
- }
- }
- List<int> result = buffer.data.getRange(buffer.start, toRead);
- buffer.advanceStart(toRead);
- _setHandlersAfterRead();
- return result;
- }
-
- int readList(List<int> data, int offset, int bytes) {
- if (_closedRead) {
- throw new SocketException("Reading from a closed socket");
- }
- if (offset < 0 || bytes < 0 || offset + bytes > data.length) {
- throw new ArgumentError(
- "Invalid offset or bytes in TlsSocket.readList");
- }
- if (_status != CONNECTED && _status != CLOSED) {
- return 0;
- }
-
- int bytesRead = 0;
- var buffer = _tlsFilter.buffers[READ_PLAINTEXT];
- // TODO(whesse): Currently this fails if the if is turned into a while loop.
- // Fix it so that it can loop and read more than one buffer's worth of data.
- if (bytes > bytesRead) {
- _readEncryptedData();
- if (buffer.length > 0) {
- int toRead = min(bytes - bytesRead, buffer.length);
- data.setRange(offset, toRead, buffer.data, buffer.start);
- buffer.advanceStart(toRead);
- bytesRead += toRead;
- offset += toRead;
- }
- }
-
- _setHandlersAfterRead();
- return bytesRead;
- }
-
- // Write the data to the socket, and flush it as much as possible
- // until it would block. If the write would block, _writeEncryptedData sets
- // up handlers to flush the pipeline when possible.
- int writeList(List<int> data, int offset, int bytes) {
- if (_closedWrite) {
- throw new SocketException("Writing to a closed socket");
- }
- if (_status != CONNECTED) return 0;
- var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT];
- if (bytes > buffer.free) {
- bytes = buffer.free;
- }
- if (bytes > 0) {
- buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset);
- buffer.length += bytes;
- }
- _writeEncryptedData(); // Tries to flush all pipeline stages.
- return bytes;
- }
-
- void _tlsConnectHandler() {
- _connectPending = true;
- _tlsFilter.connect(_host, _port, _is_server, _certificateName);
- _status = HANDSHAKE;
- _tlsHandshake();
- }
-
- void _tlsWriteHandler() {
- _writeEncryptedData();
- if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) {
- _socket.close(true);
- _sockedClosedWrite = true;
- }
- if (_status == HANDSHAKE) {
- _tlsHandshake();
- } else if (_status == CONNECTED &&
- _socketWriteHandler != null &&
- _tlsFilter.buffers[WRITE_PLAINTEXT].free > 0) {
- // We must be able to set onWrite from the onWrite callback.
- var handler = _socketWriteHandler;
- // Reset the one-shot handler.
- _socketWriteHandler = null;
- handler();
- }
- }
-
- void _tlsDataHandler() {
- if (_status == HANDSHAKE) {
- _tlsHandshake();
- } else {
- _writeEncryptedData(); // TODO(whesse): Removing this causes a failure.
- _readEncryptedData();
- if (!_filterReadEmpty) {
- // Call the onData event.
- if (scheduledDataEvent != null) {
- scheduledDataEvent.cancel();
- scheduledDataEvent = null;
- }
- if (_socketDataHandler != null) {
- _socketDataHandler();
- }
- }
- }
- }
-
- void _tlsCloseHandler() {
- _socketClosedRead = true;
- if (_filterReadEmpty) {
- _closedRead = true;
- _fireCloseEvent();
- if (_socketClosedWrite) {
- _tlsFilter.destroy();
- _tlsFilter = null;
- _status = CLOSED;
- }
- }
- }
-
- void _tlsHandshake() {
- _readEncryptedData();
- _tlsFilter.handshake();
- _writeEncryptedData();
- if (_tlsFilter.buffers[WRITE_ENCRYPTED].length > 0) {
- _socket.onWrite = _tlsWriteHandler;
- }
- }
-
- void _tlsHandshakeCompleteHandler() {
- _status = CONNECTED;
- if (_connectPending && _socketConnectHandler != null) {
- _connectPending = false;
- _socketConnectHandler();
- }
- if (_socketWriteHandler != null) {
- _socket.onWrite = _tlsWriteHandler;
- }
- }
-
- // True if the underlying socket is closed, the filter has been emptied of
- // all data, and the close event has been fired.
- get _closed => _socketClosed && !_fireCloseEventPending;
-
- void _fireCloseEvent() {
- if (scheduledDataEvent != null) {
- scheduledDataEvent.cancel();
- }
- if (_socketCloseHandler != null) {
- _socketCloseHandler();
- }
- }
-
- void _readEncryptedData() {
- // Read from the socket, and push it through the filter as far as
- // possible.
- var encrypted = _tlsFilter.buffers[READ_ENCRYPTED];
- var plaintext = _tlsFilter.buffers[READ_PLAINTEXT];
- bool progress = true;
- while (progress) {
- progress = false;
- // Do not try to read plaintext from the filter while handshaking.
- if ((_status == CONNECTED) && plaintext.free > 0) {
- int bytes = _tlsFilter.processBuffer(READ_PLAINTEXT);
- if (bytes > 0) {
- plaintext.length += bytes;
- progress = true;
- }
- }
- if (encrypted.length > 0) {
- int bytes = _tlsFilter.processBuffer(READ_ENCRYPTED);
- if (bytes > 0) {
- encrypted.advanceStart(bytes);
- progress = true;
- }
- }
- if (!_socketClosedRead) {
- int bytes = _socket.readList(encrypted.data,
- encrypted.start + encrypted.length,
- encrypted.free);
- if (bytes > 0) {
- encrypted.length += bytes;
- progress = true;
- }
- }
- }
- // If there is any data in any stages of the filter, there should
- // be data in the plaintext buffer after this process.
- // TODO(whesse): Verify that this is true, and there can be no
- // partial encrypted block stuck in the tlsFilter.
- _filterReadEmpty = (plaintext.length == 0);
- }
-
- void _writeEncryptedData() {
- if (_socketClosedWrite) return;
- var encrypted = _tlsFilter.buffers[WRITE_ENCRYPTED];
- var plaintext = _tlsFilter.buffers[WRITE_PLAINTEXT];
- while (true) {
- if (encrypted.length > 0) {
- // Write from the filter to the socket.
- int bytes = _socket.writeList(encrypted.data,
- encrypted.start,
- encrypted.length);
- if (bytes == 0) {
- // The socket has blocked while we have data to write.
- // We must be notified when it becomes unblocked.
- _socket.onWrite = _tlsWriteHandler;
- _filterWriteEmpty = false;
- break;
- }
- encrypted.advanceStart(bytes);
- } else {
- var plaintext = _tlsFilter.buffers[WRITE_PLAINTEXT];
- if (plaintext.length > 0) {
- int plaintext_bytes = _tlsFilter.processBuffer(WRITE_PLAINTEXT);
- plaintext.advanceStart(plaintext_bytes);
- }
- int bytes = _tlsFilter.processBuffer(WRITE_ENCRYPTED);
- if (bytes <= 0) {
- // We know the WRITE_ENCRYPTED buffer is empty, and the
- // filter wrote zero bytes to it, so the filter must be empty.
- // Also, the WRITE_PLAINTEXT buffer must have been empty, or
- // it would have written to the filter.
- // TODO(whesse): Verify that the filter works this way.
- _filterWriteEmpty = true;
- break;
- }
- encrypted.length += bytes;
- }
- }
- }
-
- /* After a read, the onData handler is enabled to fire again.
- * We may also have a close event waiting for the TlsFilter to empty.
- */
- void _setHandlersAfterRead() {
- // If the filter is empty, then we are guaranteed an event when it
- // becomes unblocked. Cancel any _tlsDataHandler call.
- // Otherwise, schedule a _tlsDataHandler call since there may data
- // available, and this read call enables the data event.
- if (_filterReadEmpty) {
- if (scheduledDataEvent != null) {
- scheduledDataEvent.cancel();
- scheduledDataEvent = null;
- }
- } else if (scheduledDataEvent == null) {
- scheduledDataEvent = new Timer(0, (_) => _tlsDataHandler());
- }
-
- if (_socketClosedRead) { // An onClose event is pending.
- // _closedRead is false, since we are in a read or readList call.
- if (!_filterReadEmpty) {
- // _filterReadEmpty may be out of date since read and readList empty
- // the plaintext buffer after calling _readEncryptedData.
- // TODO(whesse): Fix this as part of fixing read and readList.
- _readEncryptedData();
- }
- if (_filterReadEmpty) {
- // This can't be an else clause: the value of _filterReadEmpty changes.
- // This must be asynchronous, because we are in a read or readList call.
- new Timer(0, (_) => _fireCloseEvent());
- }
- }
- }
-
- bool get _socketClosed => _closedRead;
-
- // _TlsSocket cannot extend _Socket and use _Socket's factory constructor.
- Socket _socket;
- String _host;
- int _port;
- bool _is_server;
- String _certificateName;
-
- var _status = NOT_CONNECTED;
- bool _socketClosedRead = false; // The network socket is closed for reading.
- bool _socketClosedWrite = false; // The network socket is closed for writing.
- bool _closedRead = false; // The secure socket has fired an onClosed event.
- bool _closedWrite = false; // The secure socket has been closed for writing.
- bool _filterReadEmpty = true; // There is no buffered data to read.
- bool _filterWriteEmpty = true; // There is no buffered data to be written.
- _SocketInputStream _inputStream;
- _SocketOutputStream _outputStream;
- bool _connectPending = false;
- Function _socketConnectHandler;
- Function _socketWriteHandler;
- Function _socketDataHandler;
- Function _socketCloseHandler;
- Timer scheduledDataEvent;
-
- _TlsFilter _tlsFilter;
-}
-
-
-class _TlsExternalBuffer {
- static final int SIZE = 8 * 1024;
- _TlsExternalBuffer() : start = 0, length = 0;
-
- // TODO(whesse): Consider making this a circular buffer. Only if it helps.
- void advanceStart(int numBytes) {
- start += numBytes;
- length -= numBytes;
- if (length == 0) {
- start = 0;
- }
- }
-
- int get free => SIZE - (start + length);
-
- List data; // This will be a ExternalByteArray, backed by C allocated data.
- int start;
- int length;
-}
-
-
-abstract class _TlsFilter {
- external factory _TlsFilter();
-
- void connect(String hostName,
- int port,
- bool is_server,
- String certificateName);
- void destroy();
- void handshake();
- void init();
- int processBuffer(int bufferIndex);
- void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
-
- List<_TlsExternalBuffer> get buffers;
-}
« no previous file with comments | « sdk/lib/io/tls_server_socket.dart ('k') | tests/standalone/io/secure_server_stream_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698