| Index: runtime/bin/socket_impl.dart
|
| diff --git a/runtime/bin/socket_impl.dart b/runtime/bin/socket_impl.dart
|
| index 31e2ceee973f9da736387a7aba2fc897689ba3b6..97c3e5e63fe6a2f994dfb98fee6a1921a6e63f97 100644
|
| --- a/runtime/bin/socket_impl.dart
|
| +++ b/runtime/bin/socket_impl.dart
|
| @@ -19,6 +19,8 @@ class _SocketBase {
|
| static final int _CLOSE_EVENT = 3;
|
|
|
| static final int _CLOSE_COMMAND = 8;
|
| + static final int _SHUTDOWN_READ_COMMAND = 9;
|
| + static final int _SHUTDOWN_WRITE_COMMAND = 10;
|
|
|
| // Flag send to the eventhandler saying that the file descriptor in
|
| // question represents a listening socket.
|
| @@ -27,9 +29,12 @@ class _SocketBase {
|
| static final int _FIRST_EVENT = _IN_EVENT;
|
| static final int _LAST_EVENT = _CLOSE_EVENT;
|
|
|
| + static final int _FIRST_COMMAND = _CLOSE_COMMAND;
|
| + static final int _LAST_COMMAND = _SHUTDOWN_WRITE_COMMAND;
|
| +
|
| _SocketBase () {
|
| _handler = new ReceivePort();
|
| - _handlerMap = new List(_CLOSE_EVENT + 1);
|
| + _handlerMap = new List(_LAST_EVENT + 1);
|
| _handlerMask = 0;
|
| _canActivateHandlers = true;
|
| _id = -1;
|
| @@ -46,20 +51,26 @@ class _SocketBase {
|
| assert(message.length == 1);
|
| _canActivateHandlers = false;
|
| int event_mask = message[0];
|
| - for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) {
|
| - if (((event_mask & (1 << i)) != 0) && _handlerMap[i] != null) {
|
| - var handleEvent = _handlerMap[i];
|
| + for (int i = _FIRST_EVENT; i <= _LAST_EVENT; i++) {
|
| + if (((event_mask & (1 << i)) != 0)) {
|
| + if ((i == _CLOSE_EVENT) && this is _Socket && _id >= 0) {
|
| + if (_closedWrite) _close();
|
| + }
|
|
|
| + var eventHandler = _handlerMap[i];
|
| + if (eventHandler != null) {
|
| // Unregister the out handler before executing it.
|
| if (i == _OUT_EVENT) _setHandler(i, null);
|
|
|
| // Don't call the in handler if there is no data available
|
| // after all.
|
| - if (i == _IN_EVENT && this is _Socket && available() == 0) continue;
|
| -
|
| - handleEvent();
|
| + if (i == _IN_EVENT && this is _Socket && available() == 0) {
|
| + continue;
|
| + }
|
| + eventHandler();
|
| }
|
| }
|
| + }
|
| _canActivateHandlers = true;
|
| _activateHandlers();
|
| }
|
| @@ -83,7 +94,13 @@ class _SocketBase {
|
| void _activateHandlers() {
|
| if (_canActivateHandlers && (_id >= 0)) {
|
| int data = _handlerMask;
|
| - if (_isListenSocket()) data |= (1 << _LISTENING_SOCKET);
|
| + if (_isListenSocket()) {
|
| + data |= (1 << _LISTENING_SOCKET);
|
| + } else {
|
| + if (_closedRead) { data &= ~(1 << _IN_EVENT); }
|
| + if (_closedWrite) { data &= ~(1 << _OUT_EVENT); }
|
| + if (_isListenSocket()) data |= (1 << _LISTENING_SOCKET);
|
| + }
|
| EventHandler._sendData(_id, _handler, data);
|
| }
|
| }
|
| @@ -99,12 +116,13 @@ class _SocketBase {
|
| return _port;
|
| }
|
|
|
| - void close() {
|
| + void close([bool halfClose = false]) {
|
| if (_id >= 0) {
|
| - EventHandler._sendData(_id, _handler, 1 << _CLOSE_COMMAND);
|
| - _handler.close();
|
| - _handler = null;
|
| - _id = -1;
|
| + if (halfClose) {
|
| + _closeWrite();
|
| + } else {
|
| + _close();
|
| + }
|
| } else if (_handler != null) {
|
| // This is to support closing sockets created but never assigned
|
| // any actual socket.
|
| @@ -113,6 +131,31 @@ class _SocketBase {
|
| }
|
| }
|
|
|
| + void _closeWrite() {
|
| + if (_closedRead) {
|
| + _close();
|
| + } else {
|
| + EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_WRITE_COMMAND);
|
| + }
|
| + _closedWrite = true;
|
| + }
|
| +
|
| + void _closeRead() {
|
| + if (_closedWrite) {
|
| + _close();
|
| + } else {
|
| + EventHandler._sendData(_id, _handler, 1 << _SHUTDOWN_READ_COMMAND);
|
| + }
|
| + _closedRead = true;
|
| + }
|
| +
|
| + void _close() {
|
| + EventHandler._sendData(_id, _handler, 1 << _CLOSE_COMMAND);
|
| + _handler.close();
|
| + _handler = null;
|
| + _id = -1;
|
| + }
|
| +
|
| abstract bool _isListenSocket();
|
|
|
| /*
|
| @@ -166,7 +209,7 @@ class _ServerSocket extends _SocketBase implements ServerSocket {
|
| return socket;
|
| }
|
|
|
| - _ServerSocket._internal() : super() {}
|
| + _ServerSocket._internal();
|
|
|
| Socket accept() {
|
| if (_id >= 0) {
|
| @@ -199,7 +242,7 @@ class _Socket extends _SocketBase implements Socket {
|
| * in which the native socket is stored. After that _createConnect is
|
| * called which creates a file discriptor and connects to the given
|
| * host on the given port. Null is returned if file descriptor creation
|
| - * or connect failsed
|
| + * or connect failed.
|
| */
|
| factory _Socket(String host, int port) {
|
| Socket socket = new _Socket._internal();
|
| @@ -209,7 +252,9 @@ class _Socket extends _SocketBase implements Socket {
|
| return socket;
|
| }
|
|
|
| - _Socket._internal() : super() {}
|
| + _Socket._internal();
|
| + _Socket._internalInputOnly() : _closedRead = true;
|
| + _Socket._internalOutputOnly() : _closedWrite = true;
|
|
|
| int available() {
|
| if (_id >= 0) {
|
| @@ -221,6 +266,8 @@ class _Socket extends _SocketBase implements Socket {
|
|
|
| int _available() native "Socket_Available";
|
|
|
| + bool get closed() => _closed;
|
| +
|
| int readList(List<int> buffer, int offset, int bytes) {
|
| if (_id >= 0) {
|
| if (bytes == 0) {
|
| @@ -301,6 +348,8 @@ class _Socket extends _SocketBase implements Socket {
|
| return _outputStream;
|
| }
|
|
|
| + bool _closedRead = false;
|
| + bool _closedWrite = false;
|
| SocketInputStream _inputStream;
|
| SocketOutputStream _outputStream;
|
| }
|
|
|