Index: sdk/lib/io/tls_socket.dart |
diff --git a/sdk/lib/io/tls_socket.dart b/sdk/lib/io/tls_socket.dart |
index 47163b54c1c64e09291efc094cd42fc6cd56b07c..0deef5acbb99949196ed18fed8737825ecb1f55a 100644 |
--- a/sdk/lib/io/tls_socket.dart |
+++ b/sdk/lib/io/tls_socket.dart |
@@ -82,11 +82,6 @@ class _TlsSocket implements TlsSocket { |
_tlsFilter.registerHandshakeCompleteCallback(_tlsHandshakeCompleteHandler); |
} |
- InputStream get inputStream { |
- // TODO(6701): Implement stream interfaces on TlsSocket. |
- throw new UnimplementedError("TlsSocket.inputStream not implemented yet"); |
- } |
- |
int get port => _socket.port; |
String get remoteHost => _socket.remoteHost; |
@@ -94,26 +89,79 @@ class _TlsSocket implements TlsSocket { |
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 { |
- // TODO(6701): Implement stream interfaces on TlsSocket. |
- throw new UnimplementedError("TlsSocket.inputStream not implemented yet"); |
+ 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() { |
@@ -124,7 +172,12 @@ class _TlsSocket implements TlsSocket { |
_socket.close(halfClose); |
} |
+ void _closeWrite([bool halfClose]) => close(true); |
+ |
List<int> read([int len]) { |
+ if (_status != CONNECTED && _status != CLOSED) { |
+ return new List<int>(0); |
+ } |
var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; |
_readEncryptedData(); |
int toRead = buffer.length; |
@@ -148,6 +201,9 @@ class _TlsSocket implements TlsSocket { |
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]; |
@@ -172,6 +228,7 @@ class _TlsSocket implements TlsSocket { |
// 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 (_status != CONNECTED) return 0; |
var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT]; |
if (bytes > buffer.free) { |
bytes = buffer.free; |
@@ -250,8 +307,18 @@ class _TlsSocket implements TlsSocket { |
_connectPending = false; |
_socketConnectHandler(); |
} |
+ if (_socketWriteHandler != null) { |
+ _socket.onWrite = _tlsWriteHandler; |
+ } |
} |
+ /** |
+ * _closed is used by SocketInputStream and SocketOutputStream. |
+ * It is true if the underlying socket is closed and the filter |
+ * has been emptied of all data, and the close event has been fired. |
+ */ |
+ get _closed => _socketClosed && !_fireCloseEventPending; |
+ |
void _fireCloseEvent() { |
_fireCloseEventPending = false; |
_tlsFilter.destroy(); |
@@ -356,6 +423,8 @@ class _TlsSocket implements TlsSocket { |
String _certificateName; |
var _status = NOT_CONNECTED; |
+ _SocketInputStream _inputStream; |
+ _SocketOutputStream _outputStream; |
bool _socketClosed = false; |
bool _filterEmpty = false; |
bool _connectPending = false; |